Mercurial > emacs
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 { |