/[emacs]/emacs/src/charset.c
ViewVC logotype

Diff of /emacs/src/charset.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.125 by eliz, Wed Feb 6 19:12:14 2002 UTC revision 1.125.2.1 by handa, Fri Mar 1 01:16:12 2002 UTC
# Line 1  Line 1 
1  /* Basic multilingual character support.  /* Basic character set support.
2     Copyright (C) 1995, 1997, 1998 Electrotechnical Laboratory, JAPAN.     Copyright (C) 1995, 97, 98, 2000, 2001 Electrotechnical Laboratory, JAPAN.
3     Licensed to the Free Software Foundation.     Licensed to the Free Software Foundation.
4     Copyright (C) 2001 Free Software Foundation, Inc.     Copyright (C) 2001 Free Software Foundation, Inc.
5       Copyright (C) 2001, 2002
6         National Institute of Advanced Industrial Science and Technology (AIST)
7         Registration Number H13PRO009
8    
9  This file is part of GNU Emacs.  This file is part of GNU Emacs.
10    
# Line 20  along with GNU Emacs; see the file COPYI Line 23  along with GNU Emacs; see the file COPYI
23  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24  Boston, MA 02111-1307, USA.  */  Boston, MA 02111-1307, USA.  */
25    
 /* At first, see the document in `charset.h' to understand the code in  
    this file.  */  
   
26  #ifdef emacs  #ifdef emacs
27  #include <config.h>  #include <config.h>
28  #endif  #endif
29    
30  #include <stdio.h>  #include <stdio.h>
31    #include <unistd.h>
32    #include <ctype.h>
33    
34  #ifdef emacs  #ifdef emacs
35    
36  #include <sys/types.h>  #include <sys/types.h>
37  #include "lisp.h"  #include "lisp.h"
38  #include "buffer.h"  #include "character.h"
39  #include "charset.h"  #include "charset.h"
 #include "composite.h"  
40  #include "coding.h"  #include "coding.h"
41  #include "disptab.h"  #include "disptab.h"
42    #include "buffer.h"
43    
44  #else  /* not emacs */  #else  /* not emacs */
45    
# Line 45  Boston, MA 02111-1307, USA.  */ Line 47  Boston, MA 02111-1307, USA.  */
47    
48  #endif /* emacs */  #endif /* emacs */
49    
 Lisp_Object Qcharset, Qascii, Qeight_bit_control, Qeight_bit_graphic;  
 Lisp_Object Qunknown;  
50    
51  /* Declaration of special leading-codes.  */  /*** GENERAL NOTE on CODED CHARACTER SET (CHARSET) ***
52  int leading_code_private_11;    /* for private DIMENSION1 of 1-column */  
53  int leading_code_private_12;    /* for private DIMENSION1 of 2-column */    A coded character set ("charset" hereafter) is a meaningful
54  int leading_code_private_21;    /* for private DIMENSION2 of 1-column */    collection (i.e. language, culture, functionality, etc) of
55  int leading_code_private_22;    /* for private DIMENSION2 of 2-column */    characters.  Emacs handles multiple charsets at once.  In Emacs Lisp
56      code, a charset is represented by symbol.  In C code, a charset is
57  /* Declaration of special charsets.  The values are set by    represented by its ID number or by a pointer the struct charset.
58     Fsetup_special_charsets.  */  
59  int charset_latin_iso8859_1;    /* ISO8859-1 (Latin-1) */    The actual information about each charset is stored in two places.
60  int charset_jisx0208_1978;      /* JISX0208.1978 (Japanese Kanji old set) */    Lispy information is stored in the hash table Vcharset_hash_table as
61  int charset_jisx0208;           /* JISX0208.1983 (Japanese Kanji) */    a vector (charset attributes).  The other information is stored in
62  int charset_katakana_jisx0201;  /* JISX0201.Kana (Japanese Katakana) */    charset_table as struct charset.
63  int charset_latin_jisx0201;     /* JISX0201.Roman (Japanese Roman) */  
64  int charset_big5_1;             /* Big5 Level 1 (Chinese Traditional) */  */
 int charset_big5_2;             /* Big5 Level 2 (Chinese Traditional) */  
   
 Lisp_Object Qcharset_table;  
   
 /* A char-table containing information of each character set.  */  
 Lisp_Object Vcharset_table;  
   
 /* A vector of charset symbol indexed by charset-id.  This is used  
    only for returning charset symbol from C functions.  */  
 Lisp_Object Vcharset_symbol_table;  
65    
66  /* A list of charset symbols ever defined.  */  /* List of all charsets.  This variable is used only from Emacs
67       Lisp.  */
68  Lisp_Object Vcharset_list;  Lisp_Object Vcharset_list;
69    
70  /* Vector of translation table ever defined.  /* Hash table that contains attributes of each charset.  Keys are
71     ID of a translation table is used to index this vector.  */     charset symbols, and values are vectors of charset attributes.  */
72  Lisp_Object Vtranslation_table_vector;  Lisp_Object Vcharset_hash_table;
73    
74  /* A char-table for characters which may invoke auto-filling.  */  /* Table of struct charset.  */
75  Lisp_Object Vauto_fill_chars;  struct charset *charset_table;
76    
77  Lisp_Object Qauto_fill_chars;  static int charset_table_size;
78    int charset_table_used;
79  /* Tables used by macros BYTES_BY_CHAR_HEAD and WIDTH_BY_CHAR_HEAD.  */  
80  int bytes_by_char_head[256];  Lisp_Object Qcharsetp;
81  int width_by_char_head[256];  
82    /* Special charset symbols.  */
83    Lisp_Object Qascii;
84    Lisp_Object Qeight_bit_control;
85    Lisp_Object Qeight_bit_graphic;
86    Lisp_Object Qiso_8859_1;
87    Lisp_Object Qunicode;
88    
89    /* The corresponding charsets.  */
90    int charset_ascii;
91    int charset_8_bit_control;
92    int charset_8_bit_graphic;
93    int charset_iso_8859_1;
94    int charset_unicode;
95    
96    /* Value of charset attribute `charset-iso-plane'.  */
97    Lisp_Object Qgl, Qgr;
98    
99    /* The primary charset.  It is a charset of unibyte characters.  */
100    int charset_primary;
101    
102    /* List of charsets ordered by the priority.  */
103    Lisp_Object Vcharset_ordered_list;
104    
105    /* List of iso-2022 charsets.  */
106    Lisp_Object Viso_2022_charset_list;
107    
108    /* List of emacs-mule charsets.  */
109    Lisp_Object Vemacs_mule_charset_list;
110    
111    struct charset *emacs_mule_charset[256];
112    
113  /* Mapping table from ISO2022's charset (specified by DIMENSION,  /* Mapping table from ISO2022's charset (specified by DIMENSION,
114     CHARS, and FINAL-CHAR) to Emacs' charset.  */     CHARS, and FINAL-CHAR) to Emacs' charset.  */
115  int iso_charset_table[2][2][128];  int iso_charset_table[ISO_MAX_DIMENSION][ISO_MAX_CHARS][ISO_MAX_FINAL];
116    
117  /* Variables used locally in the macro FETCH_MULTIBYTE_CHAR.  */  Lisp_Object Vcharset_map_directory;
 unsigned char *_fetch_multibyte_char_p;  
 int _fetch_multibyte_char_len;  
118    
119  /* Offset to add to a non-ASCII value when inserting it.  */  Lisp_Object Vchar_unified_charset_table;
 int nonascii_insert_offset;  
120    
121  /* Translation table for converting non-ASCII unibyte characters  #define CODE_POINT_TO_INDEX(charset, code)                      \
122     to multibyte codes, or nil.  */    ((charset)->code_linear_p                                     \
123  Lisp_Object Vnonascii_translation_table;     ? (code) - (charset)->min_code                               \
124       : ((((code) >> 24) <= (charset)->code_space[13])             \
125  /* List of all possible generic characters.  */        && ((((code) >> 16) & 0xFF) <= (charset)->code_space[9])  \
126  Lisp_Object Vgeneric_character_list;        && ((((code) >> 8) & 0xFF) <= (charset)->code_space[5])   \
127          && (((code) & 0xFF) <= (charset)->code_space[1]))         \
128       ? (((((code) >> 24) - (charset)->code_space[12])             \
129           * (charset)->code_space[11])                             \
130          + (((((code) >> 16) & 0xFF) - (charset)->code_space[8])   \
131             * (charset)->code_space[7])                            \
132          + (((((code) >> 8) & 0xFF) - (charset)->code_space[4])    \
133             * (charset)->code_space[3])                            \
134          + (((code) & 0xFF) - (charset)->code_space[0]))           \
135       : -1)
136    
137    
138    /* Convert the character index IDX to code-point CODE for CHARSET.
139       It is assumed that IDX is in a valid range.  */
140    
141    #define INDEX_TO_CODE_POINT(charset, idx)                                  \
142      ((charset)->code_linear_p                                                \
143       ? (idx) + (charset)->min_code                                           \
144       : (((charset)->code_space[0] + (idx) % (charset)->code_space[2])        \
145          | (((charset)->code_space[4]                                         \
146              + ((idx) / (charset)->code_space[3] % (charset)->code_space[6])) \
147             << 8)                                                             \
148          | (((charset)->code_space[8]                                         \
149              + ((idx) / (charset)->code_space[7] % (charset)->code_space[10])) \
150             << 16)                                                            \
151          | (((charset)->code_space[12] + ((idx) / (charset)->code_space[11])) \
152             << 24)))
153    
154    
 void  
 invalid_character (c)  
      int c;  
 {  
   error ("Invalid character: 0%o, %d, 0x%x", c, c, c);  
 }  
155    
156  /* Parse string STR of length LENGTH and fetch information of a  /* Set to 1 when a charset map is loaded to warn that a buffer text
157     character at STR.  Set BYTES to the byte length the character     and a string data may be relocated.  */
158     occupies, CHARSET, C1, C2 to proper values of the character. */  int charset_map_loaded;
159    
160  #define SPLIT_MULTIBYTE_SEQ(str, length, bytes, charset, c1, c2)             \  /* Parse the mapping vector MAP which has this form:
161    do {                                                                       \          [CODE0 CHAR0 CODE1 CHAR1 ... ]
162      (c1) = *(str);                                                           \  
163      (bytes) = BYTES_BY_CHAR_HEAD (c1);                                       \     If CONTROL_FLAG is 0, setup CHARSET->min_char and CHARSET->max_char.
164      if ((bytes) == 1)                                                        \  
165        (charset) = ASCII_BYTE_P (c1) ? CHARSET_ASCII : CHARSET_8_BIT_GRAPHIC; \     If CONTROL_FLAG is 1, setup CHARSET->min_char, CHARSET->max_char,
166      else if ((bytes) == 2)                                                   \     CHARSET->decoder, and CHARSET->encoder.
167        {                                                                      \  
168          if ((c1) == LEADING_CODE_8_BIT_CONTROL)                              \     If CONTROL_FLAG is 2, setup CHARSET->deunifier and
169            (charset) = CHARSET_8_BIT_CONTROL, (c1) = (str)[1] - 0x20;         \     Vchar_unify_table.  If Vchar_unified_charset_table is non-nil,
170          else                                                                 \     setup it too.  */
171            (charset) = (c1), (c1) = (str)[1] & 0x7F;                          \  
172        }                                                                      \  static void
173      else if ((bytes) == 3)                                                   \  parse_charset_map (charset, map, control_flag)
174        {                                                                      \    struct charset *charset;
175          if ((c1) < LEADING_CODE_PRIVATE_11)                                  \    Lisp_Object map;
176            (charset) = (c1), (c1) = (str)[1] & 0x7F, (c2) = (str)[2] & 0x7F;  \    int control_flag;
177          else                                                                 \  {
178            (charset) = (str)[1], (c1) = (str)[2] & 0x7F;                      \    Lisp_Object vec, table;
179        }                                                                      \    unsigned min_code = CHARSET_MIN_CODE (charset);
180      else                                                                     \    unsigned max_code = CHARSET_MAX_CODE (charset);
181        (charset) = (str)[1], (c1) = (str)[2] & 0x7F, (c2) = (str)[3] & 0x7F;  \    int ascii_compatible_p = charset->ascii_compatible_p;
182    } while (0)    int min_char, max_char, nonascii_min_char;
183      int size;
184  /* 1 if CHARSET, C1, and C2 compose a valid character, else 0.  */    int i;
185  #define CHAR_COMPONENTS_VALID_P(charset, c1, c2)        \    int first;
186    ((charset) == CHARSET_ASCII                           \    unsigned char *fast_map = charset->fast_map;
    ? ((c1) >= 0 && (c1) <= 0x7F)                        \  
    : ((charset) == CHARSET_8_BIT_CONTROL                \  
       ? ((c1) >= 0x80 && (c1) <= 0x9F)                  \  
       : ((charset) == CHARSET_8_BIT_GRAPHIC             \  
          ? ((c1) >= 0x80 && (c1) <= 0xFF)               \  
          : (CHARSET_DIMENSION (charset) == 1            \  
             ? ((c1) >= 0x20 && (c1) <= 0x7F)            \  
             : ((c1) >= 0x20 && (c1) <= 0x7F             \  
                && (c2) >= 0x20 && (c2) <= 0x7F)))))  
   
 /* Store multi-byte form of the character C in STR.  The caller should  
    allocate at least 4-byte area at STR in advance.  Returns the  
    length of the multi-byte form.  If C is an invalid character code,  
    return -1.  */  
187    
188  int    if (control_flag)
189  char_to_string_1 (c, str)      {
190       int c;        int n = CODE_POINT_TO_INDEX (charset, max_code) + 1;
191       unsigned char *str;        unsigned invalid_code = CHARSET_INVALID_CODE (charset);
192  {  
193    unsigned char *p = str;        table = Fmake_char_table (Qnil, make_number (invalid_code));
194          if (control_flag == 1)
195            vec = Fmake_vector (make_number (n), make_number (-1));
196          else if (! CHAR_TABLE_P (Vchar_unify_table))
197            Vchar_unify_table = Fmake_char_table (Qnil, make_number (-1));
198    
199    if (c & CHAR_MODIFIER_MASK)   /* This includes the case C is negative.  */        charset_map_loaded = 1;
200        }
201    
202      size = ASIZE (map);
203      nonascii_min_char = MAX_CHAR;
204      CHARSET_COMPACT_CODES_P (charset) = 1;
205      for (first = 1, i = 0; i < size; i += 2)
206      {      {
207        /* Multibyte character can't have a modifier bit.  */        Lisp_Object val;
208        if (! SINGLE_BYTE_CHAR_P ((c & ~CHAR_MODIFIER_MASK)))        unsigned code, temp;
209          return -1;        int c, char_index;
210    
211        /* For Meta, Shift, and Control modifiers, we need special care.  */        val = AREF (map, i);
212        if (c & CHAR_META)        CHECK_NATNUM (val);
213          {        code = XFASTINT (val);
214            /* Move the meta bit to the right place for a string.  */        val = AREF (map, i + 1);
215            c = (c & ~CHAR_META) | 0x80;        CHECK_NATNUM (val);
216          }        c = XFASTINT (val);
217        if (c & CHAR_SHIFT)  
218          {        if (code < min_code || code > max_code)
219            /* Shift modifier is valid only with [A-Za-z].  */          continue;
220            if ((c & 0377) >= 'A' && (c & 0377) <= 'Z')        char_index = CODE_POINT_TO_INDEX (charset, code);
221              c &= ~CHAR_SHIFT;        if (char_index < 0
222            else if ((c & 0377) >= 'a' && (c & 0377) <= 'z')            || c > MAX_CHAR)
223              c = (c & ~CHAR_SHIFT) - ('a' - 'A');          continue;
224          }          
225        if (c & CHAR_CTL)        if (control_flag < 2)
226          {          {
227            /* Simulate the code in lread.c.  */            if (first)
228            /* Allow `\C- ' and `\C-?'.  */              {
229            if (c == (CHAR_CTL | ' '))                min_char = max_char = c;
230              c = 0;                first = 0;
231            else if (c == (CHAR_CTL | '?'))              }
232              c = 127;            else if (c > max_char)
233            /* ASCII control chars are made from letters (both cases),              max_char = c;
234               as well as the non-letters within 0100...0137.  */            else if (c < min_char)
235            else if ((c & 0137) >= 0101 && (c & 0137) <= 0132)              min_char = c;
236              c &= (037 | (~0177 & ~CHAR_CTL));            if (ascii_compatible_p && ! ASCII_BYTE_P (c)
237            else if ((c & 0177) >= 0100 && (c & 0177) <= 0137)                && c < nonascii_min_char)
238              c &= (037 | (~0177 & ~CHAR_CTL));              nonascii_min_char = c;
239    
240              CHARSET_FAST_MAP_SET (c, fast_map);
241          }          }
242    
243        /* If C still has any modifier bits, just ignore it.  */        if (control_flag)
       c &= ~CHAR_MODIFIER_MASK;  
     }  
     
   if (SINGLE_BYTE_CHAR_P (c))  
     {  
       if (ASCII_BYTE_P (c) || c >= 0xA0)  
         *p++ = c;  
       else  
244          {          {
245            *p++ = LEADING_CODE_8_BIT_CONTROL;            if (control_flag == 1)
246            *p++ = c + 0x20;              {
247                  if (char_index >= ASIZE (vec))
248                    abort ();
249                  ASET (vec, char_index, make_number (c));
250                  if (code > 0x7FFFFFF)
251                    {
252                      CHAR_TABLE_SET (table, c,
253                                      Fcons (make_number (code >> 16),
254                                             make_number (code & 0xFFFF)));
255                      CHARSET_COMPACT_CODES_P (charset) = 0;
256                    }
257                  else
258                    CHAR_TABLE_SET (table, c, make_number (code));
259                }
260              else
261                {
262                  int c1 = DECODE_CHAR (charset, code);
263                  if (c1 >= 0)
264                    {
265                      CHAR_TABLE_SET (table, c, make_number (c1));
266                      CHAR_TABLE_SET (Vchar_unify_table, c1, c);
267                      if (CHAR_TABLE_P (Vchar_unified_charset_table))
268                        CHAR_TABLE_SET (Vchar_unified_charset_table, c1,
269                                        CHARSET_NAME (charset));
270                    }
271                }
272          }          }
273      }      }
   else if (CHAR_VALID_P (c, 0))  
     {  
       int charset, c1, c2;  
274    
275        SPLIT_CHAR (c, charset, c1, c2);    if (control_flag < 2)
276        {
277        if (charset >= LEADING_CODE_EXT_11)        CHARSET_MIN_CHAR (charset) = (ascii_compatible_p
278          *p++ = (charset < LEADING_CODE_EXT_12                                      ? nonascii_min_char : min_char);
279                  ? LEADING_CODE_PRIVATE_11        CHARSET_MAX_CHAR (charset) = max_char;
280                  : (charset < LEADING_CODE_EXT_21        if (control_flag)
281                     ? LEADING_CODE_PRIVATE_12          {
282                     : (charset < LEADING_CODE_EXT_22            CHARSET_DECODER (charset) = vec;
283                        ? LEADING_CODE_PRIVATE_21            CHARSET_ENCODER (charset) = table;
                       : LEADING_CODE_PRIVATE_22)));  
       *p++ = charset;  
       if ((c1 > 0 && c1 < 32) || (c2 > 0 && c2 < 32))  
         return -1;  
       if (c1)  
         {  
           *p++ = c1 | 0x80;  
           if (c2 > 0)  
             *p++ = c2 | 0x80;  
284          }          }
285      }      }
286    else    else
287      return -1;      CHARSET_DEUNIFIER (charset) = table;  
   
   return (p - str);  
288  }  }
289    
290    
291  /* Store multi-byte form of the character C in STR.  The caller should  /* Read a hexadecimal number (preceded by "0x") from the file FP while
292     allocate at least 4-byte area at STR in advance.  Returns the     paying attention to comment charcter '#'.  */
    length of the multi-byte form.  If C is an invalid character code,  
    signal an error.  
   
    Use macro `CHAR_STRING (C, STR)' instead of calling this function  
    directly if C can be an ASCII character.  */  
293    
294  int  static INLINE unsigned
295  char_to_string (c, str)  read_hex (fp, eof)
296       int c;       FILE *fp;
297       unsigned char *str;       int *eof;
298  {  {
299    int len;    int c;
300    len = char_to_string_1 (c, str);    unsigned n;
301    if (len == -1)  
302      invalid_character (c);    while ((c = getc (fp)) != EOF)
303    return len;      {
304          if (c == '#' || c == ' ')
305            {
306              while ((c = getc (fp)) != EOF && c != '\n');
307            }
308          else if (c == '0')
309            {
310              if ((c = getc (fp)) == EOF || c == 'x')
311                break;
312            }
313        }      
314      if (c == EOF)
315        {
316          *eof = 1;
317          return 0;
318        }
319      *eof = 0;
320      n = 0;
321      if (c == 'x')
322        while ((c = getc (fp)) != EOF && isxdigit (c))
323          n = ((n << 4)
324               | (c <= '9' ? c - '0' : c <= 'F' ? c - 'A' + 10 : c - 'a' + 10));
325      else
326        while ((c = getc (fp)) != EOF && isdigit (c))
327          n = (n * 10) + c - '0';
328      return n;
329  }  }
330    
331    
332  /* Return the non-ASCII character corresponding to multi-byte form at  /* Return a mapping vector for CHARSET loaded from MAPFILE.
333     STR of length LEN.  If ACTUAL_LEN is not NULL, store the byte     Each line of MAPFILE has this form:
334     length of the multibyte form in *ACTUAL_LEN.          0xAAAA 0xBBBB
335       where 0xAAAA is a code-point and 0xBBBB is the corresponding
336       character code.
337       The returned vector has this form:
338            [ CODE1 CHAR1 CODE2 CHAR2 .... ]
339    */
340    
341    static Lisp_Object
342    load_charset_map (charset, mapfile)
343         struct charset *charset;
344         Lisp_Object mapfile;
345    {
346      int fd;
347      FILE *fp;
348      int num;
349      unsigned *numbers_table[256];
350      int numbers_table_used;
351      unsigned *numbers;
352      int eof;
353      Lisp_Object suffixes;
354      Lisp_Object vec;
355      int i;
356    
357     Use macros STRING_CHAR or STRING_CHAR_AND_LENGTH instead of calling    suffixes = Fcons (build_string (".map"),
358     this function directly if you want ot handle ASCII characters as                      Fcons (build_string (".TXT"), Qnil));
    well.  */  
359    
360  int    fd = openp (Fcons (Vcharset_map_directory, Qnil), mapfile, suffixes,
361  string_to_char (str, len, actual_len)                NULL, 0);
362       const unsigned char *str;    if (fd < 0
363       int len, *actual_len;        || ! (fp = fdopen (fd, "r")))
364  {      {
365    int c, bytes, charset, c1, c2;        add_to_log ("Failure in loading charset map: %S", mapfile, Qnil);
366          return Qnil;
367    SPLIT_MULTIBYTE_SEQ (str, len, bytes, charset, c1, c2);      }
   c = MAKE_CHAR (charset, c1, c2);  
   if (actual_len)  
     *actual_len = bytes;  
   return c;  
 }  
368    
369  /* Return the length of the multi-byte form at string STR of length LEN.    numbers_table_used = 0;
370     Use the macro MULTIBYTE_FORM_LENGTH instead.  */    num = 0;
371  int    eof = 0;
372  multibyte_form_length (str, len)    while (1)
373       const unsigned char *str;      {
374       int len;        unsigned n = read_hex (fp, &eof);
 {  
   int bytes;  
375    
376    PARSE_MULTIBYTE_SEQ (str, len, bytes);        if (eof)
377    return bytes;          break;
378  }        if ((num % 0x10000) == 0)
379            {
380              if (numbers_table_used == 256)
381                break;
382              numbers = (unsigned *) alloca (sizeof (unsigned) * 0x10000);
383              numbers_table[numbers_table_used++] = numbers;          
384            }
385          *numbers++ = n;
386          num++;
387        }
388      fclose (fp);
389      close (fd);
390    
391  /* Check multibyte form at string STR of length LEN and set variables    vec = Fmake_vector (make_number (num), Qnil);
392     pointed by CHARSET, C1, and C2 to charset and position codes of the    for (i = 0; i < num; i++, numbers++)
393     character at STR, and return 0.  If there's no multibyte character,      {
394     return -1.  This should be used only in the macro SPLIT_STRING        if ((i % 0x10000) == 0)
395     which checks range of STR in advance.  */          numbers = numbers_table[i / 0x10000];
396          ASET (vec, i, make_number (*numbers));
397        }
398    
399  int    charset_map_loaded = 1;
 split_string (str, len, charset, c1, c2)  
      const unsigned char *str;  
      unsigned char *c1, *c2;  
      int len, *charset;  
 {  
   register int bytes, cs, code1, code2 = -1;  
400    
401    SPLIT_MULTIBYTE_SEQ (str, len, bytes, cs, code1, code2);    return vec;
   if (cs == CHARSET_ASCII)  
     return -1;  
   *charset = cs;  
   *c1 = code1;  
   *c2 = code2;  
   return 0;  
402  }  }
403    
404  /* Return 1 iff character C has valid printable glyph.  static void
405     Use the macro CHAR_PRINTABLE_P instead.  */  load_charset (charset)
406  int       struct charset *charset;
 char_printable_p (c)  
      int c;  
407  {  {
408    int charset, c1, c2;    if (CHARSET_METHOD (charset) == CHARSET_METHOD_MAP_DEFERRED)
409        {
410          Lisp_Object map;
411    
412    if (ASCII_BYTE_P (c))        map = CHARSET_MAP (charset);
413      return 1;        if (STRINGP (map))
414    else if (SINGLE_BYTE_CHAR_P (c))          map = load_charset_map (charset, map);
415      return 0;        parse_charset_map (charset, map, 1);
416    else if (c >= MAX_CHAR)        CHARSET_METHOD (charset) = CHARSET_METHOD_MAP;
417      return 0;      }
     
   SPLIT_CHAR (c, charset, c1, c2);  
   if (! CHARSET_DEFINED_P (charset))  
     return 0;  
   if (CHARSET_CHARS (charset) == 94  
       ? c1 <= 32 || c1 >= 127  
       : c1 < 32)  
     return 0;  
   if (CHARSET_DIMENSION (charset) == 2  
       && (CHARSET_CHARS (charset) == 94  
           ? c2 <= 32 || c2 >= 127  
           : c2 < 32))  
     return 0;  
   return 1;  
418  }  }
419    
420  /* Translate character C by translation table TABLE.  If C  
421     is negative, translate a character specified by CHARSET, C1, and C2  DEFUN ("charsetp", Fcharsetp, Scharsetp, 1, 1, 0,
422     (C1 and C2 are code points of the character).  If no translation is         doc: /* Return non-nil if and only if OBJECT is a charset.*/)
423     found in TABLE, return C.  */       (object)
424  int       Lisp_Object object;
 translate_char (table, c, charset, c1, c2)  
      Lisp_Object table;  
      int c, charset, c1, c2;  
425  {  {
426    Lisp_Object ch;    return (CHARSETP (object) ? Qt : Qnil);
427    int alt_charset, alt_c1, alt_c2, dimension;  }
428    
   if (c < 0) c = MAKE_CHAR (charset, (c1 & 0x7F) , (c2 & 0x7F));  
   if (!CHAR_TABLE_P (table)  
       || (ch = Faref (table, make_number (c)), !NATNUMP (ch)))  
     return c;  
   
   SPLIT_CHAR (XFASTINT (ch), alt_charset, alt_c1, alt_c2);  
   dimension = CHARSET_DIMENSION (alt_charset);  
   if ((dimension == 1 && alt_c1 > 0) || (dimension == 2 && alt_c2 > 0))  
     /* CH is not a generic character, just return it.  */  
     return XFASTINT (ch);  
   
   /* Since CH is a generic character, we must return a specific  
      charater which has the same position codes as C from CH.  */  
   if (charset < 0)  
     SPLIT_CHAR (c, charset, c1, c2);  
   if (dimension != CHARSET_DIMENSION (charset))  
     /* We can't make such a character because of dimension mismatch.  */  
     return c;  
   return MAKE_CHAR (alt_charset, c1, c2);  
 }  
   
 /* Convert the unibyte character C to multibyte based on  
    Vnonascii_translation_table or nonascii_insert_offset.  If they can't  
    convert C to a valid multibyte character, convert it based on  
    DEFAULT_NONASCII_INSERT_OFFSET which makes C a Latin-1 character.  */  
429    
430  int  void
431  unibyte_char_to_multibyte (c)  map_charset_chars (c_function, function, charset_symbol, arg)
432       int c;       void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object);
433  {       Lisp_Object function, charset_symbol, arg;
434    if (c < 0400 && c >= 0200)  {
435      int id;
436      struct charset *charset;
437      Lisp_Object range;
438    
439      CHECK_CHARSET_GET_ID (charset_symbol, id);
440      charset = CHARSET_FROM_ID (id);
441    
442      if (CHARSET_METHOD (charset) == CHARSET_METHOD_MAP_DEFERRED)  
443        load_charset (charset);
444    
445      if (CHARSET_METHOD (charset) == CHARSET_METHOD_OFFSET)
446        {
447          range = Fcons (make_number (CHARSET_MIN_CHAR (charset)),
448                         make_number (CHARSET_MAX_CHAR (charset)));
449          if (NILP (function))
450            (*c_function) (arg, range, Qnil);
451          else
452            call2 (function, range, arg);
453        }
454      else if (CHARSET_METHOD (charset) == CHARSET_METHOD_MAP)
455      {      {
456        int c_save = c;        if (! CHAR_TABLE_P (CHARSET_ENCODER (charset)))
457            return;
458        if (! NILP (Vnonascii_translation_table))        if (CHARSET_ASCII_COMPATIBLE_P (charset))
459          {          {
460            c = XINT (Faref (Vnonascii_translation_table, make_number (c)));            range = Fcons (make_number (0), make_number (127));
461            if (c >= 0400 && ! char_valid_p (c, 0))            if (NILP (function))
462              c = c_save + DEFAULT_NONASCII_INSERT_OFFSET;              (*c_function) (arg, range, Qnil);
463              else
464                call2 (function, range, arg);
465          }          }
466        else if (c >= 0240 && nonascii_insert_offset > 0)        map_char_table (c_function, function, CHARSET_ENCODER (charset), arg,
467                          0, NULL);
468        }
469      else                          /* i.e. CHARSET_METHOD_PARENT */
470        {
471          int from, to, c;
472          unsigned code;
473          int i, j, k, l;
474          int *code_space = CHARSET_CODE_SPACE (charset);
475          Lisp_Object val;
476    
477          range = Fcons (Qnil, Qnil);
478          from = to = -2;
479          for (i = code_space[12]; i <= code_space[13]; i++)
480            for (j = code_space[8]; j <= code_space[9]; j++)
481              for (k = code_space[4]; k <= code_space[5]; k++)
482                for (l = code_space[0]; l <= code_space[1]; l++)
483                  {
484                    code = (i << 24) | (j << 16) | (k << 8) | l;
485                    c = DECODE_CHAR (charset, code);
486                    if (c == to + 1)
487                      {
488                        to++;
489                        continue;
490                      }
491                    if (from >= 0)
492                      {
493                        if (from < to)
494                          {
495                            XSETCAR (range, make_number (from));
496                            XSETCDR (range, make_number (to));
497                            val = range;
498                          }
499                        else
500                          val = make_number (from);
501                        if (NILP (function))
502                          (*c_function) (arg, val, Qnil);
503                        else
504                          call2 (function, val, arg);
505                      }
506                    from = to = (c < 0 ? -2 : c);
507                  }
508          if (from >= 0)
509          {          {
510            c += nonascii_insert_offset;            if (from < to)
511            if (c < 0400 || ! char_valid_p (c, 0))              {
512              c = c_save + DEFAULT_NONASCII_INSERT_OFFSET;                XSETCAR (range, make_number (from));
513                  XSETCDR (range, make_number (to));
514                  val = range;
515                }
516              else
517                val = make_number (from);
518              if (NILP (function))
519                (*c_function) (arg, val, Qnil);
520              else
521                call2 (function, val, arg);
522          }          }
       else if (c >= 0240)  
         c = c_save + DEFAULT_NONASCII_INSERT_OFFSET;  
523      }      }
524    return c;  }
525      
526    DEFUN ("map-charset-chars", Fmap_charset_chars, Smap_charset_chars, 2, 3, 0,
527           doc: /* Call FUNCTION for each characters in CHARSET.
528    FUNCTION is called with three arguments; FROM, TO, and the 3rd optional
529    argument ARG.
530    FROM and TO indicates a range of character sequence that are contained
531    in CHARSET.  */)
532         (function, charset, arg)
533           Lisp_Object function, charset, arg;
534    {
535      map_charset_chars (NULL, function, charset, arg);
536      return Qnil;
537  }  }
538    
539    
540  /* Convert the multibyte character C to unibyte 8-bit character based  /* Define a charset according to the arguments.  The Nth argument is
541     on Vnonascii_translation_table or nonascii_insert_offset.  If     the Nth attribute of the charset (the last attribute `charset-id'
542     REV_TBL is non-nil, it should be a reverse table of     is not included).  See the docstring of `define-charset' for the
543     Vnonascii_translation_table, i.e. what given by:     detail.  */
544       Fchar_table_extra_slot (Vnonascii_translation_table, make_number (0))  */  
545    DEFUN ("define-charset-internal", Fdefine_charset_internal,
546  int         Sdefine_charset_internal, charset_arg_max, MANY, 0,
547  multibyte_char_to_unibyte (c, rev_tbl)         doc: /* For internal use only.  */)
548       int c;       (nargs, args)
549       Lisp_Object rev_tbl;       int nargs;
550         Lisp_Object *args;
551  {  {
552    if (!SINGLE_BYTE_CHAR_P (c))    /* Charset attr vector.  */
553      Lisp_Object attrs;
554      Lisp_Object val;
555      unsigned hash_code;
556      struct Lisp_Hash_Table *hash_table = XHASH_TABLE (Vcharset_hash_table);
557      int i;
558      struct charset charset;
559      int id;
560      int dimension;
561      int new_definition_p;
562      int nchars;
563    
564      if (nargs != charset_arg_max)
565        return Fsignal (Qwrong_number_of_arguments,
566                        Fcons (intern ("define-charset-internal"),
567                               make_number (nargs)));
568    
569      attrs = Fmake_vector (make_number (charset_attr_max), Qnil);
570    
571      CHECK_SYMBOL (args[charset_arg_name]);
572      ASET (attrs, charset_name, args[charset_arg_name]);
573    
574      val = args[charset_arg_code_space];
575      for (i = 0, dimension = 0, nchars = 1; i < 4; i++)
576        {
577          int min_byte, max_byte;
578    
579          min_byte = XINT (Faref (val, make_number (i * 2)));
580          max_byte = XINT (Faref (val, make_number (i * 2 + 1)));
581          if (min_byte < 0 || min_byte > max_byte || max_byte >= 256)
582            error ("Invalid :code-space value");
583          charset.code_space[i * 4] = min_byte;
584          charset.code_space[i * 4 + 1] = max_byte;
585          charset.code_space[i * 4 + 2] = max_byte - min_byte + 1;
586          nchars *= charset.code_space[i * 4 + 2];
587          charset.code_space[i * 4 + 3] = nchars;
588          if (max_byte > 0)
589            dimension = i + 1;
590        }
591    
592      val = args[charset_arg_dimension];
593      if (NILP (val))
594        charset.dimension = dimension;
595      else
596      {      {
597        int c_save = c;        CHECK_NATNUM (val);
598          charset.dimension = XINT (val);
599          if (charset.dimension < 1 || charset.dimension > 4)
600            args_out_of_range_3 (val, make_number (1), make_number (4));
601        }
602    
603      charset.code_linear_p
604        = (charset.dimension == 1
605           || (charset.code_space[2] == 256
606               && (charset.dimension == 2
607                   || (charset.code_space[6] == 256
608                       && (charset.dimension == 3
609                           || charset.code_space[10] == 256)))));
610    
611      charset.iso_chars_96 = charset.code_space[2] == 96;
612    
613      charset.min_code = (charset.code_space[0]
614                          | (charset.code_space[4] << 8)
615                          | (charset.code_space[8] << 16)
616                          | (charset.code_space[12] << 24));
617      charset.max_code = (charset.code_space[1]
618                          | (charset.code_space[5] << 8)
619                          | (charset.code_space[9] << 16)
620                          | (charset.code_space[13] << 24));
621    
622        if (! CHAR_TABLE_P (rev_tbl)    val = args[charset_arg_invalid_code];
623            && CHAR_TABLE_P (Vnonascii_translation_table))    if (NILP (val))
624          rev_tbl = Fchar_table_extra_slot (Vnonascii_translation_table,      {
625                                            make_number (0));        if (charset.min_code > 0)
626        if (CHAR_TABLE_P (rev_tbl))          charset.invalid_code = 0;
         {  
           Lisp_Object temp;  
           temp = Faref (rev_tbl, make_number (c));  
           if (INTEGERP (temp))  
             c = XINT (temp);  
           if (c >= 256)  
             c = (c_save & 0177) + 0200;  
         }  
627        else        else
628          {          {
629            if (nonascii_insert_offset > 0)            XSETINT (val, charset.max_code + 1);
630              c -= nonascii_insert_offset;            if (XINT (val) == charset.max_code + 1)
631            if (c < 128 || c >= 256)              charset.invalid_code = charset.max_code + 1;
632              c = (c_save & 0177) + 0200;            else
633                error ("Attribute :invalid-code must be specified");
634          }          }
635      }      }
636      else
637        {
638          CHECK_NATNUM (val);
639          charset.invalid_code = XFASTINT (val);
640        }
641    
642    return c;    val = args[charset_arg_iso_final];
643  }    if (NILP (val))
644        charset.iso_final = -1;
645      else
646        {
647          CHECK_NUMBER (val);
648          if (XINT (val) < '0' || XINT (val) > 127)
649            error ("Invalid iso-final-char: %d", XINT (val));
650          charset.iso_final = XINT (val);
651        }
652        
653      val = args[charset_arg_iso_revision];
654      if (NILP (val))
655        charset.iso_revision = -1;
656      else
657        {
658          CHECK_NUMBER (val);
659          if (XINT (val) > 63)
660            args_out_of_range (make_number (63), val);
661          charset.iso_revision = XINT (val);
662        }
663    
664      val = args[charset_arg_emacs_mule_id];
665  /* Update the table Vcharset_table with the given arguments (see the    if (NILP (val))
666     document of `define-charset' for the meaning of each argument).      charset.emacs_mule_id = -1;
667     Several other table contents are also updated.  The caller should    else
668     check the validity of CHARSET-ID and the remaining arguments in      {
669     advance.  */        CHECK_NATNUM (val);
670          if ((XINT (val) > 0 && XINT (val) <= 128) || XINT (val) >= 256)
671            error ("Invalid emacs-mule-id: %d", XINT (val));
672          charset.emacs_mule_id = XINT (val);
673        }
674    
675  void    charset.ascii_compatible_p = ! NILP (args[charset_arg_ascii_compatible_p]);
676  update_charset_table (charset_id, dimension, chars, width, direction,  
677                        iso_final_char, iso_graphic_plane,    charset.supplementary_p = ! NILP (args[charset_arg_supplementary_p]);
678                        short_name, long_name, description)  
679       Lisp_Object charset_id, dimension, chars, width, direction;    charset.unified_p = 0;
680       Lisp_Object iso_final_char, iso_graphic_plane;  
681       Lisp_Object short_name, long_name, description;    bzero (charset.fast_map, sizeof (charset.fast_map));
682  {  
683    int charset = XINT (charset_id);    if (! NILP (args[charset_arg_code_offset]))
684    int bytes;      {
685    unsigned char leading_code_base, leading_code_ext;        val = args[charset_arg_code_offset];
686          CHECK_NUMBER (val);
687    if (NILP (CHARSET_TABLE_ENTRY (charset)))  
688      CHARSET_TABLE_ENTRY (charset)        charset.method = CHARSET_METHOD_OFFSET;
689        = Fmake_vector (make_number (CHARSET_MAX_IDX), Qnil);        charset.code_offset = XINT (val);
690    
691    if (NILP (long_name))        i = CODE_POINT_TO_INDEX (&charset, charset.min_code);
692      long_name = short_name;        charset.min_char = i + charset.code_offset;
693    if (NILP (description))        i = CODE_POINT_TO_INDEX (&charset, charset.max_code);
694      description = long_name;        charset.max_char = i + charset.code_offset;
695          if (charset.max_char > MAX_CHAR)
696    /* Get byte length of multibyte form, base leading-code, and          error ("Unsupported max char: %d", charset.max_char);
697       extended leading-code of the charset.  See the comment under the  
698       title "GENERAL NOTE on CHARACTER SET (CHARSET)" in charset.h.  */        for (i = charset.min_char; i < 0x10000 && i <= charset.max_char;
699    bytes = XINT (dimension);             i += 128)
700    if (charset < MIN_CHARSET_PRIVATE_DIMENSION1)          CHARSET_FAST_MAP_SET (i, charset.fast_map);
701      {        for (; i <= charset.max_char; i += 0x1000)
702        /* Official charset, it doesn't have an extended leading-code.  */          CHARSET_FAST_MAP_SET (i, charset.fast_map);
       if (charset != CHARSET_ASCII && charset != CHARSET_8_BIT_GRAPHIC)  
         bytes += 1; /* For a base leading-code.  */  
       leading_code_base = charset;  
       leading_code_ext = 0;  
703      }      }
704    else    else if (! NILP (args[charset_arg_map]))
705      {      {
706        /* Private charset.  */        val = args[charset_arg_map];
707        bytes += 2; /* For base and extended leading-codes.  */        ASET (attrs, charset_map, val);
708        leading_code_base        if (STRINGP (val))
709          = (charset < LEADING_CODE_EXT_12          val = load_charset_map (&charset, val);
710             ? LEADING_CODE_PRIVATE_11        CHECK_VECTOR (val);
711             : (charset < LEADING_CODE_EXT_21        parse_charset_map (&charset, val, 0);
712                ? LEADING_CODE_PRIVATE_12        charset.method = CHARSET_METHOD_MAP_DEFERRED;
713                : (charset < LEADING_CODE_EXT_22      }
714                   ? LEADING_CODE_PRIVATE_21    else if (! NILP (args[charset_arg_parents]))
715                   : LEADING_CODE_PRIVATE_22)));      {
716        leading_code_ext = charset;        val = args[charset_arg_parents];
717        if (BYTES_BY_CHAR_HEAD (leading_code_base) != bytes)        CHECK_LIST (val);
718          error ("Invalid dimension for the charset-ID %d", charset);        charset.method = CHARSET_METHOD_INHERIT;
719      }        val = Fcopy_sequence (val);
720          ASET (attrs, charset_parents, val);
   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;  
   CHARSET_TABLE_INFO (charset, CHARSET_CHARS_IDX) = chars;  
   CHARSET_TABLE_INFO (charset, CHARSET_WIDTH_IDX) = width;  
   CHARSET_TABLE_INFO (charset, CHARSET_DIRECTION_IDX) = direction;  
   CHARSET_TABLE_INFO (charset, CHARSET_LEADING_CODE_BASE_IDX)  
     = make_number (leading_code_base);  
   CHARSET_TABLE_INFO (charset, CHARSET_LEADING_CODE_EXT_IDX)  
     = make_number (leading_code_ext);  
   CHARSET_TABLE_INFO (charset, CHARSET_ISO_FINAL_CHAR_IDX) = iso_final_char;  
   CHARSET_TABLE_INFO (charset, CHARSET_ISO_GRAPHIC_PLANE_IDX)  
     = iso_graphic_plane;  
   CHARSET_TABLE_INFO (charset, CHARSET_SHORT_NAME_IDX) = short_name;  
   CHARSET_TABLE_INFO (charset, CHARSET_LONG_NAME_IDX) = long_name;  
   CHARSET_TABLE_INFO (charset, CHARSET_DESCRIPTION_IDX) = description;  
   CHARSET_TABLE_INFO (charset, CHARSET_PLIST_IDX) = Qnil;  
721    
722    {        charset.min_char = MAX_CHAR;
723      /* If we have already defined a charset which has the same        charset.max_char = 0;
724         DIMENSION, CHARS and ISO-FINAL-CHAR but the different        for (; ! NILP (val); val = Fcdr (val))
725         DIRECTION, we must update the entry REVERSE-CHARSET of both          {
726         charsets.  If there's no such charset, the value of the entry            Lisp_Object elt, car_part, cdr_part;
727         is set to nil.  */            int this_id, offset;
728      int i;            struct charset *this_charset;
729    
730      for (i = 0; i <= MAX_CHARSET; i++)            elt = Fcar (val);
731        if (!NILP (CHARSET_TABLE_ENTRY (i)))            if (CONSP (elt))
         {  
           if (CHARSET_DIMENSION (i) == XINT (dimension)  
               && CHARSET_CHARS (i) == XINT (chars)  
               && CHARSET_ISO_FINAL_CHAR (i) == XINT (iso_final_char)  
               && CHARSET_DIRECTION (i) != XINT (direction))  
732              {              {
733                CHARSET_TABLE_INFO (charset, CHARSET_REVERSE_CHARSET_IDX)                car_part = XCAR (elt);
734                  = make_number (i);                cdr_part = XCDR (elt);
735                CHARSET_TABLE_INFO (i, CHARSET_REVERSE_CHARSET_IDX) = charset_id;                CHECK_CHARSET_GET_ID (car_part, this_id);
736                break;                CHECK_NUMBER (cdr_part);
737                  offset = XINT (cdr_part);
738              }              }
739              else
740                {
741                  CHECK_CHARSET_GET_ID (elt, this_id);
742                  offset = 0;
743                }
744              XSETCAR (val, Fcons (make_number (this_id), make_number (offset)));
745    
746              this_charset = CHARSET_FROM_ID (this_id);
747              if (charset.min_char > this_charset->min_char)
748                charset.min_char = this_charset->min_char;
749              if (charset.max_char < this_charset->max_char)
750                charset.max_char = this_charset->max_char;
751              for (i = 0; i < 190; i++)
752                charset.fast_map[i] |= this_charset->fast_map[i];
753          }          }
754      if (i > MAX_CHARSET)      }
755        /* No such a charset.  */    else
756        CHARSET_TABLE_INFO (charset, CHARSET_REVERSE_CHARSET_IDX)      error ("None of :code-offset, :map, :parents are specified");
         = make_number (-1);  
   }  
757    
758    if (charset != CHARSET_ASCII && charset != CHARSET_8_BIT_GRAPHIC    val = args[charset_arg_unify_map];
759        && charset < MIN_CHARSET_PRIVATE_DIMENSION1)    if (! NILP (val) && !STRINGP (val))
760        CHECK_VECTOR (val);
761      ASET (attrs, charset_unify_map, val);
762    
763      CHECK_LIST (args[charset_arg_plist]);
764      ASET (attrs, charset_plist, args[charset_arg_plist]);
765    
766      charset.hash_index = hash_lookup (hash_table, args[charset_arg_name],
767                                        &hash_code);
768      if (charset.hash_index >= 0)
769        {
770          new_definition_p = 0;
771          HASH_VALUE (hash_table, charset.hash_index) = attrs;
772        }
773      else
774      {      {
775        bytes_by_char_head[leading_code_base] = bytes;        charset.hash_index = hash_put (hash_table, args[charset_arg_name], attrs,
776        width_by_char_head[leading_code_base] = XINT (width);                                       hash_code);
777          if (charset_table_used == charset_table_size)
778            {
779              charset_table_size += 256;
780              charset_table
781                = ((struct charset *)
782                   xrealloc (charset_table,
783                             sizeof (struct charset) * charset_table_size));
784            }
785          id = charset_table_used++;
786          ASET (attrs, charset_id, make_number (id));
787          new_definition_p = 1;
788        }
789    
790    
791      charset.id = id;
792      charset_table[id] = charset;
793    
794        /* Update table emacs_code_class.  */    if (charset.iso_final >= 0)
795        emacs_code_class[charset] = (bytes == 2      {
796                                     ? EMACS_leading_code_2        ISO_CHARSET_TABLE (charset.dimension, charset.iso_chars_96,
797                                     : (bytes == 3                           charset.iso_final) = id;
798                                        ? EMACS_leading_code_3        if (new_definition_p)
799                                        : EMACS_leading_code_4));          Viso_2022_charset_list = nconc2 (Viso_2022_charset_list,
800      }                                           Fcons (make_number (id), Qnil));
801        }
802    /* Update table iso_charset_table.  */          
803    if (XINT (iso_final_char) >= 0    if (charset.emacs_mule_id >= 0)
804        && ISO_CHARSET_TABLE (dimension, chars, iso_final_char) < 0)      {
805      ISO_CHARSET_TABLE (dimension, chars, iso_final_char) = charset;        emacs_mule_charset[charset.emacs_mule_id] = CHARSET_FROM_ID (id);
806          if (new_definition_p)
807            Vemacs_mule_charset_list = nconc2 (Vemacs_mule_charset_list,
808                                               Fcons (make_number (id), Qnil));
809        }
810    
811      if (new_definition_p)
812        {
813          Vcharset_list = Fcons (args[charset_arg_name], Vcharset_list);
814          Vcharset_ordered_list = nconc2 (Vcharset_ordered_list,
815                                          Fcons (make_number (id), Qnil));
816        }
817    
818      return Qnil;
819  }  }
820    
 #ifdef emacs  
821    
822  /* Return charset id of CHARSET_SYMBOL, or return -1 if CHARSET_SYMBOL  DEFUN ("define-charset-alias", Fdefine_charset_alias,
823     is invalid.  */         Sdefine_charset_alias, 2, 2, 0,
824  int         doc: /* Define ALIAS as an alias for charset CHARSET.  */)
825  get_charset_id (charset_symbol)       (alias, charset)
826       Lisp_Object charset_symbol;       Lisp_Object alias, charset;
827  {  {
828    Lisp_Object val;    Lisp_Object attr;
   int charset;  
829    
830    /* This originally used a ?: operator, but reportedly the HP-UX    CHECK_CHARSET_GET_ATTR (charset, attr);
831       compiler version HP92453-01 A.10.32.22 miscompiles that.  */    Fputhash (alias, attr, Vcharset_hash_table);
832    if (SYMBOLP (charset_symbol)    return Qnil;
       && VECTORP (val = Fget (charset_symbol, Qcharset))  
       && CHARSET_VALID_P (charset =  
                           XINT (XVECTOR (val)->contents[CHARSET_ID_IDX])))  
     return charset;  
   else  
     return -1;  
833  }  }
834    
835  /* Return an identification number for a new private charset of  
836     DIMENSION and WIDTH.  If there's no more room for the new charset,  DEFUN ("primary-charset", Fprimary_charset, Sprimary_charset, 0, 0, 0,
837     return 0.  */         doc: /* Return the primary charset.  */)
838  Lisp_Object       ()
 get_new_private_charset_id (dimension, width)  
      int dimension, width;  
839  {  {
840    int charset, from, to;    return CHARSET_NAME (CHARSET_FROM_ID (charset_primary));
841    }
842    
   if (dimension == 1)  
     {  
       from = LEADING_CODE_EXT_11;  
       to = LEADING_CODE_EXT_21;  
     }  
   else  
     {  
       from = LEADING_CODE_EXT_21;  
       to = LEADING_CODE_EXT_MAX + 1;  
     }  
843    
844    for (charset = from; charset < to; charset++)  DEFUN ("set-primary-charset", Fset_primary_charset, Sset_primary_charset,
845      if (!CHARSET_DEFINED_P (charset)) break;         1, 1, 0,
846           doc: /* Set the primary charset to CHARSET.  */)
847         (charset)
848         Lisp_Object charset;
849    {
850      int id;
851    
852    return make_number (charset < to ? charset : 0);    CHECK_CHARSET_GET_ID (charset, id);
853      charset_primary = id;
854      return Qnil;
855  }  }
856    
857  DEFUN ("define-charset", Fdefine_charset, Sdefine_charset, 3, 3, 0,  
858         doc: /* Define CHARSET-ID as the identification number of CHARSET with INFO-VECTOR.  DEFUN ("charset-plist", Fcharset_plist, Scharset_plist, 1, 1, 0,
859  If CHARSET-ID is nil, it is decided automatically, which means CHARSET is         doc: /* Return a property list of CHARSET.  */)
860   treated as a private charset.       (charset)
861  INFO-VECTOR is a vector of the format:       Lisp_Object charset;
862     [DIMENSION CHARS WIDTH DIRECTION ISO-FINAL-CHAR ISO-GRAPHIC-PLANE  {
863      SHORT-NAME LONG-NAME DESCRIPTION]    Lisp_Object attrs;
864  The meanings of each elements is as follows:  
865  DIMENSION (integer) is the number of bytes to represent a character: 1 or 2.    CHECK_CHARSET_GET_ATTR (charset, attrs);
866  CHARS (integer) is the number of characters in a dimension: 94 or 96.    return CHARSET_ATTR_PLIST (attrs);
 WIDTH (integer) is the number of columns a character in the charset  
 occupies on the screen: one of 0, 1, and 2.  
   
 DIRECTION (integer) is the rendering direction of characters in the  
 charset when rendering.  If 0, render from left to right, else  
 render from right to left.  
   
 ISO-FINAL-CHAR (character) is the final character of the  
 corresponding ISO 2022 charset.  
 It may be -1 if the charset is internal use only.  
   
 ISO-GRAPHIC-PLANE (integer) is the graphic plane to be invoked  
 while encoding to variants of ISO 2022 coding system, one of the  
 following: 0/graphic-plane-left(GL), 1/graphic-plane-right(GR).  
 It may be -1 if the charset is internal use only.  
   
 SHORT-NAME (string) is the short name to refer to the charset.  
   
 LONG-NAME (string) is the long name to refer to the charset.  
   
 DESCRIPTION (string) is the description string of the charset.  */)  
        (charset_id, charset_symbol, info_vector)  
      Lisp_Object charset_id, charset_symbol, info_vector;  
 {  
   Lisp_Object *vec;  
   
   if (!NILP (charset_id))  
     CHECK_NUMBER (charset_id);  
   CHECK_SYMBOL (charset_symbol);  
   CHECK_VECTOR (info_vector);  
   
   if (! NILP (charset_id))  
     {  
       if (! CHARSET_VALID_P (XINT (charset_id)))  
         error ("Invalid CHARSET: %d", XINT (charset_id));  
       else if (CHARSET_DEFINED_P (XINT (charset_id)))  
         error ("Already defined charset: %d", XINT (charset_id));  
     }  
   
   vec = XVECTOR (info_vector)->contents;  
   if (XVECTOR (info_vector)->size != 9  
       || !INTEGERP (vec[0]) || !(XINT (vec[0]) == 1 || XINT (vec[0]) == 2)  
       || !INTEGERP (vec[1]) || !(XINT (vec[1]) == 94 || XINT (vec[1]) == 96)  
       || !INTEGERP (vec[2]) || !(XINT (vec[2]) == 1 || XINT (vec[2]) == 2)  
       || !INTEGERP (vec[3]) || !(XINT (vec[3]) == 0 || XINT (vec[3]) == 1)  
       || !INTEGERP (vec[4])  
       || !(XINT (vec[4]) == -1 || (XINT (vec[4]) >= '0' && XINT (vec[4]) <= '~'))  
       || !INTEGERP (vec[5])  
       || !(XINT (vec[5]) == -1 || XINT (vec[5]) == 0 || XINT (vec[5]) == 1)  
       || !STRINGP (vec[6])  
       || !STRINGP (vec[7])  
       || !STRINGP (vec[8]))  
     error ("Invalid info-vector argument for defining charset %s",  
            XSYMBOL (charset_symbol)->name->data);  
   
   if (NILP (charset_id))  
     {  
       charset_id = get_new_private_charset_id (XINT (vec[0]), XINT (vec[2]));  
       if (XINT (charset_id) == 0)  
         error ("There's no room for a new private charset %s",  
                XSYMBOL (charset_symbol)->name->data);  
     }  
   
   update_charset_table (charset_id, vec[0], vec[1], vec[2], vec[3],  
                         vec[4], vec[5], vec[6], vec[7], vec[8]);  
   Fput (charset_symbol, Qcharset, CHARSET_TABLE_ENTRY (XINT (charset_id)));  
   CHARSET_SYMBOL (XINT (charset_id)) = charset_symbol;  
   Vcharset_list = Fcons (charset_symbol, Vcharset_list);  
   Fupdate_coding_systems_internal ();  
   return Qnil;  
867  }  }
868    
869  DEFUN ("generic-character-list", Fgeneric_character_list,  
870         Sgeneric_character_list, 0, 0, 0,  DEFUN ("set-charset-plist", Fset_charset_plist, Sset_charset_plist, 2, 2, 0,
871         doc: /* Return a list of all possible generic characters.         doc: /* Set CHARSET's property list to PLIST.  */)
872  It includes a generic character for a charset not yet defined.  */)       (charset, plist)
873       ()       Lisp_Object charset, plist;
874  {  {
875    return Vgeneric_character_list;    Lisp_Object attrs;
876    
877      CHECK_CHARSET_GET_ATTR (charset, attrs);
878      CHARSET_ATTR_PLIST (attrs) = plist;
879      return plist;
880    }
881    
882    
883    DEFUN ("unify-charset", Funify_charset, Sunify_charset, 1, 2, 0,
884           doc: /* Unify characters of CHARSET with Unicode.   */)
885         (charset, unify_map)
886         Lisp_Object charset, unify_map;
887    {
888      int id;
889      struct charset *cs;
890      
891      CHECK_CHARSET_GET_ID (charset, id);
892      cs = CHARSET_FROM_ID (id);
893      if (CHARSET_METHOD (cs) == CHARSET_METHOD_MAP_DEFERRED)
894        load_charset (cs);
895      if (CHARSET_UNIFIED_P (cs)
896          && CHAR_TABLE_P (CHARSET_DEUNIFIER (cs)))
897        return Qnil;
898      CHARSET_UNIFIED_P (cs) = 0;
899      if (NILP (unify_map))
900        unify_map = CHARSET_UNIFY_MAP (cs);
901      if (STRINGP (unify_map))
902        unify_map = load_charset_map (cs, unify_map);
903      parse_charset_map (cs, unify_map, 2);
904      CHARSET_UNIFIED_P (cs) = 1;
905      return Qnil;
906  }  }
907    
908  DEFUN ("get-unused-iso-final-char", Fget_unused_iso_final_char,  DEFUN ("get-unused-iso-final-char", Fget_unused_iso_final_char,
909         Sget_unused_iso_final_char, 2, 2, 0,         Sget_unused_iso_final_char, 2, 2, 0,
910         doc: /* Return an unsed ISO's final char for a charset of DIMENISION and CHARS.         doc: /*
911    Return an unsed ISO's final char for a charset of DIMENISION and CHARS.
912  DIMENSION is the number of bytes to represent a character: 1 or 2.  DIMENSION is the number of bytes to represent a character: 1 or 2.
913  CHARS is the number of characters in a dimension: 94 or 96.  CHARS is the number of characters in a dimension: 94 or 96.
914    
915  This final char is for private use, thus the range is `0' (48) .. `?' (63).  This final char is for private use, thus the range is `0' (48) .. `?' (63).
916  If there's no unused final char for the specified kind of charset,  If there's no unused final char for the attrified kind of charset,
917  return nil.  */)  return nil.  */)
918       (dimension, chars)       (dimension, chars)
919       Lisp_Object dimension, chars;       Lisp_Object dimension, chars;
# Line 741  return nil.  */) Line 922  return nil.  */)
922    
923    CHECK_NUMBER (dimension);    CHECK_NUMBER (dimension);
924    CHECK_NUMBER (chars);    CHECK_NUMBER (chars);
925    if (XINT (dimension) != 1 && XINT (dimension) != 2)    if (XINT (dimension) != 1 && XINT (dimension) != 2 && XINT (dimension) != 3)
926      error ("Invalid charset dimension %d, it should be 1 or 2",      args_out_of_range_3 (dimension, make_number (1), make_number (3));
            XINT (dimension));  
927    if (XINT (chars) != 94 && XINT (chars) != 96)    if (XINT (chars) != 94 && XINT (chars) != 96)
928      error ("Invalid charset chars %d, it should be 94 or 96",      args_out_of_range_3 (chars, make_number (94), make_number (96));
            XINT (chars));  
929    for (final_char = '0'; final_char <= '?'; final_char++)    for (final_char = '0'; final_char <= '?'; final_char++)
930      {      if (ISO_CHARSET_TABLE (XINT (dimension), XINT (chars), final_char) < 0)
931        if (ISO_CHARSET_TABLE (dimension, chars, make_number (final_char)) < 0)        break;
         break;  
     }  
932    return (final_char <= '?' ? make_number (final_char) : Qnil);    return (final_char <= '?' ? make_number (final_char) : Qnil);
933  }  }
934    
935  DEFUN ("declare-equiv-charset", Fdeclare_equiv_charset, Sdeclare_equiv_charset,  static void
936         4, 4, 0,  check_iso_charset_parameter (dimension, chars, final_char)
937         doc: /* Declare a charset of DIMENSION, CHARS, FINAL-CHAR is the same as CHARSET.       Lisp_Object dimension, chars, final_char;
 CHARSET should be defined by `defined-charset' in advance.  */)  
      (dimension, chars, final_char, charset_symbol)  
      Lisp_Object dimension, chars, final_char, charset_symbol;  
938  {  {
939    int charset;    CHECK_NATNUM (dimension);
940      CHECK_NATNUM (chars);
941      CHECK_NATNUM (final_char);
942    
943    CHECK_NUMBER (dimension);    if (XINT (dimension) > 3)
944    CHECK_NUMBER (chars);      error ("Invalid DIMENSION %d, it should be 1, 2, or 3", XINT (dimension));
   CHECK_NUMBER (final_char);  
   CHECK_SYMBOL (charset_symbol);  
   
   if (XINT (dimension) != 1 && XINT (dimension) != 2)  
     error ("Invalid DIMENSION %d, it should be 1 or 2", XINT (dimension));  
945    if (XINT (chars) != 94 && XINT (chars) != 96)    if (XINT (chars) != 94 && XINT (chars) != 96)
946      error ("Invalid CHARS %d, it should be 94 or 96", XINT (chars));      error ("Invalid CHARS %d, it should be 94 or 96", XINT (chars));
947    if (XINT (final_char) < '0' || XFASTINT (final_char) > '~')    if (XINT (final_char) < '0' || XINT (final_char) > '~')
948      error ("Invalid FINAL-CHAR %c, it should be `0'..`~'", XINT (chars));      error ("Invalid FINAL-CHAR %c, it should be `0'..`~'", XINT (chars));
949    if ((charset = get_charset_id (charset_symbol)) < 0)  }
950      error ("Invalid charset %s", XSYMBOL (charset_symbol)->name->data);  
951    
952    ISO_CHARSET_TABLE (dimension, chars, final_char) = charset;  DEFUN ("declare-equiv-charset", Fdeclare_equiv_charset, Sdeclare_equiv_charset,
953           4, 4, 0,
954           doc: /*
955    Declare a charset of DIMENSION, CHARS, FINAL-CHAR is the same as CHARSET.
956    CHARSET should be defined by `defined-charset' in advance.  */)
957         (dimension, chars, final_char, charset)
958         Lisp_Object dimension, chars, final_char, charset;
959    {
960      int id;
961    
962      CHECK_CHARSET_GET_ID (charset, id);
963      check_iso_charset_parameter (dimension, chars, final_char);
964    
965      ISO_CHARSET_TABLE (dimension, chars, final_char) = id;
966    return Qnil;    return Qnil;
967  }  }
968    
969    
970  /* Return information about charsets in the text at PTR of NBYTES  /* Return information about charsets in the text at PTR of NBYTES
971     bytes, which are NCHARS characters.  The value is:     bytes, which are NCHARS characters.  The value is:
972    
973          0: Each character is represented by one byte.  This is always          0: Each character is represented by one byte.  This is always
974             true for unibyte text.             true for a unibyte string.  For a multibyte string, true if
975          1: No charsets other than ascii eight-bit-control,             it contains only ASCII characters.
            eight-bit-graphic, and latin-1 are found.  
         2: Otherwise.  
976    
977     In addition, if CHARSETS is nonzero, for each found charset N, set          1: No charsets other than ascii, eight-bit-control, and
978     CHARSETS[N] to 1.  For that, callers should allocate CHARSETS          latin-1 are found.
979     (MAX_CHARSET + 1 elements) in advance.  It may lookup a translation  
980     table TABLE if supplied.  For invalid charsets, set CHARSETS[1] to          2: Otherwise.
981     1 (note that there's no charset whose ID is 1).  */  */
982    
983  int  int
984  find_charset_in_text (ptr, nchars, nbytes, charsets, table)  string_xstring_p (string)
985       unsigned char *ptr;       Lisp_Object string;
      int nchars, nbytes, *charsets;  
      Lisp_Object table;  
986  {  {
987    if (nchars == nbytes)    unsigned char *p = XSTRING (string)->data;
988      unsigned char *endp = p + STRING_BYTES (XSTRING (string));
989      struct charset *charset;
990    
991      if (XSTRING (string)->size == STRING_BYTES (XSTRING (string)))
992        return 0;
993    
994      charset = CHARSET_FROM_ID (charset_iso_8859_1);
995      while (p < endp)
996      {      {
997        if (charsets && nbytes > 0)        int c = STRING_CHAR_ADVANCE (p);
         {  
           unsigned char *endp = ptr + nbytes;  
           int maskbits = 0;  
998    
999            while (ptr < endp && maskbits != 7)        if (ENCODE_CHAR (charset, c) < 0)
1000              {          return 2;
               maskbits |= (*ptr < 0x80 ? 1 : *ptr < 0xA0 ? 2 : 4);  
               ptr++;  
             }          
   
           if (maskbits & 1)  
             charsets[CHARSET_ASCII] = 1;  
           if (maskbits & 2)  
             charsets[CHARSET_8_BIT_CONTROL] = 1;  
           if (maskbits & 4)  
             charsets[CHARSET_8_BIT_GRAPHIC] = 1;  
         }  
       return 0;  
1001      }      }
1002    else    return 1;
1003      {  }
       int return_val = 1;  
       int bytes, charset, c1, c2;  
1004    
       if (! CHAR_TABLE_P (table))  
         table = Qnil;  
1005    
1006        while (nchars-- > 0)  /* Find charsets in the string at PTR of NCHARS and NBYTES.
1007          {  
1008            SPLIT_MULTIBYTE_SEQ (ptr, len, bytes, charset, c1, c2);     CHARSETS is a vector.  Each element is a cons of CHARSET and
1009            ptr += bytes;     FOUND-FLAG.  CHARSET is a charset id, and FOUND-FLAG is nil or t.
1010       FOUND-FLAG t (or nil) means that the corresponding charset is
1011       already found (or not yet found).
1012    
1013       It may lookup a translation table TABLE if supplied.  */
1014    
1015    static void
1016    find_charsets_in_text (ptr, nchars, nbytes, charsets, table)
1017         unsigned char *ptr;
1018         int nchars, nbytes;
1019         Lisp_Object charsets, table;
1020    {
1021      unsigned char *pend = ptr + nbytes;
1022      int ncharsets = ASIZE (charsets);
1023    
1024            if (!CHARSET_DEFINED_P (charset))    if (nchars == nbytes)
1025              charset = 1;      return;
1026            else if (! NILP (table))  
1027      while (ptr < pend)
1028        {
1029          int c = STRING_CHAR_ADVANCE (ptr);
1030          int i;
1031          int all_found = 1;
1032          Lisp_Object elt;
1033    
1034          if (!NILP (table))
1035            c = translate_char (table, c);
1036          for (i = 0; i < ncharsets; i++)
1037            {
1038              elt = AREF (charsets, i);
1039              if (NILP (XCDR (elt)))
1040              {              {
1041                int c = translate_char (table, -1, charset, c1, c2);                struct charset *charset = CHARSET_FROM_ID (XINT (XCAR (elt)));
               if (c >= 0)  
                 charset = CHAR_CHARSET (c);  
             }  
1042    
1043            if (return_val == 1                if (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset))
1044                && charset != CHARSET_ASCII                  XCDR (elt) = Qt;
1045                && charset != CHARSET_8_BIT_CONTROL                else
1046                && charset != CHARSET_8_BIT_GRAPHIC                  all_found = 0;
1047                && charset != charset_latin_iso8859_1)              }
             return_val = 2;  
   
           if (charsets)  
             charsets[charset] = 1;  
           else if (return_val == 2)  
             break;  
1048          }          }
1049        return return_val;        if (all_found)
1050            break;
1051      }      }
1052  }  }
1053    
1054    
1055  DEFUN ("find-charset-region", Ffind_charset_region, Sfind_charset_region,  DEFUN ("find-charset-region", Ffind_charset_region, Sfind_charset_region,
1056         2, 3, 0,         2, 3, 0,
1057         doc: /* Return a list of charsets in the region between BEG and END.         doc: /* Return a list of charsets in the region between BEG and END.
# Line 877  only `ascii', `eight-bit-control', and ` Line 1066  only `ascii', `eight-bit-control', and `
1066       (beg, end, table)       (beg, end, table)
1067       Lisp_Object beg, end, table;       Lisp_Object beg, end, table;
1068  {  {
1069    int charsets[MAX_CHARSET + 1];    Lisp_Object charsets;
1070    int from, from_byte, to, stop, stop_byte, i;    int from, from_byte, to, stop, stop_byte, i;
1071    Lisp_Object val;    Lisp_Object val;
1072    
# Line 895  only `ascii', `eight-bit-control', and ` Line 1084  only `ascii', `eight-bit-control', and `
1084    
1085    from_byte = CHAR_TO_BYTE (from);    from_byte = CHAR_TO_BYTE (from);
1086    
1087    bzero (charsets, (MAX_CHARSET + 1) * sizeof (int));    charsets = Fmake_vector (make_number (charset_table_used), Qnil);
1088      for (i = 0; i < charset_table_used; i++)
1089        ASET (charsets, i, Fcons (make_number (i), Qnil));
1090    
1091    while (1)    while (1)
1092      {      {
1093        find_charset_in_text (BYTE_POS_ADDR (from_byte), stop - from,        find_charsets_in_text (BYTE_POS_ADDR (from_byte), stop - from,
1094                              stop_byte - from_byte, charsets, table);                               stop_byte - from_byte, charsets, table);
1095        if (stop < to)        if (stop < to)
1096          {          {
1097            from = stop, from_byte = stop_byte;            from = stop, from_byte = stop_byte;
# Line 910  only `ascii', `eight-bit-control', and ` Line 1102  only `ascii', `eight-bit-control', and `
1102      }      }
1103    
1104    val = Qnil;    val = Qnil;
1105    if (charsets[1])    for (i = charset_table_used - 1; i >= 0; i--)
1106      val = Fcons (Qunknown, val);      if (!NILP (XCDR (AREF (charsets, i))))
1107    for (i = MAX_CHARSET; i >= MIN_CHARSET_OFFICIAL_DIMENSION1; i--)        val = Fcons (CHARSET_NAME (charset_table + i), val);
     if (charsets[i])  
       val = Fcons (CHARSET_SYMBOL (i), val);  
   if (charsets[0])  
     val = Fcons (Qascii, val);  
1108    return val;    return val;
1109  }  }
1110    
# Line 929  If the string contains invalid multibyte Line 1117  If the string contains invalid multibyte
1117  `unknown' is included in the returned list.  `unknown' is included in the returned list.
1118    
1119  If STR is unibyte, the returned list may contain  If STR is unibyte, the returned list may contain
1120  only `ascii', `eight-bit-control', and `eight-bit-graphic'.  */)  only `ascii', `eight-bit-control', and `eight-bit-graphic'. */)
1121       (str, table)       (str, table)
1122       Lisp_Object str, table;       Lisp_Object str, table;
1123  {  {
1124    int charsets[MAX_CHARSET + 1];    Lisp_Object charsets;
1125    int i;    int i;
1126    Lisp_Object val;    Lisp_Object val;
1127    
1128    CHECK_STRING (str);    CHECK_STRING (str);
1129    
1130    bzero (charsets, (MAX_CHARSET + 1) * sizeof (int));    charsets = Fmake_vector (make_number (charset_table_used), Qnil);
1131    find_charset_in_text (XSTRING (str)->data, XSTRING (str)->size,    find_charsets_in_text (XSTRING (str)->data, XSTRING (str)->size,
1132                          STRING_BYTES (XSTRING (str)), charsets, table);                           STRING_BYTES (XSTRING (str)), charsets, table);
1133    
1134    val = Qnil;    val = Qnil;
1135    if (charsets[1])    for (i = charset_table_used - 1; i >= 0; i--)
1136      val = Fcons (Qunknown, val);      if (!NILP (XCDR (AREF (charsets, i))))
1137    for (i = MAX_CHARSET; i >= MIN_CHARSET_OFFICIAL_DIMENSION1; i--)        val = Fcons (CHARSET_NAME (charset_table + i), val);
     if (charsets[i])  
       val = Fcons (CHARSET_SYMBOL (i), val);  
   if (charsets[0])  
     val = Fcons (Qascii, val);  
1138    return val;    return val;
1139  }  }
1140    
1141    
 DEFUN ("make-char-internal", Fmake_char_internal, Smake_char_internal, 1, 3, 0,  
        doc: /* Return a character made from arguments.  
 Internal use only.  */)  
      (charset, code1, code2)  
      Lisp_Object charset, code1, code2;  
 {  
   int charset_id, c1, c2;  
   
   CHECK_NUMBER (charset);  
   charset_id = XINT (charset);  
   if (!CHARSET_DEFINED_P (charset_id))  
     error ("Invalid charset ID: %d", XINT (charset));  
1142    
1143    if (NILP (code1))  /* Return a character correponding to the code-point CODE of
1144      c1 = 0;     CHARSET.  */
1145    else  
1146      {  int
1147        CHECK_NUMBER (code1);  decode_char (charset, code)
1148        c1 = XINT (code1);       struct charset *charset;
1149      }       unsigned code;
1150    if (NILP (code2))  {
1151      c2 = 0;    int c, char_index;
1152    else    enum charset_method method = CHARSET_METHOD (charset);
1153    
1154      if (code < CHARSET_MIN_CODE (charset) || code > CHARSET_MAX_CODE (charset))
1155        return -1;
1156    
1157      if (method == CHARSET_METHOD_MAP_DEFERRED)
1158      {      {
1159        CHECK_NUMBER (code2);        load_charset (charset);
1160        c2 = XINT (code2);        method = CHARSET_METHOD (charset);
1161      }      }
1162    
1163    if (charset_id == CHARSET_ASCII)    if (method == CHARSET_METHOD_INHERIT)
1164      {      {
1165        if (c1 < 0 || c1 > 0x7F)        Lisp_Object parents;
         goto invalid_code_posints;  
       return make_number (c1);  
     }  
   else if (charset_id == CHARSET_8_BIT_CONTROL)  
     {  
       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 (NILP (code1))  
         c1 = 0xA0;  
       else if (c1 < 0xA0 || c1 > 0xFF)  
         goto invalid_code_posints;  
       return make_number (c1);  
     }  
   else if (c1 < 0 || c1 > 0xFF || c2 < 0 || c2 > 0xFF)  
     goto invalid_code_posints;  
   c1 &= 0x7F;  
   c2 &= 0x7F;  
   if (c1 == 0  
       ? c2 != 0  
       : (c2 == 0  
          ? !CHAR_COMPONENTS_VALID_P (charset_id, c1, 0x20)  
          : !CHAR_COMPONENTS_VALID_P (charset_id, c1, c2)))  
     goto invalid_code_posints;  
   return make_number (MAKE_CHAR (charset_id, c1, c2));  
1166    
1167   invalid_code_posints:        parents = CHARSET_PARENTS (charset);
1168    error ("Invalid code points for charset ID %d: %d %d", charset_id, c1, c2);        c = -1;
1169  }        for (; CONSP (parents); parents = XCDR (parents))
1170            {
1171              int id = XINT (XCAR (XCAR (parents)));
1172              int code_offset = XINT (XCDR (XCAR (parents)));
1173              unsigned this_code = code + code_offset;
1174    
1175  DEFUN ("split-char", Fsplit_char, Ssplit_char, 1, 1, 0,            charset = CHARSET_FROM_ID (id);
1176         doc: /* Return list of charset and one or two position-codes of CHAR.            if ((c = DECODE_CHAR (charset, this_code)) >= 0)
1177  If CHAR is invalid as a character code,              break;
1178  return a list of symbol `unknown' and CHAR.  */)          }
1179       (ch)      }
1180       Lisp_Object ch;    else
1181  {      {
1182    int c, charset, c1, c2;        char_index = CODE_POINT_TO_INDEX (charset, code);
1183    
1184    CHECK_NUMBER (ch);        if (method == CHARSET_METHOD_MAP)
1185    c = XFASTINT (ch);          {
1186    if (!CHAR_VALID_P (c, 1))            Lisp_Object decoder;
     return Fcons (Qunknown, Fcons (ch, Qnil));  
   SPLIT_CHAR (XFASTINT (ch), charset, c1, c2);  
   return (c2 >= 0  
           ? Fcons (CHARSET_SYMBOL (charset),  
                    Fcons (make_number (c1), Fcons (make_number (c2), Qnil)))  
           : Fcons (CHARSET_SYMBOL (charset), Fcons (make_number (c1), Qnil)));  
 }  
1187    
1188  DEFUN ("char-charset", Fchar_charset, Schar_charset, 1, 1, 0,            decoder = CHARSET_DECODER (charset);
1189         doc: /* Return charset of CHAR.  */)            if (! VECTORP (decoder))
1190       (ch)              return -1;
1191       Lisp_Object ch;            c = XINT (AREF (decoder, char_index));
1192  {          }
1193    CHECK_NUMBER (ch);        else
1194            {
1195              c = char_index + CHARSET_CODE_OFFSET (charset);
1196            }
1197        }
1198    
1199    return CHARSET_SYMBOL (CHAR_CHARSET (XINT (ch)));    if (CHARSET_UNIFIED_P (charset)
1200  }        && c >= 0)
1201        MAYBE_UNIFY_CHAR (c);
1202    
1203  DEFUN ("charset-after", Fcharset_after, Scharset_after, 0, 1, 0,    return c;
        doc: /* Return charset of a character in the current buffer at position POS.  
 If POS is nil, it defauls to the current point.  
 If POS is out of range, the value is nil.  */)  
      (pos)  
      Lisp_Object pos;  
 {  
   Lisp_Object ch;  
   int charset;  
   
   ch = Fchar_after (pos);  
   if (! INTEGERP (ch))  
     return ch;  
   charset = CHAR_CHARSET (XINT (ch));  
   return CHARSET_SYMBOL (charset);  
1204  }  }
1205    
 DEFUN ("iso-charset", Fiso_charset, Siso_charset, 3, 3, 0,  
        doc: /* Return charset of ISO's specification DIMENSION, CHARS, and FINAL-CHAR.  
   
 ISO 2022's designation sequence (escape sequence) distinguishes charsets  
 by their DIMENSION, CHARS, and FINAL-CHAR,  
 where as Emacs distinguishes them by charset symbol.  
 See the documentation of the function `charset-info' for the meanings of  
 DIMENSION, CHARS, and FINAL-CHAR.  */)  
      (dimension, chars, final_char)  
      Lisp_Object dimension, chars, final_char;  
 {  
   int charset;  
   
   CHECK_NUMBER (dimension);  
   CHECK_NUMBER (chars);  
   CHECK_NUMBER (final_char);  
1206    
1207    if ((charset = ISO_CHARSET_TABLE (dimension, chars, final_char)) < 0)  /* Return a code-point of CHAR in CHARSET.  If CHAR doesn't belong to
1208      return Qnil;     CHARSET, return CHARSET_INVALID_CODE (CHARSET).  */
   return CHARSET_SYMBOL (charset);  
 }  
1209    
1210  /* If GENERICP is nonzero, return nonzero iff C is a valid normal or  unsigned
1211     generic character.  If GENERICP is zero, return nonzero iff C is a  encode_char (charset, c)
1212     valid normal character.  Do not call this function directly,       struct charset *charset;
1213     instead use macro CHAR_VALID_P.  */       int c;
 int  
 char_valid_p (c, genericp)  
      int c, genericp;  
1214  {  {
1215    int charset, c1, c2;    unsigned code;
1216      enum charset_method method = CHARSET_METHOD (charset);
1217    
1218    if (c < 0 || c >= MAX_CHAR)    if (CHARSET_UNIFIED_P (charset))
     return 0;  
   if (SINGLE_BYTE_CHAR_P (c))  
     return 1;  
   SPLIT_CHAR (c, charset, c1, c2);  
   if (genericp)  
1219      {      {
1220        if (c1)        Lisp_Object deunifier;
1221          {        int deunified;
1222            if (c2 <= 0) c2 = 0x20;  
1223          }        deunifier = CHARSET_DEUNIFIER (charset);
1224        else        if (! CHAR_TABLE_P (deunifier))
1225          {          {
1226            if (c2 <= 0) c1 = c2 = 0x20;            Funify_charset (CHARSET_NAME (charset), Qnil);
1227              deunifier = CHARSET_DEUNIFIER (charset);
1228          }          }
1229          deunified = XINT (CHAR_TABLE_REF (deunifier, c));
1230          if (deunified > 0)
1231            c = deunified;
1232      }      }
   return (CHARSET_DEFINED_P (charset)  
           && CHAR_COMPONENTS_VALID_P (charset, c1, c2));  
 }  
1233    
1234  DEFUN ("char-valid-p", Fchar_valid_p, Schar_valid_p, 1, 2, 0,    if (! CHARSET_FAST_MAP_REF ((c), charset->fast_map)
1235         doc: /* Return t if OBJECT is a valid normal character.        || c < CHARSET_MIN_CHAR (charset) || c > CHARSET_MAX_CHAR (charset))
1236  If optional arg GENERICP is non-nil, also return t if OBJECT is      return CHARSET_INVALID_CODE (charset);
 a valid generic character.  */)  
      (object, genericp)  
      Lisp_Object object, genericp;  
 {  
   if (! NATNUMP (object))  
     return Qnil;  
   return (CHAR_VALID_P (XFASTINT (object), !NILP (genericp)) ? Qt : Qnil);  
 }  
1237    
1238  DEFUN ("unibyte-char-to-multibyte", Funibyte_char_to_multibyte,    if (method == CHARSET_METHOD_INHERIT)
1239         Sunibyte_char_to_multibyte, 1, 1, 0,      {
1240         doc: /* Convert the unibyte character CH to multibyte character.        Lisp_Object parents;
 The conversion is done based on `nonascii-translation-table' (which see)  
  or `nonascii-insert-offset' (which see).  */)  
      (ch)  
      Lisp_Object ch;  
 {  
   int c;  
   
   CHECK_NUMBER (ch);  
   c = XINT (ch);  
   if (c < 0 || c >= 0400)  
     error ("Invalid unibyte character: %d", c);  
   c = unibyte_char_to_multibyte (c);  
   if (c < 0)  
     error ("Can't convert to multibyte character: %d", XINT (ch));  
   return make_number (c);  
 }  
1241    
1242  DEFUN ("multibyte-char-to-unibyte", Fmultibyte_char_to_unibyte,        parents = CHARSET_PARENTS (charset);
1243         Smultibyte_char_to_unibyte, 1, 1, 0,        for (; CONSP (parents); parents = XCDR (parents))
1244         doc: /* Convert the multibyte character CH to unibyte character.          {
1245  The conversion is done based on `nonascii-translation-table' (which see)            int id = XINT (XCAR (XCAR (parents)));
1246   or `nonascii-insert-offset' (which see).  */)            int code_offset = XINT (XCDR (XCAR (parents)));
1247       (ch)            struct charset *this_charset = CHARSET_FROM_ID (id);
      Lisp_Object ch;  
 {  
   int c;  
1248    
1249    CHECK_NUMBER (ch);            code = ENCODE_CHAR (this_charset, c);
1250    c = XINT (ch);            if (code != CHARSET_INVALID_CODE (this_charset)
1251    if (! CHAR_VALID_P (c, 0))                && (code_offset < 0 || code >= code_offset))
1252      error ("Invalid multibyte character: %d", c);              {
1253    c = multibyte_char_to_unibyte (c, Qnil);                code -= code_offset;
1254    if (c < 0)                if (CODE_POINT_TO_INDEX (charset, code) >= 0)
1255      error ("Can't convert to unibyte character: %d", XINT (ch));                  return code;
1256    return make_number (c);              }
1257  }          }
1258          return CHARSET_INVALID_CODE (charset);
1259        }
1260    
1261  DEFUN ("char-bytes", Fchar_bytes, Schar_bytes, 1, 1, 0,    if (method == CHARSET_METHOD_MAP_DEFERRED)
1262         doc: /* Return 1 regardless of the argument CHAR.      {
1263  This is now an obsolete function.  We keep it just for backward compatibility.  */)        load_charset (charset);
1264       (ch)        method = CHARSET_METHOD (charset);
1265       Lisp_Object ch;      }
 {  
   CHECK_NUMBER (ch);  
   return make_number (1);  
 }  
1266    
1267  /* Return how many bytes C will occupy in a multibyte buffer.    if (method == CHARSET_METHOD_MAP)
1268     Don't call this function directly, instead use macro CHAR_BYTES.  */      {
1269  int        Lisp_Object encoder;
1270  char_bytes (c)        Lisp_Object val;
      int c;  
 {  
   int charset;  
1271    
1272    if (ASCII_BYTE_P (c) || (c & ~((1 << CHARACTERBITS) -1)))        encoder = CHARSET_ENCODER (charset);
1273      return 1;        if (! CHAR_TABLE_P (CHARSET_ENCODER (charset)))
1274    if (SINGLE_BYTE_CHAR_P (c) && c >= 0xA0)          return CHARSET_INVALID_CODE (charset);
1275      return 1;        val = CHAR_TABLE_REF (encoder, c);
1276          if (CONSP (val))
1277            code = (XINT (XCAR (val)) << 16) | XINT (XCDR (val));
1278          else
1279            code = XINT (val);
1280        }
1281      else
1282        {
1283          code = c - CHARSET_CODE_OFFSET (charset);
1284          code = INDEX_TO_CODE_POINT (charset, code);
1285        }
1286    
1287    charset = CHAR_CHARSET (c);    return code;
   return (CHARSET_DEFINED_P (charset) ? CHARSET_BYTES (charset) : 1);  
1288  }  }
1289    
 /* Return the width of character of which multi-byte form starts with  
    C.  The width is measured by how many columns occupied on the  
    screen when displayed in the current buffer.  */  
   
 #define ONE_BYTE_CHAR_WIDTH(c)                                          \  
   (c < 0x20                                                             \  
    ? (c == '\t'                                                         \  
       ? XFASTINT (current_buffer->tab_width)                            \  
       : (c == '\n' ? 0 : (NILP (current_buffer->ctl_arrow) ? 4 : 2)))   \  
    : (c < 0x7f                                                          \  
       ? 1                                                               \  
       : (c == 0x7F                                                      \  
          ? (NILP (current_buffer->ctl_arrow) ? 4 : 2)                   \  
          : ((! NILP (current_buffer->enable_multibyte_characters)       \  
              && BASE_LEADING_CODE_P (c))                                \  
             ? WIDTH_BY_CHAR_HEAD (c)                                    \  
             : 4))))  
   
 DEFUN ("char-width", Fchar_width, Schar_width, 1, 1, 0,  
        doc: /* Return width of CHAR when displayed in the current buffer.  
 The width is measured by how many columns it occupies on the screen.  
 Tab is taken to occupy `tab-width' columns.  */)  
      (ch)  
      Lisp_Object ch;  
 {  
   Lisp_Object val, disp;  
   int c;  
   struct Lisp_Char_Table *dp = buffer_display_table ();  
1290    
1291    CHECK_NUMBER (ch);  DEFUN ("decode-char", Fdecode_char, Sdecode_char, 2, 3, 0,
1292           doc: /* Decode the pair of CHARSET and CODE-POINT into a character.
1293    Return nil if CODE-POINT is not valid in CHARSET.
1294    
1295    c = XINT (ch);  CODE-POINT may be a cons (HIGHER-16-BIT-VALUE . LOWER-16-BIT-VALUE).
1296    
1297    /* Get the way the display table would display it.  */  Optional argument RESTRICTION specifies a way to map the pair of CCS
1298    disp = dp ? DISP_CHAR_VECTOR (dp, c) : Qnil;  and CODE-POINT to a chracter.   Currently not supported and just ignored.  */)
1299      (charset, code_point, restriction)
1300         Lisp_Object charset, code_point, restriction;
1301    {
1302      int c, id;
1303      unsigned code;
1304      struct charset *charsetp;
1305    
1306    if (VECTORP (disp))    CHECK_CHARSET_GET_ID (charset, id);
1307      XSETINT (val, XVECTOR (disp)->size);    if (CONSP (code_point))
1308    else if (SINGLE_BYTE_CHAR_P (c))      {
1309      XSETINT (val, ONE_BYTE_CHAR_WIDTH (c));        CHECK_NATNUM (XCAR (code_point));
1310          CHECK_NATNUM (XCDR (code_point));
1311          code = (XINT (XCAR (code_point)) << 16) | (XINT (XCAR (code_point)));
1312        }
1313    else    else
1314      {      {
1315        int charset = CHAR_CHARSET (c);        CHECK_NATNUM (code_point);
1316          code = XINT (code_point);
       XSETFASTINT (val, CHARSET_WIDTH (charset));  
1317      }      }
1318    return val;    charsetp = CHARSET_FROM_ID (id);
1319      c = DECODE_CHAR (charsetp, code);
1320      return (c >= 0 ? make_number (c) : Qnil);
1321  }  }
1322    
 /* 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.  */  
1323    
1324  int  DEFUN ("encode-char", Fencode_char, Sencode_char, 2, 3, 0,
1325  strwidth (str, len)         doc: /* Encode the character CH into a code-point of CHARSET.
1326       unsigned char *str;  Return nil if CHARSET doesn't include CH.
1327       int len;  
1328  {  Optional argument RESTRICTION specifies a way to map CHAR to a
1329    return c_string_width (str, len, -1, NULL, NULL);  code-point in CCS.  Currently not supported and just ignored.  */)
1330         (ch, charset, restriction)
1331         Lisp_Object ch, charset, restriction;
1332    {
1333      int c, id;
1334      unsigned code;
1335      struct charset *charsetp;
1336    
1337      CHECK_CHARSET_GET_ID (charset, id);
1338      CHECK_NATNUM (ch);
1339      c = XINT (ch);
1340      charsetp = CHARSET_FROM_ID (id);
1341      code = ENCODE_CHAR (charsetp, ch);
1342      if (code == CHARSET_INVALID_CODE (charsetp))
1343        return Qnil;
1344      if (code > 0x7FFFFFF)
1345        return Fcons (make_number (code >> 16), make_number (code & 0xFFFF));
1346      return make_number (code);
1347  }  }
1348    
 /* 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.  */  
1349    
1350  int  DEFUN ("make-char", Fmake_char, Smake_char, 1, 4, 0,
1351  c_string_width (str, len, precision, nchars, nbytes)         doc: /* Return a character of CHARSET whose position code is CODE.
      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 ();  
1352    
1353    while (i_byte < len)  If dimension of CHARSET is two, and the third optional arg CODE2 is
1354      {  non-nil, CODE actually specifies the first byte of the position code,
1355        int bytes, thiswidth;  and CODE2 specifies the second byte.
       Lisp_Object val;  
1356    
1357        if (dp)  If dimension of CHARSET is three, and the third optional arg CODE2 and
1358          {  the fourth optional arg CODE3 are both non-nil, CODE actually
1359            int c = STRING_CHAR_AND_LENGTH (str + i_byte, len - i_byte, bytes);  specifies the first byte of the position code, CODE2 the second byte,
1360    and CODE3 the third byte.  */)
1361         (charset, code, code2, code3)
1362         Lisp_Object charset, code, code2, code3;
1363    {
1364      int id, dimension;
1365      struct charset *charsetp;
1366      unsigned c;
1367    
1368            chars = 1;    CHECK_CHARSET_GET_ID (charset, id);
1369            val = DISP_CHAR_VECTOR (dp, c);    charsetp = CHARSET_FROM_ID (id);
1370            if (VECTORP (val))  
1371              thiswidth = XVECTOR (val)->size;    if (NILP (code))
1372            else      code = make_number (CHARSET_MIN_CODE (charsetp));
1373              thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]);    else
1374          }      {
1375        else        CHECK_NATNUM (code);
1376          {        dimension = CHARSET_DIMENSION (charsetp);
           chars = 1;  
           PARSE_MULTIBYTE_SEQ (str + i_byte, len - i_byte, bytes);  
           thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]);  
         }  
1377    
1378        if (precision > 0        if (!NILP (code2))
           && (width + thiswidth > precision))  
1379          {          {
1380            *nchars = i;            CHECK_NATNUM (code2);
1381            *nbytes = i_byte;            if (dimension == 3)
1382            return width;              CHECK_NATNUM (code3);
1383          }          }
       i++;  
       i_byte += bytes;  
       width += thiswidth;  
   }  
   
   if (precision > 0)  
     {  
       *nchars = i;  
       *nbytes = i_byte;  
1384      }      }
1385    
1386    return width;    if (dimension == 1 || NILP (code2))
1387        c = XFASTINT (code);
1388      else if (dimension == 2)
1389        c = (XFASTINT (code) << 8) | XFASTINT (code2);
1390      else if (dimension == 3)
1391        c = (XFASTINT (code) << 16) | (XFASTINT (code2) << 8) | XFASTINT (code3);
1392    
1393      c = DECODE_CHAR (charsetp, c);
1394      return make_number (c);
1395  }  }
1396    
 /* 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.  */  
1397    
1398  int  /* Return the first charset in CHARSET_LIST that contains C.
1399  lisp_string_width (string, precision, nchars, nbytes)     CHARSET_LIST is a list of charset IDs.  If it is nil, use
1400       Lisp_Object string;     Vcharset_ordered_list.  */
1401       int precision, *nchars, *nbytes;  
1402    struct charset *
1403    char_charset (c, charset_list, code_return)
1404         int c;
1405         Lisp_Object charset_list;
1406         unsigned *code_return;
1407  {  {
1408    int len = XSTRING (string)->size;    if (NILP (charset_list))
1409    int len_byte = STRING_BYTES (XSTRING (string));      charset_list = Vcharset_ordered_list;
   unsigned char *str = XSTRING (string)->data;  
   int i = 0, i_byte = 0;  
   int width = 0;  
   struct Lisp_Char_Table *dp = buffer_display_table ();  
1410    
1411    while (i < len)    while (CONSP (charset_list))
1412      {      {
1413        int chars, bytes, thiswidth;        struct charset *charset = CHARSET_FROM_ID (XINT (XCAR (charset_list)));
1414        Lisp_Object val;        unsigned code = ENCODE_CHAR (charset, c);
       int cmp_id;  
       int ignore, end;  
1415    
1416        if (find_composition (i, -1, &ignore, &end, &val, string)        if (code != CHARSET_INVALID_CODE (charset))
           && ((cmp_id = get_composition_id (i, i_byte, end - i, val, string))  
               >= 0))  
1417          {          {
1418            thiswidth = composition_table[cmp_id]->width;            if (code_return)
1419            chars = end - i;              *code_return = code;
1420            bytes = string_char_to_byte (string, end) - i_byte;            return charset;
1421          }          }
1422        else if (dp)        charset_list = XCDR (charset_list);
         {  
           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  
         {  
           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;  
   }  
   
   if (precision > 0)  
     {  
       *nchars = i;  
       *nbytes = i_byte;  
1423      }      }
1424      return NULL;
   return width;  
1425  }  }
1426    
 DEFUN ("string-width", Fstring_width, Sstring_width, 1, 1, 0,  
        doc: /* Return width of STRING when displayed in the current buffer.  
 Width is measured by how many columns it occupies on the screen.  
 When calculating width of a multibyte character in STRING,  
 only the base leading-code is considered; the validity of  
 the following bytes is not checked.  Tabs in STRING are always  
 taken to occupy `tab-width' columns.  */)  
      (str)  
      Lisp_Object str;  
 {  
   Lisp_Object val;  
   
   CHECK_STRING (str);  
   XSETFASTINT (val, lisp_string_width (str, -1, NULL, NULL));  
   return val;  
 }  
1427    
1428  DEFUN ("char-direction", Fchar_direction, Schar_direction, 1, 1, 0,  DEFUN ("split-char", Fsplit_char, Ssplit_char, 1, 1, 0,
1429         doc: /* Return the direction of CHAR.         doc: /*Return list of charset and one or two position-codes of CHAR.
1430  The returned value is 0 for left-to-right and 1 for right-to-left.  */)  If CHAR is invalid as a character code,
1431    return a list of symbol `unknown' and CHAR.  */)
1432       (ch)       (ch)
1433       Lisp_Object ch;       Lisp_Object ch;
1434  {  {
1435    int charset;    struct charset *charset;
1436      int c, dimension;
1437      unsigned code;
1438      Lisp_Object val;
1439    
1440    CHECK_NUMBER (ch);    CHECK_CHARACTER (ch);
1441    charset = CHAR_CHARSET (XFASTINT (ch));    c = XFASTINT (ch);
1442    if (!CHARSET_DEFINED_P (charset))    charset = CHAR_CHARSET (c);
1443      invalid_character (XINT (ch));    if (! charset)
1444    return CHARSET_TABLE_INFO (charset, CHARSET_DIRECTION_IDX);      return Fcons (intern ("unknown"), Fcons (ch, Qnil));
1445      
1446      code = ENCODE_CHAR (charset, c);
1447      if (code == CHARSET_INVALID_CODE (charset))
1448        abort ();
1449      dimension = CHARSET_DIMENSION (charset);
1450      val = (dimension == 1 ? Fcons (make_number (code), Qnil)
1451             : dimension == 2 ? Fcons (make_number (code >> 8),
1452                                       Fcons (make_number (code & 0xFF), Qnil))
1453             : Fcons (make_number (code >> 16),
1454                      Fcons (make_number ((code >> 8) & 0xFF),
1455                             Fcons (make_number (code & 0xFF), Qnil))));
1456      return Fcons (CHARSET_NAME (charset), val);
1457  }  }
1458    
 DEFUN ("chars-in-region", Fchars_in_region, Schars_in_region, 2, 2, 0,  
        doc: /* Return number of characters between BEG and END.  */)  
      (beg, end)  
      Lisp_Object beg, end;  
 {  
   int from, to;  
1459    
1460    CHECK_NUMBER_COERCE_MARKER (beg);  DEFUN ("char-charset", Fchar_charset, Schar_charset, 1, 1, 0,
1461    CHECK_NUMBER_COERCE_MARKER (end);         doc: /* Return the charset of highest priority that contains CHAR.  */)
1462         (ch)
1463    from = min (XFASTINT (beg), XFASTINT (end));       Lisp_Object ch;
1464    to = max (XFASTINT (beg), XFASTINT (end));  {
1465      struct charset *charset;
1466    
1467    return make_number (to - from);    CHECK_CHARACTER (ch);
1468      charset = CHAR_CHARSET (XINT (ch));
1469      return (CHARSET_NAME (charset));
1470  }  }
1471    
 /* Return the number of characters in the NBYTES bytes at PTR.  
    This works by looking at the contents and checking for multibyte sequences.  
    However, if the current buffer has enable-multibyte-characters = nil,  
    we treat each byte as a character.  */  
1472    
1473  int  DEFUN ("charset-after", Fcharset_after, Scharset_after, 0, 1, 0,
1474  chars_in_text (ptr, nbytes)         doc: /*
1475       unsigned char *ptr;  Return charset of a character in the current buffer at position POS.
1476       int nbytes;  If POS is nil, it defauls to the current point.
1477    If POS is out of range, the value is nil.  */)
1478         (pos)
1479         Lisp_Object pos;
1480  {  {
1481    /* current_buffer is null at early stages of Emacs initialization.  */    Lisp_Object ch;
1482    if (current_buffer == 0    struct charset *charset;
       || NILP (current_buffer->enable_multibyte_characters))  
     return nbytes;  
1483    
1484    return multibyte_chars_in_text (ptr, nbytes);    ch = Fchar_after (pos);
1485      if (! INTEGERP (ch))
1486        return ch;
1487      charset = CHAR_CHARSET (XINT (ch));
1488      return (CHARSET_NAME (charset));
1489  }  }
1490    
 /* Return the number of characters in the NBYTES bytes at PTR.  
    This works by looking at the contents and checking for multibyte sequences.  
    It ignores enable-multibyte-characters.  */  
1491    
1492  int  DEFUN ("iso-charset", Fiso_charset, Siso_charset, 3, 3, 0,
1493  multibyte_chars_in_text (ptr, nbytes)         doc: /*
1494       unsigned char *ptr;  Return charset of ISO's specification DIMENSION, CHARS, and FINAL-CHAR.
      int nbytes;  
 {  
   unsigned char *endp;  
   int chars, bytes;  
   
   endp = ptr + nbytes;  
   chars = 0;  
1495    
1496    while (ptr < endp)  ISO 2022's designation sequence (escape sequence) distinguishes charsets
1497      {  by their DIMENSION, CHARS, and FINAL-CHAR,
1498        PARSE_MULTIBYTE_SEQ (ptr, endp - ptr, bytes);  where as Emacs distinguishes them by charset symbol.
1499        ptr += bytes;  See the documentation of the function `charset-info' for the meanings of
1500        chars++;  DIMENSION, CHARS, and FINAL-CHAR.  */)
1501      }       (dimension, chars, final_char)
1502         Lisp_Object dimension, chars, final_char;
1503    {
1504      int id;
1505    
1506    return chars;    check_iso_charset_parameter (dimension, chars, final_char);
1507      id = ISO_CHARSET_TABLE (XFASTINT (dimension), XFASTINT (chars),
1508                              XFASTINT (final_char));
1509      return (id >= 0 ? CHARSET_NAME (CHARSET_FROM_ID (id)) : Qnil);
1510  }  }
1511    
1512  /* Parse unibyte text at STR of LEN bytes as multibyte text, and  
1513     count the numbers of characters and bytes in it.  On counting  DEFUN ("clear-charset-maps", Fclear_charset_maps, Sclear_charset_maps,
1514     bytes, pay attention to the fact that 8-bit characters in the range         0, 0, 0,
1515     0x80..0x9F are represented by 2 bytes in multibyte text.  */         doc: /*
1516  void  Clear encoder and decoder of charsets that are loaded from mapfiles.  */)
1517  parse_str_as_multibyte (str, len, nchars, nbytes)       ()
      unsigned char *str;  
      int len, *nchars, *nbytes;  
1518  {  {
1519    unsigned char *endp = str + len;    int i;
1520    int n, chars = 0, bytes = 0;    struct charset *charset;
1521      Lisp_Object attrs;
1522    
1523    while (str < endp)    for (i = 0; i < charset_table_used; i++)
1524      {      {
1525        if (UNIBYTE_STR_AS_MULTIBYTE_P (str, endp - str, n))        charset = CHARSET_FROM_ID (i);
1526          str += n, bytes += n;        attrs = CHARSET_ATTRIBUTES (charset);
       else  
         str++, bytes += 2;  
       chars++;  
     }  
   *nchars = chars;  
   *nbytes = bytes;  
   return;  
 }  
1527    
1528  /* Arrange unibyte text at STR of NBYTES bytes as multibyte text.        if (CHARSET_METHOD (charset) == CHARSET_METHOD_MAP)
    It actually converts only 8-bit characters in the range 0x80..0x9F  
    that don't contruct multibyte characters to multibyte forms.  If  
    NCHARS is nonzero, set *NCHARS to the number of characters in the  
    text.  It is assured that we can use LEN bytes at STR as a work  
    area and that is enough.  Return the number of bytes of the  
    resulting text.  */  
   
 int  
 str_as_multibyte (str, len, nbytes, nchars)  
      unsigned char *str;  
      int len, nbytes, *nchars;  
 {  
   unsigned char *p = str, *endp = str + nbytes;  
   unsigned char *to;  
   int chars = 0;  
   int n;  
   
   while (p < endp && UNIBYTE_STR_AS_MULTIBYTE_P (p, endp - p, n))  
     p += n, chars++;  
   if (nchars)  
     *nchars = chars;  
   if (p == endp)  
     return nbytes;  
   
   to = p;  
   nbytes = endp - p;  
   endp = str + len;  
   safe_bcopy (p, endp - nbytes, nbytes);  
   p = endp - nbytes;  
   while (p < endp)  
     {  
       if (UNIBYTE_STR_AS_MULTIBYTE_P (p, endp - p, n))  
         {  
           while (n--)  
             *to++ = *p++;  
         }          
       else  
1529          {          {
1530            *to++ = LEADING_CODE_8_BIT_CONTROL;            CHARSET_ATTR_DECODER (attrs) = Qnil;
1531            *to++ = *p++ + 0x20;            CHARSET_ATTR_ENCODER (attrs) = Qnil;
1532              CHARSET_METHOD (charset) = CHARSET_METHOD_MAP_DEFERRED;
1533          }          }
       chars++;  
     }  
   if (nchars)  
     *nchars = chars;  
   return (to - str);  
 }  
   
 /* Parse unibyte string at STR of LEN bytes, and return the number of  
    bytes it may ocupy when converted to multibyte string by  
    `str_to_multibyte'.  */  
   
 int  
 parse_str_to_multibyte (str, len)  
      unsigned char *str;  
      int len;  
 {  
   unsigned char *endp = str + len;  
   int bytes;  
   
   for (bytes = 0; str < endp; str++)  
     bytes += (*str < 0x80 || *str >= 0xA0) ? 1 : 2;  
   return bytes;  
 }  
   
 /* Convert unibyte text at STR of NBYTES bytes to multibyte text  
    that contains the same single-byte characters.  It actually  
    converts all 8-bit characters to multibyte forms.  It is assured  
    that we can use LEN bytes at STR as a work area and that is  
    enough.  */  
   
 int  
 str_to_multibyte (str, len, bytes)  
      unsigned char *str;  
      int len, bytes;  
 {  
   unsigned char *p = str, *endp = str + bytes;  
   unsigned char *to;  
   
   while (p < endp && (*p < 0x80 || *p >= 0xA0)) p++;  
   if (p == endp)  
     return bytes;  
   to = p;  
   bytes = endp - p;  
   endp = str + len;  
   safe_bcopy (p, endp - bytes, bytes);  
   p = endp - bytes;  
   while (p < endp)        
     {  
       if (*p < 0x80 || *p >= 0xA0)  
         *to++ = *p++;  
       else  
         *to++ = LEADING_CODE_8_BIT_CONTROL, *to++ = *p++ + 0x20;  
     }  
   return (to - str);  
 }  
   
 /* Arrange multibyte text at STR of LEN bytes as a unibyte text.  It  
    actually converts only 8-bit characters in the range 0x80..0x9F to  
    unibyte forms.  */  
   
 int  
 str_as_unibyte (str, bytes)  
      unsigned char *str;  
      int bytes;  
 {  
   unsigned char *p = str, *endp = str + bytes;  
   unsigned char *to = str;  
   
   while (p < endp && *p != LEADING_CODE_8_BIT_CONTROL) p++;  
   to = p;  
   while (p < endp)        
     {  
       if (*p == LEADING_CODE_8_BIT_CONTROL)  
         *to++ = *(p + 1) - 0x20, p += 2;  
       else  
         *to++ = *p++;  
     }  
   return (to - str);  
 }  
1534    
1535          if (CHARSET_UNIFIED_P (charset))
1536  DEFUN ("string", Fstring, Sstring, 1, MANY, 0,          CHARSET_ATTR_DEUNIFIER (attrs) = Qnil;
   doc: /* Concatenate all the argument characters and make the result a string.  
 usage: (string &rest CHARACTERS)  */)  
      (n, args)  
      int n;  
      Lisp_Object *args;  
 {  
   int i;  
   unsigned char *buf = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH * n);  
   unsigned char *p = buf;  
   int c;  
   int multibyte = 0;  
   
   for (i = 0; i < n; i++)  
     {  
       CHECK_NUMBER (args[i]);  
       if (!multibyte && !SINGLE_BYTE_CHAR_P (XFASTINT (args[i])))  
         multibyte = 1;  
1537      }      }
1538    
1539    for (i = 0; i < n; i++)    if (CHAR_TABLE_P (Vchar_unified_charset_table))
1540      {      {
1541        c = XINT (args[i]);        Foptimize_char_table (Vchar_unified_charset_table);
1542        if (multibyte)        Vchar_unify_table = Vchar_unified_charset_table;
1543          p += CHAR_STRING (c, p);        Vchar_unified_charset_table = Qnil;
       else  
         *p++ = c;  
1544      }      }
1545    
1546    return make_string_from_bytes (buf, n, p - buf);    return Qnil;
1547  }  }
1548    
 #endif /* emacs */  
1549    
1550  int  void
1551  charset_id_internal (charset_name)  init_charset ()
      char *charset_name;  
1552  {  {
   Lisp_Object val;  
   
   val= Fget (intern (charset_name), Qcharset);  
   if (!VECTORP (val))  
     error ("Charset %s is not defined", charset_name);  
1553    
   return (XINT (XVECTOR (val)->contents[0]));  
1554  }  }
1555    
 DEFUN ("setup-special-charsets", Fsetup_special_charsets,  
        Ssetup_special_charsets, 0, 0, 0, doc: /* Internal use only.  */)  
      ()  
 {  
   charset_latin_iso8859_1 = charset_id_internal ("latin-iso8859-1");  
   charset_jisx0208_1978 = charset_id_internal ("japanese-jisx0208-1978");  
   charset_jisx0208 = charset_id_internal ("japanese-jisx0208");  
   charset_katakana_jisx0201 = charset_id_internal ("katakana-jisx0201");  
   charset_latin_jisx0201 = charset_id_internal ("latin-jisx0201");  
   charset_big5_1 = charset_id_internal ("chinese-big5-1");  
   charset_big5_2 = charset_id_internal ("chinese-big5-2");  
   return Qnil;  
 }  
1556    
1557  void  void
1558  init_charset_once ()  init_charset_once ()
1559  {  {
1560    int i, j, k;    int i, j, k;
1561    
1562    staticpro (&Vcharset_table);    for (i = 0; i < ISO_MAX_DIMENSION; i++)
1563    staticpro (&Vcharset_symbol_table);      for (j = 0; j < ISO_MAX_CHARS; j++)
1564    staticpro (&Vgeneric_character_list);        for (k = 0; k < ISO_MAX_FINAL; k++)
1565            iso_charset_table[i][j][k] = -1;
1566    /* This has to be done here, before we call Fmake_char_table.  */  
1567    Qcharset_table = intern ("charset-table");    for (i = 0; i < 255; i++)
1568    staticpro (&Qcharset_table);      emacs_mule_charset[i] = NULL;
1569    
1570    #if 0
1571      Vchar_charset_set = Fmake_char_table (Qnil, Qnil);
1572      CHAR_TABLE_SET (Vchar_charset_set, make_number (97), Qnil);
1573    
1574      DEFSYM (Qcharset_encode_table, "charset-encode-table");
1575    
1576    /* Intern this now in case it isn't already done.    /* Intern this now in case it isn't already done.
1577       Setting this variable twice is harmless.       Setting this variable twice is harmless.
1578       But don't staticpro it here--that is done in alloc.c.  */       But don't staticpro it here--that is done in alloc.c.  */
1579    Qchar_table_extra_slots = intern ("char-table-extra-slots");    Qchar_table_extra_slots = intern ("char-table-extra-slots");
1580    
1581    /* Now we are ready to set up this property, so we can    /* Now we are ready to set up this property, so we can create syntax
1582       create the charset table.  */       tables.  */
1583    Fput (Qcharset_table, Qchar_table_extra_slots, make_number (0));    Fput (Qcharset_encode_table, Qchar_table_extra_slots, make_number (0));
1584    Vcharset_table = Fmake_char_table (Qcharset_table, Qnil);  #endif
   
   Qunknown = intern ("unknown");  
   staticpro (&Qunknown);  
   Vcharset_symbol_table = Fmake_vector (make_number (MAX_CHARSET + 1),  
                                         Qunknown);  
   
   /* Setup tables.  */  
   for (i = 0; i < 2; i++)  
     for (j = 0; j < 2; j++)  
       for (k = 0; k < 128; k++)  
         iso_charset_table [i][j][k] = -1;  
   
   for (i = 0; i < 256; i++)  
     bytes_by_char_head[i] = 1;  
   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;  
   
   for (i = 0; i < 128; i++)  
     width_by_char_head[i] = 1;  
   for (; i < 256; i++)  
     width_by_char_head[i] = 4;  
   width_by_char_head[LEADING_CODE_PRIVATE_11] = 1;  
   width_by_char_head[LEADING_CODE_PRIVATE_12] = 2;  
   width_by_char_head[LEADING_CODE_PRIVATE_21] = 1;  
   width_by_char_head[LEADING_CODE_PRIVATE_22] = 2;  
   
   {  
     Lisp_Object val;  
   
     val = Qnil;  
     for (i = 0x81; i < 0x90; i++)  
       val = Fcons (make_number ((i - 0x70) << 7), val);  
     for (; i < 0x9A; i++)  
       val = Fcons (make_number ((i - 0x8F) << 14), val);  
     for (i = 0xA0; i < 0xF0; i++)  
       val = Fcons (make_number ((i - 0x70) << 7), val);  
     for (; i < 0xFF; i++)  
       val = Fcons (make_number ((i - 0xE0) << 14), val);  
     Vgeneric_character_list = Fnreverse (val);  
   }  
   
   nonascii_insert_offset = 0;  
   Vnonascii_translation_table = Qnil;  
1585  }  }
1586    
1587  #ifdef emacs  #ifdef emacs
# Line 1768  init_charset_once () Line 1589  init_charset_once ()
1589  void  void
1590  syms_of_charset ()  syms_of_charset ()
1591  {  {
1592    Qcharset = intern ("charset");    char *p;
   staticpro (&Qcharset);  
   
   Qascii = intern ("ascii");  
   staticpro (&Qascii);  
1593    
1594    Qeight_bit_control = intern ("eight-bit-control");    DEFSYM (Qcharsetp, "charsetp");
   staticpro (&Qeight_bit_control);  
1595    
1596    Qeight_bit_graphic = intern ("eight-bit-graphic");    DEFSYM (Qascii, "ascii");
1597    staticpro (&Qeight_bit_graphic);    DEFSYM (Qunicode, "unicode");
1598      DEFSYM (Qeight_bit_control, "eight-bit-control");
1599    /* Define special charsets ascii, eight-bit-control, and    DEFSYM (Qeight_bit_graphic, "eight-bit-graphic");
1600       eight-bit-graphic.  */    DEFSYM (Qiso_8859_1, "iso-8859-1");
1601    update_charset_table (make_number (CHARSET_ASCII),  
1602                          make_number (1), make_number (94),    DEFSYM (Qgl, "gl");
1603                          make_number (1),    DEFSYM (Qgr, "gr");
1604                          make_number (0),  
1605                          make_number ('B'),    p = (char *) xmalloc (30000);
1606                          make_number (0),  
1607                          build_string ("ASCII"),    staticpro (&Vcharset_ordered_list);
1608                          Qnil,   /* same as above */    Vcharset_ordered_list = Qnil;
1609                          build_string ("ASCII (ISO646 IRV)"));  
1610    CHARSET_SYMBOL (CHARSET_ASCII) = Qascii;    staticpro (&Viso_2022_charset_list);
1611    Fput (Qascii, Qcharset, CHARSET_TABLE_ENTRY (CHARSET_ASCII));    Viso_2022_charset_list = Qnil;
1612    
1613    update_charset_table (make_number (CHARSET_8_BIT_CONTROL),    staticpro (&Vemacs_mule_charset_list);
1614                          make_number (1), make_number (96),    Vemacs_mule_charset_list = Qnil;
1615                          make_number (4),  
1616                          make_number (0),    staticpro (&Vcharset_hash_table);
1617                          make_number (-1),    Vcharset_hash_table = Fmakehash (Qeq);
1618                          make_number (-1),  
1619                          build_string ("8-bit control code (0x80..0x9F)"),    charset_table_size = 128;
1620                          Qnil,   /* same as above */    charset_table = ((struct charset *)
1621                          Qnil);  /* same as above */                     xmalloc (sizeof (struct charset) * charset_table_size));
1622    CHARSET_SYMBOL (CHARSET_8_BIT_CONTROL) = Qeight_bit_control;    charset_table_used = 0;
1623    Fput (Qeight_bit_control, Qcharset,  
1624          CHARSET_TABLE_ENTRY (CHARSET_8_BIT_CONTROL));    staticpro (&Vchar_unified_charset_table);
1625      Vchar_unified_charset_table = Fmake_char_table (Qnil, make_number (-1));
1626    update_charset_table (make_number (CHARSET_8_BIT_GRAPHIC),  
1627                          make_number (1), make_number (96),    defsubr (&Scharsetp);
1628                          make_number (4),    defsubr (&Smap_charset_chars);
1629                          make_number (0),    defsubr (&Sdefine_charset_internal);
1630                          make_number (-1),    defsubr (&Sdefine_charset_alias);
1631                          make_number (-1),    defsubr (&Sprimary_charset);
1632                          build_string ("8-bit graphic char (0xA0..0xFF)"),    defsubr (&Sset_primary_charset);
1633                          Qnil,   /* same as above */    defsubr (&Scharset_plist);
1634                          Qnil);  /* same as above */    defsubr (&Sset_charset_plist);
1635    CHARSET_SYMBOL (CHARSET_8_BIT_GRAPHIC) = Qeight_bit_graphic;    defsubr (&Sunify_charset);
   Fput (Qeight_bit_graphic, Qcharset,  
         CHARSET_TABLE_ENTRY (CHARSET_8_BIT_GRAPHIC));  
   
   Qauto_fill_chars = intern ("auto-fill-chars");  
   staticpro (&Qauto_fill_chars);  
   Fput (Qauto_fill_chars, Qchar_table_extra_slots, make_number (0));  
   
   defsubr (&Sdefine_charset);  
   defsubr (&Sgeneric_character_list);  
1636    defsubr (&Sget_unused_iso_final_char);    defsubr (&Sget_unused_iso_final_char);
1637    defsubr (&Sdeclare_equiv_charset);    defsubr (&Sdeclare_equiv_charset);
1638    defsubr (&Sfind_charset_region);    defsubr (&Sfind_charset_region);
1639    defsubr (&Sfind_charset_string);    defsubr (&Sfind_charset_string);
1640    defsubr (&Smake_char_internal);    defsubr (&Sdecode_char);
1641      defsubr (&Sencode_char);
1642    defsubr (&Ssplit_char);    defsubr (&Ssplit_char);
1643      defsubr (&Smake_char);
1644    defsubr (&Schar_charset);    defsubr (&Schar_charset);
1645    defsubr (&Scharset_after);    defsubr (&Scharset_after);
1646    defsubr (&Siso_charset);    defsubr (&Siso_charset);
1647    defsubr (&Schar_valid_p);    defsubr (&Sclear_charset_maps);
1648    defsubr (&Sunibyte_char_to_multibyte);  
1649    defsubr (&Smultibyte_char_to_unibyte);    DEFVAR_LISP ("charset-map-directory", &Vcharset_map_directory,
1650    defsubr (&Schar_bytes);                 doc: /* Directory of charset map files that come with GNU Emacs.
1651    defsubr (&Schar_width);  The default value is \"\\[data-directory]/charsets\".  */);
1652    defsubr (&Sstring_width);    Vcharset_map_directory = Fexpand_file_name (build_string ("charsets"),
1653    defsubr (&Schar_direction);                                                Vdata_directory);
   defsubr (&Schars_in_region);  
   defsubr (&Sstring);  
   defsubr (&Ssetup_special_charsets);  
1654    
1655    DEFVAR_LISP ("charset-list", &Vcharset_list,    DEFVAR_LISP ("charset-list", &Vcharset_list,
1656                 doc: /* List of charsets ever defined.  */);                 doc: /* List of charsets ever defined.  */);
1657    Vcharset_list = Fcons (Qascii, Fcons (Qeight_bit_control,    Vcharset_list = Qnil;
                                         Fcons (Qeight_bit_graphic, Qnil)));  
1658    
1659    DEFVAR_LISP ("translation-table-vector",  &Vtranslation_table_vector,    /* Make the prerequisite charset `ascii' and `unicode'.  */
1660                 doc: /* Vector of cons cell of a symbol and translation table ever defined.    {
1661  An ID of a translation table is an index of this vector.  */);      Lisp_Object args[charset_arg_max];
1662    Vtranslation_table_vector = Fmake_vector (make_number (16), Qnil);      Lisp_Object plist[14];
1663        Lisp_Object val;
1664    DEFVAR_INT ("leading-code-private-11", &leading_code_private_11,  
1665                doc: /* Leading-code of private TYPE9N charset of column-width 1.  */);      plist[0] = intern (":name");
1666    leading_code_private_11 = LEADING_CODE_PRIVATE_11;      plist[1] = args[charset_arg_name] = Qascii;
1667        plist[2] = intern (":dimension");
1668    DEFVAR_INT ("leading-code-private-12", &leading_code_private_12,      plist[3] = args[charset_arg_dimension] = make_number (1);
1669                doc: /* Leading-code of private TYPE9N charset of column-width 2.  */);      val = Fmake_vector (make_number (8), make_number (0));
1670    leading_code_private_12 = LEADING_CODE_PRIVATE_12;      ASET (val, 1, make_number (127));
1671        plist[4] = intern (":code-space");
1672    DEFVAR_INT ("leading-code-private-21", &leading_code_private_21,      plist[5] = args[charset_arg_code_space] = val;
1673                doc: /* Leading-code of private TYPE9Nx9N charset of column-width 1.  */);      plist[6] = intern (":iso-final-char");
1674    leading_code_private_21 = LEADING_CODE_PRIVATE_21;      plist[7] = args[charset_arg_iso_final] = make_number ('B');
1675        args[charset_arg_iso_revision] = Qnil;
1676    DEFVAR_INT ("leading-code-private-22", &leading_code_private_22,      plist[8] = intern (":emacs-mule-id");
1677                doc: /* Leading-code of private TYPE9Nx9N charset of column-width 2.  */);      plist[9] = args[charset_arg_emacs_mule_id] = make_number (0);
1678    leading_code_private_22 = LEADING_CODE_PRIVATE_22;      plist[10] = intern (":ascii-compatible-p");
1679        plist[11] = args[charset_arg_ascii_compatible_p] = Qt;
1680    DEFVAR_INT ("nonascii-insert-offset", &nonascii_insert_offset,      args[charset_arg_supplementary_p] = Qnil;
1681                doc: /* Offset for converting non-ASCII unibyte codes 0240...0377 to multibyte.      args[charset_arg_invalid_code] = Qnil;
1682  This is used for converting unibyte text to multibyte,      plist[12] = intern (":code-offset");
1683  and for inserting character codes specified by number.      plist[13] = args[charset_arg_code_offset] = make_number (0);
1684        args[charset_arg_map] = Qnil;
1685  This serves to convert a Latin-1 or similar 8-bit character code      args[charset_arg_parents] = Qnil;
1686  to the corresponding Emacs multibyte character code.      args[charset_arg_unify_map] = Qnil;
1687  Typically the value should be (- (make-char CHARSET 0) 128),      /* The actual plist is set by mule-conf.el.  */
1688  for your choice of character set.      args[charset_arg_plist] = Flist (14, plist);
1689  If `nonascii-translation-table' is non-nil, it overrides this variable.  */);      Fdefine_charset_internal (charset_arg_max, args);
1690    nonascii_insert_offset = 0;      charset_ascii = CHARSET_SYMBOL_ID (Qascii);
1691    
1692    DEFVAR_LISP ("nonascii-translation-table", &Vnonascii_translation_table,      plist[1] = args[charset_arg_name] = Qunicode;
1693                 doc: /* Translation table to convert non-ASCII unibyte codes to multibyte.      plist[3] = args[charset_arg_dimension] = make_number (3);
1694  This is used for converting unibyte text to multibyte,      val = Fmake_vector (make_number (8), make_number (0));
1695  and for inserting character codes specified by number.      ASET (val, 1, make_number (255));
1696        ASET (val, 3, make_number (255));
1697  Conversion is performed only when multibyte characters are enabled,      ASET (val, 5, make_number (16));
1698  and it serves to convert a Latin-1 or similar 8-bit character code      plist[5] = args[charset_arg_code_space] = val;
1699  to the corresponding Emacs character code.      plist[7] = args[charset_arg_iso_final] = Qnil;
1700        args[charset_arg_iso_revision] = Qnil;
1701  If this is nil, `nonascii-insert-offset' is used instead.      plist[9] = args[charset_arg_emacs_mule_id] = Qnil;
1702  See also the docstring of `make-translation-table'.  */);      plist[11] = args[charset_arg_ascii_compatible_p] = Qt;
1703    Vnonascii_translation_table = Qnil;      args[charset_arg_supplementary_p] = Qnil;
1704        args[charset_arg_invalid_code] = Qnil;
1705    DEFVAR_LISP ("auto-fill-chars", &Vauto_fill_chars,      plist[13] = args[charset_arg_code_offset] = make_number (0);
1706                 doc: /* A char-table for characters which invoke auto-filling.      args[charset_arg_map] = Qnil;
1707  Such characters have value t in this table.  */);      args[charset_arg_parents] = Qnil;
1708    Vauto_fill_chars = Fmake_char_table (Qauto_fill_chars, Qnil);      args[charset_arg_unify_map] = Qnil;
1709    CHAR_TABLE_SET (Vauto_fill_chars, make_number (' '), Qt);      /* The actual plist is set by mule-conf.el.  */
1710    CHAR_TABLE_SET (Vauto_fill_chars, make_number ('\n'), Qt);      args[charset_arg_plist] = Flist (14, plist);
1711        Fdefine_charset_internal (charset_arg_max, args);
1712        charset_unicode = CHARSET_SYMBOL_ID (Qunicode);
1713      }
1714  }  }
1715    
1716  #endif /* emacs */  #endif /* emacs */

Legend:
Removed from v.1.125  
changed lines
  Added in v.1.125.2.1

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26