1 /** @file scim_m17n_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_m17n_imengine.cpp,v 1.26 2007/01/11 00:44:33 suzhe 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 #define Uses_STL_MAP
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #include <string.h>
37 #include <scim.h>
38
39 #include "scim_m17n_imengine.h"
40
41 #define scim_module_init m17n_LTX_scim_module_init
42 #define scim_module_exit m17n_LTX_scim_module_exit
43 #define scim_imengine_module_init m17n_LTX_scim_imengine_module_init
44 #define scim_imengine_module_create_factory m17n_LTX_scim_imengine_module_create_factory
45
46 #define SCIM_PROP_STATUS "/IMEngine/M17N/Status"
47
48 #ifndef SCIM_M17N_ICON_FILE
49 #define SCIM_M17N_ICON_FILE (SCIM_ICONDIR "/scim-m17n.png")
50 #endif
51
52 struct M17NInfo {
53 String lang;
54 String name;
55 String uuid;
56 };
57
58 static std::vector <M17NInfo> __m17n_input_methods;
59 static std::map <MInputContext *, M17NInstance *> __m17n_input_contexts;
60
61 static CommonLookupTable __lookup_table;
62
63 static MConverter *__m17n_converter = 0;
64
65 static M17NInstance * __find_instance (MInputContext *ic);
66
67 static MSymbol __key_to_symbol (const KeyEvent &key);
68
69 extern "C" {
scim_module_init(void)70 void scim_module_init (void)
71 {
72 __lookup_table.fix_page_size ();
73 }
74
scim_module_exit(void)75 void scim_module_exit (void)
76 {
77 M17N_FINI();
78 }
79
scim_imengine_module_init(const ConfigPointer & config)80 uint32 scim_imengine_module_init (const ConfigPointer &config)
81 {
82 SCIM_DEBUG_IMENGINE(1) << "Initialize M17N Engine.\n";
83
84 MPlist *imlist, *elm;
85 MSymbol utf8;
86
87 size_t i;
88 size_t count = 0;
89
90 M17N_INIT();
91 utf8 = msymbol("utf8");
92
93 __m17n_converter = mconv_buffer_converter(utf8, NULL, 0);
94
95 if (!__m17n_converter) return 0;
96
97 imlist = mdatabase_list(msymbol("input-method"), Mnil, Mnil, Mnil);
98
99 for (elm = imlist; elm && mplist_key(elm) != Mnil; elm = mplist_next(elm)) {
100 MDatabase *mdb = (MDatabase *) mplist_value(elm);
101 MSymbol *tag = mdatabase_tag(mdb);
102 if (tag[1] != Mnil && tag[2] != Mnil) {
103 const char *im_lang = msymbol_name (tag[1]);
104 const char *im_name = msymbol_name (tag[2]);
105
106 if (im_lang && im_lang[0] && im_name && im_name[0]) {
107 M17NInfo info;
108
109 SCIM_DEBUG_IMENGINE(1) << im_lang << "-" << im_name << "\n";
110
111 info.lang = String (im_lang);
112 info.name = String (im_name);
113
114 __m17n_input_methods.push_back (info);
115
116 count++;
117 }
118 }
119 }
120
121 if (imlist) m17n_object_unref(imlist);
122
123 // Set uuids.
124 for (i = 0; i < count; ++i)
125 __m17n_input_methods [i].uuid = String ("IMEngine-M17N-" +
126 __m17n_input_methods [i].lang +
127 String ("-") +
128 __m17n_input_methods [i].name);
129
130 return count;
131 }
132
scim_imengine_module_create_factory(uint32 engine)133 IMEngineFactoryPointer scim_imengine_module_create_factory (uint32 engine)
134 {
135 if (engine >= __m17n_input_methods.size ()) return 0;
136
137 M17NFactory *factory = 0;
138
139 try {
140 factory = new M17NFactory (__m17n_input_methods [engine].lang,
141 __m17n_input_methods [engine].name,
142 __m17n_input_methods [engine].uuid);
143 } catch (...) {
144 delete factory;
145 factory = 0;
146 }
147
148 return factory;
149 }
150 }
151
M17NFactory(const String & lang,const String & name,const String & uuid)152 M17NFactory::M17NFactory (const String &lang,
153 const String &name,
154 const String &uuid)
155 : m_im (0), m_lang (lang), m_name (name), m_uuid (uuid)
156 {
157 SCIM_DEBUG_IMENGINE(1) << "Create M17N Factory :\n";
158 SCIM_DEBUG_IMENGINE(1) << " Lang : " << lang << "\n";
159 SCIM_DEBUG_IMENGINE(1) << " Name : " << name << "\n";
160 SCIM_DEBUG_IMENGINE(1) << " UUID : " << uuid << "\n";
161
162 if (lang.length () >= 2)
163 set_languages (lang);
164 }
165
~M17NFactory()166 M17NFactory::~M17NFactory ()
167 {
168 if (m_im)
169 minput_close_im (m_im);
170 }
171
172 bool
load_input_method()173 M17NFactory::load_input_method ()
174 {
175 SCIM_DEBUG_IMENGINE(1) << "load_input_method(" << m_lang << "," << m_name << ")\n";
176
177 if (m_im) return true;
178
179 m_im = minput_open_im(msymbol (m_lang.c_str ()), msymbol (m_name.c_str ()), NULL);
180
181 if (m_im) {
182 m_im->driver.callback_list = M17NInstance::register_callbacks(m_im->driver.callback_list);
183 return true;
184 }
185
186 return false;
187 }
188
189 WideString
get_name() const190 M17NFactory::get_name () const
191 {
192 return utf8_mbstowcs (m_lang + String ("-") + m_name);
193 }
194
195 WideString
get_authors() const196 M17NFactory::get_authors () const
197 {
198 return WideString ();
199 }
200
201 WideString
get_credits() const202 M17NFactory::get_credits () const
203 {
204 return WideString ();
205 }
206
207 WideString
get_help() const208 M17NFactory::get_help () const
209 {
210 #if M17N_VERSION >= 10300
211 MText *desc = minput_get_description (msymbol (m_lang.c_str ()), msymbol (m_name.c_str ()));
212 if (desc) {
213 int bufsize = mtext_len (desc) * 6; // long enough
214 char *buf = new char [ bufsize ];
215 mconv_rebind_buffer(__m17n_converter, (unsigned char *) buf, bufsize);
216 mconv_encode(__m17n_converter, desc);
217 buf[__m17n_converter->nbytes] = 0;
218 m17n_object_unref(desc);
219
220 return utf8_mbstowcs (buf);
221 }
222 #endif
223 return WideString ();
224 }
225
226 String
get_uuid() const227 M17NFactory::get_uuid () const
228 {
229 return m_uuid;
230 }
231
232 String
get_icon_file() const233 M17NFactory::get_icon_file () const
234 {
235 #if M17N_VERSION >= 10300
236 MPlist *l = minput_get_title_icon (msymbol (m_lang.c_str ()), msymbol (m_name.c_str ()));
237 if (l) {
238 char buf [256] = SCIM_M17N_ICON_FILE;
239 MPlist *n = mplist_next (l);
240
241 if (n && mplist_key (n) == Mtext) {
242 MText *icon = (MText*) mplist_value (n);
243 mconv_rebind_buffer(__m17n_converter, (unsigned char *) buf, 256);
244 mconv_encode(__m17n_converter, icon);
245 buf[__m17n_converter->nbytes] = 0;
246 }
247
248 m17n_object_unref (l);
249 return String (buf);
250 }
251 #endif
252 return String (SCIM_M17N_ICON_FILE);
253 }
254
255 IMEngineInstancePointer
create_instance(const String & encoding,int id)256 M17NFactory::create_instance (const String &encoding, int id)
257 {
258 if (m_im || load_input_method ())
259 return new M17NInstance (this, encoding, id);
260
261 return new DummyIMEngineInstance(dynamic_cast<DummyIMEngineFactory*>(this), encoding, id);
262 }
263
M17NInstance(M17NFactory * factory,const String & encoding,int id)264 M17NInstance::M17NInstance (M17NFactory *factory,
265 const String &encoding,
266 int id)
267 : IMEngineInstanceBase (factory, encoding, id),
268 m_ic (0),
269 m_cap (0),
270 m_block_preedit_op (false),
271 m_pending_preedit_start (false),
272 m_pending_preedit_draw (false),
273 m_pending_preedit_done (false),
274 m_preedit_showed (false)
275 {
276 SCIM_DEBUG_IMENGINE(1) << "Create M17N Instance " << encoding << " " << id << "\n";
277
278 if (factory->m_im) {
279 SCIM_DEBUG_IMENGINE(2) << " Create minput instance.\n";
280 m_ic = minput_create_ic (factory->m_im, NULL);
281 }
282
283 if (m_ic)
284 __m17n_input_contexts [m_ic] = this;
285 }
286
~M17NInstance()287 M17NInstance::~M17NInstance ()
288 {
289 SCIM_DEBUG_IMENGINE(1) << "Destroy M17N Instance " << get_id () << "\n";
290
291 if (m_ic) {
292 __m17n_input_contexts.erase (m_ic);
293 minput_destroy_ic (m_ic);
294 }
295 }
296
297 bool
process_key_event(const KeyEvent & key)298 M17NInstance::process_key_event (const KeyEvent& key)
299 {
300 if (!m_ic) return false;
301
302 if (key.is_key_release ()) return true;
303
304 MSymbol m17n_key = __key_to_symbol (key.map_to_layout (SCIM_KEYBOARD_Default));
305
306 if (m17n_key == Mnil) return false;
307
308 return m17n_process_key (m17n_key);
309 }
310
311 bool
m17n_process_key(MSymbol key)312 M17NInstance::m17n_process_key (MSymbol key)
313 {
314 SCIM_DEBUG_IMENGINE(2) << "process_key_event. " << msymbol_name (key) << "\n";
315
316 char buf [1024];
317 MText *produced;
318 int ret;
319
320 m_block_preedit_op = true;
321
322 ret = minput_filter(m_ic, key, NULL);
323
324 m_block_preedit_op = false;
325
326 if (ret) {
327 SCIM_DEBUG_IMENGINE(3) << "minput_filter returns 1\n";
328 do_preedit_op ();
329 return true;
330 }
331
332 produced = mtext();
333
334 ret = minput_lookup(m_ic, key, NULL, produced);
335
336 if (ret) {
337 SCIM_DEBUG_IMENGINE(3) << "minput_lookup returns 1\n";
338 }
339
340 mconv_rebind_buffer(__m17n_converter, (unsigned char *) buf, 1024);
341 mconv_encode(__m17n_converter, produced);
342 buf[__m17n_converter->nbytes] = 0;
343 m17n_object_unref(produced);
344
345 if (buf[0]) {
346 SCIM_DEBUG_IMENGINE(2) << "commit_string: " << buf << "\n";
347 commit_string (utf8_mbstowcs (buf));
348 }
349
350 do_preedit_op ();
351
352 return ret == 0;
353 }
354
355 void
do_preedit_op()356 M17NInstance::do_preedit_op ()
357 {
358 if (m_block_preedit_op)
359 return;
360
361 if (m_pending_preedit_start) {
362 preedit_start_cb (m_ic, Minput_preedit_start);
363 m_pending_preedit_start = false;
364 }
365
366 if (m_pending_preedit_draw) {
367 preedit_draw_cb (m_ic, Minput_preedit_draw);
368 m_pending_preedit_draw = false;
369 }
370
371 if (m_pending_preedit_done) {
372 preedit_done_cb (m_ic, Minput_preedit_done);
373 m_pending_preedit_done = false;
374 }
375 }
376
377 void
move_preedit_caret(unsigned int pos)378 M17NInstance::move_preedit_caret (unsigned int pos)
379 {
380 }
381
382 void
select_candidate(unsigned int item)383 M17NInstance::select_candidate (unsigned int item)
384 {
385 if (item <= 10) {
386 char buf [4];
387 snprintf (buf, 4, "%d", (item + 1) % 10);
388 m17n_process_key (msymbol (buf));
389 }
390 }
391
392 void
update_lookup_table_page_size(unsigned int page_size)393 M17NInstance::update_lookup_table_page_size (unsigned int page_size)
394 {
395 }
396
397 void
lookup_table_page_up()398 M17NInstance::lookup_table_page_up ()
399 {
400 m17n_process_key (msymbol ("Up"));
401 }
402
403 void
lookup_table_page_down()404 M17NInstance::lookup_table_page_down ()
405 {
406 m17n_process_key (msymbol ("Down"));
407 }
408
409 void
reset()410 M17NInstance::reset ()
411 {
412 SCIM_DEBUG_IMENGINE(2) << "reset.\n";
413 minput_reset_ic(m_ic);
414
415 hide_preedit_string ();
416 hide_aux_string ();
417 hide_lookup_table ();
418
419 m_preedit_showed = false;
420 m_pending_preedit_start = false;
421 m_pending_preedit_draw = false;
422 m_pending_preedit_done = false;
423 }
424
425 void
focus_in()426 M17NInstance::focus_in ()
427 {
428 SCIM_DEBUG_IMENGINE(2) << "focus_in.\n";
429
430 PropertyList props;
431 Property prop (String (SCIM_PROP_STATUS),
432 String (""));
433
434 prop.hide ();
435 props.push_back (prop);
436
437 register_properties (props);
438
439 #if M17N_VERSION >= 10300
440 m17n_process_key (Minput_focus_in);
441 #else
442 preedit_draw_cb (m_ic, Minput_preedit_draw);
443 candidates_draw_cb (m_ic, Minput_candidates_draw);
444 #endif
445
446 //FIXME: Minput_focus_in can't trigger status_draw_cb, so call it here.
447 status_draw_cb (m_ic, Minput_status_draw);
448 }
449
450 void
focus_out()451 M17NInstance::focus_out ()
452 {
453 SCIM_DEBUG_IMENGINE(2) << "focus_out.\n";
454
455 #if M17N_VERSION >= 10300
456 m17n_process_key (Minput_focus_out);
457 #else
458 reset ();
459 #endif
460 }
461
462 void
trigger_property(const String & property)463 M17NInstance::trigger_property (const String &property)
464 {
465 }
466
467 void
update_client_capabilities(unsigned int cap)468 M17NInstance::update_client_capabilities (unsigned int cap)
469 {
470 m_cap = cap;
471 }
472
473 static M17NInstance *
__find_instance(MInputContext * ic)474 __find_instance (MInputContext *ic)
475 {
476 std::map <MInputContext *, M17NInstance *>::iterator it =
477 __m17n_input_contexts.find (ic);
478
479 if (it != __m17n_input_contexts.end ())
480 return it->second;
481
482 return 0;
483 }
484
485
486 MPlist *
register_callbacks(MPlist * callback_list)487 M17NInstance::register_callbacks(MPlist *callback_list)
488 {
489 if(!callback_list)
490 callback_list = mplist();
491
492 mplist_put(callback_list, Minput_preedit_start, (void*)preedit_start_cb);
493 mplist_put(callback_list, Minput_preedit_draw, (void*)preedit_draw_cb);
494 mplist_put(callback_list, Minput_preedit_done, (void*)preedit_done_cb);
495 mplist_put(callback_list, Minput_status_start, (void*)status_start_cb);
496 mplist_put(callback_list, Minput_status_draw, (void*)status_draw_cb);
497 mplist_put(callback_list, Minput_status_done, (void*)status_done_cb);
498 mplist_put(callback_list, Minput_candidates_start, (void*)candidates_start_cb);
499 mplist_put(callback_list, Minput_candidates_draw, (void*)candidates_draw_cb);
500 mplist_put(callback_list, Minput_candidates_done, (void*)candidates_done_cb);
501
502 #if M17N_VERSION >= 10300
503 mplist_put(callback_list, Minput_get_surrounding_text, (void*)get_surrounding_text_cb);
504 mplist_put(callback_list, Minput_delete_surrounding_text, (void*)delete_surrounding_text_cb);
505 #endif
506
507 return callback_list;
508 }
509
510 void
preedit_start_cb(MInputContext * ic,MSymbol command)511 M17NInstance::preedit_start_cb (MInputContext *ic, MSymbol command)
512 {
513 M17NInstance *this_ptr = __find_instance (ic);
514
515 if (this_ptr && !this_ptr->m_preedit_showed) {
516 SCIM_DEBUG_IMENGINE(2) << "preedit_start_cb.\n";
517
518 if (this_ptr->m_block_preedit_op) {
519 this_ptr->m_pending_preedit_start = true;
520 return;
521 }
522
523 this_ptr->show_preedit_string ();
524 this_ptr->m_preedit_showed = true;
525 }
526 }
527
528 void
preedit_draw_cb(MInputContext * ic,MSymbol command)529 M17NInstance::preedit_draw_cb (MInputContext *ic, MSymbol command)
530 {
531 M17NInstance *this_ptr = __find_instance (ic);
532
533 if (this_ptr && ic->preedit) {
534 SCIM_DEBUG_IMENGINE(2) << "preedit_draw_cb.\n";
535
536 if (this_ptr->m_block_preedit_op) {
537 this_ptr->m_pending_preedit_draw = true;
538 return;
539 }
540
541 char buf[1024];
542 mconv_rebind_buffer(__m17n_converter, (unsigned char *)buf, 1024);
543 mconv_encode(__m17n_converter, ic->preedit);
544 buf[__m17n_converter->nbytes] = 0;
545
546 WideString wstr = utf8_mbstowcs (buf);
547 if (wstr.length ()) {
548 AttributeList attrs;
549
550 if (ic->candidate_from < ic->candidate_to && ic->candidate_to <= wstr.length ())
551 attrs.push_back (Attribute (ic->candidate_from,
552 ic->candidate_to - ic->candidate_from,
553 SCIM_ATTR_DECORATE,
554 SCIM_ATTR_DECORATE_REVERSE));
555
556 if (!this_ptr->m_preedit_showed) {
557 this_ptr->show_preedit_string ();
558 this_ptr->m_preedit_showed = true;
559 }
560
561 this_ptr->update_preedit_string (wstr, attrs);
562 this_ptr->update_preedit_caret (ic->cursor_pos);
563 } else {
564 this_ptr->hide_preedit_string ();
565 this_ptr->m_preedit_showed = false;
566 }
567 }
568 }
569
570 void
preedit_done_cb(MInputContext * ic,MSymbol command)571 M17NInstance::preedit_done_cb (MInputContext *ic, MSymbol command)
572 {
573 M17NInstance *this_ptr = __find_instance (ic);
574
575 if (this_ptr && this_ptr->m_preedit_showed) {
576 SCIM_DEBUG_IMENGINE(2) << "preedit_done_cb.\n";
577
578 if (this_ptr->m_block_preedit_op) {
579 this_ptr->m_pending_preedit_done = true;
580 return;
581 }
582
583 this_ptr->hide_preedit_string ();
584 this_ptr->m_preedit_showed = false;
585 }
586 }
587
588 void
status_start_cb(MInputContext * ic,MSymbol command)589 M17NInstance::status_start_cb (MInputContext *ic, MSymbol command)
590 {
591 M17NInstance *this_ptr = __find_instance (ic);
592
593 if (this_ptr) {
594 SCIM_DEBUG_IMENGINE(2) << "status_start_cb.\n";
595
596 Property prop (String (SCIM_PROP_STATUS), String (""));
597
598 this_ptr->update_property (prop);
599 }
600 }
601
602 void
status_draw_cb(MInputContext * ic,MSymbol command)603 M17NInstance::status_draw_cb (MInputContext *ic, MSymbol command)
604 {
605 M17NInstance *this_ptr = __find_instance (ic);
606
607 if (this_ptr && ic->status) {
608 SCIM_DEBUG_IMENGINE(2) << "status_draw_cb.\n";
609
610 char buf[1024];
611 mconv_rebind_buffer(__m17n_converter, (unsigned char *)buf, 1024);
612 mconv_encode(__m17n_converter, ic->status);
613 buf[__m17n_converter->nbytes] = 0;
614
615 Property prop (String (SCIM_PROP_STATUS), String (buf));
616
617 this_ptr->update_property (prop);
618 }
619 }
620
621 void
status_done_cb(MInputContext * ic,MSymbol command)622 M17NInstance::status_done_cb (MInputContext *ic, MSymbol command)
623 {
624 M17NInstance *this_ptr = __find_instance (ic);
625
626 if (this_ptr) {
627 SCIM_DEBUG_IMENGINE(2) << "status_done_cb.\n";
628
629 Property prop (String (SCIM_PROP_STATUS), String (""));
630 prop.hide ();
631
632 this_ptr->update_property (prop);
633 }
634 }
635
636 void
candidates_start_cb(MInputContext * ic,MSymbol command)637 M17NInstance::candidates_start_cb (MInputContext *ic, MSymbol command)
638 {
639 M17NInstance *this_ptr = __find_instance (ic);
640
641 if (this_ptr) {
642 SCIM_DEBUG_IMENGINE(2) << "candidates_start_cb.\n";
643 this_ptr->show_lookup_table ();
644 }
645 }
646
647 void
candidates_draw_cb(MInputContext * ic,MSymbol command)648 M17NInstance::candidates_draw_cb (MInputContext *ic, MSymbol command)
649 {
650 M17NInstance *this_ptr = __find_instance (ic);
651
652 if (this_ptr) {
653 __lookup_table.clear ();
654
655 SCIM_DEBUG_IMENGINE(2) << "candidates_draw_cb.\n";
656 SCIM_DEBUG_IMENGINE(3) << "candidate_index = " << ic->candidate_index << "\n";
657 SCIM_DEBUG_IMENGINE(3) << "candidate_from = " << ic->candidate_from << "\n";
658 SCIM_DEBUG_IMENGINE(3) << "candidate_to = " << ic->candidate_to << "\n";
659 SCIM_DEBUG_IMENGINE(3) << "candidate_show = " << ic->candidate_show << "\n";
660
661 if (ic->candidate_list && ic->candidate_show) {
662 MPlist *group;
663 MText *mt;
664 char buf [1024];
665 int i, len, cur, page;
666 bool page_up, page_down;
667 WideString wstr;
668
669 i = 0;
670 page = 0;
671 group = ic->candidate_list;
672 while (1) {
673 if (mplist_key (group) == Mtext)
674 len = mtext_len ((MText *) mplist_value (group));
675 else
676 len = mplist_length ((MPlist*) mplist_value (group));
677
678 if (i + len > ic->candidate_index)
679 break;
680 i += len;
681 group = mplist_next (group);
682
683 ++page;
684 }
685
686 cur = ic->candidate_index - i;
687
688 page_up = (page > 0);
689 page_down = ((page + 1) < mplist_length (ic->candidate_list));
690
691 if (page_up)
692 __lookup_table.append_candidate (0x3000);
693
694 if (mplist_key (group) == Mtext) {
695 mt = (MText *) mplist_value (group);
696 mconv_rebind_buffer(__m17n_converter, (unsigned char *)buf, 1024);
697 mconv_encode(__m17n_converter, mt);
698 buf[__m17n_converter->nbytes] = 0;
699 wstr = utf8_mbstowcs (buf);
700
701 for (i = 0; i < wstr.length (); ++i)
702 __lookup_table.append_candidate (wstr [i]);
703
704 if (page_up) {
705 __lookup_table.set_page_size (1);
706 __lookup_table.page_down ();
707 }
708
709 __lookup_table.set_page_size (wstr.length ());
710 } else {
711 MPlist *pl;
712
713 len = 0;
714 for (pl = (MPlist *) mplist_value (group); mplist_key (pl) != Mnil; pl = mplist_next (pl)) {
715 mt = (MText *) mplist_value (pl);
716 mconv_rebind_buffer(__m17n_converter, (unsigned char *)buf, 1024);
717 mconv_encode(__m17n_converter, mt);
718 buf[__m17n_converter->nbytes] = 0;
719 wstr = utf8_mbstowcs (buf);
720
721 __lookup_table.append_candidate (wstr);
722 ++ len;
723 }
724
725 if (page_up) {
726 __lookup_table.set_page_size (1);
727 __lookup_table.page_down ();
728 }
729
730 __lookup_table.set_page_size (len);
731 }
732
733 if (page_down)
734 __lookup_table.append_candidate (0x3000);
735
736 __lookup_table.set_cursor_pos_in_current_page (cur);
737 __lookup_table.show_cursor ();
738
739 this_ptr->update_lookup_table (__lookup_table);
740 this_ptr->show_lookup_table ();
741 } else {
742 this_ptr->hide_lookup_table ();
743 }
744 }
745 }
746
747 void
candidates_done_cb(MInputContext * ic,MSymbol command)748 M17NInstance::candidates_done_cb (MInputContext *ic, MSymbol command)
749 {
750 M17NInstance *this_ptr = __find_instance (ic);
751
752 if (this_ptr) {
753 SCIM_DEBUG_IMENGINE(2) << "candidates_done_cb.\n";
754 this_ptr->hide_lookup_table ();
755 }
756 }
757
758 #if M17N_VERSION >= 10300
759 void
get_surrounding_text_cb(MInputContext * ic,MSymbol command)760 M17NInstance::get_surrounding_text_cb (MInputContext *ic, MSymbol command)
761 {
762 M17NInstance *this_ptr = __find_instance (ic);
763
764 if (this_ptr && (this_ptr->m_cap & SCIM_CLIENT_CAP_SURROUNDING_TEXT)) {
765 SCIM_DEBUG_IMENGINE(2) << "get_surrounding_text_cb.\n";
766 if (ic->plist && mplist_key (ic->plist) == Minteger) {
767 int len = (int) ((size_t) mplist_value (ic->plist));
768 int cursor;
769 WideString wstr;
770 MText *txt = mtext ();
771 if (this_ptr->get_surrounding_text (wstr, cursor, (len < 0) ? (-len) : 0, (len > 0) ? len : 0)) {
772 for (WideString::const_iterator i = wstr.begin (); i != wstr.end (); ++i)
773 mtext_cat_char (txt, (int) *i);
774 }
775 mplist_set (ic->plist, Mtext, txt);
776 m17n_object_unref (txt);
777 }
778 }
779 }
780
781 void
delete_surrounding_text_cb(MInputContext * ic,MSymbol command)782 M17NInstance::delete_surrounding_text_cb (MInputContext *ic, MSymbol command)
783 {
784 M17NInstance *this_ptr = __find_instance (ic);
785
786 if (this_ptr) {
787 SCIM_DEBUG_IMENGINE(2) << "delete_surrounding_text_cb.\n";
788 if (ic->plist && mplist_key (ic->plist) == Minteger) {
789 int len = (int) ((size_t) mplist_value (ic->plist));
790 // FIXME: There is no way to inform m17n whether it's failed or not.
791 this_ptr->delete_surrounding_text ((len < 0) ? len : 0, (len > 0) ? len : (-len));
792 }
793 }
794 }
795 #endif
796
797 static MSymbol
__key_to_symbol(const KeyEvent & key)798 __key_to_symbol (const KeyEvent &key)
799 {
800 int mask = 0;
801 String keysym;
802
803 if (key.code >= SCIM_KEY_space && key.code <= SCIM_KEY_asciitilde) {
804 int c = key.code;
805
806 if ((c == SCIM_KEY_space) &&
807 key.is_shift_down ())
808 mask |= SCIM_KEY_ShiftMask;
809
810 if (key.is_control_down ()) {
811 if (c >= 'a' && c <= 'z')
812 c += 'A' - 'a';
813 mask |= SCIM_KEY_ControlMask;
814 }
815
816 keysym.push_back (c);
817 } else if (key.code >= SCIM_KEY_Shift_L && key.code <= SCIM_KEY_Hyper_R) {
818 return Mnil;
819 } else {
820 if (!scim_key_to_string (keysym, KeyEvent (key.code, 0)))
821 return Mnil;
822 if (key.is_control_down ())
823 mask |= SCIM_KEY_ControlMask;
824 if (key.is_shift_down ())
825 mask |= SCIM_KEY_ShiftMask;
826 }
827
828 if (key.is_super_down ())
829 mask |= SCIM_KEY_SuperMask;
830
831 if (key.is_hyper_down ())
832 mask |= SCIM_KEY_HyperMask;
833
834 if (key.is_meta_down ())
835 mask |= SCIM_KEY_MetaMask;
836
837 if (key.is_alt_down ())
838 mask |= SCIM_KEY_AltMask;
839
840 if (!keysym.length ()) return Mnil;
841
842 if (mask & SCIM_KEY_HyperMask)
843 keysym = String ("H-") + keysym;
844 if (mask & SCIM_KEY_SuperMask)
845 keysym = String ("s-") + keysym;
846 if (mask & SCIM_KEY_AltMask)
847 keysym = String ("A-") + keysym;
848 if (mask & SCIM_KEY_MetaMask)
849 keysym = String ("M-") + keysym;
850 if (mask & SCIM_KEY_ControlMask)
851 keysym = String ("C-") + keysym;
852 if (mask & SCIM_KEY_ShiftMask)
853 keysym = String ("S-") + keysym;
854
855 return msymbol (keysym.c_str ());
856 }
857
858 /*
859 vi:ts=4:nowrap:ai:expandtab
860 */
861