Mercurial > hg > xemacs-beta
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 |