2
* Smart Common Input Method
4
* Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2 of the License, or (at your option) any later version.
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this program; if not, write to the
19
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20
* Boston, MA 02111-1307 USA
22
* $Id: scim_utility.cpp,v 1.48.2.5 2006/11/02 04:11:51 suzhe Exp $
25
#define Uses_SCIM_UTILITY
26
#define Uses_SCIM_CONFIG_PATH
36
#include <sys/types.h>
44
#include "scim_private.h"
50
utf8_mbtowc (ucs4_t *pwc, const unsigned char *src, int src_len)
55
unsigned char c = src [0];
60
} else if (c < 0xc2) {
62
} else if (c < 0xe0) {
65
if (!((src [1] ^ 0x80) < 0x40))
67
*pwc = ((ucs4_t) (c & 0x1f) << 6)
68
| (ucs4_t) (src [1] ^ 0x80);
70
} else if (c < 0xf0) {
73
if (!((src [1] ^ 0x80) < 0x40 && (src [2] ^ 0x80) < 0x40
74
&& (c >= 0xe1 || src [1] >= 0xa0)))
76
*pwc = ((ucs4_t) (c & 0x0f) << 12)
77
| ((ucs4_t) (src [1] ^ 0x80) << 6)
78
| (ucs4_t) (src [2] ^ 0x80);
80
} else if (c < 0xf8) {
83
if (!((src [1] ^ 0x80) < 0x40 && (src [2] ^ 0x80) < 0x40
84
&& (src [3] ^ 0x80) < 0x40
85
&& (c >= 0xf1 || src [1] >= 0x90)))
87
*pwc = ((ucs4_t) (c & 0x07) << 18)
88
| ((ucs4_t) (src [1] ^ 0x80) << 12)
89
| ((ucs4_t) (src [2] ^ 0x80) << 6)
90
| (ucs4_t) (src [3] ^ 0x80);
92
} else if (c < 0xfc) {
95
if (!((src [1] ^ 0x80) < 0x40 && (src [2] ^ 0x80) < 0x40
96
&& (src [3] ^ 0x80) < 0x40 && (src [4] ^ 0x80) < 0x40
97
&& (c >= 0xf9 || src [1] >= 0x88)))
99
*pwc = ((ucs4_t) (c & 0x03) << 24)
100
| ((ucs4_t) (src [1] ^ 0x80) << 18)
101
| ((ucs4_t) (src [2] ^ 0x80) << 12)
102
| ((ucs4_t) (src [3] ^ 0x80) << 6)
103
| (ucs4_t) (src [4] ^ 0x80);
105
} else if (c < 0xfe) {
107
return RET_TOOFEW(0);
108
if (!((src [1] ^ 0x80) < 0x40 && (src [2] ^ 0x80) < 0x40
109
&& (src [3] ^ 0x80) < 0x40 && (src [4] ^ 0x80) < 0x40
110
&& (src [5] ^ 0x80) < 0x40
111
&& (c >= 0xfd || src [1] >= 0x84)))
113
*pwc = ((ucs4_t) (c & 0x01) << 30)
114
| ((ucs4_t) (src [1] ^ 0x80) << 24)
115
| ((ucs4_t) (src [2] ^ 0x80) << 18)
116
| ((ucs4_t) (src [3] ^ 0x80) << 12)
117
| ((ucs4_t) (src [4] ^ 0x80) << 6)
118
| (ucs4_t) (src [5] ^ 0x80);
125
utf8_wctomb (unsigned char *dest, ucs4_t wc, int dest_size)
135
else if (wc < 0x10000)
137
else if (wc < 0x200000)
139
else if (wc < 0x4000000)
141
else if (wc <= 0x7fffffff)
145
if (dest_size < count)
147
switch (count) { /* note: code falls through cases! */
148
case 6: dest [5] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x4000000;
149
case 5: dest [4] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x200000;
150
case 4: dest [3] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x10000;
151
case 3: dest [2] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0x800;
152
case 2: dest [1] = 0x80 | (wc & 0x3f); wc = wc >> 6; wc |= 0xc0;
153
case 1: dest [0] = wc;
159
utf8_read_wchar (std::istream &is)
161
unsigned char utf8[6];
164
for (int i=0; i<6; ++i) {
165
is.read ((char*)(utf8+i), sizeof(unsigned char));
166
if ((count=utf8_mbtowc (&wc, utf8, i+1)) > 0)
168
if (count == RET_ILSEQ)
175
utf8_read_wstring (std::istream &is, ucs4_t delim, bool rm_delim)
179
while ((wc = utf8_read_wchar (is)) > 0) {
192
utf8_write_wchar (std::ostream &os, ucs4_t wc)
194
unsigned char utf8[6];
197
if ((count=utf8_wctomb (utf8, wc, 6)) > 0)
198
os.write ((char*)utf8, count * sizeof (unsigned char));
204
utf8_write_wstring (std::ostream &os, const WideString & wstr)
206
for (unsigned int i=0; i<wstr.size (); ++i)
207
utf8_write_wchar (os, wstr [i]);
213
utf8_mbstowcs (const String & str)
220
const unsigned char *s = (const unsigned char *) str.c_str ();
222
while (sn < str.length () && *s != 0 &&
223
(un=utf8_mbtowc (&wc, s, str.length () - sn)) > 0) {
232
utf8_mbstowcs (const char *str, int len)
241
if (len < 0) len = strlen (str);
243
while (sn < len && *str != 0 && (un=utf8_mbtowc (&wc, (const unsigned char *)str, len - sn)) > 0) {
254
utf8_wcstombs (const WideString & wstr)
260
for (unsigned int i = 0; i<wstr.size (); ++i) {
261
un = utf8_wctomb ((unsigned char*)utf8, wstr [i], 6);
263
str.append (utf8, un);
269
utf8_wcstombs (const ucs4_t *wstr, int len)
277
for (len = 0; wstr [len]; ++len) NULL;
279
for (int i = 0; i < len; ++i) {
280
un = utf8_wctomb ((unsigned char*)utf8, wstr [i], 6);
282
str.append (utf8, un);
289
scim_validate_locale (const String& locale)
293
String last = String (setlocale (LC_CTYPE, 0));
295
if (setlocale (LC_CTYPE, locale.c_str ())) {
298
std::vector<String> vec;
299
if (scim_split_string_list (vec, locale, '.') == 2) {
300
if (isupper (vec[1][0])) {
301
for (String::iterator i=vec[1].begin (); i!=vec[1].end (); ++i)
302
*i = (char) tolower (*i);
304
for (String::iterator i=vec[1].begin (); i!=vec[1].end (); ++i)
305
*i = (char) toupper (*i);
307
if (setlocale (LC_CTYPE, (vec[0] + "." + vec[1]).c_str ())) {
308
good = vec [0] + "." + vec[1];
313
setlocale (LC_CTYPE, last.c_str ());
319
scim_get_locale_encoding (const String& locale)
321
String last = String (setlocale (LC_CTYPE, 0));
324
if (setlocale (LC_CTYPE, locale.c_str ()))
325
encoding = String (nl_langinfo (CODESET));
327
std::vector<String> vec;
328
if (scim_split_string_list (vec, locale, '.') == 2) {
329
if (isupper (vec[1][0])) {
330
for (String::iterator i=vec[1].begin (); i!=vec[1].end (); ++i)
331
*i = (char) tolower (*i);
333
for (String::iterator i=vec[1].begin (); i!=vec[1].end (); ++i)
334
*i = (char) toupper (*i);
336
if (setlocale (LC_CTYPE, (vec[0] + "." + vec[1]).c_str ()))
337
encoding = String (nl_langinfo (CODESET));
342
setlocale (LC_CTYPE, last.c_str ());
348
scim_get_locale_maxlen (const String& locale)
352
String last = String (setlocale (LC_CTYPE, 0));
354
if (setlocale (LC_CTYPE, locale.c_str ()))
359
setlocale (LC_CTYPE, last.c_str ());
364
scim_split_string_list (std::vector<String>& vec, const String& str, char delim)
369
String::const_iterator bg, ed;
376
while (bg != str.end () && ed != str.end ()) {
377
for (; ed != str.end (); ++ed) {
381
temp.assign (bg, ed);
382
vec.push_back (temp);
385
if (ed != str.end ())
392
scim_combine_string_list (const std::vector<String>& vec, char delim)
395
for (std::vector<String>::const_iterator i = vec.begin (); i!=vec.end (); ++i) {
397
if (i+1 != vec.end ())
404
scim_if_wchar_ucs4_equal ()
406
if (sizeof (wchar_t) != sizeof (ucs4_t))
410
wchar_t wcbuf [2] = {0,0};
411
ucs4_t ucsbuf [2] = {0x4E00, 0x0001};
412
size_t wclen = 2 * sizeof (wchar_t);
413
size_t ucslen = 2 * sizeof (ucs4_t);
415
char *wcp = (char *) wcbuf;
416
ICONV_CONST char *ucsp = (ICONV_CONST char *) ucsbuf;
418
if (scim_is_little_endian ())
419
cd = iconv_open ("UCS-4LE", "wchar_t");
421
cd = iconv_open ("UCS-4BE", "wchar_t");
423
if (cd == (iconv_t) -1)
426
iconv (cd, &ucsp, &ucslen, &wcp, &wclen);
430
if (wcbuf [0] == (wchar_t) ucsbuf [0] &&
431
wcbuf [1] == (wchar_t) ucsbuf [1])
441
} __half_full_table [] = {
443
{0x0021, 0xFF01, 0x5E},
496
{0xFFA1, 0x3131, 30},
508
* convert a half width unicode char to full width char
511
scim_wchar_to_full_width (ucs4_t code)
514
while (__half_full_table [i].size) {
515
if (code >= __half_full_table [i].half &&
516
code < __half_full_table [i].half +
517
__half_full_table [i].size)
518
return __half_full_table [i].full +
519
(code - __half_full_table [i].half);
526
* convert a full width unicode char to half width char
529
scim_wchar_to_half_width (ucs4_t code)
532
while (__half_full_table [i].size) {
533
if (code >= __half_full_table [i].full &&
534
code < __half_full_table [i].full +
535
__half_full_table [i].size)
536
return __half_full_table [i].half +
537
(code - __half_full_table [i].full);
546
const char * home_dir = 0;
550
home_dir = getenv ("SCIM_HOME");
551
if (home_dir && *home_dir) {
552
return String (home_dir);
556
pw = getpwuid (getuid ());
560
home_dir = pw->pw_dir;
564
home_dir = getenv ("HOME");
567
return String (home_dir);
571
scim_get_user_name ()
574
const char *user_name;
576
user_name = getenv ("SCIM_USER");
577
if (user_name && *user_name) {
578
return String (user_name);
582
pw = getpwuid (getuid ());
585
if (pw && pw->pw_name)
586
return String (pw->pw_name);
587
else if ((user_name = getenv ("USER")) != NULL)
588
return String (user_name);
592
snprintf (uid_str, 10, "%u", getuid ());
594
return String (uid_str);
598
scim_get_user_data_dir ()
600
String dir = scim_get_home_dir () + String ("/.scim");
606
scim_get_current_locale ()
608
char *locale = setlocale (LC_MESSAGES, 0);
610
if (locale) return String (locale);
614
String scim_get_current_language ()
616
return scim_get_locale_language (scim_get_current_locale ());
620
scim_is_little_endian ()
623
return (*((char *)&endian) != 0);
627
scim_load_file (const String &filename, char **bufptr)
629
if (!filename.length ())
634
if (stat (filename.c_str (), &statbuf) < 0 ||
635
!S_ISREG (statbuf.st_mode) ||
640
return statbuf.st_size;
642
FILE *fp = fopen (filename.c_str (), "r");
650
*bufptr = new char [statbuf.st_size];
661
size_t size = fread (*bufptr, 1, statbuf.st_size, fp);
674
scim_make_dir (const String &dir)
676
std::vector <String> paths;
679
scim_split_string_list (paths, dir, SCIM_PATH_DELIM);
681
for (size_t i = 0; i < paths.size (); ++i) {
682
path += SCIM_PATH_DELIM_STRING + paths [i];
684
//Make the dir if it's not exist.
685
if (access (path.c_str (), R_OK) != 0) {
686
mkdir (path.c_str (), S_IRUSR | S_IWUSR | S_IXUSR);
687
if (access (path.c_str (), R_OK) != 0)
696
const char *normalized;
698
const char *untranslated;
699
const char *locale_suffix;
702
static __Language __languages [] = {
703
{ "C", NULL, N_("English/Keyboard"), NULL, NULL},
704
{ "am_ET", NULL, N_("Amharic"), NULL, NULL },
705
{ "ar", "ar_EG", N_("Arabic"), NULL, NULL },
706
{ "ar_EG", NULL, N_("Arabic (Egypt)"), NULL, NULL },
707
{ "ar_LB", NULL, N_("Arabic (Lebanon)"), NULL, NULL },
708
{ "as_IN", NULL, N_("Assamese"), NULL, NULL},
709
{ "az_AZ", NULL, N_("Azerbaijani"), NULL, NULL },
710
{ "be_BY", NULL, N_("Belarusian"), "Беларуская мова", NULL },
711
{ "bg_BG", NULL, N_("Bulgarian"), "Български", NULL },
712
{ "bn", "bn_BD", N_("Bengali"), "বাংলা", NULL },
713
{ "bn_BD", NULL, N_("Bengali"), "বাংলা", NULL },
714
{ "bn_IN", NULL, N_("Bengali (India)"), "বাংলা", NULL },
715
{ "bo", NULL, N_("Tibetan"), NULL, NULL },
716
{ "bs_BA", NULL, N_("Bosnian"), NULL, NULL },
717
{ "ca_ES", NULL, N_("Catalan"), "Català", "@euro" },
718
{ "cs_CZ", NULL, N_("Czech"), "čeština", NULL },
719
{ "cy_GB", NULL, N_("Welsh"), "Cymraeg", NULL },
720
{ "da_DK", NULL, N_("Danish"), "dansk", "@euro" },
721
{ "de_DE", NULL, N_("German"), "Deutsch", "@euro" },
722
{ "dv_MV", NULL, N_("Divehi"), "ދިވެހިބަސް", NULL },
723
{ "el_GR", NULL, N_("Greek"), "ελληνικά", NULL },
724
{ "en" , "en_US", N_("English"), "English", NULL },
725
{ "en_AU", NULL, N_("English (Australian)"), "Australian English", NULL },
726
{ "en_CA", NULL, N_("English (Canadian)"), "Canadian English", NULL },
727
{ "en_GB", NULL, N_("English (British)"), "British English", ".iso885915" },
728
{ "en_IE", NULL, N_("English (Ireland)"), "Irish English", NULL },
729
{ "en_US", NULL, N_("English (American)"), "American English", ".iso885915" },
730
{ "eo", NULL, N_("Esperanto"), "Esperanto", NULL },
731
{ "es", "es_ES", N_("Spanish"), "Español", NULL },
732
{ "es_ES", NULL, N_("Spanish"), "Español", "@euro" },
733
{ "es_MX", NULL, N_("Spanish (Mexico)"), "Español (Mexico)", NULL },
734
{ "et_EE", NULL, N_("Estonian"), "Eesti", ".iso885915" },
735
{ "eu_ES", NULL, N_("Basque"), "Euskara", "@euro" },
736
{ "fa_IR", NULL, N_("Persian"), "فارسی", NULL },
737
{ "fi_FI", NULL, N_("Finnish"), "Suomi", "@euro" },
738
{ "fr_FR", NULL, N_("French"), "Français", "@euro" },
739
{ "ga_IE", NULL, N_("Irish"), "Gaeilge", "@euro" },
740
{ "gl_ES", NULL, N_("Galician"), "Galego", "@euro" },
741
{ "gu_IN", NULL, N_("Gujarati"), NULL, NULL },
742
{ "he_IL", NULL, N_("Hebrew"), "עברית", NULL },
743
{ "hi_IN", NULL, N_("Hindi"), "हिंदी", NULL },
744
{ "hr_HR", NULL, N_("Croatian"), "Hrvatski", NULL },
745
{ "hu_HU", NULL, N_("Hungarian"), "Magyar", NULL },
746
{ "hy_AM", NULL, N_("Armenian"), "Հայերէն", NULL },
747
{ "ia" , NULL, N_("Interlingua"), NULL },
748
{ "id_ID", NULL, N_("Indonesian"), "Bahasa Indonesia", NULL },
749
{ "is_IS", NULL, N_("Icelandic"), NULL, NULL },
750
{ "it_IT", NULL, N_("Italian"), "Italiano", "@euro" },
751
{ "iw_IL", NULL, N_("Hebrew"), "עברית", NULL },
752
{ "ja_JP", NULL, N_("Japanese"), "日本語", ".EUC-JP,.SJIS,.eucJP" },
753
{ "ka_GE", NULL, N_("Georgian"), "ქართული", NULL },
754
{ "kk_KZ", NULL, N_("Kazakh"), NULL, NULL },
755
{ "km", NULL, N_("Cambodian"), NULL, NULL },
756
{ "kn_IN", NULL, N_("Kannada"), "ಕನ್ನಡ", NULL },
757
{ "ko_KR", NULL, N_("Korean"), "한국어", ".EUC-KR,.eucKR" },
758
{ "lo_LA", NULL, N_("Laothian"), NULL, NULL },
759
{ "lt_LT", NULL, N_("Lithuanian"), "Lietuvių", NULL },
760
{ "lv_LV", NULL, N_("Latvian"), "Latviešu", NULL },
761
{ "mk_MK", NULL, N_("Macedonian"), NULL, NULL },
762
{ "ml_IN", NULL, N_("Malayalam"), "മലയാളം", NULL },
763
{ "mn_MN", NULL, N_("Mongolian"), "Монгол", NULL },
764
{ "mr_IN", NULL, N_("Marathi"), NULL, NULL },
765
{ "ms_MY", NULL, N_("Malay"), "Bahasa Melayu", NULL },
766
{ "my_MM", NULL, N_("Burmese"), "", NULL },
767
{ "ne_NP", NULL, N_("Nepali"), NULL, NULL },
768
{ "nl_NL", NULL, N_("Dutch"), "Nederlands", "@euro" },
769
{ "nn_NO", NULL, N_("Norwegian (nynorsk)"), "Norsk (nynorsk)", NULL },
770
{ "no_NO", NULL, N_("Norwegian (bokmal)"), "Norsk (bokmål)", NULL },
771
{ "or_IN", NULL, N_("Oriya"), NULL, NULL },
772
{ "pa_IN", NULL, N_("Punjabi"), NULL, NULL },
773
{ "pl_PL", NULL, N_("Polish"), "Polski", NULL },
774
{ "pt", "pt_PT", N_("Portuguese"), "Português", NULL },
775
{ "pt_BR", NULL, N_("Portuguese (Brazil)"), "Português do Brasil", NULL },
776
{ "pt_PT", NULL, N_("Portuguese"), "Português", "@euro" },
777
{ "ro_RO", NULL, N_("Romanian"), "Română", NULL },
778
{ "ru_RU", NULL, N_("Russian"), "русский", ".koi8r" },
779
{ "si_LK", NULL, N_("Sinhala"), "සිංහල", NULL },
780
{ "sk_SK", NULL, N_("Slovak"), "Slovenský", NULL },
781
{ "sl_SI", NULL, N_("Slovenian"), "Slovenščina", NULL },
782
{ "sq_AL", NULL, N_("Albanian"), "Shqip", NULL },
783
{ "sr", "sr_YU", N_("Serbian"), "српски", NULL },
784
{ "sr_CS", NULL, N_("Serbian"), "српски", NULL },
785
{ "sr_YU", NULL, N_("Serbian"), "српски", "@cyrillic" },
786
{ "sv", "sv_SE", N_("Swedish"), "Svenska", NULL },
787
{ "sv_FI", NULL, N_("Swedish (Finland)"), "Svenska (Finland)", "@euro" },
788
{ "sv_SE", NULL, N_("Swedish"), "Svenska", ".iso885915" },
789
{ "ta_IN", NULL, N_("Tamil"), NULL, NULL },
790
{ "te_IN", NULL, N_("Telugu"), NULL, NULL },
791
{ "th_TH", NULL, N_("Thai"), "ไทย", NULL },
792
{ "tr_TR", NULL, N_("Turkish"), "Türkçe", NULL },
793
{ "ug", NULL, N_("Uighur"), NULL, NULL },
794
{ "uk_UA", NULL, N_("Ukrainian"), "Українська", NULL },
795
{ "ur_PK", NULL, N_("Urdu"), NULL, NULL },
796
{ "uz_UZ", NULL, N_("Uzbek"), NULL, "@cyrillic" },
797
{ "vi_VN", NULL, N_("Vietnamese"), "Việt Nam", ".tcvn" },
798
{ "wa_BE", NULL, N_("Walloon"), "Walon", "@euro" },
799
{ "yi" , "yi_US", N_("Yiddish"), "ייִדיש", NULL },
800
{ "yi_US", NULL, N_("Yiddish"), "ייִדיש", NULL },
801
{ "zh", "zh_CN", N_("Chinese"), "中文", NULL },
802
{ "zh_CN", NULL, N_("Chinese (simplified)"), "中文 (简体)", ".GB18030,.GBK,.GB2312,.eucCN" },
803
{ "zh_HK", "zh_TW", N_("Chinese (traditional)"), "中文 (繁體)", NULL },
804
{ "zh_SG", "zh_CN", N_("Chinese (simplified)"), "中文 (简体)", ".GBK" },
805
{ "zh_TW", NULL, N_("Chinese (traditional)"), "中文 (繁體)", ".eucTW" },
806
{ "", "", "", NULL, NULL }
812
bool operator () (const __Language &lhs, const __Language &rhs) const {
813
return strcmp (lhs.code, rhs.code) < 0;
816
bool operator () (const __Language &lhs, const String &rhs) const {
817
return strcmp (lhs.code, rhs.c_str ()) < 0;
820
bool operator () (const String &lhs, const __Language &rhs) const {
821
return strcmp (lhs.c_str (), rhs.code) < 0;
826
__find_language (const String &lang)
828
static __Language *langs_begin = __languages;
829
static __Language *langs_end = __languages + sizeof (__languages) / sizeof (__Language) - 1;
832
bool contry_code = false;
834
// Normalize the language name.
835
for (String::iterator it = nlang.begin (); it != nlang.end (); ++it) {
836
if (*it == '-' || *it == '_') {
839
} else if (contry_code) {
846
__Language *result = std::lower_bound (langs_begin, langs_end, nlang, __LanguageLess ());
848
if (result != langs_end) {
849
if (strncmp (result->code, nlang.c_str (), strlen (result->code)) == 0 ||
850
(strncmp (result->code, nlang.c_str (), nlang.length ()) == 0 &&
851
strncmp (result->code, (result+1)->code, nlang.length ()) != 0))
859
scim_get_language_name (const String &lang)
861
return String (_(scim_get_language_name_english (lang).c_str ()));
865
scim_get_language_name_english (const String &lang)
867
__Language *result = __find_language (lang);
870
return String (result->name);
872
return String ("Other");
876
scim_get_language_name_untranslated (const String &lang)
878
__Language *result = __find_language (lang);
881
if (result->untranslated)
882
return String (result->untranslated);
884
return String (_(result->name));
887
return String (_("Other"));
891
scim_get_language_locales (const String &lang)
893
__Language *result = __find_language (lang);
895
std::vector<String> locales;
900
if (strlen (result->code) < 5 && result->normalized)
901
result = __find_language (result->normalized);
903
good = scim_validate_locale (String (result->code) + ".UTF-8");
905
if (good.length ()) locales.push_back (good);
907
if (result->locale_suffix) {
908
std::vector<String> suffixes;
910
scim_split_string_list (suffixes, result->locale_suffix, ',');
911
for (size_t i = 0; i < suffixes.size (); ++ i) {
912
good = scim_validate_locale (String (result->code) + suffixes [i]);
913
if (good.length ()) locales.push_back (good);
917
good = scim_validate_locale (result->code);
919
if (good.length ()) locales.push_back (good);
922
return scim_combine_string_list (locales, ',');
926
scim_get_locale_language (const String &locale)
928
if (locale.length () == 0) return String ();
930
String str = locale.substr (0, locale.find ('.'));
931
return scim_validate_language (str.substr (0, str.find ('@')));
935
scim_validate_language (const String &lang)
937
__Language *result = __find_language (lang);
940
return String (result->code);
942
// Add prefix ~ to let other become the last item when sorting.
943
return String ("~other");
947
scim_get_normalized_language (const String &lang)
949
__Language *result = __find_language (lang);
952
if (result->normalized) return String (result->normalized);
953
else return String (result->code);
956
// Add prefix ~ to let other become the last item when sorting.
957
return String ("~other");
960
#ifndef SCIM_LAUNCHER
961
#define SCIM_LAUNCHER (SCIM_LIBEXECDIR "/scim-launcher")
964
int scim_launch (bool daemon,
965
const String &config,
966
const String &imengines,
967
const String &frontend,
968
char * const argv [])
970
if (!config.length () || !imengines.length () || !frontend.length ())
975
char verbose_buf [10];
977
new_argv [new_argc ++] = strdup (SCIM_LAUNCHER);
980
new_argv [new_argc ++] = strdup ("-d");
982
new_argv [new_argc ++] = strdup ("-c");
983
new_argv [new_argc ++] = strdup (config.c_str ());
984
new_argv [new_argc ++] = strdup ("-e");
985
new_argv [new_argc ++] = strdup (imengines.c_str ());
986
new_argv [new_argc ++] = strdup ("-f");
987
new_argv [new_argc ++] = strdup (frontend.c_str ());
990
for (int i = 0; argv [i] && new_argc < 40 ; ++i, ++new_argc)
991
new_argv [new_argc] = strdup (argv [i]);
994
new_argv [new_argc] = 0;
1001
if (child_pid < 0) return -1;
1003
// In child process, start scim-launcher.
1004
if (child_pid == 0) {
1005
return execv (SCIM_LAUNCHER, new_argv);
1008
// In parent process, wait the child exit.
1010
for (int i = 0; i < new_argc; ++i)
1011
if (new_argv [i]) free (new_argv [i]);
1016
ret_pid = waitpid (child_pid, &status, 0);
1018
if (ret_pid == child_pid && WIFEXITED(status))
1019
return WEXITSTATUS(status);
1024
#ifndef SCIM_PANEL_PROGRAM
1025
#define SCIM_PANEL_PROGRAM (SCIM_LIBEXECDIR "/scim-panel-gtk")
1028
int scim_launch_panel (bool daemon,
1029
const String &config,
1030
const String &display,
1031
char * const argv [])
1033
if (!config.length ())
1036
String panel_program = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_PANEL_PROGRAM, String (SCIM_PANEL_PROGRAM));
1038
if (!panel_program.length ())
1039
panel_program = String (SCIM_PANEL_PROGRAM);
1041
if (panel_program [0] != SCIM_PATH_DELIM) {
1042
panel_program = String (SCIM_LIBEXECDIR) +
1043
String (SCIM_PATH_DELIM_STRING) +
1047
//if the file is not exist or is not executable, fallback to default
1048
if (access (panel_program.c_str (), X_OK) != 0)
1049
panel_program = String (SCIM_PANEL_PROGRAM);
1052
char *new_argv [80];
1054
new_argv [new_argc ++] = strdup (panel_program.c_str ());
1056
new_argv [new_argc ++] = strdup ("--display");
1057
new_argv [new_argc ++] = strdup (display.c_str ());
1059
new_argv [new_argc ++] = strdup ("-c");
1060
new_argv [new_argc ++] = strdup (config.c_str ());
1063
new_argv [new_argc ++] = strdup ("-d");
1066
for (int i = 0; argv [i] && new_argc < 40; ++i, ++new_argc)
1067
new_argv [new_argc] = strdup (argv [i]);
1070
new_argv [new_argc] = 0;
1074
child_pid = fork ();
1077
if (child_pid < 0) return -1;
1079
// In child process, start scim-launcher.
1080
if (child_pid == 0) {
1081
return execv (panel_program.c_str (), new_argv);
1084
// In parent process, wait the child exit.
1086
for (int i = 0; i < new_argc; ++i)
1087
if (new_argv [i]) free (new_argv [i]);
1092
ret_pid = waitpid (child_pid, &status, 0);
1094
if (ret_pid == child_pid && WIFEXITED(status))
1095
return WEXITSTATUS(status);
1101
scim_usleep (unsigned int usec)
1103
if (usec == 0) return;
1106
struct timespec req, rem;
1108
req.tv_sec = usec / 1000000;
1109
req.tv_nsec = (usec % 1000000) * 1000;
1111
while (nanosleep (&req, &rem) == -1 && errno == EINTR && (rem.tv_sec != 0 || rem.tv_nsec != 0))
1114
unsigned int sec = usec / 1000000;
1117
for (unsigned int i = 0; i < sec; ++i)
1122
unsigned int sec = usec / 1000000;
1124
sleep (sec ? sec : 1);
1131
if (daemon (0, 0) == -1)
1132
std::cerr << "Error to make SCIM into a daemon!\n";
1140
std::cerr << "Error to make SCIM into a daemon!\n";
1142
} else if (id > 0) {
1148
std::cerr << "Error to make SCIM into a daemon!\n";
1150
} else if (id > 0) {
1161
vi:ts=4:ai:nowrap:expandtab