comparison src/keyboard.c @ 46343:fb71432c8a02

(command_loop_1): Invert check on Vmemory_full.
author Kim F. Storm <storm@cua.dk>
date Fri, 12 Jul 2002 23:47:31 +0000
parents 06bf5ed360fd
children 0b55cf135919
comparison
equal deleted inserted replaced
46342:744d34a040d3 46343:fb71432c8a02
658 658
659 /* If non-nil, always disable point adjustment. */ 659 /* If non-nil, always disable point adjustment. */
660 660
661 Lisp_Object Vglobal_disable_point_adjustment; 661 Lisp_Object Vglobal_disable_point_adjustment;
662 662
663 /* A function to display keyboard-menus, and read the user's response.
664 If nil, keyboard menus are disabled. */
665
666 Lisp_Object Vkey_menu_prompt_function;
667
663 /* The time when Emacs started being idle. */ 668 /* The time when Emacs started being idle. */
664 669
665 static EMACS_TIME timer_idleness_start_time; 670 static EMACS_TIME timer_idleness_start_time;
666 671
667 /* After Emacs stops being idle, this saves the last value 672 /* After Emacs stops being idle, this saves the last value
1357 1362
1358 nonundocount = 0; 1363 nonundocount = 0;
1359 this_command_key_count = 0; 1364 this_command_key_count = 0;
1360 this_single_command_key_start = 0; 1365 this_single_command_key_start = 0;
1361 1366
1362 if (! NILP (Vmemory_full)) 1367 if (NILP (Vmemory_full))
1363 { 1368 {
1364 /* Make sure this hook runs after commands that get errors and 1369 /* Make sure this hook runs after commands that get errors and
1365 throw to top level. */ 1370 throw to top level. */
1366 /* Note that the value cell will never directly contain nil 1371 /* Note that the value cell will never directly contain nil
1367 if the symbol is a local variable. */ 1372 if the symbol is a local variable. */
7664 } 7669 }
7665 #endif /* HAVE_MENUS */ 7670 #endif /* HAVE_MENUS */
7666 return Qnil ; 7671 return Qnil ;
7667 } 7672 }
7668 7673
7669 /* Buffer in use so far for the minibuf prompts for menu keymaps.
7670 We make this bigger when necessary, and never free it. */
7671 static char *read_char_minibuf_menu_text;
7672 /* Size of that buffer. */
7673 static int read_char_minibuf_menu_width;
7674
7675 static Lisp_Object 7674 static Lisp_Object
7676 read_char_minibuf_menu_prompt (commandflag, nmaps, maps) 7675 read_char_minibuf_menu_prompt (commandflag, nmaps, maps)
7677 int commandflag ; 7676 int commandflag ;
7678 int nmaps; 7677 int nmaps;
7679 Lisp_Object *maps; 7678 Lisp_Object *maps;
7680 { 7679 {
7681 int mapno; 7680 int mapno;
7682 register Lisp_Object name; 7681 register Lisp_Object name;
7683 int nlength;
7684 int width = FRAME_WIDTH (SELECTED_FRAME ()) - 4;
7685 int idx = -1; 7682 int idx = -1;
7686 int nobindings = 1;
7687 Lisp_Object rest, vector; 7683 Lisp_Object rest, vector;
7688 char *menu; 7684 /* This is a list of the prompt and individual menu entries passed to
7685 lisp for formatting and display. The format is:
7686 MENU_LIST : (MENU_PROMPT ENTRY...)
7687 ENTRY : (EVENT PROMPT [BINDING [TOGGLE_TYPE TOGGLE_STATE]]) */
7688 Lisp_Object menu_list = Qnil;
7689 7689
7690 vector = Qnil; 7690 vector = Qnil;
7691 name = Qnil; 7691 name = Qnil;
7692 7692
7693 if (! menu_prompting) 7693 if (! menu_prompting)
7694 return Qnil; 7694 return Qnil;
7695
7696 /* Make sure we have a big enough buffer for the menu text. */
7697 if (read_char_minibuf_menu_text == 0)
7698 {
7699 read_char_minibuf_menu_width = width + 4;
7700 read_char_minibuf_menu_text = (char *) xmalloc (width + 4);
7701 }
7702 else if (width + 4 > read_char_minibuf_menu_width)
7703 {
7704 read_char_minibuf_menu_width = width + 4;
7705 read_char_minibuf_menu_text
7706 = (char *) xrealloc (read_char_minibuf_menu_text, width + 4);
7707 }
7708 menu = read_char_minibuf_menu_text;
7709 7695
7710 /* Get the menu name from the first map that has one (a prompt string). */ 7696 /* Get the menu name from the first map that has one (a prompt string). */
7711 for (mapno = 0; mapno < nmaps; mapno++) 7697 for (mapno = 0; mapno < nmaps; mapno++)
7712 { 7698 {
7713 name = Fkeymap_prompt (maps[mapno]); 7699 name = Fkeymap_prompt (maps[mapno]);
7717 7703
7718 /* If we don't have any menus, just read a character normally. */ 7704 /* If we don't have any menus, just read a character normally. */
7719 if (!STRINGP (name)) 7705 if (!STRINGP (name))
7720 return Qnil; 7706 return Qnil;
7721 7707
7722 /* Prompt string always starts with map's prompt, and a space. */
7723 strcpy (menu, XSTRING (name)->data);
7724 nlength = STRING_BYTES (XSTRING (name));
7725 menu[nlength++] = ':';
7726 menu[nlength++] = ' ';
7727 menu[nlength] = 0;
7728
7729 /* Start prompting at start of first map. */ 7708 /* Start prompting at start of first map. */
7730 mapno = 0; 7709 mapno = 0;
7731 rest = maps[mapno]; 7710 rest = maps[mapno];
7732 7711
7733 /* Present the documented bindings, a line at a time. */ 7712 /* Loop over elements of map. */
7734 while (1) 7713 for (;;)
7735 { 7714 {
7736 int notfirst = 0; 7715 Lisp_Object elt;
7737 int i = nlength; 7716
7738 Lisp_Object obj; 7717 /* If reached end of map, start at beginning of next map. */
7739 int ch; 7718 if (NILP (rest))
7740 Lisp_Object orig_defn_macro; 7719 {
7741 7720 mapno++;
7742 /* Loop over elements of map. */ 7721 if (mapno == nmaps)
7743 while (i < width) 7722 /* Done with all maps. */
7744 { 7723 break;
7745 Lisp_Object elt; 7724 rest = maps[mapno];
7746 7725 }
7747 /* If reached end of map, start at beginning of next map. */ 7726
7748 if (NILP (rest)) 7727 /* Look at the next element of the map. */
7728 if (idx >= 0)
7729 elt = AREF (vector, idx);
7730 else
7731 elt = Fcar_safe (rest);
7732
7733 if (idx < 0 && VECTORP (elt))
7734 {
7735 /* If we found a dense table in the keymap,
7736 advanced past it, but start scanning its contents. */
7737 rest = Fcdr_safe (rest);
7738 vector = elt;
7739 idx = 0;
7740 }
7741 else
7742 {
7743 /* An ordinary element. */
7744 Lisp_Object event, tem;
7745
7746 if (idx < 0)
7749 { 7747 {
7750 mapno++; 7748 event = Fcar_safe (elt); /* alist */
7751 /* At end of last map, wrap around to first map if just starting, 7749 elt = Fcdr_safe (elt);
7752 or end this line if already have something on it. */
7753 if (mapno == nmaps)
7754 {
7755 mapno = 0;
7756 if (notfirst || nobindings) break;
7757 }
7758 rest = maps[mapno];
7759 }
7760
7761 /* Look at the next element of the map. */
7762 if (idx >= 0)
7763 elt = XVECTOR (vector)->contents[idx];
7764 else
7765 elt = Fcar_safe (rest);
7766
7767 if (idx < 0 && VECTORP (elt))
7768 {
7769 /* If we found a dense table in the keymap,
7770 advanced past it, but start scanning its contents. */
7771 rest = Fcdr_safe (rest);
7772 vector = elt;
7773 idx = 0;
7774 } 7750 }
7775 else 7751 else
7776 { 7752 {
7777 /* An ordinary element. */ 7753 XSETINT (event, idx); /* vector */
7778 Lisp_Object event, tem;
7779
7780 if (idx < 0)
7781 {
7782 event = Fcar_safe (elt); /* alist */
7783 elt = Fcdr_safe (elt);
7784 }
7785 else
7786 {
7787 XSETINT (event, idx); /* vector */
7788 }
7789
7790 /* Ignore the element if it has no prompt string. */
7791 if (INTEGERP (event) && parse_menu_item (elt, 0, -1))
7792 {
7793 /* 1 if the char to type matches the string. */
7794 int char_matches;
7795 Lisp_Object upcased_event, downcased_event;
7796 Lisp_Object desc = Qnil;
7797 Lisp_Object s
7798 = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];
7799
7800 upcased_event = Fupcase (event);
7801 downcased_event = Fdowncase (event);
7802 char_matches = (XINT (upcased_event) == XSTRING (s)->data[0]
7803 || XINT (downcased_event) == XSTRING (s)->data[0]);
7804 if (! char_matches)
7805 desc = Fsingle_key_description (event, Qnil);
7806
7807 #if 0 /* It is redundant to list the equivalent key bindings because
7808 the prefix is what the user has already typed. */
7809 tem
7810 = XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ];
7811 if (!NILP (tem))
7812 /* Insert equivalent keybinding. */
7813 s = concat2 (s, tem);
7814 #endif
7815 tem
7816 = XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE];
7817 if (EQ (tem, QCradio) || EQ (tem, QCtoggle))
7818 {
7819 /* Insert button prefix. */
7820 Lisp_Object selected
7821 = XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED];
7822 if (EQ (tem, QCradio))
7823 tem = build_string (NILP (selected) ? "(*) " : "( ) ");
7824 else
7825 tem = build_string (NILP (selected) ? "[X] " : "[ ] ");
7826 s = concat2 (tem, s);
7827 }
7828
7829
7830 /* If we have room for the prompt string, add it to this line.
7831 If this is the first on the line, always add it. */
7832 if ((XSTRING (s)->size + i + 2
7833 + (char_matches ? 0 : XSTRING (desc)->size + 3))
7834 < width
7835 || !notfirst)
7836 {
7837 int thiswidth;
7838
7839 /* Punctuate between strings. */
7840 if (notfirst)
7841 {
7842 strcpy (menu + i, ", ");
7843 i += 2;
7844 }
7845 notfirst = 1;
7846 nobindings = 0 ;
7847
7848 /* If the char to type doesn't match the string's
7849 first char, explicitly show what char to type. */
7850 if (! char_matches)
7851 {
7852 /* Add as much of string as fits. */
7853 thiswidth = XSTRING (desc)->size;
7854 if (thiswidth + i > width)
7855 thiswidth = width - i;
7856 bcopy (XSTRING (desc)->data, menu + i, thiswidth);
7857 i += thiswidth;
7858 strcpy (menu + i, " = ");
7859 i += 3;
7860 }
7861
7862 /* Add as much of string as fits. */
7863 thiswidth = XSTRING (s)->size;
7864 if (thiswidth + i > width)
7865 thiswidth = width - i;
7866 bcopy (XSTRING (s)->data, menu + i, thiswidth);
7867 i += thiswidth;
7868 menu[i] = 0;
7869 }
7870 else
7871 {
7872 /* If this element does not fit, end the line now,
7873 and save the element for the next line. */
7874 strcpy (menu + i, "...");
7875 break;
7876 }
7877 }
7878
7879 /* Move past this element. */
7880 if (idx >= 0 && idx + 1 >= XVECTOR (vector)->size)
7881 /* Handle reaching end of dense table. */
7882 idx = -1;
7883 if (idx >= 0)
7884 idx++;
7885 else
7886 rest = Fcdr_safe (rest);
7887 } 7754 }
7888 } 7755
7889 7756 /* Ignore the element if it has no prompt string. */
7890 /* Prompt with that and read response. */ 7757 if (INTEGERP (event) && parse_menu_item (elt, 0, -1))
7891 message2_nolog (menu, strlen (menu), 7758 {
7892 ! NILP (current_buffer->enable_multibyte_characters)); 7759 /* The list describing this entry. */
7893 7760 Lisp_Object entry = Qnil;
7894 /* Make believe its not a keyboard macro in case the help char 7761 Lisp_Object prop_val;
7895 is pressed. Help characters are not recorded because menu prompting 7762
7896 is not used on replay. 7763 prop_val = AREF (item_properties, ITEM_PROPERTY_TYPE);
7897 */ 7764 if (EQ (prop_val, QCradio) || EQ (prop_val, QCtoggle))
7898 orig_defn_macro = current_kboard->defining_kbd_macro; 7765 /* This is a `toggle-able' menu-entry, make the
7899 current_kboard->defining_kbd_macro = Qnil; 7766 tail of the list describe it. */
7900 do 7767 entry
7901 obj = read_char (commandflag, 0, 0, Qt, 0); 7768 = Fcons (prop_val,
7902 while (BUFFERP (obj)); 7769 Fcons (AREF (item_properties,
7903 current_kboard->defining_kbd_macro = orig_defn_macro; 7770 ITEM_PROPERTY_SELECTED),
7904 7771 entry));
7905 if (!INTEGERP (obj)) 7772
7906 return obj; 7773 /* Equivalent keybinding. */
7907 else 7774 prop_val = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
7908 ch = XINT (obj); 7775 if (!NILP (entry) || !NILP (prop_val))
7909 7776 entry = Fcons (prop_val, entry);
7910 if (! EQ (obj, menu_prompt_more_char) 7777
7911 && (!INTEGERP (menu_prompt_more_char) 7778 /* The string prompt. */
7912 || ! EQ (obj, make_number (Ctl (XINT (menu_prompt_more_char)))))) 7779 prop_val = AREF (item_properties, ITEM_PROPERTY_NAME);
7913 { 7780 entry = Fcons (prop_val, entry);
7914 if (!NILP (current_kboard->defining_kbd_macro)) 7781
7915 store_kbd_macro_char (obj); 7782 /* Finally, the car of the list is the event. */
7916 return obj; 7783 entry = Fcons (event, entry);
7917 } 7784
7918 /* Help char - go round again */ 7785 /* Push this entry on the the list of entries. */
7919 } 7786 menu_list = Fcons (entry, menu_list);
7787 }
7788
7789 /* Move past this element. */
7790 if (idx >= 0 && idx + 1 >= XVECTOR (vector)->size)
7791 /* Handle reaching end of dense table. */
7792 idx = -1;
7793 if (idx >= 0)
7794 idx++;
7795 else
7796 rest = Fcdr_safe (rest);
7797 }
7798 }
7799
7800 /* Put the entries in the proper order for the display function. */
7801 menu_list = Fnreverse (menu_list);
7802
7803 /* The car of the entries list is the prompt for the whole menu. */
7804 menu_list = Fcons (name, menu_list);
7805
7806 /* Display the menu, and prompt for a key. */
7807 if (NILP (Vkey_menu_prompt_function))
7808 return Qnil;
7809 else
7810 return call1 (Vkey_menu_prompt_function, menu_list);
7920 } 7811 }
7921 7812
7922 /* Reading key sequences. */ 7813 /* Reading key sequences. */
7923 7814
7924 /* Follow KEY in the maps in CURRENT[0..NMAPS-1], placing its bindings 7815 /* Follow KEY in the maps in CURRENT[0..NMAPS-1], placing its bindings
11010 10901
11011 DEFVAR_LISP ("minibuffer-message-timeout", &Vminibuffer_message_timeout, 10902 DEFVAR_LISP ("minibuffer-message-timeout", &Vminibuffer_message_timeout,
11012 doc: /* *How long to display an echo-area message when the minibuffer is active. 10903 doc: /* *How long to display an echo-area message when the minibuffer is active.
11013 If the value is not a number, such messages don't time out. */); 10904 If the value is not a number, such messages don't time out. */);
11014 Vminibuffer_message_timeout = make_number (2); 10905 Vminibuffer_message_timeout = make_number (2);
10906
10907 DEFVAR_LISP ("key-menu-prompt-function", &Vkey_menu_prompt_function,
10908 doc: /* A function to display keyboard-menus, and read the user's response.
10909 If nil, keyboard menus are disabled.
10910
10911 It is called with single argument, which is a list describing the keyboard menu
10912 and should return the key the user types.
10913
10914 The argument is a list of the prompt and individual menu entries.
10915 The format is as follows:
10916
10917 MENU : (PROMPT ENTRY...)
10918 ENTRY : (EVENT PROMPT [BINDING [TOGGLE_TYPE TOGGLE_STATE]])
10919
10920 Note that there is a prompt for the whole menu, and one for each
10921 individual entry. */);
10922 Vkey_menu_prompt_function = Qnil;
11015 } 10923 }
11016 10924
11017 void 10925 void
11018 keys_of_keyboard () 10926 keys_of_keyboard ()
11019 { 10927 {