b410b5061e08cd1ae1edd87f685bb1279da2a42e
[profile/ivi/isf.git] / ism / modules / frontend / scim_socket_frontend.cpp
1 /** @file scim_socket_frontend.cpp
2  * implementation of class SocketFrontEnd.
3  */
4 /* ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable. */
5
6 /*
7  * Smart Common Input Method
8  * 
9  * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
10  *
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this program; if not, write to the
24  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
25  * Boston, MA  02111-1307  USA
26  *
27  * $Id: scim_socket_frontend.cpp,v 1.37 2005/07/03 08:36:42 suzhe Exp $
28  *
29  */
30
31 #define Uses_SCIM_CONFIG_PATH
32 #define Uses_SCIM_FRONTEND
33 #define Uses_SCIM_SOCKET
34 #define Uses_SCIM_TRANSACTION
35 #define Uses_STL_UTILITY
36 #define Uses_C_STDIO
37 #define Uses_C_STDLIB
38 #define Uses_SCIM_CONFIG_BASE
39 #define Uses_SCIM_UTILITY
40 #define Uses_SCIM_IMENGINE_MODULE
41 #define Uses_SCIM_PANEL_AGENT
42
43 #include <string.h>
44
45 #include <limits.h>
46 #include "scim_private.h"
47 #include "scim.h"
48 #include "scim_socket_frontend.h"
49 #include "scim_helper.h"
50 #include "scim_helper_module.h"
51 #include "isf_query_utility.h"
52 #include <sys/time.h>
53 #include <sys/times.h>
54 #include <sys/wait.h>
55 #include <unistd.h>
56 #include <signal.h>
57
58 #define scim_module_init socket_LTX_scim_module_init
59 #define scim_module_exit socket_LTX_scim_module_exit
60 #define scim_frontend_module_init socket_LTX_scim_frontend_module_init
61 #define scim_frontend_module_run socket_LTX_scim_frontend_module_run
62
63 #define SCIM_CONFIG_FRONTEND_SOCKET_CONFIG_READONLY    "/FrontEnd/Socket/ConfigReadOnly"
64 #define SCIM_CONFIG_FRONTEND_SOCKET_MAXCLIENTS         "/FrontEnd/Socket/MaxClients"
65
66 using namespace scim;
67
68 static Pointer <SocketFrontEnd> _scim_frontend (0);
69
70 static int      _argc;
71 static char   **_argv = NULL;
72
73 //Module Interface
74 extern "C" {
75     void scim_module_init (void)
76     {
77         SCIM_DEBUG_FRONTEND(1) << "Initializing Socket FrontEnd module...\n";
78     }
79
80     void scim_module_exit (void)
81     {
82         SCIM_DEBUG_FRONTEND(1) << "Exiting Socket FrontEnd module...\n";
83         _scim_frontend.reset ();
84     }
85
86     void scim_frontend_module_init (const BackEndPointer &backend,
87                                     const ConfigPointer &config,
88                                     int argc,
89                                     char **argv)
90     {
91         if (_scim_frontend.null ()) {
92             SCIM_DEBUG_FRONTEND(1) << "Initializing Socket FrontEnd module (more)...\n";
93             _scim_frontend = new SocketFrontEnd (backend, config);
94             _argc = argc;
95             _argv = argv;
96         }
97     }
98
99     void scim_frontend_module_run (void)
100     {
101         struct tms tiks_buf;
102         clock_t start = times (&tiks_buf);
103         if (!_scim_frontend.null ()) {
104             SCIM_DEBUG_FRONTEND(1) << "Starting Socket FrontEnd module...\n";
105             _scim_frontend->init (_argc, _argv);
106             gettime (start, "Init socket frontend");
107             _scim_frontend->run ();
108         }
109     }
110 }
111
112 /**
113  * To reduce the number of the servers, we merge the function of 
114  * HelperManager process into the SocketFrontEnd.
115 */
116
117 typedef std::vector < std::pair <HelperInfo, String> >                      HelperRepository;
118
119 static HelperRepository     __helpers;
120 static std::vector<String>  __load_engine_list;
121
122 void SocketFrontEnd::load_helper_modules (const std::vector<String> &load_engine_list)
123 {
124     SCIM_DEBUG_MAIN (1) << "load_helper_modules ()\n";
125     
126     size_t i;
127
128     __load_engine_list.clear ();
129     for (i = 0; i < load_engine_list.size (); ++i)
130         __load_engine_list.push_back (load_engine_list [i]);
131
132     std::vector <String> mod_list;
133     std::vector <String> all_helper_list;
134
135     scim_get_helper_module_list (all_helper_list);
136
137     // Get the helper module list which should be loaded.
138     if (load_engine_list.size () && all_helper_list.size ()) {
139         for (i = 0; i < all_helper_list.size (); ++i) {
140             if (std::find (load_engine_list.begin (),
141                            load_engine_list.end (),
142                            all_helper_list [i]) != load_engine_list.end ())
143                 mod_list.push_back (all_helper_list [i]);
144         }
145     }
146
147     if (mod_list.size ()) {
148         HelperInfo           info;
149         std::vector<ISEINFO> info_list;
150         std::vector<String>  tmp_list;
151         isf_read_ise_info_list (USER_ENGINE_FILE_NAME, info_list);
152         for (size_t i = 0; i < info_list.size (); ++i) {
153             if (info_list [i].mode != TOOLBAR_HELPER_MODE)
154                 continue;
155             if (std::find (mod_list.begin (), mod_list.end (), info_list [i].module) != mod_list.end ()) {
156                 info.uuid   = info_list [i].uuid;
157                 info.name   = info_list [i].name;
158                 info.icon   = info_list [i].icon;
159                 info.option = info_list [i].option;
160                 SCIM_DEBUG_MAIN (3) << "  " << info.uuid << ": " << info.name << "\n";
161                 __helpers.push_back (std::make_pair (info, info_list [i].module));
162                 tmp_list.push_back (info_list [i].module);
163             }
164         }
165
166         HelperModule module;
167
168         for (size_t i = 0; i < mod_list.size (); ++i) {
169             if (std::find (tmp_list.begin (), tmp_list.end (), mod_list [i]) != tmp_list.end ())
170                 continue;
171
172             SCIM_DEBUG_MAIN (2) << " Load module: " << mod_list [i] << "\n";
173
174             if (module.load (mod_list [i]) && module.valid ()) {
175                 size_t num = module.number_of_helpers ();
176
177                 SCIM_DEBUG_MAIN (2) << " Find " << num << " Helpers:\n";
178
179                 for (size_t j = 0; j < num; ++j) {
180                     if (module.get_helper_info (j, info)) {
181                         SCIM_DEBUG_MAIN (3) << "  " << info.uuid << ": " << info.name << "\n";
182                         __helpers.push_back (std::make_pair (info, mod_list [i]));
183                     }
184                 }
185             }
186
187             module.unload ();
188         }
189     }
190 }
191
192 void SocketFrontEnd::get_helper_list (const Socket &client)
193 {
194     HelperRepository::iterator it = __helpers.begin ();
195
196     m_send_trans.clear ();
197     m_send_trans.put_command (SCIM_TRANS_CMD_REPLY);
198     m_send_trans.put_data ((uint32)__helpers.size ());
199
200     for (; it != __helpers.end (); ++it) {
201         m_send_trans.put_data (it->first.uuid);
202         m_send_trans.put_data (it->first.name);
203         m_send_trans.put_data (it->first.icon);
204         m_send_trans.put_data (it->first.description);
205         m_send_trans.put_data (it->first.option);
206     }
207 }
208
209 #ifndef SCIM_HELPER_LAUNCHER_PROGRAM
210   #define SCIM_HELPER_LAUNCHER_PROGRAM  (SCIM_LIBEXECDIR "/scim-helper-launcher")
211 #endif
212 static std::vector<String>  __active_helpers;
213
214 void SocketFrontEnd::run_helper (const Socket &client)
215 {
216     String uuid;
217     String config;
218     String display;
219     if (!(m_receive_trans.get_data (uuid) && uuid.length ()
220              && m_receive_trans.get_data (config)
221              && m_receive_trans.get_data (display)))
222     {
223         m_send_trans.put_command (SCIM_TRANS_CMD_FAIL);
224         return;
225     }
226
227     for (size_t i = 0; i < __helpers.size (); ++i) {
228         if (__helpers [i].first.uuid == uuid && __helpers [i].second.length ()) {
229
230             __active_helpers.push_back(__helpers [i].first.name);
231
232             int pid;
233
234             pid = fork ();
235
236             if (pid < 0) return;
237
238             if (pid == 0) {
239                 const char *argv [] = { SCIM_HELPER_LAUNCHER_PROGRAM,
240                                    "--daemon",
241                                    "--config", const_cast<char*> (config.c_str ()),
242                                    "--display", const_cast<char*> (display.c_str ()),
243                                    const_cast<char*> (__helpers [i].second.c_str ()),
244                                    const_cast<char*> (__helpers [i].first.uuid.c_str ()),
245                                    0};
246
247                 SCIM_DEBUG_MAIN(2) << " Call scim-helper-launcher.\n";
248
249                 execv (SCIM_HELPER_LAUNCHER_PROGRAM, (char **)argv);
250                 exit (-1);
251             }
252
253             //int status;
254             //waitpid (pid, &status, 0);
255
256             break;
257         }
258     }
259
260     m_send_trans.put_command (SCIM_TRANS_CMD_OK);
261     SCIM_DEBUG_MAIN(2) << " exit run_helper ().\n";
262 }
263
264 /**
265  * get_active_ise_list
266  * Get the active ise list. we can control the loading of ISEs through
267  * the command option "-e" of scim process.
268  */
269 void
270 SocketFrontEnd::get_active_ise_list (int clientid)
271 {
272     m_send_trans.put_data (__load_engine_list);
273 }
274
275 void
276 SocketFrontEnd::unregister_helper ()
277 {
278     String name;
279     if (m_receive_trans.get_data (name) && name.length ())
280     {
281         std::vector<String>::iterator iter = __active_helpers.begin ();
282         for (; iter != __active_helpers.end (); iter++)
283         {
284             if (!name.compare (*iter))
285             {
286                 __active_helpers.erase (iter);
287                 break;
288             }
289         }
290     }
291
292     m_send_trans.put_command (SCIM_TRANS_CMD_OK);
293 }
294
295 SocketFrontEnd::SocketFrontEnd (const BackEndPointer &backend,
296                                 const ConfigPointer  &config)
297     : FrontEndBase (backend),
298       m_config (config),
299       m_stay (true),
300       m_config_readonly (false),
301       m_socket_timeout (scim_get_default_socket_timeout ()),
302       m_current_instance (-1),
303       m_current_socket_client (-1),
304       m_current_socket_client_key (0)
305 {
306     SCIM_DEBUG_FRONTEND (2) << " Constructing SocketFrontEnd object...\n";
307 }
308
309 SocketFrontEnd::~SocketFrontEnd ()
310 {
311     SCIM_DEBUG_FRONTEND (2) << " Destructing SocketFrontEnd object...\n";
312     if (m_socket_server.is_running ())
313         m_socket_server.shutdown ();
314 }
315
316 void
317 SocketFrontEnd::show_preedit_string (int id)
318 {
319     if (m_current_instance == id)
320         m_send_trans.put_command (SCIM_TRANS_CMD_SHOW_PREEDIT_STRING);
321 }
322
323 void
324 SocketFrontEnd::show_aux_string (int id)
325 {
326     if (m_current_instance == id)
327         m_send_trans.put_command (SCIM_TRANS_CMD_SHOW_AUX_STRING);
328 }
329
330 void
331 SocketFrontEnd::show_lookup_table (int id)
332 {
333     if (m_current_instance == id)
334         m_send_trans.put_command (SCIM_TRANS_CMD_SHOW_LOOKUP_TABLE);
335 }
336
337 void
338 SocketFrontEnd::hide_preedit_string (int id)
339 {
340     if (m_current_instance == id)
341         m_send_trans.put_command (SCIM_TRANS_CMD_HIDE_PREEDIT_STRING);
342 }
343
344 void
345 SocketFrontEnd::hide_aux_string (int id)
346 {
347     if (m_current_instance == id)
348         m_send_trans.put_command (SCIM_TRANS_CMD_HIDE_AUX_STRING);
349 }
350
351 void
352 SocketFrontEnd::hide_lookup_table (int id)
353 {
354     if (m_current_instance == id)
355         m_send_trans.put_command (SCIM_TRANS_CMD_HIDE_LOOKUP_TABLE);
356 }
357
358 void
359 SocketFrontEnd::update_preedit_caret (int id, int caret)
360 {
361     if (m_current_instance == id) {
362         m_send_trans.put_command (SCIM_TRANS_CMD_UPDATE_PREEDIT_CARET);
363         m_send_trans.put_data ((uint32) caret);
364     }
365 }
366
367 void
368 SocketFrontEnd::update_preedit_string (int id,
369                                        const WideString & str,
370                                        const AttributeList & attrs)
371 {
372     if (m_current_instance == id) {
373         m_send_trans.put_command (SCIM_TRANS_CMD_UPDATE_PREEDIT_STRING);
374         m_send_trans.put_data (str);
375         m_send_trans.put_data (attrs);
376     }
377 }
378
379 void
380 SocketFrontEnd::update_aux_string (int id,
381                                    const WideString & str,
382                                    const AttributeList & attrs)
383 {
384     if (m_current_instance == id) {
385         m_send_trans.put_command (SCIM_TRANS_CMD_UPDATE_AUX_STRING);
386         m_send_trans.put_data (str);
387         m_send_trans.put_data (attrs);
388     }
389 }
390
391 void
392 SocketFrontEnd::commit_string (int id, const WideString & str)
393 {
394     if (m_current_instance == id) {
395         m_send_trans.put_command (SCIM_TRANS_CMD_COMMIT_STRING);
396         m_send_trans.put_data (str);
397     }
398 }
399
400 void
401 SocketFrontEnd::forward_key_event (int id, const KeyEvent & key)
402 {
403     if (m_current_instance == id) {
404         m_send_trans.put_command (SCIM_TRANS_CMD_FORWARD_KEY_EVENT);
405         m_send_trans.put_data (key);
406     }
407 }
408
409 void
410 SocketFrontEnd::update_lookup_table (int id, const LookupTable & table)
411 {
412     if (m_current_instance == id) {
413         m_send_trans.put_command (SCIM_TRANS_CMD_UPDATE_LOOKUP_TABLE);
414         m_send_trans.put_data (table);
415     }
416 }
417
418 void
419 SocketFrontEnd::register_properties (int id, const PropertyList &properties)
420 {
421     if (m_current_instance == id) {
422         m_send_trans.put_command (SCIM_TRANS_CMD_REGISTER_PROPERTIES);
423         m_send_trans.put_data (properties);
424     }
425 }
426
427 void
428 SocketFrontEnd::update_property (int id, const Property &property)
429 {
430     if (m_current_instance == id) {
431         m_send_trans.put_command (SCIM_TRANS_CMD_UPDATE_PROPERTY);
432         m_send_trans.put_data (property);
433     }
434 }
435
436 void
437 SocketFrontEnd::beep (int id)
438 {
439     if (m_current_instance == id) {
440         m_send_trans.put_command (SCIM_TRANS_CMD_BEEP);
441     }
442 }
443
444 void
445 SocketFrontEnd::start_helper (int id, const String &helper_uuid)
446 {
447     SCIM_DEBUG_FRONTEND (2) << "start_helper (" << helper_uuid << ")\n";
448     if (m_current_instance == id) {
449         m_send_trans.put_command (SCIM_TRANS_CMD_START_HELPER);
450         m_send_trans.put_data (helper_uuid);
451     }
452 }
453
454 void
455 SocketFrontEnd::stop_helper (int id, const String &helper_uuid)
456 {
457     SCIM_DEBUG_FRONTEND (2) << "stop_helper (" << helper_uuid << ")\n";
458
459     if (m_current_instance == id) {
460         m_send_trans.put_command (SCIM_TRANS_CMD_STOP_HELPER);
461         m_send_trans.put_data (helper_uuid);
462     }
463 }
464
465 void
466 SocketFrontEnd::send_helper_event (int id, const String &helper_uuid, const Transaction &trans)
467 {
468     if (m_current_instance == id) {
469         m_send_trans.put_command (SCIM_TRANS_CMD_SEND_HELPER_EVENT);
470         m_send_trans.put_data (helper_uuid);
471         m_send_trans.put_data (trans);
472     }
473 }
474
475 bool
476 SocketFrontEnd::get_surrounding_text (int id, WideString &text, int &cursor, int maxlen_before, int maxlen_after)
477 {
478     text.clear ();
479     cursor = 0;
480
481     if (m_current_instance == id && m_current_socket_client >= 0 && (maxlen_before != 0 || maxlen_after != 0)) {
482         if (maxlen_before < 0) maxlen_before = -1;
483         if (maxlen_after < 0) maxlen_after = -1;
484
485         m_temp_trans.clear ();
486         m_temp_trans.put_command (SCIM_TRANS_CMD_REPLY);
487         m_temp_trans.put_command (SCIM_TRANS_CMD_GET_SURROUNDING_TEXT);
488         m_temp_trans.put_data ((uint32) maxlen_before);
489         m_temp_trans.put_data ((uint32) maxlen_after);
490
491         Socket socket_client (m_current_socket_client);
492
493         if (m_temp_trans.write_to_socket (socket_client) &&
494             m_temp_trans.read_from_socket (socket_client, m_socket_timeout)) {
495
496             int cmd;
497             uint32 key;
498             uint32 cur;
499
500             if (m_temp_trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REQUEST &&
501                 m_temp_trans.get_data (key) && key == m_current_socket_client_key &&
502                 m_temp_trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_GET_SURROUNDING_TEXT &&
503                 m_temp_trans.get_data (text) && m_temp_trans.get_data (cur)) {
504                 cursor = (int) cur;
505                 return true;
506             }
507         }
508     }
509     return false;
510 }
511
512 bool
513 SocketFrontEnd::delete_surrounding_text (int id, int offset, int len)
514 {
515     if (m_current_instance == id && m_current_socket_client >= 0 && len > 0) {
516         m_temp_trans.clear ();
517         m_temp_trans.put_command (SCIM_TRANS_CMD_REPLY);
518         m_temp_trans.put_command (SCIM_TRANS_CMD_DELETE_SURROUNDING_TEXT);
519         m_temp_trans.put_data ((uint32) offset);
520         m_temp_trans.put_data ((uint32) len);
521
522         Socket socket_client (m_current_socket_client);
523
524         if (m_temp_trans.write_to_socket (socket_client) &&
525             m_temp_trans.read_from_socket (socket_client, m_socket_timeout)) {
526
527             int cmd;
528             uint32 key;
529
530             if (m_temp_trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REQUEST &&
531                 m_temp_trans.get_data (key) && key == m_current_socket_client_key &&
532                 m_temp_trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_DELETE_SURROUNDING_TEXT &&
533                 m_temp_trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_OK)
534                 return true;
535         }
536     }
537     return false;
538 }
539
540 void
541 SocketFrontEnd::init (int argc, char **argv)
542 {
543     int max_clients = -1;
544
545     std::vector<String> engine_list;
546
547     if (!m_config.null ()) {
548         String str;
549
550         m_config_readonly = m_config->read (String (SCIM_CONFIG_FRONTEND_SOCKET_CONFIG_READONLY), false);
551
552         max_clients = m_config->read (String (SCIM_CONFIG_FRONTEND_SOCKET_MAXCLIENTS), -1);
553
554         m_config->signal_connect_reload (slot (this, &SocketFrontEnd::reload_config_callback));
555     } else {
556         m_config_readonly = false;
557         max_clients = -1;
558     }
559
560     if (!m_socket_server.create (scim_get_default_socket_frontend_address ()))
561         throw FrontEndError ("SocketFrontEnd -- Cannot create SocketServer.");
562
563     m_socket_server.set_max_clients (max_clients);
564
565     m_socket_server.signal_connect_accept (
566         slot (this, &SocketFrontEnd::socket_accept_callback));
567
568     m_socket_server.signal_connect_receive (
569         slot (this, &SocketFrontEnd::socket_receive_callback));
570
571     m_socket_server.signal_connect_exception(
572         slot (this, &SocketFrontEnd::socket_exception_callback));
573
574     if (argv && argc > 1) {
575         for (int i = 1; i < argc && argv [i]; ++i) {
576             if (String ("-e") == argv [i] || String ("--engines") == argv [i]) {
577                 if (++i >= argc) {
578                     std::cerr << "No argument for option " << argv [i-1] << "\n";
579                     break;
580                 }
581                 if (String (argv [i]) != "none") {
582                     scim_split_string_list (engine_list, String (argv [i]), ',');
583                 }
584                 continue;
585             }
586             if (String ("--no-stay") == argv [i])
587                 m_stay = false;
588         }
589     }
590
591     load_helper_modules (engine_list);
592
593     /**
594      * initialize the random number generator.
595      */
596     srand (time (0));
597
598     signal (SIGCHLD, SIG_IGN);
599 }
600
601 void
602 SocketFrontEnd::run ()
603 {
604     if (m_socket_server.valid ())
605         m_socket_server.run ();
606 }
607
608 uint32
609 SocketFrontEnd::generate_key () const
610 {
611     return (uint32)rand ();
612 }
613
614 bool
615 SocketFrontEnd::check_client_connection (const Socket &client) const
616 {
617     SCIM_DEBUG_FRONTEND (1) << "check_client_connection (" << client.get_id () << ").\n";
618
619     unsigned char buf [sizeof(uint32)];
620
621     int nbytes = client.read_with_timeout (buf, sizeof(uint32), m_socket_timeout);
622
623     if (nbytes == sizeof (uint32))
624         return true;
625
626     if (nbytes < 0) {
627         SCIM_DEBUG_FRONTEND (2) << " Error occurred when reading socket (" << client.get_id ()
628             << "):" << client.get_error_message () << "\n";
629     } else {
630         SCIM_DEBUG_FRONTEND (2) << " Timeout when reading socket (" << client.get_id ()
631             << ").\n";
632     }
633
634     return false;
635 }
636
637 void
638 SocketFrontEnd::socket_accept_callback (SocketServer *server, const Socket &client)
639 {
640     SCIM_DEBUG_FRONTEND (1) << "socket_accept_callback (" << client.get_id () << ").\n";
641 }
642
643 void
644 SocketFrontEnd::socket_receive_callback (SocketServer *server, const Socket &client)
645 {
646     int id = client.get_id ();
647     int cmd;
648     uint32 key;
649     bool reply = true;
650
651     ClientInfo client_info;
652
653     SCIM_DEBUG_FRONTEND (1) << "socket_receive_callback (" << id << ").\n";
654
655     // Check if the client is closed.
656     if (!check_client_connection (client)) {
657         SCIM_DEBUG_FRONTEND (2) << " closing client connection.\n";
658         socket_close_connection (server, client);
659         return;
660     }
661
662     client_info = socket_get_client_info (client);
663
664     // If it's a new client, then request to open the connection first.
665     if (client_info.type == UNKNOWN_CLIENT) {
666         socket_open_connection (server, client);
667         return;
668     }
669
670     // If can not read the transaction,
671     // or the transaction is not started with SCIM_TRANS_CMD_REQUEST,
672     // or the key is mismatch,
673     // just return.
674     if (!m_receive_trans.read_from_socket (client, m_socket_timeout) ||
675         !m_receive_trans.get_command (cmd) || cmd != SCIM_TRANS_CMD_REQUEST ||
676         !m_receive_trans.get_data (key) || key != (uint32) client_info.key)
677         return;
678
679     m_current_socket_client     = id;
680     m_current_socket_client_key = key;
681
682     m_send_trans.clear ();
683     m_send_trans.put_command (SCIM_TRANS_CMD_REPLY);
684
685     // Move the read ptr to the end.
686     if (!m_send_trans.get_command (cmd))
687         return;
688
689     while (m_receive_trans.get_command (cmd)) {
690         if (cmd == SCIM_TRANS_CMD_PROCESS_KEY_EVENT)
691             socket_process_key_event (id);
692         else if (cmd == SCIM_TRANS_CMD_MOVE_PREEDIT_CARET)
693             socket_move_preedit_caret (id);
694         else if (cmd == ISM_TRANS_CMD_SELECT_AUX)
695             socket_select_aux (id);
696         else if (cmd == SCIM_TRANS_CMD_SELECT_CANDIDATE)
697             socket_select_candidate (id);
698         else if (cmd == SCIM_TRANS_CMD_UPDATE_LOOKUP_TABLE_PAGE_SIZE)
699             socket_update_lookup_table_page_size (id);
700         else if (cmd == SCIM_TRANS_CMD_LOOKUP_TABLE_PAGE_UP)
701             socket_lookup_table_page_up (id);
702         else if (cmd == SCIM_TRANS_CMD_LOOKUP_TABLE_PAGE_DOWN)
703             socket_lookup_table_page_down (id);
704         else if (cmd == ISM_TRANS_CMD_RESET_ISE_OPTION)
705             socket_reset_option (id);
706         else if (cmd == SCIM_TRANS_CMD_RESET)
707             socket_reset (id);
708         else if (cmd == SCIM_TRANS_CMD_FOCUS_IN)
709             socket_focus_in (id);
710         else if (cmd == SCIM_TRANS_CMD_FOCUS_OUT)
711             socket_focus_out (id);
712         else if (cmd == SCIM_TRANS_CMD_TRIGGER_PROPERTY)
713             socket_trigger_property (id);
714         else if (cmd == SCIM_TRANS_CMD_PROCESS_HELPER_EVENT)
715             socket_process_helper_event (id);
716         else if (cmd == SCIM_TRANS_CMD_UPDATE_CLIENT_CAPABILITIES)
717             socket_update_client_capabilities (id);
718         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_LIST)
719             socket_get_factory_list (id);
720         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_NAME)
721             socket_get_factory_name (id);
722         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_AUTHORS)
723             socket_get_factory_authors (id);
724         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_CREDITS)
725             socket_get_factory_credits (id);
726         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_HELP)
727             socket_get_factory_help (id);
728         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_LOCALES)
729             socket_get_factory_locales (id);
730         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_ICON_FILE)
731             socket_get_factory_icon_file (id);
732         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_LANGUAGE)
733             socket_get_factory_language (id);
734         else if (cmd == SCIM_TRANS_CMD_NEW_INSTANCE)
735             socket_new_instance (id);
736         else if (cmd == SCIM_TRANS_CMD_DELETE_INSTANCE)
737             socket_delete_instance (id);
738         else if (cmd == SCIM_TRANS_CMD_DELETE_ALL_INSTANCES)
739             socket_delete_all_instances (id);
740         else if (cmd == SCIM_TRANS_CMD_FLUSH_CONFIG)
741             socket_flush_config (id);
742         else if (cmd == SCIM_TRANS_CMD_ERASE_CONFIG)
743             socket_erase_config (id);
744         else if (cmd == SCIM_TRANS_CMD_RELOAD_CONFIG)
745             socket_reload_config (id);
746         else if (cmd == SCIM_TRANS_CMD_GET_CONFIG_STRING)
747             socket_get_config_string (id);
748         else if (cmd == SCIM_TRANS_CMD_SET_CONFIG_STRING)
749             socket_set_config_string (id);
750         else if (cmd == SCIM_TRANS_CMD_GET_CONFIG_INT)
751             socket_get_config_int (id);
752         else if (cmd == SCIM_TRANS_CMD_SET_CONFIG_INT)
753             socket_set_config_int (id);
754         else if (cmd == SCIM_TRANS_CMD_GET_CONFIG_BOOL)
755             socket_get_config_bool (id);
756         else if (cmd == SCIM_TRANS_CMD_SET_CONFIG_BOOL)
757             socket_set_config_bool (id);
758         else if (cmd == SCIM_TRANS_CMD_GET_CONFIG_DOUBLE)
759             socket_get_config_double (id);
760         else if (cmd == SCIM_TRANS_CMD_SET_CONFIG_DOUBLE)
761             socket_set_config_double (id);
762         else if (cmd == SCIM_TRANS_CMD_GET_CONFIG_VECTOR_STRING)
763             socket_get_config_vector_string (id);
764         else if (cmd == SCIM_TRANS_CMD_SET_CONFIG_VECTOR_STRING)
765             socket_set_config_vector_string (id);
766         else if (cmd == SCIM_TRANS_CMD_GET_CONFIG_VECTOR_INT)
767             socket_get_config_vector_int (id);
768         else if (cmd == SCIM_TRANS_CMD_SET_CONFIG_VECTOR_INT)
769             socket_set_config_vector_int (id);
770         else if (cmd == ISM_TRANS_CMD_GET_ACTIVE_ISE_LIST)
771             get_active_ise_list (id);
772         else if (cmd == SCIM_TRANS_CMD_LOAD_FILE)
773             socket_load_file (id);
774         else if (cmd == SCIM_TRANS_CMD_CLOSE_CONNECTION) {
775             socket_close_connection (server, client);
776             m_current_socket_client     = -1;
777             m_current_socket_client_key = 0;
778             return;
779         }else if(cmd == SCIM_TRANS_CMD_HELPER_MANAGER_GET_HELPER_LIST) {    
780             SCIM_DEBUG_FRONTEND (1) << "receive cmd SCIM_TRANS_CMD_HELPER_MANAGER_GET_HELPER_LIST\n";
781             get_helper_list (client);
782         } else if (cmd == SCIM_TRANS_CMD_HELPER_MANAGER_RUN_HELPER) {
783             SCIM_DEBUG_FRONTEND (1) << "receive cmd SCIM_TRANS_CMD_HELPER_MANAGER_RUN_HELPER\n";
784             reply = false;
785             run_helper (client);
786         } else if (cmd == SCIM_TRANS_CMD_HELPER_MANAGER_STOP_HELPER) {
787             SCIM_DEBUG_FRONTEND (1) << "receive cmd SCIM_TRANS_CMD_HELPER_MANAGER_STOP_HELPER\n";
788             unregister_helper ();
789         } else if (cmd == SCIM_TRANS_CMD_HELPER_MANAGER_SEND_DISPLAY) {
790             SCIM_DEBUG_FRONTEND (1) << "receive cmd SCIM_TRANS_CMD_HELPER_MANAGER_SEND_DISPLAY\n";
791             socket_set_display_name (id);
792         } else if (cmd == SCIM_TRANS_CMD_HELPER_MANAGER_SEND_ISE_LIST) {
793             SCIM_DEBUG_FRONTEND (1) << "receive cmd SCIM_TRANS_CMD_HELPER_MANAGER_SEND_ISE_LIST\n";
794             reply = false;
795             socket_update_ise_list (id);
796         } else if (cmd == ISM_TRANS_CMD_TURN_ON_LOG) {
797             SCIM_DEBUG_FRONTEND (1) << "receive cmd ISM_TRANS_CMD_TURN_ON_LOG\n";
798             socket_turn_on_log (id);
799         }
800     }
801
802     // Send reply to client
803     if (m_send_trans.get_data_type () == SCIM_TRANS_DATA_UNKNOWN)
804         m_send_trans.put_command (SCIM_TRANS_CMD_FAIL);
805
806     if (reply)
807         m_send_trans.write_to_socket (client);
808
809     m_current_socket_client     = -1;
810     m_current_socket_client_key = 0;
811
812     SCIM_DEBUG_FRONTEND (1) << "End of socket_receive_callback (" << id << ").\n";
813 }
814
815 bool
816 SocketFrontEnd::socket_open_connection (SocketServer *server, const Socket &client)
817 {
818     SCIM_DEBUG_FRONTEND (2) << " Open socket connection for client " << client.get_id () << "  number of clients=" << m_socket_client_repository.size () << ".\n";
819
820     uint32 key;
821     String type = scim_socket_accept_connection (key,
822                                                  String ("SocketFrontEnd,HelperLauncher"), 
823                                                  String ("SocketIMEngine,SocketConfig,HelperManager"),
824                                                  client,
825                                                  m_socket_timeout);
826
827     if (type.length ()) {
828         ClientInfo info;
829         info.key = key;
830         info.type = ((type == "SocketIMEngine") ? IMENGINE_CLIENT 
831                         : ((type == "SocketConfig") ? CONFIG_CLIENT : HELPER_MANAGER_CLIENT));
832
833         SCIM_DEBUG_MAIN (2) << " Add client to repository. Type=" << type << " key=" << key << "\n";
834         m_socket_client_repository [client.get_id ()] = info;
835         return true;
836     }
837
838     // Client did not pass the registration process, close it.
839     SCIM_DEBUG_FRONTEND (2) << " Failed to create new connection.\n"; 
840     server->close_connection (client);
841     return false;
842 }
843
844 void
845 SocketFrontEnd::socket_close_connection (SocketServer *server, const Socket &client)
846 {
847     SCIM_DEBUG_FRONTEND (2) << " Close client connection " << client.get_id () << "  number of clients=" << m_socket_client_repository.size () << ".\n";
848
849     ClientInfo client_info = socket_get_client_info (client);
850
851     server->close_connection (client);
852
853     if (client_info.type != UNKNOWN_CLIENT) {
854         m_socket_client_repository.erase (client.get_id ());
855
856         if (client_info.type == IMENGINE_CLIENT)
857             socket_delete_all_instances (client.get_id ());
858
859         if (!m_socket_client_repository.size () && !m_stay)
860             server->shutdown ();
861     }
862 }
863
864 SocketFrontEnd::ClientInfo
865 SocketFrontEnd::socket_get_client_info (const Socket &client)
866 {
867     static ClientInfo null_client = { 0, UNKNOWN_CLIENT };
868     SocketClientRepository::iterator it = m_socket_client_repository.find (client.get_id ());
869
870     if (it != m_socket_client_repository.end ())
871         return it->second;
872
873     return null_client;
874 }
875
876 void
877 SocketFrontEnd::socket_exception_callback (SocketServer *server, const Socket &client)
878 {
879     SCIM_DEBUG_FRONTEND (1) << "socket_exception_callback (" << client.get_id () << ").\n";
880
881     socket_close_connection (server, client);
882 }
883
884 //client_id is client's socket id
885 void
886 SocketFrontEnd::socket_get_factory_list (int /*client_id*/)
887 {
888     String encoding;
889
890     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_list.\n";
891
892     if (m_receive_trans.get_data (encoding)) {
893         std::vector<String> uuids;
894
895         if (encoding == "")
896             get_factory_list (uuids);
897         else
898             get_factory_list_for_encoding (uuids, encoding);
899
900         SCIM_DEBUG_FRONTEND (3) << "  Encoding (" << encoding
901             << ") Num(" << uuids.size () << ").\n";
902
903         m_send_trans.put_data (uuids);
904         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
905     }
906 }
907
908 void
909 SocketFrontEnd::socket_get_factory_name (int /*client_id*/)
910 {
911     String sfid;
912
913     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_name.\n";
914
915     if (m_receive_trans.get_data (sfid)) {
916         WideString name = get_factory_name (sfid);
917
918         m_send_trans.put_data (name);
919         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
920     }
921 }
922
923 void
924 SocketFrontEnd::socket_get_factory_authors (int /*client_id*/)
925 {
926     String sfid;
927
928     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_authors.\n";
929
930     if (m_receive_trans.get_data (sfid)) {
931         WideString authors = get_factory_authors (sfid);
932
933         m_send_trans.put_data (authors);
934         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
935     }
936 }
937
938 void
939 SocketFrontEnd::socket_get_factory_credits (int /*client_id*/)
940 {
941     String sfid;
942
943     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_credits.\n";
944
945     if (m_receive_trans.get_data (sfid)) {
946         WideString credits = get_factory_credits (sfid);
947
948         m_send_trans.put_data (credits);
949         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
950     }
951 }
952
953 void
954 SocketFrontEnd::socket_get_factory_help (int /*client_id*/)
955 {
956     String sfid;
957
958     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_help.\n";
959
960     if (m_receive_trans.get_data (sfid)) {
961         WideString help = get_factory_help (sfid);
962
963         m_send_trans.put_data (help);
964         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
965     }
966 }
967
968 void
969 SocketFrontEnd::socket_get_factory_locales (int /*client_id*/)
970 {
971     String sfid;
972
973     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_locales.\n";
974
975     if (m_receive_trans.get_data (sfid)) {
976         String locales = get_factory_locales (sfid);
977
978         SCIM_DEBUG_FRONTEND (3) << "  Locales (" << locales << ").\n";
979
980         m_send_trans.put_data (locales);
981         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
982     }
983 }
984
985 void
986 SocketFrontEnd::socket_get_factory_icon_file (int /*client_id*/)
987 {
988     String sfid;
989
990     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_icon_file.\n";
991
992     if (m_receive_trans.get_data (sfid)) {
993         String iconfile = get_factory_icon_file (sfid);
994
995         SCIM_DEBUG_FRONTEND (3) << "  ICON File (" << iconfile << ").\n";
996
997         m_send_trans.put_data (iconfile);
998         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
999     }
1000 }
1001
1002 void
1003 SocketFrontEnd::socket_get_factory_language (int /*client_id*/)
1004 {
1005     String sfid;
1006
1007     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_language.\n";
1008
1009     if (m_receive_trans.get_data (sfid)) {
1010         String language = get_factory_language (sfid);
1011
1012         SCIM_DEBUG_FRONTEND (3) << "  Language (" << language << ").\n";
1013
1014         m_send_trans.put_data (language);
1015         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1016     }
1017 }
1018
1019 void
1020 SocketFrontEnd::socket_new_instance (int client_id)
1021 {
1022     String sfid;
1023     String encoding;
1024
1025     SCIM_DEBUG_FRONTEND (2) << " socket_new_instance.\n";
1026
1027     if (m_receive_trans.get_data (sfid) &&
1028         m_receive_trans.get_data (encoding)) {
1029         int siid = new_instance (m_config, sfid, encoding);
1030
1031         // Instance created OK.
1032         if (siid >= 0) {
1033             SocketInstanceRepository::iterator it =
1034                 std::lower_bound (m_socket_instance_repository.begin (),
1035                                   m_socket_instance_repository.end (),
1036                                   std::pair <int, int> (client_id, siid));
1037
1038             if (it == m_socket_instance_repository.end ())
1039                 m_socket_instance_repository.push_back (std::pair <int, int> (client_id, siid));
1040             else
1041                 m_socket_instance_repository.insert (it, std::pair <int, int> (client_id, siid));
1042
1043             SCIM_DEBUG_FRONTEND (3) << "  InstanceID (" << siid << ").\n";
1044
1045             m_send_trans.put_data ((uint32)siid);
1046             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1047         }
1048     }
1049 }
1050
1051 void
1052 SocketFrontEnd::socket_delete_instance (int client_id)
1053 {
1054     uint32 siid;
1055
1056     SCIM_DEBUG_FRONTEND (2) << " socket_delete_instance.\n";
1057
1058     if (m_receive_trans.get_data (siid)) {
1059
1060         SCIM_DEBUG_FRONTEND (3) << "  InstanceID (" << siid << ").\n";
1061
1062         m_current_instance = (int) siid;
1063
1064         delete_instance ((int) siid);
1065
1066         m_current_instance = -1;
1067
1068         SocketInstanceRepository::iterator it =
1069             std::lower_bound (m_socket_instance_repository.begin (),
1070                               m_socket_instance_repository.end (),
1071                               std::pair <int, int> (client_id, siid));
1072
1073         if (it != m_socket_instance_repository.end () &&
1074             *it == std::pair <int, int> (client_id, siid))
1075             m_socket_instance_repository.erase (it);
1076
1077         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1078     }
1079 }
1080
1081 void
1082 SocketFrontEnd::socket_delete_all_instances (int client_id)
1083 {
1084     SCIM_DEBUG_FRONTEND (2) << " socket_delete_all_instances.\n";
1085
1086     SocketInstanceRepository::iterator it;
1087
1088     SocketInstanceRepository::iterator lit =
1089         std::lower_bound (m_socket_instance_repository.begin (),
1090                           m_socket_instance_repository.end (),
1091                           std::pair <int, int> (client_id, 0));
1092
1093     SocketInstanceRepository::iterator uit =
1094         std::upper_bound (m_socket_instance_repository.begin (),
1095                           m_socket_instance_repository.end (),
1096                           std::pair <int, int> (client_id, INT_MAX));
1097
1098     if (lit != uit) {
1099         for (it = lit; it != uit; ++it) {
1100             m_current_instance = it->second;
1101             delete_instance (it->second);
1102         }
1103         m_current_instance = -1;
1104         m_socket_instance_repository.erase (lit, uit);
1105         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1106     }
1107 }
1108
1109 void
1110 SocketFrontEnd::socket_process_key_event (int /*client_id*/)
1111 {
1112     uint32   siid;
1113     KeyEvent event;
1114
1115     SCIM_DEBUG_FRONTEND (2) << " socket_process_key_event.\n";
1116
1117     if (m_receive_trans.get_data (siid) &&
1118         m_receive_trans.get_data (event)) {
1119
1120         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ") KeyEvent ("
1121             << event.code << "," << event.mask << ").\n";
1122
1123         m_current_instance = (int) siid;
1124
1125         if (process_key_event ((int) siid, event))
1126             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1127         else
1128             m_send_trans.put_command (SCIM_TRANS_CMD_FAIL);
1129
1130         m_current_instance = -1;
1131     }
1132 }
1133
1134 void
1135 SocketFrontEnd::socket_move_preedit_caret (int /*client_id*/)
1136 {
1137     uint32 siid;
1138     uint32 caret;
1139
1140     SCIM_DEBUG_FRONTEND (2) << " socket_move_preedit_caret.\n";
1141
1142     if (m_receive_trans.get_data (siid) &&
1143         m_receive_trans.get_data (caret)) {
1144
1145         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid
1146             << ") Caret (" << caret << ").\n";
1147
1148         m_current_instance = (int) siid;
1149
1150         move_preedit_caret ((int) siid, caret); 
1151         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1152
1153         m_current_instance = -1;
1154     }
1155 }
1156
1157 void
1158 SocketFrontEnd::socket_select_aux (int /*client_id*/)
1159 {
1160     uint32 siid;
1161     uint32 item;
1162
1163     SCIM_DEBUG_FRONTEND (2) << " socket_select_aux.\n";
1164
1165     if (m_receive_trans.get_data (siid) &&
1166         m_receive_trans.get_data (item)) {
1167
1168         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ") Item (" << item << ").\n";
1169
1170         m_current_instance = (int) siid;
1171
1172         select_aux ((int) siid, item); 
1173         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1174
1175         m_current_instance = -1;
1176     }
1177 }
1178
1179 void
1180 SocketFrontEnd::socket_select_candidate (int /*client_id*/)
1181 {
1182     uint32 siid;
1183     uint32 item;
1184
1185     SCIM_DEBUG_FRONTEND (2) << " socket_select_candidate.\n";
1186
1187     if (m_receive_trans.get_data (siid) &&
1188         m_receive_trans.get_data (item)) {
1189
1190         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ") Item (" << item << ").\n";
1191
1192         m_current_instance = (int) siid;
1193
1194         select_candidate ((int) siid, item); 
1195         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1196
1197         m_current_instance = -1;
1198     }
1199 }
1200
1201 void
1202 SocketFrontEnd::socket_update_lookup_table_page_size (int /*client_id*/)
1203 {
1204     uint32 siid;
1205     uint32 size;
1206
1207     SCIM_DEBUG_FRONTEND (2) << " socket_update_lookup_table_page_size.\n";
1208
1209     if (m_receive_trans.get_data (siid) &&
1210         m_receive_trans.get_data (size)) {
1211
1212         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ") PageSize (" << size << ").\n";
1213
1214         m_current_instance = (int) siid;
1215
1216         update_lookup_table_page_size ((int) siid, size); 
1217         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1218
1219         m_current_instance = -1;
1220     }
1221 }
1222
1223 void
1224 SocketFrontEnd::socket_lookup_table_page_up (int /*client_id*/)
1225 {
1226     uint32 siid;
1227
1228     SCIM_DEBUG_FRONTEND (2) << " socket_lookup_table_page_up.\n";
1229
1230     if (m_receive_trans.get_data (siid)) {
1231
1232         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1233
1234         m_current_instance = (int) siid;
1235
1236         lookup_table_page_up ((int) siid); 
1237         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1238
1239         m_current_instance = -1;
1240     }
1241 }
1242
1243 void
1244 SocketFrontEnd::socket_lookup_table_page_down (int /*client_id*/)
1245 {
1246     uint32 siid;
1247
1248     SCIM_DEBUG_FRONTEND (2) << " socket_lookup_table_page_down.\n";
1249
1250     if (m_receive_trans.get_data (siid)) {
1251
1252         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1253
1254         m_current_instance = (int) siid;
1255
1256         lookup_table_page_down ((int) siid); 
1257         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1258
1259         m_current_instance = -1;
1260     }
1261 }
1262
1263 void
1264 SocketFrontEnd::socket_reset_option (int /*client_id*/)
1265 {
1266     uint32 siid;
1267
1268     SCIM_DEBUG_FRONTEND (2) << " socket_reset_option.\n";
1269
1270     if (m_receive_trans.get_data (siid)) {
1271
1272         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1273
1274         m_current_instance = (int) siid;
1275
1276         reset_option ((int) siid); 
1277         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1278
1279         m_current_instance = -1;
1280     }
1281 }
1282
1283 void
1284 SocketFrontEnd::socket_reset (int /*client_id*/)
1285 {
1286     uint32 siid;
1287
1288     SCIM_DEBUG_FRONTEND (2) << " socket_reset.\n";
1289
1290     if (m_receive_trans.get_data (siid)) {
1291
1292         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1293
1294         m_current_instance = (int) siid;
1295
1296         reset ((int) siid); 
1297         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1298
1299         m_current_instance = -1;
1300     }
1301 }
1302
1303 void
1304 SocketFrontEnd::socket_focus_in (int /*client_id*/)
1305 {
1306     uint32 siid;
1307
1308     SCIM_DEBUG_FRONTEND (2) << " socket_focus_in.\n";
1309
1310     if (m_receive_trans.get_data (siid)) {
1311
1312         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1313
1314         m_current_instance = (int) siid;
1315
1316         focus_in ((int) siid); 
1317         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1318
1319         m_current_instance = -1;
1320     }
1321 }
1322
1323 void
1324 SocketFrontEnd::socket_focus_out (int /*client_id*/)
1325 {
1326     uint32 siid;
1327
1328     SCIM_DEBUG_FRONTEND (2) << " socket_focus_out.\n";
1329
1330     if (m_receive_trans.get_data (siid)) {
1331
1332         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1333
1334         m_current_instance = (int) siid;
1335
1336         focus_out ((int) siid); 
1337         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1338
1339         m_current_instance = -1;
1340     }
1341 }
1342
1343 void
1344 SocketFrontEnd::socket_trigger_property (int /*client_id*/)
1345 {
1346     uint32 siid;
1347     String property;
1348
1349     SCIM_DEBUG_FRONTEND (2) << " socket_trigger_property.\n";
1350
1351     if (m_receive_trans.get_data (siid) &&
1352         m_receive_trans.get_data (property)) {
1353
1354         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1355
1356         m_current_instance = (int) siid;
1357
1358         trigger_property ((int) siid, property); 
1359         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1360
1361         m_current_instance = -1;
1362     }
1363 }
1364
1365 void
1366 SocketFrontEnd::socket_process_helper_event (int /*client_id*/)
1367 {
1368     uint32 siid;
1369     String helper_uuid;
1370     Transaction trans;
1371
1372     SCIM_DEBUG_FRONTEND (2) << " socket_process_helper_event.\n";
1373
1374     if (m_receive_trans.get_data (siid) &&
1375         m_receive_trans.get_data (helper_uuid) &&
1376         m_receive_trans.get_data (trans)) {
1377
1378         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1379
1380         m_current_instance = (int) siid;
1381
1382         process_helper_event ((int) siid, helper_uuid, trans); 
1383         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1384
1385         m_current_instance = -1;
1386     }
1387 }
1388
1389 void
1390 SocketFrontEnd::socket_update_client_capabilities (int /*client_id*/)
1391 {
1392     uint32 siid;
1393     uint32 cap;
1394
1395     SCIM_DEBUG_FRONTEND (2) << " socket_update_client_capabilities.\n";
1396
1397     if (m_receive_trans.get_data (siid) && m_receive_trans.get_data (cap)) {
1398
1399         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1400
1401         m_current_instance = (int) siid;
1402
1403         update_client_capabilities ((int) siid, cap); 
1404
1405         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1406
1407         m_current_instance = -1;
1408     }
1409 }
1410
1411
1412 void
1413 SocketFrontEnd::socket_flush_config (int /*client_id*/)
1414 {
1415     if (m_config_readonly || m_config.null ())
1416         return;
1417
1418     SCIM_DEBUG_FRONTEND (2) << " socket_flush_config.\n";
1419
1420     if (m_config->flush ())
1421         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1422 }
1423
1424 void
1425 SocketFrontEnd::socket_erase_config (int /*client_id*/)
1426 {
1427     if (m_config_readonly || m_config.null ())
1428         return;
1429
1430     String key;
1431
1432     SCIM_DEBUG_FRONTEND (2) << " socket_erase_config.\n";
1433
1434     if (m_receive_trans.get_data (key)) {
1435
1436         SCIM_DEBUG_FRONTEND (3) << "  Key   (" << key << ").\n";
1437
1438         if (m_config->erase (key))
1439             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1440     }
1441 }
1442
1443 void
1444 SocketFrontEnd::socket_reload_config (int /*client_id*/)
1445 {
1446     static timeval last_timestamp = {0, 0};
1447
1448     if (m_config.null ())
1449         return;
1450
1451     SCIM_DEBUG_FRONTEND (2) << " socket_reload_config.\n";
1452
1453     timeval timestamp;
1454
1455     gettimeofday (&timestamp, 0);
1456
1457     if (timestamp.tv_sec >= last_timestamp.tv_sec)
1458         m_config->reload ();
1459
1460     gettimeofday (&last_timestamp, 0);
1461
1462     m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1463 }
1464
1465 void
1466 SocketFrontEnd::socket_set_display_name (int /*client_id*/)
1467 {
1468     String name;
1469
1470     if (m_receive_trans.get_data (name) && name.length () > 0)
1471         m_display = name;
1472
1473     m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1474 }
1475
1476 void
1477 SocketFrontEnd::socket_update_ise_list (int /*client_id*/)
1478 {
1479     String strName;
1480     //std::vector<String> name_list;
1481     std::vector<String> imengine_list;
1482     std::vector<String> helper_list;
1483
1484     if (m_receive_trans.get_data (strName) && strName.length () > 0) {
1485         //std::cout << "ISE name list:" << strName << "\n";
1486         //scim_split_string_list (name_list, strName);
1487
1488         scim_get_imengine_module_list (imengine_list);
1489         scim_get_helper_module_list (helper_list);
1490
1491         for (size_t i = 0; i < imengine_list.size (); ++i) {
1492             if (std::find (__load_engine_list.begin (), __load_engine_list.end (), imengine_list [i]) == __load_engine_list.end ()) {
1493                 SCIM_DEBUG_FRONTEND (3) << "add_module " << imengine_list [i]  << " in " << __FUNCTION__ << "\n";
1494                 //add_module (m_config, imengine_list [i], true);
1495                 add_module_info (m_config, imengine_list [i]);
1496                 __load_engine_list.push_back (imengine_list [i]);
1497             }
1498         }
1499
1500         HelperModule module;
1501         HelperInfo   info;
1502         for (size_t i = 0; i < helper_list.size (); ++i) {
1503             if (std::find (__load_engine_list.begin (), __load_engine_list.end (), helper_list [i]) == __load_engine_list.end ()) {
1504                 if (module.load (helper_list [i]) && module.valid ()) {
1505                     size_t num = module.number_of_helpers ();
1506                     for (size_t j = 0; j < num; ++j) {
1507                         if (module.get_helper_info (j, info))
1508                             __helpers.push_back (std::make_pair (info, helper_list [i]));
1509                     }
1510                     __load_engine_list.push_back (helper_list [i]);
1511                 }
1512                 module.unload ();
1513             }
1514         }
1515     }
1516
1517     m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1518 }
1519
1520 void
1521 SocketFrontEnd::socket_get_config_string (int /*client_id*/)
1522 {
1523     if (m_config.null ()) return;
1524
1525     String key;
1526
1527     SCIM_DEBUG_FRONTEND (2) << " socket_get_config_string.\n";
1528
1529     if (m_receive_trans.get_data (key)) {
1530         String value;
1531
1532         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1533
1534         if (m_config->read (key, &value)) {
1535             m_send_trans.put_data (value);
1536             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1537         }
1538     }
1539 }
1540
1541 void
1542 SocketFrontEnd::socket_set_config_string (int /*client_id*/)
1543 {
1544     if (m_config_readonly || m_config.null ())
1545         return;
1546
1547     String key;
1548     String value;
1549
1550     SCIM_DEBUG_FRONTEND (2) << " socket_set_config_string.\n";
1551
1552     if (m_receive_trans.get_data (key) &&
1553         m_receive_trans.get_data (value)) {
1554
1555         SCIM_DEBUG_FRONTEND (3) << "  Key   (" << key << ").\n";
1556         SCIM_DEBUG_FRONTEND (3) << "  Value (" << value << ").\n";
1557
1558         if (m_config->write (key, value))
1559             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1560     }
1561 }
1562
1563 void
1564 SocketFrontEnd::socket_get_config_int (int /*client_id*/)
1565 {
1566     if (m_config.null ()) return;
1567
1568     String key;
1569
1570     SCIM_DEBUG_FRONTEND (2) << " socket_get_config_int.\n";
1571
1572     if (m_receive_trans.get_data (key)) {
1573
1574         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1575
1576         int value;
1577         if (m_config->read (key, &value)) {
1578             m_send_trans.put_data ((uint32) value);
1579             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1580         }
1581     }
1582 }
1583
1584 void
1585 SocketFrontEnd::socket_set_config_int (int /*client_id*/)
1586 {
1587     if (m_config_readonly || m_config.null ())
1588         return;
1589
1590     String key;
1591     uint32 value;
1592
1593     SCIM_DEBUG_FRONTEND (2) << " socket_set_config_int.\n";
1594
1595     if (m_receive_trans.get_data (key) &&
1596         m_receive_trans.get_data (value)) {
1597
1598         SCIM_DEBUG_FRONTEND (3) << "  Key   (" << key << ").\n";
1599         SCIM_DEBUG_FRONTEND (3) << "  Value (" << value << ").\n";
1600
1601         if (m_config->write (key, (int) value))
1602             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1603     }
1604 }
1605
1606 void
1607 SocketFrontEnd::socket_get_config_bool (int /*client_id*/)
1608 {
1609     if (m_config.null ()) return;
1610
1611     String key;
1612
1613     SCIM_DEBUG_FRONTEND (2) << " socket_get_config_bool.\n";
1614
1615     if (m_receive_trans.get_data (key)) {
1616         bool value;
1617
1618         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1619
1620         if (m_config->read (key, &value)) {
1621             m_send_trans.put_data ((uint32) value);
1622             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1623         }
1624     }
1625 }
1626
1627 void
1628 SocketFrontEnd::socket_set_config_bool (int /*client_id*/)
1629 {
1630     if (m_config_readonly || m_config.null ())
1631         return;
1632
1633     String key;
1634     uint32 value;
1635
1636     SCIM_DEBUG_FRONTEND (2) << " socket_set_config_bool.\n";
1637
1638     if (m_receive_trans.get_data (key) &&
1639         m_receive_trans.get_data (value)) {
1640
1641         SCIM_DEBUG_FRONTEND (3) << "  Key   (" << key << ").\n";
1642         SCIM_DEBUG_FRONTEND (3) << "  Value (" << value << ").\n";
1643
1644         if (m_config->write (key, (bool) value))
1645             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1646     }
1647 }
1648
1649 void
1650 SocketFrontEnd::socket_get_config_double (int /*client_id*/)
1651 {
1652     if (m_config.null ()) return;
1653
1654     String key;
1655
1656     SCIM_DEBUG_FRONTEND (2) << " socket_get_config_double.\n";
1657
1658     if (m_receive_trans.get_data (key)) {
1659         double value;
1660
1661         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1662
1663         if (m_config->read (key, &value)) {
1664             char buf [80];
1665             snprintf (buf, 79, "%lE", value);
1666             m_send_trans.put_data (String (buf));
1667             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1668         }
1669     }
1670 }
1671
1672 void
1673 SocketFrontEnd::socket_set_config_double (int /*client_id*/)
1674 {
1675     if (m_config_readonly || m_config.null ())
1676         return;
1677
1678     String key;
1679     String str;
1680
1681     SCIM_DEBUG_FRONTEND (2) << " socket_set_config_double.\n";
1682
1683     if (m_receive_trans.get_data (key) &&
1684         m_receive_trans.get_data (str)) {
1685         double value;
1686         sscanf (str.c_str (), "%lE", &value);
1687
1688         SCIM_DEBUG_FRONTEND (3) << "  Key   (" << key << ").\n";
1689         SCIM_DEBUG_FRONTEND (3) << "  Value (" << value << ").\n";
1690
1691         if (m_config->write (key, value))
1692             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1693     }
1694 }
1695
1696 void
1697 SocketFrontEnd::socket_get_config_vector_string (int /*client_id*/)
1698 {
1699     if (m_config.null ()) return;
1700
1701     String key;
1702
1703     SCIM_DEBUG_FRONTEND (2) << " socket_get_config_vector_string.\n";
1704
1705     if (m_receive_trans.get_data (key)) {
1706         std::vector <String> vec;
1707
1708         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1709
1710         if (m_config->read (key, &vec)) {
1711             m_send_trans.put_data (vec);
1712             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1713         }
1714     }
1715 }
1716
1717 void
1718 SocketFrontEnd::socket_set_config_vector_string (int /*client_id*/)
1719 {
1720     if (m_config_readonly || m_config.null ())
1721         return;
1722
1723     String key;
1724     std::vector<String> vec;
1725
1726     SCIM_DEBUG_FRONTEND (2) << " socket_set_config_vector_string.\n";
1727
1728     if (m_receive_trans.get_data (key) &&
1729         m_receive_trans.get_data (vec)) {
1730
1731         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1732
1733         if (m_config->write (key, vec))
1734             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1735     }
1736 }
1737
1738 void
1739 SocketFrontEnd::socket_get_config_vector_int (int /*client_id*/)
1740 {
1741     if (m_config.null ()) return;
1742
1743     String key;
1744
1745     SCIM_DEBUG_FRONTEND (2) << " socket_get_config_vector_int.\n";
1746
1747     if (m_receive_trans.get_data (key)) {
1748         std::vector <int> vec;
1749
1750         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1751
1752         if (m_config->read (key, &vec)) {
1753             std::vector <uint32> reply;
1754
1755             for (uint32 i=0; i<vec.size (); ++i)
1756                 reply.push_back ((uint32) vec[i]);
1757
1758             m_send_trans.put_data (reply);
1759             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1760         }
1761     }
1762 }
1763
1764 void
1765 SocketFrontEnd::socket_set_config_vector_int (int /*client_id*/)
1766 {
1767     if (m_config_readonly || m_config.null ())
1768         return;
1769
1770     String key;
1771     std::vector<uint32> vec;
1772
1773     SCIM_DEBUG_FRONTEND (2) << " socket_set_config_vector_int.\n";
1774
1775     if (m_receive_trans.get_data (key) &&
1776         m_receive_trans.get_data (vec)) {
1777         std::vector<int> req;
1778
1779         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1780
1781         for (uint32 i=0; i<vec.size (); ++i)
1782             req.push_back ((int) vec[i]);
1783
1784         if (m_config->write (key, req))
1785             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1786     }
1787 }
1788
1789 void
1790 SocketFrontEnd::socket_load_file (int /*client_id*/)
1791 {
1792     String filename;
1793     char *bufptr = 0;
1794     size_t filesize = 0;
1795
1796     SCIM_DEBUG_FRONTEND (2) << " socket_load_file.\n";
1797
1798     if (m_receive_trans.get_data (filename)) {
1799         SCIM_DEBUG_FRONTEND (3) << "  File (" << filename << ").\n";
1800
1801         filesize = scim_load_file (filename, &bufptr);
1802         if (filesize > 0) {
1803             m_send_trans.put_data (bufptr, filesize);
1804             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1805         }
1806
1807         delete [] bufptr;
1808     }
1809 }
1810
1811 void
1812 SocketFrontEnd::socket_turn_on_log (int /*client_id*/)
1813 {
1814     uint32 isOn;
1815     SCIM_DEBUG_FRONTEND (2) << " socket_turn_on_log.\n";
1816
1817     if (m_receive_trans.get_data (isOn)) {
1818         if (isOn) {
1819             DebugOutput::enable_debug (SCIM_DEBUG_AllMask);
1820             DebugOutput::set_verbose_level (7);
1821         } else {
1822             DebugOutput::disable_debug (SCIM_DEBUG_AllMask);
1823             DebugOutput::set_verbose_level (0);
1824         }
1825         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1826         return;
1827     }
1828
1829     m_send_trans.put_command (SCIM_TRANS_CMD_FAIL);
1830     return;
1831 }
1832
1833 void
1834 SocketFrontEnd::reload_config_callback (const ConfigPointer &config)
1835 {
1836     SCIM_DEBUG_FRONTEND (1) << "Reload configuration.\n";
1837
1838     int max_clients = -1;
1839
1840     m_config_readonly = config->read (String (SCIM_CONFIG_FRONTEND_SOCKET_CONFIG_READONLY), false);
1841     max_clients = config->read (String (SCIM_CONFIG_FRONTEND_SOCKET_MAXCLIENTS), -1);
1842
1843     m_socket_server.set_max_clients (max_clients);
1844 }
1845
1846 /*
1847 vi:ts=4:nowrap:expandtab
1848 */