1 /* ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable. */
4 * Smart Common Input Method
6 * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
7 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this program; if not, write to the
22 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23 * Boston, MA 02111-1307 USA
25 * Modifications by Samsung Electronics Co., Ltd.
26 * 1. Add time and logs functions for performance profile
28 * $Id: scim_utility.cpp,v 1.48.2.5 2006/11/02 04:11:51 suzhe Exp $
31 #define Uses_SCIM_UTILITY
32 #define Uses_SCIM_CONFIG_PATH
42 #include <sys/types.h>
50 #include <sys/times.h>
52 #include "scim_private.h"
58 utf8_mbtowc (ucs4_t *pwc, const unsigned char *src, int src_len)
63 unsigned char c = src [0];
68 } else if (c < 0xc2) {
70 } else if (c < 0xe0) {
73 if (!((src [1] ^ 0x80) < 0x40))
75 *pwc = ((ucs4_t) (c & 0x1f) << 6)
76 | (ucs4_t) (src [1] ^ 0x80);
78 } else if (c < 0xf0) {
81 if (!((src [1] ^ 0x80) < 0x40 && (src [2] ^ 0x80) < 0x40
82 && (c >= 0xe1 || src [1] >= 0xa0)))
84 *pwc = ((ucs4_t) (c & 0x0f) << 12)
85 | ((ucs4_t) (src [1] ^ 0x80) << 6)
86 | (ucs4_t) (src [2] ^ 0x80);
88 } else if (c < 0xf8) {
91 if (!((src [1] ^ 0x80) < 0x40 && (src [2] ^ 0x80) < 0x40
92 && (src [3] ^ 0x80) < 0x40
93 && (c >= 0xf1 || src [1] >= 0x90)))
95 *pwc = ((ucs4_t) (c & 0x07) << 18)
96 | ((ucs4_t) (src [1] ^ 0x80) << 12)
97 | ((ucs4_t) (src [2] ^ 0x80) << 6)
98 | (ucs4_t) (src [3] ^ 0x80);
100 } else if (c < 0xfc) {
102 return RET_TOOFEW(0);
103 if (!((src [1] ^ 0x80) < 0x40 && (src [2] ^ 0x80) < 0x40
104 && (src [3] ^ 0x80) < 0x40 && (src [4] ^ 0x80) < 0x40
105 && (c >= 0xf9 || src [1] >= 0x88)))
107 *pwc = ((ucs4_t) (c & 0x03) << 24)
108 | ((ucs4_t) (src [1] ^ 0x80) << 18)
109 | ((ucs4_t) (src [2] ^ 0x80) << 12)
110 | ((ucs4_t) (src [3] ^ 0x80) << 6)
111 | (ucs4_t) (src [4] ^ 0x80);
113 } else if (c < 0xfe) {
115 return RET_TOOFEW(0);
116 if (!((src [1] ^ 0x80) < 0x40 && (src [2] ^ 0x80) < 0x40
117 && (src [3] ^ 0x80) < 0x40 && (src [4] ^ 0x80) < 0x40
118 && (src [5] ^ 0x80) < 0x40
119 && (c >= 0xfd || src [1] >= 0x84)))
121 *pwc = ((ucs4_t) (c & 0x01) << 30)
122 | ((ucs4_t) (src [1] ^ 0x80) << 24)
123 | ((ucs4_t) (src [2] ^ 0x80) << 18)
124 | ((ucs4_t) (src [3] ^ 0x80) << 12)
125 | ((ucs4_t) (src [4] ^ 0x80) << 6)
126 | (ucs4_t) (src [5] ^ 0x80);
133 utf8_wctomb (unsigned char *dest, ucs4_t wc, int dest_size)
143 else if (wc < 0x10000)
145 else if (wc < 0x200000)
147 else if (wc < 0x4000000)
149 else if (wc <= 0x7fffffff)
153 if (dest_size < count)
155 switch (count) { /* note: code falls through cases! */
156 case 6: dest [5] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x4000000;
157 case 5: dest [4] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x200000;
158 case 4: dest [3] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x10000;
159 case 3: dest [2] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x800;
160 case 2: dest [1] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0xc0;
161 case 1: dest [0] = wc;
167 utf8_read_wchar (std::istream &is)
169 unsigned char utf8[6];
173 memset (utf8, 0, sizeof(unsigned char) * 6);
174 for (int i=0; i<6; ++i) {
175 is.read ((char*)(utf8+i), sizeof(unsigned char));
176 if ((count=utf8_mbtowc (&wc, utf8, i+1)) > 0)
178 if (count == RET_ILSEQ)
185 utf8_read_wstring (std::istream &is, ucs4_t delim, bool rm_delim)
189 while ((wc = utf8_read_wchar (is)) > 0) {
202 utf8_write_wchar (std::ostream &os, ucs4_t wc)
204 unsigned char utf8[6];
207 if ((count=utf8_wctomb (utf8, wc, 6)) > 0)
208 os.write ((char*)utf8, count * sizeof (unsigned char));
214 utf8_write_wstring (std::ostream &os, const WideString & wstr)
216 for (unsigned int i=0; i<wstr.size (); ++i)
217 utf8_write_wchar (os, wstr [i]);
223 utf8_mbstowcs (const String & str)
230 const unsigned char *s = (const unsigned char *) str.c_str ();
232 while (sn < str.length () && *s != 0 &&
233 (un=utf8_mbtowc (&wc, s, str.length () - sn)) > 0) {
242 utf8_mbstowcs (const char *str, int len)
251 if (len < 0) len = strlen (str);
253 while (sn < ((unsigned int)len) && *str != 0 && (un=utf8_mbtowc (&wc, (const unsigned char *)str, len - sn)) > 0) {
264 utf8_wcstombs (const WideString & wstr)
270 for (unsigned int i = 0; i<wstr.size (); ++i) {
271 un = utf8_wctomb ((unsigned char*)utf8, wstr [i], 6);
273 str.append (utf8, un);
279 utf8_wcstombs (const ucs4_t *wstr, int len)
292 for (int i = 0; i < len; ++i) {
293 un = utf8_wctomb ((unsigned char*)utf8, wstr [i], 6);
295 str.append (utf8, un);
302 scim_validate_locale (const String& locale)
306 String last = String (setlocale (LC_CTYPE, 0));
308 if (setlocale (LC_CTYPE, locale.c_str ())) {
311 std::vector<String> vec;
312 if (scim_split_string_list (vec, locale, '.') == 2) {
313 if (isupper (vec[1][0])) {
314 for (String::iterator i=vec[1].begin (); i!=vec[1].end (); ++i)
315 *i = (char) tolower (*i);
317 for (String::iterator i=vec[1].begin (); i!=vec[1].end (); ++i)
318 *i = (char) toupper (*i);
320 if (setlocale (LC_CTYPE, (vec[0] + "." + vec[1]).c_str ())) {
321 good = vec [0] + "." + vec[1];
326 setlocale (LC_CTYPE, last.c_str ());
332 scim_get_locale_encoding (const String& locale)
334 String last = String (setlocale (LC_CTYPE, 0));
337 if (setlocale (LC_CTYPE, locale.c_str ()))
338 encoding = String (nl_langinfo (CODESET));
340 std::vector<String> vec;
341 if (scim_split_string_list (vec, locale, '.') == 2) {
342 if (isupper (vec[1][0])) {
343 for (String::iterator i=vec[1].begin (); i!=vec[1].end (); ++i)
344 *i = (char) tolower (*i);
346 for (String::iterator i=vec[1].begin (); i!=vec[1].end (); ++i)
347 *i = (char) toupper (*i);
349 if (setlocale (LC_CTYPE, (vec[0] + "." + vec[1]).c_str ()))
350 encoding = String (nl_langinfo (CODESET));
355 setlocale (LC_CTYPE, last.c_str ());
361 scim_get_locale_maxlen (const String& locale)
365 String last = String (setlocale (LC_CTYPE, 0));
367 if (setlocale (LC_CTYPE, locale.c_str ()))
372 setlocale (LC_CTYPE, last.c_str ());
377 scim_split_string_list (std::vector<String>& vec, const String& str, char delim)
382 String::const_iterator bg, ed;
389 while (bg != str.end () && ed != str.end ()) {
390 for (; ed != str.end (); ++ed) {
394 temp.assign (bg, ed);
395 vec.push_back (temp);
398 if (ed != str.end ())
405 scim_combine_string_list (const std::vector<String>& vec, char delim)
408 for (std::vector<String>::const_iterator i = vec.begin (); i!=vec.end (); ++i) {
410 if (i+1 != vec.end ())
417 scim_if_wchar_ucs4_equal ()
419 if (sizeof (wchar_t) != sizeof (ucs4_t))
423 wchar_t wcbuf [2] = {0,0};
424 ucs4_t ucsbuf [2] = {0x4E00, 0x0001};
425 size_t wclen = 2 * sizeof (wchar_t);
426 size_t ucslen = 2 * sizeof (ucs4_t);
428 char *wcp = (char *) wcbuf;
429 ICONV_CONST char *ucsp = (ICONV_CONST char *) ucsbuf;
431 if (scim_is_little_endian ())
432 cd = iconv_open ("UCS-4LE", "wchar_t");
434 cd = iconv_open ("UCS-4BE", "wchar_t");
436 if (cd == (iconv_t) -1)
439 iconv (cd, &ucsp, &ucslen, &wcp, &wclen);
443 if (wcbuf [0] == (wchar_t) ucsbuf [0] &&
444 wcbuf [1] == (wchar_t) ucsbuf [1])
454 } __half_full_table [] = {
456 {0x0021, 0xFF01, 0x5E},
509 {0xFFA1, 0x3131, 30},
521 * convert a half width unicode char to full width char
524 scim_wchar_to_full_width (ucs4_t code)
527 while (__half_full_table [i].size) {
528 if (code >= __half_full_table [i].half &&
529 code < __half_full_table [i].half +
530 __half_full_table [i].size)
531 return __half_full_table [i].full +
532 (code - __half_full_table [i].half);
539 * convert a full width unicode char to half width char
542 scim_wchar_to_half_width (ucs4_t code)
545 while (__half_full_table [i].size) {
546 if (code >= __half_full_table [i].full &&
547 code < __half_full_table [i].full +
548 __half_full_table [i].size)
549 return __half_full_table [i].half +
550 (code - __half_full_table [i].full);
559 const char * home_dir = 0;
564 pw = getpwuid (getuid ());
568 home_dir = pw->pw_dir;
572 home_dir = getenv ("HOME");
575 return String (home_dir);
579 scim_get_user_name ()
582 const char *user_name;
585 pw = getpwuid (getuid ());
588 if (pw && pw->pw_name)
589 return String (pw->pw_name);
590 else if ((user_name = getenv ("USER")) != NULL)
591 return String (user_name);
595 snprintf (uid_str, 10, "%u", getuid ());
597 return String (uid_str);
601 scim_get_user_data_dir ()
603 String dir = scim_get_home_dir () + String ("/.scim");
609 scim_get_current_locale ()
611 char *locale = setlocale (LC_CTYPE, 0);
613 if (locale) return String (locale);
617 String scim_get_current_language ()
619 return scim_get_locale_language (scim_get_current_locale ());
623 scim_is_little_endian ()
626 return (*((char *)&endian) != 0);
630 scim_load_file (const String &filename, char **bufptr)
632 if (!filename.length ())
637 if (stat (filename.c_str (), &statbuf) < 0 ||
638 !S_ISREG (statbuf.st_mode) ||
643 return statbuf.st_size;
645 FILE *fp = fopen (filename.c_str (), "r");
653 *bufptr = new char [statbuf.st_size];
664 size_t size = fread (*bufptr, 1, statbuf.st_size, fp);
677 scim_make_dir (const String &dir)
679 std::vector <String> paths;
682 scim_split_string_list (paths, dir, SCIM_PATH_DELIM);
684 for (size_t i = 0; i < paths.size (); ++i) {
685 path += SCIM_PATH_DELIM_STRING + paths [i];
687 //Make the dir if it's not exist.
688 if (access (path.c_str (), R_OK) != 0) {
689 mkdir (path.c_str (), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
690 if (access (path.c_str (), R_OK) != 0)
699 const char *normalized;
701 const char *untranslated;
702 const char *locale_suffix;
705 static __Language __languages [] = {
706 { "C", NULL, N_("English/Keyboard"), NULL, NULL},
707 { "am_ET", NULL, N_("Amharic"), NULL, NULL },
708 { "ar", "ar", N_("Arabic"), NULL, NULL },
709 { "ar_EG", NULL, N_("Arabic (Egypt)"), NULL, NULL },
710 { "ar_LB", NULL, N_("Arabic (Lebanon)"), NULL, NULL },
711 { "as_IN", NULL, N_("Assamese"), NULL, NULL},
712 { "az_AZ", NULL, N_("Azerbaijani"), NULL, NULL },
713 { "be_BY", NULL, N_("Belarusian"), "Беларуская мова", NULL },
714 { "bg_BG", NULL, N_("Bulgarian"), "Български", NULL },
715 { "bn", "bn_BD", N_("Bengali"), "বাংলা", NULL },
716 { "bn_BD", NULL, N_("Bengali"), "বাংলা", NULL },
717 { "bn_IN", NULL, N_("Bengali (India)"), "বাংলা", NULL },
718 { "bo", NULL, N_("Tibetan"), NULL, NULL },
719 { "bs_BA", NULL, N_("Bosnian"), NULL, NULL },
720 { "ca_ES", NULL, N_("Catalan"), "Català", "@euro" },
721 { "cs_CZ", NULL, N_("Czech"), "čeština", NULL },
722 { "cy_GB", NULL, N_("Welsh"), "Cymraeg", NULL },
723 { "da_DK", NULL, N_("Danish"), "Dansk", "@euro" },
724 { "de_DE", NULL, N_("German"), "Deutsch", "@euro" },
725 { "dv_MV", NULL, N_("Divehi"), "ދިވެހިބަސް", NULL },
726 { "el_GR", NULL, N_("Greek"), "ελληνικά", NULL },
727 { "en" , NULL, N_("English"), "English", NULL },
728 { "en_AU", NULL, N_("English (Australian)"), "Australian English", NULL },
729 { "en_CA", NULL, N_("English (Canadian)"), "Canadian English", NULL },
730 { "en_GB", NULL, N_("English (British)"), "British English", ".iso885915" },
731 { "en_IE", NULL, N_("English (Ireland)"), "Irish English", NULL },
732 { "en_US", NULL, N_("English (American)"), "American English", ".iso885915" },
733 { "es", "es_ES", N_("Spanish"), "Español", NULL },
734 { "es_ES", NULL, N_("Spanish"), "Español", "@euro" },
735 { "es_MX", NULL, N_("Spanish (Mexico)"), "Español (Mexico)", NULL },
736 { "et_EE", NULL, N_("Estonian"), "Eesti", ".iso885915" },
737 { "eu_ES", NULL, N_("Basque"), "Euskara", "@euro" },
738 { "fa_IR", NULL, N_("Persian"), "فارسی", NULL },
739 { "fi_FI", NULL, N_("Finnish"), "Suomi", "@euro" },
740 { "fr_FR", NULL, N_("French"), "Français", "@euro" },
741 { "ga_IE", NULL, N_("Irish"), "Gaeilge", "@euro" },
742 { "gl_ES", NULL, N_("Galician"), "Galego", "@euro" },
743 { "gu_IN", NULL, N_("Gujarati"), NULL, NULL },
744 { "he_IL", NULL, N_("Hebrew"), "עברית", NULL },
745 { "hi_IN", NULL, N_("Hindi"), "हिंदी", NULL },
746 { "hr_HR", NULL, N_("Croatian"), "Hrvatski", NULL },
747 { "hu_HU", NULL, N_("Hungarian"), "Magyar", NULL },
748 { "hy_AM", NULL, N_("Armenian"), "Հայերէն", NULL },
749 { "ia" , NULL, N_("Interlingua"), NULL },
750 { "id_ID", NULL, N_("Indonesian"), "Bahasa Indonesia", NULL },
751 { "is_IS", NULL, N_("Icelandic"), NULL, NULL },
752 { "it_IT", NULL, N_("Italian"), "Italiano", "@euro" },
753 { "iw_IL", NULL, N_("Hebrew"), "עברית", NULL },
754 { "ja_JP", NULL, N_("Japanese"), "日本語", ".EUC-JP,.SJIS,.eucJP" },
755 { "ka_GE", NULL, N_("Georgian"), "ქართული", NULL },
756 { "kk_KZ", NULL, N_("Kazakh"), NULL, NULL },
757 { "km", NULL, N_("Cambodian"), NULL, NULL },
758 { "kn_IN", NULL, N_("Kannada"), "ಕನ್ನಡ", NULL },
759 { "ko_KR", NULL, N_("Korean"), "한국어", ".EUC-KR,.eucKR" },
760 { "lo_LA", NULL, N_("Laothian"), NULL, NULL },
761 { "lt_LT", NULL, N_("Lithuanian"), "Lietuvių", NULL },
762 { "lv_LV", NULL, N_("Latvian"), "Latviešu", NULL },
763 { "mk_MK", NULL, N_("Macedonian"), NULL, NULL },
764 { "ml_IN", NULL, N_("Malayalam"), "മലയാളം", NULL },
765 { "mn_MN", NULL, N_("Mongolian"), "Монгол", NULL },
766 { "mr_IN", NULL, N_("Marathi"), NULL, NULL },
767 { "ms_MY", NULL, N_("Malay"), "Bahasa Melayu", NULL },
768 { "my_MM", NULL, N_("Burmese"), "", NULL },
769 { "ne_NP", NULL, N_("Nepali"), NULL, NULL },
770 { "nl_NL", NULL, N_("Dutch"), "Nederlands", "@euro" },
771 { "nn_NO", NULL, N_("Norwegian (Nynorsk)"), "Norsk (Nynorsk)", NULL },
772 { "no_NO", NULL, N_("Norwegian (Bokmal)"), "Norsk (Bokmål)", NULL },
773 { "or_IN", NULL, N_("Oriya"), NULL, NULL },
774 { "pa_IN", NULL, N_("Punjabi"), NULL, NULL },
775 { "pl_PL", NULL, N_("Polish"), "Polski", NULL },
776 { "pt", "pt_PT", N_("Portuguese"), "Português", NULL },
777 { "pt_BR", NULL, N_("Portuguese (Brazil)"), "Português do Brasil", NULL },
778 { "pt_PT", NULL, N_("Portuguese"), "Português", "@euro" },
779 { "ro_RO", NULL, N_("Romanian"), "Română", NULL },
780 { "ru_RU", NULL, N_("Russian"), "русский", ".koi8r" },
781 { "si_LK", NULL, N_("Sinhala"), "සිංහල", NULL },
782 { "sk_SK", NULL, N_("Slovak"), "Slovenský", NULL },
783 { "sl_SI", NULL, N_("Slovenian"), "Slovenščina", NULL },
784 { "sq_AL", NULL, N_("Albanian"), "Shqip", NULL },
785 { "sr", "sr_YU", N_("Serbian"), "српски", NULL },
786 { "sr_CS", NULL, N_("Serbian"), "српски", NULL },
787 { "sr_YU", NULL, N_("Serbian"), "српски", "@cyrillic" },
788 { "sv", "sv_SE", N_("Swedish"), "Svenska", NULL },
789 { "sv_FI", NULL, N_("Swedish (Finland)"), "Svenska (Finland)", "@euro" },
790 { "sv_SE", NULL, N_("Swedish"), "Svenska", ".iso885915" },
791 { "ta_IN", NULL, N_("Tamil"), NULL, NULL },
792 { "te_IN", NULL, N_("Telugu"), NULL, NULL },
793 { "th_TH", NULL, N_("Thai"), "ไทย", NULL },
794 { "tr_TR", NULL, N_("Turkish"), "Türkçe", NULL },
795 { "ug", NULL, N_("Uighur"), NULL, NULL },
796 { "uk_UA", NULL, N_("Ukrainian"), "Українська", NULL },
797 { "ur_PK", NULL, N_("Urdu"), NULL, NULL },
798 { "uz_UZ", NULL, N_("Uzbek"), NULL, "@cyrillic" },
799 { "vi_VN", NULL, N_("Vietnamese"), "Việt Nam", ".tcvn" },
800 { "wa_BE", NULL, N_("Walloon"), "Walon", "@euro" },
801 { "yi" , "yi_US", N_("Yiddish"), "ייִדיש", NULL },
802 { "yi_US", NULL, N_("Yiddish"), "ייִדיש", NULL },
803 { "zh", "zh_CN", N_("Chinese"), "中文", NULL },
804 { "zh_CN", NULL, N_("Chinese (Simplified)"), "中文 (简体)", ".GB18030,.GBK,.GB2312,.eucCN" },
805 { "zh_HK", NULL, N_("Chinese (Hongkong)"), "中文 (香港)", NULL },
806 { "zh_SG", "zh_CN", N_("Chinese (Simplified)"), "中文 (简体)", ".GBK" },
807 { "zh_TW", NULL, N_("Chinese (Traditional)"), "中文 (繁體)", ".eucTW" },
809 { "nl_NL", NULL, N_("Dutch"), "Dutch", NULL },
810 { "nl_BE", NULL, N_("Dutch (Belgian)"), "Dutch (Belgian)", NULL },
811 { "en_US", NULL, N_("English (United States)"), "English (United States)", NULL },
812 { "en_GB", NULL, N_("English (United Kingdom)"), "English (United Kingdom)", NULL },
813 { "en_AU", NULL, N_("English (Australian)"), "English (Australian)", NULL },
814 { "en_CA", NULL, N_("English (Canadian)"), "English (Canadian)", NULL },
815 { "en_NZ", NULL, N_("English (New Zealand)"), "English (New Zealand)", NULL },
816 { "en_IE", NULL, N_("English (Irish)"), "English (Irish)", NULL },
817 { "en_ZA", NULL, N_("English (South Africa)"), "English (South Africa)", NULL },
818 { "en_JM", NULL, N_("English (Jamaica)"), "English (Jamaica)", NULL },
819 { "en_BZ", NULL, N_("English (Belize)"), "English (Belize)", NULL },
820 { "en_TT", NULL, N_("English (Trinidad)"), "English (Trinidad)", NULL },
821 { "en_ZW", NULL, N_("English (Zimbabwe)"), "English (Zimbabwe)", NULL },
822 { "en_PH", NULL, N_("English (Philippines)"), "English (Philippines)", NULL },
823 { "fr_FR", NULL, N_("French"), "French", NULL },
824 { "fr_BE", NULL, N_("French (Belgian)"), "French (Belgian)", NULL },
825 { "fr_CA", NULL, N_("French (Canadian)"), "French (Canadian)", NULL },
826 { "fr_CH", NULL, N_("French (Swiss)"), "French (Swiss)", NULL },
827 { "fr_LU", NULL, N_("French (Luxembourg)"), "French (Luxembourg)", NULL },
828 { "fr_MC", NULL, N_("French (Monaco)"), "French (Monaco)", NULL },
829 { "de_DE", NULL, N_("German"), "German", NULL },
830 { "de_CH", NULL, N_("German (Swiss)"), "German (Swiss)", NULL },
831 { "de_AT", NULL, N_("German (Austrian)"), "German (Austrian)", NULL },
832 { "de_LU", NULL, N_("German (Luxembourg)"), "German (Luxembourg)", NULL },
833 { "de_LI", NULL, N_("German (Liechtenstein)"), "German (Liechtenstein)", NULL },
834 { "it_IT", NULL, N_("Italian"), "Italian", NULL },
835 { "it_CH", NULL, N_("Italian (Swiss)"), "Italian (Swiss)", NULL },
836 { "pt_BR", NULL, N_("Portuguese (Brazilian)"), "Portuguese (Brazilian)", NULL },
837 { "pt_PT", NULL, N_("Portuguese"), "Portuguese", NULL },
838 { "es_ES", NULL, N_("Spanish (Traditional Sort)"), "Spanish (Traditional Sort)", NULL },
839 { "es_MX", NULL, N_("Spanish (Mexican)"), "Spanish (Mexican)", NULL },
840 { "es_GT", NULL, N_("Spanish (Guatemala)"), "Spanish (Guatemala)", NULL },
841 { "es_CR", NULL, N_("Spanish (Costa Rica)"), "Spanish (Costa Rica)", NULL },
842 { "es_PA", NULL, N_("Spanish (Panama)"), "Spanish (Panama)", NULL },
843 { "es_DO", NULL, N_("Spanish (Dominican Republic)"), "Spanish (Dominican Republic)", NULL },
844 { "es_VE", NULL, N_("Spanish (Venezuela)"), "Spanish (Venezuela)", NULL },
845 { "es_CO", NULL, N_("Spanish (Colombia)"), "Spanish (Colombia)", NULL },
846 { "es_PE", NULL, N_("Spanish (Peru)"), "Spanish (Peru)", NULL },
847 { "es_AR", NULL, N_("Spanish (Argentina)"), "Spanish (Argentina)", NULL },
848 { "es_EC", NULL, N_("Spanish (Ecuador)"), "Spanish (Ecuador)", NULL },
849 { "es_CL", NULL, N_("Spanish (Chile)"), "Spanish (Chile)", NULL },
850 { "es_UY", NULL, N_("Spanish (Uruguay)"), "Spanish (Uruguay)", NULL },
851 { "es_PY", NULL, N_("Spanish (Paraguay)"), "Spanish (Paraguay)", NULL },
852 { "es_BO", NULL, N_("Spanish (Bolivia)"), "Spanish (Bolivia)", NULL },
853 { "es_SV", NULL, N_("Spanish (El Salvador)"), "Spanish (El Salvador)", NULL },
854 { "es_HN", NULL, N_("Spanish (Honduras)"), "Spanish (Honduras)", NULL },
855 { "es_NI", NULL, N_("Spanish (Nicaragua)"), "Spanish (Nicaragua)", NULL },
856 { "es_PR", NULL, N_("Spanish (Puerto Rico)"), "Spanish (Puerto Rico)", NULL },
857 { "eu_ES", NULL, N_("Basque"), "Basque", NULL },
858 { "ca_ES", NULL, N_("Catalan"), "Catalan", NULL },
859 { "da_DK", NULL, N_("Danish"), "Danish", NULL },
860 { "af_AF", NULL, N_("Afrikaans"), "Afrikaans", NULL },
861 { "is_IS", NULL, N_("Icelandic"), "Icelandic", NULL },
862 { "fi_FI", NULL, N_("Finnish"), "Finnish", NULL },
863 { "ms_MY", NULL, N_("Malay (Malaysia)"), "Malay (Malaysia)", NULL },
864 { "ms_BN", NULL, N_("Malay (Brunei Darussalam)"), "Malay (Brunei Darussalam)", NULL },
865 { "no_NO", NULL, N_("Norwegian"), "Norwegian", NULL },
866 { "sv_SE", NULL, N_("Swedish"), "Swedish", NULL },
867 { "sv_FI", NULL, N_("Swedish (Finland)"), "Swedish (Finland)", NULL },
868 { "cs_CZ", NULL, N_("Czech"), "Czech", NULL },
869 { "hu_HU", NULL, N_("Hungarian"), "Hungarian", NULL },
870 { "pl_PL", NULL, N_("Polish"), "Polish", NULL },
871 { "ro_RO", NULL, N_("Romanian"), "Romanian", NULL },
872 { "sr_RS", NULL, N_("Serbian (Latin)"), "Serbian (Latin)", NULL },
873 { "sk_SK", NULL, N_("Slovak"), "Slovak", NULL },
874 { "sl_SI", NULL, N_("Slovenian"), "Slovenian", NULL },
875 { "et_EE", NULL, N_("Estonian"), "Estonian", NULL },
876 { "lv_LV", NULL, N_("Latvian"), "Latvian", NULL },
877 { "lt_LT", NULL, N_("Lithuanian"), "Lithuanian", NULL },
878 { "el_GR", NULL, N_("Greek"), "Greek", NULL },
879 { "bg_BG", NULL, N_("Bulgarian"), "Bulgarian", NULL },
880 { "kk_KZ", NULL, N_("Kazakh"), "Kazakh", NULL },
881 { "mk_MK", NULL, N_("Macedonian"), "Macedonian", NULL },
882 { "ru_RU", NULL, N_("Russian"), "Russian", NULL },
883 { "sr_RS", NULL, N_("Serbian (Cyrillic)"), "Serbian (Cyrillic)", NULL },
884 { "uk_UA", NULL, N_("Ukrainian"), "Ukrainian", NULL },
885 { "tr_TR", NULL, N_("Turkish"), "Turkish", NULL },
886 { "uz_UZ", NULL, N_("Uzbek (Latin)"), "Uzbek (Latin)", NULL },
887 { "ja_JP", NULL, N_("Japanese"), "Japanese", NULL },
888 { "ko_KR", NULL, N_("Korean"), "Korean", NULL },
889 { "zh_TW", NULL, N_("Chinese (Taiwan)"), "Chinese (Taiwan)", NULL },
890 { "zh_HK", NULL, N_("Chinese (Hong Kong)"), "Chinese (Hong Kong)", NULL },
891 { "zh_MO", NULL, N_("Chinese (Macau)"), "Chinese (Macau)", NULL },
892 { "zh_CN", NULL, N_("Chinese (PRC)"), "Chinese (PRC)", NULL },
893 { "zh_SG", NULL, N_("Chinese (Singapore)"), "Chinese (Singapore)", NULL },
894 { "th_TH", NULL, N_("Thai"), "Thai", NULL },
895 { "he_IL", NULL, N_("Hebrew"), "Hebrew", NULL },
896 { "ar_SA", NULL, N_("Arabic (Saudi Arabia)"), "Arabic (Saudi Arabia)", NULL },
897 { "ar_IQ", NULL, N_("Arabic (Iraq)"), "Arabic (Iraq)", NULL },
898 { "ar_EG", NULL, N_("Arabic (Egypt)"), "Arabic (Egypt)", NULL },
899 { "ar_LY", NULL, N_("Arabic (Libya)"), "Arabic (Libya)", NULL },
900 { "ar_DZ", NULL, N_("Arabic (Algeria)"), "Arabic (Algeria)", NULL },
901 { "ar_MA", NULL, N_("Arabic (Morocco)"), "Arabic (Morocco)", NULL },
902 { "ar_TN", NULL, N_("Arabic (Tunisia)"), "Arabic (Tunisia)", NULL },
903 { "ar_OM", NULL, N_("Arabic (Oman)"), "Arabic (Oman)", NULL },
904 { "ar_YE", NULL, N_("Arabic (Yemen)"), "Arabic (Yemen)", NULL },
905 { "ar_SY", NULL, N_("Arabic (Syria)"), "Arabic (Syria)", NULL },
906 { "ar_JO", NULL, N_("Arabic (Jordan)"), "Arabic (Jordan)", NULL },
907 { "ar_LB", NULL, N_("Arabic (Lebanon)"), "Arabic (Lebanon)", NULL },
908 { "ar_KW", NULL, N_("Arabic (Kuwait)"), "Arabic (Kuwait)", NULL },
909 { "ar_AE", NULL, N_("Arabic (UAE)"), "Arabic (UAE)", NULL },
910 { "ar_BH", NULL, N_("Arabic (Bahrain)"), "Arabic (Bahrain)", NULL },
911 { "ar_QA", NULL, N_("Arabic (Qatar)"), "Arabic (Qatar)", NULL },
912 { "ur_PK", NULL, N_("Urdu"), "Urdu", NULL },
913 { "vi_VN", NULL, N_("Vietnamese"), "Vietnamese", NULL },
914 { "hi_IN", NULL, N_("Hindi"), "Hindi", NULL },
915 { "te_IN", NULL, N_("Telugu"), "Telugu", NULL },
916 { "mr_IN", NULL, N_("Marathi"), "Marathi", NULL },
917 { "ta_IN", NULL, N_("Tamil"), "Tamil", NULL },
918 { "bn_IN", NULL, N_("Bengali"), "Bengali", NULL },
919 { "gu_IN", NULL, N_("Gujarati"), "Gujarati", NULL },
920 { "ml_IN", NULL, N_("Malayalam"), "Malayalam", NULL },
921 { "pa_IN", NULL, N_("Punjabi"), "Punjabi", NULL },
922 { "ka_GE", NULL, N_("Georgian"), "Georgian", NULL },
923 { "az_IR", NULL, N_("Azerbaijani"), "Azerbaijani", NULL },
924 { "gl_ES", NULL, N_("Galician"), "Galician", NULL },
925 { "ha_BJ", NULL, N_("Hausa"), "Hausa", NULL },
926 { "ga_IE", NULL, N_("Irish"), "Irish", NULL },
927 { "si_LK", NULL, N_("Sinhala"), "Sinhala", NULL },
928 { "cy_UK", NULL, N_("Welsh"), "Welsh", NULL },
929 { "xh_ZA", NULL, N_("Xhosa"), "Xhosa", NULL },
930 { "yo_NG", NULL, N_("Yoruba"), "Yoruba", NULL },
931 { "zu_ZA", NULL, N_("Zulu"), "Zulu", NULL },
933 { "", "", "", NULL, NULL }
939 bool operator () (const __Language &lhs, const __Language &rhs) const {
940 return strcmp (lhs.code, rhs.code) < 0;
943 bool operator () (const __Language &lhs, const String &rhs) const {
944 return strcmp (lhs.code, rhs.c_str ()) < 0;
947 bool operator () (const String &lhs, const __Language &rhs) const {
948 return strcmp (lhs.c_str (), rhs.code) < 0;
952 static bool language_sorted = false;
955 __find_language (const String &lang)
957 if (!language_sorted) {
958 language_sorted = true;
959 for (int loop = 0; ((unsigned int)loop) < sizeof(__languages) / sizeof(__Language) - 1; loop++) {
960 for (int innerLoop = loop + 1; ((unsigned int)innerLoop) < sizeof(__languages) / sizeof(__Language) - 1; innerLoop++) {
961 if (strcmp (__languages[loop].code, __languages[innerLoop].code) > 0) {
962 __Language temp = __languages[innerLoop];
963 __languages[innerLoop] = __languages[loop];
964 __languages[loop] = temp;
970 static __Language *langs_begin = __languages;
971 static __Language *langs_end = __languages + sizeof (__languages) / sizeof (__Language) - 1;
974 bool contry_code = false;
976 // Normalize the language name.
977 for (String::iterator it = nlang.begin (); it != nlang.end (); ++it) {
978 if (*it == '-' || *it == '_') {
981 } else if (contry_code) {
988 __Language *result = std::lower_bound (langs_begin, langs_end, nlang, __LanguageLess ());
990 if (result != langs_end) {
991 if (strncmp (result->code, nlang.c_str (), strlen (result->code)) == 0 ||
992 (strncmp (result->code, nlang.c_str (), nlang.length ()) == 0 &&
993 strncmp (result->code, (result+1)->code, nlang.length ()) != 0))
1001 scim_get_language_name (const String &lang)
1003 return String (_(scim_get_language_name_english (lang).c_str ()));
1007 scim_get_language_name_english (const String &lang)
1009 __Language *result = __find_language (lang);
1012 return String (result->name);
1014 return String ("Other");
1018 scim_get_language_name_untranslated (const String &lang)
1020 __Language *result = __find_language (lang);
1023 if (result->untranslated)
1024 return String (result->untranslated);
1026 return String (_(result->name));
1029 return String (_("Other"));
1033 scim_get_language_locales (const String &lang)
1035 __Language *result = __find_language (lang);
1037 std::vector<String> locales;
1042 if (strlen (result->code) < 5 && result->normalized)
1043 result = __find_language (result->normalized);
1046 good = scim_validate_locale (String (result->code) + ".UTF-8");
1048 if (good.length ()) locales.push_back (good);
1050 if (result && result->locale_suffix) {
1051 std::vector<String> suffixes;
1053 scim_split_string_list (suffixes, result->locale_suffix, ',');
1054 for (size_t i = 0; i < suffixes.size (); ++ i) {
1055 good = scim_validate_locale (String (result->code) + suffixes [i]);
1056 if (good.length ()) locales.push_back (good);
1061 good = scim_validate_locale (result->code);
1063 if (good.length ()) locales.push_back (good);
1066 return scim_combine_string_list (locales, ',');
1070 scim_get_locale_language (const String &locale)
1072 if (locale.length () == 0) return String ();
1074 String str = locale.substr (0, locale.find ('.'));
1075 return scim_validate_language (str.substr (0, str.find ('@')));
1079 scim_validate_language (const String &lang)
1081 __Language *result = __find_language (lang);
1084 return String (result->code);
1086 // Add prefix ~ to let other become the last item when sorting.
1087 return String ("~other");
1091 scim_get_normalized_language (const String &lang)
1093 __Language *result = __find_language (lang);
1096 if (result->normalized) return String (result->normalized);
1097 else return String (result->code);
1100 // Add prefix ~ to let other become the last item when sorting.
1101 //return String ("~other");
1102 return String ("en");
1105 #ifndef SCIM_LAUNCHER
1106 #define SCIM_LAUNCHER (SCIM_LIBEXECDIR "/scim-launcher")
1109 int scim_launch (bool daemon,
1110 const String &config,
1111 const String &imengines,
1112 const String &frontend,
1113 char * const argv [])
1115 if (!config.length () || !imengines.length () || !frontend.length ())
1119 char *new_argv [40];
1121 new_argv [new_argc ++] = strdup (SCIM_LAUNCHER);
1124 new_argv [new_argc ++] = strdup ("-d");
1126 new_argv [new_argc ++] = strdup ("-c");
1127 new_argv [new_argc ++] = strdup (config.c_str ());
1128 new_argv [new_argc ++] = strdup ("-e");
1129 new_argv [new_argc ++] = strdup (imengines.c_str ());
1130 new_argv [new_argc ++] = strdup ("-f");
1131 new_argv [new_argc ++] = strdup (frontend.c_str ());
1134 for (int i = 0; argv [i] && new_argc < 39 ; ++i, ++new_argc)
1135 new_argv [new_argc] = strdup (argv [i]);
1138 new_argv [new_argc] = 0;
1142 child_pid = fork ();
1145 if (child_pid < 0) return -1;
1147 // In child process, start scim-launcher.
1148 if (child_pid == 0) {
1149 return execv (SCIM_LAUNCHER, new_argv);
1152 // In parent process, wait the child exit.
1154 for (int i = 0; i < new_argc; ++i)
1155 if (new_argv [i]) free (new_argv [i]);
1160 ret_pid = waitpid (child_pid, &status, 0);
1162 if (ret_pid == child_pid && WIFEXITED(status))
1163 return WEXITSTATUS(status);
1168 #ifndef SCIM_PANEL_PROGRAM
1169 #define SCIM_PANEL_PROGRAM (SCIM_BINDIR "/scim-panel-gtk")
1172 int scim_launch_panel (bool daemon,
1173 const String &config,
1174 const String &display,
1175 char * const argv [])
1177 if (!config.length ())
1180 String panel_program = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_PANEL_PROGRAM, String (SCIM_PANEL_PROGRAM));
1182 if (!panel_program.length ())
1183 panel_program = String (SCIM_PANEL_PROGRAM);
1185 if (panel_program [0] != SCIM_PATH_DELIM) {
1186 panel_program = String (SCIM_BINDIR) +
1187 String (SCIM_PATH_DELIM_STRING) +
1191 //if the file is not exist or is not executable, fallback to default
1192 if (access (panel_program.c_str (), X_OK) != 0)
1193 panel_program = String (SCIM_PANEL_PROGRAM);
1196 char *new_argv [80];
1198 new_argv [new_argc ++] = strdup (panel_program.c_str ());
1200 new_argv [new_argc ++] = strdup ("--display");
1201 new_argv [new_argc ++] = strdup (display.c_str ());
1203 new_argv [new_argc ++] = strdup ("-c");
1204 new_argv [new_argc ++] = strdup (config.c_str ());
1207 new_argv [new_argc ++] = strdup ("-d");
1210 for (int i = 0; argv [i] && new_argc < 40; ++i, ++new_argc)
1211 new_argv [new_argc] = strdup (argv [i]);
1214 new_argv [new_argc] = 0;
1218 child_pid = fork ();
1221 if (child_pid < 0) return -1;
1223 // In child process, start scim-launcher.
1224 if (child_pid == 0) {
1225 return execv (panel_program.c_str (), new_argv);
1228 // In parent process, wait the child exit.
1230 for (int i = 0; i < new_argc; ++i)
1231 if (new_argv [i]) free (new_argv [i]);
1236 ret_pid = waitpid (child_pid, &status, 0);
1238 if (ret_pid == child_pid && WIFEXITED(status))
1239 return WEXITSTATUS(status);
1245 scim_usleep (unsigned int usec)
1247 if (usec == 0) return;
1250 struct timespec req, rem;
1252 req.tv_sec = usec / 1000000;
1253 req.tv_nsec = (usec % 1000000) * 1000;
1255 while (nanosleep (&req, &rem) == -1 && errno == EINTR && (rem.tv_sec != 0 || rem.tv_nsec != 0))
1258 unsigned int sec = usec / 1000000;
1261 for (unsigned int i = 0; i < sec; ++i)
1266 unsigned int sec = usec / 1000000;
1268 sleep (sec ? sec : 1);
1275 if (daemon (0, 0) == -1)
1276 std::cerr << "Error to make SCIM into a daemon!\n";
1284 std::cerr << "Error to make SCIM into a daemon!\n";
1286 } else if (id > 0) {
1292 std::cerr << "Error to make SCIM into a daemon!\n";
1294 } else if (id > 0) {
1302 void isf_save_log (const char *str)
1304 String strLogFile = scim_get_user_data_dir () + String (SCIM_PATH_DELIM_STRING) + String ("isf.log");
1305 std::ofstream isf_log_file (strLogFile.c_str (), std::ios::app);
1306 isf_log_file << str;
1307 isf_log_file.flush ();
1310 static struct timeval _t0 = {0, 0};
1311 static struct timeval _t1;
1313 static clock_t _p_t0;
1314 static clock_t _p_t1;
1316 void ISF_PROF_DEBUG_TIME_BEGIN ()
1320 _p_t0 = times (&tms);
1323 /* Measure elapased time */
1324 void ISF_PROF_DEBUG_TIME_END (char const* format, char const* func, int line)
1328 static long clktck = 0;
1331 if ((clktck = sysconf (_SC_CLK_TCK)) < 0)
1334 _p_t1 = times (&tms);
1336 etime = (_p_t1 - _p_t0) / (double) clktck;
1338 printf (format, func, line);
1339 printf (mzc_red "[T:%ld][E:%f]" mzc_normal " ", _p_t1, etime);
1344 /* Measure elapased time */
1345 void ISF_PROF_DEBUG_TIME (char const* func, int line, char const* str)
1349 if (_t0.tv_sec == 0 && _t0.tv_usec == 0) {
1350 gettimeofday (&_t0, NULL);
1354 gettimeofday (&_t1, NULL);
1356 if (_t0.tv_usec != 0) {
1357 etime = ((_t1.tv_sec * 1000000 + _t1.tv_usec) - (_t0.tv_sec * 1000000 + _t0.tv_usec))/1000000.0;
1360 printf (mzc_red "[%s:%04d] [T:%ld][E:%f] %s " mzc_normal " \n", func, line, (_t1.tv_sec * 1000000 + _t1.tv_usec), etime, str);
1367 void gettime (clock_t clock_start, const char* str)
1370 struct tms tiks_buf;
1371 double clock_tiks = (double)sysconf (_SC_CLK_TCK);
1372 clock_t times_tiks = times (&tiks_buf);
1373 double times_secs = (double)(times_tiks - clock_start) / clock_tiks;
1374 double utime = (double)tiks_buf.tms_utime / clock_tiks;
1375 double stime = (double)tiks_buf.tms_stime / clock_tiks;
1376 printf (mzc_red "%s Times: %.3f \t User: %.3f \t System: %.3f " mzc_normal "\n", str, (double)times_secs, (double)utime , (double)stime);
1383 vi:ts=4:ai:nowrap:expandtab