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