comparison src/toolbar-msw.c @ 276:6330739388db r21-0b36

Import from CVS: tag r21-0b36
author cvs
date Mon, 13 Aug 2007 10:30:37 +0200
parents
children 90d73dddcdc4
comparison
equal deleted inserted replaced
275:a68ae4439f57 276:6330739388db
1 /* toolbar implementation -- mswindows interface.
2 Copyright (C) 1998 Free Software Foundation.
3
4 This file is part of XEmacs.
5
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* This implementation by Andy Piper <andyp@parallax.co.uk>, with bits
22 borrowed from toolbar-x.c */
23
24 /* Synched up with: Not in FSF. */
25
26 #include <config.h>
27 #include "lisp.h"
28
29 #include "faces.h"
30 #include "frame.h"
31 #include "toolbar.h"
32 #include "window.h"
33 #include "gui.h"
34 #include "console-msw.h"
35 #include "glyphs-msw.h"
36 #include "objects-msw.h"
37
38 /* Why did Kirill choose this range ? */
39 #define TOOLBAR_ITEM_ID_MIN 0x4000
40 #define TOOLBAR_ITEM_ID_MAX 0x7FFF
41 #define TOOLBAR_ITEM_ID_BITS(x) (((x) & 0x3FFF) | 0x4000)
42 #ifndef TB_SETIMAGELIST
43 #define TB_SETIMAGELIST (WM_USER + 48)
44 #define TB_GETIMAGELIST (WM_USER + 49)
45 #endif
46
47 #define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag) \
48 do { \
49 switch (pos) \
50 { \
51 case TOP_TOOLBAR: \
52 (frame)->top_toolbar_was_visible = flag; \
53 break; \
54 case BOTTOM_TOOLBAR: \
55 (frame)->bottom_toolbar_was_visible = flag; \
56 break; \
57 case LEFT_TOOLBAR: \
58 (frame)->left_toolbar_was_visible = flag; \
59 break; \
60 case RIGHT_TOOLBAR: \
61 (frame)->right_toolbar_was_visible = flag; \
62 break; \
63 default: \
64 abort (); \
65 } \
66 } while (0)
67
68 static int
69 allocate_toolbar_item_id (struct frame* f, struct toolbar_button* button)
70 {
71 /* hmm what do we generate an id based on */
72 int id = TOOLBAR_ITEM_ID_BITS (internal_hash (button->callback, 0));
73 while (!NILP (Fgethash (make_int (id),
74 FRAME_MSWINDOWS_TOOLBAR_HASHTABLE (f), Qnil)))
75 {
76 id = TOOLBAR_ITEM_ID_BITS (id + 1);
77 }
78 return id;
79 }
80
81 static void
82 mswindows_clear_toolbar (struct frame *f, enum toolbar_pos pos,
83 int thickness_change)
84 {
85 HIMAGELIST ilist=NULL;
86 if (FRAME_MSWINDOWS_TOOLBAR (f))
87 {
88 /* get the image list and delete it */
89 SendMessage (FRAME_MSWINDOWS_TOOLBAR (f),
90 TB_GETIMAGELIST, 0,
91 (LONG) &ilist);
92
93 /* destroy the toolbar window */
94 DestroyWindow (FRAME_MSWINDOWS_TOOLBAR (f));
95 FRAME_MSWINDOWS_TOOLBAR (f) = 0;
96
97 /* finally get rid of the image list assuming it clears up its
98 bitmaps */
99 if (ilist)
100 {
101 ImageList_Destroy(ilist);
102 }
103 }
104 }
105
106 static void
107 mswindows_output_toolbar (struct frame *f, enum toolbar_pos pos)
108 {
109 int x, y, bar_width, bar_height, vert;
110 int width=-1, height=-1, bmwidth=-1, bmheight=-1;
111 int border_width = FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, pos);
112 Lisp_Object button, window, glyph, instance;
113 int nbuttons=0;
114 struct window *w;
115 TBBUTTON* button_tbl, *tbbutton;
116 HIMAGELIST ilist=NULL;
117
118 get_toolbar_coords (f, pos, &x, &y, &bar_width, &bar_height, &vert, 0);
119 window = FRAME_LAST_NONMINIBUF_WINDOW (f);
120 w = XWINDOW (window);
121
122 /* set button sizes based on bar size */
123 if (vert)
124 {
125 width = height = bar_width - border_width * 2;
126 bmwidth = bmheight = width -2;
127 }
128 else
129 {
130 height = width = bar_height - border_width * 2;
131 bmwidth = bmheight = width -2;
132 }
133
134 button = FRAME_TOOLBAR_DATA (f, pos)->toolbar_buttons;
135
136 /* First loop over all of the buttons to determine how many there
137 are. This loop will also make sure that all instances are
138 instantiated so when we actually output them they will come up
139 immediately. */
140 while (!NILP (button))
141 {
142 struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
143 button = tb->next;
144 nbuttons++;
145 }
146
147 /* build up the data required by win32 fns. */
148 button_tbl = xnew_array_and_zero (TBBUTTON, nbuttons);
149 button = FRAME_TOOLBAR_DATA (f, pos)->toolbar_buttons;
150 tbbutton = button_tbl;
151
152 while (!NILP (button))
153 {
154 struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
155
156 tbbutton->idCommand = allocate_toolbar_item_id (f, tb);
157 tbbutton->fsState=tb->enabled ? TBSTATE_ENABLED : TBSTATE_INDETERMINATE;
158 tbbutton->fsStyle=tb->blank ? TBSTYLE_SEP : TBSTYLE_BUTTON;
159 tbbutton->dwData=0;
160 tbbutton->iString=0;
161
162 /* mess with the button image */
163 glyph = get_toolbar_button_glyph (w, tb);
164
165 if (GLYPHP (glyph))
166 instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1);
167 else
168 instance = Qnil;
169
170 if (IMAGE_INSTANCEP (instance))
171 {
172 struct Lisp_Image_Instance* p = XIMAGE_INSTANCE (instance);
173
174 if (IMAGE_INSTANCE_PIXMAP_TYPE_P (p))
175 {
176 /* we are going to honour the toolbar settings and
177 resize the bitmaps accordingly */
178
179 if ((IMAGE_INSTANCE_PIXMAP_WIDTH (p) != bmwidth
180 ||
181 IMAGE_INSTANCE_PIXMAP_HEIGHT (p) != bmheight)
182 &&
183 !mswindows_resize_dibitmap_instance (p, f,
184 bmwidth, bmheight))
185 {
186 xfree (button_tbl);
187 if (ilist) ImageList_Destroy (ilist);
188 signal_simple_error ("couldn't resize pixmap",
189 instance);
190 }
191
192 /* need to build an image list for the bitmaps */
193 if (!ilist)
194 {
195 if (!(ilist = ImageList_Create
196 ( IMAGE_INSTANCE_PIXMAP_WIDTH (p),
197 IMAGE_INSTANCE_PIXMAP_HEIGHT (p),
198 ILC_COLOR24,
199 nbuttons,
200 nbuttons * 2 )))
201 {
202 xfree (button_tbl);
203 signal_simple_error ("couldn't create image list",
204 instance);
205 }
206 }
207
208 /* add a bitmap to the list */
209 if ((tbbutton->iBitmap =
210 ImageList_Add (ilist,
211 IMAGE_INSTANCE_MSWINDOWS_BITMAP (p),
212 IMAGE_INSTANCE_MSWINDOWS_MASK (p))) < 0)
213 {
214 xfree (button_tbl);
215 if (ilist) ImageList_Destroy (ilist);
216 signal_simple_error ("image list creation failed",
217 instance);
218 }
219 }
220 }
221
222 Fputhash (make_int (tbbutton->idCommand),
223 tb->callback, FRAME_MSWINDOWS_TOOLBAR_HASHTABLE (f));
224
225 tbbutton++;
226 button = tb->next;
227 }
228
229 button = FRAME_TOOLBAR_DATA (f, pos)->toolbar_buttons;
230
231 /* now create the toolbar ... */
232 if ((FRAME_MSWINDOWS_TOOLBAR (f) =
233 CreateToolbarEx (FRAME_MSWINDOWS_HANDLE (f),
234 TBSTYLE_ALTDRAG | WS_CHILD,
235 NULL,
236 nbuttons,
237 0,
238 0,
239 button_tbl,
240 nbuttons,
241 width, height,
242 bmwidth, bmheight,
243 sizeof(TBBUTTON) )) == NULL)
244 {
245 xfree (button_tbl);
246 ImageList_Destroy (ilist);
247 error ("couldn't create toolbar");
248 }
249
250 /* finally populate with images */
251 if (SendMessage (FRAME_MSWINDOWS_TOOLBAR (f), TB_SETIMAGELIST, NULL,
252 (LPARAM)ilist) == -1)
253 {
254 mswindows_clear_toolbar (f, pos, 0);
255 error ("couldn't add image list to toolbar");
256 }
257
258 /* now move the window */
259 SetWindowPos (FRAME_MSWINDOWS_TOOLBAR (f), HWND_TOP, x, y,
260 bar_width, bar_height,
261 SWP_SHOWWINDOW);
262 #if 0
263 ShowWindow (FRAME_MSWINDOWS_TOOLBAR (f), SW_SHOWNORMAL);
264 #endif
265
266 if (button_tbl) xfree (button_tbl);
267
268 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 1);
269 }
270
271 static void
272 mswindows_initialize_frame_toolbars (struct frame *f)
273 {
274
275 }
276
277 static void
278 mswindows_output_frame_toolbars (struct frame *f)
279 {
280 assert (FRAME_MSWINDOWS_P (f));
281
282 if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
283 mswindows_output_toolbar (f, TOP_TOOLBAR);
284 else if (f->top_toolbar_was_visible)
285 mswindows_clear_toolbar (f, TOP_TOOLBAR, 0);
286
287 if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
288 mswindows_output_toolbar (f, BOTTOM_TOOLBAR);
289 else if (f->bottom_toolbar_was_visible)
290 mswindows_clear_toolbar (f, BOTTOM_TOOLBAR, 0);
291
292 if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
293 mswindows_output_toolbar (f, LEFT_TOOLBAR);
294 else if (f->left_toolbar_was_visible)
295 mswindows_clear_toolbar (f, LEFT_TOOLBAR, 0);
296
297 if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
298 mswindows_output_toolbar (f, RIGHT_TOOLBAR);
299 else if (f->right_toolbar_was_visible)
300 mswindows_clear_toolbar (f, RIGHT_TOOLBAR, 0);
301 }
302
303 static void
304 mswindows_free_frame_toolbars (struct frame *f)
305 {
306 mswindows_clear_toolbar(f, 0, 0);
307 }
308
309 /*
310 * Return value is Qt if we have dispatched the command,
311 * or Qnil if id has not been mapped to a callback.
312 * Window procedure may try other targets to route the
313 * command if we return nil
314 */
315 Lisp_Object
316 mswindows_handle_toolbar_wm_command (struct frame* f, WORD id)
317 {
318 /* Try to map the command id through the proper hash table */
319 Lisp_Object command, funcsym, frame;
320 struct gcpro gcpro1;
321
322 command = Fgethash (make_int (id),
323 FRAME_MSWINDOWS_TOOLBAR_HASHTABLE (f), Qunbound);
324 if (UNBOUNDP (command))
325 {
326 return Qnil;
327 }
328
329 /* Need to gcpro because the hashtable may get destroyed
330 by menu_cleanup(), and will not gcpro the command
331 any more */
332 GCPRO1 (command);
333
334 /* Ok, this is our one. Enqueue it. */
335 if (SYMBOLP (command))
336 funcsym = Qcall_interactively;
337 else if (CONSP (command))
338 funcsym = Qeval;
339 else
340 signal_simple_error ("Callback must be either evallable form or a symbol",
341 command);
342
343 XSETFRAME (frame, f);
344 enqueue_misc_user_event (frame, funcsym, command);
345
346 /* Needs good bump also, for WM_COMMAND may have been dispatched from
347 mswindows_need_event, which will block again despite new command
348 event has arrived */
349 mswindows_bump_queue ();
350
351 UNGCPRO; /* command */
352 return Qt;
353 }
354
355
356 /************************************************************************/
357 /* initialization */
358 /************************************************************************/
359
360 void
361 console_type_create_toolbar_mswindows (void)
362 {
363 CONSOLE_HAS_METHOD (mswindows, output_frame_toolbars);
364 CONSOLE_HAS_METHOD (mswindows, initialize_frame_toolbars);
365 CONSOLE_HAS_METHOD (mswindows, free_frame_toolbars);
366 }
367