1 #if UNIX
2 #include <sys/types.h>
3 #include <sys/wait.h>
4 #include <sys/socket.h>
5 #include <sys/un.h>
6 #include <netinet/in.h>
7 #include <arpa/inet.h>
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <signal.h>
11 #include <errno.h>
12 #ifndef _XSERVER64
13 #define _XSERVER64
14 #endif
15 #else
16 #include <windows.h>
17 #include <winsock.h>
18 #endif
19 #include "os-dep.h"
20 #include "gcin.h"
21 #include "gcin-protocol.h"
22 #include "gcin-im-client.h"
23 #define DBG 0
24 static int flags_backup;
25 
26 #if UNIX
27 Atom get_gcin_sockpath_atom(Display *dpy);
save_old_sigaction_single(int signo,struct sigaction * act)28 static void save_old_sigaction_single(int signo, struct sigaction *act)
29 {
30   sigaction(signo, NULL, act);
31 
32   if (act->sa_handler != SIG_IGN) {
33     signal(signo, SIG_IGN);
34   }
35 }
36 
restore_old_sigaction_single(int signo,struct sigaction * act)37 static void restore_old_sigaction_single(int signo, struct sigaction *act)
38 {
39   if (act->sa_handler != SIG_IGN)
40     signal(signo, act->sa_handler);
41 }
42 char *get_gcin_im_srv_sock_path();
43 Atom get_gcin_addr_atom(Display *dpy);
44 #endif
45 
46 
47 
48 #if UNIX
find_gcin_window(Display * dpy)49 Window find_gcin_window(Display *dpy)
50 {
51   Atom gcin_addr_atom = get_gcin_addr_atom(dpy);
52   if (!gcin_addr_atom)
53     return FALSE;
54   return XGetSelectionOwner(dpy, gcin_addr_atom);
55 }
56 #else
find_gcin_window()57 HWND find_gcin_window()
58 {
59   return FindWindowA(GCIN_WIN_NAME, NULL);
60 }
61 #endif
62 
63 
64 #if WIN32
65 #include <share.h>
66 #include <io.h>
67 #include <strsafe.h>
68 
69 bool sys_end_session;
70 static HWND serverWnd;
71 
start_gcin()72 static bool start_gcin()
73 {
74   int retried=0;
75 restart:
76   serverWnd = find_gcin_window();
77   if (!serverWnd) {
78     if (retried < 10) {
79 	  if (!retried)
80         win32exec("gcin.exe");
81 
82       Sleep(2000);
83 	  retried++;
84       goto restart;
85 	} else {
86       dbg("exec not found ?\n");
87 	}
88 
89 	  MessageBoxA(NULL, "cannnot start gcin.exe", NULL, MB_OK);
90 	  return false;
91   }
92 
93   dbg("serverwnd %x\n", serverWnd);
94   return true;
95 }
96 
97 
98 #if SHARED_MEMORY
99 
open_shm_client()100 GCIN_SHM open_shm_client()
101 {
102   if (!start_gcin())
103 	 return NULL;
104   int port = SendMessageA(serverWnd, GCIN_PORT_MESSAGE, GetCurrentProcessId(), 0);
105 
106   return gcin_open_shm(serverWnd, port);
107 }
108 
109 #else
err_strw(DWORD dw)110 static WCHAR *err_strw(DWORD dw)
111 {
112 	static WCHAR msgstr[128];
113     LPVOID lpMsgBuf;
114 
115     FormatMessageW(
116         FORMAT_MESSAGE_ALLOCATE_BUFFER |
117         FORMAT_MESSAGE_FROM_SYSTEM |
118         FORMAT_MESSAGE_IGNORE_INSERTS,
119         NULL,
120         dw,
121         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
122         (LPWSTR) &lpMsgBuf,
123         0, NULL );
124 
125     // Display the error message and exit the process
126 
127     StringCchPrintfW(msgstr, ARRAYSIZE(msgstr), L"%d: %s", dw, lpMsgBuf);
128 	return msgstr;
129 }
130 
131 
sys_err_strw()132 static WCHAR *sys_err_strw()
133 {
134 	return err_strw(GetLastError());
135 }
136 
open_pipe_client()137 HANDLE open_pipe_client()
138 {
139   if (!start_gcin())
140 	 return NULL;
141   int port = SendMessageA(serverWnd, GCIN_PORT_MESSAGE, 0, 0);
142 
143   dbg("port %d\n", port);
144 
145   char pipe_path[64];
146   sprintf(pipe_path, GCIN_PIPE_PATH, port);
147   dbg("pipe_path %s\n", pipe_path);
148 
149   HANDLE hPipe;
150 
151   int i;
152   for(i=0;i<20;i++)
153    {
154       hPipe = CreateFileA(
155          pipe_path,   // pipe name
156          GENERIC_READ |  // read and write access
157          GENERIC_WRITE,
158          0,              // no sharing
159          NULL,           // default security attributes
160          OPEN_EXISTING,  // opens existing pipe
161          0,              // default attributes
162          NULL);          // no template file
163 
164    // Break if the pipe handle is valid.
165 
166       if (hPipe != INVALID_HANDLE_VALUE) {
167 		 dbg("connection established %x\n", hPipe);
168          return hPipe;
169 	  }
170 
171       // Exit if an error other than ERROR_PIPE_BUSY occurs.
172 	  static bool opened = false;
173       if (GetLastError() != ERROR_PIPE_BUSY) {
174 		 if (!opened) {
175 			opened = true;
176 			MessageBoxW(NULL, sys_err_strw(), L"Could not open gcin pipe", MB_OK|MB_ICONERROR);
177 		 }
178          return NULL;
179       }
180 
181       // All pipe instances are busy, so wait for 20 seconds.
182 
183       if (!WaitNamedPipeA(pipe_path, 2000)) {
184          printf("Could not open pipe: 20 second wait timed out.");
185          return NULL;
186       }
187    }
188 
189    MessageBoxA(NULL, "cannot connect to gcin.exe", NULL, MB_OK);
190 
191   return NULL;
192 }
193 
194 
195 #endif
196 
197 #endif
198 #if UNIX
199 int is_special_user;
200 #endif
201 
202 #if SHARED_MEMORY
203 GCIN_SHM gcin_open_shared_mem(int port);
204 #endif
205 
gcin_im_client_reopen(GCIN_client_handle * gcin_ch,Display * dpy)206 static GCIN_client_handle *gcin_im_client_reopen(GCIN_client_handle *gcin_ch, Display *dpy)
207 {
208 #if WIN32
209   char current_exec[80];
210   if (GetModuleFileNameA(NULL, current_exec, sizeof(current_exec))) {
211 	  if (strstr(current_exec, "\\gcin.exe"))
212 		  return NULL;
213   }
214   int retried;
215 #endif
216 
217 //  dbg("gcin_im_client_reopen\n");
218   int dbg_msg = getenv("GCIN_CONNECT_MSG_ON") != NULL;
219 #if UNIX
220   int sockfd=0;
221   int servlen;
222   char *addr;
223   Server_IP_port srv_ip_port;
224   u_char *pp;
225 
226   int uid = getuid();
227   if (uid > 0 && uid < 500) {
228     is_special_user = TRUE;
229   }
230 #else
231 #if SHARED_MEMORY
232   GCIN_SHM sockfd;
233 #else
234   HANDLE sockfd;
235 #endif
236 #endif
237 
238   int tcp = FALSE;
239   GCIN_client_handle *handle;
240   int rstatus;
241 
242 //  dbg("gcin_im_client_reopen\n");
243 #if UNIX
244   if (!dpy) {
245     dbg("null disp %d\n", gcin_ch->fd);
246     goto next;
247   }
248 
249   Atom gcin_addr_atom = get_gcin_addr_atom(dpy);
250   Window gcin_win = None;
251 
252 
253 #define MAX_TRY 3
254   int loop;
255 
256   if (!is_special_user)
257   for(loop=0; loop < MAX_TRY; loop++) {
258     if ((gcin_win=find_gcin_window(dpy))!=None || getenv("GCIN_IM_CLIENT_NO_AUTO_EXEC"))
259       break;
260     static time_t exec_time;
261 
262     if (time(NULL) - exec_time > 1 /* && count < 5 */) {
263       time(&exec_time);
264       dbg("XGetSelectionOwner: old version of gcin or gcin is not running ??\n");
265       static char execbin[]=GCIN_BIN_DIR"/gcin";
266       dbg("... try to start a new gcin server %s\n", execbin);
267 
268       int pid;
269 
270       if ((pid=fork())==0) {
271         putenv("GCIN_DAEMON=");
272         execl(execbin, "gcin", NULL);
273       } else {
274         int status;
275         // gcin will daemon()
276         waitpid(pid, &status, 0);
277       }
278     }
279   }
280 
281   if (loop == MAX_TRY || gcin_win == None) {
282     goto next;
283   }
284 
285   Atom actual_type;
286   int actual_format;
287   u_long nitems,bytes_after;
288   char *message_sock = NULL;
289   Atom gcin_sockpath_atom = get_gcin_sockpath_atom(dpy);
290 
291 //  printf("gcin_sockpath_atom %d\n", gcin_sockpath_atom);
292 
293   if (!gcin_sockpath_atom || XGetWindowProperty(dpy, gcin_win, gcin_sockpath_atom, 0, 64,
294      False, AnyPropertyType, &actual_type, &actual_format,
295      &nitems,&bytes_after,(u_char **)&message_sock) != Success) {
296 #if DBG || 1
297     dbg("XGetWindowProperty 2: old version of gcin or gcin is not running ??\n");
298 #endif
299     goto next;
300   }
301 
302   Server_sock_path srv_sock_path;
303   srv_sock_path.sock_path[0] = 0;
304   if (message_sock) {
305     memcpy(&srv_sock_path, message_sock, sizeof(srv_sock_path));
306     XFree(message_sock);
307   } else
308     goto next;
309 
310   struct sockaddr_un serv_addr;
311   bzero((char *) &serv_addr,sizeof(serv_addr));
312   serv_addr.sun_family = AF_UNIX;
313   char sock_path[128];
314 
315   if (srv_sock_path.sock_path[0]) {
316     strcpy(sock_path, srv_sock_path.sock_path);
317   }
318   else {
319     get_gcin_im_srv_sock_path(sock_path, sizeof(sock_path));
320   }
321 
322   addr = sock_path;
323   strcpy(serv_addr.sun_path, sock_path);
324 #ifdef SUN_LEN
325   servlen = SUN_LEN(&serv_addr);
326 #else
327   servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family);
328 #endif
329 
330   if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
331     perror("cannot open socket");
332     goto tcp;
333   }
334 
335   if (connect(sockfd, (struct sockaddr *)&serv_addr, servlen) < 0) {
336     close(sockfd);
337     sockfd = 0;
338     goto tcp;
339   }
340 
341   if (dbg_msg)
342     dbg("connected to unix socket addr %s\n", sock_path);
343   goto next;
344 
345   char *message;
346 
347 tcp:
348   message = NULL;
349 
350   if (!gcin_addr_atom || XGetWindowProperty(dpy, gcin_win, gcin_addr_atom, 0, 64,
351      False, AnyPropertyType, &actual_type, &actual_format,
352      &nitems,&bytes_after,(u_char **)&message) != Success) {
353 #if DBG || 1
354     dbg("XGetWindowProperty: old version of gcin or gcin is not running ??\n");
355 #endif
356     goto next;
357   }
358 
359   if (message) {
360     memcpy(&srv_ip_port, message, sizeof(srv_ip_port));
361     XFree(message);
362   } else
363     goto next;
364 
365 
366 //  dbg("im server tcp port %d\n", ntohs(srv_ip_port.port));
367 
368   struct sockaddr_in in_serv_addr;
369   bzero((char *) &in_serv_addr, sizeof(in_serv_addr));
370 
371   in_serv_addr.sin_family = AF_INET;
372   in_serv_addr.sin_addr.s_addr = srv_ip_port.ip;
373   in_serv_addr.sin_port = srv_ip_port.port;
374   servlen = sizeof(in_serv_addr);
375 
376 
377   if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
378       perror("cannot open socket");
379       goto next;
380   }
381 
382   dbg("sock %d\n", sockfd);
383 
384   if (connect(sockfd, (struct sockaddr *)&in_serv_addr, servlen) < 0) {
385     dbg("gcin_im_client_open cannot open: ") ;
386     perror("");
387     close(sockfd);
388     sockfd = 0;
389     goto next;
390   }
391 
392   pp = (u_char *)&srv_ip_port.ip;
393   if (dbg_msg)
394     dbg("gcin client connected to server %d.%d.%d.%d:%d\n",
395         pp[0], pp[1], pp[2], pp[3], ntohs(srv_ip_port.port));
396 #else
397 #if SHARED_MEMORY
398 	sockfd = open_shm_client();
399 #else
400 	sockfd = open_pipe_client();
401 #endif
402 #endif // UNIX
403 
404   tcp = TRUE;
405 
406 next:
407   if (!gcin_ch)
408     handle = tzmalloc(GCIN_client_handle, 1);
409   else {
410     handle = gcin_ch;
411   }
412 
413   if (sockfd < 0)
414     sockfd = 0;
415 
416   if (sockfd > 0) {
417     handle->fd = sockfd;
418 #if UNIX
419     if (tcp) {
420       if (!handle->passwd)
421         handle->passwd = malloc(sizeof(GCIN_PASSWD));
422       memcpy(handle->passwd, &srv_ip_port.passwd, sizeof(srv_ip_port.passwd));
423     } else {
424       if (handle->passwd) {
425         free(handle->passwd); handle->passwd = NULL;
426       }
427     }
428 #else
429 #if !SHARED_MEMORY
430 	DWORD rn;
431 	ReadFile(sockfd, &handle->server_idx, sizeof(int), &rn, NULL);
432 //	dbg("server_idx %d\n", handle->server_idx);
433 #endif
434 #endif
435   }
436 
437   if (handle->fd)  {
438     if (BITON(handle->flag, FLAG_GCIN_client_handle_has_focus))
439       gcin_im_client_focus_in(handle);
440 
441     gcin_im_client_set_flags(handle, flags_backup, &rstatus);
442   }
443 
444   return handle;
445 }
446 
447 
validate_handle(GCIN_client_handle * gcin_ch)448 static void validate_handle(GCIN_client_handle *gcin_ch)
449 {
450   if (gcin_ch->fd > 0)
451     return;
452 #if UNIX
453   if (is_special_user)
454     return;
455 #endif
456 
457   gcin_im_client_reopen(gcin_ch, gcin_ch->disp);
458 }
459 
460 
gcin_im_client_open(Display * disp)461 GCIN_client_handle *gcin_im_client_open(Display *disp)
462 {
463 //  dbg("gcin_im_client_open\n");
464   GCIN_client_handle *handle = gcin_im_client_reopen(NULL,  disp);
465   handle->disp = disp;
466   return handle;
467 }
468 
gcin_im_client_close(GCIN_client_handle * handle)469 void gcin_im_client_close(GCIN_client_handle *handle)
470 {
471   if (!handle)
472     return;
473 
474   if (handle->fd > 0)
475 #if WIN32
476 #if SHARED_MEMORY
477 	SendMessageA(serverWnd, GCIN_CLIENT_MESSAGE_CLOSE, handle->fd->port, NULL);
478     gcin_shm_close(handle->fd);
479 #else
480 	CloseHandle((HANDLE)handle->fd);
481 #endif
482 #else
483     close(handle->fd);
484 #endif
485 #if UNIX
486   free(handle->passwd);
487 #endif
488   free(handle);
489 }
490 
491 
send_req_msg(GCIN_client_handle * handle)492 static void send_req_msg(GCIN_client_handle *handle)
493 {
494 #if WIN32
495 #if SHARED_MEMORY
496 	SendMessageA(serverWnd, GCIN_CLIENT_MESSAGE_REQ, handle->fd->port, NULL);
497 #else
498 #if 1
499 	PostMessageA(serverWnd, GCIN_CLIENT_MESSAGE_REQ, handle->server_idx, NULL);
500 #else
501 	SendMessageA(serverWnd, GCIN_CLIENT_MESSAGE_REQ, handle->server_idx, NULL);
502 #endif
503 #endif
504 #endif
505 }
506 
gen_req(GCIN_client_handle * handle,u_int req_no,GCIN_req * req)507 static int gen_req(GCIN_client_handle *handle, u_int req_no, GCIN_req *req)
508 {
509 #if WIN32
510   if (req_no  & (GCIN_req_key_press|GCIN_req_key_release|GCIN_req_test_key_press|GCIN_req_test_key_release)) {
511 //    dbg("gen_req validate\n");
512 	validate_handle(handle);
513   }
514 #else
515   validate_handle(handle);
516 #endif
517 
518   if (!handle->fd)
519     return 0;
520 
521   handle->seq++;
522 
523   bzero(req, sizeof(GCIN_req));
524 
525   req->req_no = req_no;
526   to_gcin_endian_4(&req->req_no);
527 
528   req->client_win = handle->client_win;
529   to_gcin_endian_4(&req->client_win);
530 
531   req->input_style = handle->input_style;
532   to_gcin_endian_4(&req->input_style);
533 
534   req->spot_location.x = handle->spot_location.x;
535   req->spot_location.y = handle->spot_location.y;
536   to_gcin_endian_2(&req->spot_location.x);
537   to_gcin_endian_2(&req->spot_location.y);
538 
539 #if SHARED_MEMORY
540   gcin_start_shm_write(handle->fd);
541 #endif
542   return 1;
543 }
544 
error_proc(GCIN_client_handle * handle,char * msg)545 static void error_proc(GCIN_client_handle *handle, char *msg)
546 {
547   if (!handle->fd)
548     return;
549 
550   perror(msg);
551 #if WIN32
552 #if SHARED_MEMROY
553   gcin_shm_close(handle->fd);
554 #else
555   CloseHandle(handle->fd);
556 #endif
557 #else
558   close(handle->fd);
559 #endif
560   handle->fd = 0;
561 #if WIN32
562   Sleep(100);
563 #else
564   usleep(100000);
565 #endif
566 }
567 
568 
569 #if WIN32
handle_read(GCIN_client_handle * handle,void * ptr,int N)570 static int handle_read(GCIN_client_handle *handle, void *ptr, int N)
571 {
572 #if SHARED_MEMORY
573   gcin_shm_read(handle->fd, ptr, N);
574   return N;
575 #else
576   BOOL r;
577   HANDLE fd = handle->fd;
578 
579   if (!fd)
580     return 0;
581   int trN=0, loop=0;
582   int n = N;
583 
584   while (n > 0 && loop < 10) {
585     DWORD bytes = 0;
586     for(int l=0;l < 1000; l++) {
587        bytes = 0;
588        if (PeekNamedPipe(fd, NULL, 0, NULL, &bytes, NULL)) {
589 //         dbg("bytes %d\n", bytes);
590        } else
591          dbg("PeekNamedPipe failed %s", sys_err_strA());
592 
593        if (bytes > 0)
594          break;
595 
596        Sleep(10);
597      }
598 
599      if (!bytes) {
600 	   dbg("no data\n");
601        return -1;
602 	 }
603 
604 	dbg("bytes %d %d\n", n, bytes);
605 
606 	if (bytes > n)
607 		bytes = n;
608 
609     DWORD rn;
610     r = ReadFile(fd, (char *)ptr, bytes, &rn, 0);
611 
612     if (!r)
613 	  return -1;
614 
615 	n-=rn;
616 	trN+=rn;
617 	ptr = (char *)ptr + rn;
618 	loop++;
619   }
620 
621   if (trN != N) {
622 	dbg("trN != N %d,%d\n", trN, N);
623 	return -1;
624   }
625   return trN;
626 #endif
627 }
628 #else
629 typedef struct {
630   struct sigaction apipe;
631 } SAVE_ACT;
save_old_sigaction(SAVE_ACT * save_act)632 static void save_old_sigaction(SAVE_ACT *save_act)
633 {
634   save_old_sigaction_single(SIGPIPE, &save_act->apipe);
635 }
restore_old_sigaction(SAVE_ACT * save_act)636 static void restore_old_sigaction(SAVE_ACT *save_act)
637 {
638   restore_old_sigaction_single(SIGPIPE, &save_act->apipe);
639 }
handle_read(GCIN_client_handle * handle,void * ptr,int n)640 static int handle_read(GCIN_client_handle *handle, void *ptr, int n)
641 {
642   int fd = handle->fd;
643 
644   if (!fd)
645     return 0;
646 
647   SAVE_ACT save_act;
648   save_old_sigaction(&save_act);
649   int r = read(fd, ptr, n);
650 
651 #if (DBG || 1)
652   if (r < 0)
653     perror("handle_read");
654 #endif
655 
656   restore_old_sigaction(&save_act);
657 
658   if (r<=0)
659     return r;
660   if (handle->passwd)
661     __gcin_enc_mem((u_char *)ptr, n, handle->passwd, &handle->passwd->seed);
662   return r;
663 }
664 #endif
665 
666 
667 #if WIN32
handle_write(GCIN_client_handle * handle,void * ptr,int n)668 static int handle_write(GCIN_client_handle *handle, void *ptr, int n)
669 {
670 #if SHARED_MEMORY
671   gcin_shm_write(handle->fd, ptr, n);
672   return n;
673 #else
674   BOOL r;
675   char *tmp;
676   HANDLE fd = (HANDLE)handle->fd;
677 
678   if (!fd)
679     return 0;
680 
681   tmp = (char *)malloc(n);
682   memcpy(tmp, ptr, n);
683 
684   DWORD wn;
685   r =  WriteFile(fd, tmp, n, &wn, NULL);
686   free(tmp);
687   if (!r)
688 	  return -1;
689   return wn;
690 #endif
691 }
692 #else
handle_write(GCIN_client_handle * handle,void * ptr,int n)693 static int handle_write(GCIN_client_handle *handle, void *ptr, int n)
694 {
695   int fd = handle->fd;
696 
697   if (!fd)
698     return 0;
699 
700   u_char *tmp = malloc(n);
701   memcpy(tmp, ptr, n);
702 
703   if (handle->passwd)
704     __gcin_enc_mem(tmp, n, handle->passwd, &handle->passwd->seed);
705 
706   SAVE_ACT save_act;
707 #if 1
708   save_old_sigaction(&save_act);
709 #endif
710   int r =  write(fd, tmp, n);
711 #if 1
712   restore_old_sigaction(&save_act);
713 #endif
714   free(tmp);
715 
716   return r;
717 }
718 #endif
719 
720 
gcin_im_client_focus_in(GCIN_client_handle * handle)721 void gcin_im_client_focus_in(GCIN_client_handle *handle)
722 {
723   if (!handle)
724     return;
725 #if UNIX
726   if (is_special_user)
727     return;
728 #endif
729 
730   GCIN_req req;
731 //  dbg("gcin_im_client_focus_in\n");
732   handle->flag |= FLAG_GCIN_client_handle_has_focus;
733 
734   if (!gen_req(handle, GCIN_req_focus_in, &req))
735     return;
736 
737   if (handle_write(handle, &req, sizeof(req)) <=0) {
738     error_proc(handle,"gcin_im_client_focus_in error");
739   }
740   send_req_msg(handle);
741 
742   gcin_im_client_set_cursor_location(handle, handle->spot_location.x,
743      handle->spot_location.y);
744 }
745 
746 
gcin_im_client_focus_out(GCIN_client_handle * handle)747 void gcin_im_client_focus_out(GCIN_client_handle *handle)
748 {
749   if (!handle)
750     return;
751 #if UNIX
752   if (is_special_user)
753     return;
754 #endif
755 
756   GCIN_req req;
757 //  dbg("gcin_im_client_focus_out\n");
758   handle->flag &= ~FLAG_GCIN_client_handle_has_focus;
759 
760   if (!gen_req(handle, GCIN_req_focus_out, &req))
761     return;
762 
763   if (handle_write(handle, &req, sizeof(req)) <=0) {
764     error_proc(handle,"gcin_im_client_focus_out error");
765   }
766 
767   send_req_msg(handle);
768 }
769 
770 #if UNIX
gcin_im_client_focus_out2(GCIN_client_handle * handle,char ** rstr)771 void gcin_im_client_focus_out2(GCIN_client_handle *handle, char **rstr)
772 {
773   GCIN_req req;
774   GCIN_reply reply;
775 
776   if (rstr)
777     *rstr = NULL;
778 
779   if (!handle)
780     return;
781 
782 #if UNIX
783   if (is_special_user)
784     return;
785 #endif
786 
787 #if DBG
788   dbg("gcin_im_client_focus_out2\n");
789 #endif
790   handle->flag &= ~FLAG_GCIN_client_handle_has_focus;
791 
792   if (!gen_req(handle, GCIN_req_focus_out2, &req))
793     return;
794 
795   if (handle_write(handle, &req, sizeof(req)) <=0) {
796     error_proc(handle,"gcin_im_client_focus_out error");
797   }
798 
799   bzero(&reply, sizeof(reply));
800   if (handle_read(handle, &reply, sizeof(reply)) <=0) {
801     error_proc(handle, "cannot read reply from gcin server");
802     return;
803   }
804 
805   to_gcin_endian_4(&reply.datalen);
806   to_gcin_endian_4(&reply.flag);
807 
808   if (reply.datalen > 0) {
809     *rstr = (char *)malloc(reply.datalen);
810     if (handle_read(handle, *rstr, reply.datalen) <= 0) {
811       free(*rstr); *rstr = NULL;
812       error_proc(handle, "cannot read reply str from gcin server");
813       return;
814     }
815   }
816 
817 //  dbg("gcin_im_client_forward_key_event %x\n", reply.flag);
818 
819   return;
820 }
821 #endif
822 
gcin_im_client_forward_key_event(GCIN_client_handle * handle,GCIN_req_t event_type,KeySym key,u_int state,char ** rstr)823 static int gcin_im_client_forward_key_event(GCIN_client_handle *handle,
824                                           GCIN_req_t event_type,
825                                           KeySym key, u_int state,
826                                           char **rstr)
827 {
828   GCIN_reply reply;
829   GCIN_req req;
830 
831   *rstr = NULL;
832 #if UNIX
833   if (is_special_user)
834     return 0;
835 #endif
836 
837   if (!gen_req(handle, event_type, &req))
838     return 0;
839 
840   req.keyeve.key = key;
841   to_gcin_endian_4(&req.keyeve.key);
842   req.keyeve.state = state;
843   to_gcin_endian_4(&req.keyeve.state);
844 
845 
846   if (handle_write(handle, &req, sizeof(req)) <= 0) {
847     error_proc(handle, "cannot write to gcin server");
848     return FALSE;
849   }
850   send_req_msg(handle);
851 
852 
853 #if SHARED_MEMORY
854   gcin_start_shm_read(handle->fd);
855 #endif
856   bzero(&reply, sizeof(reply));
857   if (handle_read(handle, &reply, sizeof(reply)) <=0) {
858     error_proc(handle, "cannot read reply from gcin server");
859     return FALSE;
860   }
861 
862   to_gcin_endian_4(&reply.datalen);
863   to_gcin_endian_4(&reply.flag);
864 
865   if (reply.datalen > 0) {
866     *rstr = (char *)malloc(reply.datalen);
867     if (handle_read(handle, *rstr, reply.datalen) <= 0) {
868       free(*rstr); *rstr = NULL;
869       error_proc(handle, "cannot read reply str from gcin server");
870       return FALSE;
871     }
872   }
873 
874 //  dbg("gcin_im_client_forward_key_event %x\n", reply.flag);
875 
876   return reply.flag;
877 }
878 
879 
880 // return TRUE if the key is accepted
gcin_im_client_forward_key_press(GCIN_client_handle * handle,KeySym key,u_int state,char ** rstr)881 int gcin_im_client_forward_key_press(GCIN_client_handle *handle,
882                                           KeySym key, u_int state,
883                                           char **rstr)
884 {
885   int flag;
886   if (!handle)
887     return 0;
888   // in case client didn't send focus in event
889   if (!BITON(handle->flag, FLAG_GCIN_client_handle_has_focus)) {
890     gcin_im_client_focus_in(handle);
891     handle->flag |= FLAG_GCIN_client_handle_has_focus;
892     gcin_im_client_set_cursor_location(handle, handle->spot_location.x,
893        handle->spot_location.y);
894   }
895 
896 //  dbg("gcin_im_client_forward_key_press\n");
897   flag = gcin_im_client_forward_key_event(
898              handle, GCIN_req_key_press, key, state, rstr);
899 
900   return ((flag & GCIN_reply_key_processed) !=0);
901 }
902 
903 
904 // return TRUE if the key is accepted
gcin_im_client_forward_key_release(GCIN_client_handle * handle,KeySym key,u_int state,char ** rstr)905 int gcin_im_client_forward_key_release(GCIN_client_handle *handle,
906                                           KeySym key, u_int state,
907                                           char **rstr)
908 {
909   int flag;
910   if (!handle)
911     return 0;
912   handle->flag |= FLAG_GCIN_client_handle_has_focus;
913 //  dbg("gcin_im_client_forward_key_release\n");
914   flag = gcin_im_client_forward_key_event(
915              handle, GCIN_req_key_release, key, state, rstr);
916   return ((flag & GCIN_reply_key_processed) !=0);
917 }
918 
919 
gcin_im_client_set_cursor_location(GCIN_client_handle * handle,int x,int y)920 void gcin_im_client_set_cursor_location(GCIN_client_handle *handle, int x, int y)
921 {
922   if (!handle)
923     return;
924 #if UNIX
925   if (is_special_user)
926     return;
927 #endif
928 
929 //  dbg("gcin_im_client_set_cursor_location %d   %d,%d\n", handle->flag, x, y);
930 
931   GCIN_req req;
932   handle->spot_location.x = x;
933   handle->spot_location.y = y;
934 
935   if (!BITON(handle->flag, FLAG_GCIN_client_handle_has_focus))
936     return;
937 
938   if (!gen_req(handle, GCIN_req_set_cursor_location, &req))
939     return;
940 
941   if (handle_write(handle, &req, sizeof(req)) <=0) {
942     error_proc(handle,"gcin_im_client_set_cursor_location error");
943   }
944   send_req_msg(handle);
945 }
946 
947 // in win32, if win is NULL, this means gcin_im_client_set_cursor_location(x,y) is screen position
gcin_im_client_set_window(GCIN_client_handle * handle,Window win)948 void gcin_im_client_set_window(GCIN_client_handle *handle, Window win)
949 {
950   if (!handle)
951     return;
952 //  dbg("gcin_im_client_set_window %x\n", win);
953 
954 #if UNIX
955   if (is_special_user)
956     return;
957   if (!win)
958     return;
959 #endif
960   handle->client_win = win;
961 
962 // For chrome
963 //  gcin_im_client_set_cursor_location(handle, handle->spot_location.x, handle->spot_location.y);
964 }
965 
gcin_im_client_set_flags(GCIN_client_handle * handle,int flags,int * ret_flag)966 void gcin_im_client_set_flags(GCIN_client_handle *handle, int flags, int *ret_flag)
967 {
968   GCIN_req req;
969 
970 #if DBG
971   dbg("gcin_im_client_set_flags\n");
972 #endif
973 
974   if (!handle)
975     return;
976 
977 #if UNIX
978   if (is_special_user)
979     return;
980 #endif
981 
982   if (!gen_req(handle, GCIN_req_set_flags, &req))
983     return;
984 
985   req.flag |= flags;
986 
987   flags_backup = req.flag;
988 
989 #if DBG
990   dbg("gcin_im_client_set_flags b\n");
991 #endif
992 
993   if (handle_write(handle, &req, sizeof(req)) <=0) {
994     error_proc(handle,"gcin_im_client_set_flags error");
995   }
996   send_req_msg(handle);
997 
998 #if DBG
999   dbg("gcin_im_client_set_flags c\n");
1000 #endif
1001 
1002 #if SHARED_MEMORY
1003   gcin_start_shm_read(handle->fd);
1004 #endif
1005 
1006   if (handle_read(handle, ret_flag, sizeof(int)) <= 0) {
1007     error_proc(handle, "cannot read reply str from gcin server");
1008   }
1009 }
1010 
1011 
gcin_im_client_clear_flags(GCIN_client_handle * handle,int flags,int * ret_flag)1012 void gcin_im_client_clear_flags(GCIN_client_handle *handle, int flags, int *ret_flag)
1013 {
1014   GCIN_req req;
1015 
1016   if (!handle)
1017     return;
1018 
1019 #if UNIX
1020   if (is_special_user)
1021     return;
1022 #endif
1023 
1024   if (!gen_req(handle, GCIN_req_set_flags, &req))
1025     return;
1026 
1027   req.flag &= ~flags;
1028 
1029   flags_backup = req.flag;
1030 
1031   if (handle_write(handle, &req, sizeof(req)) <=0) {
1032     error_proc(handle,"gcin_im_client_set_flags error");
1033   }
1034   send_req_msg(handle);
1035 
1036 #if SHARED_MEMORY
1037   gcin_start_shm_read(handle->fd);
1038 #endif
1039 
1040   if (handle_read(handle, ret_flag, sizeof(int)) <= 0) {
1041     error_proc(handle, "cannot read reply str from gcin server");
1042   }
1043 }
1044 
1045 
gcin_im_client_get_preedit(GCIN_client_handle * handle,char ** str,GCIN_PREEDIT_ATTR att[],int * cursor,int * sub_comp_len)1046 int gcin_im_client_get_preedit(GCIN_client_handle *handle, char **str, GCIN_PREEDIT_ATTR att[], int *cursor,int *sub_comp_len)
1047 {
1048   *str=NULL;
1049   if (!handle)
1050     return 0;
1051 
1052 #if UNIX
1053   if (is_special_user)
1054     return 0;
1055 #endif
1056 
1057   int attN, tcursor, str_len;
1058 #if DBG
1059   dbg("gcin_im_client_get_preedit\n");
1060 #endif
1061   GCIN_req req;
1062   if (!gen_req(handle, GCIN_req_get_preedit, &req)) {
1063 err_ret:
1064 #if DBG
1065     dbg("aaaaaaaaaaaaa %x\n", str);
1066 #endif
1067     if (cursor)
1068       *cursor=0;
1069     *str=strdup("");
1070     return 0;
1071   }
1072 
1073   if (handle_write(handle, &req, sizeof(req)) <=0) {
1074     error_proc(handle,"gcin_im_client_get_preedit error");
1075     goto err_ret;
1076   }
1077   send_req_msg(handle);
1078 
1079 #if SHARED_MEMORY
1080   gcin_start_shm_read(handle->fd);
1081 #endif
1082 
1083   str_len=-1; // str_len includes \0
1084   if (handle_read(handle, &str_len, sizeof(str_len))<=0)
1085     goto err_ret; // including \0
1086 
1087   *str = (char *)malloc(str_len);
1088 
1089   if (handle_read(handle, *str, str_len)<=0)
1090     goto err_ret;
1091 #if DBG
1092   dbg("gcin_im_client_get_preedit len:%d '%s' \n", str_len, *str);
1093 #endif
1094   attN = -1;
1095   if (handle_read(handle, &attN, sizeof(attN))<=0) {
1096     goto err_ret;
1097   }
1098 
1099   dbg("preedit str:%s attrN:%d\n", *str, attN);
1100 
1101   if (attN>0 && handle_read(handle, att, sizeof(GCIN_PREEDIT_ATTR)*attN)<=0) {
1102     goto err_ret;
1103   }
1104 
1105   tcursor=0;
1106   if (handle_read(handle, &tcursor, sizeof(tcursor))<=0) {
1107     goto err_ret;
1108   }
1109 
1110   if (cursor)
1111     *cursor = tcursor;
1112 
1113 
1114 #if WIN32 || 1
1115   int tsub_comp_len;
1116   tsub_comp_len=0;
1117   if (handle_read(handle, &tsub_comp_len, sizeof(tsub_comp_len))<=0) {
1118     goto err_ret;
1119   }
1120   if (sub_comp_len)
1121 	*sub_comp_len = tsub_comp_len;
1122 #endif
1123 
1124 #if DBG
1125   dbg("jjjjjjjjj %d tcursor:%d\n", attN, tcursor);
1126 #endif
1127   return attN;
1128 }
1129 
1130 
1131 
gcin_im_client_reset(GCIN_client_handle * handle)1132 void gcin_im_client_reset(GCIN_client_handle *handle)
1133 {
1134   if (!handle)
1135     return;
1136 
1137 #if UNIX
1138   if (is_special_user)
1139     return;
1140 #endif
1141 
1142   GCIN_req req;
1143 #if DBG
1144   dbg("gcin_im_client_reset\n");
1145 #endif
1146   if (!gen_req(handle, GCIN_req_reset, &req))
1147     return;
1148 
1149   if (handle_write(handle, &req, sizeof(req)) <=0) {
1150     error_proc(handle,"gcin_im_client_reset error");
1151   }
1152   send_req_msg(handle);
1153 }
1154 
1155 
gcin_im_client_message(GCIN_client_handle * handle,char * message)1156 void gcin_im_client_message(GCIN_client_handle *handle, char *message)
1157 {
1158   GCIN_req req;
1159   short len;
1160 #if DBG
1161   dbg("gcin_im_client_message\n");
1162 #endif
1163   if (!gen_req(handle, GCIN_req_message, &req))
1164     return;
1165 
1166   if (handle_write(handle, &req, sizeof(req)) <=0) {
1167     error_proc(handle,"gcin_im_client_message error 1");
1168   }
1169   send_req_msg(handle);
1170 
1171   len = strlen(message)+1;
1172   if (handle_write(handle, &len, sizeof(len)) <=0) {
1173     error_proc(handle,"gcin_im_client_message error 2");
1174   }
1175 
1176   if (handle_write(handle, message, len) <=0) {
1177     error_proc(handle,"gcin_im_client_message error 2");
1178   }
1179 }
1180 
1181 #if WIN32
gcin_im_client_set_tsin_pho_mode(GCIN_client_handle * handle,int pho_mode)1182 void gcin_im_client_set_tsin_pho_mode(GCIN_client_handle *handle, int pho_mode)
1183 {
1184   dbg("gcin_im_client_set_tsin_pho_mode %d\n", pho_mode);
1185   if (!handle)
1186     return;
1187 
1188   GCIN_req req;
1189 #if DBG
1190   dbg("gcin_im_client_reset\n");
1191 #endif
1192   if (!gen_req(handle, GCIN_req_set_tsin_pho_mode, &req))
1193     return;
1194 
1195   req.flag = pho_mode;
1196 
1197   if (handle_write(handle, &req, sizeof(req)) <=0) {
1198     error_proc(handle,"gcin_im_client_reset error");
1199   }
1200   send_req_msg(handle);
1201 }
1202 #endif
1203 
1204 #if TSF
gcin_im_client_key_eaten(GCIN_client_handle * handle,int press_release,KeySym key,u_int state)1205 bool gcin_im_client_key_eaten(GCIN_client_handle *handle, int press_release,
1206                                           KeySym key, u_int state)
1207 {
1208   GCIN_reply reply;
1209   GCIN_req req;
1210 
1211   if (!gen_req(handle, press_release?GCIN_req_test_key_release:GCIN_req_test_key_press, &req))
1212     return 0;
1213 
1214   req.keyeve.key = key;
1215   to_gcin_endian_4(&req.keyeve.key);
1216   req.keyeve.state = state;
1217   to_gcin_endian_4(&req.keyeve.state);
1218 
1219 
1220   if (handle_write(handle, &req, sizeof(req)) <= 0) {
1221     error_proc(handle, "cannot write to gcin server");
1222     return FALSE;
1223   }
1224   send_req_msg(handle);
1225 
1226   bzero(&reply, sizeof(reply));
1227   if (handle_read(handle, &reply, sizeof(reply)) <=0) {
1228     error_proc(handle, "cannot read reply from gcin server");
1229     return FALSE;
1230   }
1231 
1232   to_gcin_endian_4(&reply.datalen);
1233   to_gcin_endian_4(&reply.flag);
1234 
1235   return (reply.flag & GCIN_reply_key_processed) > 0;
1236 }
1237 #endif
1238