1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  *  Copyright (C) 2005 Takuro Ashie
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19 
20 #include <string.h>
21 #include <sys/wait.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 
25 #include "scim_anthy_utils.h"
26 #include "scim_anthy_default_tables.h"
27 
28 namespace scim_anthy {
29 
30 bool
util_match_key_event(const KeyEventList & list,const KeyEvent & key,uint16 ignore_mask)31 util_match_key_event (const KeyEventList &list, const KeyEvent &key,
32                       uint16 ignore_mask)
33 {
34     KeyEventList::const_iterator kit;
35 
36     for (kit = list.begin (); kit != list.end (); kit++) {
37         uint16 mod1, mod2;
38 
39         mod1 = kit->mask;
40         mod2 = key.mask;
41         mod1 &= ~ignore_mask;
42         mod2 &= ~ignore_mask;
43 
44         if (key.code == kit->code && mod1 == mod2)
45              return true;
46     }
47     return false;
48 }
49 
50 void
util_split_string(String & str,std::vector<String> & str_list,char * delim,int num)51 util_split_string (String &str, std::vector<String> &str_list,
52                    char *delim, int num)
53 {
54     String::size_type start = 0, end;
55 
56     for (int i = 0; (num > 0 && i < num) || start < str.length (); i++) {
57         end = str.find (delim, start);
58         if ((num > 0 && i == num - 1) || (end == String::npos))
59             end = str.length ();
60 
61         if (start < str.length ()) {
62             str_list.push_back (str.substr (start, end - start));
63             start = end + strlen (delim);
64         } else {
65             str_list.push_back (String ());
66         }
67     }
68 }
69 
70 void
util_convert_to_wide(WideString & wide,const String & str)71 util_convert_to_wide (WideString & wide, const String & str)
72 {
73     if (str.length () < 0)
74         return;
75 
76     for (unsigned int i = 0; i < str.length (); i++) {
77         int c = str[i];
78         char cc[2]; cc[0] = c; cc[1] = '\0';
79         bool found = false;
80 
81         for (unsigned int j = 0; scim_anthy_wide_table[j].code; j++) {
82             if ( scim_anthy_wide_table[j].code &&
83                 *scim_anthy_wide_table[j].code == c)
84             {
85                 wide += utf8_mbstowcs (scim_anthy_wide_table[j].wide);
86                 found = true;
87                 break;
88             }
89         }
90 
91         if (!found)
92             wide += utf8_mbstowcs (cc);
93     }
94 }
95 
96 void
util_convert_to_half(String & half,const WideString & str)97 util_convert_to_half (String & half, const WideString & str)
98 {
99     if (str.length () < 0)
100         return;
101 
102     for (unsigned int i = 0; i < str.length (); i++) {
103         WideString wide = str.substr (i, 1);
104         bool found = false;
105 
106         for (unsigned int j = 0; scim_anthy_wide_table[j].code; j++) {
107             if (scim_anthy_wide_table[j].wide &&
108                 wide == utf8_mbstowcs (scim_anthy_wide_table[j].wide))
109             {
110                 half += scim_anthy_wide_table[j].code;
111                 found = true;
112                 break;
113             }
114         }
115 
116         if (!found)
117             half += utf8_wcstombs (wide);
118     }
119 }
120 
121 void
util_convert_to_katakana(WideString & kata,const WideString & hira,bool half)122 util_convert_to_katakana (WideString & kata,
123                           const WideString & hira,
124                           bool half)
125 {
126     if (hira.length () < 0)
127         return;
128 
129     for (unsigned int i = 0; i < hira.length (); i++) {
130         WideString tmpwide;
131         bool found = false;
132 
133         HiraganaKatakanaRule *table = scim_anthy_hiragana_katakana_table;
134 
135         for (unsigned int j = 0; table[j].hiragana; j++) {
136             tmpwide = utf8_mbstowcs (table[j].hiragana);
137             if (hira.substr(i, 1) == tmpwide) {
138                 if (half)
139                     kata += utf8_mbstowcs (table[j].half_katakana);
140                 else
141                     kata += utf8_mbstowcs (table[j].katakana);
142                 found = true;
143                 break;
144             }
145         }
146 
147         if (!found)
148             kata += hira.substr(i, 1);
149     }
150 }
151 
152 void
util_create_attributes(AttributeList & attrs,unsigned int start,unsigned int length,String type,unsigned int fg_color,unsigned int bg_color)153 util_create_attributes (AttributeList &attrs,
154                         unsigned int start,
155                         unsigned int length,
156                         String type,
157                         unsigned int fg_color,
158                         unsigned int bg_color)
159 {
160     if (type == "None") {
161         return;
162     } else if (type == "Underline") {
163         attrs.push_back (Attribute (start, length,
164                                     SCIM_ATTR_DECORATE,
165                                     SCIM_ATTR_DECORATE_UNDERLINE));
166     } else if (type == "Reverse") {
167         attrs.push_back (Attribute (start, length,
168                                     SCIM_ATTR_DECORATE,
169                                     SCIM_ATTR_DECORATE_REVERSE));
170     } else if (type == "Highlight") {
171         attrs.push_back (Attribute (start, length,
172                                     SCIM_ATTR_DECORATE,
173                                     SCIM_ATTR_DECORATE_HIGHLIGHT));
174     } else {
175         if (type == "Color" || type == "FGColor")
176             attrs.push_back (Attribute (start, length,
177                                         SCIM_ATTR_FOREGROUND,
178                                         fg_color));
179         if (type == "Color" || type == "BGColor")
180             attrs.push_back (Attribute (start, length,
181                                         SCIM_ATTR_BACKGROUND,
182                                         bg_color));
183     }
184 }
185 
186 bool
util_key_is_keypad(const KeyEvent & key)187 util_key_is_keypad (const KeyEvent &key)
188 {
189     switch (key.code) {
190     case SCIM_KEY_KP_Equal:
191     case SCIM_KEY_KP_Multiply:
192     case SCIM_KEY_KP_Add:
193     case SCIM_KEY_KP_Separator:
194     case SCIM_KEY_KP_Subtract:
195     case SCIM_KEY_KP_Decimal:
196     case SCIM_KEY_KP_Divide:
197     case SCIM_KEY_KP_0:
198     case SCIM_KEY_KP_1:
199     case SCIM_KEY_KP_2:
200     case SCIM_KEY_KP_3:
201     case SCIM_KEY_KP_4:
202     case SCIM_KEY_KP_5:
203     case SCIM_KEY_KP_6:
204     case SCIM_KEY_KP_7:
205     case SCIM_KEY_KP_8:
206     case SCIM_KEY_KP_9:
207         return true;
208     default:
209         return false;
210     }
211 }
212 
213 void
util_keypad_to_string(String & str,const KeyEvent & key)214 util_keypad_to_string (String &str, const KeyEvent &key)
215 {
216     char raw[2];
217 
218     switch (key.code) {
219     case SCIM_KEY_KP_Equal:
220         raw[0] = '=';
221         break;
222 
223     case SCIM_KEY_KP_Multiply:
224         raw[0] = '*';
225         break;
226 
227     case SCIM_KEY_KP_Add:
228         raw[0] = '+';
229         break;
230 
231     case SCIM_KEY_KP_Separator:
232         raw[0] = ',';
233         break;
234 
235     case SCIM_KEY_KP_Subtract:
236         raw[0] = '-';
237         break;
238 
239     case SCIM_KEY_KP_Decimal:
240         raw[0] = '.';
241         break;
242 
243     case SCIM_KEY_KP_Divide:
244         raw[0] = '/';
245         break;
246 
247     case SCIM_KEY_KP_0:
248     case SCIM_KEY_KP_1:
249     case SCIM_KEY_KP_2:
250     case SCIM_KEY_KP_3:
251     case SCIM_KEY_KP_4:
252     case SCIM_KEY_KP_5:
253     case SCIM_KEY_KP_6:
254     case SCIM_KEY_KP_7:
255     case SCIM_KEY_KP_8:
256     case SCIM_KEY_KP_9:
257         raw[0] = '0' + key.code - SCIM_KEY_KP_0;
258         break;
259 
260     default:
261         if (isprint (key.get_ascii_code()))
262             raw[0] = key.get_ascii_code();
263         else
264             raw[0] = '\0';
265         break;
266     }
267 
268     raw[1] = '\0';
269     str = raw;
270 }
271 
272 void
util_launch_program(const char * command)273 util_launch_program (const char *command)
274 {
275     if (!command) return;
276 
277     /* split string */
278     unsigned int len = strlen (command);
279     char tmp[len + 1];
280     strncpy (tmp, command, len);
281     tmp[len] = '\0';
282 
283     char *str = tmp;
284     std::vector<char *> array;
285 
286     for (unsigned int i = 0; i < len + 1; i++) {
287         if (!tmp[i] || isspace (tmp[i])) {
288             if (*str) {
289                 tmp[i] = '\0';
290                 array.push_back (str);
291             }
292             str = tmp + i + 1;
293         }
294     }
295 
296     if (array.size () <= 0) return;
297     array.push_back (NULL);
298 
299     char *args[array.size()];
300     for (unsigned int i = 0; i < array.size (); i++)
301         args[i] = array[i];
302 
303 
304     /* exec command */
305 	pid_t child_pid;
306 
307 	child_pid = fork();
308 	if (child_pid < 0) {
309 		perror("fork");
310 	} else if (child_pid == 0) {		 /* child process  */
311 		pid_t grandchild_pid;
312 
313 		grandchild_pid = fork();
314 		if (grandchild_pid < 0) {
315 			perror("fork");
316 			_exit(1);
317 		} else if (grandchild_pid == 0) { /* grandchild process  */
318 			execvp(args[0], args);
319 			perror("execvp");
320 			_exit(1);
321 		} else {
322 			_exit(0);
323 		}
324 	} else {                              /* parent process */
325 		int status;
326 		waitpid(child_pid, &status, 0);
327 	}
328 }
329 
330 }
331