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