Mercurial > hg > xemacs-beta
comparison src/menubar-msw.c @ 398:74fd4e045ea6 r21-2-29
Import from CVS: tag r21-2-29
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:13:30 +0200 |
parents | 6719134a07c2 |
children | a86b2b5e0111 |
comparison
equal
deleted
inserted
replaced
397:f4aeb21a5bad | 398:74fd4e045ea6 |
---|---|
114 #define MENU_ITEM_ID_MIN 0x8000 | 114 #define MENU_ITEM_ID_MIN 0x8000 |
115 #define MENU_ITEM_ID_MAX 0xFFFF | 115 #define MENU_ITEM_ID_MAX 0xFFFF |
116 #define MENU_ITEM_ID_BITS(x) (((x) & 0x7FFF) | 0x8000) | 116 #define MENU_ITEM_ID_BITS(x) (((x) & 0x7FFF) | 0x8000) |
117 static HMENU top_level_menu; | 117 static HMENU top_level_menu; |
118 | 118 |
119 #define MAX_MENUITEM_LENGTH 128 | |
120 | |
121 /* | 119 /* |
122 * This returns Windows-style menu item string: | 120 * This returns Windows-style menu item string: |
123 * "Left Flush\tRight Flush" | 121 * "Left Flush\tRight Flush" |
124 */ | 122 */ |
125 static char* | 123 static char* |
126 displayable_menu_item (struct gui_item* pgui_item, int bar_p) | 124 displayable_menu_item (Lisp_Object gui_item, int bar_p) |
127 { | 125 { |
128 /* We construct the name in a static buffer. That's fine, because | 126 /* We construct the name in a static buffer. That's fine, because |
129 menu items longer than 128 chars are probably programming errors, | 127 menu items longer than 128 chars are probably programming errors, |
130 and better be caught than displayed! */ | 128 and better be caught than displayed! */ |
131 | 129 |
132 static char buf[MAX_MENUITEM_LENGTH+2]; | 130 static char buf[MAX_MENUITEM_LENGTH+2]; |
133 char *ptr; | 131 char *ptr; |
134 unsigned int ll, lr; | 132 unsigned int ll, lr; |
135 | 133 |
136 /* Left flush part of the string */ | 134 /* Left flush part of the string */ |
137 ll = gui_item_display_flush_left (pgui_item, buf, MAX_MENUITEM_LENGTH); | 135 ll = gui_item_display_flush_left (gui_item, buf, MAX_MENUITEM_LENGTH); |
138 | 136 |
139 /* Escape '&' as '&&' */ | 137 /* Escape '&' as '&&' */ |
140 ptr = buf; | 138 ptr = buf; |
141 while ((ptr=memchr (ptr, '&', ll-(ptr-buf))) != NULL) | 139 while ((ptr=memchr (ptr, '&', ll-(ptr-buf))) != NULL) |
142 { | 140 { |
143 if (ll+2 >= MAX_MENUITEM_LENGTH) | 141 if (ll+2 >= MAX_MENUITEM_LENGTH) |
144 signal_simple_error ("Menu item produces too long displayable string", | 142 signal_simple_error ("Menu item produces too long displayable string", |
145 pgui_item->name); | 143 XGUI_ITEM (gui_item)->name); |
146 memmove (ptr+1, ptr, (ll-(ptr-buf))+1); | 144 memmove (ptr+1, ptr, (ll-(ptr-buf))+1); |
147 ll++; | 145 ll++; |
148 ptr+=2; | 146 ptr+=2; |
149 } | 147 } |
150 | 148 |
163 | 161 |
164 /* Right flush part, unless we're at the top-level where it's not allowed */ | 162 /* Right flush part, unless we're at the top-level where it's not allowed */ |
165 if (!bar_p) | 163 if (!bar_p) |
166 { | 164 { |
167 assert (MAX_MENUITEM_LENGTH > ll + 1); | 165 assert (MAX_MENUITEM_LENGTH > ll + 1); |
168 lr = gui_item_display_flush_right (pgui_item, buf + ll + 1, | 166 lr = gui_item_display_flush_right (gui_item, buf + ll + 1, |
169 MAX_MENUITEM_LENGTH - ll - 1); | 167 MAX_MENUITEM_LENGTH - ll - 1); |
170 if (lr) | 168 if (lr) |
171 buf [ll] = '\t'; | 169 buf [ll] = '\t'; |
172 } | 170 } |
173 | 171 |
277 } | 275 } |
278 else if (CONSP (item)) | 276 else if (CONSP (item)) |
279 { | 277 { |
280 /* Submenu */ | 278 /* Submenu */ |
281 HMENU submenu; | 279 HMENU submenu; |
282 struct gui_item gui_item; | 280 Lisp_Object gui_item = allocate_gui_item (); |
281 Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item); | |
283 struct gcpro gcpro1; | 282 struct gcpro gcpro1; |
284 | 283 |
285 gui_item_init (&gui_item); | 284 GCPRO1 (gui_item); |
286 GCPRO_GUI_ITEM (&gui_item); | 285 |
287 | 286 menu_parse_submenu_keywords (item, gui_item); |
288 menu_parse_submenu_keywords (item, &gui_item); | 287 |
289 | 288 if (!STRINGP (pgui_item->name)) |
290 if (!STRINGP (gui_item.name)) | |
291 signal_simple_error ("Menu name (first element) must be a string", item); | 289 signal_simple_error ("Menu name (first element) must be a string", item); |
292 | 290 |
293 if (!gui_item_included_p (&gui_item, Vmenubar_configuration)) | 291 if (!gui_item_included_p (gui_item, Vmenubar_configuration)) |
294 return; | 292 return; |
295 | 293 |
296 if (!gui_item_active_p (&gui_item)) | 294 if (!gui_item_active_p (gui_item)) |
297 item_info.fState = MFS_GRAYED; | 295 item_info.fState = MFS_GRAYED; |
298 /* Temptation is to put 'else' right here. Although, the | 296 /* Temptation is to put 'else' right here. Although, the |
299 displayed item won't have an arrow indicating that it is a | 297 displayed item won't have an arrow indicating that it is a |
300 popup. So we go ahead a little bit more and create a popup */ | 298 popup. So we go ahead a little bit more and create a popup */ |
301 submenu = create_empty_popup_menu(); | 299 submenu = create_empty_popup_menu(); |
302 | 300 |
303 item_info.fMask |= MIIM_SUBMENU; | 301 item_info.fMask |= MIIM_SUBMENU; |
304 item_info.dwTypeData = displayable_menu_item (&gui_item, bar_p); | 302 item_info.dwTypeData = displayable_menu_item (gui_item, bar_p); |
305 item_info.hSubMenu = submenu; | 303 item_info.hSubMenu = submenu; |
306 | 304 |
307 if (!(item_info.fState & MFS_GRAYED)) | 305 if (!(item_info.fState & MFS_GRAYED)) |
308 { | 306 { |
309 /* Now add the full submenu path as a value to the hash table, | 307 /* Now add the full submenu path as a value to the hash table, |
310 keyed by menu handle */ | 308 keyed by menu handle */ |
311 if (NILP(path)) | 309 if (NILP(path)) |
312 /* list1 cannot GC */ | 310 /* list1 cannot GC */ |
313 path = list1 (gui_item.name); | 311 path = list1 (pgui_item->name); |
314 else | 312 else |
315 { | 313 { |
316 Lisp_Object arg[2]; | 314 Lisp_Object arg[2]; |
317 arg[0] = path; | 315 arg[0] = path; |
318 arg[1] = list1 (gui_item.name); | 316 arg[1] = list1 (pgui_item->name); |
319 /* Fappend gcpro'es its arg */ | 317 /* Fappend gcpro'es its arg */ |
320 path = Fappend (2, arg); | 318 path = Fappend (2, arg); |
321 } | 319 } |
322 | 320 |
323 /* Fputhash GCPRO'es PATH */ | 321 /* Fputhash GCPRO'es PATH */ |
327 } | 325 } |
328 else if (VECTORP (item)) | 326 else if (VECTORP (item)) |
329 { | 327 { |
330 /* An ordinary item */ | 328 /* An ordinary item */ |
331 Lisp_Object style, id; | 329 Lisp_Object style, id; |
332 struct gui_item gui_item; | 330 Lisp_Object gui_item = gui_parse_item_keywords (item); |
331 Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item); | |
333 struct gcpro gcpro1; | 332 struct gcpro gcpro1; |
334 | 333 |
335 gui_item_init (&gui_item); | 334 GCPRO1 (gui_item); |
336 GCPRO_GUI_ITEM (&gui_item); | 335 |
337 | 336 if (!gui_item_included_p (gui_item, Vmenubar_configuration)) |
338 gui_parse_item_keywords (item, &gui_item); | |
339 | |
340 if (!gui_item_included_p (&gui_item, Vmenubar_configuration)) | |
341 return; | 337 return; |
342 | 338 |
343 if (!gui_item_active_p (&gui_item)) | 339 if (!gui_item_active_p (gui_item)) |
344 item_info.fState = MFS_GRAYED; | 340 item_info.fState = MFS_GRAYED; |
345 | 341 |
346 style = (NILP (gui_item.selected) || NILP (Feval (gui_item.selected)) | 342 style = (NILP (pgui_item->selected) || NILP (Feval (pgui_item->selected)) |
347 ? Qnil : gui_item.style); | 343 ? Qnil : pgui_item->style); |
348 | 344 |
349 if (EQ (style, Qradio)) | 345 if (EQ (style, Qradio)) |
350 { | 346 { |
351 item_info.fType |= MFT_RADIOCHECK; | 347 item_info.fType |= MFT_RADIOCHECK; |
352 item_info.fState |= MFS_CHECKED; | 348 item_info.fState |= MFS_CHECKED; |
354 else if (EQ (style, Qtoggle)) | 350 else if (EQ (style, Qtoggle)) |
355 { | 351 { |
356 item_info.fState |= MFS_CHECKED; | 352 item_info.fState |= MFS_CHECKED; |
357 } | 353 } |
358 | 354 |
359 id = allocate_menu_item_id (path, gui_item.name, | 355 id = allocate_menu_item_id (path, pgui_item->name, |
360 gui_item.suffix); | 356 pgui_item->suffix); |
361 Fputhash (id, gui_item.callback, hash_tab); | 357 Fputhash (id, pgui_item->callback, hash_tab); |
362 | 358 |
363 item_info.wID = (UINT) XINT(id); | 359 item_info.wID = (UINT) XINT(id); |
364 item_info.fType |= MFT_STRING; | 360 item_info.fType |= MFT_STRING; |
365 item_info.dwTypeData = displayable_menu_item (&gui_item, bar_p); | 361 item_info.dwTypeData = displayable_menu_item (gui_item, bar_p); |
366 | 362 |
367 UNGCPRO; /* gui_item */ | 363 UNGCPRO; /* gui_item */ |
368 } | 364 } |
369 else | 365 else |
370 { | 366 { |
394 { | 390 { |
395 Lisp_Object item_desc; | 391 Lisp_Object item_desc; |
396 int deep_p, flush_right; | 392 int deep_p, flush_right; |
397 struct gcpro gcpro1; | 393 struct gcpro gcpro1; |
398 unsigned long checksum; | 394 unsigned long checksum; |
399 struct gui_item gui_item; | 395 Lisp_Object gui_item = allocate_gui_item (); |
400 | 396 Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item); |
401 gui_item_init (&gui_item); | 397 GCPRO1 (gui_item); |
402 GCPRO_GUI_ITEM (&gui_item); | |
403 | 398 |
404 /* We are sometimes called with the menubar unchanged, and with changed | 399 /* We are sometimes called with the menubar unchanged, and with changed |
405 right flush. We have to update the menubar in this case, | 400 right flush. We have to update the menubar in this case, |
406 so account for the compliance setting in the hash value */ | 401 so account for the compliance setting in the hash value */ |
407 checksum = REPLACE_ME_WITH_GLOBAL_VARIABLE_WHICH_CONTROLS_RIHGT_FLUSH; | 402 checksum = REPLACE_ME_WITH_GLOBAL_VARIABLE_WHICH_CONTROLS_RIHGT_FLUSH; |
412 | 407 |
413 /* PATH set to nil indicates top-level popup or menubar */ | 408 /* PATH set to nil indicates top-level popup or menubar */ |
414 deep_p = !NILP (path); | 409 deep_p = !NILP (path); |
415 | 410 |
416 /* Fetch keywords prepending the item list */ | 411 /* Fetch keywords prepending the item list */ |
417 desc = menu_parse_submenu_keywords (desc, &gui_item); | 412 desc = menu_parse_submenu_keywords (desc, gui_item); |
418 | 413 |
419 /* Check that menu name is specified when expected */ | 414 /* Check that menu name is specified when expected */ |
420 if (NILP (gui_item.name) && deep_p) | 415 if (NILP (pgui_item->name) && deep_p) |
421 signal_simple_error ("Menu must have a name", desc); | 416 signal_simple_error ("Menu must have a name", desc); |
422 | 417 |
423 /* Apply filter if specified */ | 418 /* Apply filter if specified */ |
424 if (!NILP (gui_item.filter)) | 419 if (!NILP (pgui_item->filter)) |
425 desc = call1 (gui_item.filter, desc); | 420 desc = call1 (pgui_item->filter, desc); |
426 | 421 |
427 /* Loop thru the desc's CDR and add items for each entry */ | 422 /* Loop thru the desc's CDR and add items for each entry */ |
428 flush_right = 0; | 423 flush_right = 0; |
429 EXTERNAL_LIST_LOOP (item_desc, desc) | 424 EXTERNAL_LIST_LOOP (item_desc, desc) |
430 { | 425 { |
451 RemoveMenu (menu, EMPTY_ITEM_ID, MF_BYCOMMAND); | 446 RemoveMenu (menu, EMPTY_ITEM_ID, MF_BYCOMMAND); |
452 | 447 |
453 /* Add the header to the popup, if told so. The same as in X - an | 448 /* Add the header to the popup, if told so. The same as in X - an |
454 insensitive item, and a separator (Seems to me, there were | 449 insensitive item, and a separator (Seems to me, there were |
455 two separators in X... In Windows this looks ugly, anyways. */ | 450 two separators in X... In Windows this looks ugly, anyways. */ |
456 if (!bar_p && !deep_p && popup_menu_titles && !NILP(gui_item.name)) | 451 if (!bar_p && !deep_p && popup_menu_titles && !NILP(pgui_item->name)) |
457 { | 452 { |
458 CHECK_STRING (gui_item.name); | 453 CHECK_STRING (pgui_item->name); |
459 InsertMenu (menu, 0, MF_BYPOSITION | MF_STRING | MF_DISABLED, | 454 InsertMenu (menu, 0, MF_BYPOSITION | MF_STRING | MF_DISABLED, |
460 0, XSTRING_DATA(gui_item.name)); | 455 0, XSTRING_DATA(pgui_item->name)); |
461 InsertMenu (menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); | 456 InsertMenu (menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); |
462 SetMenuDefaultItem (menu, 0, MF_BYPOSITION); | 457 SetMenuDefaultItem (menu, 0, MF_BYPOSITION); |
463 } | 458 } |
464 } | 459 } |
465 UNGCPRO; /* gui_item */ | 460 UNGCPRO; /* gui_item */ |
739 | 734 |
740 static void | 735 static void |
741 mswindows_popup_menu (Lisp_Object menu_desc, Lisp_Object event) | 736 mswindows_popup_menu (Lisp_Object menu_desc, Lisp_Object event) |
742 { | 737 { |
743 struct frame *f = selected_frame (); | 738 struct frame *f = selected_frame (); |
744 struct Lisp_Event *eev = NULL; | 739 Lisp_Event *eev = NULL; |
745 HMENU menu; | 740 HMENU menu; |
746 POINT pt; | 741 POINT pt; |
747 int ok; | 742 int ok; |
748 | 743 |
749 if (!NILP (event)) | 744 if (!NILP (event)) |