]> code.delx.au - gnu-emacs/blobdiff - src/charset.c
(non_ascii_char_to_string): If C is negative, signal error.
[gnu-emacs] / src / charset.c
index f7a5cae63f6b67a8e92942c7a0afdf6293414aaa..054b2848894412d1928c95b1d53474b05b8c590e 100644 (file)
@@ -141,6 +141,9 @@ non_ascii_char_to_string (c, workbuf, str)
 {
   int charset, c1, c2;
 
+  if (c < 0)
+    invalid_character (c);
+
   if (COMPOSITE_CHAR_P (c))
     {
       int cmpchar_id = COMPOSITE_CHAR_ID (c);
@@ -191,48 +194,54 @@ string_to_non_ascii_char (str, len, actual_len, exclude_tail_garbage)
 {
   int charset;
   unsigned char c1, c2;
-  register int c, bytes;
+  int c, bytes;
+  const unsigned char *begp = str;
 
-  c = *str;
+  c = *str++;
   bytes = 1;
 
   if (BASE_LEADING_CODE_P (c))
-    {
-      while (bytes < len && ! CHAR_HEAD_P (str[bytes])) bytes++;
+    do {
+      while (bytes < len && ! CHAR_HEAD_P (begp[bytes])) bytes++;
 
       if (c == LEADING_CODE_COMPOSITION)
        {
-         int cmpchar_id = str_cmpchar_id (str, bytes);
+         int cmpchar_id = str_cmpchar_id (begp, bytes);
 
          if (cmpchar_id >= 0)
            {
              c = MAKE_COMPOSITE_CHAR (cmpchar_id);
-             if (exclude_tail_garbage)
-               bytes = cmpchar_table[cmpchar_id]->len;
+             str += cmpchar_table[cmpchar_id]->len - 1;
            }
+         else
+           str += bytes - 1;
        }
       else
        {
+         const unsigned char *endp = begp + bytes;
          int charset = c, c1, c2 = 0;
-         int char_bytes = BYTES_BY_CHAR_HEAD (c);
 
-         str++;
-         if (c >= LEADING_CODE_PRIVATE_11)
-           charset = *str++;
-         if (char_bytes <= bytes && CHARSET_DEFINED_P (charset))
+         if (str >= endp) break;
+         if (c >= LEADING_CODE_PRIVATE_11 && c <= LEADING_CODE_PRIVATE_22)
            {
-             c1 = *str++ & 0x7f;
-             if (CHARSET_DIMENSION (charset) == 2)
-               c2 = *str & 0x7F;
-             c = MAKE_NON_ASCII_CHAR (charset, c1, c2);
-             if (exclude_tail_garbage)
-               bytes = char_bytes;
+             charset = *str++;
+             if (str < endp)
+               c1 = *str++ & 0x7F;
+             else
+               c1 = charset, charset = c;
            }
+         else
+           c1 = *str++ & 0x7f;
+         if (CHARSET_DEFINED_P (charset)
+             && CHARSET_DIMENSION (charset) == 2
+             && str < endp)
+           c2 = *str++ & 0x7F;
+         c = MAKE_NON_ASCII_CHAR (charset, c1, c2);
        }
-    }
+    } while (0);
 
   if (actual_len)
-    *actual_len = bytes;
+    *actual_len = exclude_tail_garbage ? str - begp : bytes;
   return c;
 }
 
@@ -447,6 +456,9 @@ update_charset_table (charset_id, dimension, chars, width, direction,
       leading_code_ext = charset;
     } 
 
+  if (BYTES_BY_CHAR_HEAD (leading_code_base) != bytes)
+    error ("Invalid dimension for the charset-ID %d", charset);
+
   CHARSET_TABLE_INFO (charset, CHARSET_ID_IDX) = charset_id;
   CHARSET_TABLE_INFO (charset, CHARSET_BYTES_IDX) = make_number (bytes);
   CHARSET_TABLE_INFO (charset, CHARSET_DIMENSION_IDX) = dimension;
@@ -496,8 +508,6 @@ update_charset_table (charset_id, dimension, chars, width, direction,
   if (charset != CHARSET_ASCII
       && charset < MIN_CHARSET_PRIVATE_DIMENSION1)
     {
-      /* Update tables bytes_by_char_head and width_by_char_head.  */
-      bytes_by_char_head[leading_code_base] = bytes;
       width_by_char_head[leading_code_base] = XINT (width);
 
       /* Update table emacs_code_class.  */
@@ -985,7 +995,7 @@ char_valid_p (c, genericp)
   if (SINGLE_BYTE_CHAR_P (c))
     return 1;
   SPLIT_NON_ASCII_CHAR (c, charset, c1, c2);
-  if (!CHARSET_VALID_P (charset))
+  if (charset != CHARSET_COMPOSITION && !CHARSET_DEFINED_P (charset))
     return 0;
   return (c < MIN_CHAR_COMPOSITION
          ? ((c & CHAR_FIELD1_MASK) /* i.e. dimension of C is two.  */
@@ -1410,7 +1420,12 @@ str_cmpchar_id (str, len)
     p = str + 1;
     while (p < endp)
       {
-       if (embedded_rule) p++;
+       if (embedded_rule)
+         {
+           p++;
+           if (p >= endp)
+             return -1;
+         }
        /* No need of checking if *P is 0xA0 because
           BYTES_BY_CHAR_HEAD (0x80) surely returns 2.  */
        p += BYTES_BY_CHAR_HEAD (*p - 0x20);
@@ -1590,16 +1605,27 @@ str_cmpchar_id (str, len)
   return n_cmpchars++;
 }
 
-/* Return the Nth element of the composite character C.  */
+/* Return the Nth element of the composite character C.  If NOERROR is
+   nonzero, return 0 on error condition (C is an invalid composite
+   charcter, or N is out of range). */
 int
-cmpchar_component (c, n)
-     unsigned int c, n;
+cmpchar_component (c, n, noerror)
+     int c, n, noerror;
 {
   int id = COMPOSITE_CHAR_ID (c);
 
-  if (id >= n_cmpchars         /* C is not a valid composite character.  */
-      || n >= cmpchar_table[id]->glyph_len) /* No such component.  */
-    return -1;
+  if (id < 0 || id >= n_cmpchars)
+    {
+      /* C is not a valid composite character.  */
+      if (noerror) return 0;
+      error ("Invalid composite character: %d", c)  ;
+    }
+  if (n >= cmpchar_table[id]->glyph_len)
+    {
+      /* No such component.  */
+      if (noerror) return 0;
+      args_out_of_range (make_number (c), make_number (n));
+    }
   /* No face data is stored in glyph code.  */
   return ((int) (cmpchar_table[id]->glyph[n]));
 }
@@ -1615,30 +1641,28 @@ DEFUN ("cmpcharp", Fcmpcharp, Scmpcharp, 1, 1, 0,
 
 DEFUN ("composite-char-component", Fcmpchar_component, Scmpchar_component,
        2, 2, 0,
-  "Return the IDXth component character of composite character CHARACTER.")
-  (character, idx)
-     Lisp_Object character, idx;
+  "Return the Nth component character of composite character CHARACTER.")
+  (character, n)
+     Lisp_Object character, n;
 {
-  int c;
+  int id;
 
   CHECK_NUMBER (character, 0);
-  CHECK_NUMBER (idx, 1);
-
-  if ((c = cmpchar_component (XINT (character), XINT (idx))) < 0)
-    args_out_of_range (character, idx);
+  CHECK_NUMBER (n, 1);
 
-  return make_number (c);
+  return (make_number (cmpchar_component (XINT (character), XINT (n), 0)));
 }
 
 DEFUN ("composite-char-composition-rule", Fcmpchar_cmp_rule, Scmpchar_cmp_rule,
        2, 2, 0,
-  "Return the Nth composition rule embedded in composite character CHARACTER.\n\
+  "Return the Nth composition rule of composite character CHARACTER.\n\
 The returned rule is for composing the Nth component\n\
-on the (N-1)th component.  If N is 0, the returned value is always 255.")
+on the (N-1)th component.\n\
+If CHARACTER should be composed relatively or N is 0, return 255.")
   (character, n)
      Lisp_Object character, n;
 {
-  int id, i;
+  int id;
 
   CHECK_NUMBER (character, 0);
   CHECK_NUMBER (n, 1);
@@ -1646,11 +1670,12 @@ on the (N-1)th component.  If N is 0, the returned value is always 255.")
   id = COMPOSITE_CHAR_ID (XINT (character));
   if (id < 0 || id >= n_cmpchars)
     error ("Invalid composite character: %d", XINT (character));
-  i = XINT (n);
-  if (i > cmpchar_table[id]->glyph_len)
+  if (XINT (n) < 0 || XINT (n) >= cmpchar_table[id]->glyph_len)
     args_out_of_range (character, n);
 
-  return make_number (cmpchar_table[id]->cmp_rule[i]);
+  return make_number (cmpchar_table[id]->cmp_rule
+                     ? cmpchar_table[id]->cmp_rule[XINT (n)]
+                     : 255);
 }
 
 DEFUN ("composite-char-composition-rule-p", Fcmpchar_cmp_rule_p,
@@ -1702,7 +1727,7 @@ DEFUN ("compose-string", Fcompose_string, Scompose_string,
   i = 1;
   while (p < pend)
     {
-      if (*p < 0x20 || *p == 127) /* control code */
+      if (*p < 0x20) /* control code */
        error ("Invalid component character: %d", *p);
       else if (*p < 0x80)      /* ASCII */
        {
@@ -1719,8 +1744,12 @@ DEFUN ("compose-string", Fcompose_string, Scompose_string,
              LEADING_CODE_COMPOSITION, keep the remaining bytes
              unchanged.  */
          p++;
+         if (*p == 255)
+           error ("Can't compose a rule-based composition character");
          ptemp = p;
          while (! CHAR_HEAD_P (*p)) p++;
+         if (str_cmpchar_id (ptemp - 1, p - ptemp + 1) < 0)
+           error ("Can't compose an invalid composition character");
          if (i + (p - ptemp) >= MAX_LENGTH_OF_MULTI_BYTE_FORM)
            error ("Too long string to be composed: %s", XSTRING (str)->data);
          bcopy (ptemp, buf + i, p - ptemp);
@@ -1730,7 +1759,10 @@ DEFUN ("compose-string", Fcompose_string, Scompose_string,
        {
          /* Add 0x20 to the base leading-code, keep the remaining
              bytes unchanged.  */
-         len = BYTES_BY_CHAR_HEAD (*p);
+         int c = STRING_CHAR_AND_CHAR_LENGTH (p, pend - p, len);
+
+         if (len <= 1 || ! CHAR_VALID_P (c, 0))
+           error ("Can't compose an invalid character");
          if (i + len >= MAX_LENGTH_OF_MULTI_BYTE_FORM)
            error ("Too long string to be composed: %s", XSTRING (str)->data);
          bcopy (p, buf + i, len);
@@ -1810,13 +1842,21 @@ init_charset_once ()
 
   for (i = 0; i < 256; i++)
     BYTES_BY_CHAR_HEAD (i) = 1;
+  for (i = MIN_CHARSET_OFFICIAL_DIMENSION1;
+       i <= MAX_CHARSET_OFFICIAL_DIMENSION1; i++)
+    BYTES_BY_CHAR_HEAD (i) = 2;
+  for (i = MIN_CHARSET_OFFICIAL_DIMENSION2;
+       i <= MAX_CHARSET_OFFICIAL_DIMENSION2; i++)
+    BYTES_BY_CHAR_HEAD (i) = 3;
   BYTES_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_11) = 3;
   BYTES_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_12) = 3;
   BYTES_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_21) = 4;
   BYTES_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_22) = 4;
-  /* The following doesn't reflect the actual bytes, but just to tell
+  /* The followings don't reflect the actual bytes, but just to tell
      that it is a start of a multibyte character.  */
   BYTES_BY_CHAR_HEAD (LEADING_CODE_COMPOSITION) = 2;
+  BYTES_BY_CHAR_HEAD (0x9E) = 2;
+  BYTES_BY_CHAR_HEAD (0x9F) = 2;
 
   for (i = 0; i < 128; i++)
     WIDTH_BY_CHAR_HEAD (i) = 1;