aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Rumney2008-06-09 12:38:07 +0000
committerJason Rumney2008-06-09 12:38:07 +0000
commit6fc032ed6fb0b960e7b8f1e347062c88115c6f0b (patch)
treed56d7a12ae9a9bc1b9eca2e3b0ab8bb2000e30e6 /src
parenta8495745c0f10e685797848adf87a46363b90c80 (diff)
downloademacs-6fc032ed6fb0b960e7b8f1e347062c88115c6f0b.tar.gz
emacs-6fc032ed6fb0b960e7b8f1e347062c88115c6f0b.zip
(enum button_type, widget_value, local_heap, local_alloc):
(local_free, malloc_widget_value, free_widget_value): (MENU_ITEMS_ITEM_NAME, MENU_ITEMS_ITEM_ENABLE, MENU_ITEMS_ITEM_VALUE): (MENU_ITEMS_ITEM_EQUIV_KEY, MENU_ITEMS_ITEM_DEFINITION): (MENU_ITEMS_ITEM_TYPE, MENU_ITEMS_ITEM_SELECTED, MENU_ITEMS_ITEM_HELP): (MENU_ITEMS_ITEM_LENGTH, enum menu_item_idx): Remove defs. (menu_items, menu_items_allocated, menu_items_used): (menu_items_n_panes, menu_items_submenu_depth): Remove global vars. (init_menu_items, finish_menu_items, discard_menu_items): (grow_menu_items, push_submenu_start, push_submenu_end): (push_left_right_boundary, push_menu_pane, push_menu_item, (keymap_panes, single_keymap_panes, list_of_panes, list_of_items): (free_menubar_widget_tree_value, parse_single_submenu): (update_submenu_strings): Remove functions. (xmalloc_widget_value): Remove and declare extern.
Diffstat (limited to 'src')
-rw-r--r--src/w32menu.c525
1 files changed, 2 insertions, 523 deletions
diff --git a/src/w32menu.c b/src/w32menu.c
index 8957da895dd..a689d472e71 100644
--- a/src/w32menu.c
+++ b/src/w32menu.c
@@ -50,82 +50,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
50 50
51#undef HAVE_DIALOGS /* TODO: Implement native dialogs. */ 51#undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
52 52
53/******************************************************************/
54/* Definitions copied from lwlib.h */
55
56typedef void * XtPointer;
57typedef char Boolean;
58
59enum button_type
60{
61 BUTTON_TYPE_NONE,
62 BUTTON_TYPE_TOGGLE,
63 BUTTON_TYPE_RADIO
64};
65
66/* This structure is based on the one in ../lwlib/lwlib.h, modified
67 for Windows. */
68typedef struct _widget_value
69{
70 /* name of widget */
71 Lisp_Object lname;
72 char* name;
73 /* value (meaning depend on widget type) */
74 char* value;
75 /* keyboard equivalent. no implications for XtTranslations */
76 Lisp_Object lkey;
77 char* key;
78 /* Help string or nil if none.
79 GC finds this string through the frame's menu_bar_vector
80 or through menu_items. */
81 Lisp_Object help;
82 /* true if enabled */
83 Boolean enabled;
84 /* true if selected */
85 Boolean selected;
86 /* The type of a button. */
87 enum button_type button_type;
88 /* true if menu title */
89 Boolean title;
90#if 0
91 /* true if was edited (maintained by get_value) */
92 Boolean edited;
93 /* true if has changed (maintained by lw library) */
94 change_type change;
95 /* true if this widget itself has changed,
96 but not counting the other widgets found in the `next' field. */
97 change_type this_one_change;
98#endif
99 /* Contents of the sub-widgets, also selected slot for checkbox */
100 struct _widget_value* contents;
101 /* data passed to callback */
102 XtPointer call_data;
103 /* next one in the list */
104 struct _widget_value* next;
105#if 0
106 /* slot for the toolkit dependent part. Always initialize to NULL. */
107 void* toolkit_data;
108 /* tell us if we should free the toolkit data slot when freeing the
109 widget_value itself. */
110 Boolean free_toolkit_data;
111
112 /* we resource the widget_value structures; this points to the next
113 one on the free list if this one has been deallocated.
114 */
115 struct _widget_value *free_list;
116#endif
117} widget_value;
118
119/* Local memory management */
120#define local_heap (GetProcessHeap ())
121#define local_alloc(n) (HeapAlloc (local_heap, HEAP_ZERO_MEMORY, (n)))
122#define local_free(p) (HeapFree (local_heap, 0, ((LPVOID) (p))))
123
124#define malloc_widget_value() ((widget_value *) local_alloc (sizeof (widget_value)))
125#define free_widget_value(wv) (local_free ((wv)))
126
127/******************************************************************/
128
129#ifndef TRUE 53#ifndef TRUE
130#define TRUE 1 54#define TRUE 1
131#define FALSE 0 55#define FALSE 0
@@ -180,71 +104,12 @@ static Lisp_Object simple_dialog_show P_ ((FRAME_PTR, Lisp_Object, Lisp_Object))
180static Lisp_Object w32_menu_show P_ ((FRAME_PTR, int, int, int, int, 104static Lisp_Object w32_menu_show P_ ((FRAME_PTR, int, int, int, int,
181 Lisp_Object, char **)); 105 Lisp_Object, char **));
182 106
183static void keymap_panes P_ ((Lisp_Object *, int, int));
184static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
185 int, int));
186static void single_menu_item P_ ((Lisp_Object, Lisp_Object,
187 Lisp_Object *, int, int));
188static void list_of_panes P_ ((Lisp_Object));
189static void list_of_items P_ ((Lisp_Object));
190void w32_free_menu_strings P_((HWND)); 107void w32_free_menu_strings P_((HWND));
191 108
192/* This holds a Lisp vector that holds the results of decoding
193 the keymaps or alist-of-alists that specify a menu.
194
195 It describes the panes and items within the panes.
196
197 Each pane is described by 3 elements in the vector:
198 t, the pane name, the pane's prefix key.
199 Then follow the pane's items, with 5 elements per item:
200 the item string, the enable flag, the item's value,
201 the definition, and the equivalent keyboard key's description string.
202
203 In some cases, multiple levels of menus may be described.
204 A single vector slot containing nil indicates the start of a submenu.
205 A single vector slot containing lambda indicates the end of a submenu.
206 The submenu follows a menu item which is the way to reach the submenu.
207
208 A single vector slot containing quote indicates that the
209 following items should appear on the right of a dialog box.
210
211 Using a Lisp vector to hold this information while we decode it
212 takes care of protecting all the data from GC. */
213
214#define MENU_ITEMS_PANE_NAME 1
215#define MENU_ITEMS_PANE_PREFIX 2
216#define MENU_ITEMS_PANE_LENGTH 3
217
218enum menu_item_idx
219{
220 MENU_ITEMS_ITEM_NAME = 0,
221 MENU_ITEMS_ITEM_ENABLE,
222 MENU_ITEMS_ITEM_VALUE,
223 MENU_ITEMS_ITEM_EQUIV_KEY,
224 MENU_ITEMS_ITEM_DEFINITION,
225 MENU_ITEMS_ITEM_TYPE,
226 MENU_ITEMS_ITEM_SELECTED,
227 MENU_ITEMS_ITEM_HELP,
228 MENU_ITEMS_ITEM_LENGTH
229};
230
231static Lisp_Object menu_items;
232
233/* Number of slots currently allocated in menu_items. */
234static int menu_items_allocated;
235
236/* This is the index in menu_items of the first empty slot. */
237static int menu_items_used;
238
239/* The number of panes currently recorded in menu_items,
240 excluding those within submenus. */
241static int menu_items_n_panes;
242
243/* Current depth within submenus. */
244static int menu_items_submenu_depth;
245
246static int next_menubar_widget_id; 109static int next_menubar_widget_id;
247 110
111extern widget_value *xmalloc_widget_value P_ ((void));
112
248/* This is set nonzero after the user activates the menu bar, and set 113/* This is set nonzero after the user activates the menu bar, and set
249 to zero again after the menu bars are redisplayed by prepare_menu_bar. 114 to zero again after the menu bars are redisplayed by prepare_menu_bar.
250 While it is nonzero, all calls to set_frame_menubar go deep. 115 While it is nonzero, all calls to set_frame_menubar go deep.
@@ -279,343 +144,6 @@ menubar_id_to_frame (id)
279 return 0; 144 return 0;
280} 145}
281 146
282/* Initialize the menu_items structure if we haven't already done so.
283 Also mark it as currently empty. */
284
285static void
286init_menu_items ()
287{
288 if (NILP (menu_items))
289 {
290 menu_items_allocated = 60;
291 menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
292 }
293
294 menu_items_used = 0;
295 menu_items_n_panes = 0;
296 menu_items_submenu_depth = 0;
297}
298
299/* Call at the end of generating the data in menu_items.
300 This fills in the number of items in the last pane. */
301
302static void
303finish_menu_items ()
304{
305}
306
307/* Call when finished using the data for the current menu
308 in menu_items. */
309
310static void
311discard_menu_items ()
312{
313 /* Free the structure if it is especially large.
314 Otherwise, hold on to it, to save time. */
315 if (menu_items_allocated > 200)
316 {
317 menu_items = Qnil;
318 menu_items_allocated = 0;
319 }
320}
321
322/* Make the menu_items vector twice as large. */
323
324static void
325grow_menu_items ()
326{
327 menu_items_allocated *= 2;
328 menu_items = larger_vector (menu_items, menu_items_allocated, Qnil);
329}
330
331/* Begin a submenu. */
332
333static void
334push_submenu_start ()
335{
336 if (menu_items_used + 1 > menu_items_allocated)
337 grow_menu_items ();
338
339 ASET (menu_items, menu_items_used, Qnil);
340 menu_items_used++;
341 menu_items_submenu_depth++;
342}
343
344/* End a submenu. */
345
346static void
347push_submenu_end ()
348{
349 if (menu_items_used + 1 > menu_items_allocated)
350 grow_menu_items ();
351
352 ASET (menu_items, menu_items_used, Qlambda);
353 menu_items_used++;
354 menu_items_submenu_depth--;
355}
356
357/* Indicate boundary between left and right. */
358
359static void
360push_left_right_boundary ()
361{
362 if (menu_items_used + 1 > menu_items_allocated)
363 grow_menu_items ();
364
365 ASET (menu_items, menu_items_used, Qquote);
366 menu_items_used++;
367}
368
369/* Start a new menu pane in menu_items.
370 NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */
371
372static void
373push_menu_pane (name, prefix_vec)
374 Lisp_Object name, prefix_vec;
375{
376 if (menu_items_used + MENU_ITEMS_PANE_LENGTH > menu_items_allocated)
377 grow_menu_items ();
378
379 if (menu_items_submenu_depth == 0)
380 menu_items_n_panes++;
381 ASET (menu_items, menu_items_used, Qt); menu_items_used++;
382 ASET (menu_items, menu_items_used, name); menu_items_used++;
383 ASET (menu_items, menu_items_used, prefix_vec); menu_items_used++;
384}
385
386/* Push one menu item into the current pane. NAME is the string to
387 display. ENABLE if non-nil means this item can be selected. KEY
388 is the key generated by choosing this item, or nil if this item
389 doesn't really have a definition. DEF is the definition of this
390 item. EQUIV is the textual description of the keyboard equivalent
391 for this item (or nil if none). TYPE is the type of this menu
392 item, one of nil, `toggle' or `radio'. */
393
394static void
395push_menu_item (name, enable, key, def, equiv, type, selected, help)
396 Lisp_Object name, enable, key, def, equiv, type, selected, help;
397{
398 if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
399 grow_menu_items ();
400
401 ASET (menu_items, menu_items_used, name); menu_items_used++;
402 ASET (menu_items, menu_items_used, enable); menu_items_used++;
403 ASET (menu_items, menu_items_used, key); menu_items_used++;
404 ASET (menu_items, menu_items_used, equiv); menu_items_used++;
405 ASET (menu_items, menu_items_used, def); menu_items_used++;
406 ASET (menu_items, menu_items_used, type); menu_items_used++;
407 ASET (menu_items, menu_items_used, selected); menu_items_used++;
408 ASET (menu_items, menu_items_used, help); menu_items_used++;
409}
410
411/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
412 and generate menu panes for them in menu_items.
413 If NOTREAL is nonzero,
414 don't bother really computing whether an item is enabled. */
415
416static void
417keymap_panes (keymaps, nmaps, notreal)
418 Lisp_Object *keymaps;
419 int nmaps;
420 int notreal;
421{
422 int mapno;
423
424 init_menu_items ();
425
426 /* Loop over the given keymaps, making a pane for each map.
427 But don't make a pane that is empty--ignore that map instead.
428 P is the number of panes we have made so far. */
429 for (mapno = 0; mapno < nmaps; mapno++)
430 single_keymap_panes (keymaps[mapno],
431 Fkeymap_prompt (keymaps[mapno]), Qnil, notreal, 10);
432
433 finish_menu_items ();
434}
435
436/* This is a recursive subroutine of keymap_panes.
437 It handles one keymap, KEYMAP.
438 The other arguments are passed along
439 or point to local variables of the previous function.
440 If NOTREAL is nonzero, only check for equivalent key bindings, don't
441 evaluate expressions in menu items and don't make any menu.
442
443 If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
444
445static void
446single_keymap_panes (keymap, pane_name, prefix, notreal, maxdepth)
447 Lisp_Object keymap;
448 Lisp_Object pane_name;
449 Lisp_Object prefix;
450 int notreal;
451 int maxdepth;
452{
453 Lisp_Object pending_maps = Qnil;
454 Lisp_Object tail, item;
455 struct gcpro gcpro1, gcpro2;
456
457 if (maxdepth <= 0)
458 return;
459
460 push_menu_pane (pane_name, prefix);
461
462 for (tail = keymap; CONSP (tail); tail = XCDR (tail))
463 {
464 GCPRO2 (keymap, pending_maps);
465 /* Look at each key binding, and if it is a menu item add it
466 to this menu. */
467 item = XCAR (tail);
468 if (CONSP (item))
469 single_menu_item (XCAR (item), XCDR (item),
470 &pending_maps, notreal, maxdepth);
471 else if (VECTORP (item))
472 {
473 /* Loop over the char values represented in the vector. */
474 int len = ASIZE (item);
475 int c;
476 for (c = 0; c < len; c++)
477 {
478 Lisp_Object character;
479 XSETFASTINT (character, c);
480 single_menu_item (character, AREF (item, c),
481 &pending_maps, notreal, maxdepth);
482 }
483 }
484 UNGCPRO;
485 }
486
487 /* Process now any submenus which want to be panes at this level. */
488 while (!NILP (pending_maps))
489 {
490 Lisp_Object elt, eltcdr, string;
491 elt = Fcar (pending_maps);
492 eltcdr = XCDR (elt);
493 string = XCAR (eltcdr);
494 /* We no longer discard the @ from the beginning of the string here.
495 Instead, we do this in w32_menu_show. */
496 single_keymap_panes (Fcar (elt), string,
497 XCDR (eltcdr), notreal, maxdepth - 1);
498 pending_maps = Fcdr (pending_maps);
499 }
500}
501
502/* This is a subroutine of single_keymap_panes that handles one
503 keymap entry.
504 KEY is a key in a keymap and ITEM is its binding.
505 PENDING_MAPS_PTR points to a list of keymaps waiting to be made into
506 separate panes.
507 If NOTREAL is nonzero, only check for equivalent key bindings, don't
508 evaluate expressions in menu items and don't make any menu.
509 If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
510
511static void
512single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth)
513 Lisp_Object key, item;
514 Lisp_Object *pending_maps_ptr;
515 int maxdepth, notreal;
516{
517 Lisp_Object map, item_string, enabled;
518 struct gcpro gcpro1, gcpro2;
519 int res;
520
521 /* Parse the menu item and leave the result in item_properties. */
522 GCPRO2 (key, item);
523 res = parse_menu_item (item, notreal, 0);
524 UNGCPRO;
525 if (!res)
526 return; /* Not a menu item. */
527
528 map = AREF (item_properties, ITEM_PROPERTY_MAP);
529
530 if (notreal)
531 {
532 /* We don't want to make a menu, just traverse the keymaps to
533 precompute equivalent key bindings. */
534 if (!NILP (map))
535 single_keymap_panes (map, Qnil, key, 1, maxdepth - 1);
536 return;
537 }
538
539 enabled = AREF (item_properties, ITEM_PROPERTY_ENABLE);
540 item_string = AREF (item_properties, ITEM_PROPERTY_NAME);
541
542 if (!NILP (map) && SREF (item_string, 0) == '@')
543 {
544 if (!NILP (enabled))
545 /* An enabled separate pane. Remember this to handle it later. */
546 *pending_maps_ptr = Fcons (Fcons (map, Fcons (item_string, key)),
547 *pending_maps_ptr);
548 return;
549 }
550
551 push_menu_item (item_string, enabled, key,
552 AREF (item_properties, ITEM_PROPERTY_DEF),
553 AREF (item_properties, ITEM_PROPERTY_KEYEQ),
554 AREF (item_properties, ITEM_PROPERTY_TYPE),
555 AREF (item_properties, ITEM_PROPERTY_SELECTED),
556 AREF (item_properties, ITEM_PROPERTY_HELP));
557
558 /* Display a submenu using the toolkit. */
559 if (! (NILP (map) || NILP (enabled)))
560 {
561 push_submenu_start ();
562 single_keymap_panes (map, Qnil, key, 0, maxdepth - 1);
563 push_submenu_end ();
564 }
565}
566
567/* Push all the panes and items of a menu described by the
568 alist-of-alists MENU.
569 This handles old-fashioned calls to x-popup-menu. */
570
571static void
572list_of_panes (menu)
573 Lisp_Object menu;
574{
575 Lisp_Object tail;
576
577 init_menu_items ();
578
579 for (tail = menu; CONSP (tail); tail = XCDR (tail))
580 {
581 Lisp_Object elt, pane_name, pane_data;
582 elt = XCAR (tail);
583 pane_name = Fcar (elt);
584 CHECK_STRING (pane_name);
585 push_menu_pane (pane_name, Qnil);
586 pane_data = Fcdr (elt);
587 CHECK_CONS (pane_data);
588 list_of_items (pane_data);
589 }
590
591 finish_menu_items ();
592}
593
594/* Push the items in a single pane defined by the alist PANE. */
595
596static void
597list_of_items (pane)
598 Lisp_Object pane;
599{
600 Lisp_Object tail, item, item1;
601
602 for (tail = pane; CONSP (tail); tail = XCDR (tail))
603 {
604 item = XCAR (tail);
605 if (STRINGP (item))
606 push_menu_item (item, Qnil, Qnil, Qt, Qnil, Qnil, Qnil, Qnil);
607 else if (NILP (item))
608 push_left_right_boundary ();
609 else
610 {
611 CHECK_CONS (item);
612 item1 = Fcar (item);
613 CHECK_STRING (item1);
614 push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil, Qnil, Qnil, Qnil);
615 }
616 }
617}
618
619DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0, 147DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
620 doc: /* Pop up a deck-of-cards menu and return user's selection. 148 doc: /* Pop up a deck-of-cards menu and return user's selection.
621POSITION is a position specification. This is either a mouse button 149POSITION is a position specification. This is either a mouse button
@@ -1092,20 +620,6 @@ menubar_selection_callback (FRAME_PTR f, void * client_data)
1092 f->output_data.w32->menubar_active = 0; 620 f->output_data.w32->menubar_active = 0;
1093} 621}
1094 622
1095/* Allocate a widget_value, blocking input. */
1096
1097widget_value *
1098xmalloc_widget_value ()
1099{
1100 widget_value *value;
1101
1102 BLOCK_INPUT;
1103 value = malloc_widget_value ();
1104 UNBLOCK_INPUT;
1105
1106 return value;
1107}
1108
1109/* This recursively calls free_widget_value on the tree of widgets. 623/* This recursively calls free_widget_value on the tree of widgets.
1110 It must free all data that was malloc'ed for these widget_values. 624 It must free all data that was malloc'ed for these widget_values.
1111 In Emacs, many slots are pointers into the data of Lisp_Strings, and 625 In Emacs, many slots are pointers into the data of Lisp_Strings, and
@@ -1366,41 +880,6 @@ digest_single_submenu (start, end, top_level_items)
1366} 880}
1367 881
1368 882
1369/* Walk through the widget_value tree starting at FIRST_WV and update
1370 the char * pointers from the corresponding lisp values.
1371 We do this after building the whole tree, since GC may happen while the
1372 tree is constructed, and small strings are relocated. So we must wait
1373 until no GC can happen before storing pointers into lisp values. */
1374static void
1375update_submenu_strings (first_wv)
1376 widget_value *first_wv;
1377{
1378 widget_value *wv;
1379
1380 for (wv = first_wv; wv; wv = wv->next)
1381 {
1382 if (wv->lname && ! NILP (wv->lname))
1383 {
1384 wv->name = SDATA (wv->lname);
1385
1386 /* Ignore the @ that means "separate pane".
1387 This is a kludge, but this isn't worth more time. */
1388 if (wv->value == (char *)1)
1389 {
1390 if (wv->name[0] == '@')
1391 wv->name++;
1392 wv->value = 0;
1393 }
1394 }
1395
1396 if (wv->lkey && ! NILP (wv->lkey))
1397 wv->key = SDATA (wv->lkey);
1398
1399 if (wv->contents)
1400 update_submenu_strings (wv->contents);
1401 }
1402}
1403
1404 883
1405/* Set the contents of the menubar widgets of frame F. 884/* Set the contents of the menubar widgets of frame F.
1406 The argument FIRST_TIME is currently ignored; 885 The argument FIRST_TIME is currently ignored;