Mercurial > emacs
comparison src/xmenu.c @ 6291:38ec8e76594f
(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.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Thu, 10 Mar 1994 17:03:21 +0000 |
parents | 01c57ae8ca57 |
children | 1f9fa4022502 |
comparison
equal
deleted
inserted
replaced
6290:6ecf8ea4bd8d | 6291:38ec8e76594f |
---|---|
111 t, the pane name, the pane's prefix key. | 111 t, the pane name, the pane's prefix key. |
112 Then follow the pane's items, with 4 elements per item: | 112 Then follow the pane's items, with 4 elements per item: |
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 |
119 #define MENU_ITEMS_PANE_NAME 1 | 124 #define MENU_ITEMS_PANE_NAME 1 |
120 #define MENU_ITEMS_PANE_PREFIX 2 | 125 #define MENU_ITEMS_PANE_PREFIX 2 |
132 static int menu_items_allocated; | 137 static int menu_items_allocated; |
133 | 138 |
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; |
145 | |
146 /* Current depth within submenus. */ | |
147 static int menu_items_submenu_depth; | |
139 | 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 |
143 static void | 152 static void |
149 menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil); | 158 menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil); |
150 } | 159 } |
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. |
157 This fills in the number of items in the last pane. */ | 167 This fills in the number of items in the last pane. */ |
158 | 168 |
174 menu_items = Qnil; | 184 menu_items = Qnil; |
175 menu_items_allocated = 0; | 185 menu_items_allocated = 0; |
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 |
182 static void | 231 static void |
183 push_menu_pane (name, prefix_vec) | 232 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; | 237 |
189 int old_size = menu_items_allocated; | 238 if (menu_items_submenu_depth == 0) |
190 old = menu_items; | 239 menu_items_n_panes++; |
191 | |
192 menu_items_allocated *= 2; | |
193 menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil); | |
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; |
202 } | 243 } |
203 | 244 |
210 static void | 251 static void |
211 push_menu_item (name, enable, key, equiv) | 252 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; |
228 XVECTOR (menu_items)->contents[menu_items_used++] = key; | 260 XVECTOR (menu_items)->contents[menu_items_used++] = key; |
229 XVECTOR (menu_items)->contents[menu_items_used++] = equiv; | 261 XVECTOR (menu_items)->contents[menu_items_used++] = equiv; |
317 { | 349 { |
318 return Qnil; | 350 return Qnil; |
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. |
334 Otherwise, enable if value is not nil. */ | 369 Otherwise, enable if value is not nil. */ |
335 tem = Fget (def, Qmenu_enable); | 370 tem = Fget (def, Qmenu_enable); |
341 } | 376 } |
342 return enabled; | 377 return enabled; |
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 |
355 init_menu_items (); | 393 init_menu_items (); |
356 | 394 |
357 /* Loop over the given keymaps, making a pane for each map. | 395 /* Loop over the given keymaps, making a pane for each map. |
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 } |
365 | 403 |
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; |
379 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 420 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
380 | 421 |
408 Protecting KEYMAP preserves everything we use; | 449 Protecting KEYMAP preserves everything we use; |
409 aside from that, must protect whatever might be | 450 aside from that, must protect whatever might be |
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; |
417 | 459 |
418 tem = Fkeymapp (def); | 460 tem = Fkeymapp (def); |
419 if (XSTRING (item_string)->data[0] == '@' && !NILP (tem)) | 461 if (XSTRING (item_string)->data[0] == '@' && !NILP (tem)) |
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 } |
428 else if (XTYPE (item) == Lisp_Vector) | 490 else if (XTYPE (item) == Lisp_Vector) |
429 { | 491 { |
453 Protecting KEYMAP preserves everything we use; | 515 Protecting KEYMAP preserves everything we use; |
454 aside from that, must protect whatever might be | 516 aside from that, must protect whatever might be |
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; |
462 | 524 |
463 tem = Fkeymapp (def); | 525 tem = Fkeymapp (def); |
464 if (XSTRING (item_string)->data[0] == '@' && !NILP (tem)) | 526 if (XSTRING (item_string)->data[0] == '@' && !NILP (tem)) |
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 } |
473 } | 553 } |
474 } | 554 } |
475 | 555 |
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 } |
488 | 570 |
489 /* Push all the panes and items of a menu decsribed by the | 571 /* Push all the panes and items of a menu decsribed by the |
579 Lisp_Object x, y, window; | 661 Lisp_Object x, y, window; |
580 int keymaps = 0; | 662 int keymaps = 0; |
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 { |
591 /* Use the mouse's current position. */ | 673 /* Use the mouse's current position. */ |
592 FRAME_PTR new_f; | 674 FRAME_PTR new_f; |
666 /* We were given a keymap. Extract menu info from the keymap. */ | 748 /* We were given a keymap. Extract menu info from the keymap. */ |
667 Lisp_Object prompt; | 749 Lisp_Object prompt; |
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. */ |
675 prompt = map_prompt (keymap); | 757 prompt = map_prompt (keymap); |
676 | 758 |
702 if (NILP (title) && !NILP (prompt)) | 784 if (NILP (title) && !NILP (prompt)) |
703 title = prompt; | 785 title = prompt; |
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) |
711 XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = title; | 793 XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = title; |
712 | 794 |
1121 | 1203 |
1122 /* This is the menu bar item (if any) that led to this menu. */ | 1204 /* This is the menu bar item (if any) that led to this menu. */ |
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. */ |
1129 struct event_queue | 1216 struct event_queue |
1130 { | 1217 { |
1186 | 1273 |
1187 /* Loop over all panes and items, filling in the tree. */ | 1274 /* Loop over all panes and items, filling in the tree. */ |
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; |
1195 char *pane_string; | 1298 char *pane_string; |
1196 pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME]; | 1299 pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME]; |
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 = ""; |
1204 | 1307 |
1205 /* If the pane has a meaningful name, | 1308 /* If the pane has a meaningful name, |
1400 i = 0; | 1503 i = 0; |
1401 while (i < menu_items_used) | 1504 while (i < menu_items_used) |
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]; |
1409 i += MENU_ITEMS_PANE_LENGTH; | 1523 i += MENU_ITEMS_PANE_LENGTH; |
1410 } | 1524 } |
1414 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE]; | 1528 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE]; |
1415 if (menu_item_selection == &XVECTOR (menu_items)->contents[i]) | 1529 if (menu_item_selection == &XVECTOR (menu_items)->contents[i]) |
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 } |
1425 i += MENU_ITEMS_ITEM_LENGTH; | 1543 i += MENU_ITEMS_ITEM_LENGTH; |
1426 } | 1544 } |