1 /* locale.c -- locale module.
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
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., 51 Franklin Street, Fifth Floor,
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. */
92 make_locale (const char *name)
99 M17N_OBJECT (locale, NULL, MERROR_LOCALE);
100 locale->name = msymbol (name);
101 msymbol_put (locale->name, M_locale, (void *) locale);
102 M17N_OBJECT_UNREF (locale);
104 len = strlen (name) + 1;
106 memcpy (str, name, len);
114 for (i = 0; str[i]; i++)
115 if (str[i] == '_' || str[i] == '.' || str[i] == '@')
120 /* The first field is for language. */
121 locale->language = msymbol (str);
123 /* The field following '_' is for territory. */
124 locale->territory = msymbol (str);
126 /* The field following '.' is for codeset. */
127 locale->codeset = msymbol (str);
129 /* The other field is for modifier. */
130 locale->modifier = msymbol (str);
137 #ifdef HAVE_NL_LANGINFO
139 /* If we can use nl_langinfo () to retrieve a codeset name, respect
140 it over the codeset name extracted from the locale name. */
141 locale->codeset = msymbol (nl_langinfo (CODESET));
145 /* If the locale name specifies a codeset, get the corresponding
147 if (locale->codeset != Mnil)
149 locale->coding = mconv_resolve_coding (locale->codeset);
150 if (locale->coding == Mnil)
151 locale->coding = Mcoding_us_ascii;
154 locale->coding = Mcoding_us_ascii;
159 /** Decode the byte sequence at BUF of length SIZE bytes by the coding
160 system associated with LOCALE, and return a generated M-text. */
163 decode_locale (unsigned char *buf, int size, MLocale *locale)
165 return mconv_decode_buffer (locale->coding, buf, size);
169 /** Encode the M-text MT by the coding system associated with LOCALE,
170 and store the resulting bytes in the memory area at BUF of *SIZE
171 bytes. If the area is too short, allocate a new and wider area.
172 Store the length of the generated bytes in the place pointed by
173 SIZE, and return the address of those bytes. */
175 static unsigned char *
176 encode_locale (MText *mt, unsigned char *buf, int *size, MLocale *locale)
178 int nbytes = mconv_encode_buffer (locale->coding, mt, buf, *size - 1);
185 MTABLE_REALLOC (buf, *size, MERROR_LOCALE);
186 nbytes = mconv_encode_buffer (mlocale__ctype->coding, mt, buf,
188 } while (nbytes < 0);
196 /** Structure of transformed strings. The function mtext_coll ()
197 caches this object in an M-text as a text property. */
200 /* Common header for a managed object. */
203 /* Locale corresponding to <str>. */
206 /** Result of strxfrm. */
212 free_xfrm (void *object)
214 MXfrm *xfrm = (MXfrm *) object;
216 M17N_OBJECT_UNREF (xfrm->locale);
223 MTextProperty *prop = mtext_get_property (mt, 0, M_xfrm);
226 unsigned char *buf, *newbuf;
231 if (prop->end == mt->nchars)
233 xfrm = (MXfrm *) prop->val;
234 if (xfrm->locale == mlocale__ctype)
237 mtext_detach_property (prop);
242 newbuf = encode_locale (mt, buf, &size, mlocale__ctype);
243 M17N_OBJECT (xfrm, free_xfrm, MERROR_MTEXT);
244 xfrm->str = malloc (size);
245 request = strxfrm (xfrm->str, (char *) newbuf, size);
248 xfrm->str = realloc (xfrm->str, request);
249 strxfrm (xfrm->str, (char *) newbuf, size);
253 prop = mtext_property (M_xfrm, xfrm, MTEXTPROP_VOLATILE_WEAK);
254 mtext_attach_property (mt, 0, mt->nchars, prop);
255 M17N_OBJECT_UNREF (prop);
265 M_locale = msymbol_as_managing_key (" locale");
267 Mterritory = msymbol ("territory");
268 Mcodeset = msymbol ("codeset");
270 mlocale__collate = mlocale_set (LC_COLLATE, NULL);
271 M17N_OBJECT_REF (mlocale__collate);
272 mlocale__ctype = mlocale_set (LC_CTYPE, NULL);
273 M17N_OBJECT_REF (mlocale__ctype);
274 mlocale__messages = mlocale_set (LC_MESSAGES, NULL);
275 M17N_OBJECT_REF (mlocale__messages);
276 mlocale__time = mlocale_set (LC_TIME, NULL);
277 M17N_OBJECT_REF (mlocale__time);
279 M_xfrm = msymbol_as_managing_key (" xfrm");
286 M17N_OBJECT_UNREF (mlocale__collate);
287 M17N_OBJECT_UNREF (mlocale__ctype);
288 M17N_OBJECT_UNREF (mlocale__messages);
289 M17N_OBJECT_UNREF (mlocale__time);
293 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
297 /*** @addtogroup m17nLocale */
301 /***en The symbol whose name is "territory". */
302 /***ja "territory" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë. */
306 /***en The symbol whose name is "modifier". */
307 /***ja "modifier" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë. */
311 /***en The symbol whose name is "codeset". */
312 /***ja "codeset" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë. */
318 @brief Set the current locale.
320 The mlocale_set () function sets or query a part of the current
321 locale. The part is specified by $CATEGORY which must be a valid
322 first argument to <tt>setlocale ()</tt>.
324 If $LOCALE is not NULL, the locale of the specified part is set to
325 $LOCALE. If $LOCALE is not supported by the system, the current
326 locale is not changed.
328 If $LOCALE is NULL, the current locale of the specified part is
332 If the call is successful, mlocale_set () returns an opaque locale
333 object that corresponds to the locale. The name of the locale can
334 be acquired by the function mlocale_get_prop ().
335 Otherwise, it returns NULL. */
338 @brief ¸½ºß¤Î¥í¥±¡¼¥ë¤òÀßÄꤹ¤ë.
340 ´Ø¿ô mlocale_set () ¤Ï¸½ºß¤Î¥í¥±¡¼¥ë¤Î°ìÉô¤òÀßÄꤷ¤¿¤êÌ䤤¹ç¤ï¤»¤¿¤ê¤¹¤ë¡£¤³¤³¤Ç°ìÉô¤È¤Ï
341 $CATEGORY ¤Ç»ØÄꤵ¤ì¡¢<tt>setlocale ()</tt> ¤Î͸ú¤ÊÂè°ì°ú¿ô¤È¤Ê¤ë¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
343 $LOCALE ¤¬ NULL ¤Ç¤Ê¤±¤ì¤Ð¡¢»ØÄꤷ¤¿Éôʬ¤Î¥í¥±¡¼¥ë¤¬$LOCALE ¤ËÀßÄꤵ¤ì¤ë¡£
344 $LOCALE ¤¬¥·¥¹¥Æ¥à¤Ë¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¡¢ÀßÄê¤Ï¹Ô¤ï¤ì¤º¡¢¸½ºß¤Î¥í¥±¡¼¥ë¤ÏÊѤï¤é¤Ê¤¤¡£
346 $LOCALE ¤¬ NULL ¤Ê¤é¤Ð¡¢¸½ºß¤Î¥í¥±¡¼¥ë¤Î»ØÄꤷ¤¿Éôʬ¤òÌ䤤¹ç¤ï¤»¤ë¡£
350 ¸Æ¤Ó½Ð¤·¤ËÀ®¸ù¤¹¤ì¤Ð¡¢mlocale_set () ¤Ï¥í¥±¡¼¥ë¤ËÂбþ¤¹¤ë opaque
351 ¥í¥±¡¼¥ë¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡£¥í¥±¡¼¥ë¤Î̾Á°¤Ï´Ø¿ô
352 mlocale_get_prop () ¤Ë¤è¤Ã¤ÆÆÀ¤ë¤³¤È¤¬¤Ç¤¤ë¡£
353 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð NULL ¤òÊÖ¤¹¡£
361 mlocale_set (int category, const char *name)
366 new = setlocale (category, name);
370 locale = (MLocale *) msymbol_get (msymbol (new), M_locale);
372 locale = make_locale (new);
375 if (name && (category == LC_ALL || category == LC_COLLATE))
377 M17N_OBJECT_REF (locale);
378 M17N_OBJECT_UNREF (mlocale__collate);
379 mlocale__collate = locale;
381 else if (name && (category == LC_ALL || category == LC_CTYPE))
383 M17N_OBJECT_REF (locale);
384 M17N_OBJECT_UNREF (mlocale__ctype);
385 mlocale__ctype = locale;
387 if (name && (category == LC_ALL || category == LC_MESSAGES))
389 M17N_OBJECT_REF (locale);
390 M17N_OBJECT_UNREF (mlocale__messages);
391 mlocale__messages = locale;
393 if (name && (category == LC_ALL || category == LC_TIME))
395 M17N_OBJECT_REF (locale);
396 M17N_OBJECT_UNREF (mlocale__time);
397 mlocale__time = locale;
405 @brief Get the value of a locale property.
407 The mlocale_get_prop () function returns the value of a property
408 $KEY of local $LOCALE. $KEY must be #Mname, #Mlanguage,
409 #Mterritory, #Mcodeset, #Mmodifier, or #Mcoding. */
412 @brief ¥í¥±¡¼¥ë¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÆÀ¤ë.
414 ´Ø¿ô mlocale_get_prop () ¤Ï¡¢¥í¥±¡¼¥ë $LOCALE ¤Î $KEY ¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹¡£
415 $KEY ¤Ï #Mname, #Mlanguage, #Mterritory, #Mcodeset, #Mmodifier,
416 #Mcoding ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£ */
419 mlocale_get_prop (MLocale *locale, MSymbol key)
422 return locale->coding;
425 if (key == Mlanguage)
426 return locale->language;
427 if (key == Mterritory)
428 return locale->territory;
430 return locale->codeset;
431 if (key == Mmodifier)
432 return locale->modifier;
438 @brief Format date and time.
440 The mtext_ftime () function formats the broken-down time $TM
441 according to the format specification $FORMAT and append the
442 result to the M-text $MT. The formating is done according to the
443 locale $LOCALE (if not NULL) or the current locale (LC_TIME).
445 The meaning of the arguments $TM and $FORMAT are the same as those
452 @brief ÆüÉդȻþ´Ö¤ò¥Õ¥©¡¼¥Þ¥Ã¥È¤¹¤ë.
454 ´Ø¿ô mtext_ftime () ¤Ï»þ¹ï¥Ç¡¼¥¿ (broken-down time) $TM ¤ò$FORMAT
455 ¤Ç»ØÄꤵ¤ì¤¿·Á¼°¤ËÀ¶½ñ¤·¡¢·ë²Ì¤òM-text $MT ¤ËÉղ乤롣¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï
456 NULL ¤Ç¤Ê¤±¤ì¤Ð ¥í¥±¡¼¥ë $LOCALE ¤Ë¡¢¤Þ¤¿¤Ï¸½ºß¤Î¥í¥±¡¼¥ë(LC_TIME) ¤Ë½¾¤¦¡£
458 °ú¿ô $TM ¤È $FORMAT ¤Î°ÕÌ£¤Ï strftime () ¤Î¾ì¹ç¤ÈƱ¤¸¡£
465 mtext_ftime (MText *mt, const char *format, const struct tm *tm,
470 size_t nbytes, nchars;
471 char *current_locale = NULL;
475 char *str = setlocale (LC_TIME, NULL);
476 int len = strlen (str) + 1;
478 current_locale = alloca (len);
479 memcpy (current_locale, str, len);
480 mlocale_set (LC_TIME, msymbol_name (locale->name));
486 MTABLE_ALLOCA (buf, bufsize, MERROR_MTEXT);
488 nbytes = strftime ((char *) buf, bufsize, format, tm);
497 MText *work = decode_locale (buf, nbytes, mlocale__time);
501 nchars = work->nchars;
502 mtext_cat (mt, work);
503 M17N_OBJECT_UNREF (work);
512 mlocale_set (LC_TIME, current_locale);
520 @brief Get an environment variable.
522 The mtext_getenv () function searches the environment variable
523 list for a string that matches the string pointed to by $NAME.
525 If there is a match, the function decodes the value according to
526 the current locale (LC_CTYPE) into an M-text, and return that
529 If there is no match, the function returns NULL. */
531 @brief ´Ä¶ÊÑ¿ô¤òÆÀ¤ë.
533 ´Ø¿ô mtext_getenv () ¤Ï $NAME
534 ¤Ç»Ø¤µ¤ì¤ëʸ»úÎó¤È¹çÃפ¹¤ëʸ»úÎó¤ò´Ä¶ÊÑ¿ô¤Î¥ê¥¹¥ÈÃ椫¤éõ¤¹¡£
536 ¸«¤Ä¤«¤Ã¤¿¾ì¹ç¤Ë¤Ï¡¢¤½¤ÎÃͤò¸½ºß¤Î¥í¥±¡¼¥ë(LC_CTYPE) ¤Ë½¾¤Ã¤Æ
537 M-text ¤Ë¥Ç¥³¡¼¥É¤·¡¢¤½¤ÎM-text ¤òÊÖ¤¹¡£
539 ¸«¤Ä¤«¤é¤Ê¤±¤ì¤Ð¡¢NULL ¤òÊÖ¤¹¡£ */
542 mtext_getenv (const char *name)
544 char *p = getenv (name);
548 return decode_locale ((unsigned char *) p, strlen (p), mlocale__ctype);
554 @brief Change or add an environment variable.
556 The mtext_putenv () function changes or adds the value of
557 environment variables according to M-text $MT. It calls the
558 function <tt>putenv</tt> with an argument generated by encoding
559 $MT according to the current locale (LC_CTYPE).
562 This function returns zero on success, or -1 if an error
565 @brief ´Ä¶ÊÑ¿ô¤òÊѹ¹¡¿Äɲ乤ë.
567 ´Ø¿ô mtext_putenv () ¤Ï M-text $MT
568 ¤Ë½¾¤Ã¤Æ¡¢´Ä¶ÊÑ¿ô¤ÎÃͤòÊѹ¹¤·¤¿¤êÄɲä·¤¿¤ê¤¹¤ë¡£¤³¤Î´Ø¿ô¤Ï¡¢¸½ºß¤Î¥í¥±¡¼¥ë
569 (LC_CTYPE) ¤Ë½¾¤Ã¤Æ$MT ¤ò¥¨¥ó¥³¡¼¥É¤·¡¢¤½¤ì¤ò°ú¿ô¤È¤·¤Æ´Ø¿ô <tt>putenv</tt> ¤ò¸Æ¤Ö¡£
572 ¤³¤Î´Ø¿ô¤Ï¡¢À®¸ù¤·¤¿¾ì¹ç¤Ë¤Ï 0 ¤ò¡¢¥¨¥é¡¼¤¬µ¯¤³¤ì¤Ð -1 ¤òÊÖ¤¹¡£
577 mtext_putenv (MText *mt)
579 unsigned char buf[1024];
581 unsigned char *newbuf;
584 newbuf = encode_locale (mt, buf, &size, mlocale__ctype);
585 result = putenv ((char *) newbuf);
594 @brief Compare two M-texts using the current locale.
596 The mtext_coll () function compares the two M-texts $MT1 and $MT2.
597 It returns an integer less than, equal to, or greater than zero if
598 $MT1 is found, respectively, to be less than, to match, or to be
599 greater than $MT2. The comparison is based on texts as
600 appropriate for the current locale (LC_COLLATE).
602 This function makes use of information that is automatically
603 cached in the M-texts as a text property. So, the second call of
604 this function with $MT1 or $MT2 finishes faster than the first
607 @brief ¸½ºß¤Î¥í¥±¡¼¥ë¤òÍѤ¤¤Æ£²¤Ä¤Î M-text ¤òÈæ³Ó¤¹¤ë.
609 ´Ø¿ô mtext_coll () ¤Ï£²¤Ä¤Î M-text $MT1 ¤È $MT2
610 ¤òÈæ³Ó¤¹¤ë¡£Ìá¤êÃͤÏÉé¤ÎÀ°¿ôÃÍ, 0, Àµ¤ÎÀ°¿ôÃͤΤ¤¤º¤ì¤«¤Ç¤¢¤ê¡¢¤½¤ì¤¾¤ì
611 $MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤¤¡¢Æ±¤¸¡¢Â礤¤¾ì¹ç¤ËÁêÅö¤¹¤ë¡£Èæ³Ó¤Ï¸½ºß¤Î¥í¥±¡¼¥ë
612 (LC_COLLATE) ¤Ë´ð¤Å¤¤¤Æ¹Ô¤ï¤ì¤ë¡£
615 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤È¤·¤Æ¼«Æ°Åª¤Ë¥¥ã¥Ã¥·¥å¤µ¤ì¤ë¾ðÊó¤òÍøÍѤ¹¤ë¤Î¤Ç¡¢£²ÅÙÌܰʹߤÎƱ¤¸Èæ³Ó¤Ï£±ÅÙÌܤè¤ê®¤¯¼Â¹Ô¤µ¤ì¤ë¡£ */
618 mtext_coll (MText *mt1, MText *mt2)
622 if (mt1->nchars == 0)
623 return (mt2->nchars == 0 ? 0 : -1);
624 else if (mt2->nchars == 0)
627 str1 = get_xfrm (mt1);
628 str2 = get_xfrm (mt2);
629 return strcoll (str1, str2);