1 /* locale.c -- locale module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
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.
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.
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
24 @addtogroup m17nLocale
25 @brief Locale objects and API for them.
27 The m17n library represents locale related information as objects
31 @addtogroup m17nLocale
32 @brief ¥í¥±¡¼¥ë¥ª¥Ö¥¸¥§¥¯¥È¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
34 m17n ¥é¥¤¥Ö¥é¥ê¤Ï¥í¥±¡¼¥ë´ØÏ¢¾ðÊó¤ò #MLocale ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Çɽ¸½¤¹¤ë¡£ */
38 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
39 /*** @addtogroup m17nInternal
49 #ifdef HAVE_LANGINFO_H
55 #include "m17n-misc.h"
62 static MSymbol M_locale;
63 static MSymbol M_xfrm;
66 /** Structure of locales. */
80 /** The current locales of each category. */
81 MLocale *mlocale__collate, *mlocale__ctype;
82 MLocale *mlocale__messages, *mlocale__time;
84 /* These are currently not used. */
86 MLocale *mlocale_monetary, *mlocale_numeric, ;
89 /** Parse locale name NAME and return a newly created MLocale object.
90 If the locale is not supported by the system, return NULL. */
93 make_locale (const char *name)
95 char *current, *new, *str;
100 str = setlocale (LC_CTYPE, NULL);
101 len = strlen (str) + 1;
102 current = alloca (len);
103 memcpy (current, str, len);
105 if (! (new = setlocale (LC_CTYPE, name)))
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);
114 len = strlen (new) + 1;
116 memcpy (str, new, len);
124 for (i = 0; str[i]; i++)
125 if (str[i] == '_' || str[i] == '.' || str[i] == '@')
130 /* The first field is for language. */
131 locale->language = msymbol (name);
133 /* The field following '_' is for territory. */
134 locale->territory = msymbol (name);
136 /* The field following '.' is for codeset. */
137 locale->codeset = msymbol (name);
139 /* The other field is for modifier. */
140 locale->modifier = msymbol (name);
147 #ifdef HAVE_NL_LANGINFO
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));
155 /* If the locale name specifies a codeset, get the corresponding
157 if (locale->codeset != Mnil)
159 locale->coding = mconv_resolve_coding (locale->codeset);
160 if (locale->coding == Mnil)
161 locale->coding = Mcoding_us_ascii;
164 locale->coding = Mcoding_us_ascii;
166 setlocale (LC_CTYPE, current);
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. */
175 decode_locale (unsigned char *buf, int size, MLocale *locale)
177 return mconv_decode_buffer (locale->coding, buf, size);
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. */
187 static unsigned char *
188 encode_locale (MText *mt, unsigned char *buf, int *size, MLocale *locale)
190 int nbytes = mconv_encode_buffer (locale->coding, mt, buf, *size - 1);
197 MTABLE_REALLOC (buf, *size, MERROR_LOCALE);
198 nbytes = mconv_encode_buffer (mlocale__ctype->coding, mt, buf,
200 } while (nbytes < 0);
208 /** Structure of transformed strings. The function mtext_coll ()
209 caches this object in an M-text as a text property. */
212 /* Common header for a managed object. */
215 /* Locale corresponding to <str>. */
218 /** Result of strxfrm. */
224 free_xfrm (void *object)
226 MXfrm *xfrm = (MXfrm *) object;
228 M17N_OBJECT_UNREF (xfrm->locale);
235 MTextProperty *prop = mtext_get_property (mt, 0, M_xfrm);
238 unsigned char *buf, *newbuf;
243 if (prop->end == mt->nchars)
245 xfrm = (MXfrm *) prop->val;
246 if (xfrm->locale == mlocale__ctype)
249 mtext_detach_property (prop);
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);
260 xfrm->str = realloc (xfrm->str, request);
261 strxfrm (xfrm->str, (char *) newbuf, size);
265 prop = mtext_property (M_xfrm, xfrm, MTEXTPROP_VOLATILE_WEAK);
266 mtext_attach_property (mt, 0, mt->nchars, prop);
267 M17N_OBJECT_UNREF (prop);
277 M_locale = msymbol_as_managing_key (" locale");
279 Mlanguage = msymbol ("language");
280 Mterritory = msymbol ("territory");
281 Mcodeset = msymbol ("codeset");
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);
292 M_xfrm = msymbol_as_managing_key (" xfrm");
299 M17N_OBJECT_UNREF (mlocale__collate);
300 M17N_OBJECT_UNREF (mlocale__ctype);
301 M17N_OBJECT_UNREF (mlocale__messages);
302 M17N_OBJECT_UNREF (mlocale__time);
306 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
310 /*** @addtogroup m17nLocale */
314 /***en The symbol whose name is "language". */
315 /***ja "language" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë. */
319 /***en The symbol whose name is "territory". */
320 /***ja "territory" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë. */
324 /***en The symbol whose name is "modifier". */
325 /***ja "modifier" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë. */
329 /***en The symbol whose name is "codeset". */
330 /***ja "codeset" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë. */
336 @brief Set the current locale.
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>.
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.
346 If $LOCALE is NULL, the current locale of the specified part is
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 ().
354 Otherwise, it returns NULL. */
357 @brief ¸½ºß¤Î¥í¥±¡¼¥ë¤òÀßÄꤹ¤ë.
359 ´Ø¿ô mlocale_set () ¤Ï¸½ºß¤Î¥í¥±¡¼¥ë¤Î°ìÉô¤òÀßÄꤷ¤¿¤êÌ䤤¹ç¤ï¤»¤¿¤ê¤¹¤ë¡£¤³¤³¤Ç°ìÉô¤È¤Ï
360 $CATEGORY ¤Ç»ØÄꤵ¤ì¡¢<tt>setlocale ()</tt> ¤Î͸ú¤ÊÂè°ì°ú¿ô¤È¤Ê¤ë¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
362 $LOCALE ¤¬ NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢»ØÄꤷ¤¿Éôʬ¤Î¥í¥±¡¼¥ë¤¬$LOCALE ¤ËÀßÄꤵ¤ì¤ë¡£
363 $LOCALE ¤¬¥·¥¹¥Æ¥à¤Ë¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¡¢ÀßÄê¤Ï¹Ô¤ï¤ì¤º¡¢¸½ºß¤Î¥í¥±¡¼¥ë¤ÏÊѤï¤é¤Ê¤¤¡£
365 $LOCALE ¤¬ NULL ¤Ê¤é¤Ð¡¢¸½ºß¤Î¥í¥±¡¼¥ë¤Î»ØÄꤷ¤¿Éôʬ¤òÌ䤤¹ç¤ï¤»¤ë¡£
369 ¸Æ¤Ó½Ð¤·¤ËÀ®¸ù¤¹¤ì¤Ð¡¢mlocale_set () ¤Ï¥í¥±¡¼¥ë¤ËÂбþ¤¹¤ë opaque
370 ¥í¥±¡¼¥ë¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡£¥í¥±¡¼¥ë¤Î̾Á°¤Ï´Ø¿ô
371 mlocale_get_prop () ¤Ë¤è¤Ã¤ÆÆÀ¤ë¤³¤È¤¬¤Ç¤¤ë¡£
373 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð NULL ¤òÊÖ¤¹¡£
381 mlocale_set (int category, const char *name)
386 new = setlocale (category, name);
390 locale = (MLocale *) msymbol_get (msymbol (new), M_locale);
392 locale = make_locale (new);
395 if (name && (category == LC_ALL || category == LC_COLLATE))
397 M17N_OBJECT_REF (locale);
398 M17N_OBJECT_UNREF (mlocale__collate);
399 mlocale__collate = locale;
401 else if (name && (category == LC_ALL || category == LC_CTYPE))
403 M17N_OBJECT_REF (locale);
404 M17N_OBJECT_UNREF (mlocale__ctype);
405 mlocale__ctype = locale;
407 if (name && (category == LC_ALL || category == LC_MESSAGES))
409 M17N_OBJECT_REF (locale);
410 M17N_OBJECT_UNREF (mlocale__messages);
411 mlocale__messages = locale;
413 if (name && (category == LC_ALL || category == LC_TIME))
415 M17N_OBJECT_REF (locale);
416 M17N_OBJECT_UNREF (mlocale__time);
417 mlocale__time = locale;
425 @brief Get the value of a locale property.
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. */
432 @brief ¥í¥±¡¼¥ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
434 ´Ø¿ô mlocale_get_prop () ¤Ï¡¢¥í¥±¡¼¥ë $LOCALE ¤Î $KEY ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£
435 $KEY ¤Ï #Mname, #Mlanguage, #Mterritory, #Mcodeset, #Mmodifier,
436 #Mcoding ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£ */
439 mlocale_get_prop (MLocale *locale, MSymbol key)
442 return locale->coding;
445 if (key == Mlanguage)
446 return locale->language;
447 if (key == Mterritory)
448 return locale->territory;
450 return locale->codeset;
451 if (key == Mmodifier)
452 return locale->modifier;
458 @brief Format date and time.
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).
465 The meaning of the arguments $TM and $FORMAT are the same as those
472 @brief ÆüÉդȻþ´Ö¤ò¥Õ¥©¡¼¥Þ¥Ã¥È¤¹¤ë.
474 ´Ø¿ô mtext_ftime () ¤Ï»þ¹ï¥Ç¡¼¥¿ (broken-down time) $TM ¤ò$FORMAT
475 ¤Ç»ØÄꤵ¤ì¤¿·Á¼°¤ËÀ¶½ñ¤·¡¢·ë²Ì¤òM-text $MT ¤ËÉղ乤롣¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï
476 NULL ¤Ç¤Ê¤±¤ì¤Ð ¥í¥±¡¼¥ë $LOCALE ¤Ë¡¢¤Þ¤¿¤Ï¸½ºß¤Î¥í¥±¡¼¥ë(LC_TIME) ¤Ë½¾¤¦¡£
478 °ú¿ô $TM ¤È $FORMAT ¤Î°ÕÌ£¤Ï strftime () ¤Î¾ì¹ç¤ÈƱ¤¸¡£
485 mtext_ftime (MText *mt, const char *format, const struct tm *tm,
490 size_t nbytes, nchars;
491 char *current_locale = NULL;
495 char *str = setlocale (LC_TIME, NULL);
496 int len = strlen (str) + 1;
498 current_locale = alloca (len);
499 memcpy (current_locale, str, len);
500 mlocale_set (LC_TIME, msymbol_name (locale->name));
506 MTABLE_ALLOCA (buf, bufsize, MERROR_MTEXT);
508 nbytes = strftime ((char *) buf, bufsize, format, tm);
517 MText *work = decode_locale (buf, nbytes, mlocale__time);
521 nchars = work->nchars;
522 mtext_cat (mt, work);
523 M17N_OBJECT_UNREF (work);
532 mlocale_set (LC_TIME, current_locale);
540 @brief Get an environment variable.
542 The mtext_getenv () function searches the environment variable
543 list for a string that matches the string pointed to by $NAME.
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
549 If there is no match, the function returns NULL. */
551 @brief ´Ä¶ÊÑ¿ô¤òÆÀ¤ë.
553 ´Ø¿ô mtext_getenv () ¤Ï $NAME
554 ¤Ç»Ø¤µ¤ì¤ëʸ»úÎó¤È¹çÃפ¹¤ëʸ»úÎó¤ò´Ä¶ÊÑ¿ô¤Î¥ê¥¹¥ÈÃ椫¤éõ¤¹¡£
556 ¸«¤Ä¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¤½¤ÎÃͤò¸½ºß¤Î¥í¥±¡¼¥ë(LC_CTYPE) ¤Ë½¾¤Ã¤Æ
557 M-text ¤Ë¥Ç¥³¡¼¥É¤·¡¢¤½¤ÎM-text ¤òÊÖ¤¹¡£
559 ¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢NULL ¤òÊÖ¤¹¡£ */
562 mtext_getenv (const char *name)
564 char *p = getenv (name);
568 return decode_locale ((unsigned char *) p, strlen (p), mlocale__ctype);
574 @brief Change or add an environment variable.
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).
582 This function returns zero on success, or -1 if an error
585 @brief ´Ä¶ÊÑ¿ô¤òÊѹ¹¡¿Äɲ乤ë.
587 ´Ø¿ô mtext_putenv () ¤Ï M-text $MT
588 ¤Ë½¾¤Ã¤Æ¡¢´Ä¶ÊÑ¿ô¤ÎÃͤòÊѹ¹¤·¤¿¤êÄɲä·¤¿¤ê¤¹¤ë¡£¤³¤Î´Ø¿ô¤Ï¡¢¸½ºß¤Î¥í¥±¡¼¥ë
589 (LC_CTYPE) ¤Ë½¾¤Ã¤Æ$MT ¤ò¥¨¥ó¥³¡¼¥É¤·¡¢¤½¤ì¤ò°ú¿ô¤È¤·¤Æ´Ø¿ô <tt>putenv</tt> ¤ò¸Æ¤Ö¡£
592 ¤³¤Î´Ø¿ô¤Ï¡¢À®¸ù¤·¤¿¾ì¹ç¤Ë¤Ï 0 ¤ò¡¢¥¨¥é¡¼¤¬µ¯¤³¤ì¤Ð -1 ¤òÊÖ¤¹¡£
597 mtext_putenv (MText *mt)
599 unsigned char buf[1024];
601 unsigned char *newbuf;
604 newbuf = encode_locale (mt, buf, &size, mlocale__ctype);
605 result = putenv ((char *) newbuf);
614 @brief Compare two M-texts using the current locale.
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).
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
627 @brief ¸½ºß¤Î¥í¥±¡¼¥ë¤òÍѤ¤¤Æ£²¤Ä¤Î M-text ¤òÈæ³Ó¤¹¤ë.
629 ´Ø¿ô mtext_coll () ¤Ï£²¤Ä¤Î M-text $MT1 ¤È $MT2
630 ¤òÈæ³Ó¤¹¤ë¡£Ìá¤êÃͤÏÉé¤ÎÀ°¿ôÃÍ, 0, Àµ¤ÎÀ°¿ôÃͤΤ¤¤º¤ì¤«¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì
631 $MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤¤¡¢Æ±¤¸¡¢Â礤¤¾ì¹ç¤ËÁêÅö¤¹¤ë¡£Èæ³Ó¤Ï¸½ºß¤Î¥í¥±¡¼¥ë
632 (LC_COLLATE) ¤Ë´ð¤Å¤¤¤Æ¹Ô¤ï¤ì¤ë¡£
635 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤È¤·¤Æ¼«Æ°Åª¤Ë¥¥ã¥Ã¥·¥å¤µ¤ì¤ë¾ðÊó¤òÍøÍѤ¹¤ë¤Î¤Ç¡¢£²ÅÙÌܰʹߤÎƱ¤¸Èæ³Ó¤Ï£±ÅÙÌܤè¤ê®¤¯¼Â¹Ô¤µ¤ì¤ë¡£ */
638 mtext_coll (MText *mt1, MText *mt2)
642 if (mt1->nchars == 0)
643 return (mt2->nchars == 0 ? 0 : -1);
644 else if (mt2->nchars == 0)
647 str1 = get_xfrm (mt1);
648 str2 = get_xfrm (mt2);
649 return strcoll (str1, str2);