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