diff options
| author | Richard M. Stallman | 1994-03-10 17:03:21 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1994-03-10 17:03:21 +0000 |
| commit | 101bb4a5539a543fae012c71b2d23b642c2026e3 (patch) | |
| tree | b440510c3f2d65cd2a2c7e76eb5fddf8f39a7336 /src | |
| parent | 51d5a2c95f507e988922ccd80828a1c73405bdd7 (diff) | |
| download | emacs-101bb4a5539a543fae012c71b2d23b642c2026e3.tar.gz emacs-101bb4a5539a543fae012c71b2d23b642c2026e3.zip | |
(Fx_popup_menu): If POSITION is nil,
don't require an open X connection.
(single_keymap_panes, keymap_panes, menu_item_enabled_p): New arg NOTREAL.
(Fx_popup_menu): Pass new arg (1 if POSITION is nil).
(menu_item_enabled_p): If NOTREAL, always return t.
(single_keymap_panes) [!USE_X_TOOLKIT]:
Append > to item_string if submenu.
[USE_X_TOOLKIT]: Display submenus in Xt style.
(menu_items): Record where submenus start and end.
(menu_items_submenu_depth): New variable.
(init_menu_items): Init it.
(push_submenu_start, push_submenu_end): New functions.
(grow_menu_items): New function.
(push_menu_pane, push_menu_item): Use it.
(push_menu_pane): Increment menu_items_n_panes only if depth is 0.
(single_keymap_panes) [USE_X_TOOLKIT]: Record submenus in menu_items.
(xmenu_show) [USE_X_TOOLKIT]: Give submenus to toolkit.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xmenu.c | 210 |
1 files changed, 164 insertions, 46 deletions
diff --git a/src/xmenu.c b/src/xmenu.c index acfb48e2fec..eb9122b2d06 100644 --- a/src/xmenu.c +++ b/src/xmenu.c | |||
| @@ -113,6 +113,11 @@ static void list_of_items (); | |||
| 113 | the item string, the enable flag, the item's value, | 113 | the item string, the enable flag, the item's value, |
| 114 | and the equivalent keyboard key's description string. | 114 | and the equivalent keyboard key's description string. |
| 115 | 115 | ||
| 116 | In some cases, multiple levels of menus may be described. | ||
| 117 | A single vector slot containing nil indicates the start of a submenu. | ||
| 118 | A single vector slot containing lambda indicates the end of a submenu. | ||
| 119 | The submenu follows a menu item which is the way to reach the submenu. | ||
| 120 | |||
| 116 | Using a Lisp vector to hold this information while we decode it | 121 | Using a Lisp vector to hold this information while we decode it |
| 117 | takes care of protecting all the data from GC. */ | 122 | takes care of protecting all the data from GC. */ |
| 118 | 123 | ||
| @@ -134,9 +139,13 @@ static int menu_items_allocated; | |||
| 134 | /* This is the index in menu_items of the first empty slot. */ | 139 | /* This is the index in menu_items of the first empty slot. */ |
| 135 | static int menu_items_used; | 140 | static int menu_items_used; |
| 136 | 141 | ||
| 137 | /* The number of panes currently recorded in menu_items. */ | 142 | /* The number of panes currently recorded in menu_items, |
| 143 | excluding those within submenus. */ | ||
| 138 | static int menu_items_n_panes; | 144 | static int menu_items_n_panes; |
| 139 | 145 | ||
| 146 | /* Current depth within submenus. */ | ||
| 147 | static int menu_items_submenu_depth; | ||
| 148 | |||
| 140 | /* Initialize the menu_items structure if we haven't already done so. | 149 | /* Initialize the menu_items structure if we haven't already done so. |
| 141 | Also mark it as currently empty. */ | 150 | Also mark it as currently empty. */ |
| 142 | 151 | ||
| @@ -151,6 +160,7 @@ init_menu_items () | |||
| 151 | 160 | ||
| 152 | menu_items_used = 0; | 161 | menu_items_used = 0; |
| 153 | menu_items_n_panes = 0; | 162 | menu_items_n_panes = 0; |
| 163 | menu_items_submenu_depth = 0; | ||
| 154 | } | 164 | } |
| 155 | 165 | ||
| 156 | /* Call at the end of generating the data in menu_items. | 166 | /* Call at the end of generating the data in menu_items. |
| @@ -176,6 +186,45 @@ discard_menu_items () | |||
| 176 | } | 186 | } |
| 177 | } | 187 | } |
| 178 | 188 | ||
| 189 | /* Make the menu_items vector twice as large. */ | ||
| 190 | |||
| 191 | static void | ||
| 192 | grow_menu_items () | ||
| 193 | { | ||
| 194 | Lisp_Object old; | ||
| 195 | int old_size = menu_items_allocated; | ||
| 196 | old = menu_items; | ||
| 197 | |||
| 198 | menu_items_allocated *= 2; | ||
| 199 | menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil); | ||
| 200 | bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents, | ||
| 201 | old_size * sizeof (Lisp_Object)); | ||
| 202 | } | ||
| 203 | |||
| 204 | /* Begin a submenu. */ | ||
| 205 | |||
| 206 | static void | ||
| 207 | push_submenu_start () | ||
| 208 | { | ||
| 209 | if (menu_items_used + 1 > menu_items_allocated) | ||
| 210 | grow_menu_items (); | ||
| 211 | |||
| 212 | XVECTOR (menu_items)->contents[menu_items_used++] = Qnil; | ||
| 213 | menu_items_submenu_depth++; | ||
| 214 | } | ||
| 215 | |||
| 216 | /* End a submenu. */ | ||
| 217 | |||
| 218 | static void | ||
| 219 | push_submenu_end () | ||
| 220 | { | ||
| 221 | if (menu_items_used + 1 > menu_items_allocated) | ||
| 222 | grow_menu_items (); | ||
| 223 | |||
| 224 | XVECTOR (menu_items)->contents[menu_items_used++] = Qlambda; | ||
| 225 | menu_items_submenu_depth--; | ||
| 226 | } | ||
| 227 | |||
| 179 | /* Start a new menu pane in menu_items.. | 228 | /* Start a new menu pane in menu_items.. |
| 180 | NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */ | 229 | NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */ |
| 181 | 230 | ||
| @@ -184,18 +233,10 @@ push_menu_pane (name, prefix_vec) | |||
| 184 | Lisp_Object name, prefix_vec; | 233 | Lisp_Object name, prefix_vec; |
| 185 | { | 234 | { |
| 186 | if (menu_items_used + MENU_ITEMS_PANE_LENGTH > menu_items_allocated) | 235 | if (menu_items_used + MENU_ITEMS_PANE_LENGTH > menu_items_allocated) |
| 187 | { | 236 | grow_menu_items (); |
| 188 | Lisp_Object old; | ||
| 189 | int old_size = menu_items_allocated; | ||
| 190 | old = menu_items; | ||
| 191 | 237 | ||
| 192 | menu_items_allocated *= 2; | 238 | if (menu_items_submenu_depth == 0) |
| 193 | menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil); | 239 | menu_items_n_panes++; |
| 194 | bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents, | ||
| 195 | old_size * sizeof (Lisp_Object)); | ||
| 196 | } | ||
| 197 | |||
| 198 | menu_items_n_panes++; | ||
| 199 | XVECTOR (menu_items)->contents[menu_items_used++] = Qt; | 240 | XVECTOR (menu_items)->contents[menu_items_used++] = Qt; |
| 200 | XVECTOR (menu_items)->contents[menu_items_used++] = name; | 241 | XVECTOR (menu_items)->contents[menu_items_used++] = name; |
| 201 | XVECTOR (menu_items)->contents[menu_items_used++] = prefix_vec; | 242 | XVECTOR (menu_items)->contents[menu_items_used++] = prefix_vec; |
| @@ -212,16 +253,7 @@ push_menu_item (name, enable, key, equiv) | |||
| 212 | Lisp_Object name, enable, key, equiv; | 253 | Lisp_Object name, enable, key, equiv; |
| 213 | { | 254 | { |
| 214 | if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated) | 255 | if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated) |
| 215 | { | 256 | grow_menu_items (); |
| 216 | Lisp_Object old; | ||
| 217 | int old_size = menu_items_allocated; | ||
| 218 | old = menu_items; | ||
| 219 | |||
| 220 | menu_items_allocated *= 2; | ||
| 221 | menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil); | ||
| 222 | bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents, | ||
| 223 | old_size * sizeof (Lisp_Object)); | ||
| 224 | } | ||
| 225 | 257 | ||
| 226 | XVECTOR (menu_items)->contents[menu_items_used++] = name; | 258 | XVECTOR (menu_items)->contents[menu_items_used++] = name; |
| 227 | XVECTOR (menu_items)->contents[menu_items_used++] = enable; | 259 | XVECTOR (menu_items)->contents[menu_items_used++] = enable; |
| @@ -319,15 +351,18 @@ menu_item_enabled_p_1 (arg) | |||
| 319 | } | 351 | } |
| 320 | 352 | ||
| 321 | /* Return non-nil if the command DEF is enabled when used as a menu item. | 353 | /* Return non-nil if the command DEF is enabled when used as a menu item. |
| 322 | This is based on looking for a menu-enable property. */ | 354 | This is based on looking for a menu-enable property. |
| 355 | If NOTREAL is set, don't bother really computing this. */ | ||
| 323 | 356 | ||
| 324 | static Lisp_Object | 357 | static Lisp_Object |
| 325 | menu_item_enabled_p (def) | 358 | menu_item_enabled_p (def, notreal) |
| 326 | Lisp_Object def; | 359 | Lisp_Object def; |
| 327 | { | 360 | { |
| 328 | Lisp_Object enabled, tem; | 361 | Lisp_Object enabled, tem; |
| 329 | 362 | ||
| 330 | enabled = Qt; | 363 | enabled = Qt; |
| 364 | if (notreal) | ||
| 365 | return enabled; | ||
| 331 | if (XTYPE (def) == Lisp_Symbol) | 366 | if (XTYPE (def) == Lisp_Symbol) |
| 332 | { | 367 | { |
| 333 | /* No property, or nil, means enable. | 368 | /* No property, or nil, means enable. |
| @@ -343,12 +378,15 @@ menu_item_enabled_p (def) | |||
| 343 | } | 378 | } |
| 344 | 379 | ||
| 345 | /* Look through KEYMAPS, a vector of keymaps that is NMAPS long, | 380 | /* Look through KEYMAPS, a vector of keymaps that is NMAPS long, |
| 346 | and generate menu panes for them in menu_items. */ | 381 | and generate menu panes for them in menu_items. |
| 382 | If NOTREAL is nonzero, | ||
| 383 | don't bother really computing whether an item is enabled. */ | ||
| 347 | 384 | ||
| 348 | static void | 385 | static void |
| 349 | keymap_panes (keymaps, nmaps) | 386 | keymap_panes (keymaps, nmaps, notreal) |
| 350 | Lisp_Object *keymaps; | 387 | Lisp_Object *keymaps; |
| 351 | int nmaps; | 388 | int nmaps; |
| 389 | int notreal; | ||
| 352 | { | 390 | { |
| 353 | int mapno; | 391 | int mapno; |
| 354 | 392 | ||
| @@ -358,7 +396,7 @@ keymap_panes (keymaps, nmaps) | |||
| 358 | But don't make a pane that is empty--ignore that map instead. | 396 | But don't make a pane that is empty--ignore that map instead. |
| 359 | P is the number of panes we have made so far. */ | 397 | P is the number of panes we have made so far. */ |
| 360 | for (mapno = 0; mapno < nmaps; mapno++) | 398 | for (mapno = 0; mapno < nmaps; mapno++) |
| 361 | single_keymap_panes (keymaps[mapno], Qnil, Qnil); | 399 | single_keymap_panes (keymaps[mapno], Qnil, Qnil, notreal); |
| 362 | 400 | ||
| 363 | finish_menu_items (); | 401 | finish_menu_items (); |
| 364 | } | 402 | } |
| @@ -366,13 +404,16 @@ keymap_panes (keymaps, nmaps) | |||
| 366 | /* This is a recursive subroutine of keymap_panes. | 404 | /* This is a recursive subroutine of keymap_panes. |
| 367 | It handles one keymap, KEYMAP. | 405 | It handles one keymap, KEYMAP. |
| 368 | The other arguments are passed along | 406 | The other arguments are passed along |
| 369 | or point to local variables of the previous function. */ | 407 | or point to local variables of the previous function. |
| 408 | If NOTREAL is nonzero, | ||
| 409 | don't bother really computing whether an item is enabled. */ | ||
| 370 | 410 | ||
| 371 | static void | 411 | static void |
| 372 | single_keymap_panes (keymap, pane_name, prefix) | 412 | single_keymap_panes (keymap, pane_name, prefix, notreal) |
| 373 | Lisp_Object keymap; | 413 | Lisp_Object keymap; |
| 374 | Lisp_Object pane_name; | 414 | Lisp_Object pane_name; |
| 375 | Lisp_Object prefix; | 415 | Lisp_Object prefix; |
| 416 | int notreal; | ||
| 376 | { | 417 | { |
| 377 | Lisp_Object pending_maps; | 418 | Lisp_Object pending_maps; |
| 378 | Lisp_Object tail, item, item1, item_string, table; | 419 | Lisp_Object tail, item, item1, item_string, table; |
| @@ -410,7 +451,8 @@ single_keymap_panes (keymap, pane_name, prefix) | |||
| 410 | a string. Since there's no GCPRO5, we refetch | 451 | a string. Since there's no GCPRO5, we refetch |
| 411 | item_string instead of protecting it. */ | 452 | item_string instead of protecting it. */ |
| 412 | GCPRO4 (keymap, pending_maps, def, descrip); | 453 | GCPRO4 (keymap, pending_maps, def, descrip); |
| 413 | enabled = menu_item_enabled_p (def); | 454 | enabled = menu_item_enabled_p (def, notreal); |
| 455 | |||
| 414 | UNGCPRO; | 456 | UNGCPRO; |
| 415 | 457 | ||
| 416 | item_string = XCONS (item1)->car; | 458 | item_string = XCONS (item1)->car; |
| @@ -420,8 +462,28 @@ single_keymap_panes (keymap, pane_name, prefix) | |||
| 420 | pending_maps = Fcons (Fcons (def, Fcons (item_string, XCONS (item)->car)), | 462 | pending_maps = Fcons (Fcons (def, Fcons (item_string, XCONS (item)->car)), |
| 421 | pending_maps); | 463 | pending_maps); |
| 422 | else | 464 | else |
| 423 | push_menu_item (item_string, enabled, XCONS (item)->car, | 465 | { |
| 424 | descrip); | 466 | Lisp_Object submap; |
| 467 | submap = get_keymap_1 (def, 0, 1); | ||
| 468 | #ifndef USE_X_TOOLKIT | ||
| 469 | /* Indicate visually that this is a submenu. */ | ||
| 470 | if (!NILP (submap)) | ||
| 471 | item_string = concat2 (item_string, | ||
| 472 | build_string (" >")); | ||
| 473 | #endif | ||
| 474 | push_menu_item (item_string, enabled, XCONS (item)->car, | ||
| 475 | descrip); | ||
| 476 | #ifdef USE_X_TOOLKIT | ||
| 477 | /* Display a submenu using the toolkit. */ | ||
| 478 | if (! NILP (submap)) | ||
| 479 | { | ||
| 480 | push_submenu_start (); | ||
| 481 | single_keymap_panes (submap, Qnil, | ||
| 482 | XCONS (item)->car, notreal); | ||
| 483 | push_submenu_end (); | ||
| 484 | } | ||
| 485 | #endif | ||
| 486 | } | ||
| 425 | } | 487 | } |
| 426 | } | 488 | } |
| 427 | } | 489 | } |
| @@ -455,7 +517,7 @@ single_keymap_panes (keymap, pane_name, prefix) | |||
| 455 | a string. Since there's no GCPRO5, we refetch | 517 | a string. Since there's no GCPRO5, we refetch |
| 456 | item_string instead of protecting it. */ | 518 | item_string instead of protecting it. */ |
| 457 | GCPRO4 (keymap, pending_maps, def, descrip); | 519 | GCPRO4 (keymap, pending_maps, def, descrip); |
| 458 | enabled = menu_item_enabled_p (def); | 520 | enabled = menu_item_enabled_p (def, notreal); |
| 459 | UNGCPRO; | 521 | UNGCPRO; |
| 460 | 522 | ||
| 461 | item_string = XCONS (item1)->car; | 523 | item_string = XCONS (item1)->car; |
| @@ -465,8 +527,26 @@ single_keymap_panes (keymap, pane_name, prefix) | |||
| 465 | pending_maps = Fcons (Fcons (def, Fcons (item_string, character)), | 527 | pending_maps = Fcons (Fcons (def, Fcons (item_string, character)), |
| 466 | pending_maps); | 528 | pending_maps); |
| 467 | else | 529 | else |
| 468 | push_menu_item (item_string, enabled, | 530 | { |
| 469 | character, descrip); | 531 | Lisp_Object submap; |
| 532 | submap = get_keymap_1 (def, 0, 1); | ||
| 533 | #ifndef USE_X_TOOLKIT | ||
| 534 | if (!NILP (submap)) | ||
| 535 | item_string = concat2 (item_string, | ||
| 536 | build_string (" >")); | ||
| 537 | #endif | ||
| 538 | push_menu_item (item_string, enabled, character, | ||
| 539 | descrip); | ||
| 540 | #ifdef USE_X_TOOLKIT | ||
| 541 | if (! NILP (submap)) | ||
| 542 | { | ||
| 543 | push_submenu_start (); | ||
| 544 | single_keymap_panes (submap, Qnil, | ||
| 545 | character, notreal); | ||
| 546 | push_submenu_end (); | ||
| 547 | } | ||
| 548 | #endif | ||
| 549 | } | ||
| 470 | } | 550 | } |
| 471 | } | 551 | } |
| 472 | } | 552 | } |
| @@ -476,12 +556,14 @@ single_keymap_panes (keymap, pane_name, prefix) | |||
| 476 | /* Process now any submenus which want to be panes at this level. */ | 556 | /* Process now any submenus which want to be panes at this level. */ |
| 477 | while (!NILP (pending_maps)) | 557 | while (!NILP (pending_maps)) |
| 478 | { | 558 | { |
| 479 | Lisp_Object elt, eltcdr; | 559 | Lisp_Object elt, eltcdr, string; |
| 480 | elt = Fcar (pending_maps); | 560 | elt = Fcar (pending_maps); |
| 481 | eltcdr = XCONS (elt)->cdr; | 561 | eltcdr = XCONS (elt)->cdr; |
| 482 | single_keymap_panes (Fcar (elt), | 562 | string = XCONS (eltcdr)->car; |
| 483 | /* Fails to discard the @. */ | 563 | /* We no longer discard the @ from the beginning of the string here. |
| 484 | XCONS (eltcdr)->car, XCONS (eltcdr)->cdr); | 564 | Instead, we do this in xmenu_show. */ |
| 565 | single_keymap_panes (Fcar (elt), string, | ||
| 566 | XCONS (eltcdr)->cdr, notreal); | ||
| 485 | pending_maps = Fcdr (pending_maps); | 567 | pending_maps = Fcdr (pending_maps); |
| 486 | } | 568 | } |
| 487 | } | 569 | } |
| @@ -581,10 +663,10 @@ cached information about equivalent key sequences.") | |||
| 581 | int menubarp = 0; | 663 | int menubarp = 0; |
| 582 | struct gcpro gcpro1; | 664 | struct gcpro gcpro1; |
| 583 | 665 | ||
| 584 | check_x (); | ||
| 585 | |||
| 586 | if (! NILP (position)) | 666 | if (! NILP (position)) |
| 587 | { | 667 | { |
| 668 | check_x (); | ||
| 669 | |||
| 588 | /* Decode the first argument: find the window and the coordinates. */ | 670 | /* Decode the first argument: find the window and the coordinates. */ |
| 589 | if (EQ (position, Qt)) | 671 | if (EQ (position, Qt)) |
| 590 | { | 672 | { |
| @@ -668,7 +750,7 @@ cached information about equivalent key sequences.") | |||
| 668 | keymap = get_keymap (menu); | 750 | keymap = get_keymap (menu); |
| 669 | 751 | ||
| 670 | /* Extract the detailed info to make one pane. */ | 752 | /* Extract the detailed info to make one pane. */ |
| 671 | keymap_panes (&menu, 1); | 753 | keymap_panes (&menu, 1, NILP (position)); |
| 672 | 754 | ||
| 673 | /* Search for a string appearing directly as an element of the keymap. | 755 | /* Search for a string appearing directly as an element of the keymap. |
| 674 | That string is the title of the menu. */ | 756 | That string is the title of the menu. */ |
| @@ -704,7 +786,7 @@ cached information about equivalent key sequences.") | |||
| 704 | } | 786 | } |
| 705 | 787 | ||
| 706 | /* Extract the detailed info to make one pane. */ | 788 | /* Extract the detailed info to make one pane. */ |
| 707 | keymap_panes (maps, nmaps); | 789 | keymap_panes (maps, nmaps, NILP (position)); |
| 708 | 790 | ||
| 709 | /* Make the title be the pane title of the first pane. */ | 791 | /* Make the title be the pane title of the first pane. */ |
| 710 | if (!NILP (title) && menu_items_n_panes >= 0) | 792 | if (!NILP (title) && menu_items_n_panes >= 0) |
| @@ -1123,6 +1205,11 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) | |||
| 1123 | widget_value *menubar_item = 0; | 1205 | widget_value *menubar_item = 0; |
| 1124 | 1206 | ||
| 1125 | widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; | 1207 | widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; |
| 1208 | widget_value **submenu_stack | ||
| 1209 | = (widget_value **) alloca (menu_items_used * sizeof (widget_value *)); | ||
| 1210 | Lisp_Object *subprefix_stack | ||
| 1211 | = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object)); | ||
| 1212 | int submenu_depth = 0; | ||
| 1126 | 1213 | ||
| 1127 | /* Define a queue to save up for later unreading | 1214 | /* Define a queue to save up for later unreading |
| 1128 | all X events that don't pertain to the menu. */ | 1215 | all X events that don't pertain to the menu. */ |
| @@ -1188,7 +1275,23 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) | |||
| 1188 | i = 0; | 1275 | i = 0; |
| 1189 | while (i < menu_items_used) | 1276 | while (i < menu_items_used) |
| 1190 | { | 1277 | { |
| 1191 | if (EQ (XVECTOR (menu_items)->contents[i], Qt)) | 1278 | if (EQ (XVECTOR (menu_items)->contents[i], Qnil)) |
| 1279 | { | ||
| 1280 | submenu_stack[submenu_depth++] = save_wv; | ||
| 1281 | save_wv = prev_wv; | ||
| 1282 | prev_wv = 0; | ||
| 1283 | i++; | ||
| 1284 | } | ||
| 1285 | else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda)) | ||
| 1286 | { | ||
| 1287 | prev_wv = save_wv; | ||
| 1288 | save_wv = submenu_stack[--submenu_depth]; | ||
| 1289 | i++; | ||
| 1290 | } | ||
| 1291 | else if (EQ (XVECTOR (menu_items)->contents[i], Qt) | ||
| 1292 | && submenu_depth != 0) | ||
| 1293 | i += MENU_ITEMS_PANE_LENGTH; | ||
| 1294 | else if (EQ (XVECTOR (menu_items)->contents[i], Qt)) | ||
| 1192 | { | 1295 | { |
| 1193 | /* Create a new pane. */ | 1296 | /* Create a new pane. */ |
| 1194 | Lisp_Object pane_name, prefix; | 1297 | Lisp_Object pane_name, prefix; |
| @@ -1197,7 +1300,7 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) | |||
| 1197 | prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; | 1300 | prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; |
| 1198 | pane_string = (NILP (pane_name) | 1301 | pane_string = (NILP (pane_name) |
| 1199 | ? "" : (char *) XSTRING (pane_name)->data); | 1302 | ? "" : (char *) XSTRING (pane_name)->data); |
| 1200 | /* If there is just one pane, put all its items directly | 1303 | /* If there is just one top-level pane, put all its items directly |
| 1201 | under the top-level menu. */ | 1304 | under the top-level menu. */ |
| 1202 | if (menu_items_n_panes == 1) | 1305 | if (menu_items_n_panes == 1) |
| 1203 | pane_string = ""; | 1306 | pane_string = ""; |
| @@ -1402,7 +1505,18 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) | |||
| 1402 | { | 1505 | { |
| 1403 | Lisp_Object entry; | 1506 | Lisp_Object entry; |
| 1404 | 1507 | ||
| 1405 | if (EQ (XVECTOR (menu_items)->contents[i], Qt)) | 1508 | if (EQ (XVECTOR (menu_items)->contents[i], Qnil)) |
| 1509 | { | ||
| 1510 | subprefix_stack[submenu_depth++] = prefix; | ||
| 1511 | prefix = entry; | ||
| 1512 | i++; | ||
| 1513 | } | ||
| 1514 | else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda)) | ||
| 1515 | { | ||
| 1516 | prefix = subprefix_stack[--submenu_depth]; | ||
| 1517 | i++; | ||
| 1518 | } | ||
| 1519 | else if (EQ (XVECTOR (menu_items)->contents[i], Qt)) | ||
| 1406 | { | 1520 | { |
| 1407 | prefix | 1521 | prefix |
| 1408 | = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; | 1522 | = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; |
| @@ -1416,9 +1530,13 @@ xmenu_show (f, x, y, menubarp, keymaps, title, error) | |||
| 1416 | { | 1530 | { |
| 1417 | if (keymaps != 0) | 1531 | if (keymaps != 0) |
| 1418 | { | 1532 | { |
| 1533 | int j; | ||
| 1534 | |||
| 1419 | entry = Fcons (entry, Qnil); | 1535 | entry = Fcons (entry, Qnil); |
| 1420 | if (!NILP (prefix)) | 1536 | if (!NILP (prefix)) |
| 1421 | entry = Fcons (prefix, entry); | 1537 | entry = Fcons (prefix, entry); |
| 1538 | for (j = submenu_depth - 1; j >= 0; j--) | ||
| 1539 | entry = Fcons (subprefix_stack[j], entry); | ||
| 1422 | } | 1540 | } |
| 1423 | return entry; | 1541 | return entry; |
| 1424 | } | 1542 | } |