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