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 ·¿¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ç
39 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
40 /*** @addtogroup m17nInternal
50 #ifdef HAVE_LANGINFO_H
56 #include "m17n-misc.h"
63 static MSymbol M_locale;
64 static MSymbol M_xfrm;
67 /** Structure of locales. */
81 /** The current locales of each category. */
82 MLocale *mlocale__collate, *mlocale__ctype;
83 MLocale *mlocale__messages, *mlocale__time;
85 /* These are currently not used. */
87 MLocale *mlocale_monetary, *mlocale_numeric, ;
90 /** Parse locale name NAME and return a newly created MLocale object.
91 If the locale is not supported by the system, return NULL. */
94 make_locale (const char *name)
96 char *current, *new, *str;
101 str = setlocale (LC_CTYPE, NULL);
102 len = strlen (str) + 1;
103 current = alloca (len);
104 memcpy (current, str, len);
106 if (! (new = setlocale (LC_CTYPE, name)))
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);
115 len = strlen (new) + 1;
117 memcpy (str, new, len);
125 for (i = 0; str[i]; i++)
126 if (str[i] == '_' || str[i] == '.' || str[i] == '@')
131 /* The first field is for language. */
132 locale->language = msymbol (name);
134 /* The field following '_' is for territory. */
135 locale->territory = msymbol (name);
137 /* The field following '.' is for codeset. */
138 locale->codeset = msymbol (name);
140 /* The other field is for modifier. */
141 locale->modifier = msymbol (name);
148 #ifdef HAVE_NL_LANGINFO
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));
156 /* If the locale name specifies a codeset, get the corresponding
158 if (locale->codeset != Mnil)
160 locale->coding = mconv_resolve_coding (locale->codeset);
161 if (locale->coding == Mnil)
162 locale->coding = Mcoding_us_ascii;
165 locale->coding = Mcoding_us_ascii;
167 setlocale (LC_CTYPE, current);
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. */
176 decode_locale (unsigned char *buf, int size, MLocale *locale)
178 return mconv_decode_buffer (locale->coding, buf, size);
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. */
188 static unsigned char *
189 encode_locale (MText *mt, unsigned char *buf, int *size, MLocale *locale)
191 int nbytes = mconv_encode_buffer (locale->coding, mt, buf, *size - 1);
198 MTABLE_REALLOC (buf, *size, MERROR_LOCALE);
199 nbytes = mconv_encode_buffer (mlocale__ctype->coding, mt, buf,
201 } while (nbytes < 0);
209 /** Structure of transformed strings. The function mtext_coll ()
210 caches this object in an M-text as a text property. */
213 /* Common header for a managed object. */
216 /* Locale corresponding to <str>. */
219 /** Result of strxfrm. */
225 free_xfrm (void *object)
227 MXfrm *xfrm = (MXfrm *) object;
229 M17N_OBJECT_UNREF (xfrm->locale);
236 MTextProperty *prop = mtext_get_property (mt, 0, M_xfrm);
239 unsigned char *buf, *newbuf;
244 if (prop->end == mt->nchars)
246 xfrm = (MXfrm *) prop->val;
247 if (xfrm->locale == mlocale__ctype)
250 mtext_detach_property (prop);
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);
261 xfrm->str = realloc (xfrm->str, request);
262 strxfrm (xfrm->str, (char *) newbuf, size);
266 prop = mtext_property (M_xfrm, xfrm, MTEXTPROP_VOLATILE_WEAK);
267 mtext_attach_property (mt, 0, mt->nchars, prop);
268 M17N_OBJECT_UNREF (prop);
278 M_locale = msymbol_as_managing_key (" locale");
280 Mlanguage = msymbol ("language");
281 Mterritory = msymbol ("territory");
282 Mcodeset = msymbol ("codeset");
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);
293 M_xfrm = msymbol_as_managing_key (" xfrm");
300 M17N_OBJECT_UNREF (mlocale__collate);
301 M17N_OBJECT_UNREF (mlocale__ctype);
302 M17N_OBJECT_UNREF (mlocale__messages);
303 M17N_OBJECT_UNREF (mlocale__time);
307 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
311 /*** @addtogroup m17nLocale */
315 /***en The symbol whose name is "language". */
316 /***ja "language" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë. */
320 /***en The symbol whose name is "territory". */
321 /***ja "territory" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë. */
325 /***en The symbol whose name is "modifier". */
326 /***ja "modifier" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë. */
330 /***en The symbol whose name is "codeset". */
331 /***ja "codeset" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë. */
337 @brief Set the current locale.
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>.
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.
347 If $LOCALE is NULL, the current locale of the specified part is
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 ().
355 Otherwise, it returns NULL. */
358 @brief ¸½ºß¤Î¥í¥±¡¼¥ë¤òÀßÄꤹ¤ë.
360 ´Ø¿ô mlocale_set () ¤Ï¸½ºß¤Î¥í¥±¡¼¥ë¤Î°ìÉô¤òÀßÄꤷ¤¿¤êÌ䤤¹ç¤ï¤»¤¿
361 ¤ê¤¹¤ë¡£¤³¤³¤Ç°ìÉô¤È¤Ï $CATEGORY ¤Ç»ØÄꤵ¤ì¡¢<tt>setlocale ()</tt>
362 ¤Î͸ú¤ÊÂè°ì°ú¿ô¤È¤Ê¤ë¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
364 $LOCALE ¤¬ NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢»ØÄꤷ¤¿Éôʬ¤Î¥í¥±¡¼¥ë¤¬$LOCALE ¤ËÀßÄê
365 ¤µ¤ì¤ë¡£ $LOCALE ¤¬¥·¥¹¥Æ¥à¤Ë¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¡¢ÀßÄê¤Ï¹Ô¤ï
366 ¤ì¤º¡¢¸½ºß¤Î¥í¥±¡¼¥ë¤ÏÊѤï¤é¤Ê¤¤¡£
368 $LOCALE ¤¬ NULL ¤Ê¤é¤Ð¡¢¸½ºß¤Î¥í¥±¡¼¥ë¤Î»ØÄꤷ¤¿Éôʬ¤òÌ䤤¹ç¤ï¤»¤ë¡£
372 ¸Æ¤Ó½Ð¤·¤ËÀ®¸ù¤¹¤ì¤Ð¡¢mlocale_set () ¤Ï¥í¥±¡¼¥ë¤ËÂбþ¤¹¤ë opaque
373 ¥í¥±¡¼¥ë¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡£¥í¥±¡¼¥ë¤Î̾Á°¤Ï´Ø¿ô
374 mlocale_get_prop () ¤Ë¤è¤Ã¤ÆÆÀ¤ë¤³¤È¤¬¤Ç¤¤ë¡£
376 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð NULL ¤òÊÖ¤¹¡£
384 mlocale_set (int category, const char *name)
389 new = setlocale (category, name);
393 locale = (MLocale *) msymbol_get (msymbol (new), M_locale);
395 locale = make_locale (new);
398 if (name && (category == LC_ALL || category == LC_COLLATE))
400 M17N_OBJECT_REF (locale);
401 M17N_OBJECT_UNREF (mlocale__collate);
402 mlocale__collate = locale;
404 else if (name && (category == LC_ALL || category == LC_CTYPE))
406 M17N_OBJECT_REF (locale);
407 M17N_OBJECT_UNREF (mlocale__ctype);
408 mlocale__ctype = locale;
410 if (name && (category == LC_ALL || category == LC_MESSAGES))
412 M17N_OBJECT_REF (locale);
413 M17N_OBJECT_UNREF (mlocale__messages);
414 mlocale__messages = locale;
416 if (name && (category == LC_ALL || category == LC_TIME))
418 M17N_OBJECT_REF (locale);
419 M17N_OBJECT_UNREF (mlocale__time);
420 mlocale__time = locale;
428 @brief Get the value of a locale property.
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. */
435 @brief ¥í¥±¡¼¥ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
437 ´Ø¿ô mlocale_get_prop () ¤Ï¡¢¥í¥±¡¼¥ë $LOCALE ¤Î $KEY ¥×¥í¥Ñ¥Æ¥£¤Î
438 ÃͤòÊÖ¤¹¡£ $KEY ¤Ï #Mname, #Mlanguage, #Mterritory, #Mcodeset,
439 #Mmodifier, #Mcoding ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£ */
442 mlocale_get_prop (MLocale *locale, MSymbol key)
445 return locale->coding;
448 if (key == Mlanguage)
449 return locale->language;
450 if (key == Mterritory)
451 return locale->territory;
453 return locale->codeset;
454 if (key == Mmodifier)
455 return locale->modifier;
461 @brief Format date and time.
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).
468 The meaning of the arguments $TM and $FORMAT are the same as those
475 @brief ÆüÉդȻþ´Ö¤ò¥Õ¥©¡¼¥Þ¥Ã¥È¤¹¤ë.
477 ´Ø¿ô mtext_ftime () ¤Ï»þ¹ï¥Ç¡¼¥¿ (broken-down time) $TM ¤ò$FORMAT
478 ¤Ç»ØÄꤵ¤ì¤¿·Á¼°¤ËÀ¶½ñ¤·¡¢·ë²Ì¤òM-text $MT ¤ËÉղ乤롣¥Õ¥©¡¼¥Þ¥Ã
479 ¥È¤Ï NULL ¤Ç¤Ê¤±¤ì¤Ð ¥í¥±¡¼¥ë $LOCALE ¤Ë¡¢¤Þ¤¿¤Ï¸½ºß¤Î¥í¥±¡¼¥ë
482 °ú¿ô $TM ¤È $FORMAT ¤Î°ÕÌ£¤Ï strftime () ¤Î¾ì¹ç¤ÈƱ¤¸¡£
489 mtext_ftime (MText *mt, const char *format, const struct tm *tm,
494 size_t nbytes, nchars;
495 char *current_locale = NULL;
499 char *str = setlocale (LC_TIME, NULL);
500 int len = strlen (str) + 1;
502 current_locale = alloca (len);
503 memcpy (current_locale, str, len);
504 mlocale_set (LC_TIME, msymbol_name (locale->name));
510 MTABLE_ALLOCA (buf, bufsize, MERROR_MTEXT);
512 nbytes = strftime ((char *) buf, bufsize, format, tm);
521 MText *work = decode_locale (buf, nbytes, mlocale__time);
525 nchars = work->nchars;
526 mtext_cat (mt, work);
527 M17N_OBJECT_UNREF (work);
536 mlocale_set (LC_TIME, current_locale);
544 @brief Get an environment variable.
546 The mtext_getenv () function searches the environment variable
547 list for a string that matches the string pointed to by $NAME.
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
553 If there is no match, the function returns NULL. */
555 @brief ´Ä¶ÊÑ¿ô¤òÆÀ¤ë.
557 ´Ø¿ô mtext_getenv () ¤Ï $NAME ¤Ç»Ø¤µ¤ì¤ëʸ»úÎó¤È¹çÃפ¹¤ëʸ»úÎó¤ò
558 ´Ä¶ÊÑ¿ô¤Î¥ê¥¹¥ÈÃ椫¤éõ¤¹¡£
560 ¸«¤Ä¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¤½¤ÎÃͤò¸½ºß¤Î¥í¥±¡¼¥ë(LC_CTYPE) ¤Ë½¾¤Ã¤Æ
561 M-text ¤Ë¥Ç¥³¡¼¥É¤·¡¢¤½¤ÎM-text ¤òÊÖ¤¹¡£
563 ¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢NULL ¤òÊÖ¤¹¡£ */
566 mtext_getenv (const char *name)
568 char *p = getenv (name);
572 return decode_locale ((unsigned char *) p, strlen (p), mlocale__ctype);
578 @brief Change or add an environment variable.
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).
586 This function returns zero on success, or -1 if an error
589 @brief ´Ä¶ÊÑ¿ô¤òÊѹ¹¡¿Äɲ乤ë.
591 ´Ø¿ô mtext_putenv () ¤Ï M-text $MT ¤Ë½¾¤Ã¤Æ¡¢´Ä¶ÊÑ¿ô¤ÎÃͤòÊѹ¹¤·
592 ¤¿¤êÄɲä·¤¿¤ê¤¹¤ë¡£¤³¤Î´Ø¿ô¤Ï¡¢¸½ºß¤Î¥í¥±¡¼¥ë(LC_CTYPE) ¤Ë½¾¤Ã¤Æ
593 $MT ¤ò¥¨¥ó¥³¡¼¥É¤·¡¢¤½¤ì¤ò°ú¿ô¤È¤·¤Æ´Ø¿ô <tt>putenv</tt> ¤ò¸Æ¤Ö¡£
596 ¤³¤Î´Ø¿ô¤Ï¡¢À®¸ù¤·¤¿¾ì¹ç¤Ë¤Ï 0 ¤ò¡¢¥¨¥é¡¼¤¬µ¯¤³¤ì¤Ð -1 ¤òÊÖ¤¹¡£
601 mtext_putenv (MText *mt)
603 unsigned char buf[1024];
605 unsigned char *newbuf;
608 newbuf = encode_locale (mt, buf, &size, mlocale__ctype);
609 result = putenv ((char *) newbuf);
618 @brief Compare two M-texts using the current locale.
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).
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
631 @brief ¸½ºß¤Î¥í¥±¡¼¥ë¤òÍѤ¤¤Æ£²¤Ä¤Î M-text ¤òÈæ³Ó¤¹¤ë.
633 ´Ø¿ô mtext_coll () ¤Ï£²¤Ä¤Î M-text $MT1 ¤È $MT2 ¤òÈæ³Ó¤¹¤ë¡£Ìá¤êÃÍ
634 ¤ÏÉé¤ÎÀ°¿ôÃÍ, 0, Àµ¤ÎÀ°¿ôÃͤΤ¤¤º¤ì¤«¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì$MT1 ¤¬ $MT2
635 ¤è¤ê¾®¤µ¤¤¡¢Æ±¤¸¡¢Â礤¤¾ì¹ç¤ËÁêÅö¤¹¤ë¡£Èæ³Ó¤Ï¸½ºß¤Î¥í¥±¡¼¥ë
636 (LC_COLLATE) ¤Ë´ð¤Å¤¤¤Æ¹Ô¤ï¤ì¤ë¡£
638 ¤³¤Î´Ø¿ô¤Ï M-text ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤È¤·¤Æ¼«Æ°Åª¤Ë¥¥ã¥Ã¥·¥å¤µ¤ì
639 ¤ë¾ðÊó¤òÍøÍѤ¹¤ë¤Î¤Ç¡¢£²ÅÙÌܰʹߤÎƱ¤¸Èæ³Ó¤Ï£±ÅÙÌܤè¤ê®¤¯¼Â¹Ô¤µ¤ì
643 mtext_coll (MText *mt1, MText *mt2)
647 if (mt1->nchars == 0)
648 return (mt2->nchars == 0 ? 0 : -1);
649 else if (mt2->nchars == 0)
652 str1 = get_xfrm (mt1);
653 str2 = get_xfrm (mt2);
654 return strcoll (str1, str2);