XEmacs 21.2-b1
[chise/xemacs-chise.git.1] / src / toolbar-msw.c
1 /* toolbar implementation -- mswindows interface.
2    Copyright (C) 1995 Board of Trustees, University of Illinois.
3    Copyright (C) 1995 Sun Microsystems, Inc.
4    Copyright (C) 1995, 1996 Ben Wing.
5    Copyright (C) 1996 Chuck Thompson.
6    Copyright (C) 1998 Andy Piper.
7
8 This file is part of XEmacs.
9
10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
13 later version.
14
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18 for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with XEmacs; see the file COPYING.  If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA.  */
24
25 /* This implementation by Andy Piper <andyp@parallax.co.uk>, with bits
26    borrowed from toolbar-x.c */
27
28 /* Synched up with: Not in FSF. */
29
30 #include <config.h>
31 #include "lisp.h"
32
33 #include "faces.h"
34 #include "frame.h"
35 #include "toolbar.h"
36 #include "window.h"
37 #include "gui.h"
38 #include "elhash.h"
39 #include "console-msw.h"
40 #include "glyphs-msw.h"
41 #include "objects-msw.h"
42
43 #define TOOLBAR_ITEM_ID_MIN 0x4000
44 #define TOOLBAR_ITEM_ID_MAX 0x7FFF
45 #define TOOLBAR_ITEM_ID_BITS(x) (((x) & 0x3FFF) | 0x4000)
46 #define TOOLBAR_ID_BIAS 16
47 #define TOOLBAR_HANDLE(f,p) \
48 GetDlgItem(FRAME_MSWINDOWS_HANDLE(f), TOOLBAR_ID_BIAS + p)
49 #ifndef TB_SETIMAGELIST
50 #define TB_SETIMAGELIST (WM_USER + 48)
51 #define TB_GETIMAGELIST (WM_USER + 49)
52 #define TB_SETDISABLEDIMAGELIST (WM_USER + 54)
53 #define TB_GETDISABLEDIMAGELIST (WM_USER + 55)
54 #endif
55 #ifndef TB_SETPADDING
56 #define TB_SETPADDING   (WM_USER + 87)
57 #endif
58 #define MSWINDOWS_BUTTON_SHADOW_THICKNESS 2
59 #define MSWINDOWS_BLANK_SIZE 5
60 #define MSWINDOWS_MINIMUM_TOOLBAR_SIZE 8
61
62 #define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag)                  \
63   do {                                                                  \
64     switch (pos)                                                        \
65       {                                                                 \
66       case TOP_TOOLBAR:                                                 \
67         (frame)->top_toolbar_was_visible = flag;                        \
68         break;                                                          \
69       case BOTTOM_TOOLBAR:                                              \
70         (frame)->bottom_toolbar_was_visible = flag;                     \
71         break;                                                          \
72       case LEFT_TOOLBAR:                                                \
73         (frame)->left_toolbar_was_visible = flag;                       \
74         break;                                                          \
75       case RIGHT_TOOLBAR:                                               \
76         (frame)->right_toolbar_was_visible = flag;                      \
77         break;                                                          \
78       default:                                                          \
79         abort ();                                                       \
80       }                                                                 \
81   } while (0)
82
83 static int
84 allocate_toolbar_item_id (struct frame* f, struct toolbar_button* button,
85                           enum toolbar_pos pos)
86 {
87   /* hmm what do we generate an id based on */
88   int id = TOOLBAR_ITEM_ID_BITS (internal_hash (button->callback, 0));
89   while (!NILP (Fgethash (make_int (id),
90                           FRAME_MSWINDOWS_TOOLBAR_HASHTABLE (f), Qnil)))
91     {
92       id = TOOLBAR_ITEM_ID_BITS (id + 1);
93     }
94   return id;
95 }
96
97 static void
98 mswindows_clear_toolbar (struct frame *f, enum toolbar_pos pos,
99                          int thickness_change)
100 {
101   HIMAGELIST ilist=NULL;
102   int i;
103   HWND toolbarwnd = TOOLBAR_HANDLE(f, pos);
104   if (toolbarwnd)
105     {
106       TBBUTTON info;
107       
108       /* delete the buttons and remove the command from the hashtable*/
109       i = SendMessage (toolbarwnd, TB_BUTTONCOUNT, 0, 0);
110       for (i--; i >= 0; i--)
111         {
112           SendMessage (toolbarwnd, TB_GETBUTTON, (WPARAM)i, 
113                        (LPARAM)&info);
114           Fremhash(make_int(info.idCommand), 
115                    FRAME_MSWINDOWS_TOOLBAR_HASHTABLE(f));
116           SendMessage (toolbarwnd, TB_DELETEBUTTON, (WPARAM)i, 0);
117         }
118           
119       /* finally get rid of the image list assuming it clears up its
120          bitmaps */
121       SendMessage (toolbarwnd, TB_GETIMAGELIST, 0, (LONG) &ilist);
122       if (ilist)
123         {
124           ImageList_Destroy(ilist);
125         }
126       SendMessage (toolbarwnd, TB_SETIMAGELIST, 0, (LPARAM)NULL);
127
128       ShowWindow(toolbarwnd, SW_HIDE);
129     }
130
131   FRAME_MSWINDOWS_TOOLBAR_CHECKSUM(f,pos)=0;
132   SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 0);
133 }
134
135 static void
136 mswindows_output_toolbar (struct frame *f, enum toolbar_pos pos)
137 {
138   int x, y, bar_width, bar_height, vert;
139   int width=-1, height=-1, bmwidth=0, bmheight=0, maxbmwidth, maxbmheight;
140   int style_3d=0;
141   int border_width = FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, pos);
142   Lisp_Object button, glyph, instance;
143   Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
144
145   int nbuttons=0;
146   int shadow_thickness = 2;     /* get this from somewhere else? */
147   int window_frame_width = 3;
148   int padding = (border_width + shadow_thickness) * 2;
149   unsigned int checksum=0;
150   struct window *w = XWINDOW (window);
151   TBBUTTON* button_tbl, *tbbutton;
152   HIMAGELIST ilist=NULL;
153   HWND toolbarwnd=NULL;
154
155   get_toolbar_coords (f, pos, &x, &y, &bar_width, &bar_height, &vert, 0);
156
157   /* ediff bogusly sets the height to 2 for some obscure X-specific
158      reason. This ensures that we only try and output a toolbar for
159      sensible sizes */
160   if (bar_width < MSWINDOWS_MINIMUM_TOOLBAR_SIZE
161       ||
162       bar_height < MSWINDOWS_MINIMUM_TOOLBAR_SIZE)
163     {
164       return;
165     }
166
167   if (x==1)
168     x=0;
169
170   toolbarwnd = TOOLBAR_HANDLE (f,pos);
171   
172   /* set button sizes based on bar size */
173   if (vert)
174     {
175       if (style_3d)
176         {
177           width = height = bar_width
178             - (window_frame_width + shadow_thickness) * 2; 
179         }
180       else 
181         width = height = bar_width;
182
183       maxbmwidth = maxbmheight = width - padding;
184     }
185   else
186     {
187       if (style_3d)
188         {
189           height = width = bar_height 
190             - (window_frame_width + shadow_thickness) * 2; 
191         }
192       else 
193         width = height = bar_height;
194
195       maxbmwidth = maxbmheight = width - padding;
196     }
197
198   button = FRAME_TOOLBAR_BUTTONS (f, pos);
199
200   /* First loop over all of the buttons to determine how many there
201      are. This loop will also make sure that all instances are
202      instantiated so when we actually output them they will come up
203      immediately. */
204   while (!NILP (button))
205     {
206
207       struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
208       checksum = HASH4 (checksum, 
209                         internal_hash (get_toolbar_button_glyph(w, tb), 0),
210                         internal_hash (tb->callback, 0),
211                         width);
212       button = tb->next;
213       nbuttons++;
214     }
215
216   /* only rebuild if something has changed */
217   if (!toolbarwnd || FRAME_MSWINDOWS_TOOLBAR_CHECKSUM(f,pos)!=checksum)
218     {
219       /* remove the old one */
220       mswindows_clear_toolbar (f, pos, 0);
221
222       FRAME_MSWINDOWS_TOOLBAR_CHECKSUM(f,pos)=checksum;
223
224       /* build up the data required by win32 fns. */
225       button_tbl = xnew_array_and_zero (TBBUTTON, nbuttons);
226       button = FRAME_TOOLBAR_BUTTONS (f, pos);
227       tbbutton = button_tbl;
228
229       while (!NILP (button))
230         {
231           struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
232           HBITMAP bitmap=NULL, mask=NULL;
233           bitmap=mask=NULL;
234
235           if (tb->blank)
236             tbbutton->fsStyle = TBSTYLE_SEP;
237           else 
238             {
239               tbbutton->idCommand = allocate_toolbar_item_id (f, tb, pos);
240               /* currently we output the toolbar again with disabled
241                  buttons it might be good to use the ms disabled code
242                  instead but that means another image list, so we'll stick
243                  with the emacs model. */
244               tbbutton->fsState = tb->enabled ? TBSTATE_ENABLED :
245                 TBSTATE_INDETERMINATE;
246               tbbutton->fsStyle = TBSTYLE_BUTTON;
247               tbbutton->dwData=0; 
248               tbbutton->iString=0;
249               
250               /* mess with the button image */
251               glyph = get_toolbar_button_glyph (w, tb);
252               
253               if (GLYPHP (glyph))
254                 instance = glyph_image_instance (glyph, window, 
255                                                  ERROR_ME_NOT, 1);
256               else
257                 instance = Qnil;
258               
259               if (IMAGE_INSTANCEP (instance))
260                 {
261                   struct Lisp_Image_Instance* p = XIMAGE_INSTANCE (instance);
262                   
263                   if (IMAGE_INSTANCE_PIXMAP_TYPE_P (p))
264                     {
265                       /* we are going to honour the toolbar settings
266                          and resize the bitmaps accordingly if they are
267                          too big.  If they are too small we leave them
268                          and pad the difference - unless a different size
269                          crops up in the middle, at which point we *have*
270                          to resize since the ImageList won't cope.*/
271                       
272                       if ((bmwidth 
273                            && 
274                            IMAGE_INSTANCE_PIXMAP_WIDTH (p) != bmwidth)
275                           ||
276                           (bmheight 
277                            && 
278                            IMAGE_INSTANCE_PIXMAP_HEIGHT (p) != bmheight)
279                           ||
280                           IMAGE_INSTANCE_PIXMAP_WIDTH (p) > maxbmwidth
281                           ||
282                           IMAGE_INSTANCE_PIXMAP_HEIGHT (p) > maxbmheight)
283                         {
284                           if (!bmheight)
285                             bmheight = min (maxbmheight, 
286                                             IMAGE_INSTANCE_PIXMAP_HEIGHT (p));
287                           if (!bmwidth)
288                             bmwidth = min (maxbmwidth,
289                                            IMAGE_INSTANCE_PIXMAP_WIDTH (p));
290                       
291                           if (! (bitmap = mswindows_create_resized_bitmap 
292                                  (p, f, bmwidth, bmheight)))
293                             {
294                               xfree (button_tbl);
295                               if (ilist) ImageList_Destroy (ilist);
296                               signal_simple_error ("couldn't resize pixmap", 
297                                                    instance);
298                             }
299                           /* we don't care if the mask fails */
300                           mask = mswindows_create_resized_mask 
301                             (p, f, bmwidth, bmheight);
302                         }
303                       else 
304                         {
305                           if (!bmwidth)
306                             bmwidth = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
307                           if (!bmheight)
308                             bmheight = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
309                         }
310               
311                       /* need to build an image list for the bitmaps */
312                       if (!ilist && !(ilist = ImageList_Create 
313                                       ( bmwidth, bmheight,
314                                         (IMAGE_INSTANCE_MSWINDOWS_MASK (p) 
315                                          ? ILC_MASK  : 0) | ILC_COLOR24, 
316                                         nbuttons, nbuttons * 2 )))
317                         {
318                           xfree (button_tbl);
319                           signal_simple_error ("couldn't create image list",
320                                                instance);
321                         }
322
323                       /* make the mask actually do something */
324                       ImageList_SetBkColor (ilist, CLR_NONE);
325                       /* add a bitmap to the list */
326                       if ((tbbutton->iBitmap =
327                            ImageList_Add
328                            (ilist,
329                             bitmap ? bitmap 
330                             : IMAGE_INSTANCE_MSWINDOWS_BITMAP (p),
331                             mask ? mask 
332                             : IMAGE_INSTANCE_MSWINDOWS_MASK (p))) < 0)
333                         {
334                           xfree (button_tbl);
335                           if (ilist) ImageList_Destroy (ilist);
336                           signal_simple_error 
337                             ("couldn't add image to image list", instance);
338                         }
339                       /* we're done with these now */
340                       DeleteObject (bitmap);
341                       DeleteObject (mask);
342                     }
343                 }
344
345               Fputhash (make_int (tbbutton->idCommand), 
346                         button, FRAME_MSWINDOWS_TOOLBAR_HASHTABLE (f));
347             }
348
349           /* now fix up the button size */
350           tb->x = x;
351           tb->y = y;
352           tb->vertical = vert;
353           tb->border_width = border_width;
354           tb->width = width + MSWINDOWS_BUTTON_SHADOW_THICKNESS * 2;
355           tb->height = height + MSWINDOWS_BUTTON_SHADOW_THICKNESS * 2;
356
357           if (tb->blank)
358             {
359               if (vert)
360                 tb->height = MSWINDOWS_BLANK_SIZE;
361               else
362                 tb->width = MSWINDOWS_BLANK_SIZE;
363             }
364           
365           if (vert)                                                     
366             y += tb->height;
367           else
368             x += tb->width;
369           /* move on to the next button */
370           tbbutton++;
371           button = tb->next;
372         }
373
374       button = FRAME_TOOLBAR_BUTTONS (f, pos);
375
376       /* create the toolbar window? */
377       if (!toolbarwnd 
378           &&
379           (toolbarwnd = 
380            CreateWindowEx ( WS_EX_WINDOWEDGE,
381                             TOOLBARCLASSNAME,
382                             NULL,
383                             WS_CHILD | WS_VISIBLE 
384                             | (style_3d ? WS_DLGFRAME : 0)
385                             | TBSTYLE_TOOLTIPS | CCS_NORESIZE 
386                             | CCS_NOPARENTALIGN | CCS_NODIVIDER,
387                             x, y, bar_width, bar_height,
388                             FRAME_MSWINDOWS_HANDLE (f),
389                             (HMENU)(TOOLBAR_ID_BIAS + pos),
390                             NULL, 
391                             NULL))==NULL)
392         {
393           xfree (button_tbl);
394           ImageList_Destroy (ilist);
395           error ("couldn't create toolbar");
396         }
397
398       /* finally populate with images */
399       if (SendMessage (toolbarwnd, TB_BUTTONSTRUCTSIZE,
400                        (WPARAM)sizeof(TBBUTTON), (LPARAM)0) == -1) 
401         {
402           mswindows_clear_toolbar (f, pos, 0);
403           error ("couldn't set button structure size");
404         }
405
406       if (vert)
407         height = min (bmheight + padding, height);
408       else
409         width = min (bmwidth + padding, width);
410         
411       /* pad the buttons */
412       SendMessage (toolbarwnd, TB_SETPADDING,
413                    0, MAKELPARAM(width - bmwidth, height - bmheight));
414
415       /* set the size of buttons */
416       SendMessage (toolbarwnd, TB_SETBUTTONSIZE, 0, 
417                    (LPARAM)MAKELONG (width, height));
418
419       /* set the size of bitmaps */
420       SendMessage (toolbarwnd, TB_SETBITMAPSIZE, 0, 
421                    (LPARAM)MAKELONG (bmwidth, bmheight));
422
423       /* tell it we've done it */
424       SendMessage (toolbarwnd, TB_AUTOSIZE, 0, 0);
425                    
426       /* finally populate with images */
427       if (!SendMessage (toolbarwnd, TB_ADDBUTTONS,
428                         (WPARAM)nbuttons, (LPARAM)button_tbl))
429         {
430           mswindows_clear_toolbar (f, pos, 0);
431           error ("couldn't add button list to toolbar");
432         }
433
434       /* vertical toolbars need more rows */
435       if (vert)
436         {
437           RECT tmp;
438           SendMessage (toolbarwnd, TB_SETROWS, 
439                        MAKEWPARAM(nbuttons, FALSE), (LPARAM)&tmp);
440         }
441
442       else
443         {
444           RECT tmp;
445           SendMessage (toolbarwnd, TB_SETROWS, MAKEWPARAM(1, FALSE), 
446                        (LPARAM)&tmp);
447         }
448
449       /* finally populate with images */
450       if (SendMessage (toolbarwnd, TB_SETIMAGELIST, 0,
451                        (LPARAM)ilist) < 0
452           ||
453           SendMessage (toolbarwnd, TB_SETDISABLEDIMAGELIST, 0,
454                        (LPARAM)ilist) < 0)
455         {
456           mswindows_clear_toolbar (f, pos, 0);
457           error ("couldn't add image list to toolbar");
458         }
459
460       /* now display the window */
461       ShowWindow (toolbarwnd, SW_SHOW);
462
463       if (button_tbl) xfree (button_tbl);
464
465       SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 1);
466     }
467 }
468
469 static void
470 mswindows_move_toolbar (struct frame *f, enum toolbar_pos pos)
471 {
472   int bar_x, bar_y, bar_width, bar_height, vert;
473   HWND toolbarwnd = TOOLBAR_HANDLE(f,pos);
474
475   if (toolbarwnd)
476     {
477       get_toolbar_coords (f, pos, &bar_x, &bar_y, &bar_width, &bar_height,
478                           &vert, 1);
479
480       /* #### This terrible mangling with coordinates perhaps
481          arises from different treatment of toolbar positions
482          by Windows and by XEmacs. */
483       switch (pos)
484         {
485         case TOP_TOOLBAR:
486           bar_x--; bar_y-=2;
487           bar_width+=3; bar_height+=3;
488           break;
489         case LEFT_TOOLBAR:
490           bar_x--; bar_y-=2;
491           bar_height++; bar_width++;
492           break;
493         case BOTTOM_TOOLBAR:
494           bar_y-=2; 
495           bar_width+=4; bar_height+=4;
496           break;
497         case RIGHT_TOOLBAR:
498           bar_y-=2; bar_x++;
499           bar_width++; bar_height++;
500           break;
501         }
502       SetWindowPos (toolbarwnd, NULL, bar_x, bar_y, 
503                     bar_width, bar_height, SWP_NOZORDER);
504     }
505 }
506
507 static void
508 mswindows_redraw_exposed_toolbars (struct frame *f, int x, int y, int width,
509                                    int height)
510 {
511   assert (FRAME_MSWINDOWS_P (f));
512
513   if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
514     mswindows_move_toolbar (f, TOP_TOOLBAR);
515
516   if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
517     mswindows_move_toolbar (f, BOTTOM_TOOLBAR);
518
519   if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
520     mswindows_move_toolbar (f, LEFT_TOOLBAR);
521
522   if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
523     mswindows_move_toolbar (f, RIGHT_TOOLBAR);
524 }
525
526 static void
527 mswindows_initialize_frame_toolbars (struct frame *f)
528 {
529
530 }
531
532 static void
533 mswindows_output_frame_toolbars (struct frame *f)
534 {
535   assert (FRAME_MSWINDOWS_P (f));
536
537   if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
538     mswindows_output_toolbar (f, TOP_TOOLBAR);
539   else if (f->top_toolbar_was_visible)
540     mswindows_clear_toolbar (f, TOP_TOOLBAR, 0);
541
542   if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
543     mswindows_output_toolbar (f, BOTTOM_TOOLBAR);
544   else if (f->bottom_toolbar_was_visible)
545     mswindows_clear_toolbar (f, BOTTOM_TOOLBAR, 0);
546
547   if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
548     mswindows_output_toolbar (f, LEFT_TOOLBAR);
549   else if (f->left_toolbar_was_visible)
550     mswindows_clear_toolbar (f, LEFT_TOOLBAR, 0);
551
552   if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
553     mswindows_output_toolbar (f, RIGHT_TOOLBAR);
554   else if (f->right_toolbar_was_visible)
555     mswindows_clear_toolbar (f, RIGHT_TOOLBAR, 0);
556 }
557
558 static void
559 mswindows_free_frame_toolbars (struct frame *f)
560 {
561   HWND twnd=NULL;
562 #define DELETE_TOOLBAR(pos) \
563   mswindows_clear_toolbar(f, 0, pos); \
564   if ((twnd=GetDlgItem(FRAME_MSWINDOWS_HANDLE(f), TOOLBAR_ID_BIAS + pos))) \
565       DestroyWindow(twnd)
566
567   DELETE_TOOLBAR(TOP_TOOLBAR);
568   DELETE_TOOLBAR(BOTTOM_TOOLBAR);
569   DELETE_TOOLBAR(LEFT_TOOLBAR);
570   DELETE_TOOLBAR(RIGHT_TOOLBAR);
571 #undef DELETE_TOOLBAR
572 }
573
574 /* map toolbar hwnd to pos*/
575 int mswindows_find_toolbar_pos(struct frame* f, HWND ctrl)
576 {
577   int id = GetDlgCtrlID(ctrl);
578   return id ? id - TOOLBAR_ID_BIAS : -1;
579 }
580
581 Lisp_Object 
582 mswindows_get_toolbar_button_text ( struct frame* f, int command_id )
583 {
584   Lisp_Object button = Fgethash (make_int (command_id),
585                                  FRAME_MSWINDOWS_TOOLBAR_HASHTABLE (f), Qnil);
586   
587   if (!NILP (button))
588     {
589       struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
590       return tb->help_string;
591     }
592   return Qnil;
593 }
594
595 /*
596  * Return value is Qt if we have dispatched the command,
597  * or Qnil if id has not been mapped to a callback.
598  * Window procedure may try other targets to route the
599  * command if we return nil
600  */
601 Lisp_Object
602 mswindows_handle_toolbar_wm_command (struct frame* f, HWND ctrl, WORD id)
603 {
604   /* Try to map the command id through the proper hash table */
605   Lisp_Object button, data, fn, arg, frame;
606
607   button = Fgethash (make_int (id), 
608                      FRAME_MSWINDOWS_TOOLBAR_HASHTABLE (f), Qnil);
609
610   if (NILP (button))
611     return Qnil;
612
613   data = XTOOLBAR_BUTTON (button)->callback;
614
615   /* #### ? */
616   if (UNBOUNDP (data))
617     return Qnil;
618
619   /* Ok, this is our one. Enqueue it. */
620   get_gui_callback (data, &fn, &arg);
621   XSETFRAME (frame, f);
622   mswindows_enqueue_misc_user_event (frame, fn, arg);
623
624   return Qt;
625 }
626 \f
627 /************************************************************************/
628 /*                            initialization                            */
629 /************************************************************************/
630
631 void
632 console_type_create_toolbar_mswindows (void)
633 {
634   CONSOLE_HAS_METHOD (mswindows, output_frame_toolbars);
635   CONSOLE_HAS_METHOD (mswindows, initialize_frame_toolbars);
636   CONSOLE_HAS_METHOD (mswindows, free_frame_toolbars);
637   CONSOLE_HAS_METHOD (mswindows, redraw_exposed_toolbars);
638 }
639