]> code.delx.au - gnu-emacs/blobdiff - src/charset.c
(Fbuffer_substring): Doc fix.
[gnu-emacs] / src / charset.c
index 2c04743dac6d8b729d228abed4b8957a8c2df1b4..54edddd47a63e0d4bdbcb904321cc0a7ca2e077d 100644 (file)
@@ -34,6 +34,7 @@ Boston, MA 02111-1307, USA.  */
 #include "lisp.h"
 #include "buffer.h"
 #include "charset.h"
+#include "composite.h"
 #include "coding.h"
 #include "disptab.h"
 
@@ -221,7 +222,7 @@ char_to_string (c, str)
          *p++ = c + 0x20;
        }
     }
-  else if (c < MAX_CHAR)
+  else if (CHAR_VALID_P (c, 0))
     {
       int charset, c1, c2;
 
@@ -315,7 +316,7 @@ int
 char_printable_p (c)
      int c;
 {
-  int charset, c1, c2, chars;
+  int charset, c1, c2;
 
   if (ASCII_BYTE_P (c))
     return 1;
@@ -562,7 +563,7 @@ update_charset_table (charset_id, dimension, chars, width, direction,
     }
 
   /* Update table iso_charset_table.  */
-  if (iso_final_char >= 0
+  if (XINT (iso_final_char) >= 0
       && ISO_CHARSET_TABLE (dimension, chars, iso_final_char) < 0)
     ISO_CHARSET_TABLE (dimension, chars, iso_final_char) = charset;
 }
@@ -596,17 +597,13 @@ get_new_private_charset_id (dimension, width)
 
   if (dimension == 1)
     {
-      if (width == 1)
-       from = LEADING_CODE_EXT_11, to = LEADING_CODE_EXT_12;
-      else
-       from = LEADING_CODE_EXT_12, to = LEADING_CODE_EXT_21;
+      from = LEADING_CODE_EXT_11;
+      to = LEADING_CODE_EXT_21;
     }
   else
     {
-      if (width == 1)
-       from = LEADING_CODE_EXT_21, to = LEADING_CODE_EXT_22;
-      else
-       from = LEADING_CODE_EXT_22, to = LEADING_CODE_EXT_MAX + 1;
+      from = LEADING_CODE_EXT_21;
+      to = LEADING_CODE_EXT_MAX + 1;
     }
 
   for (charset = from; charset < to; charset++)
@@ -849,7 +846,7 @@ DEFUN ("find-charset-region", Ffind_charset_region, Sfind_charset_region,
 BEG and END are buffer positions.\n\
 Optional arg TABLE if non-nil is a translation table to look up.\n\
 \n\
-If the region contains invalid multiybte characters,\n\
+If the region contains invalid multibyte characters,\n\
 `unknown' is included in the returned list.\n\
 \n\
 If the current buffer is unibyte, the returned list may contain\n\
@@ -905,7 +902,7 @@ DEFUN ("find-charset-string", Ffind_charset_string, Sfind_charset_string,
   "Return a list of charsets in STR.\n\
 Optional arg TABLE if non-nil is a translation table to look up.\n\
 \n\
-If the region contains invalid multiybte characters,\n\
+If the string contains invalid multibyte characters,\n\
 `unknown' is included in the returned list.\n\
 \n\
 If STR is unibyte, the returned list may contain\n\
@@ -970,13 +967,17 @@ DEFUN ("make-char-internal", Fmake_char_internal, Smake_char_internal, 1, 3, 0,
     }
   else if (charset_id == CHARSET_8_BIT_CONTROL)
     {
-      if (c1 < 0x80 || c1 > 0x9F)
+      if (NILP (code1))
+       c1 = 0x80;
+      else if (c1 < 0x80 || c1 > 0x9F)
        goto invalid_code_posints;
       return make_number (c1);
     }
   else if (charset_id == CHARSET_8_BIT_GRAPHIC)
     {
-      if (c1 < 0xA0 || c1 > 0xFF)
+      if (NILP (code1))
+       c1 = 0xA0;
+      else if (c1 < 0xA0 || c1 > 0xFF)
        goto invalid_code_posints;
       return make_number (c1);
     }
@@ -1003,7 +1004,6 @@ return a list of symbol `unknown' and CHAR.")
   (ch)
      Lisp_Object ch;
 {
-  Lisp_Object val;
   int c, charset, c1, c2;
 
   CHECK_NUMBER (ch, 0);
@@ -1076,7 +1076,7 @@ char_valid_p (c, genericp)
 {
   int charset, c1, c2;
 
-  if (c < 0)
+  if (c < 0 || c >= MAX_CHAR)
     return 0;
   if (SINGLE_BYTE_CHAR_P (c))
     return 1;
@@ -1154,8 +1154,6 @@ This is now an obsolete function.  We keep it just for backward compatibility.")
   (ch)
      Lisp_Object ch;
 {
-  Lisp_Object val;
-
   CHECK_NUMBER (ch, 0);
   return make_number (1);
 }
@@ -1197,7 +1195,8 @@ char_bytes (c)
 
 DEFUN ("char-width", Fchar_width, Schar_width, 1, 1, 0,
   "Return width of CHAR when displayed in the current buffer.\n\
-The width is measured by how many columns it occupies on the screen.")
+The width is measured by how many columns it occupies on the screen.\n\
+Tab is taken to occupy `tab-width' columns.")
   (ch)
        Lisp_Object ch;
 {
@@ -1234,29 +1233,140 @@ strwidth (str, len)
      unsigned char *str;
      int len;
 {
-  unsigned char *endp = str + len;
+  return c_string_width (str, len, -1, NULL, NULL);
+}
+
+/* Return width of string STR of length LEN when displayed in the
+   current buffer.  The width is measured by how many columns it
+   occupies on the screen.  If PRECISION > 0, return the width of
+   longest substring that doesn't exceed PRECISION, and set number of
+   characters and bytes of the substring in *NCHARS and *NBYTES
+   respectively.  */
+
+int
+c_string_width (str, len, precision, nchars, nbytes)
+     unsigned char *str;
+     int precision, *nchars, *nbytes;
+{
+  int i = 0, i_byte = 0;
   int width = 0;
+  int chars;
   struct Lisp_Char_Table *dp = buffer_display_table ();
 
-  while (str < endp)
+  while (i_byte < len)
     {
-      Lisp_Object disp;
-      int thislen;
-      int c = STRING_CHAR_AND_LENGTH (str, endp - str, thislen);
+      int bytes, thiswidth;
+      Lisp_Object val;
 
-      /* Get the way the display table would display it.  */
       if (dp)
-       disp = DISP_CHAR_VECTOR (dp, c);
+       {
+         int c = STRING_CHAR_AND_LENGTH (str + i_byte, len - i_byte, bytes);
+
+         chars = 1;
+         val = DISP_CHAR_VECTOR (dp, c);
+         if (VECTORP (val))
+           thiswidth = XVECTOR (val)->size;
+         else
+           thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]);
+       }
       else
-       disp = Qnil;
+       {
+         chars = 1;
+         PARSE_MULTIBYTE_SEQ (str + i_byte, len - i_byte, bytes);
+         thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]);
+       }
+
+      if (precision > 0
+         && (width + thiswidth > precision))
+       {
+         *nchars = i;
+         *nbytes = i_byte;
+         return width;
+       }
+      i++;
+      i_byte += bytes;
+      width += thiswidth;
+  }
 
-      if (VECTORP (disp))
-       width += XVECTOR (disp)->size;
+  if (precision > 0)
+    {
+      *nchars = i;
+      *nbytes = i_byte;
+    }
+
+  return width;
+}
+
+/* Return width of Lisp string STRING when displayed in the current
+   buffer.  The width is measured by how many columns it occupies on
+   the screen while paying attention to compositions.  If PRECISION >
+   0, return the width of longest substring that doesn't exceed
+   PRECISION, and set number of characters and bytes of the substring
+   in *NCHARS and *NBYTES respectively.  */
+
+int
+lisp_string_width (string, precision, nchars, nbytes)
+     Lisp_Object string;
+     int precision, *nchars, *nbytes;
+{
+  int len = XSTRING (string)->size;
+  int len_byte = STRING_BYTES (XSTRING (string));
+  unsigned char *str = XSTRING (string)->data;
+  int i = 0, i_byte = 0;
+  int width = 0;
+  struct Lisp_Char_Table *dp = buffer_display_table ();
+
+  while (i < len)
+    {
+      int chars, bytes, thiswidth;
+      Lisp_Object val;
+      int cmp_id;
+      int ignore, end;
+
+      if (find_composition (i, -1, &ignore, &end, &val, string)
+         && ((cmp_id = get_composition_id (i, i_byte, end - i, val, string))
+             >= 0))
+       {
+         thiswidth = composition_table[cmp_id]->width;
+         chars = end - i;
+         bytes = string_char_to_byte (string, end) - i_byte;
+       }
+      else if (dp)
+       {
+         int c = STRING_CHAR_AND_LENGTH (str + i_byte, len - i_byte, bytes);
+
+         chars = 1;
+         val = DISP_CHAR_VECTOR (dp, c);
+         if (VECTORP (val))
+           thiswidth = XVECTOR (val)->size;
+         else
+           thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]);
+       }
       else
-       width += ONE_BYTE_CHAR_WIDTH (*str);
+       {
+         chars = 1;
+         PARSE_MULTIBYTE_SEQ (str + i_byte, len_byte - i_byte, bytes);
+         thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]);
+       }
+
+      if (precision > 0
+         && (width + thiswidth > precision))
+       {
+         *nchars = i;
+         *nbytes = i_byte;
+         return width;
+       }
+      i += chars;
+      i_byte += bytes;
+      width += thiswidth;
+  }
 
-      str += thislen;
+  if (precision > 0)
+    {
+      *nchars = i;
+      *nbytes = i_byte;
     }
+
   return width;
 }
 
@@ -1265,15 +1375,15 @@ DEFUN ("string-width", Fstring_width, Sstring_width, 1, 1, 0,
 Width is measured by how many columns it occupies on the screen.\n\
 When calculating width of a multibyte character in STRING,\n\
 only the base leading-code is considered; the validity of\n\
-the following bytes is not checked.")
+the following bytes is not checked.  Tabs in STRING are always\n\
+taken to occupy `tab-width' columns.")
   (str)
      Lisp_Object str;
 {
   Lisp_Object val;
 
   CHECK_STRING (str, 0);
-  XSETFASTINT (val, strwidth (XSTRING (str)->data,
-                             STRING_BYTES (XSTRING (str))));
+  XSETFASTINT (val, lisp_string_width (str, -1, NULL, NULL));
   return val;
 }
 
@@ -1438,7 +1548,6 @@ str_to_multibyte (str, len, bytes)
 {
   unsigned char *p = str, *endp = str + bytes;
   unsigned char *to;
-  int c;
 
   while (p < endp && (*p < 0x80 || *p >= 0xA0)) p++;
   if (p == endp)