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