1 /** @file scim_socket_frontend.cpp
2  * implementation of class SocketFrontEnd.
3  */
4 
5 /*
6  * Smart Common Input Method
7  *
8  * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
9  *
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this program; if not, write to the
23  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24  * Boston, MA  02111-1307  USA
25  *
26  * $Id: scim_socket_frontend.cpp,v 1.37 2005/07/03 08:36:42 suzhe Exp $
27  *
28  */
29 
30 #define Uses_SCIM_CONFIG_PATH
31 #define Uses_SCIM_FRONTEND
32 #define Uses_SCIM_SOCKET
33 #define Uses_SCIM_TRANSACTION
34 #define Uses_STL_UTILITY
35 #define Uses_C_STDIO
36 #define Uses_C_STDLIB
37 
38 #include <limits.h>
39 #include "scim_private.h"
40 #include "scim.h"
41 #include "scim_socket_frontend.h"
42 #include <sys/time.h>
43 
44 #define scim_module_init socket_LTX_scim_module_init
45 #define scim_module_exit socket_LTX_scim_module_exit
46 #define scim_frontend_module_init socket_LTX_scim_frontend_module_init
47 #define scim_frontend_module_run socket_LTX_scim_frontend_module_run
48 
49 #define SCIM_CONFIG_FRONTEND_SOCKET_CONFIG_READONLY    "/FrontEnd/Socket/ConfigReadOnly"
50 #define SCIM_CONFIG_FRONTEND_SOCKET_MAXCLIENTS        "/FrontEnd/Socket/MaxClients"
51 
52 using namespace scim;
53 
54 static Pointer <SocketFrontEnd> _scim_frontend (0);
55 
56 static int _argc;
57 static char **_argv;
58 
59 //Module Interface
60 extern "C" {
scim_module_init(void)61     void scim_module_init (void)
62     {
63         SCIM_DEBUG_FRONTEND(1) << "Initializing Socket FrontEnd module...\n";
64     }
65 
scim_module_exit(void)66     void scim_module_exit (void)
67     {
68         SCIM_DEBUG_FRONTEND(1) << "Exiting Socket FrontEnd module...\n";
69         _scim_frontend.reset ();
70     }
71 
scim_frontend_module_init(const BackEndPointer & backend,const ConfigPointer & config,int argc,char ** argv)72     void scim_frontend_module_init (const BackEndPointer &backend,
73                                     const ConfigPointer &config,
74                                     int argc,
75                                      char **argv)
76     {
77         if (_scim_frontend.null ()) {
78             SCIM_DEBUG_FRONTEND(1) << "Initializing Socket FrontEnd module (more)...\n";
79             _scim_frontend = new SocketFrontEnd (backend, config);
80             _argc = argc;
81             _argv = argv;
82         }
83     }
84 
scim_frontend_module_run(void)85     void scim_frontend_module_run (void)
86     {
87         if (!_scim_frontend.null ()) {
88             SCIM_DEBUG_FRONTEND(1) << "Starting Socket FrontEnd module...\n";
89             _scim_frontend->init (_argc, _argv);
90             _scim_frontend->run ();
91         }
92     }
93 }
94 
SocketFrontEnd(const BackEndPointer & backend,const ConfigPointer & config)95 SocketFrontEnd::SocketFrontEnd (const BackEndPointer &backend,
96                                 const ConfigPointer  &config)
97     : FrontEndBase (backend),
98       m_config (config),
99       m_stay (true),
100       m_config_readonly (false),
101       m_socket_timeout (scim_get_default_socket_timeout ()),
102       m_current_instance (-1),
103       m_current_socket_client (-1),
104       m_current_socket_client_key (0)
105 {
106     SCIM_DEBUG_FRONTEND (2) << " Constructing SocketFrontEnd object...\n";
107 }
108 
~SocketFrontEnd()109 SocketFrontEnd::~SocketFrontEnd ()
110 {
111     SCIM_DEBUG_FRONTEND (2) << " Destructing SocketFrontEnd object...\n";
112     if (m_socket_server.is_running ())
113         m_socket_server.shutdown ();
114 }
115 
116 void
show_preedit_string(int id)117 SocketFrontEnd::show_preedit_string (int id)
118 {
119     if (m_current_instance == id)
120         m_send_trans.put_command (SCIM_TRANS_CMD_SHOW_PREEDIT_STRING);
121 }
122 
123 void
show_aux_string(int id)124 SocketFrontEnd::show_aux_string (int id)
125 {
126     if (m_current_instance == id)
127         m_send_trans.put_command (SCIM_TRANS_CMD_SHOW_AUX_STRING);
128 }
129 
130 void
show_lookup_table(int id)131 SocketFrontEnd::show_lookup_table (int id)
132 {
133     if (m_current_instance == id)
134         m_send_trans.put_command (SCIM_TRANS_CMD_SHOW_LOOKUP_TABLE);
135 }
136 
137 void
hide_preedit_string(int id)138 SocketFrontEnd::hide_preedit_string (int id)
139 {
140     if (m_current_instance == id)
141         m_send_trans.put_command (SCIM_TRANS_CMD_HIDE_PREEDIT_STRING);
142 }
143 
144 void
hide_aux_string(int id)145 SocketFrontEnd::hide_aux_string (int id)
146 {
147     if (m_current_instance == id)
148         m_send_trans.put_command (SCIM_TRANS_CMD_HIDE_AUX_STRING);
149 }
150 
151 void
hide_lookup_table(int id)152 SocketFrontEnd::hide_lookup_table (int id)
153 {
154     if (m_current_instance == id)
155         m_send_trans.put_command (SCIM_TRANS_CMD_HIDE_LOOKUP_TABLE);
156 }
157 
158 void
update_preedit_caret(int id,int caret)159 SocketFrontEnd::update_preedit_caret (int id, int caret)
160 {
161     if (m_current_instance == id) {
162         m_send_trans.put_command (SCIM_TRANS_CMD_UPDATE_PREEDIT_CARET);
163         m_send_trans.put_data ((uint32) caret);
164     }
165 }
166 
167 void
update_preedit_string(int id,const WideString & str,const AttributeList & attrs)168 SocketFrontEnd::update_preedit_string (int id,
169                                        const WideString & str,
170                                        const AttributeList & attrs)
171 {
172     if (m_current_instance == id) {
173         m_send_trans.put_command (SCIM_TRANS_CMD_UPDATE_PREEDIT_STRING);
174         m_send_trans.put_data (str);
175         m_send_trans.put_data (attrs);
176     }
177 }
178 
179 void
update_aux_string(int id,const WideString & str,const AttributeList & attrs)180 SocketFrontEnd::update_aux_string (int id,
181                                    const WideString & str,
182                                    const AttributeList & attrs)
183 {
184     if (m_current_instance == id) {
185         m_send_trans.put_command (SCIM_TRANS_CMD_UPDATE_AUX_STRING);
186         m_send_trans.put_data (str);
187         m_send_trans.put_data (attrs);
188     }
189 }
190 
191 void
commit_string(int id,const WideString & str)192 SocketFrontEnd::commit_string (int id, const WideString & str)
193 {
194     if (m_current_instance == id) {
195         m_send_trans.put_command (SCIM_TRANS_CMD_COMMIT_STRING);
196         m_send_trans.put_data (str);
197     }
198 }
199 
200 void
forward_key_event(int id,const KeyEvent & key)201 SocketFrontEnd::forward_key_event (int id, const KeyEvent & key)
202 {
203     if (m_current_instance == id) {
204         m_send_trans.put_command (SCIM_TRANS_CMD_FORWARD_KEY_EVENT);
205         m_send_trans.put_data (key);
206     }
207 }
208 
209 void
update_lookup_table(int id,const LookupTable & table)210 SocketFrontEnd::update_lookup_table (int id, const LookupTable & table)
211 {
212     if (m_current_instance == id) {
213         m_send_trans.put_command (SCIM_TRANS_CMD_UPDATE_LOOKUP_TABLE);
214         m_send_trans.put_data (table);
215     }
216 }
217 
218 void
register_properties(int id,const PropertyList & properties)219 SocketFrontEnd::register_properties (int id, const PropertyList &properties)
220 {
221     if (m_current_instance == id) {
222         m_send_trans.put_command (SCIM_TRANS_CMD_REGISTER_PROPERTIES);
223         m_send_trans.put_data (properties);
224     }
225 }
226 
227 void
update_property(int id,const Property & property)228 SocketFrontEnd::update_property (int id, const Property &property)
229 {
230     if (m_current_instance == id) {
231         m_send_trans.put_command (SCIM_TRANS_CMD_UPDATE_PROPERTY);
232         m_send_trans.put_data (property);
233     }
234 }
235 
236 void
beep(int id)237 SocketFrontEnd::beep (int id)
238 {
239     if (m_current_instance == id) {
240         m_send_trans.put_command (SCIM_TRANS_CMD_BEEP);
241     }
242 }
243 
244 void
start_helper(int id,const String & helper_uuid)245 SocketFrontEnd::start_helper (int id, const String &helper_uuid)
246 {
247     SCIM_DEBUG_FRONTEND (2) << "start_helper (" << helper_uuid << ")\n";
248     if (m_current_instance == id) {
249         m_send_trans.put_command (SCIM_TRANS_CMD_START_HELPER);
250         m_send_trans.put_data (helper_uuid);
251     }
252 }
253 
254 void
stop_helper(int id,const String & helper_uuid)255 SocketFrontEnd::stop_helper (int id, const String &helper_uuid)
256 {
257     SCIM_DEBUG_FRONTEND (2) << "stop_helper (" << helper_uuid << ")\n";
258 
259     if (m_current_instance == id) {
260         m_send_trans.put_command (SCIM_TRANS_CMD_STOP_HELPER);
261         m_send_trans.put_data (helper_uuid);
262     }
263 }
264 
265 void
send_helper_event(int id,const String & helper_uuid,const Transaction & trans)266 SocketFrontEnd::send_helper_event (int id, const String &helper_uuid, const Transaction &trans)
267 {
268     if (m_current_instance == id) {
269         m_send_trans.put_command (SCIM_TRANS_CMD_SEND_HELPER_EVENT);
270         m_send_trans.put_data (helper_uuid);
271         m_send_trans.put_data (trans);
272     }
273 }
274 
275 bool
get_surrounding_text(int id,WideString & text,int & cursor,int maxlen_before,int maxlen_after)276 SocketFrontEnd::get_surrounding_text (int id, WideString &text, int &cursor, int maxlen_before, int maxlen_after)
277 {
278     text.clear ();
279     cursor = 0;
280 
281     if (m_current_instance == id && m_current_socket_client >= 0 && (maxlen_before != 0 || maxlen_after != 0)) {
282         if (maxlen_before < 0) maxlen_before = -1;
283         if (maxlen_after < 0) maxlen_after = -1;
284 
285         m_temp_trans.clear ();
286         m_temp_trans.put_command (SCIM_TRANS_CMD_REPLY);
287         m_temp_trans.put_command (SCIM_TRANS_CMD_GET_SURROUNDING_TEXT);
288         m_temp_trans.put_data ((uint32) maxlen_before);
289         m_temp_trans.put_data ((uint32) maxlen_after);
290 
291         Socket socket_client (m_current_socket_client);
292 
293         if (m_temp_trans.write_to_socket (socket_client) &&
294             m_temp_trans.read_from_socket (socket_client, m_socket_timeout)) {
295 
296             int cmd;
297             uint32 key;
298             uint32 cur;
299 
300             if (m_temp_trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REQUEST &&
301                 m_temp_trans.get_data (key) && key == m_current_socket_client_key &&
302                 m_temp_trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_GET_SURROUNDING_TEXT &&
303                 m_temp_trans.get_data (text) && m_temp_trans.get_data (cur)) {
304                 cursor = (int) cur;
305                 return true;
306             }
307         }
308     }
309     return false;
310 }
311 
312 bool
delete_surrounding_text(int id,int offset,int len)313 SocketFrontEnd::delete_surrounding_text (int id, int offset, int len)
314 {
315     if (m_current_instance == id && m_current_socket_client >= 0 && len > 0) {
316         m_temp_trans.clear ();
317         m_temp_trans.put_command (SCIM_TRANS_CMD_REPLY);
318         m_temp_trans.put_command (SCIM_TRANS_CMD_DELETE_SURROUNDING_TEXT);
319         m_temp_trans.put_data ((uint32) offset);
320         m_temp_trans.put_data ((uint32) len);
321 
322         Socket socket_client (m_current_socket_client);
323 
324         if (m_temp_trans.write_to_socket (socket_client) &&
325             m_temp_trans.read_from_socket (socket_client, m_socket_timeout)) {
326 
327             int cmd;
328             uint32 key;
329 
330             if (m_temp_trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REQUEST &&
331                 m_temp_trans.get_data (key) && key == m_current_socket_client_key &&
332                 m_temp_trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_DELETE_SURROUNDING_TEXT &&
333                 m_temp_trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_OK)
334                 return true;
335         }
336     }
337     return false;
338 }
339 
340 void
init(int argc,char ** argv)341 SocketFrontEnd::init (int argc, char **argv)
342 {
343     int max_clients = -1;
344 
345     if (!m_config.null ()) {
346         String str;
347 
348         m_config_readonly = m_config->read (String (SCIM_CONFIG_FRONTEND_SOCKET_CONFIG_READONLY), false);
349 
350         max_clients = m_config->read (String (SCIM_CONFIG_FRONTEND_SOCKET_MAXCLIENTS), -1);
351 
352         m_config->signal_connect_reload (slot (this, &SocketFrontEnd::reload_config_callback));
353     } else {
354         m_config_readonly = false;
355         max_clients = -1;
356     }
357 
358     if (!m_socket_server.create (scim_get_default_socket_frontend_address ()))
359         throw FrontEndError ("SocketFrontEnd -- Cannot create SocketServer.");
360 
361     m_socket_server.set_max_clients (max_clients);
362 
363     m_socket_server.signal_connect_accept (
364         slot (this, &SocketFrontEnd::socket_accept_callback));
365 
366     m_socket_server.signal_connect_receive (
367         slot (this, &SocketFrontEnd::socket_receive_callback));
368 
369     m_socket_server.signal_connect_exception(
370         slot (this, &SocketFrontEnd::socket_exception_callback));
371 
372     if (argv && argc > 1) {
373         for (int i = 1; i < argc && argv [i]; ++i) {
374             if (String ("--no-stay") == argv [i])
375                 m_stay = false;
376         }
377     }
378 
379     /**
380      * initialize the random number generator.
381      */
382     srand (time (0));
383 }
384 
385 void
run()386 SocketFrontEnd::run ()
387 {
388     if (m_socket_server.valid ())
389         m_socket_server.run ();
390 }
391 
392 uint32
generate_key() const393 SocketFrontEnd::generate_key () const
394 {
395     return rand ();
396 }
397 
398 bool
check_client_connection(const Socket & client) const399 SocketFrontEnd::check_client_connection (const Socket &client) const
400 {
401     SCIM_DEBUG_FRONTEND (1) << "check_client_connection (" << client.get_id () << ").\n";
402 
403     unsigned char buf [sizeof(uint32)];
404 
405     int nbytes = client.read_with_timeout (buf, sizeof(uint32), m_socket_timeout);
406 
407     if (nbytes == sizeof (uint32))
408         return true;
409 
410     if (nbytes < 0) {
411         SCIM_DEBUG_FRONTEND (2) << " Error occurred when reading socket (" << client.get_id ()
412             << "):" << client.get_error_message () << "\n";
413     } else {
414         SCIM_DEBUG_FRONTEND (2) << " Timeout when reading socket (" << client.get_id ()
415             << ").\n";
416     }
417 
418     return false;
419 }
420 
421 void
socket_accept_callback(SocketServer * server,const Socket & client)422 SocketFrontEnd::socket_accept_callback (SocketServer *server, const Socket &client)
423 {
424     SCIM_DEBUG_FRONTEND (1) << "socket_accept_callback (" << client.get_id () << ").\n";
425 }
426 
427 void
socket_receive_callback(SocketServer * server,const Socket & client)428 SocketFrontEnd::socket_receive_callback (SocketServer *server, const Socket &client)
429 {
430     int id = client.get_id ();
431     int cmd;
432     uint32 key;
433 
434     ClientInfo client_info;
435 
436     SCIM_DEBUG_FRONTEND (1) << "socket_receive_callback (" << id << ").\n";
437 
438     // Check if the client is closed.
439     if (!check_client_connection (client)) {
440         SCIM_DEBUG_FRONTEND (2) << " closing client connection.\n";
441         socket_close_connection (server, client);
442         return;
443     }
444 
445     client_info = socket_get_client_info (client);
446 
447     // If it's a new client, then request to open the connection first.
448     if (client_info.type == UNKNOWN_CLIENT) {
449         socket_open_connection (server, client);
450         return;
451     }
452 
453     // If can not read the transaction,
454     // or the transaction is not started with SCIM_TRANS_CMD_REQUEST,
455     // or the key is mismatch,
456     // just return.
457     if (!m_receive_trans.read_from_socket (client, m_socket_timeout) ||
458         !m_receive_trans.get_command (cmd) || cmd != SCIM_TRANS_CMD_REQUEST ||
459         !m_receive_trans.get_data (key) || key != (uint32) client_info.key)
460         return;
461 
462     m_current_socket_client     = id;
463     m_current_socket_client_key = key;
464 
465     m_send_trans.clear ();
466     m_send_trans.put_command (SCIM_TRANS_CMD_REPLY);
467 
468     // Move the read ptr to the end.
469     m_send_trans.get_command (cmd);
470 
471     while (m_receive_trans.get_command (cmd)) {
472         if (cmd == SCIM_TRANS_CMD_PROCESS_KEY_EVENT)
473             socket_process_key_event (id);
474         else if (cmd == SCIM_TRANS_CMD_MOVE_PREEDIT_CARET)
475             socket_move_preedit_caret (id);
476         else if (cmd == SCIM_TRANS_CMD_SELECT_CANDIDATE)
477             socket_select_candidate (id);
478         else if (cmd == SCIM_TRANS_CMD_UPDATE_LOOKUP_TABLE_PAGE_SIZE)
479             socket_update_lookup_table_page_size (id);
480         else if (cmd == SCIM_TRANS_CMD_LOOKUP_TABLE_PAGE_UP)
481             socket_lookup_table_page_up (id);
482         else if (cmd == SCIM_TRANS_CMD_LOOKUP_TABLE_PAGE_DOWN)
483             socket_lookup_table_page_down (id);
484         else if (cmd == SCIM_TRANS_CMD_RESET)
485             socket_reset (id);
486         else if (cmd == SCIM_TRANS_CMD_FOCUS_IN)
487             socket_focus_in (id);
488         else if (cmd == SCIM_TRANS_CMD_FOCUS_OUT)
489             socket_focus_out (id);
490         else if (cmd == SCIM_TRANS_CMD_TRIGGER_PROPERTY)
491             socket_trigger_property (id);
492         else if (cmd == SCIM_TRANS_CMD_PROCESS_HELPER_EVENT)
493             socket_process_helper_event (id);
494         else if (cmd == SCIM_TRANS_CMD_UPDATE_CLIENT_CAPABILITIES)
495             socket_update_client_capabilities (id);
496         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_LIST)
497             socket_get_factory_list (id);
498         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_NAME)
499             socket_get_factory_name (id);
500         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_AUTHORS)
501             socket_get_factory_authors (id);
502         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_CREDITS)
503             socket_get_factory_credits (id);
504         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_HELP)
505             socket_get_factory_help (id);
506         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_LOCALES)
507             socket_get_factory_locales (id);
508         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_ICON_FILE)
509             socket_get_factory_icon_file (id);
510         else if (cmd == SCIM_TRANS_CMD_GET_FACTORY_LANGUAGE)
511             socket_get_factory_language (id);
512         else if (cmd == SCIM_TRANS_CMD_NEW_INSTANCE)
513             socket_new_instance (id);
514         else if (cmd == SCIM_TRANS_CMD_DELETE_INSTANCE)
515             socket_delete_instance (id);
516         else if (cmd == SCIM_TRANS_CMD_DELETE_ALL_INSTANCES)
517             socket_delete_all_instances (id);
518         else if (cmd == SCIM_TRANS_CMD_FLUSH_CONFIG)
519             socket_flush_config (id);
520         else if (cmd == SCIM_TRANS_CMD_ERASE_CONFIG)
521             socket_erase_config (id);
522         else if (cmd == SCIM_TRANS_CMD_RELOAD_CONFIG)
523             socket_reload_config (id);
524         else if (cmd == SCIM_TRANS_CMD_GET_CONFIG_STRING)
525             socket_get_config_string (id);
526         else if (cmd == SCIM_TRANS_CMD_SET_CONFIG_STRING)
527             socket_set_config_string (id);
528         else if (cmd == SCIM_TRANS_CMD_GET_CONFIG_INT)
529             socket_get_config_int (id);
530         else if (cmd == SCIM_TRANS_CMD_SET_CONFIG_INT)
531             socket_set_config_int (id);
532         else if (cmd == SCIM_TRANS_CMD_GET_CONFIG_BOOL)
533             socket_get_config_bool (id);
534         else if (cmd == SCIM_TRANS_CMD_SET_CONFIG_BOOL)
535             socket_set_config_bool (id);
536         else if (cmd == SCIM_TRANS_CMD_GET_CONFIG_DOUBLE)
537             socket_get_config_double (id);
538         else if (cmd == SCIM_TRANS_CMD_SET_CONFIG_DOUBLE)
539             socket_set_config_double (id);
540         else if (cmd == SCIM_TRANS_CMD_GET_CONFIG_VECTOR_STRING)
541             socket_get_config_vector_string (id);
542         else if (cmd == SCIM_TRANS_CMD_SET_CONFIG_VECTOR_STRING)
543             socket_set_config_vector_string (id);
544         else if (cmd == SCIM_TRANS_CMD_GET_CONFIG_VECTOR_INT)
545             socket_get_config_vector_int (id);
546         else if (cmd == SCIM_TRANS_CMD_SET_CONFIG_VECTOR_INT)
547             socket_set_config_vector_int (id);
548         else if (cmd == SCIM_TRANS_CMD_LOAD_FILE)
549             socket_load_file (id);
550         else if (cmd == SCIM_TRANS_CMD_CLOSE_CONNECTION) {
551             socket_close_connection (server, client);
552             m_current_socket_client     = -1;
553             m_current_socket_client_key = 0;
554             return;
555         }
556     }
557 
558     // Send reply to client
559     if (m_send_trans.get_data_type () == SCIM_TRANS_DATA_UNKNOWN)
560         m_send_trans.put_command (SCIM_TRANS_CMD_FAIL);
561 
562     m_send_trans.write_to_socket (client);
563 
564     m_current_socket_client     = -1;
565     m_current_socket_client_key = 0;
566 
567     SCIM_DEBUG_FRONTEND (1) << "End of socket_receive_callback (" << id << ").\n";
568 }
569 
570 bool
socket_open_connection(SocketServer * server,const Socket & client)571 SocketFrontEnd::socket_open_connection (SocketServer *server, const Socket &client)
572 {
573     SCIM_DEBUG_FRONTEND (2) << " Open socket connection for client " << client.get_id () << "  number of clients=" << m_socket_client_repository.size () << ".\n";
574 
575     uint32 key;
576     String type = scim_socket_accept_connection (key,
577                                                  String ("SocketFrontEnd"),
578                                                  String ("SocketIMEngine,SocketConfig"),
579                                                  client,
580                                                  m_socket_timeout);
581 
582     if (type.length ()) {
583         ClientInfo info;
584         info.key = key;
585         info.type = ((type == "SocketIMEngine") ? IMENGINE_CLIENT : CONFIG_CLIENT);
586 
587         SCIM_DEBUG_MAIN (2) << " Add client to repository. Type=" << type << " key=" << key << "\n";
588         m_socket_client_repository [client.get_id ()] = info;
589         return true;
590     }
591 
592     // Client did not pass the registration process, close it.
593     SCIM_DEBUG_FRONTEND (2) << " Failed to create new connection.\n";
594     server->close_connection (client);
595     return false;
596 }
597 
598 void
socket_close_connection(SocketServer * server,const Socket & client)599 SocketFrontEnd::socket_close_connection (SocketServer *server, const Socket &client)
600 {
601     SCIM_DEBUG_FRONTEND (2) << " Close client connection " << client.get_id () << "  number of clients=" << m_socket_client_repository.size () << ".\n";
602 
603     ClientInfo client_info = socket_get_client_info (client);
604 
605     server->close_connection (client);
606 
607     if (client_info.type != UNKNOWN_CLIENT) {
608         m_socket_client_repository.erase (client.get_id ());
609 
610         if (client_info.type == IMENGINE_CLIENT)
611             socket_delete_all_instances (client.get_id ());
612 
613         if (!m_socket_client_repository.size () && !m_stay)
614             server->shutdown ();
615     }
616 }
617 
618 SocketFrontEnd::ClientInfo
socket_get_client_info(const Socket & client)619 SocketFrontEnd::socket_get_client_info (const Socket &client)
620 {
621     static ClientInfo null_client = { 0, UNKNOWN_CLIENT };
622     SocketClientRepository::iterator it = m_socket_client_repository.find (client.get_id ());
623 
624     if (it != m_socket_client_repository.end ())
625         return it->second;
626 
627     return null_client;
628 }
629 
630 void
socket_exception_callback(SocketServer * server,const Socket & client)631 SocketFrontEnd::socket_exception_callback (SocketServer *server, const Socket &client)
632 {
633     SCIM_DEBUG_FRONTEND (1) << "socket_exception_callback (" << client.get_id () << ").\n";
634 
635     socket_close_connection (server, client);
636 }
637 
638 //client_id is client's socket id
639 void
socket_get_factory_list(int)640 SocketFrontEnd::socket_get_factory_list (int /*client_id*/)
641 {
642     String encoding;
643 
644     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_list.\n";
645 
646     if (m_receive_trans.get_data (encoding)) {
647         std::vector<String> uuids;
648 
649         get_factory_list_for_encoding (uuids, encoding);
650 
651         SCIM_DEBUG_FRONTEND (3) << "  Encoding (" << encoding
652             << ") Num(" << uuids.size () << ").\n";
653 
654         m_send_trans.put_data (uuids);
655         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
656     }
657 }
658 
659 void
socket_get_factory_name(int)660 SocketFrontEnd::socket_get_factory_name (int /*client_id*/)
661 {
662     String sfid;
663 
664     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_name.\n";
665 
666     if (m_receive_trans.get_data (sfid)) {
667         WideString name = get_factory_name (sfid);
668 
669         m_send_trans.put_data (name);
670         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
671     }
672 }
673 
674 void
socket_get_factory_authors(int)675 SocketFrontEnd::socket_get_factory_authors (int /*client_id*/)
676 {
677     String sfid;
678 
679     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_authors.\n";
680 
681     if (m_receive_trans.get_data (sfid)) {
682         WideString authors = get_factory_authors (sfid);
683 
684         m_send_trans.put_data (authors);
685         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
686     }
687 }
688 
689 void
socket_get_factory_credits(int)690 SocketFrontEnd::socket_get_factory_credits (int /*client_id*/)
691 {
692     String sfid;
693 
694     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_credits.\n";
695 
696     if (m_receive_trans.get_data (sfid)) {
697         WideString credits = get_factory_credits (sfid);
698 
699         m_send_trans.put_data (credits);
700         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
701     }
702 }
703 
704 void
socket_get_factory_help(int)705 SocketFrontEnd::socket_get_factory_help (int /*client_id*/)
706 {
707     String sfid;
708 
709     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_help.\n";
710 
711     if (m_receive_trans.get_data (sfid)) {
712         WideString help = get_factory_help (sfid);
713 
714         m_send_trans.put_data (help);
715         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
716     }
717 }
718 
719 void
socket_get_factory_locales(int)720 SocketFrontEnd::socket_get_factory_locales (int /*client_id*/)
721 {
722     String sfid;
723 
724     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_locales.\n";
725 
726     if (m_receive_trans.get_data (sfid)) {
727         String locales = get_factory_locales (sfid);
728 
729         SCIM_DEBUG_FRONTEND (3) << "  Locales (" << locales << ").\n";
730 
731         m_send_trans.put_data (locales);
732         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
733     }
734 }
735 
736 void
socket_get_factory_icon_file(int)737 SocketFrontEnd::socket_get_factory_icon_file (int /*client_id*/)
738 {
739     String sfid;
740 
741     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_icon_file.\n";
742 
743     if (m_receive_trans.get_data (sfid)) {
744         String iconfile = get_factory_icon_file (sfid);
745 
746         SCIM_DEBUG_FRONTEND (3) << "  ICON File (" << iconfile << ").\n";
747 
748         m_send_trans.put_data (iconfile);
749         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
750     }
751 }
752 
753 void
socket_get_factory_language(int)754 SocketFrontEnd::socket_get_factory_language (int /*client_id*/)
755 {
756     String sfid;
757 
758     SCIM_DEBUG_FRONTEND (2) << " socket_get_factory_language.\n";
759 
760     if (m_receive_trans.get_data (sfid)) {
761         String language = get_factory_language (sfid);
762 
763         SCIM_DEBUG_FRONTEND (3) << "  Language (" << language << ").\n";
764 
765         m_send_trans.put_data (language);
766         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
767     }
768 }
769 
770 void
socket_new_instance(int client_id)771 SocketFrontEnd::socket_new_instance (int client_id)
772 {
773     String sfid;
774     String encoding;
775 
776     SCIM_DEBUG_FRONTEND (2) << " socket_new_instance.\n";
777 
778     if (m_receive_trans.get_data (sfid) &&
779         m_receive_trans.get_data (encoding)) {
780         int siid = new_instance (sfid, encoding);
781 
782         // Instance created OK.
783         if (siid >= 0) {
784             SocketInstanceRepository::iterator it =
785                 std::lower_bound (m_socket_instance_repository.begin (),
786                                   m_socket_instance_repository.end (),
787                                   std::pair <int, int> (client_id, siid));
788 
789             if (it == m_socket_instance_repository.end ())
790                 m_socket_instance_repository.push_back (std::pair <int, int> (client_id, siid));
791             else
792                 m_socket_instance_repository.insert (it, std::pair <int, int> (client_id, siid));
793 
794             SCIM_DEBUG_FRONTEND (3) << "  InstanceID (" << siid << ").\n";
795 
796             m_send_trans.put_data ((uint32)siid);
797             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
798         }
799     }
800 }
801 
802 void
socket_delete_instance(int client_id)803 SocketFrontEnd::socket_delete_instance (int client_id)
804 {
805     uint32 siid;
806 
807     SCIM_DEBUG_FRONTEND (2) << " socket_delete_instance.\n";
808 
809     if (m_receive_trans.get_data (siid)) {
810 
811         SCIM_DEBUG_FRONTEND (3) << "  InstanceID (" << siid << ").\n";
812 
813         m_current_instance = (int) siid;
814 
815         delete_instance ((int) siid);
816 
817         m_current_instance = -1;
818 
819         SocketInstanceRepository::iterator it =
820             std::lower_bound (m_socket_instance_repository.begin (),
821                               m_socket_instance_repository.end (),
822                               std::pair <int, int> (client_id, siid));
823 
824         if (it != m_socket_instance_repository.end () &&
825             *it == std::pair <int, int> (client_id, siid))
826             m_socket_instance_repository.erase (it);
827 
828         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
829     }
830 }
831 
832 void
socket_delete_all_instances(int client_id)833 SocketFrontEnd::socket_delete_all_instances (int client_id)
834 {
835     SCIM_DEBUG_FRONTEND (2) << " socket_delete_all_instances.\n";
836 
837     SocketInstanceRepository::iterator it;
838 
839     SocketInstanceRepository::iterator lit =
840         std::lower_bound (m_socket_instance_repository.begin (),
841                           m_socket_instance_repository.end (),
842                           std::pair <int, int> (client_id, 0));
843 
844     SocketInstanceRepository::iterator uit =
845         std::upper_bound (m_socket_instance_repository.begin (),
846                           m_socket_instance_repository.end (),
847                           std::pair <int, int> (client_id, INT_MAX));
848 
849     if (lit != uit) {
850         for (it = lit; it != uit; ++it) {
851             m_current_instance = it->second;
852             delete_instance (it->second);
853         }
854         m_current_instance = -1;
855         m_socket_instance_repository.erase (lit, uit);
856         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
857     }
858 }
859 
860 void
socket_process_key_event(int)861 SocketFrontEnd::socket_process_key_event (int /*client_id*/)
862 {
863     uint32   siid;
864     KeyEvent event;
865 
866     SCIM_DEBUG_FRONTEND (2) << " socket_process_key_event.\n";
867 
868     if (m_receive_trans.get_data (siid) &&
869         m_receive_trans.get_data (event)) {
870 
871         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ") KeyEvent ("
872             << event.code << "," << event.mask << ").\n";
873 
874         m_current_instance = (int) siid;
875 
876         if (process_key_event ((int) siid, event))
877             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
878         else
879             m_send_trans.put_command (SCIM_TRANS_CMD_FAIL);
880 
881         m_current_instance = -1;
882     }
883 }
884 
885 void
socket_move_preedit_caret(int)886 SocketFrontEnd::socket_move_preedit_caret (int /*client_id*/)
887 {
888     uint32 siid;
889     uint32 caret;
890 
891     SCIM_DEBUG_FRONTEND (2) << " socket_move_preedit_caret.\n";
892 
893     if (m_receive_trans.get_data (siid) &&
894         m_receive_trans.get_data (caret)) {
895 
896         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid
897             << ") Caret (" << caret << ").\n";
898 
899         m_current_instance = (int) siid;
900 
901         move_preedit_caret ((int) siid, caret);
902         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
903 
904         m_current_instance = -1;
905     }
906 }
907 
908 void
socket_select_candidate(int)909 SocketFrontEnd::socket_select_candidate (int /*client_id*/)
910 {
911     uint32 siid;
912     uint32 item;
913 
914     SCIM_DEBUG_FRONTEND (2) << " socket_select_candidate.\n";
915 
916     if (m_receive_trans.get_data (siid) &&
917         m_receive_trans.get_data (item)) {
918 
919         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ") Item (" << item << ").\n";
920 
921         m_current_instance = (int) siid;
922 
923         select_candidate ((int) siid, item);
924         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
925 
926         m_current_instance = -1;
927     }
928 }
929 
930 void
socket_update_lookup_table_page_size(int)931 SocketFrontEnd::socket_update_lookup_table_page_size (int /*client_id*/)
932 {
933     uint32 siid;
934     uint32 size;
935 
936     SCIM_DEBUG_FRONTEND (2) << " socket_update_lookup_table_page_size.\n";
937 
938     if (m_receive_trans.get_data (siid) &&
939         m_receive_trans.get_data (size)) {
940 
941         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ") PageSize (" << size << ").\n";
942 
943         m_current_instance = (int) siid;
944 
945         update_lookup_table_page_size ((int) siid, size);
946         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
947 
948         m_current_instance = -1;
949     }
950 }
951 
952 void
socket_lookup_table_page_up(int)953 SocketFrontEnd::socket_lookup_table_page_up (int /*client_id*/)
954 {
955     uint32 siid;
956 
957     SCIM_DEBUG_FRONTEND (2) << " socket_lookup_table_page_up.\n";
958 
959     if (m_receive_trans.get_data (siid)) {
960 
961         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
962 
963         m_current_instance = (int) siid;
964 
965         lookup_table_page_up ((int) siid);
966         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
967 
968         m_current_instance = -1;
969     }
970 }
971 
972 void
socket_lookup_table_page_down(int)973 SocketFrontEnd::socket_lookup_table_page_down (int /*client_id*/)
974 {
975     uint32 siid;
976 
977     SCIM_DEBUG_FRONTEND (2) << " socket_lookup_table_page_down.\n";
978 
979     if (m_receive_trans.get_data (siid)) {
980 
981         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
982 
983         m_current_instance = (int) siid;
984 
985         lookup_table_page_down ((int) siid);
986         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
987 
988         m_current_instance = -1;
989     }
990 }
991 
992 void
socket_reset(int)993 SocketFrontEnd::socket_reset (int /*client_id*/)
994 {
995     uint32 siid;
996 
997     SCIM_DEBUG_FRONTEND (2) << " socket_reset.\n";
998 
999     if (m_receive_trans.get_data (siid)) {
1000 
1001         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1002 
1003         m_current_instance = (int) siid;
1004 
1005         reset ((int) siid);
1006         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1007 
1008         m_current_instance = -1;
1009     }
1010 }
1011 
1012 void
socket_focus_in(int)1013 SocketFrontEnd::socket_focus_in (int /*client_id*/)
1014 {
1015     uint32 siid;
1016 
1017     SCIM_DEBUG_FRONTEND (2) << " socket_focus_in.\n";
1018 
1019     if (m_receive_trans.get_data (siid)) {
1020 
1021         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1022 
1023         m_current_instance = (int) siid;
1024 
1025         focus_in ((int) siid);
1026         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1027 
1028         m_current_instance = -1;
1029     }
1030 }
1031 
1032 void
socket_focus_out(int)1033 SocketFrontEnd::socket_focus_out (int /*client_id*/)
1034 {
1035     uint32 siid;
1036 
1037     SCIM_DEBUG_FRONTEND (2) << " socket_focus_out.\n";
1038 
1039     if (m_receive_trans.get_data (siid)) {
1040 
1041         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1042 
1043         m_current_instance = (int) siid;
1044 
1045         focus_out ((int) siid);
1046         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1047 
1048         m_current_instance = -1;
1049     }
1050 }
1051 
1052 void
socket_trigger_property(int)1053 SocketFrontEnd::socket_trigger_property (int /*client_id*/)
1054 {
1055     uint32 siid;
1056     String property;
1057 
1058     SCIM_DEBUG_FRONTEND (2) << " socket_trigger_property.\n";
1059 
1060     if (m_receive_trans.get_data (siid) &&
1061         m_receive_trans.get_data (property)) {
1062 
1063         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1064 
1065         m_current_instance = (int) siid;
1066 
1067         trigger_property ((int) siid, property);
1068         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1069 
1070         m_current_instance = -1;
1071     }
1072 }
1073 
1074 void
socket_process_helper_event(int)1075 SocketFrontEnd::socket_process_helper_event (int /*client_id*/)
1076 {
1077     uint32 siid;
1078     String helper_uuid;
1079     Transaction trans;
1080 
1081     SCIM_DEBUG_FRONTEND (2) << " socket_process_helper_event.\n";
1082 
1083     if (m_receive_trans.get_data (siid) &&
1084         m_receive_trans.get_data (helper_uuid) &&
1085         m_receive_trans.get_data (trans)) {
1086 
1087         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1088 
1089         m_current_instance = (int) siid;
1090 
1091         process_helper_event ((int) siid, helper_uuid, trans);
1092         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1093 
1094         m_current_instance = -1;
1095     }
1096 }
1097 
1098 void
socket_update_client_capabilities(int)1099 SocketFrontEnd::socket_update_client_capabilities (int /*client_id*/)
1100 {
1101     uint32 siid;
1102     uint32 cap;
1103 
1104     SCIM_DEBUG_FRONTEND (2) << " socket_update_client_capabilities.\n";
1105 
1106     if (m_receive_trans.get_data (siid) && m_receive_trans.get_data (cap)) {
1107 
1108         SCIM_DEBUG_FRONTEND (3) << "  SI (" << siid << ").\n";
1109 
1110         m_current_instance = (int) siid;
1111 
1112         update_client_capabilities ((int) siid, cap);
1113 
1114         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1115 
1116         m_current_instance = -1;
1117     }
1118 }
1119 
1120 
1121 void
socket_flush_config(int)1122 SocketFrontEnd::socket_flush_config (int /*client_id*/)
1123 {
1124     if (m_config_readonly || m_config.null ())
1125         return;
1126 
1127     SCIM_DEBUG_FRONTEND (2) << " socket_flush_config.\n";
1128 
1129     if (m_config->flush ())
1130         m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1131 }
1132 
1133 void
socket_erase_config(int)1134 SocketFrontEnd::socket_erase_config (int /*client_id*/)
1135 {
1136     if (m_config_readonly || m_config.null ())
1137         return;
1138 
1139     String key;
1140 
1141     SCIM_DEBUG_FRONTEND (2) << " socket_erase_config.\n";
1142 
1143     if (m_receive_trans.get_data (key)) {
1144 
1145         SCIM_DEBUG_FRONTEND (3) << "  Key   (" << key << ").\n";
1146 
1147         if (m_config->erase (key))
1148             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1149     }
1150 }
1151 
1152 void
socket_reload_config(int)1153 SocketFrontEnd::socket_reload_config (int /*client_id*/)
1154 {
1155     static timeval last_timestamp = {0, 0};
1156 
1157     if (m_config.null ())
1158         return;
1159 
1160     SCIM_DEBUG_FRONTEND (2) << " socket_reload_config.\n";
1161 
1162     timeval timestamp;
1163 
1164     gettimeofday (&timestamp, 0);
1165 
1166     if (timestamp.tv_sec > last_timestamp.tv_sec + 1)
1167         m_config->reload ();
1168 
1169     gettimeofday (&last_timestamp, 0);
1170 
1171     m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1172 }
1173 
1174 void
socket_get_config_string(int)1175 SocketFrontEnd::socket_get_config_string (int /*client_id*/)
1176 {
1177     if (m_config.null ()) return;
1178 
1179     String key;
1180 
1181     SCIM_DEBUG_FRONTEND (2) << " socket_get_config_string.\n";
1182 
1183     if (m_receive_trans.get_data (key)) {
1184         String value;
1185 
1186         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1187 
1188         if (m_config->read (key, &value)) {
1189             m_send_trans.put_data (value);
1190             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1191         }
1192     }
1193 }
1194 
1195 void
socket_set_config_string(int)1196 SocketFrontEnd::socket_set_config_string (int /*client_id*/)
1197 {
1198     if (m_config_readonly || m_config.null ())
1199         return;
1200 
1201     String key;
1202     String value;
1203 
1204     SCIM_DEBUG_FRONTEND (2) << " socket_set_config_string.\n";
1205 
1206     if (m_receive_trans.get_data (key) &&
1207         m_receive_trans.get_data (value)) {
1208 
1209         SCIM_DEBUG_FRONTEND (3) << "  Key   (" << key << ").\n";
1210         SCIM_DEBUG_FRONTEND (3) << "  Value (" << value << ").\n";
1211 
1212         if (m_config->write (key, value))
1213             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1214     }
1215 }
1216 
1217 void
socket_get_config_int(int)1218 SocketFrontEnd::socket_get_config_int (int /*client_id*/)
1219 {
1220     if (m_config.null ()) return;
1221 
1222     String key;
1223 
1224     SCIM_DEBUG_FRONTEND (2) << " socket_get_config_int.\n";
1225 
1226     if (m_receive_trans.get_data (key)) {
1227 
1228         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1229 
1230         int value;
1231         if (m_config->read (key, &value)) {
1232             m_send_trans.put_data ((uint32) value);
1233             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1234         }
1235     }
1236 }
1237 
1238 void
socket_set_config_int(int)1239 SocketFrontEnd::socket_set_config_int (int /*client_id*/)
1240 {
1241     if (m_config_readonly || m_config.null ())
1242         return;
1243 
1244     String key;
1245     uint32 value;
1246 
1247     SCIM_DEBUG_FRONTEND (2) << " socket_set_config_int.\n";
1248 
1249     if (m_receive_trans.get_data (key) &&
1250         m_receive_trans.get_data (value)) {
1251 
1252         SCIM_DEBUG_FRONTEND (3) << "  Key   (" << key << ").\n";
1253         SCIM_DEBUG_FRONTEND (3) << "  Value (" << value << ").\n";
1254 
1255         if (m_config->write (key, (int) value))
1256             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1257     }
1258 }
1259 
1260 void
socket_get_config_bool(int)1261 SocketFrontEnd::socket_get_config_bool (int /*client_id*/)
1262 {
1263     if (m_config.null ()) return;
1264 
1265     String key;
1266 
1267     SCIM_DEBUG_FRONTEND (2) << " socket_get_config_bool.\n";
1268 
1269     if (m_receive_trans.get_data (key)) {
1270         bool value;
1271 
1272         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1273 
1274         if (m_config->read (key, &value)) {
1275             m_send_trans.put_data ((uint32) value);
1276             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1277         }
1278     }
1279 }
1280 
1281 void
socket_set_config_bool(int)1282 SocketFrontEnd::socket_set_config_bool (int /*client_id*/)
1283 {
1284     if (m_config_readonly || m_config.null ())
1285         return;
1286 
1287     String key;
1288     uint32 value;
1289 
1290     SCIM_DEBUG_FRONTEND (2) << " socket_set_config_bool.\n";
1291 
1292     if (m_receive_trans.get_data (key) &&
1293         m_receive_trans.get_data (value)) {
1294 
1295         SCIM_DEBUG_FRONTEND (3) << "  Key   (" << key << ").\n";
1296         SCIM_DEBUG_FRONTEND (3) << "  Value (" << value << ").\n";
1297 
1298         if (m_config->write (key, (bool) value))
1299             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1300     }
1301 }
1302 
1303 void
socket_get_config_double(int)1304 SocketFrontEnd::socket_get_config_double (int /*client_id*/)
1305 {
1306     if (m_config.null ()) return;
1307 
1308     String key;
1309 
1310     SCIM_DEBUG_FRONTEND (2) << " socket_get_config_double.\n";
1311 
1312     if (m_receive_trans.get_data (key)) {
1313         double value;
1314 
1315         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1316 
1317         if (m_config->read (key, &value)) {
1318             char buf [80];
1319             snprintf (buf, 79, "%lE", value);
1320             m_send_trans.put_data (String (buf));
1321             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1322         }
1323     }
1324 }
1325 
1326 void
socket_set_config_double(int)1327 SocketFrontEnd::socket_set_config_double (int /*client_id*/)
1328 {
1329     if (m_config_readonly || m_config.null ())
1330         return;
1331 
1332     String key;
1333     String str;
1334 
1335     SCIM_DEBUG_FRONTEND (2) << " socket_set_config_double.\n";
1336 
1337     if (m_receive_trans.get_data (key) &&
1338         m_receive_trans.get_data (str)) {
1339         double value;
1340         sscanf (str.c_str (), "%lE", &value);
1341 
1342         SCIM_DEBUG_FRONTEND (3) << "  Key   (" << key << ").\n";
1343         SCIM_DEBUG_FRONTEND (3) << "  Value (" << value << ").\n";
1344 
1345         if (m_config->write (key, value))
1346             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1347     }
1348 }
1349 
1350 void
socket_get_config_vector_string(int)1351 SocketFrontEnd::socket_get_config_vector_string (int /*client_id*/)
1352 {
1353     if (m_config.null ()) return;
1354 
1355     String key;
1356 
1357     SCIM_DEBUG_FRONTEND (2) << " socket_get_config_vector_string.\n";
1358 
1359     if (m_receive_trans.get_data (key)) {
1360         std::vector <String> vec;
1361 
1362         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1363 
1364         if (m_config->read (key, &vec)) {
1365             m_send_trans.put_data (vec);
1366             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1367         }
1368     }
1369 }
1370 
1371 void
socket_set_config_vector_string(int)1372 SocketFrontEnd::socket_set_config_vector_string (int /*client_id*/)
1373 {
1374     if (m_config_readonly || m_config.null ())
1375         return;
1376 
1377     String key;
1378     std::vector<String> vec;
1379 
1380     SCIM_DEBUG_FRONTEND (2) << " socket_set_config_vector_string.\n";
1381 
1382     if (m_receive_trans.get_data (key) &&
1383         m_receive_trans.get_data (vec)) {
1384 
1385         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1386 
1387         if (m_config->write (key, vec))
1388             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1389     }
1390 }
1391 
1392 void
socket_get_config_vector_int(int)1393 SocketFrontEnd::socket_get_config_vector_int (int /*client_id*/)
1394 {
1395     if (m_config.null ()) return;
1396 
1397     String key;
1398 
1399     SCIM_DEBUG_FRONTEND (2) << " socket_get_config_vector_int.\n";
1400 
1401     if (m_receive_trans.get_data (key)) {
1402         std::vector <int> vec;
1403 
1404         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1405 
1406         if (m_config->read (key, &vec)) {
1407             std::vector <uint32> reply;
1408 
1409             for (uint32 i=0; i<vec.size (); ++i)
1410                 reply.push_back ((uint32) vec[i]);
1411 
1412             m_send_trans.put_data (reply);
1413             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1414         }
1415     }
1416 }
1417 
1418 void
socket_set_config_vector_int(int)1419 SocketFrontEnd::socket_set_config_vector_int (int /*client_id*/)
1420 {
1421     if (m_config_readonly || m_config.null ())
1422         return;
1423 
1424     String key;
1425     std::vector<uint32> vec;
1426 
1427     SCIM_DEBUG_FRONTEND (2) << " socket_set_config_vector_int.\n";
1428 
1429     if (m_receive_trans.get_data (key) &&
1430         m_receive_trans.get_data (vec)) {
1431         std::vector<int> req;
1432 
1433         SCIM_DEBUG_FRONTEND (3) << "  Key (" << key << ").\n";
1434 
1435         for (uint32 i=0; i<vec.size (); ++i)
1436             req.push_back ((int) vec[i]);
1437 
1438         if (m_config->write (key, req))
1439             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1440     }
1441 }
1442 
1443 void
socket_load_file(int)1444 SocketFrontEnd::socket_load_file (int /*client_id*/)
1445 {
1446     String filename;
1447     char *bufptr = 0;
1448     size_t filesize = 0;
1449 
1450     SCIM_DEBUG_FRONTEND (2) << " socket_load_file.\n";
1451 
1452     if (m_receive_trans.get_data (filename)) {
1453         SCIM_DEBUG_FRONTEND (3) << "  File (" << filename << ").\n";
1454 
1455         if ((filesize = scim_load_file (filename, &bufptr)) > 0) {
1456             m_send_trans.put_data (bufptr, filesize);
1457             m_send_trans.put_command (SCIM_TRANS_CMD_OK);
1458         }
1459 
1460         delete [] bufptr;
1461     }
1462 }
1463 
1464 void
reload_config_callback(const ConfigPointer & config)1465 SocketFrontEnd::reload_config_callback (const ConfigPointer &config)
1466 {
1467     SCIM_DEBUG_FRONTEND (1) << "Reload configuration.\n";
1468 
1469     int max_clients = -1;
1470 
1471     m_config_readonly = config->read (String (SCIM_CONFIG_FRONTEND_SOCKET_CONFIG_READONLY), false);
1472     max_clients = config->read (String (SCIM_CONFIG_FRONTEND_SOCKET_MAXCLIENTS), -1);
1473 
1474     m_socket_server.set_max_clients (max_clients);
1475 }
1476 
1477 /*
1478 vi:ts=4:nowrap:expandtab
1479 */
1480