(mtext__init): Call M17N_OBJECT_ADD_ARRAY.
[m17n/m17n-lib.git] / src / locale.c
1 /* locale.c -- locale module.
2    Copyright (C) 2003, 2004
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21    02111-1307, USA.  */
22
23 /***en
24     @addtogroup m17nLocale
25     @brief Locale objects and API for them.
26
27     The m17n library represents locale related information as objects
28     of type #MLocale.  */
29
30 /***ja
31     @addtogroup m17nLocale
32     @brief ¥í¥±¡¼¥ë¥ª¥Ö¥¸¥§¥¯¥È¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
33
34     m17n ¥é¥¤¥Ö¥é¥ê¤Ï¥í¥±¡¼¥ë´ØÏ¢¾ðÊó¤ò #MLocale ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Çɽ¸½¤¹¤ë¡£  */
35
36 /*=*/
37
38 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
39 /*** @addtogroup m17nInternal
40      @{ */
41
42 #define _GNU_SOURCE
43
44 #include <config.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <locale.h>
49 #ifdef HAVE_LANGINFO_H
50 #include <langinfo.h>
51 #endif
52 #include <time.h>
53
54 #include "m17n.h"
55 #include "m17n-misc.h"
56 #include "internal.h"
57 #include "symbol.h"
58 #include "coding.h"
59 #include "textprop.h"
60 #include "mlocale.h"
61
62 static MSymbol M_locale;
63 static MSymbol M_xfrm;
64
65
66 /** Structure of locales.  */
67
68 struct MLocale
69 {
70   M17NObject control;
71   MSymbol name;
72   MSymbol language;
73   MSymbol territory;
74   MSymbol modifier;
75   MSymbol codeset;
76   MSymbol coding;
77 };
78
79
80 /** The current locales of each category.  */
81 MLocale *mlocale__collate, *mlocale__ctype;
82 MLocale *mlocale__messages, *mlocale__time;
83
84 /* These are currently not used.  */
85 #if 0
86 MLocale *mlocale_monetary, *mlocale_numeric, ;
87 #endif
88
89 /** Parse locale name NAME and return a newly created MLocale object.
90     If the locale is not supported by the system, return NULL.  */
91
92 static MLocale *
93 make_locale (const char *name)
94 {
95   char *current, *new, *str;
96   int len;
97   MLocale *locale;
98   char c;
99
100   str = setlocale (LC_CTYPE, NULL);
101   len = strlen (str) + 1;
102   current = alloca (len);
103   memcpy (current, str, len); 
104
105   if (! (new = setlocale (LC_CTYPE, name)))
106     return NULL;
107
108
109   M17N_OBJECT (locale, NULL, MERROR_LOCALE);
110   locale->name = msymbol (new);
111   msymbol_put (locale->name, M_locale, (void *) locale);
112   M17N_OBJECT_UNREF (locale);
113
114   len = strlen (new) + 1;
115   str = alloca (len);
116   memcpy (str, new, len);
117
118   c = '\0';
119   while (1)
120     {
121       char c1;
122       int i;
123
124       for (i = 0; str[i]; i++)
125         if (str[i] == '_' || str[i] == '.' || str[i] == '@')
126           break;
127       c1 = str[i];
128       str[i] = '\0';
129       if (c == '\0')
130         /* The first field is for language.  */
131         locale->language = msymbol (name);      
132       else if (c == '_')
133         /* The field following '_' is for territory.  */
134         locale->territory = msymbol (name);
135       else if (c == '.')
136         /* The field following '.' is for codeset.  */
137         locale->codeset = msymbol (name);
138       else
139         /* The other field is for modifier.  */
140         locale->modifier = msymbol (name);
141       if (! c1)
142         break;
143       c = c1;
144       name += i + 1;
145     }
146
147 #ifdef HAVE_NL_LANGINFO
148 #ifdef CODESET
149   /* If we can use nl_langinfo () to retrieve a codeset name, respect
150      it over the codeset name extracted from the locale name.  */
151   locale->codeset = msymbol (nl_langinfo (CODESET));
152 #endif
153 #endif
154
155   /* If the locale name specifies a codeset, get the corresponding
156      coding system.  */
157   if (locale->codeset != Mnil)
158     {
159       locale->coding = mconv_resolve_coding (locale->codeset);
160       if (locale->coding == Mnil)
161         locale->coding = Mcoding_us_ascii;
162     }
163   else
164     locale->coding = Mcoding_us_ascii;
165
166   setlocale (LC_CTYPE, current);
167   return locale;
168 }
169
170
171 /** Decode the byte sequence at BUF of length SIZE bytes by the coding
172     system associated with LOCALE, and return a generated M-text.  */
173
174 static MText *
175 decode_locale (unsigned char *buf, int size, MLocale *locale)
176 {
177   return mconv_decode_buffer (locale->coding, buf, size);
178 }
179
180
181 /** Encode the M-text MT by the coding system associated with LOCALE,
182     and store the resulting bytes in the memory area at BUF of *SIZE
183     bytes.  If the area is too short, allocate a new and wider area.
184     Store the length of the generated bytes in the place pointed by
185     SIZE, and return the address of those bytes.  */
186
187 static unsigned char *
188 encode_locale (MText *mt, unsigned char *buf, int *size, MLocale *locale)
189 {
190   int nbytes = mconv_encode_buffer (locale->coding, mt, buf, *size - 1);
191
192   if (nbytes < 0)
193     {
194       buf = NULL;
195       *size *= 2;
196       do {
197         MTABLE_REALLOC (buf, *size, MERROR_LOCALE);
198         nbytes = mconv_encode_buffer (mlocale__ctype->coding, mt, buf,
199                                       *size - 1);
200       } while (nbytes < 0);
201     }
202   buf[nbytes] = '\0';
203   *size = nbytes;
204   return buf;
205 }
206
207
208 /** Structure of transformed strings.  The function mtext_coll ()
209     caches this object in an M-text as a text property.  */
210
211 typedef struct {
212   /* Common header for a managed object.  */
213   M17NObject control;
214
215   /* Locale corresponding to <str>.  */
216   MLocale *locale;
217
218   /** Result of strxfrm.  */
219   char *str;
220 } MXfrm;
221
222
223 static void
224 free_xfrm (void *object)
225 {
226   MXfrm *xfrm = (MXfrm *) object;
227
228   M17N_OBJECT_UNREF (xfrm->locale);
229   free (xfrm->str);
230 }
231
232 static char *
233 get_xfrm (MText *mt)
234 {
235   MTextProperty *prop = mtext_get_property (mt, 0, M_xfrm);
236   MXfrm *xfrm;
237   int size;
238   unsigned char *buf, *newbuf;
239   int request;
240
241   if (prop)
242     {
243       if (prop->end == mt->nchars)
244         {
245           xfrm = (MXfrm *) prop->val;
246           if (xfrm->locale == mlocale__ctype)
247             return xfrm->str;
248         }
249       mtext_detach_property (prop);
250     }
251
252   size = mt->nbytes;
253   buf = alloca (size);
254   newbuf = encode_locale (mt, buf, &size, mlocale__ctype);
255   M17N_OBJECT (xfrm, free_xfrm, MERROR_MTEXT);
256   xfrm->str = malloc (size);
257   request = strxfrm (xfrm->str, (char *) newbuf, size);
258   if (request >= size)
259     {
260       xfrm->str = realloc (xfrm->str, request);
261       strxfrm (xfrm->str, (char *) newbuf, size);
262     }
263   if (buf != newbuf)
264     free (newbuf);
265   prop = mtext_property (M_xfrm, xfrm, MTEXTPROP_VOLATILE_WEAK);
266   mtext_attach_property (mt, 0, mt->nchars, prop);
267   M17N_OBJECT_UNREF (prop);
268   return xfrm->str;
269 }
270
271 \f
272 /* Internal API */
273
274 int
275 mlocale__init ()
276 {
277   M_locale = msymbol_as_managing_key ("  locale");
278
279   Mlanguage = msymbol ("language");
280   Mterritory = msymbol ("territory");
281   Mcodeset = msymbol ("codeset");
282
283   mlocale__collate = mlocale_set (LC_COLLATE, NULL);
284   M17N_OBJECT_REF (mlocale__collate);
285   mlocale__ctype = mlocale_set (LC_CTYPE, NULL);
286   M17N_OBJECT_REF (mlocale__ctype);
287   mlocale__messages = mlocale_set (LC_MESSAGES, NULL);
288   M17N_OBJECT_REF (mlocale__messages);
289   mlocale__time = mlocale_set (LC_TIME, NULL);
290   M17N_OBJECT_REF (mlocale__time);
291
292   M_xfrm = msymbol_as_managing_key ("  xfrm");
293   return 0;
294 }
295
296 void
297 mlocale__fini ()
298 {
299   M17N_OBJECT_UNREF (mlocale__collate);
300   M17N_OBJECT_UNREF (mlocale__ctype);
301   M17N_OBJECT_UNREF (mlocale__messages);
302   M17N_OBJECT_UNREF (mlocale__time);
303 }
304
305 /*** @} */
306 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
307
308 \f
309 /* External API */
310 /*** @addtogroup m17nLocale */
311 /*** @{ */
312
313 /*=*/
314 /***en The symbol whose name is "language".  */
315 /***ja "language" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.  */
316 MSymbol Mlanguage;
317
318 /*=*/
319 /***en The symbol whose name is "territory".  */
320 /***ja  "territory" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë. */
321 MSymbol Mterritory;
322
323 /*=*/
324 /***en The symbol whose name is "modifier".  */
325 /***ja  "modifier" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë. */
326 MSymbol Mmodifier;
327
328 /*=*/
329 /***en The symbol whose name is "codeset".  */
330 /***ja  "codeset" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë. */
331 MSymbol Mcodeset;
332
333 /*=*/
334
335 /***en
336     @brief Set the current locale.
337
338     The mlocale_set () function sets or query a part of the current
339     locale.  The part is specified by $CATEGORY which must be a valid
340     first argument to <tt>setlocale ()</tt>.
341
342     If $LOCALE is not NULL, the locale of the specified part is set to
343     $LOCALE.  If $LOCALE is not supported by the system, the current
344     locale is not changed.
345
346     If $LOCALE is NULL, the current locale of the specified part is
347     queried.
348
349     @return
350     If the call is successful, mlocale_set () returns an opaque locale
351     object that corresponds to the locale.  The name of the locale can
352     be acquired by the function mlocale_get_prop ().
353
354     Otherwise, it returns NULL.  */
355
356 /***ja
357     @brief ¸½ºß¤Î¥í¥±¡¼¥ë¤òÀßÄꤹ¤ë.
358
359     ´Ø¿ô mlocale_set () ¤Ï¸½ºß¤Î¥í¥±¡¼¥ë¤Î°ìÉô¤òÀßÄꤷ¤¿¤êÌ䤤¹ç¤ï¤»¤¿¤ê¤¹¤ë¡£¤³¤³¤Ç°ìÉô¤È¤Ï 
360     $CATEGORY ¤Ç»ØÄꤵ¤ì¡¢<tt>setlocale ()</tt> ¤ÎÍ­¸ú¤ÊÂè°ì°ú¿ô¤È¤Ê¤ë¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
361
362     $LOCALE ¤¬ NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢»ØÄꤷ¤¿Éôʬ¤Î¥í¥±¡¼¥ë¤¬$LOCALE ¤ËÀßÄꤵ¤ì¤ë¡£
363     $LOCALE ¤¬¥·¥¹¥Æ¥à¤Ë¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¡¢ÀßÄê¤Ï¹Ô¤ï¤ì¤º¡¢¸½ºß¤Î¥í¥±¡¼¥ë¤ÏÊѤï¤é¤Ê¤¤¡£
364
365     $LOCALE ¤¬ NULL ¤Ê¤é¤Ð¡¢¸½ºß¤Î¥í¥±¡¼¥ë¤Î»ØÄꤷ¤¿Éôʬ¤òÌ䤤¹ç¤ï¤»¤ë¡£
366
367     @return 
368
369     ¸Æ¤Ó½Ð¤·¤ËÀ®¸ù¤¹¤ì¤Ð¡¢mlocale_set () ¤Ï¥í¥±¡¼¥ë¤ËÂбþ¤¹¤ë opaque 
370     ¥í¥±¡¼¥ë¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡£¥í¥±¡¼¥ë¤Î̾Á°¤Ï´Ø¿ô
371     mlocale_get_prop () ¤Ë¤è¤Ã¤ÆÆÀ¤ë¤³¤È¤¬¤Ç¤­¤ë¡£
372
373     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð NULL ¤òÊÖ¤¹¡£
374      */
375
376 /***
377     @errors
378     @c MERROR_LOCALE  */
379
380 MLocale *
381 mlocale_set (int category, const char *name)
382 {
383   char *new;
384   MLocale *locale;
385
386   new = setlocale (category, name);
387   if (! new)
388     return NULL;
389
390   locale = (MLocale *) msymbol_get (msymbol (new), M_locale);
391   if (! locale)
392     locale = make_locale (new);
393   if (! locale)
394     return NULL;
395   if (name && (category == LC_ALL || category == LC_COLLATE))
396     {
397       M17N_OBJECT_REF (locale);
398       M17N_OBJECT_UNREF (mlocale__collate);
399       mlocale__collate = locale;
400     }
401   else if (name && (category == LC_ALL || category == LC_CTYPE))
402     {
403       M17N_OBJECT_REF (locale);
404       M17N_OBJECT_UNREF (mlocale__ctype);
405       mlocale__ctype = locale;
406     }
407   if (name && (category == LC_ALL || category == LC_MESSAGES))
408     {
409       M17N_OBJECT_REF (locale);
410       M17N_OBJECT_UNREF (mlocale__messages);
411       mlocale__messages = locale;
412     }
413   if (name && (category == LC_ALL || category == LC_TIME))
414     {
415       M17N_OBJECT_REF (locale);
416       M17N_OBJECT_UNREF (mlocale__time);
417       mlocale__time = locale;
418     }
419   return locale;
420 }
421
422 /*=*/
423
424 /***en
425     @brief Get the value of a locale property.
426
427     The mlocale_get_prop () function returns the value of a property
428     $KEY of local $LOCALE.  $KEY must be #Mname, #Mlanguage,
429     #Mterritory, #Mcodeset, #Mmodifier, or #Mcoding.  */ 
430
431 /***ja
432     @brief ¥í¥±¡¼¥ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
433
434     ´Ø¿ô mlocale_get_prop () ¤Ï¡¢¥í¥±¡¼¥ë $LOCALE ¤Î $KEY ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£
435     $KEY ¤Ï #Mname, #Mlanguage, #Mterritory, #Mcodeset, #Mmodifier, 
436     #Mcoding ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£ */ 
437
438 MSymbol
439 mlocale_get_prop (MLocale *locale, MSymbol key)
440 {
441   if (key == Mcoding)
442     return locale->coding;
443   if (key == Mname)
444     return locale->name;
445   if (key == Mlanguage)
446     return locale->language;
447   if (key == Mterritory)
448     return locale->territory;
449   if (key == Mcodeset)
450     return locale->codeset;
451   if (key == Mmodifier)
452     return locale->modifier;
453   return Mnil;
454 }
455
456 /*=*/
457 /***en
458     @brief Format date and time.
459
460     The mtext_ftime () function formats the broken-down time $TM
461     according to the format specification $FORMAT and append the
462     result to the M-text $MT.  The formating is done according to the
463     locale $LOCALE (if not NULL) or the current locale (LC_TIME).
464
465     The meaning of the arguments $TM and $FORMAT are the same as those
466     of strftime ().
467
468     @seealso
469     strftime ()
470 */
471 /***ja
472     @brief ÆüÉդȻþ´Ö¤ò¥Õ¥©¡¼¥Þ¥Ã¥È¤¹¤ë.
473
474     ´Ø¿ô mtext_ftime () ¤Ï»þ¹ï¥Ç¡¼¥¿ (broken-down time) $TM ¤ò$FORMAT 
475     ¤Ç»ØÄꤵ¤ì¤¿·Á¼°¤ËÀ¶½ñ¤·¡¢·ë²Ì¤òM-text $MT ¤ËÉղ乤롣¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï 
476     NULL ¤Ç¤Ê¤±¤ì¤Ð ¥í¥±¡¼¥ë $LOCALE ¤Ë¡¢¤Þ¤¿¤Ï¸½ºß¤Î¥í¥±¡¼¥ë(LC_TIME) ¤Ë½¾¤¦¡£
477
478     °ú¿ô $TM ¤È $FORMAT ¤Î°ÕÌ£¤Ï strftime () ¤Î¾ì¹ç¤ÈƱ¤¸¡£
479
480     @seealso
481     strftime ()
482 */
483
484 int
485 mtext_ftime (MText *mt, const char *format, const struct tm *tm,
486              MLocale *locale)
487 {
488   int bufsize;
489   unsigned char *buf;
490   size_t nbytes, nchars;
491   char *current_locale = NULL;
492
493   if (locale)
494     {
495       char *str = setlocale (LC_TIME, NULL);
496       int len = strlen (str) + 1;
497
498       current_locale = alloca (len);
499       memcpy (current_locale, str, len);
500       mlocale_set (LC_TIME, msymbol_name (locale->name));
501     }
502
503   bufsize = 1024;
504   while (1)
505     {
506       MTABLE_ALLOCA (buf, bufsize, MERROR_MTEXT);
507       buf[0] = 1;
508       nbytes = strftime ((char *) buf, bufsize, format, tm);
509       if (nbytes > 0
510           || ! buf[0])
511         break;
512       bufsize *= 2;
513     }
514
515   if (nbytes > 0)
516     {
517       MText *work = decode_locale (buf, nbytes, mlocale__time);
518
519       if (work)
520         {
521           nchars = work->nchars;
522           mtext_cat (mt, work);
523           M17N_OBJECT_UNREF (work);
524         }
525       else
526         nchars = 0;
527     }
528   else
529     nchars = 0;
530
531   if (current_locale)
532     mlocale_set (LC_TIME, current_locale);
533
534   return nchars;
535 }
536           
537 /*=*/
538
539 /***en
540     @brief Get an environment variable.
541
542     The mtext_getenv () function searches the environment variable
543     list for a string that matches the string pointed to by $NAME.
544
545     If there is a match, the function decodes the value according to
546     the current locale (LC_CTYPE) into an M-text, and return that
547     M-text.
548
549     If there is no match, the function returns NULL.  */
550 /***ja
551     @brief ´Ä¶­ÊÑ¿ô¤òÆÀ¤ë.
552
553     ´Ø¿ô mtext_getenv () ¤Ï $NAME 
554     ¤Ç»Ø¤µ¤ì¤ëʸ»úÎó¤È¹çÃפ¹¤ëʸ»úÎó¤ò´Ä¶­ÊÑ¿ô¤Î¥ê¥¹¥ÈÃ椫¤éõ¤¹¡£
555
556     ¸«¤Ä¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¤½¤ÎÃͤò¸½ºß¤Î¥í¥±¡¼¥ë(LC_CTYPE) ¤Ë½¾¤Ã¤Æ 
557     M-text ¤Ë¥Ç¥³¡¼¥É¤·¡¢¤½¤ÎM-text ¤òÊÖ¤¹¡£
558
559     ¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢NULL ¤òÊÖ¤¹¡£  */
560
561 MText *
562 mtext_getenv (const char *name)
563 {
564   char *p = getenv (name);
565
566   if (!p)
567     return NULL;
568   return decode_locale ((unsigned char *) p, strlen (p), mlocale__ctype);
569 }
570
571 /*=*/
572
573 /***en
574     @brief Change or add an environment variable.
575
576     The mtext_putenv () function changes or adds the value of
577     environment variables according to M-text $MT.  It calls the
578     function <tt>putenv</tt> with an argument generated by encoding
579     $MT according to the current locale (LC_CTYPE).
580
581     @return
582     This function returns zero on success, or -1 if an error
583     occurs.  */
584 /***ja
585     @brief ´Ä¶­ÊÑ¿ô¤òÊѹ¹¡¿Äɲ乤ë.
586
587     ´Ø¿ô mtext_putenv () ¤Ï M-text $MT 
588     ¤Ë½¾¤Ã¤Æ¡¢´Ä¶­ÊÑ¿ô¤ÎÃͤòÊѹ¹¤·¤¿¤êÄɲä·¤¿¤ê¤¹¤ë¡£¤³¤Î´Ø¿ô¤Ï¡¢¸½ºß¤Î¥í¥±¡¼¥ë
589     (LC_CTYPE) ¤Ë½¾¤Ã¤Æ$MT ¤ò¥¨¥ó¥³¡¼¥É¤·¡¢¤½¤ì¤ò°ú¿ô¤È¤·¤Æ´Ø¿ô <tt>putenv</tt> ¤ò¸Æ¤Ö¡£
590
591     @return
592     ¤³¤Î´Ø¿ô¤Ï¡¢À®¸ù¤·¤¿¾ì¹ç¤Ë¤Ï 0 ¤ò¡¢¥¨¥é¡¼¤¬µ¯¤³¤ì¤Ð -1 ¤òÊÖ¤¹¡£
593     */
594
595
596 int
597 mtext_putenv (MText *mt)
598 {
599   unsigned char buf[1024];
600   int size = 1024;
601   unsigned char *newbuf;
602   int result;
603
604   newbuf = encode_locale (mt, buf, &size, mlocale__ctype);
605   result = putenv ((char *) newbuf);
606   if (buf != newbuf)
607     free (newbuf);
608   return result;
609 }
610
611 /*=*/
612
613 /***en
614     @brief Compare two M-texts using the current locale.
615
616     The mtext_coll () function compares the two M-texts $MT1 and $MT2.
617     It returns an integer less than, equal to, or greater than zero if
618     $MT1 is found, respectively, to be less than, to match, or to be
619     greater than $MT2.  The comparison is based on texts as
620     appropriate for the current locale (LC_COLLATE).
621
622     This function makes use of information that is automatically
623     cached in the M-texts as a text property.  So, the second call of
624     this function with $MT1 or $MT2 finishes faster than the first
625     call.  */
626 /***ja
627     @brief ¸½ºß¤Î¥í¥±¡¼¥ë¤òÍѤ¤¤Æ£²¤Ä¤Î M-text ¤òÈæ³Ó¤¹¤ë.
628
629     ´Ø¿ô mtext_coll () ¤Ï£²¤Ä¤Î M-text $MT1 ¤È $MT2 
630     ¤òÈæ³Ó¤¹¤ë¡£Ìá¤êÃͤÏÉé¤ÎÀ°¿ôÃÍ, 0, Àµ¤ÎÀ°¿ôÃͤΤ¤¤º¤ì¤«¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì 
631     $MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤¤¡¢Æ±¤¸¡¢Â礭¤¤¾ì¹ç¤ËÁêÅö¤¹¤ë¡£Èæ³Ó¤Ï¸½ºß¤Î¥í¥±¡¼¥ë 
632     (LC_COLLATE) ¤Ë´ð¤Å¤¤¤Æ¹Ô¤ï¤ì¤ë¡£
633
634     ¤³¤Î´Ø¿ô¤Ï M-text 
635     ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤È¤·¤Æ¼«Æ°Åª¤Ë¥­¥ã¥Ã¥·¥å¤µ¤ì¤ë¾ðÊó¤òÍøÍѤ¹¤ë¤Î¤Ç¡¢£²ÅÙÌܰʹߤÎƱ¤¸Èæ³Ó¤Ï£±ÅÙÌܤè¤ê®¤¯¼Â¹Ô¤µ¤ì¤ë¡£  */
636
637 int
638 mtext_coll (MText *mt1, MText *mt2)
639 {
640   char *str1, *str2;
641
642   if (mt1->nchars == 0)
643     return (mt2->nchars == 0 ? 0 : -1);
644   else if (mt2->nchars == 0)
645     return 1;
646
647   str1 = get_xfrm (mt1);
648   str2 = get_xfrm (mt2);
649   return strcoll (str1, str2);
650 }
651
652 /*** @} */
653
654 /*
655   Local Variables:
656   coding: euc-japan
657   End:
658 */