diff options
| author | Andrea Corallo | 2020-10-23 20:08:58 +0100 |
|---|---|---|
| committer | Andrea Corallo | 2020-10-23 20:08:58 +0100 |
| commit | 99e7cc0da652bf0f19f691d5de3b3ce7c15e8c39 (patch) | |
| tree | e7c4921579cfeac379b649f27c2da78fed8aae48 /src | |
| parent | 3be93390fb6680d1e0c3256af72c86635a9eb327 (diff) | |
| parent | 46f5d2867cf73a845d582eeb8929ae51b78eae55 (diff) | |
| download | emacs-99e7cc0da652bf0f19f691d5de3b3ce7c15e8c39.tar.gz emacs-99e7cc0da652bf0f19f691d5de3b3ce7c15e8c39.zip | |
Merge remote-tracking branch 'savannah/master' into HEAD
Diffstat (limited to 'src')
| -rw-r--r-- | src/dired.c | 8 | ||||
| -rw-r--r-- | src/doc.c | 321 | ||||
| -rw-r--r-- | src/eval.c | 5 | ||||
| -rw-r--r-- | src/ftcrfont.c | 16 | ||||
| -rw-r--r-- | src/image.c | 46 | ||||
| -rw-r--r-- | src/keyboard.c | 11 | ||||
| -rw-r--r-- | src/keymap.c | 540 | ||||
| -rw-r--r-- | src/keymap.h | 2 | ||||
| -rw-r--r-- | src/lread.c | 7 | ||||
| -rw-r--r-- | src/nsterm.m | 6 | ||||
| -rw-r--r-- | src/print.c | 2 | ||||
| -rw-r--r-- | src/search.c | 2 | ||||
| -rw-r--r-- | src/syntax.c | 2 | ||||
| -rw-r--r-- | src/xterm.c | 13 |
14 files changed, 222 insertions, 759 deletions
diff --git a/src/dired.c b/src/dired.c index 1584b6acf08..8256f2626dc 100644 --- a/src/dired.c +++ b/src/dired.c | |||
| @@ -293,7 +293,8 @@ DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0, | |||
| 293 | There are three optional arguments: | 293 | There are three optional arguments: |
| 294 | If FULL is non-nil, return absolute file names. Otherwise return names | 294 | If FULL is non-nil, return absolute file names. Otherwise return names |
| 295 | that are relative to the specified directory. | 295 | that are relative to the specified directory. |
| 296 | If MATCH is non-nil, mention only file names that match the regexp MATCH. | 296 | If MATCH is non-nil, mention only file names whose non-directory part |
| 297 | matches the regexp MATCH. | ||
| 297 | If NOSORT is non-nil, the list is not sorted--its order is unpredictable. | 298 | If NOSORT is non-nil, the list is not sorted--its order is unpredictable. |
| 298 | Otherwise, the list returned is sorted with `string-lessp'. | 299 | Otherwise, the list returned is sorted with `string-lessp'. |
| 299 | NOSORT is useful if you plan to sort the result yourself. */) | 300 | NOSORT is useful if you plan to sort the result yourself. */) |
| @@ -325,11 +326,12 @@ by `file-attributes'. | |||
| 325 | This function accepts four optional arguments: | 326 | This function accepts four optional arguments: |
| 326 | If FULL is non-nil, return absolute file names. Otherwise return names | 327 | If FULL is non-nil, return absolute file names. Otherwise return names |
| 327 | that are relative to the specified directory. | 328 | that are relative to the specified directory. |
| 328 | If MATCH is non-nil, mention only file names that match the regexp MATCH. | 329 | If MATCH is non-nil, mention only file names whose non-directory part |
| 330 | matches the regexp MATCH. | ||
| 329 | If NOSORT is non-nil, the list is not sorted--its order is unpredictable. | 331 | If NOSORT is non-nil, the list is not sorted--its order is unpredictable. |
| 330 | NOSORT is useful if you plan to sort the result yourself. | 332 | NOSORT is useful if you plan to sort the result yourself. |
| 331 | ID-FORMAT specifies the preferred format of attributes uid and gid, see | 333 | ID-FORMAT specifies the preferred format of attributes uid and gid, see |
| 332 | `file-attributes' for further documentation. | 334 | `file-attributes' for further documentation. |
| 333 | On MS-Windows, performance depends on `w32-get-true-file-attributes', | 335 | On MS-Windows, performance depends on `w32-get-true-file-attributes', |
| 334 | which see. */) | 336 | which see. */) |
| 335 | (Lisp_Object directory, Lisp_Object full, Lisp_Object match, | 337 | (Lisp_Object directory, Lisp_Object full, Lisp_Object match, |
| @@ -420,7 +420,7 @@ string is passed through `substitute-command-keys'. */) | |||
| 420 | } | 420 | } |
| 421 | 421 | ||
| 422 | if (NILP (raw)) | 422 | if (NILP (raw)) |
| 423 | doc = Fsubstitute_command_keys (doc); | 423 | doc = call1 (Qsubstitute_command_keys, doc); |
| 424 | return doc; | 424 | return doc; |
| 425 | } | 425 | } |
| 426 | 426 | ||
| @@ -477,7 +477,7 @@ aren't strings. */) | |||
| 477 | tem = Feval (tem, Qnil); | 477 | tem = Feval (tem, Qnil); |
| 478 | 478 | ||
| 479 | if (NILP (raw) && STRINGP (tem)) | 479 | if (NILP (raw) && STRINGP (tem)) |
| 480 | tem = Fsubstitute_command_keys (tem); | 480 | tem = call1 (Qsubstitute_command_keys, tem); |
| 481 | return tem; | 481 | return tem; |
| 482 | } | 482 | } |
| 483 | 483 | ||
| @@ -702,315 +702,34 @@ text_quoting_style (void) | |||
| 702 | return CURVE_QUOTING_STYLE; | 702 | return CURVE_QUOTING_STYLE; |
| 703 | } | 703 | } |
| 704 | 704 | ||
| 705 | DEFUN ("substitute-command-keys", Fsubstitute_command_keys, | 705 | /* This is just a Lisp wrapper for text_quoting_style above. */ |
| 706 | Ssubstitute_command_keys, 1, 1, 0, | 706 | DEFUN ("get-quoting-style", Fget_quoting_style, |
| 707 | doc: /* Substitute key descriptions for command names in STRING. | 707 | Sget_quoting_style, 0, 0, 0, |
| 708 | Each substring of the form \\=\\[COMMAND] is replaced by either a | 708 | doc: /* Return the current effective text quoting style. |
| 709 | keystroke sequence that invokes COMMAND, or "M-x COMMAND" if COMMAND | 709 | See variable `text-quoting-style'. */) |
| 710 | is not on any keys. | 710 | (void) |
| 711 | |||
| 712 | Each substring of the form \\=\\{MAPVAR} is replaced by a summary of | ||
| 713 | the value of MAPVAR as a keymap. This summary is similar to the one | ||
| 714 | produced by `describe-bindings'. The summary ends in two newlines | ||
| 715 | \(used by the helper function `help-make-xrefs' to find the end of the | ||
| 716 | summary). | ||
| 717 | |||
| 718 | Each substring of the form \\=\\<MAPVAR> specifies the use of MAPVAR | ||
| 719 | as the keymap for future \\=\\[COMMAND] substrings. | ||
| 720 | |||
| 721 | Each grave accent \\=` is replaced by left quote, and each apostrophe \\=' | ||
| 722 | is replaced by right quote. Left and right quote characters are | ||
| 723 | specified by `text-quoting-style'. | ||
| 724 | |||
| 725 | \\=\\= quotes the following character and is discarded; thus, \\=\\=\\=\\= puts \\=\\= | ||
| 726 | into the output, \\=\\=\\=\\[ puts \\=\\[ into the output, and \\=\\=\\=` puts \\=` into the | ||
| 727 | output. | ||
| 728 | |||
| 729 | Return the original STRING if no substitutions are made. | ||
| 730 | Otherwise, return a new string (without any text properties). */) | ||
| 731 | (Lisp_Object string) | ||
| 732 | { | 711 | { |
| 733 | char *buf; | 712 | switch (text_quoting_style ()) |
| 734 | bool changed = false; | ||
| 735 | bool nonquotes_changed = false; | ||
| 736 | unsigned char *strp; | ||
| 737 | char *bufp; | ||
| 738 | ptrdiff_t idx; | ||
| 739 | ptrdiff_t bsize; | ||
| 740 | Lisp_Object tem; | ||
| 741 | Lisp_Object keymap; | ||
| 742 | unsigned char const *start; | ||
| 743 | ptrdiff_t length, length_byte; | ||
| 744 | Lisp_Object name; | ||
| 745 | ptrdiff_t nchars; | ||
| 746 | |||
| 747 | if (NILP (string)) | ||
| 748 | return Qnil; | ||
| 749 | |||
| 750 | /* If STRING contains non-ASCII unibyte data, process its | ||
| 751 | properly-encoded multibyte equivalent instead. This simplifies | ||
| 752 | the implementation and is OK since substitute-command-keys is | ||
| 753 | intended for use only on text strings. Keep STRING around, since | ||
| 754 | it will be returned if no changes occur. */ | ||
| 755 | Lisp_Object str = Fstring_make_multibyte (string); | ||
| 756 | |||
| 757 | enum text_quoting_style quoting_style = text_quoting_style (); | ||
| 758 | |||
| 759 | nchars = 0; | ||
| 760 | |||
| 761 | /* KEYMAP is either nil (which means search all the active keymaps) | ||
| 762 | or a specified local map (which means search just that and the | ||
| 763 | global map). If non-nil, it might come from Voverriding_local_map, | ||
| 764 | or from a \\<mapname> construct in STRING itself.. */ | ||
| 765 | keymap = Voverriding_local_map; | ||
| 766 | |||
| 767 | ptrdiff_t strbytes = SBYTES (str); | ||
| 768 | bsize = strbytes; | ||
| 769 | |||
| 770 | /* Fixed-size stack buffer. */ | ||
| 771 | char sbuf[MAX_ALLOCA]; | ||
| 772 | |||
| 773 | /* Heap-allocated buffer, if any. */ | ||
| 774 | char *abuf; | ||
| 775 | |||
| 776 | /* Extra room for expansion due to replacing ‘\[]’ with ‘M-x ’. */ | ||
| 777 | enum { EXTRA_ROOM = sizeof "M-x " - sizeof "\\[]" }; | ||
| 778 | |||
| 779 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 780 | |||
| 781 | if (bsize <= sizeof sbuf - EXTRA_ROOM) | ||
| 782 | { | ||
| 783 | abuf = NULL; | ||
| 784 | buf = sbuf; | ||
| 785 | bsize = sizeof sbuf; | ||
| 786 | } | ||
| 787 | else | ||
| 788 | { | ||
| 789 | buf = abuf = xpalloc (NULL, &bsize, EXTRA_ROOM, STRING_BYTES_BOUND, 1); | ||
| 790 | record_unwind_protect_ptr (xfree, abuf); | ||
| 791 | } | ||
| 792 | bufp = buf; | ||
| 793 | |||
| 794 | strp = SDATA (str); | ||
| 795 | while (strp < SDATA (str) + strbytes) | ||
| 796 | { | ||
| 797 | unsigned char *close_bracket; | ||
| 798 | |||
| 799 | if (strp[0] == '\\' && strp[1] == '=' | ||
| 800 | && strp + 2 < SDATA (str) + strbytes) | ||
| 801 | { | ||
| 802 | /* \= quotes the next character; | ||
| 803 | thus, to put in \[ without its special meaning, use \=\[. */ | ||
| 804 | changed = nonquotes_changed = true; | ||
| 805 | strp += 2; | ||
| 806 | /* Fall through to copy one char. */ | ||
| 807 | } | ||
| 808 | else if (strp[0] == '\\' && strp[1] == '[' | ||
| 809 | && (close_bracket | ||
| 810 | = memchr (strp + 2, ']', | ||
| 811 | SDATA (str) + strbytes - (strp + 2)))) | ||
| 812 | { | ||
| 813 | bool follow_remap = 1; | ||
| 814 | |||
| 815 | start = strp + 2; | ||
| 816 | length_byte = close_bracket - start; | ||
| 817 | idx = close_bracket + 1 - SDATA (str); | ||
| 818 | |||
| 819 | name = Fintern (make_string ((char *) start, length_byte), Qnil); | ||
| 820 | |||
| 821 | do_remap: | ||
| 822 | tem = Fwhere_is_internal (name, keymap, Qt, Qnil, Qnil); | ||
| 823 | |||
| 824 | if (VECTORP (tem) && ASIZE (tem) > 1 | ||
| 825 | && EQ (AREF (tem, 0), Qremap) && SYMBOLP (AREF (tem, 1)) | ||
| 826 | && follow_remap) | ||
| 827 | { | ||
| 828 | name = AREF (tem, 1); | ||
| 829 | follow_remap = 0; | ||
| 830 | goto do_remap; | ||
| 831 | } | ||
| 832 | |||
| 833 | /* Fwhere_is_internal can GC, so take relocation of string | ||
| 834 | contents into account. */ | ||
| 835 | strp = SDATA (str) + idx; | ||
| 836 | start = strp - length_byte - 1; | ||
| 837 | |||
| 838 | if (NILP (tem)) /* but not on any keys */ | ||
| 839 | { | ||
| 840 | memcpy (bufp, "M-x ", 4); | ||
| 841 | bufp += 4; | ||
| 842 | nchars += 4; | ||
| 843 | length = multibyte_chars_in_text (start, length_byte); | ||
| 844 | goto subst; | ||
| 845 | } | ||
| 846 | else | ||
| 847 | { /* function is on a key */ | ||
| 848 | tem = Fkey_description (tem, Qnil); | ||
| 849 | goto subst_string; | ||
| 850 | } | ||
| 851 | } | ||
| 852 | /* \{foo} is replaced with a summary of the keymap (symbol-value foo). | ||
| 853 | \<foo> just sets the keymap used for \[cmd]. */ | ||
| 854 | else if (strp[0] == '\\' && (strp[1] == '{' || strp[1] == '<') | ||
| 855 | && (close_bracket | ||
| 856 | = memchr (strp + 2, strp[1] == '{' ? '}' : '>', | ||
| 857 | SDATA (str) + strbytes - (strp + 2)))) | ||
| 858 | { | ||
| 859 | { | ||
| 860 | bool generate_summary = strp[1] == '{'; | ||
| 861 | /* This is for computing the SHADOWS arg for describe_map_tree. */ | ||
| 862 | Lisp_Object active_maps = Fcurrent_active_maps (Qnil, Qnil); | ||
| 863 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 864 | |||
| 865 | start = strp + 2; | ||
| 866 | length_byte = close_bracket - start; | ||
| 867 | idx = close_bracket + 1 - SDATA (str); | ||
| 868 | |||
| 869 | /* Get the value of the keymap in TEM, or nil if undefined. | ||
| 870 | Do this while still in the user's current buffer | ||
| 871 | in case it is a local variable. */ | ||
| 872 | name = Fintern (make_string ((char *) start, length_byte), Qnil); | ||
| 873 | tem = Fboundp (name); | ||
| 874 | if (! NILP (tem)) | ||
| 875 | { | ||
| 876 | tem = Fsymbol_value (name); | ||
| 877 | if (! NILP (tem)) | ||
| 878 | tem = get_keymap (tem, 0, 1); | ||
| 879 | } | ||
| 880 | |||
| 881 | /* Now switch to a temp buffer. */ | ||
| 882 | struct buffer *oldbuf = current_buffer; | ||
| 883 | set_buffer_internal (XBUFFER (Vprin1_to_string_buffer)); | ||
| 884 | /* This is for an unusual case where some after-change | ||
| 885 | function uses 'format' or 'prin1' or something else that | ||
| 886 | will thrash Vprin1_to_string_buffer we are using. */ | ||
| 887 | specbind (Qinhibit_modification_hooks, Qt); | ||
| 888 | |||
| 889 | if (NILP (tem)) | ||
| 890 | { | ||
| 891 | name = Fsymbol_name (name); | ||
| 892 | AUTO_STRING (msg_prefix, "\nUses keymap `"); | ||
| 893 | insert1 (Fsubstitute_command_keys (msg_prefix)); | ||
| 894 | insert_from_string (name, 0, 0, | ||
| 895 | SCHARS (name), | ||
| 896 | SBYTES (name), 1); | ||
| 897 | AUTO_STRING (msg_suffix, "', which is not currently defined.\n"); | ||
| 898 | insert1 (Fsubstitute_command_keys (msg_suffix)); | ||
| 899 | if (!generate_summary) | ||
| 900 | keymap = Qnil; | ||
| 901 | } | ||
| 902 | else if (!generate_summary) | ||
| 903 | keymap = tem; | ||
| 904 | else | ||
| 905 | { | ||
| 906 | /* Get the list of active keymaps that precede this one. | ||
| 907 | If this one's not active, get nil. */ | ||
| 908 | Lisp_Object earlier_maps | ||
| 909 | = Fcdr (Fmemq (tem, Freverse (active_maps))); | ||
| 910 | describe_map_tree (tem, 1, Fnreverse (earlier_maps), | ||
| 911 | Qnil, 0, 1, 0, 0, 1); | ||
| 912 | } | ||
| 913 | tem = Fbuffer_string (); | ||
| 914 | Ferase_buffer (); | ||
| 915 | set_buffer_internal (oldbuf); | ||
| 916 | unbind_to (count, Qnil); | ||
| 917 | } | ||
| 918 | |||
| 919 | subst_string: | ||
| 920 | /* Convert non-ASCII unibyte data to properly-encoded multibyte, | ||
| 921 | for the same reason STRING was converted to STR. */ | ||
| 922 | tem = Fstring_make_multibyte (tem); | ||
| 923 | start = SDATA (tem); | ||
| 924 | length = SCHARS (tem); | ||
| 925 | length_byte = SBYTES (tem); | ||
| 926 | subst: | ||
| 927 | nonquotes_changed = true; | ||
| 928 | subst_quote: | ||
| 929 | changed = true; | ||
| 930 | { | ||
| 931 | ptrdiff_t offset = bufp - buf; | ||
| 932 | ptrdiff_t avail = bsize - offset; | ||
| 933 | ptrdiff_t need = strbytes - idx; | ||
| 934 | if (INT_ADD_WRAPV (need, length_byte + EXTRA_ROOM, &need)) | ||
| 935 | string_overflow (); | ||
| 936 | if (avail < need) | ||
| 937 | { | ||
| 938 | abuf = xpalloc (abuf, &bsize, need - avail, | ||
| 939 | STRING_BYTES_BOUND, 1); | ||
| 940 | if (buf == sbuf) | ||
| 941 | { | ||
| 942 | record_unwind_protect_ptr (xfree, abuf); | ||
| 943 | memcpy (abuf, sbuf, offset); | ||
| 944 | } | ||
| 945 | else | ||
| 946 | set_unwind_protect_ptr (count, xfree, abuf); | ||
| 947 | buf = abuf; | ||
| 948 | bufp = buf + offset; | ||
| 949 | } | ||
| 950 | memcpy (bufp, start, length_byte); | ||
| 951 | bufp += length_byte; | ||
| 952 | nchars += length; | ||
| 953 | |||
| 954 | /* Some of the previous code can GC, so take relocation of | ||
| 955 | string contents into account. */ | ||
| 956 | strp = SDATA (str) + idx; | ||
| 957 | |||
| 958 | continue; | ||
| 959 | } | ||
| 960 | } | ||
| 961 | else if ((strp[0] == '`' || strp[0] == '\'') | ||
| 962 | && quoting_style == CURVE_QUOTING_STYLE) | ||
| 963 | { | ||
| 964 | start = (unsigned char const *) (strp[0] == '`' ? uLSQM : uRSQM); | ||
| 965 | length = 1; | ||
| 966 | length_byte = sizeof uLSQM - 1; | ||
| 967 | idx = strp - SDATA (str) + 1; | ||
| 968 | goto subst_quote; | ||
| 969 | } | ||
| 970 | else if (strp[0] == '`' && quoting_style == STRAIGHT_QUOTING_STYLE) | ||
| 971 | { | ||
| 972 | *bufp++ = '\''; | ||
| 973 | strp++; | ||
| 974 | nchars++; | ||
| 975 | changed = true; | ||
| 976 | continue; | ||
| 977 | } | ||
| 978 | |||
| 979 | /* Copy one char. */ | ||
| 980 | do | ||
| 981 | *bufp++ = *strp++; | ||
| 982 | while (! CHAR_HEAD_P (*strp)); | ||
| 983 | nchars++; | ||
| 984 | } | ||
| 985 | |||
| 986 | if (changed) /* don't bother if nothing substituted */ | ||
| 987 | { | 713 | { |
| 988 | tem = make_string_from_bytes (buf, nchars, bufp - buf); | 714 | case STRAIGHT_QUOTING_STYLE: |
| 989 | if (!nonquotes_changed) | 715 | return Qstraight; |
| 990 | { | 716 | case CURVE_QUOTING_STYLE: |
| 991 | /* Nothing has changed other than quoting, so copy the string’s | 717 | return Qcurve; |
| 992 | text properties. FIXME: Text properties should survive other | 718 | case GRAVE_QUOTING_STYLE: |
| 993 | changes too; see bug#17052. */ | 719 | default: |
| 994 | INTERVAL interval_copy = copy_intervals (string_intervals (string), | 720 | return Qgrave; |
| 995 | 0, SCHARS (string)); | ||
| 996 | if (interval_copy) | ||
| 997 | { | ||
| 998 | set_interval_object (interval_copy, tem); | ||
| 999 | set_string_intervals (tem, interval_copy); | ||
| 1000 | } | ||
| 1001 | } | ||
| 1002 | } | 721 | } |
| 1003 | else | ||
| 1004 | tem = string; | ||
| 1005 | return unbind_to (count, tem); | ||
| 1006 | } | 722 | } |
| 723 | |||
| 1007 | 724 | ||
| 1008 | void | 725 | void |
| 1009 | syms_of_doc (void) | 726 | syms_of_doc (void) |
| 1010 | { | 727 | { |
| 728 | DEFSYM (Qsubstitute_command_keys, "substitute-command-keys"); | ||
| 1011 | DEFSYM (Qfunction_documentation, "function-documentation"); | 729 | DEFSYM (Qfunction_documentation, "function-documentation"); |
| 1012 | DEFSYM (Qgrave, "grave"); | 730 | DEFSYM (Qgrave, "grave"); |
| 1013 | DEFSYM (Qstraight, "straight"); | 731 | DEFSYM (Qstraight, "straight"); |
| 732 | DEFSYM (Qcurve, "curve"); | ||
| 1014 | 733 | ||
| 1015 | DEFVAR_LISP ("internal-doc-file-name", Vdoc_file_name, | 734 | DEFVAR_LISP ("internal-doc-file-name", Vdoc_file_name, |
| 1016 | doc: /* Name of file containing documentation strings of built-in symbols. */); | 735 | doc: /* Name of file containing documentation strings of built-in symbols. */); |
| @@ -1042,5 +761,5 @@ otherwise. */); | |||
| 1042 | defsubr (&Sdocumentation); | 761 | defsubr (&Sdocumentation); |
| 1043 | defsubr (&Sdocumentation_property); | 762 | defsubr (&Sdocumentation_property); |
| 1044 | defsubr (&Ssnarf_documentation); | 763 | defsubr (&Ssnarf_documentation); |
| 1045 | defsubr (&Ssubstitute_command_keys); | 764 | defsubr (&Sget_quoting_style); |
| 1046 | } | 765 | } |
diff --git a/src/eval.c b/src/eval.c index 84631f4f942..09e12bd3752 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -553,7 +553,10 @@ usage: (quote ARG) */) | |||
| 553 | DEFUN ("function", Ffunction, Sfunction, 1, UNEVALLED, 0, | 553 | DEFUN ("function", Ffunction, Sfunction, 1, UNEVALLED, 0, |
| 554 | doc: /* Like `quote', but preferred for objects which are functions. | 554 | doc: /* Like `quote', but preferred for objects which are functions. |
| 555 | In byte compilation, `function' causes its argument to be handled by | 555 | In byte compilation, `function' causes its argument to be handled by |
| 556 | the byte compiler. `quote' cannot do that. | 556 | the byte compiler. Similarly, when expanding macros and expressions, |
| 557 | ARG can be examined and possibly expanded. If `quote' is used | ||
| 558 | instead, this doesn't happen. | ||
| 559 | |||
| 557 | usage: (function ARG) */) | 560 | usage: (function ARG) */) |
| 558 | (Lisp_Object args) | 561 | (Lisp_Object args) |
| 559 | { | 562 | { |
diff --git a/src/ftcrfont.c b/src/ftcrfont.c index 4892a34a3ab..a10308c62ee 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c | |||
| @@ -139,7 +139,8 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 139 | 139 | ||
| 140 | FcPatternDestroy (pat); | 140 | FcPatternDestroy (pat); |
| 141 | font_face = cairo_ft_font_face_create_for_pattern (match); | 141 | font_face = cairo_ft_font_face_create_for_pattern (match); |
| 142 | if (!font_face) | 142 | if (!font_face |
| 143 | || cairo_font_face_status (font_face) != CAIRO_STATUS_SUCCESS) | ||
| 143 | { | 144 | { |
| 144 | unblock_input (); | 145 | unblock_input (); |
| 145 | FcPatternDestroy (match); | 146 | FcPatternDestroy (match); |
| @@ -154,6 +155,18 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 154 | cairo_font_face_destroy (font_face); | 155 | cairo_font_face_destroy (font_face); |
| 155 | cairo_font_options_destroy (options); | 156 | cairo_font_options_destroy (options); |
| 156 | unblock_input (); | 157 | unblock_input (); |
| 158 | if (!scaled_font | ||
| 159 | || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS) | ||
| 160 | { | ||
| 161 | FcPatternDestroy (match); | ||
| 162 | return Qnil; | ||
| 163 | } | ||
| 164 | ft_face = cairo_ft_scaled_font_lock_face (scaled_font); | ||
| 165 | if (!ft_face) | ||
| 166 | { | ||
| 167 | FcPatternDestroy (match); | ||
| 168 | return Qnil; | ||
| 169 | } | ||
| 157 | 170 | ||
| 158 | font_object = font_build_object (VECSIZE (struct font_info), | 171 | font_object = font_build_object (VECSIZE (struct font_info), |
| 159 | AREF (entity, FONT_TYPE_INDEX), | 172 | AREF (entity, FONT_TYPE_INDEX), |
| @@ -234,7 +247,6 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | |||
| 234 | font->descent = font->height - font->ascent; | 247 | font->descent = font->height - font->ascent; |
| 235 | } | 248 | } |
| 236 | 249 | ||
| 237 | ft_face = cairo_ft_scaled_font_lock_face (scaled_font); | ||
| 238 | if (XFIXNUM (AREF (entity, FONT_SIZE_INDEX)) == 0) | 250 | if (XFIXNUM (AREF (entity, FONT_SIZE_INDEX)) == 0) |
| 239 | { | 251 | { |
| 240 | int upEM = ft_face->units_per_EM; | 252 | int upEM = ft_face->units_per_EM; |
diff --git a/src/image.c b/src/image.c index 25d5af8a8d5..5f6d9f4c443 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -9736,7 +9736,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents, | |||
| 9736 | ptrdiff_t size, char *filename) | 9736 | ptrdiff_t size, char *filename) |
| 9737 | { | 9737 | { |
| 9738 | RsvgHandle *rsvg_handle; | 9738 | RsvgHandle *rsvg_handle; |
| 9739 | RsvgDimensionData dimension_data; | 9739 | double viewbox_width, viewbox_height; |
| 9740 | GError *err = NULL; | 9740 | GError *err = NULL; |
| 9741 | GdkPixbuf *pixbuf; | 9741 | GdkPixbuf *pixbuf; |
| 9742 | int width; | 9742 | int width; |
| @@ -9789,15 +9789,38 @@ svg_load_image (struct frame *f, struct image *img, char *contents, | |||
| 9789 | #endif | 9789 | #endif |
| 9790 | 9790 | ||
| 9791 | /* Get the image dimensions. */ | 9791 | /* Get the image dimensions. */ |
| 9792 | #if LIBRSVG_CHECK_VERSION (2, 46, 0) | ||
| 9793 | RsvgRectangle zero_rect, viewbox; | ||
| 9794 | |||
| 9795 | rsvg_handle_get_geometry_for_layer (rsvg_handle, NULL, | ||
| 9796 | &zero_rect, &viewbox, | ||
| 9797 | NULL, NULL); | ||
| 9798 | viewbox_width = viewbox.x + viewbox.width; | ||
| 9799 | viewbox_height = viewbox.y + viewbox.height; | ||
| 9800 | #else | ||
| 9801 | /* The function used above to get the geometry of the visible area | ||
| 9802 | of the SVG are only available in librsvg 2.46 and above, so in | ||
| 9803 | certain circumstances this code path can result in some parts of | ||
| 9804 | the SVG being cropped. */ | ||
| 9805 | RsvgDimensionData dimension_data; | ||
| 9806 | |||
| 9792 | rsvg_handle_get_dimensions (rsvg_handle, &dimension_data); | 9807 | rsvg_handle_get_dimensions (rsvg_handle, &dimension_data); |
| 9793 | 9808 | ||
| 9809 | viewbox_width = dimension_data.width; | ||
| 9810 | viewbox_height = dimension_data.height; | ||
| 9811 | #endif | ||
| 9812 | compute_image_size (viewbox_width, viewbox_height, img->spec, | ||
| 9813 | &width, &height); | ||
| 9814 | |||
| 9815 | if (! check_image_size (f, width, height)) | ||
| 9816 | { | ||
| 9817 | image_size_error (); | ||
| 9818 | goto rsvg_error; | ||
| 9819 | } | ||
| 9820 | |||
| 9794 | /* We are now done with the unmodified data. */ | 9821 | /* We are now done with the unmodified data. */ |
| 9795 | g_object_unref (rsvg_handle); | 9822 | g_object_unref (rsvg_handle); |
| 9796 | 9823 | ||
| 9797 | /* Calculate the final image size. */ | ||
| 9798 | compute_image_size (dimension_data.width, dimension_data.height, | ||
| 9799 | img->spec, &width, &height); | ||
| 9800 | |||
| 9801 | /* Wrap the SVG data in another SVG. This allows us to set the | 9824 | /* Wrap the SVG data in another SVG. This allows us to set the |
| 9802 | width and height, as well as modify the foreground and background | 9825 | width and height, as well as modify the foreground and background |
| 9803 | colors. */ | 9826 | colors. */ |
| @@ -9820,7 +9843,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents, | |||
| 9820 | "xmlns:xi=\"http://www.w3.org/2001/XInclude\" " | 9843 | "xmlns:xi=\"http://www.w3.org/2001/XInclude\" " |
| 9821 | "style=\"color: #%06X; fill: currentColor;\" " | 9844 | "style=\"color: #%06X; fill: currentColor;\" " |
| 9822 | "width=\"%d\" height=\"%d\" preserveAspectRatio=\"none\" " | 9845 | "width=\"%d\" height=\"%d\" preserveAspectRatio=\"none\" " |
| 9823 | "viewBox=\"0 0 %d %d\">" | 9846 | "viewBox=\"0 0 %f %f\">" |
| 9824 | "<rect width=\"100%%\" height=\"100%%\" fill=\"#%06X\"/>" | 9847 | "<rect width=\"100%%\" height=\"100%%\" fill=\"#%06X\"/>" |
| 9825 | "<xi:include href=\"data:image/svg+xml;base64,%s\"></xi:include>" | 9848 | "<xi:include href=\"data:image/svg+xml;base64,%s\"></xi:include>" |
| 9826 | "</svg>"; | 9849 | "</svg>"; |
| @@ -9845,8 +9868,9 @@ svg_load_image (struct frame *f, struct image *img, char *contents, | |||
| 9845 | if (!wrapped_contents | 9868 | if (!wrapped_contents |
| 9846 | || buffer_size <= snprintf (wrapped_contents, buffer_size, wrapper, | 9869 | || buffer_size <= snprintf (wrapped_contents, buffer_size, wrapper, |
| 9847 | foreground & 0xFFFFFF, width, height, | 9870 | foreground & 0xFFFFFF, width, height, |
| 9848 | dimension_data.width, dimension_data.height, | 9871 | viewbox_width, viewbox_height, |
| 9849 | background & 0xFFFFFF, SSDATA (encoded_contents))) | 9872 | background & 0xFFFFFF, |
| 9873 | SSDATA (encoded_contents))) | ||
| 9850 | goto rsvg_error; | 9874 | goto rsvg_error; |
| 9851 | 9875 | ||
| 9852 | wrapped_size = strlen (wrapped_contents); | 9876 | wrapped_size = strlen (wrapped_contents); |
| @@ -9887,12 +9911,6 @@ svg_load_image (struct frame *f, struct image *img, char *contents, | |||
| 9887 | if (err) goto rsvg_error; | 9911 | if (err) goto rsvg_error; |
| 9888 | #endif | 9912 | #endif |
| 9889 | 9913 | ||
| 9890 | rsvg_handle_get_dimensions (rsvg_handle, &dimension_data); | ||
| 9891 | if (! check_image_size (f, dimension_data.width, dimension_data.height)) | ||
| 9892 | { | ||
| 9893 | image_size_error (); | ||
| 9894 | goto rsvg_error; | ||
| 9895 | } | ||
| 9896 | 9914 | ||
| 9897 | /* We can now get a valid pixel buffer from the svg file, if all | 9915 | /* We can now get a valid pixel buffer from the svg file, if all |
| 9898 | went ok. */ | 9916 | went ok. */ |
diff --git a/src/keyboard.c b/src/keyboard.c index 4d22c44810e..2e0143379a0 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -2040,7 +2040,7 @@ help_echo_substitute_command_keys (Lisp_Object help) | |||
| 2040 | help))) | 2040 | help))) |
| 2041 | return help; | 2041 | return help; |
| 2042 | 2042 | ||
| 2043 | return Fsubstitute_command_keys (help); | 2043 | return call1 (Qsubstitute_command_keys, help); |
| 2044 | } | 2044 | } |
| 2045 | 2045 | ||
| 2046 | /* Display the help-echo property of the character after the mouse pointer. | 2046 | /* Display the help-echo property of the character after the mouse pointer. |
| @@ -5254,7 +5254,6 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, | |||
| 5254 | extra_info))); | 5254 | extra_info))); |
| 5255 | } | 5255 | } |
| 5256 | 5256 | ||
| 5257 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 5258 | else if (f) | 5257 | else if (f) |
| 5259 | { | 5258 | { |
| 5260 | /* Return mouse pixel coordinates here. */ | 5259 | /* Return mouse pixel coordinates here. */ |
| @@ -5262,7 +5261,9 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, | |||
| 5262 | xret = XFIXNUM (x); | 5261 | xret = XFIXNUM (x); |
| 5263 | yret = XFIXNUM (y); | 5262 | yret = XFIXNUM (y); |
| 5264 | 5263 | ||
| 5265 | if (FRAME_LIVE_P (f) | 5264 | #ifdef HAVE_WINDOW_SYSTEM |
| 5265 | if (FRAME_WINDOW_P (f) | ||
| 5266 | && FRAME_LIVE_P (f) | ||
| 5266 | && FRAME_INTERNAL_BORDER_WIDTH (f) > 0 | 5267 | && FRAME_INTERNAL_BORDER_WIDTH (f) > 0 |
| 5267 | && !NILP (get_frame_param (f, Qdrag_internal_border))) | 5268 | && !NILP (get_frame_param (f, Qdrag_internal_border))) |
| 5268 | { | 5269 | { |
| @@ -5271,8 +5272,8 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, | |||
| 5271 | 5272 | ||
| 5272 | posn = builtin_lisp_symbol (internal_border_parts[part]); | 5273 | posn = builtin_lisp_symbol (internal_border_parts[part]); |
| 5273 | } | 5274 | } |
| 5274 | } | ||
| 5275 | #endif | 5275 | #endif |
| 5276 | } | ||
| 5276 | 5277 | ||
| 5277 | else | 5278 | else |
| 5278 | window_or_frame = Qnil; | 5279 | window_or_frame = Qnil; |
| @@ -7855,7 +7856,7 @@ parse_menu_item (Lisp_Object item, int inmenubar) | |||
| 7855 | /* The previous code preferred :key-sequence to :keys, so we | 7856 | /* The previous code preferred :key-sequence to :keys, so we |
| 7856 | preserve this behavior. */ | 7857 | preserve this behavior. */ |
| 7857 | if (STRINGP (keyeq) && !CONSP (keyhint)) | 7858 | if (STRINGP (keyeq) && !CONSP (keyhint)) |
| 7858 | keyeq = concat2 (space_space, Fsubstitute_command_keys (keyeq)); | 7859 | keyeq = concat2 (space_space, call1 (Qsubstitute_command_keys, keyeq)); |
| 7859 | else | 7860 | else |
| 7860 | { | 7861 | { |
| 7861 | Lisp_Object prefix = keyeq; | 7862 | Lisp_Object prefix = keyeq; |
diff --git a/src/keymap.c b/src/keymap.c index 0608bdddeea..e5b4781076f 100644 --- a/src/keymap.c +++ b/src/keymap.c | |||
| @@ -89,11 +89,6 @@ static Lisp_Object where_is_cache_keymaps; | |||
| 89 | static Lisp_Object store_in_keymap (Lisp_Object, Lisp_Object, Lisp_Object); | 89 | static Lisp_Object store_in_keymap (Lisp_Object, Lisp_Object, Lisp_Object); |
| 90 | 90 | ||
| 91 | static Lisp_Object define_as_prefix (Lisp_Object, Lisp_Object); | 91 | static Lisp_Object define_as_prefix (Lisp_Object, Lisp_Object); |
| 92 | static void describe_command (Lisp_Object, Lisp_Object); | ||
| 93 | static void describe_translation (Lisp_Object, Lisp_Object); | ||
| 94 | static void describe_map (Lisp_Object, Lisp_Object, | ||
| 95 | void (*) (Lisp_Object, Lisp_Object), | ||
| 96 | bool, Lisp_Object, Lisp_Object *, bool, bool); | ||
| 97 | static void describe_vector (Lisp_Object, Lisp_Object, Lisp_Object, | 92 | static void describe_vector (Lisp_Object, Lisp_Object, Lisp_Object, |
| 98 | void (*) (Lisp_Object, Lisp_Object), bool, | 93 | void (*) (Lisp_Object, Lisp_Object), bool, |
| 99 | Lisp_Object, Lisp_Object, bool, bool); | 94 | Lisp_Object, Lisp_Object, bool, bool); |
| @@ -679,6 +674,23 @@ usage: (map-keymap FUNCTION KEYMAP) */) | |||
| 679 | return Qnil; | 674 | return Qnil; |
| 680 | } | 675 | } |
| 681 | 676 | ||
| 677 | DEFUN ("keymap--get-keyelt", Fkeymap__get_keyelt, Skeymap__get_keyelt, 2, 2, 0, | ||
| 678 | doc: /* Given OBJECT which was found in a slot in a keymap, | ||
| 679 | trace indirect definitions to get the actual definition of that slot. | ||
| 680 | An indirect definition is a list of the form | ||
| 681 | (KEYMAP . INDEX), where KEYMAP is a keymap or a symbol defined as one | ||
| 682 | and INDEX is the object to look up in KEYMAP to yield the definition. | ||
| 683 | |||
| 684 | Also if OBJECT has a menu string as the first element, | ||
| 685 | remove that. Also remove a menu help string as second element. | ||
| 686 | |||
| 687 | If AUTOLOAD, load autoloadable keymaps | ||
| 688 | that are referred to with indirection. */) | ||
| 689 | (Lisp_Object object, Lisp_Object autoload) | ||
| 690 | { | ||
| 691 | return get_keyelt (object, NILP (autoload) ? false : true); | ||
| 692 | } | ||
| 693 | |||
| 682 | /* Given OBJECT which was found in a slot in a keymap, | 694 | /* Given OBJECT which was found in a slot in a keymap, |
| 683 | trace indirect definitions to get the actual definition of that slot. | 695 | trace indirect definitions to get the actual definition of that slot. |
| 684 | An indirect definition is a list of the form | 696 | An indirect definition is a list of the form |
| @@ -2733,7 +2745,7 @@ The optional argument MENUS, if non-nil, says to mention menu bindings. | |||
| 2733 | (Lisp_Object buffer, Lisp_Object prefix, Lisp_Object menus) | 2745 | (Lisp_Object buffer, Lisp_Object prefix, Lisp_Object menus) |
| 2734 | { | 2746 | { |
| 2735 | Lisp_Object outbuf, shadow; | 2747 | Lisp_Object outbuf, shadow; |
| 2736 | bool nomenu = NILP (menus); | 2748 | Lisp_Object nomenu = NILP (menus) ? Qt : Qnil; |
| 2737 | Lisp_Object start1; | 2749 | Lisp_Object start1; |
| 2738 | 2750 | ||
| 2739 | const char *alternate_heading | 2751 | const char *alternate_heading |
| @@ -2782,9 +2794,13 @@ You type Translation\n\ | |||
| 2782 | } | 2794 | } |
| 2783 | 2795 | ||
| 2784 | if (!NILP (Vkey_translation_map)) | 2796 | if (!NILP (Vkey_translation_map)) |
| 2785 | describe_map_tree (Vkey_translation_map, 0, Qnil, prefix, | 2797 | { |
| 2786 | "Key translations", nomenu, 1, 0, 0); | 2798 | Lisp_Object msg = build_unibyte_string ("Key translations"); |
| 2787 | 2799 | CALLN (Ffuncall, | |
| 2800 | Qdescribe_map_tree, | ||
| 2801 | Vkey_translation_map, Qnil, Qnil, prefix, | ||
| 2802 | msg, nomenu, Qt, Qnil, Qnil); | ||
| 2803 | } | ||
| 2788 | 2804 | ||
| 2789 | /* Print the (major mode) local map. */ | 2805 | /* Print the (major mode) local map. */ |
| 2790 | start1 = Qnil; | 2806 | start1 = Qnil; |
| @@ -2793,8 +2809,11 @@ You type Translation\n\ | |||
| 2793 | 2809 | ||
| 2794 | if (!NILP (start1)) | 2810 | if (!NILP (start1)) |
| 2795 | { | 2811 | { |
| 2796 | describe_map_tree (start1, 1, shadow, prefix, | 2812 | Lisp_Object msg = build_unibyte_string ("\f\nOverriding Bindings"); |
| 2797 | "\f\nOverriding Bindings", nomenu, 0, 0, 0); | 2813 | CALLN (Ffuncall, |
| 2814 | Qdescribe_map_tree, | ||
| 2815 | start1, Qt, shadow, prefix, | ||
| 2816 | msg, nomenu, Qnil, Qnil, Qnil); | ||
| 2798 | shadow = Fcons (start1, shadow); | 2817 | shadow = Fcons (start1, shadow); |
| 2799 | start1 = Qnil; | 2818 | start1 = Qnil; |
| 2800 | } | 2819 | } |
| @@ -2803,8 +2822,11 @@ You type Translation\n\ | |||
| 2803 | 2822 | ||
| 2804 | if (!NILP (start1)) | 2823 | if (!NILP (start1)) |
| 2805 | { | 2824 | { |
| 2806 | describe_map_tree (start1, 1, shadow, prefix, | 2825 | Lisp_Object msg = build_unibyte_string ("\f\nOverriding Bindings"); |
| 2807 | "\f\nOverriding Bindings", nomenu, 0, 0, 0); | 2826 | CALLN (Ffuncall, |
| 2827 | Qdescribe_map_tree, | ||
| 2828 | start1, Qt, shadow, prefix, | ||
| 2829 | msg, nomenu, Qnil, Qnil, Qnil); | ||
| 2808 | shadow = Fcons (start1, shadow); | 2830 | shadow = Fcons (start1, shadow); |
| 2809 | } | 2831 | } |
| 2810 | else | 2832 | else |
| @@ -2824,9 +2846,11 @@ You type Translation\n\ | |||
| 2824 | XBUFFER (buffer), Qkeymap); | 2846 | XBUFFER (buffer), Qkeymap); |
| 2825 | if (!NILP (start1)) | 2847 | if (!NILP (start1)) |
| 2826 | { | 2848 | { |
| 2827 | describe_map_tree (start1, 1, shadow, prefix, | 2849 | Lisp_Object msg = build_unibyte_string ("\f\n`keymap' Property Bindings"); |
| 2828 | "\f\n`keymap' Property Bindings", nomenu, | 2850 | CALLN (Ffuncall, |
| 2829 | 0, 0, 0); | 2851 | Qdescribe_map_tree, |
| 2852 | start1, Qt, shadow, prefix, | ||
| 2853 | msg, nomenu, Qnil, Qnil, Qnil); | ||
| 2830 | shadow = Fcons (start1, shadow); | 2854 | shadow = Fcons (start1, shadow); |
| 2831 | } | 2855 | } |
| 2832 | 2856 | ||
| @@ -2835,7 +2859,7 @@ You type Translation\n\ | |||
| 2835 | { | 2859 | { |
| 2836 | /* The title for a minor mode keymap | 2860 | /* The title for a minor mode keymap |
| 2837 | is constructed at run time. | 2861 | is constructed at run time. |
| 2838 | We let describe_map_tree do the actual insertion | 2862 | We let describe-map-tree do the actual insertion |
| 2839 | because it takes care of other features when doing so. */ | 2863 | because it takes care of other features when doing so. */ |
| 2840 | char *title, *p; | 2864 | char *title, *p; |
| 2841 | 2865 | ||
| @@ -2855,8 +2879,11 @@ You type Translation\n\ | |||
| 2855 | p += strlen (" Minor Mode Bindings"); | 2879 | p += strlen (" Minor Mode Bindings"); |
| 2856 | *p = 0; | 2880 | *p = 0; |
| 2857 | 2881 | ||
| 2858 | describe_map_tree (maps[i], 1, shadow, prefix, | 2882 | Lisp_Object msg = build_unibyte_string (title); |
| 2859 | title, nomenu, 0, 0, 0); | 2883 | CALLN (Ffuncall, |
| 2884 | Qdescribe_map_tree, | ||
| 2885 | maps[i], Qt, shadow, prefix, | ||
| 2886 | msg, nomenu, Qnil, Qnil, Qnil); | ||
| 2860 | shadow = Fcons (maps[i], shadow); | 2887 | shadow = Fcons (maps[i], shadow); |
| 2861 | SAFE_FREE (); | 2888 | SAFE_FREE (); |
| 2862 | } | 2889 | } |
| @@ -2866,432 +2893,66 @@ You type Translation\n\ | |||
| 2866 | if (!NILP (start1)) | 2893 | if (!NILP (start1)) |
| 2867 | { | 2894 | { |
| 2868 | if (EQ (start1, BVAR (XBUFFER (buffer), keymap))) | 2895 | if (EQ (start1, BVAR (XBUFFER (buffer), keymap))) |
| 2869 | describe_map_tree (start1, 1, shadow, prefix, | ||
| 2870 | "\f\nMajor Mode Bindings", nomenu, 0, 0, 0); | ||
| 2871 | else | ||
| 2872 | describe_map_tree (start1, 1, shadow, prefix, | ||
| 2873 | "\f\n`local-map' Property Bindings", | ||
| 2874 | nomenu, 0, 0, 0); | ||
| 2875 | |||
| 2876 | shadow = Fcons (start1, shadow); | ||
| 2877 | } | ||
| 2878 | } | ||
| 2879 | |||
| 2880 | describe_map_tree (current_global_map, 1, shadow, prefix, | ||
| 2881 | "\f\nGlobal Bindings", nomenu, 0, 1, 0); | ||
| 2882 | |||
| 2883 | /* Print the function-key-map translations under this prefix. */ | ||
| 2884 | if (!NILP (KVAR (current_kboard, Vlocal_function_key_map))) | ||
| 2885 | describe_map_tree (KVAR (current_kboard, Vlocal_function_key_map), 0, Qnil, prefix, | ||
| 2886 | "\f\nFunction key map translations", nomenu, 1, 0, 0); | ||
| 2887 | |||
| 2888 | /* Print the input-decode-map translations under this prefix. */ | ||
| 2889 | if (!NILP (KVAR (current_kboard, Vinput_decode_map))) | ||
| 2890 | describe_map_tree (KVAR (current_kboard, Vinput_decode_map), 0, Qnil, prefix, | ||
| 2891 | "\f\nInput decoding map translations", nomenu, 1, 0, 0); | ||
| 2892 | |||
| 2893 | return Qnil; | ||
| 2894 | } | ||
| 2895 | |||
| 2896 | /* Insert a description of the key bindings in STARTMAP, | ||
| 2897 | followed by those of all maps reachable through STARTMAP. | ||
| 2898 | If PARTIAL, omit certain "uninteresting" commands | ||
| 2899 | (such as `undefined'). | ||
| 2900 | If SHADOW is non-nil, it is a list of maps; | ||
| 2901 | don't mention keys which would be shadowed by any of them. | ||
| 2902 | PREFIX, if non-nil, says mention only keys that start with PREFIX. | ||
| 2903 | TITLE, if not 0, is a string to insert at the beginning. | ||
| 2904 | TITLE should not end with a colon or a newline; we supply that. | ||
| 2905 | If NOMENU, then omit menu-bar commands. | ||
| 2906 | |||
| 2907 | If TRANSL, the definitions are actually key translations | ||
| 2908 | so print strings and vectors differently. | ||
| 2909 | |||
| 2910 | If ALWAYS_TITLE, print the title even if there are no maps | ||
| 2911 | to look through. | ||
| 2912 | |||
| 2913 | If MENTION_SHADOW, then when something is shadowed by SHADOW, | ||
| 2914 | don't omit it; instead, mention it but say it is shadowed. | ||
| 2915 | |||
| 2916 | Any inserted text ends in two newlines (used by `help-make-xrefs'). */ | ||
| 2917 | |||
| 2918 | void | ||
| 2919 | describe_map_tree (Lisp_Object startmap, bool partial, Lisp_Object shadow, | ||
| 2920 | Lisp_Object prefix, const char *title, bool nomenu, | ||
| 2921 | bool transl, bool always_title, bool mention_shadow) | ||
| 2922 | { | ||
| 2923 | Lisp_Object maps, orig_maps, seen, sub_shadows; | ||
| 2924 | bool something = 0; | ||
| 2925 | const char *key_heading | ||
| 2926 | = "\ | ||
| 2927 | key binding\n\ | ||
| 2928 | --- -------\n"; | ||
| 2929 | |||
| 2930 | orig_maps = maps = Faccessible_keymaps (startmap, prefix); | ||
| 2931 | seen = Qnil; | ||
| 2932 | sub_shadows = Qnil; | ||
| 2933 | |||
| 2934 | if (nomenu) | ||
| 2935 | { | ||
| 2936 | Lisp_Object list; | ||
| 2937 | |||
| 2938 | /* Delete from MAPS each element that is for the menu bar. */ | ||
| 2939 | for (list = maps; CONSP (list); list = XCDR (list)) | ||
| 2940 | { | ||
| 2941 | Lisp_Object elt, elt_prefix, tem; | ||
| 2942 | |||
| 2943 | elt = XCAR (list); | ||
| 2944 | elt_prefix = Fcar (elt); | ||
| 2945 | if (ASIZE (elt_prefix) >= 1) | ||
| 2946 | { | 2896 | { |
| 2947 | tem = Faref (elt_prefix, make_fixnum (0)); | 2897 | Lisp_Object msg = build_unibyte_string ("\f\nMajor Mode Bindings"); |
| 2948 | if (EQ (tem, Qmenu_bar)) | 2898 | CALLN (Ffuncall, |
| 2949 | maps = Fdelq (elt, maps); | 2899 | Qdescribe_map_tree, |
| 2900 | start1, Qt, shadow, prefix, | ||
| 2901 | msg, nomenu, Qnil, Qnil, Qnil); | ||
| 2950 | } | 2902 | } |
| 2951 | } | 2903 | else |
| 2952 | } | ||
| 2953 | |||
| 2954 | if (!NILP (maps) || always_title) | ||
| 2955 | { | ||
| 2956 | if (title) | ||
| 2957 | { | ||
| 2958 | insert_string (title); | ||
| 2959 | if (!NILP (prefix)) | ||
| 2960 | { | 2904 | { |
| 2961 | insert_string (" Starting With "); | 2905 | Lisp_Object msg = build_unibyte_string ("\f\n`local-map' Property Bindings"); |
| 2962 | insert1 (Fkey_description (prefix, Qnil)); | 2906 | CALLN (Ffuncall, |
| 2907 | Qdescribe_map_tree, | ||
| 2908 | start1, Qt, shadow, prefix, | ||
| 2909 | msg, nomenu, Qnil, Qnil, Qnil); | ||
| 2963 | } | 2910 | } |
| 2964 | insert_string (":\n"); | ||
| 2965 | } | ||
| 2966 | insert_string (key_heading); | ||
| 2967 | something = 1; | ||
| 2968 | } | ||
| 2969 | 2911 | ||
| 2970 | for (; CONSP (maps); maps = XCDR (maps)) | 2912 | shadow = Fcons (start1, shadow); |
| 2971 | { | ||
| 2972 | register Lisp_Object elt, elt_prefix, tail; | ||
| 2973 | |||
| 2974 | elt = XCAR (maps); | ||
| 2975 | elt_prefix = Fcar (elt); | ||
| 2976 | |||
| 2977 | sub_shadows = Flookup_key (shadow, elt_prefix, Qt); | ||
| 2978 | if (FIXNATP (sub_shadows)) | ||
| 2979 | sub_shadows = Qnil; | ||
| 2980 | else if (!KEYMAPP (sub_shadows) | ||
| 2981 | && !NILP (sub_shadows) | ||
| 2982 | && !(CONSP (sub_shadows) | ||
| 2983 | && KEYMAPP (XCAR (sub_shadows)))) | ||
| 2984 | /* If elt_prefix is bound to something that's not a keymap, | ||
| 2985 | it completely shadows this map, so don't | ||
| 2986 | describe this map at all. */ | ||
| 2987 | goto skip; | ||
| 2988 | |||
| 2989 | /* Maps we have already listed in this loop shadow this map. */ | ||
| 2990 | for (tail = orig_maps; !EQ (tail, maps); tail = XCDR (tail)) | ||
| 2991 | { | ||
| 2992 | Lisp_Object tem; | ||
| 2993 | tem = Fequal (Fcar (XCAR (tail)), elt_prefix); | ||
| 2994 | if (!NILP (tem)) | ||
| 2995 | sub_shadows = Fcons (XCDR (XCAR (tail)), sub_shadows); | ||
| 2996 | } | 2913 | } |
| 2997 | |||
| 2998 | describe_map (Fcdr (elt), elt_prefix, | ||
| 2999 | transl ? describe_translation : describe_command, | ||
| 3000 | partial, sub_shadows, &seen, nomenu, mention_shadow); | ||
| 3001 | |||
| 3002 | skip: ; | ||
| 3003 | } | 2914 | } |
| 3004 | 2915 | ||
| 3005 | if (something) | 2916 | Lisp_Object msg = build_unibyte_string ("\f\nGlobal Bindings"); |
| 3006 | insert_string ("\n"); | 2917 | CALLN (Ffuncall, |
| 3007 | } | 2918 | Qdescribe_map_tree, |
| 3008 | 2919 | current_global_map, Qt, shadow, prefix, | |
| 3009 | static int previous_description_column; | 2920 | msg, nomenu, Qnil, Qt, Qnil); |
| 3010 | |||
| 3011 | static void | ||
| 3012 | describe_command (Lisp_Object definition, Lisp_Object args) | ||
| 3013 | { | ||
| 3014 | register Lisp_Object tem1; | ||
| 3015 | ptrdiff_t column = current_column (); | ||
| 3016 | int description_column; | ||
| 3017 | 2921 | ||
| 3018 | /* If column 16 is no good, go to col 32; | 2922 | /* Print the function-key-map translations under this prefix. */ |
| 3019 | but don't push beyond that--go to next line instead. */ | 2923 | if (!NILP (KVAR (current_kboard, Vlocal_function_key_map))) |
| 3020 | if (column > 30) | ||
| 3021 | { | 2924 | { |
| 3022 | insert_char ('\n'); | 2925 | Lisp_Object msg = build_unibyte_string ("\f\nFunction key map translations"); |
| 3023 | description_column = 32; | 2926 | CALLN (Ffuncall, |
| 2927 | Qdescribe_map_tree, | ||
| 2928 | KVAR (current_kboard, Vlocal_function_key_map), Qnil, Qnil, prefix, | ||
| 2929 | msg, nomenu, Qt, Qt, Qt); | ||
| 3024 | } | 2930 | } |
| 3025 | else if (column > 14 || (column > 10 && previous_description_column == 32)) | ||
| 3026 | description_column = 32; | ||
| 3027 | else | ||
| 3028 | description_column = 16; | ||
| 3029 | |||
| 3030 | Findent_to (make_fixnum (description_column), make_fixnum (1)); | ||
| 3031 | previous_description_column = description_column; | ||
| 3032 | 2931 | ||
| 3033 | if (SYMBOLP (definition)) | 2932 | /* Print the input-decode-map translations under this prefix. */ |
| 2933 | if (!NILP (KVAR (current_kboard, Vinput_decode_map))) | ||
| 3034 | { | 2934 | { |
| 3035 | tem1 = SYMBOL_NAME (definition); | 2935 | Lisp_Object msg = build_unibyte_string ("\f\nInput decoding map translations"); |
| 3036 | insert1 (tem1); | 2936 | CALLN (Ffuncall, |
| 3037 | insert_string ("\n"); | 2937 | Qdescribe_map_tree, |
| 2938 | KVAR (current_kboard, Vinput_decode_map), Qnil, Qnil, prefix, | ||
| 2939 | msg, nomenu, Qt, Qnil, Qnil); | ||
| 3038 | } | 2940 | } |
| 3039 | else if (STRINGP (definition) || VECTORP (definition)) | 2941 | return Qnil; |
| 3040 | insert_string ("Keyboard Macro\n"); | ||
| 3041 | else if (KEYMAPP (definition)) | ||
| 3042 | insert_string ("Prefix Command\n"); | ||
| 3043 | else | ||
| 3044 | insert_string ("??\n"); | ||
| 3045 | } | 2942 | } |
| 3046 | 2943 | ||
| 3047 | static void | 2944 | static void |
| 3048 | describe_translation (Lisp_Object definition, Lisp_Object args) | 2945 | describe_vector_princ (Lisp_Object elt, Lisp_Object fun) |
| 3049 | { | 2946 | { |
| 3050 | register Lisp_Object tem1; | ||
| 3051 | |||
| 3052 | Findent_to (make_fixnum (16), make_fixnum (1)); | 2947 | Findent_to (make_fixnum (16), make_fixnum (1)); |
| 3053 | 2948 | call1 (fun, elt); | |
| 3054 | if (SYMBOLP (definition)) | 2949 | Fterpri (Qnil, Qnil); |
| 3055 | { | ||
| 3056 | tem1 = SYMBOL_NAME (definition); | ||
| 3057 | insert1 (tem1); | ||
| 3058 | insert_string ("\n"); | ||
| 3059 | } | ||
| 3060 | else if (STRINGP (definition) || VECTORP (definition)) | ||
| 3061 | { | ||
| 3062 | insert1 (Fkey_description (definition, Qnil)); | ||
| 3063 | insert_string ("\n"); | ||
| 3064 | } | ||
| 3065 | else if (KEYMAPP (definition)) | ||
| 3066 | insert_string ("Prefix Command\n"); | ||
| 3067 | else | ||
| 3068 | insert_string ("??\n"); | ||
| 3069 | } | ||
| 3070 | |||
| 3071 | /* describe_map puts all the usable elements of a sparse keymap | ||
| 3072 | into an array of `struct describe_map_elt', | ||
| 3073 | then sorts them by the events. */ | ||
| 3074 | |||
| 3075 | struct describe_map_elt | ||
| 3076 | { | ||
| 3077 | Lisp_Object event; | ||
| 3078 | Lisp_Object definition; | ||
| 3079 | bool shadowed; | ||
| 3080 | }; | ||
| 3081 | |||
| 3082 | /* qsort comparison function for sorting `struct describe_map_elt' by | ||
| 3083 | the event field. */ | ||
| 3084 | |||
| 3085 | static int | ||
| 3086 | describe_map_compare (const void *aa, const void *bb) | ||
| 3087 | { | ||
| 3088 | const struct describe_map_elt *a = aa, *b = bb; | ||
| 3089 | if (FIXNUMP (a->event) && FIXNUMP (b->event)) | ||
| 3090 | return ((XFIXNUM (a->event) > XFIXNUM (b->event)) | ||
| 3091 | - (XFIXNUM (a->event) < XFIXNUM (b->event))); | ||
| 3092 | if (!FIXNUMP (a->event) && FIXNUMP (b->event)) | ||
| 3093 | return 1; | ||
| 3094 | if (FIXNUMP (a->event) && !FIXNUMP (b->event)) | ||
| 3095 | return -1; | ||
| 3096 | if (SYMBOLP (a->event) && SYMBOLP (b->event)) | ||
| 3097 | /* Sort the keystroke names in the "natural" way, with (for | ||
| 3098 | instance) "<f2>" coming between "<f1>" and "<f11>". */ | ||
| 3099 | return string_version_cmp (SYMBOL_NAME (a->event), SYMBOL_NAME (b->event)); | ||
| 3100 | return 0; | ||
| 3101 | } | ||
| 3102 | |||
| 3103 | /* Describe the contents of map MAP, assuming that this map itself is | ||
| 3104 | reached by the sequence of prefix keys PREFIX (a string or vector). | ||
| 3105 | PARTIAL, SHADOW, NOMENU are as in `describe_map_tree' above. */ | ||
| 3106 | |||
| 3107 | static void | ||
| 3108 | describe_map (Lisp_Object map, Lisp_Object prefix, | ||
| 3109 | void (*elt_describer) (Lisp_Object, Lisp_Object), | ||
| 3110 | bool partial, Lisp_Object shadow, | ||
| 3111 | Lisp_Object *seen, bool nomenu, bool mention_shadow) | ||
| 3112 | { | ||
| 3113 | Lisp_Object tail, definition, event; | ||
| 3114 | Lisp_Object tem; | ||
| 3115 | Lisp_Object suppress; | ||
| 3116 | Lisp_Object kludge; | ||
| 3117 | bool first = 1; | ||
| 3118 | |||
| 3119 | /* These accumulate the values from sparse keymap bindings, | ||
| 3120 | so we can sort them and handle them in order. */ | ||
| 3121 | ptrdiff_t length_needed = 0; | ||
| 3122 | struct describe_map_elt *vect; | ||
| 3123 | ptrdiff_t slots_used = 0; | ||
| 3124 | ptrdiff_t i; | ||
| 3125 | |||
| 3126 | suppress = Qnil; | ||
| 3127 | |||
| 3128 | if (partial) | ||
| 3129 | suppress = intern ("suppress-keymap"); | ||
| 3130 | |||
| 3131 | /* This vector gets used to present single keys to Flookup_key. Since | ||
| 3132 | that is done once per keymap element, we don't want to cons up a | ||
| 3133 | fresh vector every time. */ | ||
| 3134 | kludge = make_nil_vector (1); | ||
| 3135 | definition = Qnil; | ||
| 3136 | |||
| 3137 | map = call1 (Qkeymap_canonicalize, map); | ||
| 3138 | |||
| 3139 | for (tail = map; CONSP (tail); tail = XCDR (tail)) | ||
| 3140 | length_needed++; | ||
| 3141 | |||
| 3142 | USE_SAFE_ALLOCA; | ||
| 3143 | SAFE_NALLOCA (vect, 1, length_needed); | ||
| 3144 | |||
| 3145 | for (tail = map; CONSP (tail); tail = XCDR (tail)) | ||
| 3146 | { | ||
| 3147 | maybe_quit (); | ||
| 3148 | |||
| 3149 | if (VECTORP (XCAR (tail)) | ||
| 3150 | || CHAR_TABLE_P (XCAR (tail))) | ||
| 3151 | describe_vector (XCAR (tail), | ||
| 3152 | prefix, Qnil, elt_describer, partial, shadow, map, | ||
| 3153 | 1, mention_shadow); | ||
| 3154 | else if (CONSP (XCAR (tail))) | ||
| 3155 | { | ||
| 3156 | bool this_shadowed = 0; | ||
| 3157 | |||
| 3158 | event = XCAR (XCAR (tail)); | ||
| 3159 | |||
| 3160 | /* Ignore bindings whose "prefix" are not really valid events. | ||
| 3161 | (We get these in the frames and buffers menu.) */ | ||
| 3162 | if (!(SYMBOLP (event) || FIXNUMP (event))) | ||
| 3163 | continue; | ||
| 3164 | |||
| 3165 | if (nomenu && EQ (event, Qmenu_bar)) | ||
| 3166 | continue; | ||
| 3167 | |||
| 3168 | definition = get_keyelt (XCDR (XCAR (tail)), 0); | ||
| 3169 | |||
| 3170 | /* Don't show undefined commands or suppressed commands. */ | ||
| 3171 | if (NILP (definition)) continue; | ||
| 3172 | if (SYMBOLP (definition) && partial) | ||
| 3173 | { | ||
| 3174 | tem = Fget (definition, suppress); | ||
| 3175 | if (!NILP (tem)) | ||
| 3176 | continue; | ||
| 3177 | } | ||
| 3178 | |||
| 3179 | /* Don't show a command that isn't really visible | ||
| 3180 | because a local definition of the same key shadows it. */ | ||
| 3181 | |||
| 3182 | ASET (kludge, 0, event); | ||
| 3183 | if (!NILP (shadow)) | ||
| 3184 | { | ||
| 3185 | tem = shadow_lookup (shadow, kludge, Qt, 0); | ||
| 3186 | if (!NILP (tem)) | ||
| 3187 | { | ||
| 3188 | /* If both bindings are keymaps, this key is a prefix key, | ||
| 3189 | so don't say it is shadowed. */ | ||
| 3190 | if (KEYMAPP (definition) && KEYMAPP (tem)) | ||
| 3191 | ; | ||
| 3192 | /* Avoid generating duplicate entries if the | ||
| 3193 | shadowed binding has the same definition. */ | ||
| 3194 | else if (mention_shadow && !EQ (tem, definition)) | ||
| 3195 | this_shadowed = 1; | ||
| 3196 | else | ||
| 3197 | continue; | ||
| 3198 | } | ||
| 3199 | } | ||
| 3200 | |||
| 3201 | tem = Flookup_key (map, kludge, Qt); | ||
| 3202 | if (!EQ (tem, definition)) continue; | ||
| 3203 | |||
| 3204 | vect[slots_used].event = event; | ||
| 3205 | vect[slots_used].definition = definition; | ||
| 3206 | vect[slots_used].shadowed = this_shadowed; | ||
| 3207 | slots_used++; | ||
| 3208 | } | ||
| 3209 | else if (EQ (XCAR (tail), Qkeymap)) | ||
| 3210 | { | ||
| 3211 | /* The same keymap might be in the structure twice, if we're | ||
| 3212 | using an inherited keymap. So skip anything we've already | ||
| 3213 | encountered. */ | ||
| 3214 | tem = Fassq (tail, *seen); | ||
| 3215 | if (CONSP (tem) && !NILP (Fequal (XCAR (tem), prefix))) | ||
| 3216 | break; | ||
| 3217 | *seen = Fcons (Fcons (tail, prefix), *seen); | ||
| 3218 | } | ||
| 3219 | } | ||
| 3220 | |||
| 3221 | /* If we found some sparse map events, sort them. */ | ||
| 3222 | |||
| 3223 | qsort (vect, slots_used, sizeof (struct describe_map_elt), | ||
| 3224 | describe_map_compare); | ||
| 3225 | |||
| 3226 | /* Now output them in sorted order. */ | ||
| 3227 | |||
| 3228 | for (i = 0; i < slots_used; i++) | ||
| 3229 | { | ||
| 3230 | Lisp_Object start, end; | ||
| 3231 | |||
| 3232 | if (first) | ||
| 3233 | { | ||
| 3234 | previous_description_column = 0; | ||
| 3235 | insert ("\n", 1); | ||
| 3236 | first = 0; | ||
| 3237 | } | ||
| 3238 | |||
| 3239 | ASET (kludge, 0, vect[i].event); | ||
| 3240 | start = vect[i].event; | ||
| 3241 | end = start; | ||
| 3242 | |||
| 3243 | definition = vect[i].definition; | ||
| 3244 | |||
| 3245 | /* Find consecutive chars that are identically defined. */ | ||
| 3246 | if (FIXNUMP (vect[i].event)) | ||
| 3247 | { | ||
| 3248 | while (i + 1 < slots_used | ||
| 3249 | && EQ (vect[i+1].event, make_fixnum (XFIXNUM (vect[i].event) + 1)) | ||
| 3250 | && !NILP (Fequal (vect[i + 1].definition, definition)) | ||
| 3251 | && vect[i].shadowed == vect[i + 1].shadowed) | ||
| 3252 | i++; | ||
| 3253 | end = vect[i].event; | ||
| 3254 | } | ||
| 3255 | |||
| 3256 | /* Now START .. END is the range to describe next. */ | ||
| 3257 | |||
| 3258 | /* Insert the string to describe the event START. */ | ||
| 3259 | insert1 (Fkey_description (kludge, prefix)); | ||
| 3260 | |||
| 3261 | if (!EQ (start, end)) | ||
| 3262 | { | ||
| 3263 | insert (" .. ", 4); | ||
| 3264 | |||
| 3265 | ASET (kludge, 0, end); | ||
| 3266 | /* Insert the string to describe the character END. */ | ||
| 3267 | insert1 (Fkey_description (kludge, prefix)); | ||
| 3268 | } | ||
| 3269 | |||
| 3270 | /* Print a description of the definition of this character. | ||
| 3271 | elt_describer will take care of spacing out far enough | ||
| 3272 | for alignment purposes. */ | ||
| 3273 | (*elt_describer) (vect[i].definition, Qnil); | ||
| 3274 | |||
| 3275 | if (vect[i].shadowed) | ||
| 3276 | { | ||
| 3277 | ptrdiff_t pt = max (PT - 1, BEG); | ||
| 3278 | |||
| 3279 | SET_PT (pt); | ||
| 3280 | insert_string ("\n (this binding is currently shadowed)"); | ||
| 3281 | pt = min (PT + 1, Z); | ||
| 3282 | SET_PT (pt); | ||
| 3283 | } | ||
| 3284 | } | ||
| 3285 | |||
| 3286 | SAFE_FREE (); | ||
| 3287 | } | 2950 | } |
| 3288 | 2951 | ||
| 3289 | static void | 2952 | static void |
| 3290 | describe_vector_princ (Lisp_Object elt, Lisp_Object fun) | 2953 | describe_vector_basic (Lisp_Object elt, Lisp_Object fun) |
| 3291 | { | 2954 | { |
| 3292 | Findent_to (make_fixnum (16), make_fixnum (1)); | ||
| 3293 | call1 (fun, elt); | 2955 | call1 (fun, elt); |
| 3294 | Fterpri (Qnil, Qnil); | ||
| 3295 | } | 2956 | } |
| 3296 | 2957 | ||
| 3297 | DEFUN ("describe-vector", Fdescribe_vector, Sdescribe_vector, 1, 2, 0, | 2958 | DEFUN ("describe-vector", Fdescribe_vector, Sdescribe_vector, 1, 2, 0, |
| @@ -3311,8 +2972,40 @@ DESCRIBER is the output function used; nil means use `princ'. */) | |||
| 3311 | return unbind_to (count, Qnil); | 2972 | return unbind_to (count, Qnil); |
| 3312 | } | 2973 | } |
| 3313 | 2974 | ||
| 2975 | DEFUN ("help--describe-vector", Fhelp__describe_vector, Shelp__describe_vector, 7, 7, 0, | ||
| 2976 | doc: /* Insert in the current buffer a description of the contents of VECTOR. | ||
| 2977 | Call DESCRIBER to insert the description of one value found in VECTOR. | ||
| 2978 | |||
| 2979 | PREFIX is a string describing the key which leads to the keymap that | ||
| 2980 | this vector is in. | ||
| 2981 | |||
| 2982 | If PARTIAL, it means do not mention suppressed commands. | ||
| 2983 | |||
| 2984 | SHADOW is a list of keymaps that shadow this map. | ||
| 2985 | If it is non-nil, look up the key in those maps and don't mention it | ||
| 2986 | if it is defined by any of them. | ||
| 2987 | |||
| 2988 | ENTIRE-MAP is the keymap in which this vector appears. | ||
| 2989 | If the definition in effect in the whole map does not match | ||
| 2990 | the one in this keymap, we ignore this one. */) | ||
| 2991 | (Lisp_Object vector, Lisp_Object prefix, Lisp_Object describer, | ||
| 2992 | Lisp_Object partial, Lisp_Object shadow, Lisp_Object entire_map, | ||
| 2993 | Lisp_Object mention_shadow) | ||
| 2994 | { | ||
| 2995 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 2996 | specbind (Qstandard_output, Fcurrent_buffer ()); | ||
| 2997 | CHECK_VECTOR_OR_CHAR_TABLE (vector); | ||
| 2998 | |||
| 2999 | bool b_partial = NILP (partial) ? false : true; | ||
| 3000 | bool b_mention_shadow = NILP (mention_shadow) ? false : true; | ||
| 3001 | |||
| 3002 | describe_vector (vector, prefix, describer, describe_vector_basic, b_partial, | ||
| 3003 | shadow, entire_map, true, b_mention_shadow); | ||
| 3004 | return unbind_to (count, Qnil); | ||
| 3005 | } | ||
| 3006 | |||
| 3314 | /* Insert in the current buffer a description of the contents of VECTOR. | 3007 | /* Insert in the current buffer a description of the contents of VECTOR. |
| 3315 | We call ELT_DESCRIBER to insert the description of one value found | 3008 | Call ELT_DESCRIBER to insert the description of one value found |
| 3316 | in VECTOR. | 3009 | in VECTOR. |
| 3317 | 3010 | ||
| 3318 | ELT_PREFIX describes what "comes before" the keys or indices defined | 3011 | ELT_PREFIX describes what "comes before" the keys or indices defined |
| @@ -3568,6 +3261,7 @@ void | |||
| 3568 | syms_of_keymap (void) | 3261 | syms_of_keymap (void) |
| 3569 | { | 3262 | { |
| 3570 | DEFSYM (Qkeymap, "keymap"); | 3263 | DEFSYM (Qkeymap, "keymap"); |
| 3264 | DEFSYM (Qdescribe_map_tree, "describe-map-tree"); | ||
| 3571 | staticpro (&apropos_predicate); | 3265 | staticpro (&apropos_predicate); |
| 3572 | staticpro (&apropos_accumulate); | 3266 | staticpro (&apropos_accumulate); |
| 3573 | apropos_predicate = Qnil; | 3267 | apropos_predicate = Qnil; |
| @@ -3708,6 +3402,8 @@ be preferred. */); | |||
| 3708 | defsubr (&Scurrent_active_maps); | 3402 | defsubr (&Scurrent_active_maps); |
| 3709 | defsubr (&Saccessible_keymaps); | 3403 | defsubr (&Saccessible_keymaps); |
| 3710 | defsubr (&Skey_description); | 3404 | defsubr (&Skey_description); |
| 3405 | defsubr (&Skeymap__get_keyelt); | ||
| 3406 | defsubr (&Shelp__describe_vector); | ||
| 3711 | defsubr (&Sdescribe_vector); | 3407 | defsubr (&Sdescribe_vector); |
| 3712 | defsubr (&Ssingle_key_description); | 3408 | defsubr (&Ssingle_key_description); |
| 3713 | defsubr (&Stext_char_description); | 3409 | defsubr (&Stext_char_description); |
diff --git a/src/keymap.h b/src/keymap.h index 3ef48fb748e..2f7df2bd955 100644 --- a/src/keymap.h +++ b/src/keymap.h | |||
| @@ -36,8 +36,6 @@ extern Lisp_Object current_global_map; | |||
| 36 | extern char *push_key_description (EMACS_INT, char *); | 36 | extern char *push_key_description (EMACS_INT, char *); |
| 37 | extern Lisp_Object access_keymap (Lisp_Object, Lisp_Object, bool, bool, bool); | 37 | extern Lisp_Object access_keymap (Lisp_Object, Lisp_Object, bool, bool, bool); |
| 38 | extern Lisp_Object get_keymap (Lisp_Object, bool, bool); | 38 | extern Lisp_Object get_keymap (Lisp_Object, bool, bool); |
| 39 | extern void describe_map_tree (Lisp_Object, bool, Lisp_Object, Lisp_Object, | ||
| 40 | const char *, bool, bool, bool, bool); | ||
| 41 | extern ptrdiff_t current_minor_maps (Lisp_Object **, Lisp_Object **); | 39 | extern ptrdiff_t current_minor_maps (Lisp_Object **, Lisp_Object **); |
| 42 | extern void initial_define_key (Lisp_Object, int, const char *); | 40 | extern void initial_define_key (Lisp_Object, int, const char *); |
| 43 | extern void initial_define_lispy_key (Lisp_Object, const char *, const char *); | 41 | extern void initial_define_lispy_key (Lisp_Object, const char *, const char *); |
diff --git a/src/lread.c b/src/lread.c index 6aab470eb2f..015bcc2e11b 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -2667,6 +2667,13 @@ read_escape (Lisp_Object readcharfun, bool stringp) | |||
| 2667 | while (++count <= unicode_hex_count) | 2667 | while (++count <= unicode_hex_count) |
| 2668 | { | 2668 | { |
| 2669 | c = READCHAR; | 2669 | c = READCHAR; |
| 2670 | if (c < 0) | ||
| 2671 | { | ||
| 2672 | if (unicode_hex_count > 4) | ||
| 2673 | error ("Malformed Unicode escape: \\U%x", i); | ||
| 2674 | else | ||
| 2675 | error ("Malformed Unicode escape: \\u%x", i); | ||
| 2676 | } | ||
| 2670 | /* `isdigit' and `isalpha' may be locale-specific, which we don't | 2677 | /* `isdigit' and `isalpha' may be locale-specific, which we don't |
| 2671 | want. */ | 2678 | want. */ |
| 2672 | int digit = char_hexdigit (c); | 2679 | int digit = char_hexdigit (c); |
diff --git a/src/nsterm.m b/src/nsterm.m index a702a051d00..fa38350a2f6 100644 --- a/src/nsterm.m +++ b/src/nsterm.m | |||
| @@ -3048,6 +3048,12 @@ ns_clear_under_internal_border (struct frame *f) | |||
| 3048 | if (!face) | 3048 | if (!face) |
| 3049 | face = FRAME_DEFAULT_FACE (f); | 3049 | face = FRAME_DEFAULT_FACE (f); |
| 3050 | 3050 | ||
| 3051 | /* Sometimes with new frames we reach this point and have no | ||
| 3052 | face. I'm not sure why we have a live frame but no face, so | ||
| 3053 | just give up. */ | ||
| 3054 | if (!face) | ||
| 3055 | return; | ||
| 3056 | |||
| 3051 | ns_focus (f, &frame_rect, 1); | 3057 | ns_focus (f, &frame_rect, 1); |
| 3052 | [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set]; | 3058 | [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set]; |
| 3053 | for (int i = 0; i < 4 ; i++) | 3059 | for (int i = 0; i < 4 ; i++) |
diff --git a/src/print.c b/src/print.c index 23d0625792c..9d839d6ba66 100644 --- a/src/print.c +++ b/src/print.c | |||
| @@ -941,7 +941,7 @@ print_error_message (Lisp_Object data, Lisp_Object stream, const char *context, | |||
| 941 | else | 941 | else |
| 942 | { | 942 | { |
| 943 | Lisp_Object error_conditions = Fget (errname, Qerror_conditions); | 943 | Lisp_Object error_conditions = Fget (errname, Qerror_conditions); |
| 944 | errmsg = Fsubstitute_command_keys (Fget (errname, Qerror_message)); | 944 | errmsg = call1 (Qsubstitute_command_keys, Fget (errname, Qerror_message)); |
| 945 | file_error = Fmemq (Qfile_error, error_conditions); | 945 | file_error = Fmemq (Qfile_error, error_conditions); |
| 946 | } | 946 | } |
| 947 | 947 | ||
diff --git a/src/search.c b/src/search.c index 6fb3716cd43..e7f90949464 100644 --- a/src/search.c +++ b/src/search.c | |||
| @@ -2748,7 +2748,7 @@ since only regular expressions have distinguished subexpressions. */) | |||
| 2748 | 2748 | ||
| 2749 | /* Put point back where it was in the text, if possible. */ | 2749 | /* Put point back where it was in the text, if possible. */ |
| 2750 | TEMP_SET_PT (clip_to_bounds (BEGV, opoint + (opoint <= 0 ? ZV : 0), ZV)); | 2750 | TEMP_SET_PT (clip_to_bounds (BEGV, opoint + (opoint <= 0 ? ZV : 0), ZV)); |
| 2751 | /* Now move point "officially" to the start of the inserted replacement. */ | 2751 | /* Now move point "officially" to the end of the inserted replacement. */ |
| 2752 | move_if_not_intangible (newpoint); | 2752 | move_if_not_intangible (newpoint); |
| 2753 | 2753 | ||
| 2754 | return Qnil; | 2754 | return Qnil; |
diff --git a/src/syntax.c b/src/syntax.c index 066972e6d88..df07809aaaf 100644 --- a/src/syntax.c +++ b/src/syntax.c | |||
| @@ -1421,7 +1421,7 @@ DEFUN ("internal-describe-syntax-value", Finternal_describe_syntax_value, | |||
| 1421 | { | 1421 | { |
| 1422 | AUTO_STRING (prefixdoc, | 1422 | AUTO_STRING (prefixdoc, |
| 1423 | ",\n\t is a prefix character for `backward-prefix-chars'"); | 1423 | ",\n\t is a prefix character for `backward-prefix-chars'"); |
| 1424 | insert1 (Fsubstitute_command_keys (prefixdoc)); | 1424 | insert1 (call1 (Qsubstitute_command_keys, prefixdoc)); |
| 1425 | } | 1425 | } |
| 1426 | 1426 | ||
| 1427 | return syntax; | 1427 | return syntax; |
diff --git a/src/xterm.c b/src/xterm.c index 2e0407aff40..98bb0ea8917 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -8949,8 +8949,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 8949 | #endif | 8949 | #endif |
| 8950 | #ifdef USE_GTK | 8950 | #ifdef USE_GTK |
| 8951 | if (!f | 8951 | if (!f |
| 8952 | && (f = any) | 8952 | && (f = any) |
| 8953 | && configureEvent.xconfigure.window == FRAME_X_WINDOW (f)) | 8953 | && configureEvent.xconfigure.window == FRAME_X_WINDOW (f) |
| 8954 | && FRAME_VISIBLE_P(f)) | ||
| 8954 | { | 8955 | { |
| 8955 | block_input (); | 8956 | block_input (); |
| 8956 | if (FRAME_X_DOUBLE_BUFFERED_P (f)) | 8957 | if (FRAME_X_DOUBLE_BUFFERED_P (f)) |
| @@ -8963,10 +8964,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 8963 | configureEvent.xconfigure.height); | 8964 | configureEvent.xconfigure.height); |
| 8964 | #endif | 8965 | #endif |
| 8965 | f = 0; | 8966 | f = 0; |
| 8966 | } | 8967 | } |
| 8967 | #endif | 8968 | #endif |
| 8968 | if (f) | 8969 | if (f && FRAME_VISIBLE_P(f)) |
| 8969 | { | 8970 | { |
| 8970 | #ifdef USE_GTK | 8971 | #ifdef USE_GTK |
| 8971 | /* For GTK+ don't call x_net_wm_state for the scroll bar | 8972 | /* For GTK+ don't call x_net_wm_state for the scroll bar |
| 8972 | window. (Bug#24963, Bug#25887) */ | 8973 | window. (Bug#24963, Bug#25887) */ |
| @@ -9056,7 +9057,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, | |||
| 9056 | xic_set_statusarea (f); | 9057 | xic_set_statusarea (f); |
| 9057 | #endif | 9058 | #endif |
| 9058 | 9059 | ||
| 9059 | } | 9060 | } |
| 9060 | goto OTHER; | 9061 | goto OTHER; |
| 9061 | 9062 | ||
| 9062 | case ButtonRelease: | 9063 | case ButtonRelease: |