]> code.delx.au - gnu-emacs/commitdiff
format-message now curves ` and '
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 26 Aug 2015 01:41:31 +0000 (18:41 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Wed, 26 Aug 2015 02:00:20 +0000 (19:00 -0700)
That way, the caller doesn’t have to use curved quotes to
get diagnostics that match the text-quoting-style preferences.
Suggested by Dmitry Gutov in:
http://lists.gnu.org/archive/html/emacs-devel/2015-08/msg00893.html
This means we no longer need %qs, so remove that format.
While we’re at it, fix an unlikely bug and lessen the pressure
on the garbage collector by processing the string once rather
than twice in the usual case.
* doc/lispref/strings.texi (Formatting Strings):
* etc/NEWS: Document this.
* lisp/subr.el (format-message): Remove; now done in C.
* src/callint.c (Fcall_interactively):
* src/editfns.c (Fmessage, Fmessage_box):
Use Fformat_message instead of Finternal__text_restyle
followed by Fformat.
* src/doc.c (LSQM, RSQM): Remove; all uses changed to use
uLSQM and uRSQM.
(Fsubstitute_command_keys): Prefer AUTO_STRING to build_string
when pure ASCII now suffices.  Fix unlikely bug when parsing
unibyte string containing non-ASCII bytes.  Use inline code
rather than memcpy, as it’s a tiny number of bytes.
(Finternal__text_restyle): Remove; no longer used.
(syms_of_doc): Don’t declare it.
* src/editfns.c (Fformat): Rewrite in terms of new function
‘styled_format’.
(Fformat_message): New function, moved here from subr.el.
(styled_format): New function, with the old guts of Fformat,
except it now optionally transliterates quotes, and it transliterates
traditional grave accent and apostrophe quoting as well.
Remove recently-added q flag; no longer needed or used.
(syms_of_editfns): Define format-message.
* src/lisp.h (uLSQM0, uLSQM1, uLSQM2, uRSQM0, uRSQM1, uRSQM2):
Remove; no longer need to be global symbols.
* src/xdisp.c (vadd_to_log): Use Fformat_message, not Fformat,
so that callers can use `%s'.
* src/image.c (image_size_error, xbm_load_image, xbm_load)
(xpm_load, pbm_load, png_load_body, jpeg_load_body, tiff_load)
(gif_load, imagemagick_load_image, imagemagick_load, svg_load)
(svg_load_image, gs_load, x_kill_gs_process):
* src/lread.c (load_warn_old_style_backquotes):
* src/xfaces.c (load_pixmap):
* src/xselect.c (x_clipboard_manager_error_1):
Use `%s' instead of %qs in formats.

12 files changed:
doc/lispref/strings.texi
etc/NEWS
lisp/subr.el
src/callint.c
src/doc.c
src/editfns.c
src/image.c
src/lisp.h
src/lread.c
src/xdisp.c
src/xfaces.c
src/xselect.c

index 326359e1da03bcd6b9ce074bb4f3a1cc8b6d78fb..08e8e877a9f1d077d8d2433df48752fd526ef286 100644 (file)
@@ -816,9 +816,13 @@ if any.
 @end defun
 
 @defun format-message string &rest objects
+@cindex curved quotes
+@cindex curly quotes
 This function acts like @code{format}, except it also converts any
-curved quotes in @var{string} as per the value of
-@code{text-quoting-style}.  @xref{Keys in Documentation}.
+curved single quotes in @var{string} as per the value of
+@code{text-quoting-style}, and treats grave accent (@t{`}) and
+apostrophe (@t{'}) as if they were curved single quotes.  @xref{Keys
+in Documentation}.
 @end defun
 
 @cindex @samp{%} in format
@@ -919,20 +923,23 @@ specification is unusual in that it does not use a value.  For example,
   Any other format character results in an @samp{Invalid format
 operation} error.
 
-  Here are several examples:
+  Here are several examples, which assume the typical
+@code{text-quoting-style} settings:
 
 @example
 @group
-(format "The name of this buffer is %s." (buffer-name))
-     @result{} "The name of this buffer is strings.texi."
-
-(format "The buffer object prints as %qs." (current-buffer))
-     @result{} "The buffer object prints as ‘strings.texi’."
-
 (format "The octal value of %d is %o,
          and the hex value is %x." 18 18 18)
      @result{} "The octal value of 18 is 22,
          and the hex value is 12."
+
+(format-message
+ "The name of this buffer is ‘%s’." (buffer-name))
+     @result{} "The name of this buffer is ‘strings.texi’."
+
+(format-message
+ "The buffer object prints as `%s'." (current-buffer))
+     @result{} "The buffer object prints as ‘strings.texi’."
 @end group
 @end example
 
@@ -1001,20 +1008,13 @@ specifier, if any, to be inserted on the right rather than the left.
 If both @samp{-} and @samp{0} are present, the @samp{0} flag is
 ignored.
 
-@cindex curved quotes
-@cindex curly quotes
-  The flag @samp{q} quotes the printed representation as per the
-variable @samp{text-quoting-style}.  @xref{Keys in Documentation}.
-Typically it uses curved single quotes @t{‘like this’} as in the
-following example.
-
 @example
 @group
 (format "%06d is padded on the left with zeros" 123)
      @result{} "000123 is padded on the left with zeros"
 
-(format "%q-6d is padded on the right" 123)
-     @result{} "‘123   ’ is padded on the right"
+(format "'%-6d' is padded on the right" 123)
+     @result{} "'123   ' is padded on the right"
 
 (format "The word '%-7s' actually has %d letters in it."
         "foo" (length "foo"))
index 89ab98d0692cf1ba3f902c2e4d74ebc8410248d1..4851c350f17444a754b895fcae9d19fede095735 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -272,7 +272,7 @@ successive char insertions.
 € № ← → ↔ − ≈ ≠ ≤ ≥.  As before, you can type C-x 8 C-h to list shorthands.
 
 ** New minor mode electric-quote-mode for quoting ‘like this’ and “like this”
-as you type.
+as you type.  See also the new variable ‘text-quoting-style’.
 
 ** New minor mode global-eldoc-mode is enabled by default.
 
@@ -916,20 +916,21 @@ Set it to ‘curve’ for curved single quotes ‘like this’, to ‘straight
 for straight apostrophes 'like this', and to ‘grave’ for grave accent
 and apostrophe `like this'.  The default value nil acts like ‘curve’
 if curved single quotes are displayable, and like ‘grave’ otherwise.
-Quotes in info files are not translated.
+The new variable affects display of diagnostics and help, but not of info.
 
 +++
 ** substitute-command-keys now replaces quotes.
 That is, it converts documentation strings’ quoting style as per the
 value of ‘text-quoting-style’.  Doc strings in source code can use
-either curved quotes or grave accent and apostrophe.  As before,
-characters preceded by \= are output as-is.
+either curved single quotes or grave accents and apostrophes.  As
+before, characters preceded by \= are output as-is.
 
 +++
 ** Message-issuing functions ‘error’, ‘message’, etc. now convert quotes.
 They use the new ‘format-message’ function instead of plain ‘format’,
-so that they now follow user preference as per ‘text-quoting-style’ if
-their format argument contains curved quotes.
+so that they now follow user preference as per ‘text-quoting-style’
+when processing curved single quotes, grave accents, and apostrophes
+in their format argument.
 
 +++
 ** The character classes [:alpha:] and [:alnum:] in regular expressions
@@ -1055,13 +1056,8 @@ quotes.
 
 +++
 ** New function ‘format-message’ is like ‘format’ and also converts
-curved quotes as per ‘text-quoting-style’.
-
-+++
-** New ‘format’ flag ‘q’
-The new ‘q’ flag causes ‘format’ to quote the output representation as
-per the value of ‘text-quoting-style’.  E.g., (format "%qs failed"
-"foo") might return "‘foo’ failed".
+curved single quotes, grave accents and apostrophes as per
+‘text-quoting-style’.
 
 +++
 ** show-help-function's arg is converted via substitute-command-keys
index 21e277bd647eec47cf6aebac592d295b30d7b8a0..53dea3e2997c949a02f6d9616e9a3e628b6621a9 100644 (file)
@@ -288,12 +288,6 @@ This function accepts any number of arguments, but ignores them."
   (interactive)
   nil)
 
-(defun format-message (format-string &rest args)
-  "Format a string out of FORMAT-STRING and arguments.
-This is like ‘format’, except it also converts curved quotes in
-FORMAT-STRING as per ‘text-quoting-style’."
-  (apply #'format (internal--text-restyle format-string) args))
-
 ;; Signal a compile-error if the first arg is missing.
 (defun error (&rest args)
   "Signal an error, making error message by passing all args to `format'.
index be0fb1a84dfb202f54c310cade394d585a618ade..e39f4dff2e4e4a19943b8080a86c89963adcf485 100644 (file)
@@ -511,9 +511,8 @@ invoke it.  If KEYS is omitted or nil, the return value of
   for (i = 2; *tem; i++)
     {
       visargs[1] = make_string (tem + 1, strcspn (tem + 1, "\n"));
-      visargs[1] = Finternal__text_restyle (visargs[1]);
       if (strchr (SSDATA (visargs[1]), '%'))
-       callint_message = Fformat (i - 1, visargs + 1);
+       callint_message = Fformat_message (i - 1, visargs + 1);
       else
        callint_message = visargs[1];
 
index 7a298e286319b77d20d67d14211d2a8156257903..637200f648e64484372d510c463df56ce4dac271 100644 (file)
--- a/src/doc.c
+++ b/src/doc.c
@@ -684,10 +684,7 @@ the same file name is found in the `doc-directory'.  */)
   return unbind_to (count, Qnil);
 }
 \f
-/* Curved quotation marks.  */
-static unsigned char const LSQM[] = { uLSQM0, uLSQM1, uLSQM2 };
-static unsigned char const RSQM[] = { uRSQM0, uRSQM1, uRSQM2 };
-
+/* Return true if text quoting style should default to quote `like this'.  */
 static bool
 default_to_grave_quoting_style (void)
 {
@@ -925,14 +922,13 @@ Otherwise, return a new string.  */)
          if (NILP (tem))
            {
              name = Fsymbol_name (name);
-             insert1 (Fsubstitute_command_keys
-                      (build_string ("\nUses keymap "uLSQM)));
+             AUTO_STRING (msg_prefix, "\nUses keymap `");
+             insert1 (Fsubstitute_command_keys (msg_prefix));
              insert_from_string (name, 0, 0,
                                  SCHARS (name),
                                  SBYTES (name), 1);
-             insert1 (Fsubstitute_command_keys
-                      (build_string
-                       (uRSQM", which is not currently defined.\n")));
+             AUTO_STRING (msg_suffix, "', which is not currently defined.\n");
+             insert1 (Fsubstitute_command_keys (msg_suffix));
              if (start[-1] == '<') keymap = Qnil;
            }
          else if (start[-1] == '<')
@@ -972,9 +968,9 @@ Otherwise, return a new string.  */)
       else if ((strp[0] == '`' || strp[0] == '\'')
               && quoting_style == CURVE_QUOTING_STYLE)
        {
-         start = strp[0] == '`' ? LSQM : RSQM;
+         start = (unsigned char const *) (strp[0] == '`' ? uLSQM : uRSQM);
          length = 1;
-         length_byte = 3;
+         length_byte = sizeof uLSQM - 1;
          idx = strp - SDATA (string) + 1;
          goto subst;
        }
@@ -985,29 +981,28 @@ Otherwise, return a new string.  */)
          nchars++;
          changed = true;
        }
-      else if (strp[0] == uLSQM0 && strp[1] == uLSQM1
-              && (strp[2] == uLSQM2 || strp[2] == uRSQM2)
-              && quoting_style != CURVE_QUOTING_STYLE)
-        {
-         *bufp++ = (strp[2] == uLSQM2 && quoting_style == GRAVE_QUOTING_STYLE
-                    ? '`' : '\'');
-         strp += 3;
-         nchars++;
-         changed = true;
-        }
-      else if (! multibyte)            /* just copy other chars */
+      else if (! multibyte)
        *bufp++ = *strp++, nchars++;
       else
        {
          int len;
-
-         STRING_CHAR_AND_LENGTH (strp, len);
-         if (len == 1)
-           *bufp = *strp;
+         int ch = STRING_CHAR_AND_LENGTH (strp, len);
+         if ((ch == LEFT_SINGLE_QUOTATION_MARK
+              || ch == RIGHT_SINGLE_QUOTATION_MARK)
+             && quoting_style != CURVE_QUOTING_STYLE)
+           {
+             *bufp++ = ((ch == LEFT_SINGLE_QUOTATION_MARK
+                         && quoting_style == GRAVE_QUOTING_STYLE)
+                        ? '`' : '\'');
+             strp += len;
+             changed = true;
+           }
          else
-           memcpy (bufp, strp, len);
-         strp += len;
-         bufp += len;
+           {
+             do
+               *bufp++ = *strp++;
+             while (--len != 0);
+           }
          nchars++;
        }
     }
@@ -1019,67 +1014,6 @@ Otherwise, return a new string.  */)
   xfree (buf);
   RETURN_UNGCPRO (tem);
 }
-
-DEFUN ("internal--text-restyle", Finternal__text_restyle,
-       Sinternal__text_restyle, 1, 1, 0,
-       doc: /* Return STRING, possibly substituting quote characters.
-
-In the result, replace each curved single quote (\\=‘ and \\=’) by
-left and right quote characters as specified by ‘text-quoting-style’.
-
-Return the original STRING in the common case where no changes are needed.
-Otherwise, return a new string.  */)
-  (Lisp_Object string)
-{
-  bool changed = false;
-
-  CHECK_STRING (string);
-  if (! STRING_MULTIBYTE (string))
-    return string;
-
-  enum text_quoting_style quoting_style = text_quoting_style ();
-  if (quoting_style == CURVE_QUOTING_STYLE)
-    return string;
-
-  ptrdiff_t bsize = SBYTES (string);
-  unsigned char const *strp = SDATA (string);
-  unsigned char const *strlim = strp + bsize;
-  USE_SAFE_ALLOCA;
-  char *buf = SAFE_ALLOCA (bsize);
-  char *bufp = buf;
-  ptrdiff_t nchars = 0;
-
-  while (strp < strlim)
-    {
-      unsigned char const *cp = strp;
-      switch (STRING_CHAR_ADVANCE (strp))
-       {
-       case LEFT_SINGLE_QUOTATION_MARK:
-         *bufp++ = quoting_style == GRAVE_QUOTING_STYLE ? '`': '\'';
-         changed = true;
-         break;
-
-       case RIGHT_SINGLE_QUOTATION_MARK:
-         *bufp++ = '\'';
-         changed = true;
-         break;
-
-       default:
-         do
-           *bufp++ = *cp++;
-         while (cp != strp);
-
-         break;
-       }
-
-      nchars++;
-    }
-
-  Lisp_Object result
-    = changed ? make_string_from_bytes (buf, nchars, bufp - buf) : string;
-  SAFE_FREE ();
-  return result;
-}
 \f
 void
 syms_of_doc (void)
@@ -1113,5 +1047,4 @@ displayable, and like ‘grave’ otherwise.  */);
   defsubr (&Sdocumentation_property);
   defsubr (&Ssnarf_documentation);
   defsubr (&Ssubstitute_command_keys);
-  defsubr (&Sinternal__text_restyle);
 }
index da7d554fd942fc481bf6bfa30b0448ec4261c99c..2703a5dbcb90ee62cb8ebdd60d9203b381debc87 100644 (file)
@@ -72,6 +72,7 @@ static Lisp_Object format_time_string (char const *, ptrdiff_t, struct timespec,
 static long int tm_gmtoff (struct tm *);
 static int tm_diff (struct tm *, struct tm *);
 static void update_buffer_properties (ptrdiff_t, ptrdiff_t);
+static Lisp_Object styled_format (ptrdiff_t, Lisp_Object *, bool);
 
 #ifndef HAVE_TM_GMTOFF
 # define HAVE_TM_GMTOFF false
@@ -3696,8 +3697,7 @@ usage: (message FORMAT-STRING &rest ARGS)  */)
     }
   else
     {
-      args[0] = Finternal__text_restyle (args[0]);
-      Lisp_Object val = Fformat (nargs, args);
+      Lisp_Object val = Fformat_message (nargs, args);
       message3 (val);
       return val;
     }
@@ -3722,8 +3722,7 @@ usage: (message-box FORMAT-STRING &rest ARGS)  */)
     }
   else
     {
-      args[0] = Finternal__text_restyle (args[0]);
-      Lisp_Object val = Fformat (nargs, args);
+      Lisp_Object val = Fformat_message (nargs, args);
       Lisp_Object pane, menu;
       struct gcpro gcpro1;
 
@@ -3822,7 +3821,7 @@ specifiers, as follows:
 
   %<flags><width><precision>character
 
-where flags is [+ #-0q]+, width is [0-9]+, and precision is .[0-9]+
+where flags is [+ #-0]+, width is [0-9]+, and precision is .[0-9]+
 
 The + flag character inserts a + before any positive number, while a
 space inserts a space before any positive number; these flags only
@@ -3835,9 +3834,6 @@ The # flag means to use an alternate display form for %o, %x, %X, %e,
 for %e, %f, and %g, it causes a decimal point to be included even if
 the precision is zero.
 
-The q flag means to quote the printed representation as per
-‘text-quoting-style’.  E.g., "%qs" is equivalent to "‘%s’".
-
 The width specifier supplies a lower limit for the length of the
 printed representation.  The padding, if any, normally goes on the
 left, but it goes on the right if the - flag is present.  The padding
@@ -3852,6 +3848,31 @@ specifier truncates the string to the given width.
 
 usage: (format STRING &rest OBJECTS)  */)
   (ptrdiff_t nargs, Lisp_Object *args)
+{
+  return styled_format (nargs, args, false);
+}
+
+DEFUN ("format-message", Fformat_message, Sformat_message, 1, MANY, 0,
+       doc: /* Format a string out of a format-string and arguments.
+The first argument is a format control string.
+The other arguments are substituted into it to make the result, a string.
+
+This acts like ‘format’, except it also replaces each left single
+quotation mark (\\=‘) and grave accent (\\=`) by a left quote, and each
+right single quotation mark (\\=’) and apostrophe (\\=') by a right quote.
+The left and right quote replacement characters are specified by
+‘text-quoting-style’.
+
+usage: (format-message STRING &rest OBJECTS)  */)
+  (ptrdiff_t nargs, Lisp_Object *args)
+{
+  return styled_format (nargs, args, true);
+}
+
+/* Implement ‘format-message’ if MESSAGE is true, ‘format’ otherwise.  */
+
+static Lisp_Object
+styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
 {
   ptrdiff_t n;         /* The number of the next arg to substitute.  */
   char initial_buffer[4000];
@@ -3917,7 +3938,8 @@ usage: (format STRING &rest OBJECTS)  */)
 
   /* Try to determine whether the result should be multibyte.
      This is not always right; sometimes the result needs to be multibyte
-     because of an object that we will pass through prin1,
+     because of an object that we will pass through prin1.
+     or because a grave accent or apostrophe is requoted,
      and in that case, we won't know it here.  */
   multibyte_format = STRING_MULTIBYTE (args[0]);
   multibyte = multibyte_format;
@@ -3925,7 +3947,7 @@ usage: (format STRING &rest OBJECTS)  */)
     if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n]))
       multibyte = 1;
 
-  enum text_quoting_style quoting_style = text_quoting_style ();
+  int quoting_style = message ? text_quoting_style () : -1;
 
   /* If we start out planning a unibyte result,
      then discover it has to be multibyte, we jump back to retry.  */
@@ -3945,11 +3967,13 @@ usage: (format STRING &rest OBJECTS)  */)
       /* The values of N and FORMAT when the loop body is entered.  */
       ptrdiff_t n0 = n;
       char *format0 = format;
+      char const *convsrc = format;
+      unsigned char format_char = *format++;
 
       /* Bytes needed to represent the output of this conversion.  */
-      ptrdiff_t convbytes;
+      ptrdiff_t convbytes = 1;
 
-      if (*format == '%')
+      if (format_char == '%')
        {
          /* General format specifications look like
 
@@ -3974,23 +3998,21 @@ usage: (format STRING &rest OBJECTS)  */)
          bool space_flag = false;
          bool sharp_flag = false;
          bool  zero_flag = false;
-         bool quote_flag = false;
          ptrdiff_t field_width;
          bool precision_given;
          uintmax_t precision = UINTMAX_MAX;
          char *num_end;
          char conversion;
 
-         while (1)
+         for (; ; format++)
            {
-             switch (*++format)
+             switch (*format)
                {
                case '-': minus_flag = true; continue;
                case '+':  plus_flag = true; continue;
                case ' ': space_flag = true; continue;
                case '#': sharp_flag = true; continue;
                case '0':  zero_flag = true; continue;
-               case 'q': quote_flag = true; continue;
                }
              break;
            }
@@ -4014,11 +4036,10 @@ usage: (format STRING &rest OBJECTS)  */)
            error ("Format string ends in middle of format specifier");
 
          memset (&discarded[format0 - format_start], 1, format - format0);
-         conversion = *format;
+         conversion = *format++;
          if (conversion == '%')
            goto copy_char;
          discarded[format - format_start] = 1;
-         format++;
 
          ++n;
          if (! (n < nargs))
@@ -4118,20 +4139,6 @@ usage: (format STRING &rest OBJECTS)  */)
              if (convbytes && multibyte && ! STRING_MULTIBYTE (args[n]))
                convbytes = count_size_as_multibyte (SDATA (args[n]), nbytes);
 
-             if (quote_flag)
-               {
-                 convbytes += 2;
-                 if (quoting_style == CURVE_QUOTING_STYLE)
-                   {
-                     if (!multibyte)
-                       {
-                         multibyte = true;
-                         goto retry;
-                       }
-                     convbytes += 4;
-                   }
-               }
-
              padding = width < field_width ? field_width - width : 0;
 
              if (max_bufsize - padding <= convbytes)
@@ -4139,27 +4146,6 @@ usage: (format STRING &rest OBJECTS)  */)
              convbytes += padding;
              if (convbytes <= buf + bufsize - p)
                {
-
-                 if (quote_flag)
-                   {
-                     switch (quoting_style)
-                       {
-                       case CURVE_QUOTING_STYLE:
-                         memcpy (p, uLSQM, 3);
-                         p += 3;
-                         break;
-
-                       case GRAVE_QUOTING_STYLE:
-                         *p++ = '`';
-                         break;
-
-                       case STRAIGHT_QUOTING_STYLE:
-                         *p++ = '\'';
-                         break;
-                       }
-                     nchars++;
-                   }
-
                  if (! minus_flag)
                    {
                      memset (p, ' ', padding);
@@ -4189,22 +4175,6 @@ usage: (format STRING &rest OBJECTS)  */)
                      nchars += padding;
                    }
 
-                 if (quote_flag)
-                   {
-                     switch (quoting_style)
-                       {
-                       case CURVE_QUOTING_STYLE:
-                         memcpy (p, uRSQM, 3);
-                         p += 3;
-                         break;
-
-                       default:
-                         *p++ = '\'';
-                         break;
-                       }
-                     nchars++;
-                   }
-
                  /* If this argument has text properties, record where
                     in the result string it appears.  */
                  if (string_intervals (args[n]))
@@ -4464,44 +4434,72 @@ usage: (format STRING &rest OBJECTS)  */)
            }
        }
       else
-      copy_char:
        {
-         /* Copy a single character from format to buf.  */
+         /* Named constants for the UTF-8 encodings of U+2018 LEFT SINGLE
+            QUOTATION MARK and U+2019 RIGHT SINGLE QUOTATION MARK.  */
+         enum
+         {
+           uLSQM0 = 0xE2, uLSQM1 = 0x80, uLSQM2 = 0x98,
+           /* uRSQM0 = 0xE2, uRSQM1 = 0x80, */ uRSQM2 = 0x99
+         };
 
-         char *src = format;
          unsigned char str[MAX_MULTIBYTE_LENGTH];
 
-         if (multibyte_format)
+         if ((format_char == '`' || format_char == '\'')
+             && quoting_style == CURVE_QUOTING_STYLE)
            {
-             /* Copy a whole multibyte character.  */
-             if (p > buf
-                 && !ASCII_CHAR_P (*((unsigned char *) p - 1))
-                 && !CHAR_HEAD_P (*format))
-               maybe_combine_byte = 1;
-
-             do
-               format++;
-             while (! CHAR_HEAD_P (*format));
-
-             convbytes = format - src;
-             memset (&discarded[src + 1 - format_start], 2, convbytes - 1);
+             if (! multibyte)
+               {
+                 multibyte = true;
+                 goto retry;
+               }
+             convsrc = format_char == '`' ? uLSQM : uRSQM;
+             convbytes = 3;
+           }
+         else if (format_char == '`' && quoting_style == STRAIGHT_QUOTING_STYLE)
+           convsrc = "'";
+         else if (format_char == uLSQM0 && CURVE_QUOTING_STYLE < quoting_style
+                  && multibyte_format
+                  && (unsigned char) format[0] == uLSQM1
+                  && ((unsigned char) format[1] == uLSQM2
+                      || (unsigned char) format[1] == uRSQM2))
+           {
+             convsrc = (((unsigned char) format[1] == uLSQM2
+                         && quoting_style == GRAVE_QUOTING_STYLE)
+                        ? "`" : "'");
+             format += 2;
+             memset (&discarded[format0 + 1 - format_start], 2, 2);
            }
          else
            {
-             unsigned char uc = *format++;
-             if (! multibyte || ASCII_CHAR_P (uc))
-               convbytes = 1;
-             else
+             /* Copy a single character from format to buf.  */
+             if (multibyte_format)
+               {
+                 /* Copy a whole multibyte character.  */
+                 if (p > buf
+                     && !ASCII_CHAR_P (*((unsigned char *) p - 1))
+                     && !CHAR_HEAD_P (format_char))
+                   maybe_combine_byte = 1;
+
+                 while (! CHAR_HEAD_P (*format))
+                   format++;
+
+                 convbytes = format - format0;
+                 memset (&discarded[format0 + 1 - format_start], 2,
+                         convbytes - 1);
+               }
+             else if (multibyte && !ASCII_CHAR_P (format_char))
                {
-                 int c = BYTE8_TO_CHAR (uc);
+                 int c = BYTE8_TO_CHAR (format_char);
                  convbytes = CHAR_STRING (c, str);
-                 src = (char *) str;
+                 convsrc = (char *) str;
                }
            }
 
+       copy_char:
          if (convbytes <= buf + bufsize - p)
            {
-             memcpy (p, src, convbytes);
+             memcpy (p, convsrc, convbytes);
              p += convbytes;
              nchars++;
              continue;
@@ -5213,6 +5211,7 @@ functions if all the text being accessed has this property.  */);
   defsubr (&Smessage_or_box);
   defsubr (&Scurrent_message);
   defsubr (&Sformat);
+  defsubr (&Sformat_message);
 
   defsubr (&Sinsert_buffer_substring);
   defsubr (&Scompare_buffer_substrings);
index 63089a9a8fb53d1e5421c8c87bfe49b30f1861b7..743d230ed3b7a8e942b47017651d375e8ae8815f 100644 (file)
@@ -647,7 +647,7 @@ image_error (const char *format, ...)
 static void
 image_size_error (void)
 {
-  image_error ("Invalid image size (see %qs)", "max-image-size");
+  image_error ("Invalid image size (see `%s')", "max-image-size");
 }
 
 \f
@@ -2952,13 +2952,13 @@ xbm_load_image (struct frame *f, struct image *img, unsigned char *contents,
       if (img->pixmap == NO_PIXMAP)
        {
          x_clear_image (f, img);
-         image_error ("Unable to create X pixmap for %qs", img->spec);
+         image_error ("Unable to create X pixmap for `%s'", img->spec);
        }
       else
        success_p = 1;
     }
   else
-    image_error ("Error loading XBM image %qs", img->spec);
+    image_error ("Error loading XBM image `%s'", img->spec);
 
   return success_p;
 }
@@ -2996,7 +2996,7 @@ xbm_load (struct frame *f, struct image *img)
       Lisp_Object file = x_find_image_fd (file_name, &fd);
       if (!STRINGP (file))
        {
-         image_error ("Cannot find image file %qs", file_name);
+         image_error ("Cannot find image file `%s'", file_name);
          return 0;
        }
 
@@ -3004,7 +3004,7 @@ xbm_load (struct frame *f, struct image *img)
       unsigned char *contents = slurp_file (fd, &size);
       if (contents == NULL)
        {
-         image_error ("Error loading XBM image %qs", file);
+         image_error ("Error loading XBM image `%s'", file);
          return 0;
        }
 
@@ -3116,7 +3116,7 @@ xbm_load (struct frame *f, struct image *img)
            success_p = 1;
          else
            {
-             image_error ("Unable to create pixmap for XBM image %qs",
+             image_error ("Unable to create pixmap for XBM image `%s'",
                           img->spec);
              x_clear_image (f, img);
            }
@@ -3639,7 +3639,7 @@ xpm_load (struct frame *f, struct image *img)
       Lisp_Object file = x_find_image_file (specified_file);
       if (!STRINGP (file))
        {
-         image_error ("Cannot find image file %qs", specified_file);
+         image_error ("Cannot find image file `%s'", specified_file);
 #ifdef ALLOC_XPM_COLORS
          xpm_free_color_cache ();
 #endif
@@ -3671,7 +3671,7 @@ xpm_load (struct frame *f, struct image *img)
       Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
       if (!STRINGP (buffer))
        {
-         image_error ("Invalid image data %qs", buffer);
+         image_error ("Invalid image data `%s'", buffer);
 #ifdef ALLOC_XPM_COLORS
          xpm_free_color_cache ();
 #endif
@@ -4302,7 +4302,7 @@ xpm_load (struct frame *f,
       Lisp_Object file = x_find_image_fd (file_name, &fd);
       if (!STRINGP (file))
        {
-         image_error ("Cannot find image file %qs", file_name);
+         image_error ("Cannot find image file `%s'", file_name);
          return 0;
        }
 
@@ -4310,7 +4310,7 @@ xpm_load (struct frame *f,
       unsigned char *contents = slurp_file (fd, &size);
       if (contents == NULL)
        {
-         image_error ("Error loading XPM image %qs", file);
+         image_error ("Error loading XPM image `%s'", file);
          return 0;
        }
 
@@ -4324,7 +4324,7 @@ xpm_load (struct frame *f,
       data = image_spec_value (img->spec, QCdata, NULL);
       if (!STRINGP (data))
        {
-         image_error ("Invalid image data %qs", data);
+         image_error ("Invalid image data `%s'", data);
          return 0;
        }
       success_p = xpm_load_image (f, img, SDATA (data),
@@ -5278,7 +5278,7 @@ pbm_load (struct frame *f, struct image *img)
       Lisp_Object file = x_find_image_fd (specified_file, &fd);
       if (!STRINGP (file))
        {
-         image_error ("Cannot find image file %qs", specified_file);
+         image_error ("Cannot find image file `%s'", specified_file);
          return 0;
        }
 
@@ -5286,7 +5286,7 @@ pbm_load (struct frame *f, struct image *img)
       contents = slurp_file (fd, &size);
       if (contents == NULL)
        {
-         image_error ("Error reading %qs", file);
+         image_error ("Error reading `%s'", file);
          return 0;
        }
 
@@ -5299,7 +5299,7 @@ pbm_load (struct frame *f, struct image *img)
       data = image_spec_value (img->spec, QCdata, NULL);
       if (!STRINGP (data))
        {
-         image_error ("Invalid image data %qs", data);
+         image_error ("Invalid image data `%s'", data);
          return 0;
        }
       p = SDATA (data);
@@ -5309,7 +5309,7 @@ pbm_load (struct frame *f, struct image *img)
   /* Check magic number.  */
   if (end - p < 2 || *p++ != 'P')
     {
-      image_error ("Not a PBM image: %qs", img->spec);
+      image_error ("Not a PBM image: `%s'", img->spec);
     error:
       xfree (contents);
       img->pixmap = NO_PIXMAP;
@@ -5343,7 +5343,7 @@ pbm_load (struct frame *f, struct image *img)
       break;
 
     default:
-      image_error ("Not a PBM image: %qs", img->spec);
+      image_error ("Not a PBM image: `%s'", img->spec);
       goto error;
     }
 
@@ -5442,7 +5442,7 @@ pbm_load (struct frame *f, struct image *img)
                        x_destroy_x_image (ximg);
 #endif
                        x_clear_image (f, img);
-                       image_error ("Invalid image size in image %qs",
+                       image_error ("Invalid image size in image `%s'",
                                     img->spec);
                        goto error;
                      }
@@ -5477,7 +5477,7 @@ pbm_load (struct frame *f, struct image *img)
          x_destroy_x_image (ximg);
 #endif
          x_clear_image (f, img);
-         image_error ("Invalid image size in image %qs", img->spec);
+         image_error ("Invalid image size in image `%s'", img->spec);
          goto error;
        }
 
@@ -5520,7 +5520,7 @@ pbm_load (struct frame *f, struct image *img)
 #else
                x_destroy_x_image (ximg);
 #endif
-               image_error ("Invalid pixel value in image %qs", img->spec);
+               image_error ("Invalid pixel value in image `%s'", img->spec);
                goto error;
              }
 
@@ -5916,7 +5916,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
       Lisp_Object file = x_find_image_fd (specified_file, &fd);
       if (!STRINGP (file))
        {
-         image_error ("Cannot find image file %qs", specified_file);
+         image_error ("Cannot find image file `%s'", specified_file);
          return 0;
        }
 
@@ -5924,7 +5924,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
       fp = fdopen (fd, "rb");
       if (!fp)
        {
-         image_error ("Cannot open image file %qs", file);
+         image_error ("Cannot open image file `%s'", file);
          return 0;
        }
 
@@ -5933,7 +5933,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
          || png_sig_cmp (sig, 0, sizeof sig))
        {
          fclose (fp);
-         image_error ("Not a PNG file: %qs", file);
+         image_error ("Not a PNG file: `%s'", file);
          return 0;
        }
     }
@@ -5941,7 +5941,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
     {
       if (!STRINGP (specified_data))
        {
-         image_error ("Invalid image data %qs", specified_data);
+         image_error ("Invalid image data `%s'", specified_data);
          return 0;
        }
 
@@ -5954,7 +5954,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
       if (tbr.len < sizeof sig
          || png_sig_cmp (tbr.bytes, 0, sizeof sig))
        {
-         image_error ("Not a PNG image: %qs", img->spec);
+         image_error ("Not a PNG image: `%s'", img->spec);
          return 0;
        }
 
@@ -6681,20 +6681,20 @@ jpeg_load_body (struct frame *f, struct image *img,
       Lisp_Object file = x_find_image_fd (specified_file, &fd);
       if (!STRINGP (file))
        {
-         image_error ("Cannot find image file %qs", specified_file);
+         image_error ("Cannot find image file `%s'", specified_file);
          return 0;
        }
 
       fp = fdopen (fd, "rb");
       if (fp == NULL)
        {
-         image_error ("Cannot open %qs", file);
+         image_error ("Cannot open `%s'", file);
          return 0;
        }
     }
   else if (!STRINGP (specified_data))
     {
-      image_error ("Invalid image data %qs", specified_data);
+      image_error ("Invalid image data `%s'", specified_data);
       return 0;
     }
 
@@ -6710,7 +6710,7 @@ jpeg_load_body (struct frame *f, struct image *img,
          {
            char buf[JMSG_LENGTH_MAX];
            mgr->cinfo.err->format_message ((j_common_ptr) &mgr->cinfo, buf);
-           image_error ("Error reading JPEG image %qs: %s",
+           image_error ("Error reading JPEG image `%s': %s",
                         img->spec, build_string (buf));
            break;
          }
@@ -7196,7 +7196,7 @@ tiff_load (struct frame *f, struct image *img)
       Lisp_Object file = x_find_image_file (specified_file);
       if (!STRINGP (file))
        {
-         image_error ("Cannot find image file %qs", specified_file);
+         image_error ("Cannot find image file `%s'", specified_file);
          return 0;
        }
 
@@ -7209,7 +7209,7 @@ tiff_load (struct frame *f, struct image *img)
       tiff = TIFFOpen (SSDATA (encoded_file), "r");
       if (tiff == NULL)
        {
-         image_error ("Cannot open %qs", file);
+         image_error ("Cannot open `%s'", file);
          return 0;
        }
     }
@@ -7217,7 +7217,7 @@ tiff_load (struct frame *f, struct image *img)
     {
       if (!STRINGP (specified_data))
        {
-         image_error ("Invalid image data %qs", specified_data);
+         image_error ("Invalid image data `%s'", specified_data);
          return 0;
        }
 
@@ -7237,7 +7237,7 @@ tiff_load (struct frame *f, struct image *img)
 
       if (!tiff)
        {
-         image_error ("Cannot open memory source for %qs", img->spec);
+         image_error ("Cannot open memory source for `%s'", img->spec);
          return 0;
        }
     }
@@ -7249,7 +7249,7 @@ tiff_load (struct frame *f, struct image *img)
       if (! (TYPE_MINIMUM (tdir_t) <= ino && ino <= TYPE_MAXIMUM (tdir_t)
             && TIFFSetDirectory (tiff, ino)))
        {
-         image_error ("Invalid image number %qs in image %qs",
+         image_error ("Invalid image number `%s' in image `%s'",
                       image, img->spec);
          TIFFClose (tiff);
          return 0;
@@ -7293,7 +7293,7 @@ tiff_load (struct frame *f, struct image *img)
   TIFFClose (tiff);
   if (!rc)
     {
-      image_error ("Error reading TIFF image %qs", img->spec);
+      image_error ("Error reading TIFF image `%s'", img->spec);
       xfree (buf);
       return 0;
     }
@@ -7629,7 +7629,7 @@ gif_load (struct frame *f, struct image *img)
       Lisp_Object file = x_find_image_file (specified_file);
       if (!STRINGP (file))
        {
-         image_error ("Cannot find image file %qs", specified_file);
+         image_error ("Cannot find image file `%s'", specified_file);
          return 0;
        }
 
@@ -7643,14 +7643,14 @@ gif_load (struct frame *f, struct image *img)
       gif = DGifOpenFileName (SSDATA (encoded_file));
       if (gif == NULL)
        {
-         image_error ("Cannot open %qs", file);
+         image_error ("Cannot open `%s'", file);
          return 0;
        }
 #else
       gif = DGifOpenFileName (SSDATA (encoded_file), &gif_err);
       if (gif == NULL)
        {
-         image_error ("Cannot open %qs: %s",
+         image_error ("Cannot open `%s': %s",
                       file, build_string (GifErrorString (gif_err)));
          return 0;
        }
@@ -7660,7 +7660,7 @@ gif_load (struct frame *f, struct image *img)
     {
       if (!STRINGP (specified_data))
        {
-         image_error ("Invalid image data %qs", specified_data);
+         image_error ("Invalid image data `%s'", specified_data);
          return 0;
        }
 
@@ -7674,14 +7674,14 @@ gif_load (struct frame *f, struct image *img)
       gif = DGifOpen (&memsrc, gif_read_from_memory);
       if (!gif)
        {
-         image_error ("Cannot open memory source %qs", img->spec);
+         image_error ("Cannot open memory source `%s'", img->spec);
          return 0;
        }
 #else
       gif = DGifOpen (&memsrc, gif_read_from_memory, &gif_err);
       if (!gif)
        {
-         image_error ("Cannot open memory source %qs: %s",
+         image_error ("Cannot open memory source `%s': %s",
                       img->spec, build_string (GifErrorString (gif_err)));
          return 0;
        }
@@ -7700,7 +7700,7 @@ gif_load (struct frame *f, struct image *img)
   rc = DGifSlurp (gif);
   if (rc == GIF_ERROR || gif->ImageCount <= 0)
     {
-      image_error ("Error reading %qs", img->spec);
+      image_error ("Error reading `%s'", img->spec);
       gif_close (gif, NULL);
       return 0;
     }
@@ -7711,7 +7711,7 @@ gif_load (struct frame *f, struct image *img)
     idx = INTEGERP (image_number) ? XFASTINT (image_number) : 0;
     if (idx < 0 || idx >= gif->ImageCount)
       {
-       image_error ("Invalid image number %qs in image %qs",
+       image_error ("Invalid image number `%s' in image `%s'",
                     image_number, img->spec);
        gif_close (gif, NULL);
        return 0;
@@ -7984,10 +7984,10 @@ gif_load (struct frame *f, struct image *img)
       char *error_text = GifErrorString (gif_err);
 
       if (error_text)
-       image_error ("Error closing %qs: %s",
+       image_error ("Error closing `%s': %s",
                     img->spec, build_string (error_text));
 #else
-      image_error ("Error closing %qs", img->spec);
+      image_error ("Error closing `%s'", img->spec);
 #endif
     }
 
@@ -8528,7 +8528,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
 
   if (ino < 0 || ino >= MagickGetNumberImages (image_wand))
     {
-      image_error ("Invalid image number %qs in image %qs", image, img->spec);
+      image_error ("Invalid image number `%s' in image `%s'", image, img->spec);
       DestroyMagickWand (image_wand);
       return 0;
     }
@@ -8797,7 +8797,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
 
   MagickWandTerminus ();
   /* TODO more cleanup.  */
-  image_error ("Error parsing IMAGEMAGICK image %qs", img->spec);
+  image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec);
   return 0;
 }
 
@@ -8819,7 +8819,7 @@ imagemagick_load (struct frame *f, struct image *img)
       Lisp_Object file = x_find_image_file (file_name);
       if (!STRINGP (file))
        {
-         image_error ("Cannot find image file %qs", file_name);
+         image_error ("Cannot find image file `%s'", file_name);
          return 0;
        }
       file = ENCODE_FILE (file);
@@ -8837,7 +8837,7 @@ imagemagick_load (struct frame *f, struct image *img)
       data = image_spec_value (img->spec, QCdata, NULL);
       if (!STRINGP (data))
        {
-         image_error ("Invalid image data %qs", data);
+         image_error ("Invalid image data `%s'", data);
          return 0;
        }
       success_p = imagemagick_load_image (f, img, SDATA (data),
@@ -9098,7 +9098,7 @@ svg_load (struct frame *f, struct image *img)
       Lisp_Object file = x_find_image_fd (file_name, &fd);
       if (!STRINGP (file))
        {
-         image_error ("Cannot find image file %qs", file_name);
+         image_error ("Cannot find image file `%s'", file_name);
          return 0;
        }
 
@@ -9107,7 +9107,7 @@ svg_load (struct frame *f, struct image *img)
       unsigned char *contents = slurp_file (fd, &size);
       if (contents == NULL)
        {
-         image_error ("Error loading SVG image %qs", file);
+         image_error ("Error loading SVG image `%s'", file);
          return 0;
        }
       /* If the file was slurped into memory properly, parse it.  */
@@ -9124,7 +9124,7 @@ svg_load (struct frame *f, struct image *img)
       data = image_spec_value (img->spec, QCdata, NULL);
       if (!STRINGP (data))
        {
-         image_error ("Invalid image data %qs", data);
+         image_error ("Invalid image data `%s'", data);
          return 0;
        }
       original_filename = BVAR (current_buffer, filename);
@@ -9323,7 +9323,7 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
   g_object_unref (rsvg_handle);
   /* FIXME: Use error->message so the user knows what is the actual
      problem with the image.  */
-  image_error ("Error parsing SVG image %qs", img->spec);
+  image_error ("Error parsing SVG image `%s'", img->spec);
   g_error_free (err);
   return 0;
 }
@@ -9497,7 +9497,7 @@ gs_load (struct frame *f, struct image *img)
 
   if (!img->pixmap)
     {
-      image_error ("Unable to create pixmap for %qs" , img->spec);
+      image_error ("Unable to create pixmap for `%s'" , img->spec);
       return 0;
     }
 
@@ -9609,7 +9609,7 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f)
 #endif
        }
       else
-       image_error ("Cannot get X image of %qs; colors will not be freed",
+       image_error ("Cannot get X image of `%s'; colors will not be freed",
                     img->spec);
 
       unblock_input ();
index d3dcaecd2bb0feacc972e48f26667aa1ae723d0f..bb25ebd9be3f6a91701f1ee769c5eaba92ce4232 100644 (file)
@@ -4300,13 +4300,6 @@ extern void set_initial_environment (void);
 extern void syms_of_callproc (void);
 
 /* Defined in doc.c.  */
-enum
-  {
-    /* Named constants for the UTF-8 encodings of U+2018 LEFT SINGLE
-       QUOTATION MARK and U+2019 RIGHT SINGLE QUOTATION MARK.  */
-    uLSQM0 = 0xE2, uLSQM1 = 0x80, uLSQM2 = 0x98,
-    uRSQM0 = 0xE2, uRSQM1 = 0x80, uRSQM2 = 0x99
-  };
 enum text_quoting_style
   {
     /* Use curved single quotes ‘like this’.  */
index c342218c5324c695c8f1e80971d96a7cc624454c..21b2f9c186601827079445e27c60ac16c8e34064 100644 (file)
@@ -947,7 +947,7 @@ load_warn_old_style_backquotes (Lisp_Object file)
 {
   if (!NILP (Vold_style_backquotes))
     {
-      AUTO_STRING (format, "Loading %qs: old-style backquotes detected!");
+      AUTO_STRING (format, "Loading `%s': old-style backquotes detected!");
       CALLN (Fmessage, format, file);
     }
 }
index 8be74977b433df913a892c1432f825b134c5d8eb..f75293618e8b80a5737c5c572b4a9c67027cf2f8 100644 (file)
@@ -9838,7 +9838,7 @@ vadd_to_log (char const *format, va_list ap)
   struct gcpro gcpro1, gcpro2;
   GCPRO2 (args[1], msg);
   gcpro1.nvars = form_nargs;
-  msg = Fformat (nargs, args);
+  msg = Fformat_message (nargs, args);
 
   ptrdiff_t len = SBYTES (msg) + 1;
   USE_SAFE_ALLOCA;
index b599e6af715a2451e144672c9df4c9a0ecb236fe..ce300e7ef23da816e0c7e22afb711202737ef6f1 100644 (file)
@@ -797,7 +797,7 @@ load_pixmap (struct frame *f, Lisp_Object name)
 
   if (bitmap_id < 0)
     {
-      add_to_log ("Invalid or undefined bitmap %qs", name);
+      add_to_log ("Invalid or undefined bitmap `%s'", name);
       bitmap_id = 0;
     }
   else
index d4d4dc04b8d3fbea1d118d812f1884d5836d8ce4..3e5778de17e3514a26c4bab4ead3af4a956a68d4 100644 (file)
@@ -2148,7 +2148,7 @@ static Lisp_Object
 x_clipboard_manager_error_1 (Lisp_Object err)
 {
   AUTO_STRING (format, "X clipboard manager error: %s\n\
-If the problem persists, set %qs to nil.");
+If the problem persists, set `%s' to nil.");
   AUTO_STRING (varname, "x-select-enable-clipboard-manager");
   CALLN (Fmessage, format, CAR (CDR (err)), varname);
   return Qnil;