1 /** @file scim_imengine.cpp
2 * @brief Implementation of class IMEngineFactoryBase and IMEngineInstanceBase.
3 */
4
5 /*
6 * Smart Common Input Method
7 *
8 * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
9 *
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the
23 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24 * Boston, MA 02111-1307 USA
25 *
26 * $Id: scim_imengine.cpp,v 1.15 2005/04/08 15:24:11 suzhe Exp $
27 *
28 */
29
30 #define Uses_SCIM_IMENGINE
31 #define Uses_C_CTYPE
32
33 #include "scim_private.h"
34 #include "scim.h"
35
36 #define SCIM_KEYBOARD_ICON_FILE (SCIM_ICONDIR "/keyboard.png")
37
38 namespace scim {
39
40 typedef Signal1<void, IMEngineInstanceBase*>
41 IMEngineSignalVoid;
42
43 typedef Signal2<void, IMEngineInstanceBase*,int>
44 IMEngineSignalInt;
45
46 typedef Signal2<void, IMEngineInstanceBase*,bool>
47 IMEngineSignalBool;
48
49 typedef Signal2<void, IMEngineInstanceBase*,const String&>
50 IMEngineSignalString;
51
52 typedef Signal2<void, IMEngineInstanceBase*,const WideString&>
53 IMEngineSignalWideString;
54
55 typedef Signal2<void, IMEngineInstanceBase*,const KeyEvent&>
56 IMEngineSignalKeyEvent;
57
58 typedef Signal2<void, IMEngineInstanceBase*,const Property&>
59 IMEngineSignalProperty;
60
61 typedef Signal2<void, IMEngineInstanceBase*,const PropertyList&>
62 IMEngineSignalPropertyList;
63
64 typedef Signal2<void, IMEngineInstanceBase*,const LookupTable&>
65 IMEngineSignalLookupTable;
66
67 typedef Signal3<void, IMEngineInstanceBase*,const String&,const Transaction&>
68 IMEngineSignalStringTransaction;
69
70 typedef Signal3<void, IMEngineInstanceBase*,const WideString&,const AttributeList&>
71 IMEngineSignalWideStringAttributeList;
72
73 typedef Signal5<bool, IMEngineInstanceBase*,WideString&,int&,int,int>
74 IMEngineSignalGetSurroundingText;
75
76 typedef Signal3<bool, IMEngineInstanceBase*,int,int>
77 IMEngineSignalDeleteSurroundingText;
78
79 class IMEngineFactoryBase::IMEngineFactoryBaseImpl
80 {
81 public:
82 std::vector<String> m_encoding_list;
83 std::vector<String> m_locale_list;
84 String m_language;
85 };
86
87 class IMEngineInstanceBase::IMEngineInstanceBaseImpl
88 {
89 public:
90 IMEngineFactoryPointer m_factory;
91 String m_encoding;
92
93 IMEngineSignalVoid m_signal_show_preedit_string;
94 IMEngineSignalVoid m_signal_show_aux_string;
95 IMEngineSignalVoid m_signal_show_lookup_table;
96
97 IMEngineSignalVoid m_signal_hide_preedit_string;
98 IMEngineSignalVoid m_signal_hide_aux_string;
99 IMEngineSignalVoid m_signal_hide_lookup_table;
100
101 IMEngineSignalInt m_signal_update_preedit_caret;
102 IMEngineSignalWideStringAttributeList m_signal_update_preedit_string;
103 IMEngineSignalWideStringAttributeList m_signal_update_aux_string;
104 IMEngineSignalWideString m_signal_commit_string;
105 IMEngineSignalLookupTable m_signal_update_lookup_table;
106
107 IMEngineSignalKeyEvent m_signal_forward_key_event;
108
109 IMEngineSignalPropertyList m_signal_register_properties;
110 IMEngineSignalProperty m_signal_update_property;
111
112 IMEngineSignalVoid m_signal_beep;
113
114 IMEngineSignalString m_signal_start_helper;
115 IMEngineSignalString m_signal_stop_helper;
116 IMEngineSignalStringTransaction m_signal_send_helper_event;
117
118 IMEngineSignalGetSurroundingText m_signal_get_surrounding_text;
119 IMEngineSignalDeleteSurroundingText m_signal_delete_surrounding_text;
120
121
122 int m_id;
123 void * m_frontend_data;
124
IMEngineInstanceBaseImpl()125 IMEngineInstanceBaseImpl () : m_id (0), m_frontend_data (0) { }
126 };
127
IMEngineFactoryBase()128 IMEngineFactoryBase::IMEngineFactoryBase ()
129 : m_impl (new IMEngineFactoryBaseImpl ())
130 {
131 }
132
~IMEngineFactoryBase()133 IMEngineFactoryBase::~IMEngineFactoryBase ()
134 {
135 delete m_impl;
136 }
137
138 bool
validate_encoding(const String & encoding) const139 IMEngineFactoryBase::validate_encoding (const String& encoding) const
140 {
141 if (encoding == "UTF-8")
142 return true;
143
144 for (size_t i=0; i<m_impl->m_encoding_list.size (); ++i)
145 if (m_impl->m_encoding_list [i] == encoding)
146 return true;
147
148 return false;
149 }
150
151 bool
validate_locale(const String & locale) const152 IMEngineFactoryBase::validate_locale (const String& locale) const
153 {
154 for (size_t i=0; i<m_impl->m_locale_list.size (); ++i)
155 if (m_impl->m_locale_list [i] == locale)
156 return true;
157
158 if (scim_get_locale_encoding (locale) == "UTF-8")
159 return true;
160
161 return false;
162 }
163
164 String
get_language() const165 IMEngineFactoryBase::get_language () const
166 {
167 return m_impl->m_language;
168 }
169
170 WideString
inverse_query(const WideString & str)171 IMEngineFactoryBase::inverse_query (const WideString &str)
172 {
173 return WideString ();
174 }
175
176 String
get_encodings() const177 IMEngineFactoryBase::get_encodings () const
178 {
179 return scim_combine_string_list (m_impl->m_encoding_list);
180 }
181
182 String
get_locales() const183 IMEngineFactoryBase::get_locales () const
184 {
185 return scim_combine_string_list (m_impl->m_locale_list);
186 }
187
188 String
get_default_encoding() const189 IMEngineFactoryBase::get_default_encoding () const
190 {
191 if (m_impl->m_encoding_list.size ())
192 return m_impl->m_encoding_list [0];
193 return String ("UTF-8");
194 }
195
196 String
get_default_locale() const197 IMEngineFactoryBase::get_default_locale () const
198 {
199 if (m_impl->m_locale_list.size ())
200 return m_impl->m_locale_list [0];
201 return String ("");
202 }
203
204 void
set_locales(const String & locales)205 IMEngineFactoryBase::set_locales (const String& locales)
206 {
207 m_impl->m_locale_list.clear ();
208 m_impl->m_encoding_list.clear ();
209
210 if (locales.size () == 0) return;
211
212 String locale;
213 std::vector <String> lc_list;
214
215 scim_split_string_list (lc_list, locales);
216
217 for (size_t i=0; i<lc_list.size (); ++i) {
218 locale = scim_validate_locale (lc_list [i]);
219 if (locale.length ()) {
220 m_impl->m_locale_list.push_back (locale);
221 m_impl->m_encoding_list.push_back (scim_get_locale_encoding (locale));
222 }
223 }
224
225 m_impl->m_language = scim_get_locale_language (get_default_locale ());
226 }
227
228 void
set_languages(const String & languages)229 IMEngineFactoryBase::set_languages (const String& languages)
230 {
231 std::vector <String> lang_list;
232 String locales;
233 String all_locales;
234
235 scim_split_string_list (lang_list, languages, ',');
236
237 for (size_t i = 0; i < lang_list.size (); ++ i) {
238 locales = scim_get_language_locales (lang_list [i]);
239 if (locales.length ()) {
240 if (all_locales.length ())
241 all_locales.push_back (',');
242 all_locales += locales;
243 }
244 }
245
246 if (all_locales.length ())
247 set_locales (all_locales);
248
249 if (lang_list.size ())
250 m_impl->m_language = scim_validate_language (lang_list [0]);
251 }
252
IMEngineInstanceBase(IMEngineFactoryBase * factory,const String & encoding,int id)253 IMEngineInstanceBase::IMEngineInstanceBase (IMEngineFactoryBase *factory,
254 const String &encoding,
255 int id)
256 : m_impl (new IMEngineInstanceBaseImpl ())
257 {
258 m_impl->m_factory = factory;
259 m_impl->m_encoding = encoding;
260 m_impl->m_id = id;
261
262 if (!m_impl->m_factory.null ()) {
263 if (!m_impl->m_factory->validate_encoding (encoding)) {
264 m_impl->m_encoding = m_impl->m_factory->get_default_encoding ();
265 }
266 } else {
267 m_impl->m_encoding = String ("UTF-8");
268 }
269 }
270
~IMEngineInstanceBase()271 IMEngineInstanceBase::~IMEngineInstanceBase ()
272 {
273 delete m_impl;
274 }
275
276 bool
set_encoding(const String & encoding)277 IMEngineInstanceBase::set_encoding (const String &encoding)
278 {
279 if (!m_impl->m_factory.null () && m_impl->m_factory->validate_encoding (encoding)) {
280 m_impl->m_encoding = encoding;
281 return true;
282 }
283 return false;
284 }
285
286 String
get_encoding() const287 IMEngineInstanceBase::get_encoding () const
288 {
289 return m_impl->m_encoding;
290 }
291
292 int
get_id() const293 IMEngineInstanceBase::get_id () const
294 {
295 return m_impl->m_id;
296 }
297
298 String
get_factory_uuid() const299 IMEngineInstanceBase::get_factory_uuid () const
300 {
301 if (!m_impl->m_factory.null ())
302 return m_impl->m_factory->get_uuid ();
303
304 return String ();
305 }
306
307 void
set_frontend_data(void * data)308 IMEngineInstanceBase::set_frontend_data (void *data)
309 {
310 m_impl->m_frontend_data = data;
311 }
312
313 void *
get_frontend_data(void)314 IMEngineInstanceBase::get_frontend_data (void)
315 {
316 return m_impl->m_frontend_data;
317 }
318
319 void
move_preedit_caret(unsigned int)320 IMEngineInstanceBase::move_preedit_caret (unsigned int)
321 {
322 }
323
324 void
select_candidate(unsigned int)325 IMEngineInstanceBase::select_candidate (unsigned int)
326 {
327 }
328
329 void
update_lookup_table_page_size(unsigned int)330 IMEngineInstanceBase::update_lookup_table_page_size (unsigned int)
331 {
332 }
333
334 void
lookup_table_page_up()335 IMEngineInstanceBase::lookup_table_page_up ()
336 {
337 }
338
339 void
lookup_table_page_down()340 IMEngineInstanceBase::lookup_table_page_down ()
341 {
342 }
343
344 void
reset()345 IMEngineInstanceBase::reset ()
346 {
347 }
348
349 void
focus_in()350 IMEngineInstanceBase::focus_in ()
351 {
352 }
353
354 void
focus_out()355 IMEngineInstanceBase::focus_out ()
356 {
357 }
358
359 void
trigger_property(const String &)360 IMEngineInstanceBase::trigger_property (const String &)
361 {
362 }
363
364 void
process_helper_event(const String &,const Transaction &)365 IMEngineInstanceBase::process_helper_event (const String &, const Transaction &)
366 {
367 }
368
369 void
update_client_capabilities(unsigned int)370 IMEngineInstanceBase::update_client_capabilities (unsigned int /*cap*/)
371 {
372 }
373
374 Connection
signal_connect_show_preedit_string(IMEngineSlotVoid * slot)375 IMEngineInstanceBase::signal_connect_show_preedit_string (IMEngineSlotVoid *slot)
376 {
377 return m_impl->m_signal_show_preedit_string.connect (slot);
378 }
379
380 Connection
signal_connect_show_aux_string(IMEngineSlotVoid * slot)381 IMEngineInstanceBase::signal_connect_show_aux_string (IMEngineSlotVoid *slot)
382 {
383 return m_impl->m_signal_show_aux_string.connect (slot);
384 }
385
386 Connection
signal_connect_show_lookup_table(IMEngineSlotVoid * slot)387 IMEngineInstanceBase::signal_connect_show_lookup_table (IMEngineSlotVoid *slot)
388 {
389 return m_impl->m_signal_show_lookup_table.connect (slot);
390 }
391
392 Connection
signal_connect_hide_preedit_string(IMEngineSlotVoid * slot)393 IMEngineInstanceBase::signal_connect_hide_preedit_string (IMEngineSlotVoid *slot)
394 {
395 return m_impl->m_signal_hide_preedit_string.connect (slot);
396 }
397
398 Connection
signal_connect_hide_aux_string(IMEngineSlotVoid * slot)399 IMEngineInstanceBase::signal_connect_hide_aux_string (IMEngineSlotVoid *slot)
400 {
401 return m_impl->m_signal_hide_aux_string.connect (slot);
402 }
403
404 Connection
signal_connect_hide_lookup_table(IMEngineSlotVoid * slot)405 IMEngineInstanceBase::signal_connect_hide_lookup_table (IMEngineSlotVoid *slot)
406 {
407 return m_impl->m_signal_hide_lookup_table.connect (slot);
408 }
409
410 Connection
signal_connect_update_preedit_caret(IMEngineSlotInt * slot)411 IMEngineInstanceBase::signal_connect_update_preedit_caret (IMEngineSlotInt *slot)
412 {
413 return m_impl->m_signal_update_preedit_caret.connect (slot);
414 }
415
416 Connection
signal_connect_update_preedit_string(IMEngineSlotWideStringAttributeList * slot)417 IMEngineInstanceBase::signal_connect_update_preedit_string (IMEngineSlotWideStringAttributeList *slot)
418 {
419 return m_impl->m_signal_update_preedit_string.connect (slot);
420 }
421
422 Connection
signal_connect_update_aux_string(IMEngineSlotWideStringAttributeList * slot)423 IMEngineInstanceBase::signal_connect_update_aux_string (IMEngineSlotWideStringAttributeList *slot)
424 {
425 return m_impl->m_signal_update_aux_string.connect (slot);
426 }
427
428 Connection
signal_connect_update_lookup_table(IMEngineSlotLookupTable * slot)429 IMEngineInstanceBase::signal_connect_update_lookup_table (IMEngineSlotLookupTable *slot)
430 {
431 return m_impl->m_signal_update_lookup_table.connect (slot);
432 }
433
434 Connection
signal_connect_commit_string(IMEngineSlotWideString * slot)435 IMEngineInstanceBase::signal_connect_commit_string (IMEngineSlotWideString *slot)
436 {
437 return m_impl->m_signal_commit_string.connect (slot);
438 }
439
440 Connection
signal_connect_forward_key_event(IMEngineSlotKeyEvent * slot)441 IMEngineInstanceBase::signal_connect_forward_key_event (IMEngineSlotKeyEvent *slot)
442 {
443 return m_impl->m_signal_forward_key_event.connect (slot);
444 }
445
446 Connection
signal_connect_register_properties(IMEngineSlotPropertyList * slot)447 IMEngineInstanceBase::signal_connect_register_properties (IMEngineSlotPropertyList *slot)
448 {
449 return m_impl->m_signal_register_properties.connect (slot);
450 }
451
452 Connection
signal_connect_update_property(IMEngineSlotProperty * slot)453 IMEngineInstanceBase::signal_connect_update_property (IMEngineSlotProperty *slot)
454 {
455 return m_impl->m_signal_update_property.connect (slot);
456 }
457
458 Connection
signal_connect_beep(IMEngineSlotVoid * slot)459 IMEngineInstanceBase::signal_connect_beep (IMEngineSlotVoid *slot)
460 {
461 return m_impl->m_signal_beep.connect (slot);
462 }
463
464 Connection
signal_connect_start_helper(IMEngineSlotString * slot)465 IMEngineInstanceBase::signal_connect_start_helper (IMEngineSlotString *slot)
466 {
467 return m_impl->m_signal_start_helper.connect (slot);
468 }
469
470 Connection
signal_connect_stop_helper(IMEngineSlotString * slot)471 IMEngineInstanceBase::signal_connect_stop_helper (IMEngineSlotString *slot)
472 {
473 return m_impl->m_signal_stop_helper.connect (slot);
474 }
475
476 Connection
signal_connect_send_helper_event(IMEngineSlotStringTransaction * slot)477 IMEngineInstanceBase::signal_connect_send_helper_event (IMEngineSlotStringTransaction *slot)
478 {
479 return m_impl->m_signal_send_helper_event.connect (slot);
480 }
481
482 Connection
signal_connect_get_surrounding_text(IMEngineSlotGetSurroundingText * slot)483 IMEngineInstanceBase::signal_connect_get_surrounding_text (IMEngineSlotGetSurroundingText *slot)
484 {
485 return m_impl->m_signal_get_surrounding_text.connect (slot);
486 }
487
488 Connection
signal_connect_delete_surrounding_text(IMEngineSlotDeleteSurroundingText * slot)489 IMEngineInstanceBase::signal_connect_delete_surrounding_text (IMEngineSlotDeleteSurroundingText *slot)
490 {
491 return m_impl->m_signal_delete_surrounding_text.connect (slot);
492 }
493
494 void
show_preedit_string()495 IMEngineInstanceBase::show_preedit_string ()
496 {
497 m_impl->m_signal_show_preedit_string (this);
498 }
499
500 void
show_aux_string()501 IMEngineInstanceBase::show_aux_string ()
502 {
503 m_impl->m_signal_show_aux_string (this);
504 }
505
506 void
show_lookup_table()507 IMEngineInstanceBase::show_lookup_table ()
508 {
509 m_impl->m_signal_show_lookup_table (this);
510 }
511
512 void
hide_preedit_string()513 IMEngineInstanceBase::hide_preedit_string ()
514 {
515 m_impl->m_signal_hide_preedit_string (this);
516 }
517
518 void
hide_aux_string()519 IMEngineInstanceBase::hide_aux_string ()
520 {
521 m_impl->m_signal_hide_aux_string (this);
522 }
523
524 void
hide_lookup_table()525 IMEngineInstanceBase::hide_lookup_table ()
526 {
527 m_impl->m_signal_hide_lookup_table (this);
528 }
529
530 void
update_preedit_caret(int caret)531 IMEngineInstanceBase::update_preedit_caret (int caret)
532 {
533 m_impl->m_signal_update_preedit_caret (this, caret);
534 }
535
536 void
update_preedit_string(const WideString & str,const AttributeList & attrs)537 IMEngineInstanceBase::update_preedit_string (const WideString &str,
538 const AttributeList &attrs)
539 {
540 m_impl->m_signal_update_preedit_string (this, str, attrs);
541 }
542
543 void
update_aux_string(const WideString & str,const AttributeList & attrs)544 IMEngineInstanceBase::update_aux_string (const WideString &str,
545 const AttributeList &attrs)
546 {
547 m_impl->m_signal_update_aux_string (this, str, attrs);
548 }
549
550 void
update_lookup_table(const LookupTable & table)551 IMEngineInstanceBase::update_lookup_table (const LookupTable &table)
552 {
553 m_impl->m_signal_update_lookup_table (this, table);
554 }
555
556 void
commit_string(const WideString & str)557 IMEngineInstanceBase::commit_string (const WideString &str)
558 {
559 m_impl->m_signal_commit_string (this, str);
560 }
561
562 void
forward_key_event(const KeyEvent & key)563 IMEngineInstanceBase::forward_key_event (const KeyEvent &key)
564 {
565 m_impl->m_signal_forward_key_event (this, key);
566 }
567
568 void
register_properties(const PropertyList & properties)569 IMEngineInstanceBase::register_properties (const PropertyList &properties)
570 {
571 m_impl->m_signal_register_properties (this, properties);
572 }
573
574 void
update_property(const Property & property)575 IMEngineInstanceBase::update_property (const Property &property)
576 {
577 m_impl->m_signal_update_property (this, property);
578 }
579
580 void
beep()581 IMEngineInstanceBase::beep ()
582 {
583 m_impl->m_signal_beep (this);
584 }
585
586 void
start_helper(const String & helper_uuid)587 IMEngineInstanceBase::start_helper (const String &helper_uuid)
588 {
589 m_impl->m_signal_start_helper (this, helper_uuid);
590 }
591
592 void
stop_helper(const String & helper_uuid)593 IMEngineInstanceBase::stop_helper (const String &helper_uuid)
594 {
595 m_impl->m_signal_stop_helper (this, helper_uuid);
596 }
597
598 void
send_helper_event(const String & helper_uuid,const Transaction & trans)599 IMEngineInstanceBase::send_helper_event (const String &helper_uuid, const Transaction &trans)
600 {
601 m_impl->m_signal_send_helper_event (this, helper_uuid, trans);
602 }
603
604 bool
get_surrounding_text(WideString & text,int & cursor,int maxlen_before,int maxlen_after)605 IMEngineInstanceBase::get_surrounding_text (WideString &text, int &cursor, int maxlen_before, int maxlen_after)
606 {
607 text = WideString ();
608 cursor = 0;
609
610 if (maxlen_before == 0 && maxlen_after == 0)
611 return false;
612
613 if (m_impl->m_signal_get_surrounding_text (this, text, cursor, maxlen_before, maxlen_after) && text.length ())
614 return true;
615
616 return false;
617 }
618
619 bool
delete_surrounding_text(int offset,int len)620 IMEngineInstanceBase::delete_surrounding_text (int offset, int len)
621 {
622 return m_impl->m_signal_delete_surrounding_text (this, offset, len);
623 }
624
625 // implementation of DummyIMEngine
DummyIMEngineFactory()626 DummyIMEngineFactory::DummyIMEngineFactory ()
627 {
628 set_locales ("C");
629 }
630
~DummyIMEngineFactory()631 DummyIMEngineFactory::~DummyIMEngineFactory ()
632 {
633 }
634
635 WideString
get_name() const636 DummyIMEngineFactory::get_name () const
637 {
638 return utf8_mbstowcs (_("English/Keyboard"));
639 }
640
641 WideString
get_authors() const642 DummyIMEngineFactory::get_authors () const
643 {
644 return WideString ();
645 }
646
647 WideString
get_credits() const648 DummyIMEngineFactory::get_credits () const
649 {
650 return WideString ();
651 }
652
653 WideString
get_help() const654 DummyIMEngineFactory::get_help () const
655 {
656 return WideString ();
657 }
658
659 String
get_uuid() const660 DummyIMEngineFactory::get_uuid () const
661 {
662 return String ("0148bcec-850d-45f2-ba95-a493bb31492e");
663 }
664
665 String
get_icon_file() const666 DummyIMEngineFactory::get_icon_file () const
667 {
668 return String (SCIM_KEYBOARD_ICON_FILE);
669 }
670
671 bool
validate_encoding(const String & encoding) const672 DummyIMEngineFactory::validate_encoding (const String& encoding) const
673 {
674 return true;
675 }
676
677 bool
validate_locale(const String & locale) const678 DummyIMEngineFactory::validate_locale (const String& locale) const
679 {
680 return true;
681 }
682
683 IMEngineInstancePointer
create_instance(const String & encoding,int id)684 DummyIMEngineFactory::create_instance (const String& encoding, int id)
685 {
686 return new DummyIMEngineInstance (this, encoding, id);
687 }
688
DummyIMEngineInstance(DummyIMEngineFactory * factory,const String & encoding,int id)689 DummyIMEngineInstance::DummyIMEngineInstance (DummyIMEngineFactory *factory,
690 const String& encoding,
691 int id)
692 : IMEngineInstanceBase (factory, encoding, id)
693 {
694 }
695
~DummyIMEngineInstance()696 DummyIMEngineInstance::~DummyIMEngineInstance ()
697 {
698 }
699
700 bool
process_key_event(const KeyEvent & key)701 DummyIMEngineInstance::process_key_event (const KeyEvent& key)
702 {
703 return false;
704 }
705
706 void
focus_in()707 DummyIMEngineInstance::focus_in ()
708 {
709 register_properties (PropertyList ());
710 }
711
712 } // namespace scim
713
714 /*
715 vi:ts=4:nowrap:ai:expandtab
716 */
717