1de8588fd42b2bd6008e42f760e5005eeb240cbf
[profile/ivi/isf.git] / ism / modules / imengine / scim_socket_imengine.cpp
1 /** @file scim_socket_imengine.cpp
2  * implementation of class SocketFactory and SocketInstance.
3  */
4
5 /* ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable. */
6
7 /*
8  * Smart Common Input Method
9  *
10  * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
11  *
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Lesser General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU Lesser General Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public
24  * License along with this program; if not, write to the
25  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
26  * Boston, MA  02111-1307  USA
27  *
28  * $Id: scim_socket_imengine.cpp,v 1.21 2005/07/06 03:57:04 suzhe Exp $
29  *
30  */
31
32 #define Uses_SCIM_IMENGINE
33 #define Uses_SCIM_CONFIG_BASE
34 #define Uses_SCIM_CONFIG_PATH
35 #define Uses_SCIM_SOCKET
36 #define Uses_SCIM_TRANSACTION
37 #define Uses_C_STDLIB
38 #define Uses_SCIM_PANEL_AGENT
39
40
41 #include <string.h>
42 #include <unistd.h>
43 #include "scim_private.h"
44 #include "scim.h"
45 #include "scim_socket_imengine.h"
46 #include "scim_stl_map.h"
47 #include "isf_query_utility.h"
48
49
50 #define scim_module_init                    socket_LTX_scim_module_init
51 #define scim_module_exit                    socket_LTX_scim_module_exit
52 #define scim_imengine_module_init           socket_LTX_scim_imengine_module_init
53 #define scim_imengine_module_create_factory socket_LTX_scim_imengine_module_create_factory
54
55 #define SCIM_CONFIG_IMENGINE_SOCKET_TIMEOUT "/IMEngine/Socket/Timeout"
56 #define SCIM_CONFIG_IMENGINE_SOCKET_ADDRESS "/IMEngine/Socket/Address"
57
58 #define SCIM_SOCKET_FRONTEND_DEF_ADDRESS    "local:/tmp/scim-socket-frontend"
59
60 #ifndef SCIM_TEMPDIR
61   #define SCIM_TEMPDIR "/tmp"
62 #endif
63
64 using namespace scim;
65
66
67 class scim::SocketIMEngineGlobal
68 {
69 #if SCIM_USE_STL_EXT_HASH_MAP
70 typedef __gnu_cxx::hash_map <String, String, scim_hash_string> IconRepository;
71 #elif SCIM_USE_STL_HASH_MAP
72 typedef std::hash_map <String, String, scim_hash_string> IconRepository;
73 #else
74 typedef std::map <String, String> IconRepository;
75 #endif
76
77     SocketClient             m_socket_client;
78     SocketAddress            m_socket_address;
79     uint32                   m_socket_magic_key;
80     int                      m_socket_timeout;
81
82     std::vector<String>      m_peer_factories;
83
84     IconRepository           m_icon_repository;
85
86     Signal0<void>            m_signal_reconnect;
87
88 public:
89     SocketIMEngineGlobal ();
90     ~SocketIMEngineGlobal ();
91
92     bool            create_connection ();
93     unsigned int    number_of_factories ();
94     SocketFactory * create_factory (unsigned int index);
95
96     void            init_transaction (Transaction &trans);
97     bool            send_transaction (Transaction &trans);
98     bool            receive_transaction (Transaction &trans);
99
100     void            get_ise_info_map (const char *filename);
101     String          load_icon (const String &icon);
102
103     Connection      connect_reconnect_signal (Slot0<void> *slot_reconnect);
104
105 private:
106     void            init ();
107     void            destroy ();
108
109     void            destroy_all_icons ();
110 };
111
112 static SocketIMEngineGlobal *global = 0;
113 static std::map<String, ISEINFO> ise_info_repository;
114
115 extern "C" {
116     void scim_module_init (void)
117     {
118         if (!global)
119             global = new SocketIMEngineGlobal;
120     }
121
122     void scim_module_exit (void)
123     {
124         if (global) {
125             delete global;
126             global = 0;
127         }
128     }
129
130     unsigned int scim_imengine_module_init (const ConfigPointer &config)
131     {
132         if (global)
133             return global->number_of_factories ();
134         return 0;
135     }
136
137     IMEngineFactoryPointer scim_imengine_module_create_factory (unsigned int index)
138     {
139         if (!global)
140             return 0;
141
142         SocketFactory *sf = global->create_factory (index);
143
144         if (!sf || !sf->valid ()) {
145             delete sf;
146             sf = 0;
147         }
148
149         return sf;
150     }
151 }
152
153 namespace scim {
154
155 SocketIMEngineGlobal::SocketIMEngineGlobal ()
156     : m_socket_magic_key (0),
157       m_socket_timeout (-1)
158 {
159     init ();
160 }
161
162 SocketIMEngineGlobal::~SocketIMEngineGlobal ()
163 {
164     destroy ();
165 }
166
167 void
168 SocketIMEngineGlobal::init ()
169 {
170     SCIM_DEBUG_IMENGINE(1) << "Init SocketIMEngine Global.\n";
171
172     String address = scim_get_default_socket_imengine_address ();
173
174     m_socket_timeout = scim_get_default_socket_timeout ();
175     m_socket_address.set_address (address);
176
177     if (!m_socket_address.valid ())
178         return;
179
180     // Connect to SocketFrontEnd.
181     if (!create_connection ()) {
182         SCIM_DEBUG_IMENGINE(2) << " Cannot connect to SocketFrontEnd (" << address << ").\n";
183         return;
184     }
185
186     SCIM_DEBUG_IMENGINE(2) << " Connected to SocketFrontEnd (" << address
187                          << ") MagicKey (" << m_socket_magic_key << ").\n";
188
189     // Get IMEngineFactory list.
190     String user_file_name = String (USER_ENGINE_FILE_NAME);
191
192     ise_info_repository.clear ();
193     m_peer_factories.clear ();
194     get_ise_info_map (user_file_name.c_str ());
195 }
196
197 bool
198 SocketIMEngineGlobal::create_connection ()
199 {
200     SCIM_DEBUG_IMENGINE(1) << __FUNCTION__ << "...\n";
201
202     // Connect to SocketFrontEnd.
203     if (!m_socket_client.connect (m_socket_address))
204         return false;
205
206     if (!scim_socket_open_connection (m_socket_magic_key,
207                                       String ("SocketIMEngine"),
208                                       String ("SocketFrontEnd"),
209                                       m_socket_client,
210                                       m_socket_timeout)) {
211         m_socket_client.close ();
212         return false;
213     }
214
215     m_signal_reconnect.emit ();
216
217     return true;
218 }
219
220 void
221 SocketIMEngineGlobal::destroy ()
222 {
223     SCIM_DEBUG_IMENGINE(1) << "Destroy SocketIMEngine Global.\n";
224
225     m_socket_client.close ();
226
227     destroy_all_icons ();
228 }
229
230 unsigned int
231 SocketIMEngineGlobal::number_of_factories ()
232 {
233     return m_peer_factories.size ();
234 }
235
236 SocketFactory *
237 SocketIMEngineGlobal::create_factory (unsigned int index)
238 {
239     if (index < m_peer_factories.size ()) {
240         return new SocketFactory (m_peer_factories [index]);
241     }
242     return 0;
243 }
244
245 void
246 SocketIMEngineGlobal::init_transaction (Transaction &trans)
247 {
248     trans.clear ();
249     trans.put_command (SCIM_TRANS_CMD_REQUEST);
250     trans.put_data (m_socket_magic_key);
251 }
252
253 bool
254 SocketIMEngineGlobal::send_transaction (Transaction &trans)
255 {
256     return trans.write_to_socket (m_socket_client);
257 }
258
259 bool
260 SocketIMEngineGlobal::receive_transaction (Transaction &trans)
261 {
262     return trans.read_from_socket (m_socket_client, m_socket_timeout);
263 }
264
265 void
266 SocketIMEngineGlobal::get_ise_info_map (const char *filename)
267 {
268     FILE *engine_list_file = fopen (filename, "r");
269     if (engine_list_file == NULL) {
270         std::cerr << "failed to open " << filename << "\n";
271         return;
272     }
273
274     char buf[MAXLINE];
275
276     while (fgets (buf, MAXLINE, engine_list_file) != NULL && strlen (buf) > 0) {
277         ISEINFO info;
278         isf_get_ise_info_from_string (buf, info);
279
280         if (info.mode == TOOLBAR_KEYBOARD_MODE) {
281             m_peer_factories.push_back (info.uuid);
282             ise_info_repository[info.uuid] = info;
283         }
284     }
285
286     fclose (engine_list_file);
287     return;
288 }
289
290 String
291 SocketIMEngineGlobal::load_icon (const String &icon)
292 {
293     String local_icon = icon;
294
295     IconRepository::const_iterator it = m_icon_repository.find (icon);
296
297     // The icon has been loaded, just return the local copy filename.
298     if (it != m_icon_repository.end ())
299         local_icon = it->second;
300
301     // This icon is already available in local system, just return.
302     if (scim_load_file (local_icon, 0) != 0)
303         return local_icon;
304
305     Transaction trans;
306     int cmd;
307     char *bufptr = 0;
308     size_t filesize = 0;
309
310     local_icon = String ("");
311
312     init_transaction (trans);
313     trans.put_command (SCIM_TRANS_CMD_LOAD_FILE);
314     trans.put_data (icon);
315
316     // Load icon file from remote SocketFrontEnd.
317     if (send_transaction (trans) && receive_transaction (trans) &&
318         trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REPLY &&
319         trans.get_data (&bufptr, filesize) &&
320         trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_OK) {
321
322         String tempfile;
323         String::size_type pos = icon.rfind (SCIM_PATH_DELIM);
324
325         if (pos != String::npos) {
326             tempfile = icon.substr (pos + 1, String::npos);
327         } else {
328             tempfile = icon;
329         }
330
331         char tmp [80];
332         snprintf (tmp, 80, "%lu", (unsigned long) m_socket_magic_key);
333
334         tempfile = String (SCIM_TEMPDIR) + String (SCIM_PATH_DELIM_STRING) +
335                    String ("scim-") + String (tmp) + String ("-") +
336                    tempfile;
337
338         SCIM_DEBUG_IMENGINE(1) << "Creating temporary icon file: " << tempfile << "\n";
339
340         std::ofstream os (tempfile.c_str ());
341
342         if (os) {
343             os.write (bufptr, filesize);
344             os.close ();
345
346             // Check if the file is written correctly.
347             if (scim_load_file (tempfile, 0) == filesize) {
348                 m_icon_repository [icon] = tempfile;
349                 local_icon = tempfile;
350             } else {
351                 unlink (tempfile.c_str ());
352             }
353         }
354     }
355
356     delete [] bufptr;
357
358     return local_icon;
359 }
360
361 Connection
362 SocketIMEngineGlobal::connect_reconnect_signal (Slot0<void> *slot_reconnect)
363 {
364     return m_signal_reconnect.connect (slot_reconnect);
365 }
366
367 void
368 SocketIMEngineGlobal::destroy_all_icons ()
369 {
370     IconRepository::const_iterator it = m_icon_repository.begin ();
371
372     for (; it != m_icon_repository.end (); ++ it) {
373         unlink (it->second.c_str ());
374     }
375
376     m_icon_repository.clear ();
377 }
378
379 int
380 SocketFactory::create_peer_instance (const String &encoding)
381 {
382     int cmd;
383     int si_peer_id = -1;
384     uint32 val;
385     Transaction trans;
386
387     SCIM_DEBUG_IMENGINE(1) << "Create IMEngine Instance " << m_peer_uuid << ".\n";
388
389     global->init_transaction (trans);
390     trans.put_command (SCIM_TRANS_CMD_NEW_INSTANCE);
391     trans.put_data (m_peer_uuid);
392     trans.put_data (encoding);
393     if (global->send_transaction (trans)) {
394         if (global->receive_transaction (trans) &&
395             trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REPLY &&
396             trans.get_data (val) &&
397             trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_OK) {
398
399             si_peer_id = (int) val;
400         }
401     }
402
403     SCIM_DEBUG_IMENGINE(2) << " IMEngineInstance created (" << si_peer_id << ")\n";
404
405     return si_peer_id;
406 }
407
408 SocketFactory::SocketFactory (const String &peer_uuid)
409     : m_name (utf8_mbstowcs (_("Unknown"))),
410       m_language (String ("")),
411       m_peer_uuid (peer_uuid),
412       m_icon_file (String ("")),
413       m_ok (false)
414 {
415     String locales;
416     String iconfile;
417     Transaction trans;
418
419     SCIM_DEBUG_IMENGINE(1) << "Create SocketFactory " << peer_uuid << ".\n";
420
421     // Get factory name, locales, language and icon file.
422     std::map<String, ISEINFO>::iterator iter;
423     iter = ise_info_repository.find (m_peer_uuid);
424     if (iter != ise_info_repository.end ()) {
425         m_name = utf8_mbstowcs (iter->second.name);
426         set_locales (iter->second.locales);
427         m_language = iter->second.language;
428         //m_icon_file = global->load_icon (iter->second.icon);
429         m_ok = true;
430     } else {
431         m_language.clear ();
432     }
433 }
434
435 SocketFactory::~SocketFactory ()
436 {
437 }
438
439 WideString
440 SocketFactory::get_name () const
441 {
442     return m_name;
443 }
444
445 WideString
446 SocketFactory::get_authors () const
447 {
448     int cmd;
449     WideString authors;
450     Transaction trans;
451
452     SCIM_DEBUG_IMENGINE(1) << "Get Authors " << m_peer_uuid << ".\n";
453
454     // Get factory authors.
455     for (int retry = 0; retry < 3; ++retry) {
456         global->init_transaction (trans);
457         trans.put_command (SCIM_TRANS_CMD_GET_FACTORY_AUTHORS);
458         trans.put_data (m_peer_uuid);
459
460         if (global->send_transaction (trans) && global->receive_transaction (trans) &&
461             trans.get_command (cmd)  && cmd == SCIM_TRANS_CMD_REPLY &&
462             trans.get_data (authors) &&
463             trans.get_command (cmd)  && cmd == SCIM_TRANS_CMD_OK)
464             break;
465
466         authors = utf8_mbstowcs (_("Unknown"));
467
468         if (!global->create_connection ())
469             break;
470     }
471
472     return authors;
473 }
474
475 WideString
476 SocketFactory::get_credits () const
477 {
478     int cmd;
479     WideString credits;
480     Transaction trans;
481
482     SCIM_DEBUG_IMENGINE(1) << "Get Credits " << m_peer_uuid << ".\n";
483
484     // Get factory credits.
485     for (int retry = 0; retry < 3; ++retry) {
486         global->init_transaction (trans);
487         trans.put_command (SCIM_TRANS_CMD_GET_FACTORY_CREDITS);
488         trans.put_data (m_peer_uuid);
489
490         if (global->send_transaction (trans) && global->receive_transaction (trans) &&
491             trans.get_command (cmd)  && cmd == SCIM_TRANS_CMD_REPLY &&
492             trans.get_data (credits) &&
493             trans.get_command (cmd)  && cmd == SCIM_TRANS_CMD_OK)
494             break;
495
496         credits = utf8_mbstowcs (_("Unknown"));
497
498         if (!global->create_connection ())
499             break;
500     }
501
502     return credits;
503 }
504
505 WideString
506 SocketFactory::get_help () const
507 {
508     int cmd;
509     WideString help;
510     Transaction trans;
511
512     SCIM_DEBUG_IMENGINE(1) << "Get Help " << m_peer_uuid << ".\n";
513
514     // Get factory help.
515     for (int retry = 0; retry < 3; ++retry) {
516         global->init_transaction (trans);
517         trans.put_command (SCIM_TRANS_CMD_GET_FACTORY_HELP);
518         trans.put_data (m_peer_uuid);
519
520         if (global->send_transaction (trans) && global->receive_transaction (trans) &&
521             trans.get_command (cmd)  && cmd == SCIM_TRANS_CMD_REPLY &&
522             trans.get_data (help)    &&
523             trans.get_command (cmd)  && cmd == SCIM_TRANS_CMD_OK)
524             break;
525
526         help = utf8_mbstowcs (_("Unknown"));
527
528         if (!global->create_connection ())
529             break;
530     }
531
532     return help;
533 }
534
535 String
536 SocketFactory::get_uuid () const
537 {
538     return m_peer_uuid;
539 }
540
541 String
542 SocketFactory::get_icon_file () const
543 {
544     return m_icon_file;
545 }
546
547 String
548 SocketFactory::get_language () const
549 {
550     if (m_language.length ())
551         return m_language;
552     else
553         return IMEngineFactoryBase::get_language ();
554 }
555
556 IMEngineInstancePointer
557 SocketFactory::create_instance (const String& encoding, int id)
558 {
559     int si_peer_id = create_peer_instance (encoding);
560
561     SCIM_DEBUG_IMENGINE(2) << " IMEngineInstance created (" << si_peer_id << ")\n";
562
563     return new SocketInstance (this, encoding, id, si_peer_id);
564 }
565
566 SocketInstance::SocketInstance (SocketFactory *factory,
567                                 const String& encoding,
568                                 int           id,
569                                 int           peer_id)
570     : IMEngineInstanceBase (factory, encoding, id),
571       m_factory (factory),
572       m_peer_id (peer_id)
573 {
574     m_signal_reconnect_connection = global->connect_reconnect_signal (slot (this, &SocketInstance::reconnect_callback));
575 }
576
577 SocketInstance::~SocketInstance ()
578 {
579     Transaction trans;
580
581     SCIM_DEBUG_IMENGINE(1) << "Destroy IMEngine Instance " << m_peer_id << ".\n";
582
583     m_signal_reconnect_connection.disconnect ();
584
585     if (m_peer_id >= 0) {
586         global->init_transaction (trans);
587
588         trans.put_command (SCIM_TRANS_CMD_DELETE_INSTANCE);
589         trans.put_data (m_peer_id);
590
591         commit_transaction (trans);
592     }
593 }
594
595 bool
596 SocketInstance::process_key_event (const KeyEvent& key)
597 {
598     Transaction trans;
599
600     global->init_transaction (trans);
601
602     SCIM_DEBUG_IMENGINE(1) << "process_key_event (" << m_peer_id << ")\n";
603
604     trans.put_command (SCIM_TRANS_CMD_PROCESS_KEY_EVENT);
605     trans.put_data (m_peer_id);
606     trans.put_data (key);
607
608     return commit_transaction (trans);
609 }
610
611 void
612 SocketInstance::move_preedit_caret (unsigned int pos)
613 {
614     Transaction trans;
615
616     global->init_transaction (trans);
617
618     SCIM_DEBUG_IMENGINE(1) << "move_preedit_caret (" << m_peer_id << ")\n";
619
620     trans.put_command (SCIM_TRANS_CMD_MOVE_PREEDIT_CARET);
621     trans.put_data (m_peer_id);
622     trans.put_data ((uint32) pos);
623
624     commit_transaction (trans);
625 }
626
627 void
628 SocketInstance::select_aux (unsigned int item)
629 {
630     Transaction trans;
631
632     global->init_transaction (trans);
633
634     SCIM_DEBUG_IMENGINE(1) << "select_aux (" << m_peer_id << ")\n";
635
636     trans.put_command (ISM_TRANS_CMD_SELECT_AUX);
637     trans.put_data (m_peer_id);
638     trans.put_data ((uint32) item);
639
640     commit_transaction (trans);
641 }
642
643 void
644 SocketInstance::select_candidate (unsigned int item)
645 {
646     Transaction trans;
647
648     global->init_transaction (trans);
649
650     SCIM_DEBUG_IMENGINE(1) << "select_candidate (" << m_peer_id << ")\n";
651
652     trans.put_command (SCIM_TRANS_CMD_SELECT_CANDIDATE);
653     trans.put_data (m_peer_id);
654     trans.put_data ((uint32) item);
655
656     commit_transaction (trans);
657 }
658
659 void
660 SocketInstance::update_lookup_table_page_size (unsigned int page_size)
661 {
662     Transaction trans;
663
664     global->init_transaction (trans);
665
666     SCIM_DEBUG_IMENGINE(1) << "update_lookup_table_page_size (" << m_peer_id << ")\n";
667
668     trans.put_command (SCIM_TRANS_CMD_UPDATE_LOOKUP_TABLE_PAGE_SIZE);
669     trans.put_data (m_peer_id);
670     trans.put_data ((uint32) page_size);
671
672     commit_transaction (trans);
673 }
674
675 void
676 SocketInstance::lookup_table_page_up ()
677 {
678     Transaction trans;
679
680     global->init_transaction (trans);
681
682     SCIM_DEBUG_IMENGINE(1) << "lookup_table_page_up (" << m_peer_id << ")\n";
683
684     trans.put_command (SCIM_TRANS_CMD_LOOKUP_TABLE_PAGE_UP);
685     trans.put_data (m_peer_id);
686
687     commit_transaction (trans);
688 }
689
690 void
691 SocketInstance::lookup_table_page_down ()
692 {
693     Transaction trans;
694
695     global->init_transaction (trans);
696
697     SCIM_DEBUG_IMENGINE(1) << "lookup_table_page_up (" << m_peer_id << ")\n";
698
699     trans.put_command (SCIM_TRANS_CMD_LOOKUP_TABLE_PAGE_DOWN);
700     trans.put_data (m_peer_id);
701
702     commit_transaction (trans);
703 }
704
705 void
706 SocketInstance::set_prediction_allow (bool allow)
707 {
708     Transaction trans;
709
710     global->init_transaction (trans);
711
712     SCIM_DEBUG_IMENGINE(1) << __func__<< " (" << m_peer_id << ")\n";
713
714     trans.put_command (ISM_TRANS_CMD_SET_PREDICTION_ALLOW);
715     trans.put_data (m_peer_id);
716     trans.put_data ((uint32) allow);
717
718     commit_transaction (trans);
719 }
720
721 void
722 SocketInstance::set_layout (unsigned int layout)
723 {
724     Transaction trans;
725
726     global->init_transaction (trans);
727
728     SCIM_DEBUG_IMENGINE(1) << __func__<< " (" << m_peer_id << ")\n";
729
730     trans.put_command (ISM_TRANS_CMD_SET_LAYOUT);
731     trans.put_data (m_peer_id);
732     trans.put_data (layout);
733
734     commit_transaction (trans);
735 }
736
737 void
738 SocketInstance::reset_option ()
739 {
740     Transaction trans;
741
742     global->init_transaction (trans);
743
744     SCIM_DEBUG_IMENGINE(1) << "reset_option (" << m_peer_id << ")\n";
745
746     trans.put_command (ISM_TRANS_CMD_RESET_ISE_OPTION);
747     trans.put_data (m_peer_id);
748
749     commit_transaction (trans);
750 }
751
752 void
753 SocketInstance::reset ()
754 {
755     Transaction trans;
756
757     global->init_transaction (trans);
758
759     SCIM_DEBUG_IMENGINE(1) << "reset (" << m_peer_id << ")\n";
760
761     trans.put_command (SCIM_TRANS_CMD_RESET);
762     trans.put_data (m_peer_id);
763
764     commit_transaction (trans);
765 }
766
767 void
768 SocketInstance::focus_in ()
769 {
770     Transaction trans;
771
772     global->init_transaction (trans);
773
774     SCIM_DEBUG_IMENGINE(1) << "focus_in (" << m_peer_id << ")\n";
775
776     trans.put_command (SCIM_TRANS_CMD_FOCUS_IN);
777     trans.put_data (m_peer_id);
778
779     commit_transaction (trans);
780 }
781
782 void
783 SocketInstance::focus_out ()
784 {
785     Transaction trans;
786
787     global->init_transaction (trans);
788
789     SCIM_DEBUG_IMENGINE(1) << "focus_out (" << m_peer_id << ")\n";
790
791     trans.put_command (SCIM_TRANS_CMD_FOCUS_OUT);
792     trans.put_data (m_peer_id);
793
794     commit_transaction (trans);
795 }
796
797 void
798 SocketInstance::trigger_property (const String &property)
799 {
800     Transaction trans;
801
802     global->init_transaction (trans);
803
804     SCIM_DEBUG_IMENGINE(1) << "trigger_property (" << m_peer_id << ", " << property << ")\n";
805
806     trans.put_command (SCIM_TRANS_CMD_TRIGGER_PROPERTY);
807     trans.put_data (m_peer_id);
808     trans.put_data (property);
809
810     commit_transaction (trans);
811 }
812
813 void
814 SocketInstance::process_helper_event (const String &helper_uuid, const Transaction &helper_trans)
815 {
816     Transaction trans;
817
818     global->init_transaction (trans);
819
820     SCIM_DEBUG_IMENGINE(1) << "process_helper_event (" << m_peer_id << ", " << helper_uuid << ")\n";
821
822     trans.put_command (SCIM_TRANS_CMD_PROCESS_HELPER_EVENT);
823     trans.put_data (m_peer_id);
824     trans.put_data (helper_uuid);
825     trans.put_data (helper_trans);
826
827     commit_transaction (trans);
828 }
829
830 void
831 SocketInstance::update_client_capabilities (unsigned int cap)
832 {
833     Transaction trans;
834
835     global->init_transaction (trans);
836
837     SCIM_DEBUG_IMENGINE(1) << "update_client_capabilities (" << m_peer_id << ", " << cap << ")\n";
838
839     trans.put_command (SCIM_TRANS_CMD_UPDATE_CLIENT_CAPABILITIES);
840     trans.put_data (m_peer_id);
841     trans.put_data ((uint32) cap);
842
843     commit_transaction (trans);
844 }
845
846 bool
847 SocketInstance::commit_transaction (Transaction &trans)
848 {
849     SCIM_DEBUG_IMENGINE(2) << " commit_transaction:\n";
850
851     bool ret = false;
852
853     if (m_peer_id >= 0) {
854         if (global->send_transaction (trans)) {
855             while (1) {
856                 if (!global->receive_transaction (trans)) break;
857                 if (!do_transaction (trans, ret)) return ret;
858             }
859         }
860     }
861
862     if (global->create_connection ())
863         reset ();
864
865     return ret;
866 }
867
868 bool
869 SocketInstance::do_transaction (Transaction &trans, bool &ret)
870 {
871     int cmd = -1;
872     bool cont = false;
873
874     ret = false;
875
876     SCIM_DEBUG_IMENGINE(2) << " Do transaction:\n";
877
878     if (trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REPLY) {
879         while (trans.get_command (cmd)) {
880             switch (cmd) {
881                 case SCIM_TRANS_CMD_SHOW_PREEDIT_STRING:
882                 {
883                     SCIM_DEBUG_IMENGINE(3) << "  show_preedit_string ()\n";
884                     show_preedit_string ();
885                     break;
886                 }
887                 case SCIM_TRANS_CMD_SHOW_AUX_STRING:
888                 {
889                     SCIM_DEBUG_IMENGINE(3) << "  show_aux_string ()\n";
890                     show_aux_string ();
891                     break;
892                 }
893                 case SCIM_TRANS_CMD_SHOW_LOOKUP_TABLE:
894                 {
895                     SCIM_DEBUG_IMENGINE(3) << "  show_lookup_table ()\n";
896                     show_lookup_table ();
897                     break;
898                 }
899                 case SCIM_TRANS_CMD_HIDE_PREEDIT_STRING:
900                 {
901                     SCIM_DEBUG_IMENGINE(3) << "  hide_preedit_string ()\n";
902                     hide_preedit_string ();
903                     break;
904                 }
905                 case SCIM_TRANS_CMD_HIDE_AUX_STRING:
906                 {
907                     SCIM_DEBUG_IMENGINE(3) << "  hide_aux_string ()\n";
908                     hide_aux_string ();
909                     break;
910                 }
911                 case SCIM_TRANS_CMD_HIDE_LOOKUP_TABLE:
912                 {
913                     SCIM_DEBUG_IMENGINE(3) << "  hide_lookup_table ()\n";
914                     hide_lookup_table ();
915                     break;
916                 }
917                 case SCIM_TRANS_CMD_UPDATE_PREEDIT_CARET:
918                 {
919                     uint32 caret;
920                     if (trans.get_data (caret)) {
921                         SCIM_DEBUG_IMENGINE(3) << "  update_preedit_caret (" << caret << ")\n";
922                         update_preedit_caret (caret);
923                     }
924                     break;
925                 }
926                 case SCIM_TRANS_CMD_UPDATE_PREEDIT_STRING:
927                 {
928                     WideString str;
929                     AttributeList attrs;
930                     if (trans.get_data (str) && trans.get_data (attrs)) {
931                         SCIM_DEBUG_IMENGINE(3) << "  update_preedit_string ()\n";
932                         update_preedit_string (str, attrs);
933                     }
934                     break;
935                 }
936                 case SCIM_TRANS_CMD_UPDATE_AUX_STRING:
937                 {
938                     WideString str;
939                     AttributeList attrs;
940                     if (trans.get_data (str) && trans.get_data (attrs)) {
941                         SCIM_DEBUG_IMENGINE(3) << "  update_aux_string ()\n";
942                         update_aux_string (str, attrs);
943                     }
944                     break;
945                 }
946                 case SCIM_TRANS_CMD_UPDATE_LOOKUP_TABLE:
947                 {
948                     CommonLookupTable table;
949                     if (trans.get_data (table)) {
950                         SCIM_DEBUG_IMENGINE(3) << "  update_lookup_table ()\n";
951                         update_lookup_table (table);
952                     }
953                     break;
954                 }
955                 case SCIM_TRANS_CMD_COMMIT_STRING:
956                 {
957                     WideString str;
958                     if (trans.get_data (str)) {
959                         SCIM_DEBUG_IMENGINE(3) << "  commit_string ()\n";
960                         commit_string (str);
961                     }
962                     break;
963                 }
964                 case SCIM_TRANS_CMD_FORWARD_KEY_EVENT:
965                 {
966                     KeyEvent key;
967                     if (trans.get_data (key)) {
968                         SCIM_DEBUG_IMENGINE(3) << "  forward_key_event ()\n";
969                         forward_key_event (key);
970                     }
971                     break;
972                 }
973                 case SCIM_TRANS_CMD_REGISTER_PROPERTIES:
974                 {
975                     PropertyList proplist;
976                     if (trans.get_data (proplist)) {
977                         SCIM_DEBUG_IMENGINE(3) << "  register_properties ()\n";
978
979                         // Load icon files of these properties from remote SocketFrontEnd.
980                         for (PropertyList::iterator it = proplist.begin (); it != proplist.end (); ++it)
981                             it->set_icon (global->load_icon (it->get_icon ()));
982
983                         register_properties (proplist);
984                     }
985                     break;
986                 }
987                 case SCIM_TRANS_CMD_UPDATE_PROPERTY:
988                 {
989                     Property prop;
990                     if (trans.get_data (prop)) {
991                         SCIM_DEBUG_IMENGINE(3) << "  update_property ()\n";
992
993                         // Load the icon file of this property from remote SocketFrontEnd.
994                         prop.set_icon (global->load_icon (prop.get_icon ()));
995
996                         update_property (prop);
997                     }
998                     break;
999                 }
1000                 case SCIM_TRANS_CMD_BEEP:
1001                 {
1002                     SCIM_DEBUG_IMENGINE(3) << "  beep ()\n";
1003                     beep ();
1004                     break;
1005                 }
1006                 case SCIM_TRANS_CMD_START_HELPER:
1007                 {
1008                     String helper_uuid;
1009                     if (trans.get_data (helper_uuid)) {
1010                         SCIM_DEBUG_IMENGINE(3) << "  start_helper (" << helper_uuid << ")\n";
1011                         start_helper (helper_uuid);
1012                     }
1013                     break;
1014                 }
1015                 case SCIM_TRANS_CMD_STOP_HELPER:
1016                 {
1017                     String helper_uuid;
1018                     if (trans.get_data (helper_uuid)) {
1019                         SCIM_DEBUG_IMENGINE(3) << "  stop_helper (" << helper_uuid << ")\n";
1020                         stop_helper (helper_uuid);
1021                     }
1022                     break;
1023                 }
1024                 case SCIM_TRANS_CMD_SEND_HELPER_EVENT:
1025                 {
1026                     String helper_uuid;
1027                     Transaction temp_trans;
1028                     if (trans.get_data (helper_uuid) && trans.get_data (temp_trans)) {
1029                         SCIM_DEBUG_IMENGINE(3) << "  send_helper_event (" << helper_uuid << ")\n";
1030                         send_helper_event (helper_uuid, temp_trans);
1031                     }
1032                     break;
1033                 }
1034                 case SCIM_TRANS_CMD_OK:
1035                 {
1036                     SCIM_DEBUG_IMENGINE(3) << "  ret = true\n";
1037                     ret = true;
1038                     break;
1039                 }
1040                 case SCIM_TRANS_CMD_GET_SURROUNDING_TEXT:
1041                 {
1042                     WideString text;
1043                     int cursor;
1044                     uint32 maxlen_before;
1045                     uint32 maxlen_after;
1046                     Transaction temp_trans;
1047                     if (trans.get_data (maxlen_before) && trans.get_data (maxlen_after)) {
1048                         global->init_transaction (temp_trans);
1049                         if (get_surrounding_text (text, cursor, (int) maxlen_before, (int) maxlen_after)) {
1050                             temp_trans.put_command (SCIM_TRANS_CMD_GET_SURROUNDING_TEXT);
1051                             temp_trans.put_data (text);
1052                             temp_trans.put_data ((uint32) cursor);
1053                         } else {
1054                             temp_trans.put_command (SCIM_TRANS_CMD_FAIL);
1055                         }
1056                         if (!global->send_transaction (temp_trans))
1057                             std::cerr << "GET_SURROUNDING_TEXT: global->send_transaction () is failed!!!\n";
1058                     }
1059                     cont = true;
1060                     break;
1061                 }
1062                 case SCIM_TRANS_CMD_DELETE_SURROUNDING_TEXT:
1063                 {
1064                     uint32 offset;
1065                     uint32 len;
1066                     Transaction temp_trans;
1067                     if (trans.get_data (offset) && trans.get_data (len)) {
1068                         global->init_transaction (temp_trans);
1069                         if (delete_surrounding_text ((int) offset, (int) len)) {
1070                             temp_trans.put_command (SCIM_TRANS_CMD_DELETE_SURROUNDING_TEXT);
1071                             temp_trans.put_command (SCIM_TRANS_CMD_OK);
1072                         } else {
1073                             temp_trans.put_command (SCIM_TRANS_CMD_FAIL);
1074                         }
1075                         if (!global->send_transaction (temp_trans))
1076                             std::cerr << "DELETE_SURROUNDING_TEXT: global->send_transaction () is failed!!!\n";
1077                     }
1078                     cont = true;
1079                     break;
1080                 }
1081                 default:
1082                     SCIM_DEBUG_IMENGINE(3) << "  Strange cmd: " << cmd << "\n";;
1083             }
1084         }
1085     } else {
1086         SCIM_DEBUG_IMENGINE(3) << "  Failed to get cmd: " << cmd << "\n";
1087     }
1088
1089     SCIM_DEBUG_IMENGINE(2) << " End of Do transaction\n";
1090
1091     return cont;
1092 }
1093
1094 void
1095 SocketInstance::reconnect_callback (void)
1096 {
1097     m_peer_id = m_factory->create_peer_instance (get_encoding ());
1098 }
1099
1100 } // namespace scim
1101
1102 /*
1103 vi:ts=4:nowrap:ai:expandtab
1104 */