diff options
| author | Jason Rumney | 2008-06-09 12:38:07 +0000 |
|---|---|---|
| committer | Jason Rumney | 2008-06-09 12:38:07 +0000 |
| commit | 6fc032ed6fb0b960e7b8f1e347062c88115c6f0b (patch) | |
| tree | d56d7a12ae9a9bc1b9eca2e3b0ab8bb2000e30e6 /src | |
| parent | a8495745c0f10e685797848adf87a46363b90c80 (diff) | |
| download | emacs-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.c | 525 |
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 | |||
| 56 | typedef void * XtPointer; | ||
| 57 | typedef char Boolean; | ||
| 58 | |||
| 59 | enum 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. */ | ||
| 68 | typedef 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)) | |||
| 180 | static Lisp_Object w32_menu_show P_ ((FRAME_PTR, int, int, int, int, | 104 | static Lisp_Object w32_menu_show P_ ((FRAME_PTR, int, int, int, int, |
| 181 | Lisp_Object, char **)); | 105 | Lisp_Object, char **)); |
| 182 | 106 | ||
| 183 | static void keymap_panes P_ ((Lisp_Object *, int, int)); | ||
| 184 | static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object, | ||
| 185 | int, int)); | ||
| 186 | static void single_menu_item P_ ((Lisp_Object, Lisp_Object, | ||
| 187 | Lisp_Object *, int, int)); | ||
| 188 | static void list_of_panes P_ ((Lisp_Object)); | ||
| 189 | static void list_of_items P_ ((Lisp_Object)); | ||
| 190 | void w32_free_menu_strings P_((HWND)); | 107 | void 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 | |||
| 218 | enum 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 | |||
| 231 | static Lisp_Object menu_items; | ||
| 232 | |||
| 233 | /* Number of slots currently allocated in menu_items. */ | ||
| 234 | static int menu_items_allocated; | ||
| 235 | |||
| 236 | /* This is the index in menu_items of the first empty slot. */ | ||
| 237 | static int menu_items_used; | ||
| 238 | |||
| 239 | /* The number of panes currently recorded in menu_items, | ||
| 240 | excluding those within submenus. */ | ||
| 241 | static int menu_items_n_panes; | ||
| 242 | |||
| 243 | /* Current depth within submenus. */ | ||
| 244 | static int menu_items_submenu_depth; | ||
| 245 | |||
| 246 | static int next_menubar_widget_id; | 109 | static int next_menubar_widget_id; |
| 247 | 110 | ||
| 111 | extern 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 | |||
| 285 | static void | ||
| 286 | init_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 | |||
| 302 | static void | ||
| 303 | finish_menu_items () | ||
| 304 | { | ||
| 305 | } | ||
| 306 | |||
| 307 | /* Call when finished using the data for the current menu | ||
| 308 | in menu_items. */ | ||
| 309 | |||
| 310 | static void | ||
| 311 | discard_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 | |||
| 324 | static void | ||
| 325 | grow_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 | |||
| 333 | static void | ||
| 334 | push_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 | |||
| 346 | static void | ||
| 347 | push_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 | |||
| 359 | static void | ||
| 360 | push_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 | |||
| 372 | static void | ||
| 373 | push_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 | |||
| 394 | static void | ||
| 395 | push_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 | |||
| 416 | static void | ||
| 417 | keymap_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 | |||
| 445 | static void | ||
| 446 | single_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 | |||
| 511 | static void | ||
| 512 | single_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 | |||
| 571 | static void | ||
| 572 | list_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 | |||
| 596 | static void | ||
| 597 | list_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 | |||
| 619 | DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0, | 147 | DEFUN ("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. |
| 621 | POSITION is a position specification. This is either a mouse button | 149 | POSITION 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 | |||
| 1097 | widget_value * | ||
| 1098 | xmalloc_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. */ | ||
| 1374 | static void | ||
| 1375 | update_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; |