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