Mercurial > emacs
comparison src/xmenu.c @ 2747:f258c79c9162
(Fx_popup_menu): Add a vector of prefix keys for the panes.
(keymap_panes): Allocate that vector.
(single_keymap_panes): Fill in that vector.
(xmenu_show): Return a list of events, not just one event.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Wed, 12 May 1993 05:17:47 +0000 |
parents | 6700e25af205 |
children | e94a593c3952 |
comparison
equal
deleted
inserted
replaced
2746:e4595f258ddd | 2747:f258c79c9162 |
---|---|
98 The menu items come from key bindings that have a menu string as well as\n\ | 98 The menu items come from key bindings that have a menu string as well as\n\ |
99 a definition; actually, the \"definition\" in such a key binding looks like\n\ | 99 a definition; actually, the \"definition\" in such a key binding looks like\n\ |
100 \(STRING . REAL-DEFINITION). To give the menu a title, put a string into\n\ | 100 \(STRING . REAL-DEFINITION). To give the menu a title, put a string into\n\ |
101 the keymap as a top-level element.\n\n\ | 101 the keymap as a top-level element.\n\n\ |
102 You can also use a list of keymaps as MENU.\n\ | 102 You can also use a list of keymaps as MENU.\n\ |
103 Then each keymap makes a separate pane.\n\n\ | 103 Then each keymap makes a separate pane.\n\ |
104 When MENU is a keymap or a list of keymaps, the return value\n\ | |
105 is a list of events.\n\n\ | |
104 Alternatively, you can specify a menu of multiple panes\n\ | 106 Alternatively, you can specify a menu of multiple panes\n\ |
105 with a list of the form (TITLE PANE1 PANE2...),\n\ | 107 with a list of the form (TITLE PANE1 PANE2...),\n\ |
106 where each pane is a list of form (TITLE ITEM1 ITEM2...).\n\ | 108 where each pane is a list of form (TITLE ITEM1 ITEM2...).\n\ |
107 Each ITEM is normally a cons cell (STRING . VALUE);\n\ | 109 Each ITEM is normally a cons cell (STRING . VALUE);\n\ |
108 but a string can appear as an item--that makes a nonselectable line\n\ | 110 but a string can appear as an item--that makes a nonselectable line\n\ |
109 in the menu.") | 111 in the menu.\n\ |
112 With this form of menu, the return value is VALUE from the chosen item.") | |
110 (position, menu) | 113 (position, menu) |
111 Lisp_Object position, menu; | 114 Lisp_Object position, menu; |
112 { | 115 { |
113 int number_of_panes; | 116 int number_of_panes; |
114 Lisp_Object XMenu_return, keymap, tem; | 117 Lisp_Object XMenu_return, keymap, tem; |
115 int XMenu_xpos, XMenu_ypos; | 118 int XMenu_xpos, XMenu_ypos; |
116 char **menus; | 119 char **menus; |
117 char ***names; | 120 char ***names; |
118 int **enables; | 121 int **enables; |
119 Lisp_Object **obj_list; | 122 Lisp_Object **obj_list; |
123 Lisp_Object *prefixes; | |
120 int *items; | 124 int *items; |
121 char *title; | 125 char *title; |
122 char *error_name; | 126 char *error_name; |
123 Lisp_Object ltitle, selection; | 127 Lisp_Object ltitle, selection; |
124 int i, j; | 128 int i, j; |
211 title = (char *) XSTRING (prompt)->data; | 215 title = (char *) XSTRING (prompt)->data; |
212 } | 216 } |
213 | 217 |
214 /* Extract the detailed info to make one pane. */ | 218 /* Extract the detailed info to make one pane. */ |
215 number_of_panes = keymap_panes (&obj_list, &menus, &names, &enables, | 219 number_of_panes = keymap_panes (&obj_list, &menus, &names, &enables, |
216 &items, maps, nmaps); | 220 &items, &prefixes, maps, nmaps); |
217 /* The menu title seems to be ignored, | 221 /* The menu title seems to be ignored, |
218 so put it in the pane title. */ | 222 so put it in the pane title. */ |
219 if (menus[0] == 0) | 223 if (menus[0] == 0) |
220 menus[0] = title; | 224 menus[0] = title; |
221 } | 225 } |
223 { | 227 { |
224 /* We were given an old-fashioned menu. */ | 228 /* We were given an old-fashioned menu. */ |
225 ltitle = Fcar (menu); | 229 ltitle = Fcar (menu); |
226 CHECK_STRING (ltitle, 1); | 230 CHECK_STRING (ltitle, 1); |
227 title = (char *) XSTRING (ltitle)->data; | 231 title = (char *) XSTRING (ltitle)->data; |
232 prefixes = 0; | |
228 number_of_panes = list_of_panes (&obj_list, &menus, &names, &enables, | 233 number_of_panes = list_of_panes (&obj_list, &menus, &names, &enables, |
229 &items, Fcdr (menu)); | 234 &items, Fcdr (menu)); |
230 } | 235 } |
231 #ifdef XDEBUG | 236 #ifdef XDEBUG |
232 fprintf (stderr, "Panes = %d\n", number_of_panes); | 237 fprintf (stderr, "Panes = %d\n", number_of_panes); |
259 &dummy_window)) | 264 &dummy_window)) |
260 /* But XGetGeometry said root was the root window of f's screen! */ | 265 /* But XGetGeometry said root was the root window of f's screen! */ |
261 abort (); | 266 abort (); |
262 | 267 |
263 selection = xmenu_show (root, XMenu_xpos, XMenu_ypos, names, enables, | 268 selection = xmenu_show (root, XMenu_xpos, XMenu_ypos, names, enables, |
264 menus, items, number_of_panes, obj_list, title, | 269 menus, prefixes, items, number_of_panes, obj_list, |
265 &error_name); | 270 title, &error_name); |
266 } | 271 } |
267 UNBLOCK_INPUT; | 272 UNBLOCK_INPUT; |
268 /* fprintf (stderr, "selection = %x\n", selection); */ | 273 /* fprintf (stderr, "selection = %x\n", selection); */ |
269 if (selection != NUL) | 274 if (selection != NUL) |
270 { /* selected something */ | 275 { /* selected something */ |
296 int line; | 301 int line; |
297 }; | 302 }; |
298 | 303 |
299 Lisp_Object | 304 Lisp_Object |
300 xmenu_show (parent, startx, starty, line_list, enable_list, pane_list, | 305 xmenu_show (parent, startx, starty, line_list, enable_list, pane_list, |
301 line_cnt, pane_cnt, item_list, title, error) | 306 prefixes, line_cnt, pane_cnt, item_list, title, error) |
302 Window parent; | 307 Window parent; |
303 int startx, starty; /* upper left corner position BROKEN */ | 308 int startx, starty; /* upper left corner position BROKEN */ |
304 char **line_list[]; /* list of strings for items */ | 309 char **line_list[]; /* list of strings for items */ |
305 int *enable_list[]; /* list of strings for items */ | 310 int *enable_list[]; /* list of strings for items */ |
306 char *pane_list[]; /* list of pane titles */ | 311 char *pane_list[]; /* list of pane titles */ |
312 Lisp_Object *prefixes; /* Prefix key for each pane */ | |
307 char *title; | 313 char *title; |
308 int pane_cnt; /* total number of panes */ | 314 int pane_cnt; /* total number of panes */ |
309 Lisp_Object *item_list[]; /* All items */ | 315 Lisp_Object *item_list[]; /* All items */ |
310 int line_cnt[]; /* Lines in each pane */ | 316 int line_cnt[]; /* Lines in each pane */ |
311 char **error; /* Error returned */ | 317 char **error; /* Error returned */ |
403 case XM_SUCCESS: | 409 case XM_SUCCESS: |
404 #ifdef XDEBUG | 410 #ifdef XDEBUG |
405 fprintf (stderr, "pane= %d line = %d\n", panes, selidx); | 411 fprintf (stderr, "pane= %d line = %d\n", panes, selidx); |
406 #endif | 412 #endif |
407 entry = item_list[panes][selidx]; | 413 entry = item_list[panes][selidx]; |
414 if (prefixes != 0) | |
415 { | |
416 entry = Fcons (entry, Qnil); | |
417 if (!NILP (prefixes[panes])) | |
418 entry = Fcons (prefixes[panes], entry); | |
419 } | |
408 break; | 420 break; |
409 case XM_FAILURE: | 421 case XM_FAILURE: |
410 /* free (datap_save); */ | 422 /* free (datap_save); */ |
411 XMenuDestroy (XDISPLAY GXMenu); | 423 XMenuDestroy (XDISPLAY GXMenu); |
412 *error = "Can't activate menu"; | 424 *error = "Can't activate menu"; |
433 Return the number of panes. | 445 Return the number of panes. |
434 | 446 |
435 KEYMAPS is a vector of keymaps. NMAPS gives the length of KEYMAPS. */ | 447 KEYMAPS is a vector of keymaps. NMAPS gives the length of KEYMAPS. */ |
436 | 448 |
437 int | 449 int |
438 keymap_panes (vector, panes, names, enables, items, keymaps, nmaps) | 450 keymap_panes (vector, panes, names, enables, items, prefixes, keymaps, nmaps) |
439 Lisp_Object ***vector; /* RETURN all menu objects */ | 451 Lisp_Object ***vector; /* RETURN all menu objects */ |
440 char ***panes; /* RETURN pane names */ | 452 char ***panes; /* RETURN pane names */ |
441 char ****names; /* RETURN all line names */ | 453 char ****names; /* RETURN all line names */ |
442 int ***enables; /* RETURN enable-flags of lines */ | 454 int ***enables; /* RETURN enable-flags of lines */ |
443 int **items; /* RETURN number of items per pane */ | 455 int **items; /* RETURN number of items per pane */ |
456 Lisp_Object **prefixes; /* RETURN vector of prefix keys, per pane */ | |
444 Lisp_Object *keymaps; | 457 Lisp_Object *keymaps; |
445 int nmaps; | 458 int nmaps; |
446 { | 459 { |
447 /* Number of panes we have made. */ | 460 /* Number of panes we have made. */ |
448 int p = 0; | 461 int p = 0; |
457 *vector = (Lisp_Object **) xmalloc (npanes_allocated * sizeof (Lisp_Object *)); | 470 *vector = (Lisp_Object **) xmalloc (npanes_allocated * sizeof (Lisp_Object *)); |
458 *panes = (char **) xmalloc (npanes_allocated * sizeof (char *)); | 471 *panes = (char **) xmalloc (npanes_allocated * sizeof (char *)); |
459 *items = (int *) xmalloc (npanes_allocated * sizeof (int)); | 472 *items = (int *) xmalloc (npanes_allocated * sizeof (int)); |
460 *names = (char ***) xmalloc (npanes_allocated * sizeof (char **)); | 473 *names = (char ***) xmalloc (npanes_allocated * sizeof (char **)); |
461 *enables = (int **) xmalloc (npanes_allocated * sizeof (int *)); | 474 *enables = (int **) xmalloc (npanes_allocated * sizeof (int *)); |
475 *prefixes = (Lisp_Object *) xmalloc (npanes_allocated * sizeof (Lisp_Object)); | |
462 | 476 |
463 /* Loop over the given keymaps, making a pane for each map. | 477 /* Loop over the given keymaps, making a pane for each map. |
464 But don't make a pane that is empty--ignore that map instead. | 478 But don't make a pane that is empty--ignore that map instead. |
465 P is the number of panes we have made so far. */ | 479 P is the number of panes we have made so far. */ |
466 for (mapno = 0; mapno < nmaps; mapno++) | 480 for (mapno = 0; mapno < nmaps; mapno++) |
467 single_keymap_panes (keymaps[mapno], panes, vector, names, enables, items, | 481 single_keymap_panes (keymaps[mapno], panes, vector, names, enables, items, |
468 &p, &npanes_allocated, ""); | 482 prefixes, &p, &npanes_allocated, ""); |
469 | 483 |
470 /* Return the number of panes. */ | 484 /* Return the number of panes. */ |
471 return p; | 485 return p; |
472 } | 486 } |
473 | 487 |
474 /* This is a recursive subroutine of the previous function. | 488 /* This is a recursive subroutine of the previous function. |
475 It handles one keymap, KEYMAP. | 489 It handles one keymap, KEYMAP. |
476 The other arguments are passed along | 490 The other arguments are passed along |
477 or point to local variables of the previous function. */ | 491 or point to local variables of the previous function. */ |
478 | 492 |
479 single_keymap_panes (keymap, panes, vector, names, enables, items, | 493 single_keymap_panes (keymap, panes, vector, names, enables, items, prefixes, |
480 p_ptr, npanes_allocated_ptr, pane_name) | 494 p_ptr, npanes_allocated_ptr, pane_name) |
481 Lisp_Object keymap; | 495 Lisp_Object keymap; |
482 Lisp_Object ***vector; /* RETURN all menu objects */ | 496 Lisp_Object ***vector; /* RETURN all menu objects */ |
483 char ***panes; /* RETURN pane names */ | 497 char ***panes; /* RETURN pane names */ |
484 char ****names; /* RETURN all line names */ | 498 char ****names; /* RETURN all line names */ |
485 int ***enables; /* RETURN enable flags of lines */ | 499 int ***enables; /* RETURN enable flags of lines */ |
486 int **items; /* RETURN number of items per pane */ | 500 int **items; /* RETURN number of items per pane */ |
501 Lisp_Object **prefixes; /* RETURN vector of prefix keys, per pane */ | |
487 int *p_ptr; | 502 int *p_ptr; |
488 int *npanes_allocated_ptr; | 503 int *npanes_allocated_ptr; |
489 char *pane_name; | 504 char *pane_name; |
490 { | 505 { |
491 int i; | 506 int i; |
506 = (char **) xrealloc (*panes, | 521 = (char **) xrealloc (*panes, |
507 *npanes_allocated_ptr * sizeof (char *)); | 522 *npanes_allocated_ptr * sizeof (char *)); |
508 *items | 523 *items |
509 = (int *) xrealloc (*items, | 524 = (int *) xrealloc (*items, |
510 *npanes_allocated_ptr * sizeof (int)); | 525 *npanes_allocated_ptr * sizeof (int)); |
526 *prefixes | |
527 = (Lisp_Object *) xrealloc (*prefixes, | |
528 (*npanes_allocated_ptr | |
529 * sizeof (Lisp_Object))); | |
511 *names | 530 *names |
512 = (char ***) xrealloc (*names, | 531 = (char ***) xrealloc (*names, |
513 *npanes_allocated_ptr * sizeof (char **)); | 532 *npanes_allocated_ptr * sizeof (char **)); |
514 *enables | 533 *enables |
515 = (int **) xrealloc (*enables, | 534 = (int **) xrealloc (*enables, |
516 *npanes_allocated_ptr * sizeof (int *)); | 535 *npanes_allocated_ptr * sizeof (int *)); |
517 } | 536 } |
518 | 537 |
519 /* When a menu comes from keymaps, don't give names to the panes. */ | 538 /* When a menu comes from keymaps, don't give names to the panes. */ |
520 (*panes)[*p_ptr] = pane_name; | 539 (*panes)[*p_ptr] = pane_name; |
540 | |
541 /* Normally put nil as pane's prefix key. | |
542 Caller will override this if appropriate. */ | |
543 (*prefixes)[*p_ptr] = Qnil; | |
521 | 544 |
522 /* Get the length of the list level of the keymap. */ | 545 /* Get the length of the list level of the keymap. */ |
523 i = XFASTINT (Flength (keymap)); | 546 i = XFASTINT (Flength (keymap)); |
524 | 547 |
525 /* Add in lengths of any arrays. */ | 548 /* Add in lengths of any arrays. */ |
561 if (!NILP (tem)) | 584 if (!NILP (tem)) |
562 enabled = Feval (tem); | 585 enabled = Feval (tem); |
563 } | 586 } |
564 tem = Fkeymapp (def); | 587 tem = Fkeymapp (def); |
565 if (XSTRING (item2)->data[0] == '@' && !NILP (tem)) | 588 if (XSTRING (item2)->data[0] == '@' && !NILP (tem)) |
566 pending_maps = Fcons (Fcons (def, item2), | 589 pending_maps = Fcons (Fcons (def, Fcons (item2, XCONS (item)->car)), |
567 pending_maps); | 590 pending_maps); |
568 else | 591 else |
569 { | 592 { |
570 (*names)[*p_ptr][i] = (char *) XSTRING (item2)->data; | 593 (*names)[*p_ptr][i] = (char *) XSTRING (item2)->data; |
571 /* The menu item "value" is the key bound here. */ | 594 /* The menu item "value" is the key bound here. */ |
607 enabled = Feval (tem); | 630 enabled = Feval (tem); |
608 } | 631 } |
609 | 632 |
610 tem = Fkeymapp (def); | 633 tem = Fkeymapp (def); |
611 if (XSTRING (item2)->data[0] == '@' && !NILP (tem)) | 634 if (XSTRING (item2)->data[0] == '@' && !NILP (tem)) |
612 pending_maps = Fcons (Fcons (def, item2), | 635 pending_maps = Fcons (Fcons (def, Fcons (item2, character)), |
613 pending_maps); | 636 pending_maps); |
614 else | 637 else |
615 { | 638 { |
616 (*names)[*p_ptr][i] = (char *) XSTRING (item2)->data; | 639 (*names)[*p_ptr][i] = (char *) XSTRING (item2)->data; |
617 /* The menu item "value" is the key bound here. */ | 640 /* The menu item "value" is the key bound here. */ |
640 (*p_ptr)++; | 663 (*p_ptr)++; |
641 | 664 |
642 /* Process now any submenus which want to be panes at this level. */ | 665 /* Process now any submenus which want to be panes at this level. */ |
643 while (!NILP (pending_maps)) | 666 while (!NILP (pending_maps)) |
644 { | 667 { |
645 Lisp_Object elt; | 668 Lisp_Object elt, eltcdr; |
669 int panenum = *p_ptr; | |
646 elt = Fcar (pending_maps); | 670 elt = Fcar (pending_maps); |
671 eltcdr = XCONS (elt)->cdr; | |
647 single_keymap_panes (Fcar (elt), panes, vector, names, enables, items, | 672 single_keymap_panes (Fcar (elt), panes, vector, names, enables, items, |
648 p_ptr, npanes_allocated_ptr, | 673 prefixes, p_ptr, npanes_allocated_ptr, |
649 /* Add 1 to discard the @. */ | 674 /* Add 1 to discard the @. */ |
650 (char *) XSTRING (XCONS (elt)->cdr)->data + 1); | 675 (char *) XSTRING (XCONS (eltcdr)->car)->data + 1); |
676 (*prefixes)[panenum] = XCONS (eltcdr)->cdr; | |
651 pending_maps = Fcdr (pending_maps); | 677 pending_maps = Fcdr (pending_maps); |
652 } | 678 } |
653 } | 679 } |
654 | 680 |
655 /* Construct the vectors that describe a menu | 681 /* Construct the vectors that describe a menu |