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-2015 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 "isf_debug.h"
54 #include "scim_private.h"
60 #define LOG_TAG "ISF_UTILITY"
65 utf8_mbtowc (ucs4_t *pwc, const unsigned char *src, int src_len)
70 unsigned char c = src [0];
75 } else if (c < 0xc2) {
77 } else if (c < 0xe0) {
80 unsigned char utf8_x1 = src [1] ^ 0x80;
83 *pwc = ((ucs4_t) (c & 0x1f) << 6)
86 } else if (c < 0xf0) {
89 unsigned char utf8_x1 = src[1] ^ 0x80;
90 unsigned char utf8_x2 = src[2] ^ 0x80;
91 if (!((utf8_x1 | utf8_x2) < 0x40
92 && (c >= 0xe1 || src [1] >= 0xa0)))
94 *pwc = ((ucs4_t) (c & 0x0f) << 12)
95 | ((ucs4_t) (utf8_x1) << 6)
98 } else if (c < 0xf8) {
100 return RET_TOOFEW(0);
101 unsigned char utf8_x1 = src[1] ^ 0x80;
102 unsigned char utf8_x2 = src[2] ^ 0x80;
103 unsigned char utf8_x3 = src[3] ^ 0x80;
104 if (!((utf8_x1 | utf8_x2 | utf8_x3) < 0x40
105 && (c >= 0xf1 || src [1] >= 0x90)))
107 *pwc = ((ucs4_t) (c & 0x07) << 18)
108 | ((ucs4_t) (utf8_x1) << 12)
109 | ((ucs4_t) (utf8_x2) << 6)
110 | (ucs4_t) (utf8_x3);
112 } else if (c < 0xfc) {
114 return RET_TOOFEW(0);
115 unsigned char utf8_x1 = src[1] ^ 0x80;
116 unsigned char utf8_x2 = src[2] ^ 0x80;
117 unsigned char utf8_x3 = src[3] ^ 0x80;
118 unsigned char utf8_x4 = src[4] ^ 0x80;
119 if (!((utf8_x1 | utf8_x2 | utf8_x3 | utf8_x4) < 0x40
120 && (c >= 0xf9 || src [1] >= 0x88)))
122 *pwc = ((ucs4_t) (c & 0x03) << 24)
123 | ((ucs4_t) (utf8_x1) << 18)
124 | ((ucs4_t) (utf8_x2) << 12)
125 | ((ucs4_t) (utf8_x3) << 6)
126 | (ucs4_t) (utf8_x4);
128 } else if (c < 0xfe) {
130 return RET_TOOFEW(0);
131 unsigned char utf8_x1 = src[1] ^ 0x80;
132 unsigned char utf8_x2 = src[2] ^ 0x80;
133 unsigned char utf8_x3 = src[3] ^ 0x80;
134 unsigned char utf8_x4 = src[4] ^ 0x80;
135 unsigned char utf8_x5 = src[5] ^ 0x80;
136 if (!((utf8_x1 | utf8_x2 | utf8_x3 | utf8_x4 | utf8_x5) < 0x40
137 && (c >= 0xfd || src [1] >= 0x84)))
139 *pwc = ((ucs4_t) (c & 0x01) << 30)
140 | ((ucs4_t) (utf8_x1) << 24)
141 | ((ucs4_t) (utf8_x2) << 18)
142 | ((ucs4_t) (utf8_x3) << 12)
143 | ((ucs4_t) (utf8_x4) << 6)
144 | (ucs4_t) (utf8_x5);
151 utf8_wctomb (unsigned char *dest, ucs4_t wc, int dest_size)
156 unsigned int _wc = wc;
159 else if (_wc < 0x800)
161 else if (_wc < 0x10000)
163 else if (_wc < 0x200000)
165 else if (_wc < 0x4000000)
167 else if (_wc <= 0x7fffffff)
172 if (dest_size < count)
174 switch (count) { /* note: code falls through cases! */
175 case 6: dest [5] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x4000000;
176 case 5: dest [4] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x200000;
177 case 4: dest [3] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x10000;
178 case 3: dest [2] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x800;
179 case 2: dest [1] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0xc0;
180 case 1: dest [0] = wc;
186 utf8_read_wchar (std::istream &is)
188 unsigned char utf8[5] = {0};
189 unsigned char utf8_x_;
191 is.read ((char*)(&utf8_x_), sizeof(unsigned char)); // reducing utf8 char sequence to ucs4 convertations
192 if (utf8_x_ < 0x80) {
193 return (ucs4_t)utf8_x_;
194 } else if (utf8_x_ < 0xc2) {
196 } else if (utf8_x_ < 0xe0) {
197 unsigned char utf8_x1;
198 is.read ((char*)(&utf8_x1), sizeof(unsigned char));
202 return ((ucs4_t) (utf8_x_ & 0x1f) << 6)
203 | (ucs4_t) (utf8_x1);
204 } else if (utf8_x_ < 0xf0) {
205 is.read ((char*)(&utf8[0]), 2*sizeof(unsigned char));
206 unsigned char utf8_x1 = utf8[0] ^ 0x80;
207 unsigned char utf8_x2 = utf8[1] ^ 0x80;
208 if (!((utf8_x1 | utf8_x2) < 0x40
209 && (utf8_x_ >= 0xe1 || utf8[0] >= 0xa0)))
211 return ((ucs4_t) (utf8_x_ & 0x0f) << 12)
212 | ((ucs4_t) (utf8_x1) << 6)
213 | (ucs4_t) (utf8_x2);
214 } else if (utf8_x_ < 0xf8) {
215 is.read ((char*)(&utf8[0]), 3*sizeof(unsigned char));
216 unsigned char utf8_x1 = utf8[0] ^ 0x80;
217 unsigned char utf8_x2 = utf8[1] ^ 0x80;
218 unsigned char utf8_x3 = utf8[2] ^ 0x80;
219 if (!((utf8_x1 | utf8_x2 | utf8_x3) < 0x40
220 && (utf8_x_ >= 0xf1 || utf8[0] >= 0x90)))
222 return ((ucs4_t) (utf8_x_ & 0x07) << 18)
223 | ((ucs4_t) (utf8_x1) << 12)
224 | ((ucs4_t) (utf8_x2) << 6)
225 | (ucs4_t) (utf8_x3);
226 } else if (utf8_x_ < 0xfc) {
227 is.read ((char*)(&utf8[0]), 4*sizeof(unsigned char));
228 unsigned char utf8_x1 = utf8[0] ^ 0x80;
229 unsigned char utf8_x2 = utf8[1] ^ 0x80;
230 unsigned char utf8_x3 = utf8[2] ^ 0x80;
231 unsigned char utf8_x4 = utf8[3] ^ 0x80;
232 if (!((utf8_x1 | utf8_x2 | utf8_x3 | utf8_x4) < 0x40
233 && (utf8_x_ >= 0xf9 || utf8[0] >= 0x88)))
235 return ((ucs4_t) (utf8_x_ & 0x03) << 24)
236 | ((ucs4_t) (utf8_x1) << 18)
237 | ((ucs4_t) (utf8_x2) << 12)
238 | ((ucs4_t) (utf8_x3) << 6)
239 | (ucs4_t) (utf8_x4);
240 } else if (utf8_x_ < 0xfe) {
241 is.read ((char*)(&utf8[0]), 5*sizeof(unsigned char));
242 unsigned char utf8_x1 = utf8[0] ^ 0x80;
243 unsigned char utf8_x2 = utf8[1] ^ 0x80;
244 unsigned char utf8_x3 = utf8[2] ^ 0x80;
245 unsigned char utf8_x4 = utf8[3] ^ 0x80;
246 unsigned char utf8_x5 = utf8[4] ^ 0x80;
247 if (!((utf8_x1 | utf8_x2 | utf8_x3 | utf8_x4 | utf8_x5) < 0x40
248 && (utf8_x_ >= 0xfd || utf8[0] >= 0x84)))
250 return ((ucs4_t) (utf8_x_ & 0x01) << 30)
251 | ((ucs4_t) (utf8_x1) << 24)
252 | ((ucs4_t) (utf8_x2) << 18)
253 | ((ucs4_t) (utf8_x3) << 12)
254 | ((ucs4_t) (utf8_x4) << 6)
255 | (ucs4_t) (utf8_x5);
261 utf8_read_wstring (std::istream &is, ucs4_t delim, bool rm_delim)
265 while ((wc = utf8_read_wchar (is)) > 0) {
278 utf8_write_wchar (std::ostream &os, ucs4_t wc)
280 unsigned char utf8[6];
283 if ((count=utf8_wctomb (utf8, wc, 6)) > 0)
284 os.write ((char*)utf8, count * sizeof (unsigned char));
290 utf8_write_wstring (std::ostream &os, const WideString & wstr)
292 for (unsigned int i=0; i<wstr.size (); ++i)
293 utf8_write_wchar (os, wstr [i]);
299 utf8_mbstowcs (const String & str)
306 const unsigned char *s = (const unsigned char *) str.c_str ();
308 while (sn < str.length () && *s != 0 &&
309 (un=utf8_mbtowc (&wc, s, str.length () - sn)) > 0) {
318 utf8_mbstowcs (const char *str, int len)
327 if (len < 0) len = strlen (str);
329 while (sn < ((unsigned int)len) && *str != 0 && (un=utf8_mbtowc (&wc, (const unsigned char *)str, len - sn)) > 0) {
340 utf8_wcstombs (const WideString & wstr)
346 for (unsigned int i = 0; i<wstr.size (); ++i) {
347 un = utf8_wctomb ((unsigned char*)utf8, wstr [i], 6);
349 str.append (utf8, un);
355 utf8_wcstombs (const ucs4_t *wstr, int len)
368 for (int i = 0; i < len; ++i) {
369 un = utf8_wctomb ((unsigned char*)utf8, wstr [i], 6);
371 str.append (utf8, un);
377 static String trim_blank (const String &str)
379 String::size_type begin, len;
381 begin = str.find_first_not_of (" \t\n\v");
383 if (begin == String::npos)
386 len = str.find_last_not_of (" \t\n\v") - begin + 1;
388 return str.substr (begin, len);
392 scim_validate_locale (const String& locale)
396 String last = String (setlocale (LC_CTYPE, 0));
398 if (setlocale (LC_CTYPE, locale.c_str ())) {
401 std::vector<String> vec;
402 if (scim_split_string_list (vec, locale, '.') == 2) {
403 if (isupper (vec[1][0])) {
404 for (String::iterator i=vec[1].begin (); i!=vec[1].end (); ++i)
405 *i = (char) tolower (*i);
407 for (String::iterator i=vec[1].begin (); i!=vec[1].end (); ++i)
408 *i = (char) toupper (*i);
410 if (setlocale (LC_CTYPE, (vec[0] + "." + vec[1]).c_str ())) {
411 good = vec [0] + "." + vec[1];
416 setlocale (LC_CTYPE, last.c_str ());
422 scim_get_locale_encoding (const String& locale)
424 String last = String (setlocale (LC_CTYPE, 0));
427 if (setlocale (LC_CTYPE, locale.c_str ()))
428 encoding = String (nl_langinfo (CODESET));
430 std::vector<String> vec;
431 if (scim_split_string_list (vec, locale, '.') == 2) {
432 if (isupper (vec[1][0])) {
433 for (String::iterator i=vec[1].begin (); i!=vec[1].end (); ++i)
434 *i = (char) tolower (*i);
436 for (String::iterator i=vec[1].begin (); i!=vec[1].end (); ++i)
437 *i = (char) toupper (*i);
439 if (setlocale (LC_CTYPE, (vec[0] + "." + vec[1]).c_str ()))
440 encoding = String (nl_langinfo (CODESET));
445 setlocale (LC_CTYPE, last.c_str ());
451 scim_get_locale_maxlen (const String& locale)
455 String last = String (setlocale (LC_CTYPE, 0));
457 if (setlocale (LC_CTYPE, locale.c_str ()))
462 setlocale (LC_CTYPE, last.c_str ());
467 scim_split_string_list (std::vector<String>& vec, const String& str, char delim)
472 String::const_iterator bg, ed;
476 if (str.empty ()) return 0;
481 while (bg != str.end () && ed != str.end ()) {
482 for (; ed != str.end (); ++ed) {
486 temp.assign (bg, ed);
487 temp = trim_blank (temp);
488 vec.push_back (temp);
491 if (ed != str.end ())
498 scim_combine_string_list (const std::vector<String>& vec, char delim)
501 for (std::vector<String>::const_iterator i = vec.begin (); i!=vec.end (); ++i) {
503 if (i+1 != vec.end ())
510 scim_if_wchar_ucs4_equal ()
512 if (sizeof (wchar_t) != sizeof (ucs4_t))
516 wchar_t wcbuf [2] = {0,0};
517 ucs4_t ucsbuf [2] = {0x4E00, 0x0001};
518 size_t wclen = 2 * sizeof (wchar_t);
519 size_t ucslen = 2 * sizeof (ucs4_t);
521 char *wcp = (char *) wcbuf;
522 ICONV_CONST char *ucsp = (ICONV_CONST char *) ucsbuf;
524 if (scim_is_little_endian ())
525 cd = iconv_open ("UCS-4LE", "wchar_t");
527 cd = iconv_open ("UCS-4BE", "wchar_t");
529 if (cd == (iconv_t) -1)
532 iconv (cd, &ucsp, &ucslen, &wcp, &wclen);
536 if (wcbuf [0] == (wchar_t) ucsbuf [0] &&
537 wcbuf [1] == (wchar_t) ucsbuf [1])
547 } __half_full_table [] = {
549 {0x0021, 0xFF01, 0x5E},
602 {0xFFA1, 0x3131, 30},
614 * convert a half width unicode char to full width char
617 scim_wchar_to_full_width (ucs4_t code)
620 while (__half_full_table [i].size) {
621 if (code >= __half_full_table [i].half &&
622 code < __half_full_table [i].half +
623 __half_full_table [i].size)
624 return __half_full_table [i].full +
625 (code - __half_full_table [i].half);
632 * convert a full width unicode char to half width char
635 scim_wchar_to_half_width (ucs4_t code)
638 while (__half_full_table [i].size) {
639 if (code >= __half_full_table [i].full &&
640 code < __half_full_table [i].full +
641 __half_full_table [i].size)
642 return __half_full_table [i].half +
643 (code - __half_full_table [i].full);
652 const char * home_dir = 0;
654 struct passwd *result;
655 char buf [2048] = {0,};
658 getpwuid_r (getuid (), &pw, buf, sizeof (buf), &result);
661 if (result && pw.pw_dir) {
662 home_dir = pw.pw_dir;
664 LOGD ("Fail to getpwuid_r\n");
668 home_dir = getenv ("HOME");
672 return String (home_dir);
678 scim_get_user_name ()
680 const char *user_name;
682 struct passwd *result;
683 char buf [2048] = {0,};
686 getpwuid_r (getuid (), &pw, buf, sizeof (buf), &result);
689 if (result && pw.pw_name) {
690 return String (pw.pw_name);
691 } else if ((user_name = getenv ("USER")) != NULL) {
692 return String (user_name);
697 snprintf (uid_str, 10, "%u", getuid ());
699 return String (uid_str);
703 scim_get_user_data_dir ()
705 String dir = scim_get_home_dir () + String ("/.config/.scim");
711 scim_get_current_locale ()
713 char *locale = setlocale (LC_CTYPE, 0);
715 if (locale) return String (locale);
719 EXAPI String scim_get_current_language ()
721 return scim_get_locale_language (scim_get_current_locale ());
725 scim_is_little_endian ()
728 return (*((char *)&endian) != 0);
732 scim_load_file (const String &filename, char **bufptr)
734 if (!filename.length ())
739 if (stat (filename.c_str (), &statbuf) < 0 ||
740 !S_ISREG (statbuf.st_mode) ||
745 return statbuf.st_size;
747 FILE *fp = fopen (filename.c_str (), "r");
755 *bufptr = new char [statbuf.st_size];
766 size_t size = fread (*bufptr, 1, statbuf.st_size, fp);
779 scim_make_dir (const String &dir)
781 if (access (dir.c_str (), R_OK) != 0) {
782 std::vector <String> paths;
785 scim_split_string_list (paths, dir, SCIM_PATH_DELIM);
787 for (size_t i = 1; i < paths.size (); ++i) {
788 path += SCIM_PATH_DELIM_STRING + paths [i];
790 //Make the dir if it's not exist.
791 if (access (path.c_str (), R_OK) != 0) {
792 if (mkdir (path.c_str (), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0)
795 if (access (path.c_str (), R_OK) != 0)
805 const char *normalized;
807 const char *untranslated;
808 const char *locale_suffix;
811 static __Language __languages [] = {
812 { "C", NULL, N_("English Keyboard"), NULL, NULL},
813 { "am_ET", NULL, N_("Amharic"), "አማርኛ", NULL },
814 { "ar", "ar", N_("Arabic"), "عربي", NULL },
815 { "ar_EG", NULL, N_("Arabic (Egypt)"), "العربية (مصر)", NULL },
816 { "ar_LB", NULL, N_("Arabic (Lebanon)"), "العربية (لبنان)", NULL },
817 { "ar_IL", NULL, N_("Arabic (Israel)"), "العربية", NULL },
818 { "as_IN", NULL, N_("Assamese"), "অসমীয়া", NULL},
819 { "az_AZ", NULL, N_("Azerbaijani"), "Azərbaycan", NULL },
820 { "be_BY", NULL, N_("Belarusian"), "Беларуская мова", NULL },
821 { "bg_BG", NULL, N_("Bulgarian"), "Български", NULL },
822 { "bn", "bn_BD", N_("Bengali"), "বাংলা", NULL },
823 { "bn_BD", NULL, N_("Bengali"), "বাংলা", NULL },
824 { "bn_IN", NULL, N_("Bengali (India)"), "বাংলা", NULL },
825 { "bo", NULL, N_("Tibetan"), "པོད་སྐད་", NULL },
826 { "bs_BA", NULL, N_("Bosnian"), "Bosanski", NULL },
827 { "ca_ES", NULL, N_("Catalan"), "Català", "@euro" },
828 { "cs_CZ", NULL, N_("Czech"), "čeština", NULL },
829 { "cy_GB", NULL, N_("Welsh"), "Cymraeg", NULL },
830 { "da_DK", NULL, N_("Danish"), "Dansk", "@euro" },
831 { "de_DE", NULL, N_("German"), "Deutsch", "@euro" },
832 { "dv_MV", NULL, N_("Divehi"), "ދިވެހިބަސް", NULL },
833 { "el_GR", NULL, N_("Greek"), "ελληνικά", NULL },
834 { "en" , NULL, N_("English"), "English", NULL },
835 { "en_AU", NULL, N_("English (Australian)"), "English (Australian)", NULL },
836 { "en_CA", NULL, N_("English (Canadian)"), "English (Canadian)", NULL },
837 { "en_GB", NULL, N_("English (United Kingdom)"), "English (United Kingdom)", ".iso885915" },
838 { "en_IE", NULL, N_("English (Ireland)"), "English (Ireland)", NULL },
839 { "en_US", NULL, N_("English (United States)"), "English (United States)", ".iso885915" },
840 { "eo", NULL, N_("Esperanto"), "Esperanto", NULL },
841 { "es", "es_ES", N_("Spanish"), "Español", NULL },
842 { "es_ES", NULL, N_("Spanish"), "Español", "@euro" },
843 { "es_MX", NULL, N_("Spanish (Mexico)"), "Español (Mexico)", NULL },
844 { "es_US", NULL, N_("Spanish (United States)"), "Español (United States)", NULL },
845 { "et_EE", NULL, N_("Estonian"), "Eesti", ".iso885915" },
846 { "eu_ES", NULL, N_("Basque"), "Euskara", "@euro" },
847 { "fa_IR", NULL, N_("Persian"), "فارسی", NULL },
848 { "fi_FI", NULL, N_("Finnish"), "Suomi", "@euro" },
849 { "fr_FR", NULL, N_("French"), "Français", "@euro" },
850 { "ga_IE", NULL, N_("Irish"), "Gaeilge", "@euro" },
851 { "gl_ES", NULL, N_("Galician"), "Galego", "@euro" },
852 { "gu_IN", NULL, N_("Gujarati"), "ગુજરાતી", NULL },
853 { "he_IL", NULL, N_("Hebrew"), "עברית", NULL },
854 { "hi_IN", NULL, N_("Hindi"), "हिंदी", NULL },
855 { "hr_HR", NULL, N_("Croatian"), "Hrvatski", NULL },
856 { "hu_HU", NULL, N_("Hungarian"), "Magyar", NULL },
857 { "hy_AM", NULL, N_("Armenian"), "Հայերէն", NULL },
858 { "ia" , NULL, N_("Interlingua"), "Interlingua", NULL },
859 { "id_ID", NULL, N_("Indonesian"), "Bahasa Indonesia", NULL },
860 { "is_IS", NULL, N_("Icelandic"), "íslenska", NULL },
861 { "it_IT", NULL, N_("Italian"), "Italiano", "@euro" },
862 { "iw_IL", NULL, N_("Hebrew"), "עברית", NULL },
863 { "ja_JP", NULL, N_("Japanese"), "日本語", ".EUC-JP,.SJIS,.eucJP" },
864 { "ka_GE", NULL, N_("Georgian"), "ქართული", NULL },
865 { "kk_KZ", NULL, N_("Kazakh"), "Қазақ", NULL },
866 { "km", NULL, N_("Cambodian"), "ភាសាខ្មែរ", NULL },
867 { "kn_IN", NULL, N_("Kannada"), "ಕನ್ನಡ", NULL },
868 { "ko_KR", NULL, N_("Korean"), "한국어", ".EUC-KR,.eucKR" },
869 { "lo", NULL, N_("Lao"), "لاوس", NULL },
870 { "lo_LA", NULL, N_("Laothian"), "ລາວ", NULL },
871 { "lt_LT", NULL, N_("Lithuanian"), "Lietuvių", NULL },
872 { "lv_LV", NULL, N_("Latvian"), "Latviešu", NULL },
873 { "mk_MK", NULL, N_("Macedonian"), "Македонски", NULL },
874 { "ml_IN", NULL, N_("Malayalam"), "മലയാളം", NULL },
875 { "mn_MN", NULL, N_("Mongolian"), "Монгол", NULL },
876 { "mr_IN", NULL, N_("Marathi"), "मराठी", NULL },
877 { "ms_MY", NULL, N_("Malay"), "Bahasa Melayu", NULL },
878 { "my_MM", NULL, N_("Burmese"), "မြန်မာဘာသာ", NULL },
879 { "ne_NP", NULL, N_("Nepali"), "नेपाली", NULL },
880 { "nl_NL", NULL, N_("Dutch"), "Nederlands", "@euro" },
881 { "nn_NO", NULL, N_("Norwegian (Nynorsk)"), "Norsk (Nynorsk)", NULL },
882 { "nb_NO", NULL, N_("Norwegian (Bokmal)"), "Norsk (Bokmål)", NULL },
883 { "or_IN", NULL, N_("Oriya"), "ଓଡ଼ିଆ", NULL },
884 { "pa_IN", NULL, N_("Punjabi"), "ਪੰਜਾਬੀ", NULL },
885 { "pl_PL", NULL, N_("Polish"), "Polski", NULL },
886 { "pt", "pt_PT", N_("Portuguese"), "Português", NULL },
887 { "pt_BR", NULL, N_("Portuguese (Brazil)"), "Português (Brasil)", NULL },
888 { "pt_PT", NULL, N_("Portuguese"), "Português", "@euro" },
889 { "ro_RO", NULL, N_("Romanian"), "Română", NULL },
890 { "ru_RU", NULL, N_("Russian"), "русский", ".koi8r" },
891 { "sd", "sd_IN", N_("Sindhi"), "ﺲﻧڌﻱ", NULL },
892 { "sd_IN", NULL, N_("Sindhi"), "सिन्धी", "@devanagari" },
893 { "si_IN", NULL, N_("Sinhala"), "සිංහල", NULL },
894 { "si_LK", NULL, N_("Sinhala"), "සිංහල", NULL },
895 { "sk_SK", NULL, N_("Slovak"), "Slovenský", NULL },
896 { "sl_SI", NULL, N_("Slovenian"), "Slovenščina", NULL },
897 { "sq_AL", NULL, N_("Albanian"), "Shqip", NULL },
898 { "sr", "sr_YU", N_("Serbian"), "Srpski", NULL },
899 { "sr_CS", NULL, N_("Serbian"), "Srpski", NULL },
900 { "sr_YU", NULL, N_("Serbian"), "Srpski", "@cyrillic" },
901 { "sv", "sv_SE", N_("Swedish"), "Svenska", NULL },
902 { "sv_FI", NULL, N_("Swedish (Finland)"), "Svenska (Finland)", "@euro" },
903 { "sv_SE", NULL, N_("Swedish"), "Svenska", ".iso885915" },
904 { "ta_IN", NULL, N_("Tamil"), "தமிழ்", NULL },
905 { "te_IN", NULL, N_("Telugu"), "తెలుగు", NULL },
906 { "th_TH", NULL, N_("Thai"), "ภาษาไทย", NULL },
907 { "tr_TR", NULL, N_("Turkish"), "Türkçe", NULL },
908 { "ug", NULL, N_("Uighur"), "ئۇيغۇر", NULL },
909 { "uk_UA", NULL, N_("Ukrainian"), "Українська", NULL },
910 { "ur_PK", NULL, N_("Urdu"), "اردو", NULL },
911 { "uz_UZ", NULL, N_("Uzbek"), "o'zbek tili", "@cyrillic" },
912 { "vi_VN", NULL, N_("Vietnamese"), "Tiếng Việt", ".tcvn" },
913 { "wa_BE", NULL, N_("Walloon"), "Walon", "@euro" },
914 { "yi" , "yi_US", N_("Yiddish"), "ייִדיש", NULL },
915 { "yi_US", NULL, N_("Yiddish"), "ייִדיש", NULL },
916 { "zh", "zh_CN", N_("Chinese"), "中文", NULL },
917 { "zh_CN", NULL, N_("Chinese (Simplified)"), "中文 (简体)", ".GB18030,.GBK,.GB2312,.eucCN" },
918 { "zh_HK", NULL, N_("Chinese (Hongkong)"), "中文 (香港)", NULL },
919 { "zh_SG", "zh_CN", N_("Chinese (Singapore)"), "中文 (新加坡)", ".GBK" },
920 { "zh_TW", NULL, N_("Chinese (Traditional_Taiwan)"), "中文 (台湾)", ".eucTW" },
922 { "nl_BE", NULL, N_("Dutch (Belgian)"), "Dutch (Belgian)", NULL },
923 { "en_NZ", NULL, N_("English (New Zealand)"), "English (New Zealand)", NULL },
924 { "en_ZA", NULL, N_("English (South Africa)"), "English (South Africa)", NULL },
925 { "en_JM", NULL, N_("English (Jamaica)"), "English (Jamaica)", NULL },
926 { "en_BZ", NULL, N_("English (Belize)"), "English (Belize)", NULL },
927 { "en_TT", NULL, N_("English (Trinidad)"), "English (Trinidad)", NULL },
928 { "en_ZW", NULL, N_("English (Zimbabwe)"), "English (Zimbabwe)", NULL },
929 { "en_PH", NULL, N_("English (Philippines)"), "English (Philippines)", NULL },
930 { "fr_BE", NULL, N_("French (Belgian)"), "Français (Belgian)", NULL },
931 { "fr_CA", NULL, N_("French (Canadian)"), "Français (Canada)", NULL },
932 { "fr_CH", NULL, N_("French (Swiss)"), "Français (Suisse)", NULL },
933 { "fr_LU", NULL, N_("French (Luxembourg)"), "Français (Luxembourg)", NULL },
934 { "fr_MC", NULL, N_("French (Monaco)"), "Français (Monaco)", NULL },
935 { "de_CH", NULL, N_("German (Swiss)"), "Deutsch (Schweiz)", NULL },
936 { "de_AT", NULL, N_("German (Austrian)"), "Deutsch (Österreich)", NULL },
937 { "de_LU", NULL, N_("German (Luxembourg)"), "Deutsch (Luxembourg)", NULL },
938 { "de_LI", NULL, N_("German (Liechtenstein)"), "Deutsch (Liechtenstein)", NULL },
939 { "it_CH", NULL, N_("Italian (Swiss)"), "italiano (Svizzera)", NULL },
940 { "es_GT", NULL, N_("Spanish (Guatemala)"), "español (Guatemala)", NULL },
941 { "es_CR", NULL, N_("Spanish (Costa Rica)"), "español (Costa Rica)", NULL },
942 { "es_PA", NULL, N_("Spanish (Panama)"), "español (Panamá)", NULL },
943 { "es_DO", NULL, N_("Spanish (Dominican Republic)"), "español (República Dominicana)", NULL },
944 { "es_VE", NULL, N_("Spanish (Venezuela)"), "español (Venezuela)", NULL },
945 { "es_CO", NULL, N_("Spanish (Colombia)"), "español (Colombia)", NULL },
946 { "es_PE", NULL, N_("Spanish (Peru)"), "español (Perú)", NULL },
947 { "es_AR", NULL, N_("Spanish (Argentina)"), "español (Argentina)", NULL },
948 { "es_EC", NULL, N_("Spanish (Ecuador)"), "español (Ecuador)", NULL },
949 { "es_CL", NULL, N_("Spanish (Chile)"), "español (Chile)", NULL },
950 { "es_UY", NULL, N_("Spanish (Uruguay)"), "español (Uruguay)", NULL },
951 { "es_PY", NULL, N_("Spanish (Paraguay)"), "español (Paraguay)", NULL },
952 { "es_BO", NULL, N_("Spanish (Bolivia)"), "español (Bolivia)", NULL },
953 { "es_SV", NULL, N_("Spanish (El Salvador)"), "español (El Salvador)", NULL },
954 { "es_HN", NULL, N_("Spanish (Honduras)"), "español (Honduras)", NULL },
955 { "es_NI", NULL, N_("Spanish (Nicaragua)"), "español (Nicaragua)", NULL },
956 { "es_PR", NULL, N_("Spanish (Puerto Rico)"), "español (Puerto Rico)", NULL },
957 { "af_AF", NULL, N_("Afrikaans"), "Afrikaans", NULL },
958 { "ms_BN", NULL, N_("Malay (Brunei Darussalam)"), "Bahasa Melayu (Brunei)", NULL },
959 { "no_NO", NULL, N_("Norwegian"), "Norsk", NULL },
960 { "sr_RS", NULL, N_("Serbian (Latin)"), "Srpski (latinica)", NULL },
961 { "sr_RS", NULL, N_("Serbian (Cyrillic)"), "Srpski (ćirilica)", NULL },
962 { "zh_MO", NULL, N_("Chinese (Macau)"), "Chinese (Macau)", NULL },
963 { "ar_SA", NULL, N_("Arabic (Saudi Arabia)"), "العربية (المملكة العربية السعودية)", NULL },
964 { "ar_IQ", NULL, N_("Arabic (Iraq)"), "العربية (العراق)", NULL },
965 { "ar_LY", NULL, N_("Arabic (Libya)"), "العربية (ليبيا)", NULL },
966 { "ar_DZ", NULL, N_("Arabic (Algeria)"), "العربية (الجزائر)", NULL },
967 { "ar_MA", NULL, N_("Arabic (Morocco)"), "العربية (المغرب)", NULL },
968 { "ar_TN", NULL, N_("Arabic (Tunisia)"), "العربية (تونس)", NULL },
969 { "ar_OM", NULL, N_("Arabic (Oman)"), "العربية (عُمان)", NULL },
970 { "ar_YE", NULL, N_("Arabic (Yemen)"), "العربية (اليمن)", NULL },
971 { "ar_SY", NULL, N_("Arabic (Syria)"), "العربية (سوريا)", NULL },
972 { "ar_JO", NULL, N_("Arabic (Jordan)"), "العربية (الأردن)", NULL },
973 { "ar_KW", NULL, N_("Arabic (Kuwait)"), "العربية (الكويت)", NULL },
974 { "ar_AE", NULL, N_("Arabic (UAE)"), "العربية (الإمارات العربية المتحدة)", NULL },
975 { "ar_BH", NULL, N_("Arabic (Bahrain)"), "العربية (البحرين)", NULL },
976 { "ar_QA", NULL, N_("Arabic (Qatar)"), "العربية (قطر)", NULL },
977 { "az_IR", NULL, N_("Azerbaijani"), "Azərbaycan", NULL },
978 { "ha_BJ", NULL, N_("Hausa"), "Hausa", NULL },
979 { "cy_UK", NULL, N_("Welsh"), "Cymraeg", NULL },
980 { "xh_ZA", NULL, N_("Xhosa"), "isiXhosa", NULL },
981 { "yo_NG", NULL, N_("Yoruba"), "Èdè Yorùbá", NULL },
982 { "zu_ZA", NULL, N_("Zulu"), "isiZulu", NULL },
983 { "hg_IN", NULL, N_("Hinglish"), "Hinglish", NULL },
984 { "su_ID", NULL, N_("Sundanese"), "Basa Sunda", NULL },
985 { "tl_PH", NULL, N_("Tagalog"), "Tagalog", NULL },
986 { "af_ZA", NULL, N_("Afrikaans"), "Afrikaans", NULL },
987 { "jv_ID", NULL, N_("Javanese"), "Basa Jawa", NULL },
988 { "km_KH", NULL, N_("Khmer"), "ខ្មែរ", NULL },
989 { "fil", NULL, N_("Filipino"), "Filipino", NULL },
990 { "my", NULL, N_("Myanmar"), "ماينمار", NULL },
991 { "or", NULL, N_("Odia"), "ଓଡ଼ିଆ", NULL },
992 { "es_LA", NULL, N_("Spanish (Latin America)"), "Español (América Latina)", NULL },
994 { "", "", "", NULL, NULL }
1000 bool operator () (const __Language &lhs, const __Language &rhs) const {
1001 return strcmp (lhs.code, rhs.code) < 0;
1004 bool operator () (const __Language &lhs, const String &rhs) const {
1005 return strcmp (lhs.code, rhs.c_str ()) < 0;
1008 bool operator () (const String &lhs, const __Language &rhs) const {
1009 return strcmp (lhs.c_str (), rhs.code) < 0;
1013 static bool language_sorted = false;
1016 __find_language (const String &lang)
1018 if (!language_sorted) {
1019 language_sorted = true;
1020 for (int loop = 0; ((unsigned int)loop) < sizeof(__languages) / sizeof(__Language) - 1; loop++) {
1021 for (int innerLoop = loop + 1; ((unsigned int)innerLoop) < sizeof(__languages) / sizeof(__Language) - 1; innerLoop++) {
1022 if (strcmp (__languages[loop].code, __languages[innerLoop].code) > 0) {
1023 __Language temp = __languages[innerLoop];
1024 __languages[innerLoop] = __languages[loop];
1025 __languages[loop] = temp;
1031 static __Language *langs_begin = __languages;
1032 static __Language *langs_end = __languages + sizeof (__languages) / sizeof (__Language) - 1;
1034 String nlang = lang;
1035 bool contry_code = false;
1037 // Normalize the language name.
1038 for (String::iterator it = nlang.begin (); it != nlang.end (); ++it) {
1039 if (*it == '-' || *it == '_') {
1042 } else if (contry_code) {
1043 *it = toupper (*it);
1045 *it = tolower (*it);
1049 __Language *result = std::lower_bound (langs_begin, langs_end, nlang, __LanguageLess ());
1051 if (result != langs_end) {
1052 if (strncmp (result->code, nlang.c_str (), strlen (result->code)) == 0 ||
1053 (strncmp (result->code, nlang.c_str (), nlang.length ()) == 0 &&
1054 strncmp (result->code, (result+1)->code, nlang.length ()) != 0))
1062 scim_get_language_name (const String &lang)
1064 return String (_(scim_get_language_name_english (lang).c_str ()));
1068 scim_get_language_name_english (const String &lang)
1070 __Language *result = __find_language (lang);
1073 return String (result->name);
1075 return String ("Other");
1079 scim_get_language_name_untranslated (const String &lang)
1081 __Language *result = __find_language (lang);
1084 if (result->untranslated)
1085 return String (result->untranslated);
1087 return String (_(result->name));
1090 return String (_("Other"));
1094 scim_get_language_locales (const String &lang)
1096 __Language *result = __find_language (lang);
1098 std::vector<String> locales;
1103 if (strlen (result->code) < 5 && result->normalized)
1104 result = __find_language (result->normalized);
1107 good = scim_validate_locale (String (result->code) + ".UTF-8");
1109 if (good.length ()) locales.push_back (good);
1111 if (result && result->locale_suffix) {
1112 std::vector<String> suffixes;
1114 scim_split_string_list (suffixes, result->locale_suffix, ',');
1115 for (size_t i = 0; i < suffixes.size (); ++ i) {
1116 good = scim_validate_locale (String (result->code) + suffixes [i]);
1117 if (good.length ()) locales.push_back (good);
1122 good = scim_validate_locale (result->code);
1124 if (good.length ()) locales.push_back (good);
1127 return scim_combine_string_list (locales, ',');
1131 scim_get_locale_language (const String &locale)
1133 if (locale.length () == 0) return String ();
1135 String str = locale.substr (0, locale.find ('.'));
1136 return scim_validate_language (str.substr (0, str.find ('@')));
1140 scim_validate_language (const String &lang)
1142 __Language *result = __find_language (lang);
1145 return String (result->code);
1147 // Add prefix ~ to let other become the last item when sorting.
1148 return String ("~other");
1152 scim_get_normalized_language (const String &lang)
1154 __Language *result = __find_language (lang);
1157 if (result->normalized) return String (result->normalized);
1158 else return String (result->code);
1161 // Add prefix ~ to let other become the last item when sorting.
1162 //return String ("~other");
1163 return String ("en");
1166 #ifndef SCIM_LAUNCHER
1167 #define SCIM_LAUNCHER (SCIM_LIBEXECDIR "/scim-launcher")
1170 EXAPI int scim_launch (bool daemon,
1171 const String &config,
1172 const String &imengines,
1173 const String &frontend,
1174 char * const argv [])
1176 if (!config.length () || !imengines.length () || !frontend.length ())
1179 int i, new_argc = 0;
1180 char *new_argv [40];
1182 new_argv [new_argc ++] = strdup (SCIM_LAUNCHER);
1185 new_argv [new_argc ++] = strdup ("-d");
1187 new_argv [new_argc ++] = strdup ("-c");
1188 new_argv [new_argc ++] = strdup (config.c_str ());
1189 new_argv [new_argc ++] = strdup ("-e");
1190 new_argv [new_argc ++] = strdup (imengines.c_str ());
1191 new_argv [new_argc ++] = strdup ("-f");
1192 new_argv [new_argc ++] = strdup (frontend.c_str ());
1195 for (i = 0; argv [i] && new_argc < 39 ; ++i, ++new_argc)
1196 new_argv [new_argc] = strdup (argv [i]);
1199 new_argv [new_argc] = 0;
1203 child_pid = fork ();
1205 ISF_SAVE_LOG ("ppid: %d, fork result : %d, user %s\n", getppid (), child_pid, scim_get_user_name ().c_str ());
1208 if (child_pid < 0) {
1209 for (i = 0; i < new_argc; ++i) {
1211 free (new_argv [i]);
1212 new_argv [i] = NULL;
1218 // In child process, start scim-launcher.
1219 if (child_pid == 0) {
1220 int ret = execv (SCIM_LAUNCHER, new_argv);
1221 for (i = 0; i < new_argc; ++i) {
1223 free (new_argv [i]);
1224 new_argv [i] = NULL;
1230 // In parent process, wait the child exit.
1232 for (i = 0; i < new_argc; ++i) {
1234 free (new_argv [i]);
1235 new_argv [i] = NULL;
1242 ret_pid = waitpid (child_pid, &status, 0);
1244 if (ret_pid == child_pid && WIFEXITED(status))
1245 return WEXITSTATUS(status);
1250 #ifndef SCIM_PANEL_PROGRAM
1251 #define SCIM_PANEL_PROGRAM (SCIM_BINDIR "/scim-panel-gtk")
1254 EXAPI int scim_launch_panel (bool daemon,
1255 const String &config,
1256 const String &display,
1257 char * const argv [])
1259 if (!config.length ())
1262 String panel_program = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_PANEL_PROGRAM, String (SCIM_PANEL_PROGRAM));
1264 if (!panel_program.length ())
1265 panel_program = String (SCIM_PANEL_PROGRAM);
1267 if (panel_program [0] != SCIM_PATH_DELIM) {
1268 panel_program = String (SCIM_BINDIR) +
1269 String (SCIM_PATH_DELIM_STRING) +
1273 //if the file is not exist or is not executable, fallback to default
1274 if (access (panel_program.c_str (), X_OK) != 0)
1275 panel_program = String (SCIM_PANEL_PROGRAM);
1277 int i, new_argc = 0;
1278 char *new_argv [80];
1280 new_argv [new_argc ++] = strdup (panel_program.c_str ());
1282 if (display.length() > 0) {
1283 new_argv [new_argc ++] = strdup ("--display");
1284 new_argv [new_argc ++] = strdup (display.c_str ());
1287 new_argv [new_argc ++] = strdup ("-c");
1288 new_argv [new_argc ++] = strdup (config.c_str ());
1291 new_argv [new_argc ++] = strdup ("-d");
1294 for (i = 0; argv [i] && new_argc < 79; ++i, ++new_argc)
1295 new_argv [new_argc] = strdup (argv [i]);
1298 new_argv [new_argc] = 0;
1302 child_pid = fork ();
1304 ISF_SAVE_LOG ("ppid : %d fork result : %d\n", getppid (), child_pid);
1307 if (child_pid < 0) {
1308 for (i = 0; i < new_argc; ++i) {
1310 free (new_argv [i]);
1311 new_argv [i] = NULL;
1317 // In child process, start scim-launcher.
1318 if (child_pid == 0) {
1319 int ret = execv (panel_program.c_str (), new_argv);
1320 for (i = 0; i < new_argc; ++i) {
1322 free (new_argv [i]);
1323 new_argv [i] = NULL;
1329 // In parent process, wait the child exit.
1331 for (i = 0; i < new_argc; ++i) {
1333 free (new_argv [i]);
1334 new_argv [i] = NULL;
1341 ret_pid = waitpid (child_pid, &status, 0);
1343 if (ret_pid == child_pid && WIFEXITED(status))
1344 return WEXITSTATUS(status);
1350 scim_usleep (unsigned int usec)
1352 if (usec == 0) return;
1355 struct timespec req, rem;
1357 req.tv_sec = usec / 1000000;
1358 req.tv_nsec = ((unsigned long int)usec % 1000000) * 1000;
1360 while (nanosleep (&req, &rem) == -1 && errno == EINTR && (rem.tv_sec != 0 || rem.tv_nsec != 0))
1363 unsigned int sec = usec / 1000000;
1366 for (unsigned int i = 0; i < sec; ++i)
1371 unsigned int sec = usec / 1000000;
1373 sleep (sec ? sec : 1);
1377 EXAPI void scim_daemon ()
1380 LOGD ("ppid:%d calling daemon()\n", getppid ());
1382 if (daemon (0, 0) == -1)
1383 std::cerr << "Error to make SCIM into a daemon!\n";
1385 LOGD ("ppid:%d daemon() called\n", getppid ());
1393 std::cerr << "Error to make SCIM into a daemon!\n";
1395 } else if (id > 0) {
1399 ISF_SAVE_LOG ("ppid:%d fork result : %d\n", getppid (), id);
1403 std::cerr << "Error to make SCIM into a daemon!\n";
1405 } else if (id > 0) {
1409 ISF_SAVE_LOG ("ppid:%d fork result : %d\n", getppid (), id);
1415 EXAPI void isf_save_log (const char *fmt, ...)
1417 char buf[1024] = {0};
1421 vsnprintf (buf, sizeof (buf), fmt, ap);
1424 const int MAX_LOG_FILE_SIZE = 12 * 1024; /* 12KB */
1426 static bool size_exceeded = false;
1427 static struct stat st;
1428 if (!size_exceeded) {
1429 String strLogFile = scim_get_user_data_dir () + String (SCIM_PATH_DELIM_STRING) + String ("isf.log");
1430 int ret = stat(strLogFile.c_str(), &st);
1431 if (ret == 0 || (ret == -1 && errno == ENOENT)) {
1432 if (st.st_size < MAX_LOG_FILE_SIZE) {
1433 std::ofstream isf_log_file (strLogFile.c_str (), std::ios::app);
1434 isf_log_file << buf;
1435 isf_log_file.flush ();
1437 size_exceeded = true;
1445 static struct timeval _t0 = {0, 0};
1446 static struct timeval _t1;
1448 static clock_t _p_t0;
1449 static clock_t _p_t1;
1451 void ISF_PROF_DEBUG_TIME_BEGIN ()
1455 _p_t0 = times (&tms);
1458 /* Measure elapsed time */
1459 void ISF_PROF_DEBUG_TIME_END (char const* format, char const* func, int line)
1463 static long clktck = 0;
1466 if ((clktck = sysconf (_SC_CLK_TCK)) < 0)
1469 _p_t1 = times (&tms);
1471 etime = (_p_t1 - _p_t0) / (double) clktck;
1473 printf (format, func, line);
1474 printf (mzc_red "[T:%ld][E:%f]" mzc_normal " ", _p_t1, etime);
1479 /* Measure elapsed time */
1480 void ISF_PROF_DEBUG_TIME (char const* func, int line, char const* str)
1484 if (_t0.tv_sec == 0 && _t0.tv_usec == 0) {
1485 gettimeofday (&_t0, NULL);
1489 gettimeofday (&_t1, NULL);
1491 if (_t0.tv_usec != 0) {
1492 etime = ((_t1.tv_sec * 1000000 + _t1.tv_usec) - (_t0.tv_sec * 1000000 + _t0.tv_usec))/1000000.0;
1495 printf (mzc_red "[%s:%04d] [T:%ld][E:%f] %s " mzc_normal " \n", func, line, (_t1.tv_sec * 1000000 + _t1.tv_usec), etime, str);
1502 EXAPI void gettime (clock_t clock_start, const char* str)
1505 struct tms tiks_buf;
1506 double clock_tiks = (double)sysconf (_SC_CLK_TCK);
1507 clock_t times_tiks = times (&tiks_buf);
1508 double times_secs = (double)(times_tiks - clock_start) / clock_tiks;
1509 double utime = (double)tiks_buf.tms_utime / clock_tiks;
1510 double stime = (double)tiks_buf.tms_stime / clock_tiks;
1511 printf (mzc_red "%s Times: %.3f \t User: %.3f \t System: %.3f " mzc_normal "\n", str, (double)times_secs, (double)utime , (double)stime);
1518 vi:ts=4:ai:nowrap:expandtab