]> code.delx.au - gnu-emacs/blobdiff - src/doc.c
;* src/w32fns.c (syms_of_w32fns): Fix last commit.
[gnu-emacs] / src / doc.c
index 1d9c330d12caa547cc6449f23b06f89684273cd5..78a7815aade229f19c6421027e0e40317ef6a853 100644 (file)
--- a/src/doc.c
+++ b/src/doc.c
@@ -1,6 +1,7 @@
-/* Record indices of function doc strings stored in a file.
+/* Record indices of function doc strings stored in a file. -*- coding: utf-8 -*-
 
-Copyright (C) 1985-1986, 1993-1995, 1997-2014 Free Software Foundation, Inc.
+Copyright (C) 1985-1986, 1993-1995, 1997-2015 Free Software Foundation,
+Inc.
 
 This file is part of GNU Emacs.
 
@@ -31,11 +32,10 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "lisp.h"
 #include "character.h"
 #include "buffer.h"
+#include "disptab.h"
 #include "keyboard.h"
 #include "keymap.h"
 
-Lisp_Object Qfunction_documentation;
-
 /* Buffer used for reading from documentation file.  */
 static char *get_doc_string_buffer;
 static ptrdiff_t get_doc_string_buffer_size;
@@ -300,19 +300,6 @@ read_doc_string (Lisp_Object filepos)
 static bool
 reread_doc_file (Lisp_Object file)
 {
-#if 0
-  Lisp_Object reply, prompt[3];
-  struct gcpro gcpro1;
-  GCPRO1 (file);
-  prompt[0] = build_string ("File ");
-  prompt[1] = NILP (file) ? Vdoc_file_name : file;
-  prompt[2] = build_string (" is out of sync.  Reload? ");
-  reply = Fy_or_n_p (Fconcat (3, prompt));
-  UNGCPRO;
-  if (NILP (reply))
-    return 0;
-#endif
-
   if (NILP (file))
     Fsnarf_documentation (Vdoc_file_name);
   else
@@ -530,8 +517,13 @@ store_function_docstring (Lisp_Object obj, ptrdiff_t offset)
       if ((ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK) > COMPILED_DOC_STRING)
        ASET (fun, COMPILED_DOC_STRING, make_number (offset));
       else
-       message ("No docstring slot for %s",
-                SYMBOLP (obj) ? SSDATA (SYMBOL_NAME (obj)) : "<anonymous>");
+       {
+         AUTO_STRING (format, "No docstring slot for %s");
+         CALLN (Fmessage, format,
+                (SYMBOLP (obj)
+                 ? SYMBOL_NAME (obj)
+                 : build_string ("<anonymous>")));
+       }
     }
 }
 
@@ -692,6 +684,18 @@ the same file name is found in the `doc-directory'.  */)
   return unbind_to (count, Qnil);
 }
 \f
+/* Declare named constants for U+2018 LEFT SINGLE QUOTATION MARK and
+   U+2019 RIGHT SINGLE QUOTATION MARK, which have UTF-8 encodings
+   "\xE2\x80\x98" and "\xE2\x80\x99", respectively.  */
+enum
+  {
+    LEFT_SINGLE_QUOTATION_MARK = 0x2018,
+    uLSQM0 = 0xE2, uLSQM1 = 0x80, uLSQM2 = 0x98,
+    uRSQM0 = 0xE2, uRSQM1 = 0x80, uRSQM2 = 0x99,
+  };
+static unsigned char const LSQM[] = { uLSQM0, uLSQM1, uLSQM2 };
+static unsigned char const RSQM[] = { uRSQM0, uRSQM1, uRSQM2 };
+
 DEFUN ("substitute-command-keys", Fsubstitute_command_keys,
        Ssubstitute_command_keys, 1, 1, 0,
        doc: /* Substitute key descriptions for command names in STRING.
@@ -707,22 +711,30 @@ summary).
 
 Each substring of the form \\=\\<MAPVAR> specifies the use of MAPVAR
 as the keymap for future \\=\\[COMMAND] substrings.
-\\=\\= quotes the following character and is discarded;
-thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output.
+
+Each \\=‘ and \\=’ are replaced by left and right quote.  Each \\=` is
+replaced by left quote, and each ' preceded by \\=` and without
+intervening ' is replaced by right quote.  Left and right quote
+characters are specified by ‘help-quote-translation’.
+
+\\=\\= quotes the following character and is discarded; thus,
+\\=\\=\\=\\= puts \\=\\= into the output, \\=\\=\\=\\[ puts \\=\\[ into the output, and
+\\=\\=\\=` puts \\=` into the output.
 
 Return the original STRING if no substitutions are made.
 Otherwise, return a new string.  */)
   (Lisp_Object string)
 {
   char *buf;
-  bool changed = 0;
+  bool changed = false;
+  bool in_quote = false;
   unsigned char *strp;
   char *bufp;
   ptrdiff_t idx;
   ptrdiff_t bsize;
   Lisp_Object tem;
   Lisp_Object keymap;
-  unsigned char *start;
+  unsigned char const *start;
   ptrdiff_t length, length_byte;
   Lisp_Object name;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
@@ -738,6 +750,21 @@ Otherwise, return a new string.  */)
   name = Qnil;
   GCPRO4 (string, tem, keymap, name);
 
+  enum { unicode, grave_accent, apostrophe } quote_translation = unicode;
+  if (EQ (Vhelp_quote_translation, make_number ('`')))
+    quote_translation = grave_accent;
+  else if (EQ (Vhelp_quote_translation, make_number ('\'')))
+    quote_translation = apostrophe;
+  else if (NILP (Vhelp_quote_translation)
+          && DISP_TABLE_P (Vstandard_display_table))
+    {
+      Lisp_Object dv = DISP_CHAR_VECTOR (XCHAR_TABLE (Vstandard_display_table),
+                                        LEFT_SINGLE_QUOTATION_MARK);
+      if (VECTORP (dv) && ASIZE (dv) == 1
+         && EQ (AREF (dv, 0), make_number ('`')))
+       quote_translation = grave_accent;
+    }
+
   multibyte = STRING_MULTIBYTE (string);
   nchars = 0;
 
@@ -748,6 +775,12 @@ Otherwise, return a new string.  */)
   keymap = Voverriding_local_map;
 
   bsize = SBYTES (string);
+
+  /* Add some room for expansion due to quote replacement.  */
+  enum { EXTRA_ROOM = 20 };
+  if (bsize <= STRING_BYTES_BOUND - EXTRA_ROOM)
+    bsize += EXTRA_ROOM;
+
   bufp = buf = xmalloc (bsize);
 
   strp = SDATA (string);
@@ -757,7 +790,7 @@ Otherwise, return a new string.  */)
        {
          /* \= quotes the next character;
             thus, to put in \[ without its special meaning, use \=\[.  */
-         changed = 1;
+         changed = true;
          strp += 2;
          if (multibyte)
            {
@@ -780,7 +813,6 @@ Otherwise, return a new string.  */)
          ptrdiff_t start_idx;
          bool follow_remap = 1;
 
-         changed = 1;
          strp += 2;            /* skip \[ */
          start = strp;
          start_idx = start - SDATA (string);
@@ -847,7 +879,6 @@ Otherwise, return a new string.  */)
          Lisp_Object earlier_maps;
          ptrdiff_t count = SPECPDL_INDEX ();
 
-         changed = 1;
          strp += 2;            /* skip \{ or \< */
          start = strp;
          start_idx = start - SDATA (string);
@@ -917,6 +948,7 @@ Otherwise, return a new string.  */)
          length = SCHARS (tem);
          length_byte = SBYTES (tem);
        subst:
+         changed = true;
          {
            ptrdiff_t offset = bufp - buf;
            if (STRING_BYTES_BOUND - length_byte < bsize)
@@ -930,6 +962,39 @@ Otherwise, return a new string.  */)
            strp = SDATA (string) + idx;
          }
        }
+      else if (strp[0] == '`' && quote_translation == unicode)
+       {
+         in_quote = true;
+         start = LSQM;
+       subst_quote:
+         length = 1;
+         length_byte = 3;
+         idx = strp - SDATA (string) + 1;
+         goto subst;
+       }
+      else if (strp[0] == '`' && quote_translation == apostrophe)
+       {
+         *bufp++ = '\'';
+         strp++;
+         nchars++;
+         changed = true;
+       }
+      else if (strp[0] == '\'' && in_quote)
+       {
+         in_quote = false;
+         start = RSQM;
+         goto subst_quote;
+       }
+      else if (strp[0] == uLSQM0 && strp[1] == uLSQM1
+              && (strp[2] == uLSQM2 || strp[2] == uRSQM2)
+              && quote_translation != unicode)
+        {
+         *bufp++ = (strp[2] == uLSQM2 && quote_translation == grave_accent
+                    ? '`' : '\'');
+         strp += 3;
+         nchars++;
+         changed = true;
+        }
       else if (! multibyte)            /* just copy other chars */
        *bufp++ = *strp++, nchars++;
       else
@@ -968,6 +1033,16 @@ syms_of_doc (void)
                doc: /* A list of files used to build this Emacs binary.  */);
   Vbuild_files = Qnil;
 
+  DEFVAR_LISP ("help-quote-translation", Vhelp_quote_translation,
+               doc: /* Style to use for single quotes in help.
+The value is a left single quote character of some style.
+Quote \\=‘like this\\=’ if the value is ?\\=‘ (left single quotation mark).
+Quote 'like this' if the value is ?' (apostrophe).
+Quote \\=`like this' if the value is ?\\=` (grave accent).
+The default value is nil, which means quote with left single quotation mark
+if displayable, and with grave accent otherwise.  */);
+  Vhelp_quote_translation = Qnil;
+
   defsubr (&Sdocumentation);
   defsubr (&Sdocumentation_property);
   defsubr (&Ssnarf_documentation);