aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrea Corallo2020-10-23 20:08:58 +0100
committerAndrea Corallo2020-10-23 20:08:58 +0100
commit99e7cc0da652bf0f19f691d5de3b3ce7c15e8c39 (patch)
treee7c4921579cfeac379b649f27c2da78fed8aae48 /src
parent3be93390fb6680d1e0c3256af72c86635a9eb327 (diff)
parent46f5d2867cf73a845d582eeb8929ae51b78eae55 (diff)
downloademacs-99e7cc0da652bf0f19f691d5de3b3ce7c15e8c39.tar.gz
emacs-99e7cc0da652bf0f19f691d5de3b3ce7c15e8c39.zip
Merge remote-tracking branch 'savannah/master' into HEAD
Diffstat (limited to 'src')
-rw-r--r--src/dired.c8
-rw-r--r--src/doc.c321
-rw-r--r--src/eval.c5
-rw-r--r--src/ftcrfont.c16
-rw-r--r--src/image.c46
-rw-r--r--src/keyboard.c11
-rw-r--r--src/keymap.c540
-rw-r--r--src/keymap.h2
-rw-r--r--src/lread.c7
-rw-r--r--src/nsterm.m6
-rw-r--r--src/print.c2
-rw-r--r--src/search.c2
-rw-r--r--src/syntax.c2
-rw-r--r--src/xterm.c13
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,
293There are three optional arguments: 293There are three optional arguments:
294If FULL is non-nil, return absolute file names. Otherwise return names 294If 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.
296If MATCH is non-nil, mention only file names that match the regexp MATCH. 296If MATCH is non-nil, mention only file names whose non-directory part
297 matches the regexp MATCH.
297If NOSORT is non-nil, the list is not sorted--its order is unpredictable. 298If 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'.
325This function accepts four optional arguments: 326This function accepts four optional arguments:
326If FULL is non-nil, return absolute file names. Otherwise return names 327If 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.
328If MATCH is non-nil, mention only file names that match the regexp MATCH. 329If MATCH is non-nil, mention only file names whose non-directory part
330 matches the regexp MATCH.
329If NOSORT is non-nil, the list is not sorted--its order is unpredictable. 331If 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.
331ID-FORMAT specifies the preferred format of attributes uid and gid, see 333ID-FORMAT specifies the preferred format of attributes uid and gid, see
332`file-attributes' for further documentation. 334 `file-attributes' for further documentation.
333On MS-Windows, performance depends on `w32-get-true-file-attributes', 335On MS-Windows, performance depends on `w32-get-true-file-attributes',
334which see. */) 336which see. */)
335 (Lisp_Object directory, Lisp_Object full, Lisp_Object match, 337 (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
diff --git a/src/doc.c b/src/doc.c
index 8a4f885cc7e..d4e3ce2afea 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -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
705DEFUN ("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, 706DEFUN ("get-quoting-style", Fget_quoting_style,
707 doc: /* Substitute key descriptions for command names in STRING. 707 Sget_quoting_style, 0, 0, 0,
708Each substring of the form \\=\\[COMMAND] is replaced by either a 708 doc: /* Return the current effective text quoting style.
709keystroke sequence that invokes COMMAND, or "M-x COMMAND" if COMMAND 709See variable `text-quoting-style'. */)
710is not on any keys. 710 (void)
711
712Each substring of the form \\=\\{MAPVAR} is replaced by a summary of
713the value of MAPVAR as a keymap. This summary is similar to the one
714produced by `describe-bindings'. The summary ends in two newlines
715\(used by the helper function `help-make-xrefs' to find the end of the
716summary).
717
718Each substring of the form \\=\\<MAPVAR> specifies the use of MAPVAR
719as the keymap for future \\=\\[COMMAND] substrings.
720
721Each grave accent \\=` is replaced by left quote, and each apostrophe \\='
722is replaced by right quote. Left and right quote characters are
723specified by `text-quoting-style'.
724
725\\=\\= quotes the following character and is discarded; thus, \\=\\=\\=\\= puts \\=\\=
726into the output, \\=\\=\\=\\[ puts \\=\\[ into the output, and \\=\\=\\=` puts \\=` into the
727output.
728
729Return the original STRING if no substitutions are made.
730Otherwise, 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
1008void 725void
1009syms_of_doc (void) 726syms_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) */)
553DEFUN ("function", Ffunction, Sfunction, 1, UNEVALLED, 0, 553DEFUN ("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.
555In byte compilation, `function' causes its argument to be handled by 555In byte compilation, `function' causes its argument to be handled by
556the byte compiler. `quote' cannot do that. 556the byte compiler. Similarly, when expanding macros and expressions,
557ARG can be examined and possibly expanded. If `quote' is used
558instead, this doesn't happen.
559
557usage: (function ARG) */) 560usage: (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;
89static Lisp_Object store_in_keymap (Lisp_Object, Lisp_Object, Lisp_Object); 89static Lisp_Object store_in_keymap (Lisp_Object, Lisp_Object, Lisp_Object);
90 90
91static Lisp_Object define_as_prefix (Lisp_Object, Lisp_Object); 91static Lisp_Object define_as_prefix (Lisp_Object, Lisp_Object);
92static void describe_command (Lisp_Object, Lisp_Object);
93static void describe_translation (Lisp_Object, Lisp_Object);
94static void describe_map (Lisp_Object, Lisp_Object,
95 void (*) (Lisp_Object, Lisp_Object),
96 bool, Lisp_Object, Lisp_Object *, bool, bool);
97static void describe_vector (Lisp_Object, Lisp_Object, Lisp_Object, 92static 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
677DEFUN ("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,
679trace indirect definitions to get the actual definition of that slot.
680An indirect definition is a list of the form
681(KEYMAP . INDEX), where KEYMAP is a keymap or a symbol defined as one
682and INDEX is the object to look up in KEYMAP to yield the definition.
683
684Also if OBJECT has a menu string as the first element,
685remove that. Also remove a menu help string as second element.
686
687If AUTOLOAD, load autoloadable keymaps
688that 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
2918void
2919describe_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 = "\
2927key 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,
3009static int previous_description_column; 2920 msg, nomenu, Qnil, Qt, Qnil);
3010
3011static void
3012describe_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
3047static void 2944static void
3048describe_translation (Lisp_Object definition, Lisp_Object args) 2945describe_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
3075struct 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
3085static int
3086describe_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
3107static void
3108describe_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
3289static void 2952static void
3290describe_vector_princ (Lisp_Object elt, Lisp_Object fun) 2953describe_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
3297DEFUN ("describe-vector", Fdescribe_vector, Sdescribe_vector, 1, 2, 0, 2958DEFUN ("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
2975DEFUN ("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.
2977Call DESCRIBER to insert the description of one value found in VECTOR.
2978
2979PREFIX is a string describing the key which leads to the keymap that
2980this vector is in.
2981
2982If PARTIAL, it means do not mention suppressed commands.
2983
2984SHADOW is a list of keymaps that shadow this map.
2985If it is non-nil, look up the key in those maps and don't mention it
2986if it is defined by any of them.
2987
2988ENTIRE-MAP is the keymap in which this vector appears.
2989If the definition in effect in the whole map does not match
2990the 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
3568syms_of_keymap (void) 3261syms_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;
36extern char *push_key_description (EMACS_INT, char *); 36extern char *push_key_description (EMACS_INT, char *);
37extern Lisp_Object access_keymap (Lisp_Object, Lisp_Object, bool, bool, bool); 37extern Lisp_Object access_keymap (Lisp_Object, Lisp_Object, bool, bool, bool);
38extern Lisp_Object get_keymap (Lisp_Object, bool, bool); 38extern Lisp_Object get_keymap (Lisp_Object, bool, bool);
39extern void describe_map_tree (Lisp_Object, bool, Lisp_Object, Lisp_Object,
40 const char *, bool, bool, bool, bool);
41extern ptrdiff_t current_minor_maps (Lisp_Object **, Lisp_Object **); 39extern ptrdiff_t current_minor_maps (Lisp_Object **, Lisp_Object **);
42extern void initial_define_key (Lisp_Object, int, const char *); 40extern void initial_define_key (Lisp_Object, int, const char *);
43extern void initial_define_lispy_key (Lisp_Object, const char *, const char *); 41extern 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: