1 /** @file scim_uim_imengine.cpp
2  */
3 
4 /*
5  * Smart Common Input Method
6  *
7  * Copyright (c) 2004 James Su <suzhe@tsinghua.org.cn>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program 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 General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  * $Id: scim_uim_imengine.cpp,v 1.15 2007/04/10 05:43:59 makeinu Exp $
24  */
25 
26 #define Uses_SCIM_UTILITY
27 #define Uses_SCIM_IMENGINE
28 #define Uses_SCIM_LOOKUP_TABLE
29 #define Uses_SCIM_CONFIG_BASE
30 
31 #ifdef HAVE_CONFIG_H
32   #include <config.h>
33 #endif
34 
35 #include <cstring>
36 
37 #include <scim.h>
38 #include "scim_uim_imengine.h"
39 #include <uim/uim-scm.h>
40 #include <uim/uim-util.h>
41 
42 #define scim_module_init uim_LTX_scim_module_init
43 #define scim_module_exit uim_LTX_scim_module_exit
44 #define scim_imengine_module_init uim_LTX_scim_imengine_module_init
45 #define scim_imengine_module_create_factory uim_LTX_scim_imengine_module_create_factory
46 
47 #define SCIM_CONFIG_IMENGINE_UIM_UUID    "/IMEngine/UIM/UUID-"
48 #define SCIM_CONFIG_IMENGINE_UIM_ON_KEY  "/IMEngine/UIM/OnKey"
49 
50 #define SCIM_PROP_PREFIX                 "/IMEngine/UIM"
51 
52 #ifndef SCIM_UIM_ICON_FILE
53     #define SCIM_UIM_ICON_FILE           (SCIM_ICONDIR "/scim-uim.png")
54 #endif
55 
56 static const int   __uim_nr_uuids = 128;
57 static const char *__uim_uuids [] = {
58 "a7260f28-f634-49b9-bda0-9563e73dfdcc",
59 "0f1c9e83-87ff-4d5b-b001-d26ed9eea28b",
60 "feea4b74-69ca-466c-9dae-c66938277f62",
61 "3bf4238e-ea4e-40e2-a448-9aed0d558688",
62 "47903928-ca2d-4c4f-aaf3-97a32efb66f4",
63 "a528ac45-0576-40ce-9b56-e31a9e9dda8b",
64 "25ccf9a9-f532-4a0e-9ebf-c3c8d68cb736",
65 "2b03a434-a9bd-43e8-9c71-662931950d02",
66 "db4e7180-7faf-49a9-8a91-3b48b65423da",
67 "cf3b27aa-3c6f-4f83-8144-8a0808ebce77",
68 "a0a566ee-f85d-4a15-bd48-c857db390704",
69 "1c4660a2-516a-4ca3-bce2-8533c57bb977",
70 "7ce64cde-df38-4d20-97fb-053eba125ade",
71 "54b2928c-6e4a-4b21-8d80-19d8af37f8b2",
72 "527168c7-329b-44ec-bb3d-effeebc942be",
73 "49d4407e-08e6-447d-814a-b7b2a358b851",
74 "78270c67-6edd-4d71-8efb-11f262141020",
75 "2d4e5dde-84af-4773-b457-f84c8bf24bbd",
76 "c482abff-35a8-4bcb-822c-e43633126f95",
77 "d58644fa-8691-49f9-a06c-4969adcedabe",
78 "8303fcab-716d-4cb7-a83c-b529e1dfd9cc",
79 "50ec2062-7dfc-4948-9d3a-f853f0ee5129",
80 "aa53d188-4a70-4fe6-ad0f-fa785a22c33f",
81 "c0500ada-0f72-4dc4-9717-24e73fd7688d",
82 "db6edc87-7414-459f-9b38-313ffbba08c0",
83 "21376af6-fa66-4048-a13d-b8a4a7bc67ec",
84 "5b54efb7-5a37-46e8-802a-4845d9b2745f",
85 "00d29b16-d659-4be6-84c9-8f30ec3740ea",
86 "50cf1952-1ab0-4eb8-91db-5a4fc5ef20e7",
87 "8f8b87bf-7dbb-4de7-a50b-a78988514874",
88 "56b35489-1c04-4053-a922-9e29153d18f8",
89 "7f82f830-7311-4135-8393-5f73936f8ef1",
90 "c5f4ee73-76eb-4312-896b-17f5bf44dc6e",
91 "e6aa003b-6463-42d2-b0c5-8452a83f8b7f",
92 "94519d47-6b02-4f01-9662-68340aa54062",
93 "9bef12ea-f24a-4545-9072-44c2cb97699f",
94 "e7e8ccfa-1ddd-410d-a090-8143ecdacd4e",
95 "1b6e0b3f-9724-4e2e-b3da-489b1812d97e",
96 "bb3b545e-b05e-49f3-a07b-f75deb266371",
97 "1987ec94-fd7d-49c9-8eb5-b3b80b8fb692",
98 "18f1a0de-f409-4fba-974c-5aed8f61f8cf",
99 "088b5c7c-e57c-45aa-8a0e-a32517a58796",
100 "b4ed97f1-95ec-4cc1-8bb7-34b301c0f5f3",
101 "aba86f78-53ad-444b-9192-09d35cad3c84",
102 "63e2c45d-3dbe-4a31-8ae0-892e6c41a217",
103 "9ea81b5e-ea47-4b9b-abee-812de4bf137a",
104 "96a10d16-5ee4-4c22-be34-b4d4902b741d",
105 "1ae43bc7-cc5b-4667-a348-7ed24e78492d",
106 "347ac412-3db7-43f3-a6b7-e7c0f76bf350",
107 "6d858525-7024-440b-98a0-29916bf3b8bc",
108 "dff358bc-2470-4b4d-ac8a-7b2ef8ed16e8",
109 "cfab4949-206e-4e56-877f-9ec7e76bdfa9",
110 "456dfdd0-f967-4eb6-a7ef-8de0a98e9b3e",
111 "d462765f-4c17-4692-8597-69ef2dcc024d",
112 "e02d8a38-7fb7-4a11-8015-c4bbec8cffe6",
113 "f12a5151-b3c2-499d-ad54-ced806124859",
114 "4ea506b4-183b-4e54-bc0c-a9c6d810ddbf",
115 "51ff97b2-b41b-41a0-934c-0e6d035ad367",
116 "d9b2a316-9710-445f-af66-539e5dd28423",
117 "62ae3ad8-089c-4a74-834a-a4b8904c2d9a",
118 "08a98403-e50d-4f3e-a295-27464fa96c13",
119 "afe96cee-73c3-4af3-aed6-a1c51e5974bc",
120 "7c05965a-62f3-4d56-a82d-1e4b363fc5ab",
121 "43fd4393-8425-4bd0-9ba4-8f0d71db7659",
122 "6e65c275-8c23-4642-91e9-6ea9ecbda41c",
123 "ec7cde34-a3e3-4db6-bb36-6eea931e29d6",
124 "051b61df-28fd-4b7d-92ba-af140a1cf62d",
125 "0af548b8-7b5c-45de-8af1-444b9622bf2e",
126 "f4986a51-7b16-4c9a-8b90-7d16a84dba87",
127 "80358db4-c753-4337-a889-ea84d8135335",
128 "adada64e-d5a8-4bf4-b5cf-b3b22ddc8bf8",
129 "23c87d83-b581-4ad0-bc22-60d89d510586",
130 "003a0e50-6bf4-4a40-8f79-6a71d2866061",
131 "ef1d08d3-3d6e-4021-b191-1a5ee6a42cdd",
132 "ccd8cd0e-5d9a-4d7c-a066-39defcac48a8",
133 "224a288e-440d-4477-ae95-93dd80add396",
134 "bcc3267a-2e3b-46cc-8b00-fcfe1de2dee0",
135 "6cb55b24-0a19-4975-975e-90493eb03f20",
136 "853cd53c-8520-426d-ab79-06eb5830f5c9",
137 "1fb0a4d8-47da-4268-919c-f3ffcb0c6e55",
138 "a4ce45ab-7bac-4a9a-b30b-cadabf510b1e",
139 "1cb3271f-c661-46cb-b8b2-0e05a7f2f783",
140 "03c5a6ea-2b14-4758-abf0-ee4463079501",
141 "d44f68fd-62e9-497e-bb58-a1f1fa86a335",
142 "99fa1c0a-5434-4432-951f-68a9003e4524",
143 "6fba0759-93a6-49af-979c-ba5f542ef1b7",
144 "961e550f-de34-44db-97cd-11374968aa85",
145 "beb2cbf2-6499-4a23-8e41-8a66f98a0e52",
146 "18e304a2-cf55-43ab-81f4-3b5035ffe592",
147 "b43051d5-055b-4a5b-b4f8-2bd18396fc4e",
148 "51daa0f3-cd21-426d-9262-20c5f8264827",
149 "634ec9f1-01cb-4f7b-b350-c2713fe1b3ae",
150 "b39d13b8-3660-4ab3-a29e-6b839e2a2cc8",
151 "63310e02-2f33-4e6d-ad09-042248f1548c",
152 "dbcd01fe-c673-4291-bd34-aa967e93056f",
153 "aa47fd51-a9fc-4a22-a880-67f2ceaf4e51",
154 "9795ce0e-8917-4eff-a8b0-97df4923b962",
155 "3a941c8a-7296-4ba3-80e9-d217460fa284",
156 "7d5edaf0-567d-4b18-bd9f-9298eaca5863",
157 "3a70a0e8-9972-4b7e-9913-7fa66c858b39",
158 "800d4437-7e1f-4602-8428-a8166810a519",
159 "ffba4b45-c917-4877-a7fa-b4d598a8da3b",
160 "e40141ad-0fcf-4d21-ae51-da7d5ce39132",
161 "7f1ef850-ff54-45c0-82f3-48d329c74b25",
162 "ec3dafdf-01b6-4e50-af5b-1d13bcad0a07",
163 "90e5b710-a9be-4a51-9ee5-4ff246c7d905",
164 "f4aa1d77-3319-47df-9c08-6e48bc64647b",
165 "7e541494-c453-4ee6-b625-98b0d5918fdd",
166 "9e8e1898-5803-487f-9934-f2543abc501b",
167 "5915de02-33c0-40a3-a1fd-3a4736b1c519",
168 "55dbc4f5-f4ea-4b5b-8890-a7413d7731f1",
169 "78db4c98-324b-4a83-8fc7-1e6b4d6aef63",
170 "c6ab096c-cf09-4642-841b-cc986cf83f49",
171 "21475d28-c74f-4ea5-b323-d8e37c1c3f10",
172 "422a2a17-a7ea-4a88-96ee-a22fdedcf25a",
173 "a9069165-d399-406b-a3b6-94513d1fe5dd",
174 "ad0d8f2f-0268-4c4f-b542-00c3cffdabf8",
175 "429eecad-f904-427a-9132-7f198d3fc3e7",
176 "a5d2fa81-5243-4798-a980-1eac5ffdfcaf",
177 "5d9059aa-3daa-4a55-bae2-c7ff7787eb8a",
178 "09bd8211-68c6-44db-99e6-33ffef0b195c",
179 "3ea3a87b-835b-40f0-983d-5d296ba578a3",
180 "44c02613-42e8-49a4-bdf6-f16e9fc5d7b8",
181 "d61d2879-d3f7-4da1-aabf-c124641595e0",
182 "430cbebd-56bc-45d0-b0c4-8f8fbe8e1590",
183 "fd8f93df-0c91-49ec-9442-282dabc0d3d7",
184 "ff053f70-ebc0-462a-a52d-559435d5d390",
185 "a7027b54-ed6e-4656-80cc-3b1641853efa"
186 };
187 
188 struct UIMInfo {
189     String name;
190     String lang;
191     String uuid;
192 };
193 
194 // first = name, second = lang
195 static std::vector <UIMInfo> __uim_input_methods;
196 static KeyEvent              __uim_on_key;
197 
198 static ConfigPointer _scim_config (0);
199 
200 extern "C" {
scim_module_init(void)201     void scim_module_init (void)
202     {
203     }
204 
scim_module_exit(void)205     void scim_module_exit (void)
206     {
207         uim_quit ();
208     }
209 
scim_imengine_module_init(const ConfigPointer & config)210     uint32 scim_imengine_module_init (const ConfigPointer &config)
211     {
212         SCIM_DEBUG_IMENGINE(1) << "Initialize UIM Engine.\n";
213 
214         _scim_config = config;
215 
216         if (uim_init ()) {
217             SCIM_DEBUG_IMENGINE(1) << "Failed to initialize UIM Library!\n";
218             return 0;
219         }
220 
221         String on_key = config->read (SCIM_CONFIG_IMENGINE_UIM_ON_KEY, String ("Shift+space"));
222 
223         if (!scim_string_to_key (__uim_on_key, on_key))
224             __uim_on_key = KeyEvent (SCIM_KEY_space, SCIM_KEY_ShiftMask);
225 
226         uim_context uc = uim_create_context(NULL, "UTF-8", NULL,
227                                             NULL, uim_iconv, NULL);
228 
229         if (!uc) return 0;
230 
231         int i;
232         int nr = uim_get_nr_im(uc);
233         int count = 0;
234 
235         UIMInfo im_info;
236 
237         SCIM_DEBUG_IMENGINE(1) << "Get all IM info:\n";
238 
239         // Get all im info.
240         for (i = 0; i < nr; ++i) {
241             const char *name = uim_get_im_name (uc, i);
242             const char *lang = uim_get_im_language (uc, i);
243 
244             im_info.name = String (name);
245             im_info.lang = String (lang);
246 
247             SCIM_DEBUG_IMENGINE(1) << "  " << name << "\t" << lang << "\n";
248 
249             // Do not account the "default" im.
250             if (strncmp (name, "default", 7)) {
251                 __uim_input_methods.push_back (im_info);
252                 count ++;
253             }
254 
255             if (count >= __uim_nr_uuids) break;
256         }
257 
258         // Get all uuids.
259         for (i = 0; i < count; ++i)
260             __uim_input_methods [i].uuid = config->read (String (SCIM_CONFIG_IMENGINE_UIM_UUID) + __uim_input_methods [i].name,
261                                                          String (""));
262 
263         // Allocate uuids for the IMs without uuid.
264         for (i = 0; i < count; ++i) {
265             if (!__uim_input_methods [i].uuid.length ()) {
266                 for (int j = 0; j < __uim_nr_uuids; ++j) {
267                     int k = 0;
268                     for (; k < count; ++k)
269                         if (String (__uim_uuids [j]) == __uim_input_methods [k].uuid) break;
270 
271                     if (k == count) {
272 
273                         SCIM_DEBUG_IMENGINE(1) << "Set UUID: " << __uim_uuids [j] << " -> " << __uim_input_methods [i].name << "\n";
274 
275                         __uim_input_methods [i].uuid = __uim_uuids [j];
276                         config->write (String (SCIM_CONFIG_IMENGINE_UIM_UUID) + __uim_input_methods [i].name,
277                                        String (__uim_uuids [j]));
278                         break;
279                     }
280                 }
281             }
282         }
283 
284         return count;
285     }
286 
scim_imengine_module_create_factory(uint32 engine)287     IMEngineFactoryPointer scim_imengine_module_create_factory (uint32 engine)
288     {
289         if (engine >= __uim_input_methods.size ()) return 0;
290 
291         UIMFactory *factory = 0;
292 
293         try {
294             factory = new UIMFactory (__uim_input_methods [engine].name,
295                                       __uim_input_methods [engine].lang,
296                                       __uim_input_methods [engine].uuid);
297         } catch (...) {
298             delete factory;
299             factory = 0;
300         }
301 
302         return factory;
303     }
304 }
305 
UIMFactory(const String & name,const String & lang,const String & uuid)306 UIMFactory::UIMFactory (const String &name,
307                         const String &lang,
308                         const String &uuid)
309     : m_name (name),
310       m_uuid (uuid)
311 {
312     SCIM_DEBUG_IMENGINE(1) << "Create UIM Factory :\n";
313     SCIM_DEBUG_IMENGINE(1) << "  Name : " << name << "\n";
314     SCIM_DEBUG_IMENGINE(1) << "  Lang : " << lang << "\n";
315     SCIM_DEBUG_IMENGINE(1) << "  UUID : " << uuid << "\n";
316 
317     if (lang.length () >= 2)
318         set_languages (lang);
319 }
320 
~UIMFactory()321 UIMFactory::~UIMFactory ()
322 {
323 }
324 
325 WideString
get_name() const326 UIMFactory::get_name () const
327 {
328     return utf8_mbstowcs (String ("UIM-") + m_name);
329 }
330 
331 WideString
get_authors() const332 UIMFactory::get_authors () const
333 {
334     return WideString ();
335 }
336 
337 WideString
get_credits() const338 UIMFactory::get_credits () const
339 {
340     return WideString ();
341 }
342 
343 WideString
get_help() const344 UIMFactory::get_help () const
345 {
346     return WideString ();
347 }
348 
349 String
get_uuid() const350 UIMFactory::get_uuid () const
351 {
352     return m_uuid;
353 }
354 
355 String
get_icon_file() const356 UIMFactory::get_icon_file () const
357 {
358     return String (SCIM_UIM_ICON_FILE);
359 }
360 
361 IMEngineInstancePointer
create_instance(const String & encoding,int id)362 UIMFactory::create_instance (const String &encoding, int id)
363 {
364     return new UIMInstance (this, m_name, encoding, id);
365 }
366 
367 
UIMInstance(UIMFactory * factory,const String & uim_name,const String & encoding,int id)368 UIMInstance::UIMInstance (UIMFactory   *factory,
369                           const String &uim_name,
370                           const String &encoding,
371                           int           id)
372     : IMEngineInstanceBase (factory, encoding, id),
373       m_show_lookup_table (false)
374 {
375 
376     SCIM_DEBUG_IMENGINE(1) << "Create UIM Instance : " << uim_name << "\n";
377 
378     m_uc = uim_create_context (this, "UTF-8", NULL,
379                                uim_name.c_str (),
380                                uim_iconv,
381                                uim_commit_cb);
382 
383     if (m_uc) {
384         uim_set_preedit_cb (m_uc,
385                             uim_preedit_clear_cb,
386                             uim_preedit_pushback_cb,
387                             uim_preedit_update_cb);
388         uim_set_prop_list_update_cb (m_uc,
389                                      uim_prop_list_update_cb);
390         uim_set_prop_label_update_cb (m_uc,
391                                       uim_prop_label_update_cb);
392         uim_set_candidate_selector_cb (m_uc,
393                                        uim_cand_activate_cb,
394                                        uim_cand_select_cb,
395                                        uim_cand_shift_page_cb,
396                                        uim_cand_deactive_cb);
397 
398         if (__uim_on_key.is_key_press ())
399             uim_press_key (m_uc, convert_keycode (__uim_on_key.code), convert_keymask (__uim_on_key.mask));
400         else
401             uim_release_key (m_uc, convert_keycode (__uim_on_key.code), convert_keymask (__uim_on_key.mask));
402     }
403 }
404 
~UIMInstance()405 UIMInstance::~UIMInstance ()
406 {
407     if (m_uc) uim_release_context (m_uc);
408 }
409 
410 bool
process_key_event(const KeyEvent & key)411 UIMInstance::process_key_event (const KeyEvent& key)
412 {
413     if (!m_uc) return false;
414 
415     SCIM_DEBUG_IMENGINE(2) << "process_key_event.\n";
416 
417     int rv;
418 
419     int keycode = convert_keycode (key.code);
420     int keymask = convert_keymask (key.mask);
421 
422     if (key.is_key_press ())
423         rv = uim_press_key (m_uc, keycode, keymask);
424     else
425         rv = uim_release_key (m_uc, keycode, keymask);
426 
427     return rv == 0;
428 }
429 
430 void
move_preedit_caret(unsigned int pos)431 UIMInstance::move_preedit_caret (unsigned int pos)
432 {
433 }
434 
435 void
select_candidate(unsigned int item)436 UIMInstance::select_candidate (unsigned int item)
437 {
438     if (!m_uc || !m_lookup_table.number_of_candidates ()) return;
439 
440     SCIM_DEBUG_IMENGINE(2) << "select_candidate.\n";
441 
442     int current = m_lookup_table.get_cursor_pos_in_current_page ();
443 
444     if (current != item) {
445         m_lookup_table.set_cursor_pos_in_current_page (item);
446         uim_set_candidate_index (m_uc, m_lookup_table.get_cursor_pos ());
447         update_lookup_table (m_lookup_table);
448     }
449 }
450 
451 void
update_lookup_table_page_size(unsigned int page_size)452 UIMInstance::update_lookup_table_page_size (unsigned int page_size)
453 {
454     SCIM_DEBUG_IMENGINE(2) << "update_lookup_table_page_size.\n";
455 
456     m_lookup_table.set_page_size (page_size);
457 }
458 
459 void
lookup_table_page_up()460 UIMInstance::lookup_table_page_up ()
461 {
462     if (!m_uc || !m_lookup_table.number_of_candidates () || !m_lookup_table.get_current_page_start ()) return;
463 
464     SCIM_DEBUG_IMENGINE(2) << "lookup_table_page_up.\n";
465 
466     m_lookup_table.page_up ();
467 
468     update_lookup_table (m_lookup_table);
469     uim_set_candidate_index (m_uc, m_lookup_table.get_cursor_pos ());
470 }
471 
472 void
lookup_table_page_down()473 UIMInstance::lookup_table_page_down ()
474 {
475     if (!m_uc || !m_lookup_table.number_of_candidates () ||
476         m_lookup_table.get_current_page_start () + m_lookup_table.get_current_page_size () >=
477           m_lookup_table.number_of_candidates ())
478         return;
479 
480     SCIM_DEBUG_IMENGINE(2) << "lookup_table_page_down.\n";
481 
482     m_lookup_table.page_down ();
483 
484     update_lookup_table (m_lookup_table);
485     uim_set_candidate_index (m_uc, m_lookup_table.get_cursor_pos ());
486 }
487 
488 void
reset()489 UIMInstance::reset ()
490 {
491     SCIM_DEBUG_IMENGINE(2) << "reset.\n";
492     uim_reset_context (m_uc);
493 }
494 
495 void
focus_in()496 UIMInstance::focus_in ()
497 {
498     SCIM_DEBUG_IMENGINE(2) << "focus_in.\n";
499 
500     hide_aux_string ();
501 
502     uim_prop_list_update (m_uc);
503     uim_prop_label_update (m_uc);
504 
505     uim_preedit_update_cb (this);
506 
507     if (m_show_lookup_table && m_lookup_table.number_of_candidates ()) {
508         update_lookup_table (m_lookup_table);
509         show_lookup_table ();
510     } else {
511         hide_lookup_table ();
512     }
513 }
514 
515 void
focus_out()516 UIMInstance::focus_out ()
517 {
518     SCIM_DEBUG_IMENGINE(2) << "focus_out.\n";
519 }
520 
521 void
trigger_property(const String & property)522 UIMInstance::trigger_property (const String &property)
523 {
524     String uim_prop = property.substr (property.find_last_of ('/') + 1);
525 
526     SCIM_DEBUG_IMENGINE(2) << "trigger_property : " << property << " - " << uim_prop << "\n";
527 
528     uim_prop_activate (m_uc, uim_prop.c_str ());
529 }
530 
531 int
convert_keycode(int key)532 UIMInstance::convert_keycode (int key)
533 {
534     switch (key) {
535         case SCIM_KEY_BackSpace: return UKey_Backspace;
536         case SCIM_KEY_Delete: return UKey_Delete;
537         case SCIM_KEY_Escape: return UKey_Escape;
538         case SCIM_KEY_Tab: return UKey_Tab;
539         case SCIM_KEY_Return: return UKey_Return;
540         case SCIM_KEY_Left: return UKey_Left;
541         case SCIM_KEY_Up: return UKey_Up;
542         case SCIM_KEY_Right: return UKey_Right;
543         case SCIM_KEY_Down: return UKey_Down;
544         case SCIM_KEY_Prior: return UKey_Prior;
545         case SCIM_KEY_Next: return UKey_Next;
546         case SCIM_KEY_Home: return UKey_Home;
547         case SCIM_KEY_End: return UKey_End;
548         case SCIM_KEY_Zenkaku_Hankaku: return UKey_Zenkaku_Hankaku;
549         case SCIM_KEY_Multi_key: return UKey_Multi_key;
550         case SCIM_KEY_Mode_switch: return UKey_Mode_switch;
551         case SCIM_KEY_Henkan_Mode: return UKey_Henkan_Mode;
552         case SCIM_KEY_Muhenkan: return UKey_Muhenkan;
553         case SCIM_KEY_Shift_L: return UKey_Shift_key;
554         case SCIM_KEY_Shift_R: return UKey_Shift_key;
555         case SCIM_KEY_Control_L: return UKey_Control_key;
556         case SCIM_KEY_Control_R: return UKey_Control_key;
557         case SCIM_KEY_Alt_L: return UKey_Alt_key;
558         case SCIM_KEY_Alt_R: return UKey_Alt_key;
559         case SCIM_KEY_Meta_L: return UKey_Meta_key;
560         case SCIM_KEY_Meta_R: return UKey_Meta_key;
561         case SCIM_KEY_Super_L: return UKey_Super_key;
562         case SCIM_KEY_Super_R: return UKey_Super_key;
563         case SCIM_KEY_Hyper_L: return UKey_Hyper_key;
564         case SCIM_KEY_Hyper_R: return UKey_Hyper_key;
565     }
566 
567     if(key >= SCIM_KEY_F1 && key <= SCIM_KEY_F12) {
568         return key - SCIM_KEY_F1 + UKey_F1;
569     }
570     if(key >= SCIM_KEY_KP_0 && key <= SCIM_KEY_KP_9) {
571         return key - SCIM_KEY_KP_0 + UKey_0;
572     }
573     if (key < 256) {
574         return key;
575     }
576     return UKey_Other;
577 }
578 
579 int
convert_keymask(int mod)580 UIMInstance::convert_keymask (int mod)
581 {
582     int rv = 0;
583     if (mod & SCIM_KEY_ShiftMask) {
584         rv |= UMod_Shift;
585     }
586     if (mod & SCIM_KEY_ControlMask) {
587         rv |= UMod_Control;
588     }
589     if (mod & SCIM_KEY_AltMask) {
590         rv |= UMod_Alt;
591     }
592     if (mod & SCIM_KEY_SuperMask) {
593         rv |= UMod_Super;
594     }
595     if (mod & SCIM_KEY_HyperMask) {
596         rv |= UMod_Hyper;
597     }
598     return rv;
599 }
600 
601 void
uim_commit_cb(void * ptr,const char * str)602 UIMInstance::uim_commit_cb (void *ptr, const char *str)
603 {
604     UIMInstance *this_ptr = static_cast <UIMInstance *> (ptr);
605 
606     if (this_ptr && str) {
607 
608         SCIM_DEBUG_IMENGINE(2) << "uim_commit_cb : " << str << "\n";
609 
610         this_ptr->commit_string (utf8_mbstowcs (str));
611     }
612 }
613 
614 void
uim_preedit_clear_cb(void * ptr)615 UIMInstance::uim_preedit_clear_cb (void *ptr)
616 {
617     UIMInstance *this_ptr = static_cast <UIMInstance *> (ptr);
618     if (this_ptr) {
619 
620         SCIM_DEBUG_IMENGINE(2) << "uim_preedit_clear_cb.\n";
621 
622         this_ptr->m_preedit_string = WideString ();
623         this_ptr->m_preedit_attrs.clear ();
624         this_ptr->m_preedit_caret = 0;
625     }
626 }
627 
628 void
uim_preedit_pushback_cb(void * ptr,int attr,const char * str)629 UIMInstance::uim_preedit_pushback_cb (void *ptr, int attr, const char *str)
630 {
631     UIMInstance *this_ptr = static_cast <UIMInstance *> (ptr);
632     if (this_ptr && str) {
633 
634         SCIM_DEBUG_IMENGINE(2) << "uim_preedit_pushback_cb: " << attr << " " << str << "\n";
635 
636         WideString newstr (utf8_mbstowcs (str));
637 
638         if (!newstr.length () && !(attr & (UPreeditAttr_Cursor | UPreeditAttr_Separator)))
639             return;
640 
641         Attribute newattr (this_ptr->m_preedit_string.length (), newstr.length (), SCIM_ATTR_DECORATE);
642 
643         if ((attr & UPreeditAttr_Separator) && !newstr.length ())
644             this_ptr->m_preedit_string += utf8_mbstowcs ("|");
645 
646         if (attr & UPreeditAttr_Cursor)
647             this_ptr->m_preedit_caret = this_ptr->m_preedit_string.length ();
648 
649         if (attr & UPreeditAttr_UnderLine)
650             newattr.set_value (SCIM_ATTR_DECORATE_UNDERLINE);
651 
652         if (attr & UPreeditAttr_Reverse)
653             newattr.set_value (SCIM_ATTR_DECORATE_REVERSE | newattr.get_value ());
654 
655         if (newstr.length ()) {
656             this_ptr->m_preedit_string += newstr;
657             this_ptr->m_preedit_attrs.push_back (newattr);
658         }
659     }
660 }
661 
662 void
uim_preedit_update_cb(void * ptr)663 UIMInstance::uim_preedit_update_cb (void *ptr)
664 {
665     UIMInstance *this_ptr = static_cast <UIMInstance *> (ptr);
666     if (this_ptr) {
667 
668         SCIM_DEBUG_IMENGINE(2) << "uim_preedit_update_cb.\n";
669 
670         if (this_ptr->m_preedit_string.length ()) {
671             this_ptr->show_preedit_string ();
672             this_ptr->update_preedit_string (this_ptr->m_preedit_string,
673                                              this_ptr->m_preedit_attrs);
674             this_ptr->update_preedit_caret (this_ptr->m_preedit_caret);
675         } else {
676             this_ptr->hide_preedit_string ();
677         }
678     }
679 }
680 
681 
682 void
uim_prop_list_update_cb(void * ptr,const char * str)683 UIMInstance::uim_prop_list_update_cb (void *ptr, const char *str)
684 {
685     UIMInstance *this_ptr = static_cast <UIMInstance *> (ptr);
686 
687     if (this_ptr) {
688 
689         SCIM_DEBUG_IMENGINE(2) << "uim_prop_list_update_cb:\n" << str << "\n";
690 
691         this_ptr->m_properties.clear ();
692 
693         std::vector <String> prop_strings;
694         std::vector <String> prop_values;
695         scim_split_string_list (prop_strings, String (str), '\n');
696 
697         int branch_count = 0;
698         char buf [256];
699 
700         for (size_t i = 0; i < prop_strings.size (); ++ i) {
701             if (prop_strings [i].length () < 1) continue;
702             scim_split_string_list (prop_values, prop_strings [i], '\t');
703             if (prop_values.size () < 4) continue;
704 
705             if (prop_values [0] == "branch") {
706                 ++ branch_count;
707 
708                 // skip im-switch menu
709                 if (branch_count == 1 && uim_scm_symbol_value_bool("toolbar-show-action-based-switcher-button?"))
710                     continue;
711 
712                 snprintf (buf, 256, "/IMEngine/UIM/branch%d", branch_count);
713 
714                 Property prop (buf, prop_values [2], String (""), prop_values [3]);
715                 this_ptr->m_properties.push_back (prop);
716 
717                 SCIM_DEBUG_IMENGINE(3) << "SCIM Prop = " << buf << "\n";
718             } else if (prop_values [0] == "leaf" && prop_values.size () >= 6) {
719                 if (branch_count == 1 && uim_scm_symbol_value_bool("toolbar-show-action-based-switcher-button?"))
720                     continue;
721 
722                 snprintf (buf, 256, "/IMEngine/UIM/branch%d/%s", branch_count, prop_values [5].c_str ());
723 
724                 Property prop (buf, prop_values [3], String (""), prop_values [4]);
725                 this_ptr->m_properties.push_back (prop);
726 
727                 SCIM_DEBUG_IMENGINE(3) << "SCIM Prop = " << buf << "\n";
728             }
729         }
730 
731         this_ptr->register_properties (this_ptr->m_properties);
732     }
733 }
734 
735 void
uim_prop_label_update_cb(void * ptr,const char * str)736 UIMInstance::uim_prop_label_update_cb (void *ptr, const char *str)
737 {
738     UIMInstance *this_ptr = static_cast <UIMInstance *> (ptr);
739 
740     if (this_ptr) {
741 
742         SCIM_DEBUG_IMENGINE(2) << "uim_prop_label_update_cb:\n" << str << "\n";
743 
744         std::vector <String> prop_strings;
745         std::vector <String> prop_values;
746         scim_split_string_list (prop_strings, String (str), '\n');
747 
748         char buf [80];
749 
750         for (size_t i = 0; i < prop_strings.size (); ++ i) {
751             if (prop_strings [i].length () < 1) continue;
752             scim_split_string_list (prop_values, prop_strings [i], '\t');
753             if (prop_values.size () < 2) continue;
754 
755             snprintf (buf, 80, "/IMEngine/UIM/branch%d", i+1);
756 
757             PropertyList::iterator it = std::find (this_ptr->m_properties.begin (),
758                                                    this_ptr->m_properties.end (),
759                                                    String (buf));
760 
761             if (it != this_ptr->m_properties.end ()) {
762                 it->set_label (prop_values [0]);
763                 it->set_tip (prop_values [1]);
764                 this_ptr->update_property (*it);
765             }
766         }
767     }
768 }
769 
770 void
uim_cand_activate_cb(void * ptr,int nr,int display_limit)771 UIMInstance::uim_cand_activate_cb (void *ptr, int nr, int display_limit)
772 {
773     UIMInstance *this_ptr = static_cast <UIMInstance *> (ptr);
774     if (this_ptr) {
775 
776         SCIM_DEBUG_IMENGINE(2) << "uim_cand_activate_cb : " << nr << " " << display_limit << "\n";
777 
778         this_ptr->m_lookup_table.clear ();
779         this_ptr->m_lookup_table.set_page_size (display_limit);
780 
781         uim_candidate new_cand;
782         const char *cand_str;
783 
784         for (int i = 0; i < nr; ++i) {
785             new_cand = uim_get_candidate (this_ptr->m_uc, i, i);
786             cand_str = uim_candidate_get_cand_str (new_cand);
787             this_ptr->m_lookup_table.append_candidate (utf8_mbstowcs (cand_str));
788             uim_candidate_free (new_cand);
789         }
790 
791         this_ptr->show_lookup_table ();
792         this_ptr->update_lookup_table (this_ptr->m_lookup_table);
793         this_ptr->m_show_lookup_table = true;
794     }
795 }
796 
797 void
uim_cand_select_cb(void * ptr,int index)798 UIMInstance::uim_cand_select_cb (void *ptr, int index)
799 {
800     UIMInstance *this_ptr = static_cast <UIMInstance *> (ptr);
801     if (this_ptr) {
802 
803         SCIM_DEBUG_IMENGINE(2) << "uim_cand_select_cb : " << index << "\n";
804 
805         if (index >= 0 && index < this_ptr->m_lookup_table.number_of_candidates ()) {
806             this_ptr->m_lookup_table.set_cursor_pos (index);
807             this_ptr->update_lookup_table (this_ptr->m_lookup_table);
808         }
809     }
810 }
811 
812 void
uim_cand_shift_page_cb(void * ptr,int dir)813 UIMInstance::uim_cand_shift_page_cb (void *ptr, int dir)
814 {
815     UIMInstance *this_ptr = static_cast <UIMInstance *> (ptr);
816     if (this_ptr) {
817 
818         SCIM_DEBUG_IMENGINE(2) << "uim_cand_shift_page_cb : " << dir << "\n";
819 
820         if (dir) this_ptr->lookup_table_page_down ();
821         else this_ptr->lookup_table_page_up ();
822     }
823 }
824 
825 void
uim_cand_deactive_cb(void * ptr)826 UIMInstance::uim_cand_deactive_cb (void *ptr)
827 {
828     UIMInstance *this_ptr = static_cast <UIMInstance *> (ptr);
829     if (this_ptr) {
830 
831         SCIM_DEBUG_IMENGINE(2) << "uim_cand_deactive_cb.\n";
832 
833         this_ptr->hide_lookup_table ();
834         this_ptr->m_show_lookup_table = false;
835     }
836 }
837 /*
838 vi:ts=4:nowrap:ai:expandtab
839 */
840