Mercurial > emacs
comparison src/xmenu.c @ 50803:140fa7af01db
(struct skp): New struct, to pass args through map_keymap.
(single_keymap_panes): Use it and map_keymap.
(single_menu_item): Use skp as well.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Sun, 04 May 2003 01:27:32 +0000 |
parents | 05ebf4266798 |
children | 20b3d6c3c7e5 |
comparison
equal
deleted
inserted
replaced
50802:fe838fc4d9a9 | 50803:140fa7af01db |
---|---|
134 static Lisp_Object xmenu_show P_ ((struct frame *, int, int, int, int, | 134 static Lisp_Object xmenu_show P_ ((struct frame *, int, int, int, int, |
135 Lisp_Object, char **)); | 135 Lisp_Object, char **)); |
136 static void keymap_panes P_ ((Lisp_Object *, int, int)); | 136 static void keymap_panes P_ ((Lisp_Object *, int, int)); |
137 static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object, | 137 static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object, |
138 int, int)); | 138 int, int)); |
139 static void single_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object *, | |
140 int, int, int *)); | |
141 static void list_of_panes P_ ((Lisp_Object)); | 139 static void list_of_panes P_ ((Lisp_Object)); |
142 static void list_of_items P_ ((Lisp_Object)); | 140 static void list_of_items P_ ((Lisp_Object)); |
143 | 141 |
144 extern EMACS_TIME timer_check P_ ((int)); | 142 extern EMACS_TIME timer_check P_ ((int)); |
145 | 143 |
408 Fkeymap_prompt (keymaps[mapno]), Qnil, notreal, 10); | 406 Fkeymap_prompt (keymaps[mapno]), Qnil, notreal, 10); |
409 | 407 |
410 finish_menu_items (); | 408 finish_menu_items (); |
411 } | 409 } |
412 | 410 |
411 /* Args passed between single_keymap_panes and single_menu_item. */ | |
412 struct skp | |
413 { | |
414 Lisp_Object pending_maps; | |
415 int maxdepth, notreal; | |
416 int notbuttons; | |
417 }; | |
418 | |
419 static void single_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, | |
420 struct skp*)); | |
421 | |
413 /* This is a recursive subroutine of keymap_panes. | 422 /* This is a recursive subroutine of keymap_panes. |
414 It handles one keymap, KEYMAP. | 423 It handles one keymap, KEYMAP. |
415 The other arguments are passed along | 424 The other arguments are passed along |
416 or point to local variables of the previous function. | 425 or point to local variables of the previous function. |
417 If NOTREAL is nonzero, only check for equivalent key bindings, don't | 426 If NOTREAL is nonzero, only check for equivalent key bindings, don't |
425 Lisp_Object pane_name; | 434 Lisp_Object pane_name; |
426 Lisp_Object prefix; | 435 Lisp_Object prefix; |
427 int notreal; | 436 int notreal; |
428 int maxdepth; | 437 int maxdepth; |
429 { | 438 { |
430 Lisp_Object pending_maps = Qnil; | 439 struct skp skp; |
431 Lisp_Object tail, item; | 440 struct gcpro gcpro1; |
432 struct gcpro gcpro1, gcpro2; | 441 |
433 int notbuttons = 0; | 442 skp.pending_maps = Qnil; |
443 skp.maxdepth = maxdepth; | |
444 skp.notreal = notreal; | |
445 skp.notbuttons = 0; | |
434 | 446 |
435 if (maxdepth <= 0) | 447 if (maxdepth <= 0) |
436 return; | 448 return; |
437 | 449 |
438 push_menu_pane (pane_name, prefix); | 450 push_menu_pane (pane_name, prefix); |
440 #ifndef HAVE_BOXES | 452 #ifndef HAVE_BOXES |
441 /* Remember index for first item in this pane so we can go back and | 453 /* Remember index for first item in this pane so we can go back and |
442 add a prefix when (if) we see the first button. After that, notbuttons | 454 add a prefix when (if) we see the first button. After that, notbuttons |
443 is set to 0, to mark that we have seen a button and all non button | 455 is set to 0, to mark that we have seen a button and all non button |
444 items need a prefix. */ | 456 items need a prefix. */ |
445 notbuttons = menu_items_used; | 457 skp.notbuttons = menu_items_used; |
446 #endif | 458 #endif |
447 | 459 |
448 for (tail = keymap; CONSP (tail); tail = XCDR (tail)) | 460 GCPRO1 (skp.pending_maps); |
449 { | 461 map_keymap (keymap, single_menu_item, Qnil, &skp, 1); |
450 GCPRO2 (keymap, pending_maps); | 462 UNGCPRO; |
451 /* Look at each key binding, and if it is a menu item add it | |
452 to this menu. */ | |
453 item = XCAR (tail); | |
454 if (CONSP (item)) | |
455 single_menu_item (XCAR (item), XCDR (item), | |
456 &pending_maps, notreal, maxdepth, ¬buttons); | |
457 else if (VECTORP (item)) | |
458 { | |
459 /* Loop over the char values represented in the vector. */ | |
460 int len = XVECTOR (item)->size; | |
461 int c; | |
462 for (c = 0; c < len; c++) | |
463 { | |
464 Lisp_Object character; | |
465 XSETFASTINT (character, c); | |
466 single_menu_item (character, XVECTOR (item)->contents[c], | |
467 &pending_maps, notreal, maxdepth, ¬buttons); | |
468 } | |
469 } | |
470 UNGCPRO; | |
471 } | |
472 | 463 |
473 /* Process now any submenus which want to be panes at this level. */ | 464 /* Process now any submenus which want to be panes at this level. */ |
474 while (!NILP (pending_maps)) | 465 while (CONSP (skp.pending_maps)) |
475 { | 466 { |
476 Lisp_Object elt, eltcdr, string; | 467 Lisp_Object elt, eltcdr, string; |
477 elt = Fcar (pending_maps); | 468 elt = XCAR (skp.pending_maps); |
478 eltcdr = XCDR (elt); | 469 eltcdr = XCDR (elt); |
479 string = XCAR (eltcdr); | 470 string = XCAR (eltcdr); |
480 /* We no longer discard the @ from the beginning of the string here. | 471 /* We no longer discard the @ from the beginning of the string here. |
481 Instead, we do this in xmenu_show. */ | 472 Instead, we do this in xmenu_show. */ |
482 single_keymap_panes (Fcar (elt), string, | 473 single_keymap_panes (Fcar (elt), string, |
483 XCDR (eltcdr), notreal, maxdepth - 1); | 474 XCDR (eltcdr), notreal, maxdepth - 1); |
484 pending_maps = Fcdr (pending_maps); | 475 skp.pending_maps = XCDR (skp.pending_maps); |
485 } | 476 } |
486 } | 477 } |
487 | 478 |
488 /* This is a subroutine of single_keymap_panes that handles one | 479 /* This is a subroutine of single_keymap_panes that handles one |
489 keymap entry. | 480 keymap entry. |
490 KEY is a key in a keymap and ITEM is its binding. | 481 KEY is a key in a keymap and ITEM is its binding. |
491 PENDING_MAPS_PTR points to a list of keymaps waiting to be made into | 482 SKP->PENDING_MAPS_PTR is a list of keymaps waiting to be made into |
492 separate panes. | 483 separate panes. |
493 If NOTREAL is nonzero, only check for equivalent key bindings, don't | 484 If SKP->NOTREAL is nonzero, only check for equivalent key bindings, don't |
494 evaluate expressions in menu items and don't make any menu. | 485 evaluate expressions in menu items and don't make any menu. |
495 If we encounter submenus deeper than MAXDEPTH levels, ignore them. | 486 If we encounter submenus deeper than SKP->MAXDEPTH levels, ignore them. |
496 NOTBUTTONS_PTR is only used when simulating toggle boxes and radio | 487 SKP->NOTBUTTONS is only used when simulating toggle boxes and radio |
497 buttons. It points to variable notbuttons in single_keymap_panes, | 488 buttons. It keeps track of if we have seen a button in this menu or |
498 which keeps track of if we have seen a button in this menu or not. */ | 489 not. */ |
499 | 490 |
500 static void | 491 static void |
501 single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth, | 492 single_menu_item (key, item, dummy, skp) |
502 notbuttons_ptr) | 493 Lisp_Object key, item, dummy; |
503 Lisp_Object key, item; | 494 struct skp *skp; |
504 Lisp_Object *pending_maps_ptr; | |
505 int maxdepth, notreal; | |
506 int *notbuttons_ptr; | |
507 { | 495 { |
508 Lisp_Object map, item_string, enabled; | 496 Lisp_Object map, item_string, enabled; |
509 struct gcpro gcpro1, gcpro2; | 497 struct gcpro gcpro1, gcpro2; |
510 int res; | 498 int res; |
511 | 499 |
512 /* Parse the menu item and leave the result in item_properties. */ | 500 /* Parse the menu item and leave the result in item_properties. */ |
513 GCPRO2 (key, item); | 501 GCPRO2 (key, item); |
514 res = parse_menu_item (item, notreal, 0); | 502 res = parse_menu_item (item, skp->notreal, 0); |
515 UNGCPRO; | 503 UNGCPRO; |
516 if (!res) | 504 if (!res) |
517 return; /* Not a menu item. */ | 505 return; /* Not a menu item. */ |
518 | 506 |
519 map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP]; | 507 map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP]; |
520 | 508 |
521 if (notreal) | 509 if (skp->notreal) |
522 { | 510 { |
523 /* We don't want to make a menu, just traverse the keymaps to | 511 /* We don't want to make a menu, just traverse the keymaps to |
524 precompute equivalent key bindings. */ | 512 precompute equivalent key bindings. */ |
525 if (!NILP (map)) | 513 if (!NILP (map)) |
526 single_keymap_panes (map, Qnil, key, 1, maxdepth - 1); | 514 single_keymap_panes (map, Qnil, key, 1, skp->maxdepth - 1); |
527 return; | 515 return; |
528 } | 516 } |
529 | 517 |
530 enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE]; | 518 enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE]; |
531 item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME]; | 519 item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME]; |
532 | 520 |
533 if (!NILP (map) && SREF (item_string, 0) == '@') | 521 if (!NILP (map) && SREF (item_string, 0) == '@') |
534 { | 522 { |
535 if (!NILP (enabled)) | 523 if (!NILP (enabled)) |
536 /* An enabled separate pane. Remember this to handle it later. */ | 524 /* An enabled separate pane. Remember this to handle it later. */ |
537 *pending_maps_ptr = Fcons (Fcons (map, Fcons (item_string, key)), | 525 skp->pending_maps = Fcons (Fcons (map, Fcons (item_string, key)), |
538 *pending_maps_ptr); | 526 skp->pending_maps); |
539 return; | 527 return; |
540 } | 528 } |
541 | 529 |
542 #ifndef HAVE_BOXES | 530 #ifndef HAVE_BOXES |
543 /* Simulate radio buttons and toggle boxes by putting a prefix in | 531 /* Simulate radio buttons and toggle boxes by putting a prefix in |
548 if (!NILP (type)) | 536 if (!NILP (type)) |
549 { | 537 { |
550 Lisp_Object selected | 538 Lisp_Object selected |
551 = XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED]; | 539 = XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED]; |
552 | 540 |
553 if (*notbuttons_ptr) | 541 if (skp->notbuttons) |
554 /* The first button. Line up previous items in this menu. */ | 542 /* The first button. Line up previous items in this menu. */ |
555 { | 543 { |
556 int index = *notbuttons_ptr; /* Index for first item this menu. */ | 544 int index = skp->notbuttons; /* Index for first item this menu. */ |
557 int submenu = 0; | 545 int submenu = 0; |
558 Lisp_Object tem; | 546 Lisp_Object tem; |
559 while (index < menu_items_used) | 547 while (index < menu_items_used) |
560 { | 548 { |
561 tem | 549 tem |
581 XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME] | 569 XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME] |
582 = concat2 (build_string (" "), tem); | 570 = concat2 (build_string (" "), tem); |
583 index += MENU_ITEMS_ITEM_LENGTH; | 571 index += MENU_ITEMS_ITEM_LENGTH; |
584 } | 572 } |
585 } | 573 } |
586 *notbuttons_ptr = 0; | 574 skp->notbuttons = 0; |
587 } | 575 } |
588 | 576 |
589 /* Calculate prefix, if any, for this item. */ | 577 /* Calculate prefix, if any, for this item. */ |
590 if (EQ (type, QCtoggle)) | 578 if (EQ (type, QCtoggle)) |
591 prefix = build_string (NILP (selected) ? "[ ] " : "[X] "); | 579 prefix = build_string (NILP (selected) ? "[ ] " : "[X] "); |
592 else if (EQ (type, QCradio)) | 580 else if (EQ (type, QCradio)) |
593 prefix = build_string (NILP (selected) ? "( ) " : "(*) "); | 581 prefix = build_string (NILP (selected) ? "( ) " : "(*) "); |
594 } | 582 } |
595 /* Not a button. If we have earlier buttons, then we need a prefix. */ | 583 /* Not a button. If we have earlier buttons, then we need a prefix. */ |
596 else if (!*notbuttons_ptr && SREF (item_string, 0) != '\0' | 584 else if (!skp->notbuttons && SREF (item_string, 0) != '\0' |
597 && SREF (item_string, 0) != '-') | 585 && SREF (item_string, 0) != '-') |
598 prefix = build_string (" "); | 586 prefix = build_string (" "); |
599 | 587 |
600 if (!NILP (prefix)) | 588 if (!NILP (prefix)) |
601 item_string = concat2 (prefix, item_string); | 589 item_string = concat2 (prefix, item_string); |
618 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) | 606 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) |
619 /* Display a submenu using the toolkit. */ | 607 /* Display a submenu using the toolkit. */ |
620 if (! (NILP (map) || NILP (enabled))) | 608 if (! (NILP (map) || NILP (enabled))) |
621 { | 609 { |
622 push_submenu_start (); | 610 push_submenu_start (); |
623 single_keymap_panes (map, Qnil, key, 0, maxdepth - 1); | 611 single_keymap_panes (map, Qnil, key, 0, skp->maxdepth - 1); |
624 push_submenu_end (); | 612 push_submenu_end (); |
625 } | 613 } |
626 #endif | 614 #endif |
627 } | 615 } |
628 | 616 |