Git init
[framework/uifw/isf.git] / ism / src / scim_event.cpp
1 /* ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable. */
2
3 /*
4  * Smart Common Input Method
5  *
6  * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
7  *
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this program; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
22  * Boston, MA  02111-1307  USA
23  *
24  * $Id: scim_event.cpp,v 1.29 2005/07/13 08:54:55 suzhe Exp $
25  */
26
27 #define Uses_SCIM_EVENT
28 #define Uses_SCIM_GLOBAL_CONFIG
29 #define Uses_SCIM_CONFIG_PATH
30 #define Uses_C_STDIO
31 #define Uses_C_STRING
32 #include "scim_private.h"
33 #include "scim.h"
34 #include "scim_stl_map.h"
35
36 namespace scim {
37
38 struct __Uint16Pair
39 {
40     uint16 first;
41     uint16 second;
42 };
43
44 struct __KeyCodeMap
45 {
46     size_t        size;
47     __Uint16Pair *map;
48 };
49
50 struct __KeyName
51 {
52     uint16      value;
53     const char *name;
54 };
55
56 class __Uint16PairLessByFirst
57 {
58 public:
59     bool operator ()(const __Uint16Pair &lhs, const __Uint16Pair &rhs) const {
60         return lhs.first < rhs.first;
61     }
62
63     bool operator ()(const __Uint16Pair &lhs, const uint16 &rhs) const {
64         return lhs.first < rhs;
65     }
66
67     bool operator ()(const uint16 &lhs, const __Uint16Pair &rhs) const {
68         return lhs < rhs.first;
69     }
70 };
71
72 class __KeyNameLessByCode
73 {
74 public:
75     bool operator ()(const __KeyName &lhs, const __KeyName &rhs) const {
76         return lhs.value < rhs.value;
77     }
78
79     bool operator ()(const __KeyName &lhs, const uint16 &rhs) const {
80         return lhs.value < rhs;
81     }
82
83     bool operator ()(const uint16 &lhs, const __KeyName &rhs) const {
84         return lhs < rhs.value;
85     }
86 };
87
88 class __KeyNameLessByName
89 {
90 public:
91     bool operator ()(const __KeyName &lhs, const __KeyName &rhs) const {
92         return strcmp (lhs.name, rhs.name) < 0;
93     }
94
95     bool operator ()(const __KeyName &lhs, const char *rhs) const {
96         return strcmp (lhs.name, rhs) < 0;
97     }
98
99     bool operator ()(const char *lhs, const __KeyName &rhs) const {
100         return strcmp (lhs, rhs.name) < 0;
101     }
102 };
103
104 // Keyboard Layout data
105 #include "scim_keyboard_layout_data.h"
106
107 // KeyEvent data
108 #include "scim_keyevent_data.h"
109
110 char
111 KeyEvent::get_ascii_code () const
112 {
113     if (code >= SCIM_KEY_space && code <= SCIM_KEY_asciitilde)
114         return (char) code;
115
116     if (code >= SCIM_KEY_KP_0 && code <= SCIM_KEY_KP_9)
117         return (char) (code - SCIM_KEY_KP_0 + SCIM_KEY_0);
118
119     if (code == SCIM_KEY_Return)
120         return 0x0d;
121     if (code == SCIM_KEY_Linefeed)
122         return 0x0a;
123     if (code == SCIM_KEY_Tab)
124         return 0x09;
125     if (code == SCIM_KEY_BackSpace)
126         return 0x08;
127     if (code == SCIM_KEY_Escape)
128         return 0x1b;
129
130     return 0;
131 }
132
133 ucs4_t
134 KeyEvent::get_unicode_code () const
135 {
136     /* First check for Latin-1 characters (1:1 mapping) */
137     if ((code >= 0x0020 && code <= 0x007e) ||
138         (code >= 0x00a0 && code <= 0x00ff))
139         return code;
140
141     /* Also check for directly encoded 24-bit UCS characters:
142      */
143     if ((code & 0xff000000) == 0x01000000)
144         return code & 0x00ffffff;
145
146     /* Translation of KP_Decimal depends on locale.
147     if (code == SCIM_KP_Decimal)
148         return get_decimal_char ();
149     */
150
151     /* Invalid keyevent code. */
152     if (code > 0xFFFF)
153         return 0;
154
155     /* binary search in table */
156     __Uint16Pair * it = std::lower_bound (__scim_key_to_unicode_tab,
157                                           __scim_key_to_unicode_tab + SCIM_NUM_KEY_UNICODES,
158                                           (uint16) code,
159                                           __Uint16PairLessByFirst ());
160
161     if (it != __scim_key_to_unicode_tab + SCIM_NUM_KEY_UNICODES && it->first == (uint16) code)
162         return it->second;
163
164     /* No matching Unicode value found */
165     return 0;
166 }
167
168 String
169 KeyEvent::get_key_string () const
170 {
171     size_t i;
172     String maskstr;
173     String codestr;
174     uint16 mask_skip = 0;
175
176     for (i=0; i < SCIM_NUM_KEY_MASKS; ++i) {
177         if ((__scim_key_mask_names [i].value & mask) && !(__scim_key_mask_names [i].value & mask_skip)) {
178             if (maskstr.length ())
179                 maskstr += (String ("+") + String (__scim_key_mask_names [i].name));
180             else
181                 maskstr += String (__scim_key_mask_names [i].name);
182         }
183         mask_skip |= __scim_key_mask_names [i].value;
184     }
185
186     if (code == 0xFFFFFF) {
187         codestr = String ("VoidSymbol");
188     } else if (code <= 0xFFFF){
189         __KeyName *it = std::lower_bound (__scim_keys_by_code,
190                                           __scim_keys_by_code + SCIM_NUM_KEY_NAMES,
191                                           (uint16) code,
192                                           __KeyNameLessByCode ());
193
194         if (it != __scim_keys_by_code + SCIM_NUM_KEY_NAMES && it->value == code)
195             codestr = String (it->name);
196     }
197
198     if (!codestr.length () && code) {
199         char buf [20];
200         snprintf (buf, 20, ((code <= 0xFFFF) ? "0x%04x" : "0x%06x"), code);
201         codestr = String (buf);
202     }
203
204     if (maskstr.length () && codestr.length ())
205         return maskstr + String ("+") + codestr;
206     if (maskstr.length())
207         return maskstr;
208     if (codestr.length ())
209         return codestr;
210
211     return String ();
212 }
213
214 static uint16
215 inline __remap_keycode (uint16 from, const __KeyCodeMap &map)
216 {
217     if (map.size == 0) return from;
218
219     __Uint16Pair *it = std::lower_bound (map.map, map.map + map.size, from, __Uint16PairLessByFirst ());
220
221     if (it != map.map + map.size && it->first == from)
222         return it->second;
223
224     return from;
225 }
226
227 KeyEvent
228 KeyEvent::map_to_layout (KeyboardLayout new_layout) const
229 {
230     if (layout == SCIM_KEYBOARD_Unknown || new_layout == SCIM_KEYBOARD_Unknown || layout == new_layout ||
231         layout >= SCIM_KEYBOARD_NUM_LAYOUTS || new_layout >= SCIM_KEYBOARD_NUM_LAYOUTS || new_layout < 0 ||
232         code > 0xFFFF)
233         return *this;
234
235     KeyEvent evt (code, mask, new_layout);
236
237     uint16 new_code = (uint16) code;
238
239     switch (mask & (SCIM_KEY_CapsLockMask | SCIM_KEY_ShiftMask)) {
240         case 0:
241             new_code = __remap_keycode (new_code, __normal_map [layout]);
242             new_code = __remap_keycode (new_code, __normal_invert_map [new_layout]);
243             break;
244         case SCIM_KEY_CapsLockMask:
245             new_code = __remap_keycode (new_code, __caps_map [layout]);
246             new_code = __remap_keycode (new_code, __caps_invert_map [new_layout]);
247             break;
248         case SCIM_KEY_ShiftMask:
249             new_code = __remap_keycode (new_code, __shift_map [layout]);
250             new_code = __remap_keycode (new_code, __shift_invert_map [new_layout]);
251             break;
252         case (SCIM_KEY_ShiftMask | SCIM_KEY_CapsLockMask):
253             new_code = __remap_keycode (new_code, __caps_shift_map [layout]);
254             new_code = __remap_keycode (new_code, __caps_shift_invert_map [new_layout]);
255             break;
256     }
257
258     evt.code = (uint32) new_code;
259
260     return evt;
261 }
262
263 bool
264 scim_key_to_string (String &str, const KeyEvent & key)
265 {
266     str = key.get_key_string ();
267     return str.length () != 0;
268 }
269
270 bool
271 scim_string_to_key (KeyEvent &key, const String & str)
272 {
273     std::vector <String> list;
274     bool skip;
275     size_t i;
276
277     key.code = 0;
278     key.mask = 0;
279
280     scim_split_string_list (list, str, '+');
281
282     for (std::vector <String>::iterator it=list.begin (); it!=list.end (); ++it) {
283         skip = false;
284         for (i = 0; i < SCIM_NUM_KEY_MASKS; ++i) {
285             if (*it == String (__scim_key_mask_names [i].name)) {
286                 key.mask |= __scim_key_mask_names [i].value;
287                 skip = true;
288                 break;
289             }
290         }
291
292         if (skip) continue;
293
294         __KeyName *p = std::lower_bound (__scim_keys_by_name,
295                                          __scim_keys_by_name + SCIM_NUM_KEY_NAMES,
296                                          it->c_str (),
297                                          __KeyNameLessByName ());
298
299         if (p != __scim_keys_by_name + SCIM_NUM_KEY_NAMES && strcmp (p->name, it->c_str ()) == 0) {
300             key.code = p->value;
301         } else if (it->length () >= 6 && (*it)[0] == '0' && ((*it)[1] == 'x' || (*it)[1] == 'X')){
302             key.code = strtol (it->c_str () + 2, NULL, 16);
303         } else if (strcmp (p->name, "VoidSymbol") == 0) {
304             key.code = SCIM_KEY_VoidSymbol;
305         }
306     }
307
308     return key.code != 0;
309 }
310
311 bool
312 scim_key_list_to_string (String &str, const std::vector<KeyEvent> & keylist)
313 {
314     std::vector<String> strlist;
315
316     for (std::vector<KeyEvent>::const_iterator it = keylist.begin (); it != keylist.end (); ++it) {
317         if (scim_key_to_string (str, *it))
318             strlist.push_back (str);
319     }
320
321     str = scim_combine_string_list (strlist, ',');
322
323     return str.length () != 0;
324 }
325
326 bool
327 scim_string_to_key_list (std::vector<KeyEvent> &keylist, const String &str)
328 {
329     std::vector <String> strlist;
330     scim_split_string_list (strlist, str, ',');
331
332     keylist.clear ();
333
334     for (std::vector <String>::iterator it = strlist.begin (); it != strlist.end (); ++it) {
335         KeyEvent key;
336         if (scim_string_to_key (key, *it))
337             keylist.push_back (key);
338     }
339     return keylist.size () > 0;
340 }
341
342
343 String
344 scim_keyboard_layout_to_string (KeyboardLayout layout)
345 {
346     if (layout >= 0 && layout < SCIM_KEYBOARD_NUM_LAYOUTS)
347         return String (__scim_keyboard_layout_ids_by_code [layout].name);
348
349     return String (__scim_keyboard_layout_ids_by_code [0].name);
350 }
351
352 KeyboardLayout
353 scim_string_to_keyboard_layout (const String &str)
354 {
355     if (str == __scim_keyboard_layout_ids_by_code [0].name) return SCIM_KEYBOARD_Unknown;
356     if (str == __scim_keyboard_layout_ids_by_code [1].name || str == String ("US") || str == String ("Default")) return SCIM_KEYBOARD_Default;
357
358     __KeyName *it =
359             std::lower_bound (__scim_keyboard_layout_ids_by_name + 2,
360                               __scim_keyboard_layout_ids_by_name + SCIM_KEYBOARD_NUM_LAYOUTS,
361                               str.c_str (),
362                               __KeyNameLessByName());
363
364     if (it != __scim_keyboard_layout_ids_by_name + SCIM_KEYBOARD_NUM_LAYOUTS && strcmp (it->name, str.c_str ()) == 0)
365         return static_cast <KeyboardLayout> (it->value);
366
367     return SCIM_KEYBOARD_Unknown;
368 }
369
370 String
371 scim_keyboard_layout_get_display_name (KeyboardLayout layout)
372 {
373     if (layout >= 0 && layout < SCIM_KEYBOARD_NUM_LAYOUTS)
374         return String (_(__scim_keyboard_layout_names [layout]));
375
376     return String (_(__scim_keyboard_layout_names [0]));
377 }
378
379 KeyboardLayout
380 scim_get_default_keyboard_layout ()
381 {
382     String layout_name (__scim_keyboard_layout_ids_by_code [0].name);
383     layout_name = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_KEYBOARD_LAYOUT, layout_name);
384
385     return scim_string_to_keyboard_layout (layout_name);
386 }
387
388 void
389 scim_set_default_keyboard_layout (KeyboardLayout layout)
390 {
391     String layout_name = scim_keyboard_layout_to_string (layout);
392     scim_global_config_write (SCIM_GLOBAL_CONFIG_DEFAULT_KEYBOARD_LAYOUT, layout_name);
393 }
394
395 } // namespace scim
396
397 /*
398 vi:ts=4:nowrap:ai:expandtab
399 */