1 /* # skkinput (Simple Kana-Kanji Input)
2  * skkmain.c ---
3  * This file is part of skkinput.
4  * Copyright (C) 1997
5  * Takashi SAKAMOTO (sakamoto@yajima.kuis.kyoto-u.ac.jp)
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with skkinput; see the file COPYING.  If not, write to
19  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <setjmp.h>
24 #include <signal.h>
25 #include <sys/types.h>
26 #include <X11/Xlib.h>
27 #include <X11/Xatom.h>
28 #include <X11/IntrinsicP.h>
29 #include <X11/StringDefs.h>
30 #include <X11/Shell.h>
31 #include <X11/ShellP.h>
32 
33 #include "skkmain.h"
34 #include "skkproto.h"
35 #include "SkkInput.h"
36 #include "config.h"
37 #include "version.h"
38 
39 /*
40  * main �������Ѥ����ѿ��η������
41  */
42 struct skkinputOptionDef {
43   char *chara ;
44   int  function_no ;
45   int  need_argument ;
46 } ;
47 
48 /*
49  * �ᥤ��������Ѥ�����������
50  */
51 enum {
52   OPTION_HOST = 0, OPTION_PORT, OPTION_USERDIC, OPTION_BAKDIC,
53   OPTION_SKKDIC, OPTION_SKKREC, OPTION_HELP, OPTION_VERSION,
54   OPTION_CONFIG,
55 } ;
56 
57 
58 /*
59  * �ץ�ȥ����������
60  */
61 /* skkmain.c local */
62 static int skkinput_GlobalsInitialize( Widget parent ) ;
63 static void skkinput_StopConversion
64 ( Widget w, XEvent *xevent, String *params, Cardinal *num_params ) ;
65 static void skkinput_SelectionClear
66 ( Widget w, XEvent *xevent, String *params, Cardinal *num_params ) ;
67 static void skkinput_SelectionRequest
68 ( Widget w, XEvent *xevent, String *params, Cardinal *num_params ) ;
69 static void skkinput_Quit( void ) ;
70 static void skkinput_CheckEvent( XEvent *xevent ) ;
71 static int skkinput_usage( void ) ;
72 static int skkinput_checkOptions( int argc, char *argv[] ) ;
73 static void skkinput_redraw_allskkinputs( void ) ;
74 
75 /* skksvect.c */
76 extern void initVectorHashTable( void ) ;
77 /* skkkip.c */
78 extern int KIP_initialize( XtAppContext app_context, Widget gw ) ;
79 #if 0
80 /* skkximp.c */
81 extern int XIMP_initialize( XtAppContext app_context, Widget gw ) ;
82 #endif
83 /* skksoc.c */
84 int skkinput_StartCommunication( char *server_name, int port_num ) ;
85 int skkinput_CloseCommunication( void ) ;
86 /* skkldic.c */
87 int set_localjisyo
88 ( char *jisyo_path, char *jisyobak_path, char *record_path,
89   char *skklocaljisyo ) ;
90 int close_localjisyo( void ) ;
91 void skkinput_updateLocalJisyo( void ) ;
92 /* skkldrec.c */
93 void initHenkanKakuteiHashTable( void ) ;
94 void clearHenkanKakuteiHash( void ) ;
95 /* skkconfig.c */
96 int skkinput_readConfigFile( char *config_file ) ;
97 void initSkkinputDousaketteiVariables( void ) ;
98 
99 /*
100  * �����Х��ѿ��������
101  */
102 /* X Tool Kit ������ ���ץꥱ���������ƥ����ȡ�*/
103 static XtAppContext app_context ;
104 #if 0
105 static XContext xcontext ;
106 #endif
107 
108 /* X Tool Kit �������ɬ�פȤ��Ƥ���� Option �����ꡣ*/
109 static XrmOptionDescRec options[] = {
110   { "-fk",	"*kanjiFont",	XrmoptionSepArg,	NULL },
111   { "-fr",	"*font",	XrmoptionSepArg,	NULL },
112   { "-rv",	"*reverseVideo",XrmoptionNoArg,		"TRUE" },
113   { "+rv",	"*reverseVideo",XrmoptionNoArg,		"FALSE" },
114   { "-fg",	"*foreground",	XrmoptionSepArg,	NULL },
115   { "-bg",	"*background",	XrmoptionSepArg,	NULL },
116   { "-bd",	"*borderColor",	XrmoptionSepArg,	NULL },
117   { "-geometry","*Geometry",	XrmoptionSepArg,	NULL },
118   { "-ccsk",	"*compatibleCloseSkkinputKey", XrmoptionNoArg, "TRUE" },
119   { "+ccsk",	"*compatibleCloseSkkinputKey", XrmoptionNoArg, "FALSE" },
120 };
121 
122 /* SkkInput �� TOPLEVEL �Ǽ����Ȥ�ɬ�פΤ��� XEVENT */
123 /* ����ϥץ�ȥ������ Widget ���������٤��� �Ĥޤ�,kip �ѤȤ� xim �ѤȤ�*/
124 static XtActionsRec toplevelActions[] = {
125   { "stopConversion",	skkinput_StopConversion },
126   { "selectionClear",	skkinput_SelectionClear },
127   { "selectionRequest",	skkinput_SelectionRequest },
128 } ;
129 
130 static char defaultToplevelTranslations[] =
131 "<SelClr>:	selectionClear()\n\
132  <SelReq>:	selectionRequest()\n" ;
133 
134 /* WM_PROTOCOL ������뤿���ɬ�פ� ATOM */
135 Atom wm_delete_window ;
136 /* skkinput ����λ�������ɬ�פʽ�����Ԥ���������Ѥ��� longjmp �δĶ���*/
137 static jmp_buf skkinputQuitEnv ;
138 
139 /* ����¾��skkinput ��ɬ�פȤ����skkInputWidget ��ˤ�ɬ�פȤ��ʤ�����*/
140 char *skkserv_host ;
141 int  skkserv_portnum ;
142 char *skkinput_local_jisyo_name ;
143 char *skkinput_backup_jisyo_name ;
144 char *skk_local_jisyo_name ;
145 char *skkinput_record_name ;
146 int  skk_egg_like_newline ;
147 int  skkinput_chatadaptermode ;
148 int  skkinput_search_skk_jisyo ;
149 int  skkinput_keep_record ;
150 int  skkinput_date_ad ;
151 int  skkinput_number_style ;
152 int  skkinput_delete_implies_kakutei ;
153 int  skkinput_use_numeric_conversion ;
154 static char *skkinput_config_name ;
155 
156 int skkinput_jisyo_dirty ;
157 int skkinput_prev_jisyo_dirty ;
158 
159 /*
160  * �ᥤ��ؿ���
161  *-------
162  * �����Υ����å����Ǥ⤦�����ˤ��䤫�ˤʤ�Ĥ�ꡣ
163  */
main(int argc,char * argv[])164 int main( int argc, char *argv[] )
165 {
166   Display *display ;
167   XtTranslations trans ;
168   Widget toplevel ;
169   Arg arg[ 20 ] ;
170   Cardinal i ;
171 
172   /* skkinput ��ư����ѿ����������Ƥ�����*/
173   initSkkinputDousaketteiVariables() ;
174   /* ����Ϥޤä���Ǥ��롣*/
175   skkinput_jisyo_dirty = skkinput_prev_jisyo_dirty = False ;
176   /* �Ѵ��κݤ��Ѥ���ϥå���ơ��֥���������Ƥ�����*/
177   initVectorHashTable() ;
178   /* ����κݤ��Ѥ���ϥå���ơ��֥���������Ƥ�����*/
179   initHenkanKakuteiHashTable() ;
180 
181   /* �ޤ���Tool Kit �ν�������롣*/
182   toplevel = XtAppInitialize
183     ( &app_context, "Skkinput", options, XtNumber(options), &argc, argv,
184       NULL, arg, ( Cardinal ) 0);
185 
186   /* �������ĤäƤ����顢���������å����롣�� ToolKit �ǤϻȤ�ʤ� *
187    * ���������뤫�顣*/
188   skkinput_config_name = DEFAULT_CONFIGFILE ;
189   if( argc > 1 ){
190     /* ��˥��ץ�����������ơ�����ե�����Υѥ��˽������ʤ� *
191      * ��Ĵ�٤롣*/
192     if( !skkinput_checkOptions( argc, argv ) ){
193       /* ���Ѥ��Ƥ����������Ʋ������롣*/
194       XtDestroyApplicationContext
195 	( XtWidgetToApplicationContext( toplevel ) ) ;
196       return 1 ;
197     }
198   }
199   /* config file ���ɤ�Ǥ�餦��*/
200   skkinput_readConfigFile( skkinput_config_name ) ;
201 
202   /* ���ץ��������꤬��ͥ��ˤʤ�褦�ˡ������������ֺǸ���ɤࡣ*/
203   /* ��� prescan �ˤ�äơ������Ǥΰ��������å��ǥ��顼���֤뤳�� *
204    * �Ϥʤ���*/
205   skkinput_checkOptions( argc, argv ) ;
206 
207   /* socket ��������Ƥ�����*/
208   skkinput_StartCommunication( skkserv_host, skkserv_portnum ) ;
209   /* �ɽ꼭��ξ��������Ƥ�����*/
210   set_localjisyo
211     ( skkinput_local_jisyo_name, skkinput_backup_jisyo_name,
212       skkinput_record_name, skk_local_jisyo_name ) ;
213 
214 #if 0
215   xcontext = XUniqueContext() ;
216 #endif
217   /* �������륤�٥�ȤȤ��ν����ؿ����롣*/
218   XtAppAddActions( app_context, toplevelActions,
219 		   XtNumber( toplevelActions ) ) ;
220 
221   trans = XtParseTranslationTable( defaultToplevelTranslations ) ;
222   XtOverrideTranslations( toplevel, trans ) ;
223 
224   /* �������Ϥ��Ȥ��褦�ˤ��롣*/
225   i = 0 ;
226   XtSetArg( arg[ i ], XtNinput,  True ) ;
227   i ++ ;
228   XtSetArg( arg[ i ], XtNwidth,  10 ) ;
229   i ++ ;
230   XtSetArg( arg[ i ], XtNheight, 10 ) ;
231   i ++ ;
232 #if 0
233   XtSetArg( arg[ i ], XtNtranslations, trans ) ;
234   i ++ ;
235 #endif
236   XtSetArg( arg[ i ], XtNmappedWhenManaged, False ) ;
237   i ++ ;
238   XtSetValues( toplevel, arg, i ) ;
239 
240   /* �����Х��ѿ��ν������*/
241   skkinput_GlobalsInitialize( toplevel ) ;
242 
243   /* Widget ����ޤ���������������Ǥϼ��ΤϤʤ��Τǡ������Ǽ��Τ� *
244    * ���ΤǤ���*/
245   XtRealizeWidget( toplevel ) ;
246 
247   display = XtDisplay( toplevel ) ;
248 
249   /* Window Manager �� delete message ���������褦�� atom ���롣*/
250   wm_delete_window = XInternAtom( XtDisplay( toplevel ),
251 				  "WM_DELETE_WINDOW", False ) ;
252 
253   /* Kinput Protocol ���Ѥ��뤿��ν������Ԥ���*/
254   KIP_initialize( app_context, toplevel ) ;
255 #if 0
256   /* XIM Protocol ���Ѥ��뤿��ν������Ԥ���*/
257   XIMP_initialize( app_context, toplevel ) ;
258 #endif
259 
260   signal( SIGINT,  ( void * )skkinput_Quit ) ;
261   signal( SIGQUIT, ( void * )skkinput_Quit ) ;
262   signal( SIGTERM, ( void * )skkinput_Quit ) ;
263   signal( SIGPIPE, ( void * )skkinput_Quit ) ;
264 
265   if( !setjmp( skkinputQuitEnv ) ){
266     XEvent xevent ;
267     /* XtAppMainLoop( app_context ) ; */
268     while( 1 ){
269       XtAppNextEvent( app_context, &xevent ) ;
270       skkinput_CheckEvent( &xevent ) ;
271       XFlush( XtDisplay( toplevel ) ) ;
272     }
273   }
274   signal( SIGINT,  SIG_IGN ) ;
275   signal( SIGQUIT, SIG_IGN ) ;
276   signal( SIGTERM, SIG_IGN ) ;
277   signal( SIGPIPE, SIG_IGN ) ;
278 
279   /* ���Ѥ��Ƥ����������Ʋ������롣*/
280   XtDestroyApplicationContext
281     ( XtWidgetToApplicationContext( toplevel ) ) ;
282   /* skkserv �Ȥ� communication ���Ĥ��롣*/
283   skkinput_CloseCommunication() ;
284   /* �������ʤ��ä���� */
285   if( skkinput_jisyo_dirty ){
286     fprintf( stderr, "Saving Jisyo..." ) ;
287     /* ���ߤޤǤ˳����Ѵ����Ƥ�����������֤��롣*/
288     skkinput_updateLocalJisyo() ;
289     fprintf( stderr, "done\n" ) ;
290   }
291   /* malloc ���Ƥ�������β�����*/
292   close_localjisyo() ;
293   /* �ϥå�����ꥢ���롣*/
294   clearHenkanKakuteiHash() ;
295   return 0 ;
296 }
297 
298 /*
299  * ������ˡ�����ؿ���
300  */
skkinput_usage(void)301 static int skkinput_usage( void )
302 {
303   char **ptr ;
304   char *syntaxtable[] = {
305     "-\\?           or -help",		  "show this help",
306     "-v            or -version",	  "show version",
307     "-h <hostname> or -host <hostname>",  "specifies skkserv host",
308     "-p <port_num> or -port <port_num>",  "specifies port number",
309     "-uj <jisyo>   or -userjisyo <jisyo>","specifies skkinput-local-jisyo",
310     "-bj <jisyo>   or -backjisyo <jisyo>","specifies skkinput-local-jisyo\'s backup",
311     "-sj <jisyo>   or -skkjisyo <jisyo>", "specifies skk-local-jisyo",
312     "-rc <jisyo>   or -record <record>",  "specifies skkinput-record",
313     "-fk <kanji fontname>",		  "specifies kanji font",
314     "-fr <fontname>",			  "specifies normal text font",
315     "-fg <color>",			  "specifies foreground color",
316     "-bg <color>",			  "specifies background color",
317     "-bd <color>",			  "specifies border color",
318     "-geometry <height>x<width>",         "specifies skkinput window geometry",
319     "-/+rv",				  "reverse video mode on/off",
320     "-/+ccsk",			"<shift>+<space> close skkinput on/off",
321     NULL, NULL,
322   } ;
323   ptr = syntaxtable ;
324   while( *ptr != NULL ){
325     fprintf( stderr, "%-35s ", *ptr ++ ) ;
326     fprintf( stderr, "%s\n", *ptr ++ ) ;
327   }
328   return 0 ;
329 }
330 
331 /*
332  * ���ץ����Υ����å�����ؿ���
333  */
skkinput_checkOptions(int argc,char * argv[])334 static int skkinput_checkOptions( int argc, char *argv[] )
335 {
336   int i, j ;
337   struct skkinputOptionDef local_options[] = {
338     { "-h",		OPTION_HOST,	True },
339     { "-host",		OPTION_HOST,	True },
340     { "-p",		OPTION_PORT,	True },
341     { "-port",		OPTION_PORT,	True },
342     { "-uj",		OPTION_USERDIC,	True },
343     { "-userjisyo",	OPTION_USERDIC,	True },
344     { "-bj",		OPTION_BAKDIC,	True },
345     { "-backjisyo",	OPTION_BAKDIC,	True },
346     { "-sj",		OPTION_SKKDIC,	True },
347     { "-skkjisyo",	OPTION_SKKDIC,	True },
348     { "-rc",		OPTION_SKKREC,	True },
349     { "-record",	OPTION_SKKREC,	True },
350     { "-config",	OPTION_CONFIG,	True },
351     { "-cnf",		OPTION_CONFIG,	True },
352     { "-?",		OPTION_HELP,	False },
353     { "-help",		OPTION_HELP,	False },
354     { "-v",		OPTION_VERSION,	False },
355     { "-version",	OPTION_VERSION,	False },
356     { NULL,             0,              False },
357   } ;
358   for( i = 1 ; i < argc ; i ++ ){
359     /* �ɤ�˰��פ��뤫�������롣*/
360     for( j = 0 ; local_options[ j ].chara != NULL ; j ++ ){
361       if( !strcmp( argv[ i ], local_options[ j ].chara ) )
362 	break ;
363     }
364 #if 0
365     printf( "option : %d\n", j ) ;
366 #endif
367     /* �ɤ�ˤ���פ��ʤ��ä���硣*/
368     if( local_options[ j ].chara == NULL ){
369       fprintf( stderr, "Unknown argument: \"%s\" exists.\n", argv[ i ] ) ;
370       goto checkoption_errorreturn ;
371     }
372     /* ���˰�����ɬ�פȤ��Ƥ���Τ��� */
373     if( local_options[ j ].need_argument ){
374       i ++ ;
375       if( i >= argc ){
376 	fprintf( stderr, "Lack of argument: \"%s\".\n", argv[ i - 1 ] ) ;
377 	goto checkoption_errorreturn ;
378       }
379     }
380 #if 0
381     printf( "option accept: %d\n", j ) ;
382 #endif
383     /* ���ץ������ν�����*/
384     switch( local_options[ j ].function_no ){
385       /* skkserv �ε����Ƥ���ۥ���̾�����ꤹ�롣*/
386     case OPTION_HOST :
387 #if 0
388       printf( "option host : %s\n", argv[ i ] ) ;
389 #endif
390       skkserv_host = argv[ i ] ;
391       break ;
392       /* skkserv ���̿���������Ѥ���ݡ����ֹ�����ꤹ�롣*/
393     case OPTION_PORT :
394       skkserv_portnum = atoi( argv[ i ] ) ;
395       break ;
396       /* �ɽ꼭���̾�������ꤹ�롣*/
397     case OPTION_USERDIC :
398       skkinput_local_jisyo_name = argv[ i ] ;
399       break ;
400     case OPTION_BAKDIC :
401       skkinput_backup_jisyo_name = argv[ i ] ;
402       break ;
403       /* �إ�פ�ɽ�����롣*/
404     case OPTION_SKKREC :
405       skkinput_record_name = argv[ i ] ;
406       break ;
407       /* ����ե�����ν�ߤ���ꤹ�롣*/
408     case OPTION_CONFIG :
409       skkinput_config_name = argv[ i ] ;
410       break ;
411     case OPTION_HELP :
412       goto checkoption_errorreturn ;
413       /* �С�������ɽ�����롣*/
414     case OPTION_VERSION :
415       fprintf( stderr, "skkinput version %s\n\n", skkinput_version ) ;
416       fprintf( stderr, "This is free software. Skkinput can be copied only under the terms of\nthe GNU General Public license. There is NO warranty; not even for \nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" ) ;
417       return False ;
418     default :
419       goto checkoption_errorreturn ;
420     }
421   }
422   return True ;
423 
424 checkoption_errorreturn:
425   skkinput_usage() ;
426   return False ;
427 }
428 
429 /*
430  * SKKINPUT �Υ����Х��ѿ��ν������
431  */
skkinput_GlobalsInitialize(Widget parent)432 static int skkinput_GlobalsInitialize( Widget parent )
433 {
434   Arg arg[ 2 ] ;
435   int i ;
436   for( i = 0 ; i < MAX_SKKINPUTS ; i ++ ){
437     skkinputs[ i ].probe        = False ;
438     skkinputs[ i ].req_window   = None ;
439     skkinputs[ i ].focus_window = None ;
440     skkinputs[ i ].chat_adapter = False ;
441     skkinputs[ i ].eggnl        = False ;
442     XtSetArg( arg[ 0 ], XtNinput, True ) ;
443     skkinputs[ i ].popup = XtCreatePopupShell
444       ( "skkinput", transientShellWidgetClass, parent, arg, 1 ) ;
445   }
446   return 0 ;
447 }
448 
449 /*
450  * ����ξ��֤��Ѳ������Ƥ����ܸ���������Ф��ƥ֥��ɥ��㥹�Ȥ����
451  * ����
452  *------
453  * main -> widget �ؤ��̿��ˤϡ�XtSetValues ��Ȥ��Τ��������Ȼפ�����
454  * ��ϡ�
455  */
skkinput_redraw_allskkinputs(void)456 static void skkinput_redraw_allskkinputs( void )
457 {
458   Arg arg[ 2 ] ;
459   int i ;
460   for( i = 0 ; i < MAX_SKKINPUTS ; i ++ ){
461     /* �����Ƥ⤤�ʤ�������Ф���*/
462     if( !skkinputs[ i ].probe )
463       continue ;
464 #if 0
465     if( !XtIsManaged( skkinputs[ i ].skkinp ) )
466       continue ;
467 #endif
468     XtSetArg( arg[ 0 ], XtNjisyoDirty, skkinput_jisyo_dirty ) ;
469     XtSetValues( skkinputs[ i ].skkinp, arg, 1 ) ;
470   }
471   return ;
472 }
473 
skkinput_StopConversion(Widget w,XEvent * xevent,String * params,Cardinal * num_params)474 static void skkinput_StopConversion
475 ( Widget w, XEvent *xevent, String *params, Cardinal *num_params )
476 {
477   int i ;
478   XClientMessageEvent *cev = &( xevent->xclient ) ;
479 
480 #if 0
481   fprintf( stderr, "Stop Conversion\n" ) ;
482   fflush( stderr ) ;
483 #endif
484   /* �ɤΥ��饤����Ȥ��Ф�������줿�׵�ʤΤ���Ĵ�٤��       *
485    * SkkInputWidget �ˤ��Υ�å�������ή�줿�Τʤ��ñ�ʤΤˡġ�*/
486   for( i = 0 ; i < MAX_SKKINPUTS ; i ++ ){
487     /* Probe ���Ƥ��ʤ���Τ�̵�뤹�롣*/
488     if( !skkinputs[ i ].probe )
489       continue ;
490     /* PopUp Window ���Ф��Ƥ���̿������Τǡ��ɤ� PopUp ����Ĵ�٤롣*/
491     if( w == skkinputs[ i ].popup ){
492       if( cev->data.l[ 0 ] != wm_delete_window ){
493 	/* Window Manager �� delete ����Ȥ����׵ᤸ��ʤ��ä��Τ�̵�롣*/
494 	XBell( XtDisplay( w ), 0 ) ;
495       } else {
496 	/* ���� Window Manager ����Υ�å������� SkkInputWidget �� *
497 	 * �����Ф���*/
498 	XtDestroyWidget( skkinputs[ i ].skkinp ) ;
499       }
500       /* �Ȥ⤢�졢Event �ν����ϤǤ����Τǡ�ȴ���롣*/
501       break ;
502     }
503   }
504   return ;
505 }
506 
507 /*
508  * ���ܸ����ϼԤȤ��Ƥ�Ω����äƤ��ޤä����ν�������ؿ���
509  */
skkinput_SelectionClear(Widget w,XEvent * xevent,String * params,Cardinal * num_params)510 static void skkinput_SelectionClear
511 ( Widget w, XEvent *xevent, String *params, Cardinal *num_params )
512 {
513   int i ;
514   /* �����Ƥ����뤬���ä��顢�Ĥ��롣*/
515   for( i = 0 ; i < MAX_SKKINPUTS ; i ++ ){
516     if( skkinputs[ i ].probe ){
517       XtDestroyWidget( skkinputs[ i ].skkinp ) ;
518       skkinputs[ i ].probe   = False ;
519       skkinputs[ i ].reserve = False ;
520     }
521   }
522   fprintf( stderr, "I lost selection owner.\n" ) ;
523   /* �ᥤ��ؿ��ν�λ�����ؤ����֡�*/
524   longjmp( skkinputQuitEnv, 1 ) ;
525 }
526 
527 /*
528  * �ɤ�ʬ����ʤ���������ؿ������ɡĤɤ���顢�Ѥ��׵᤬�褿��Ϥ�
529  * ��Ȥ����������Ƥ���ߤ�������
530  */
skkinput_SelectionRequest(Widget w,XEvent * xevent,String * params,Cardinal * num_params)531 static void skkinput_SelectionRequest
532 ( Widget w, XEvent *xevent, String *params, Cardinal *num_params )
533 {
534   XSelectionRequestEvent *xsrev = &( xevent->xselectionrequest ) ;
535   XEvent reply ;
536 
537   reply.xselection.type      = SelectionNotify ;
538   reply.xselection.requestor = xsrev->requestor ;
539   reply.xselection.selection = xsrev->selection ;
540   reply.xselection.target    = xsrev->target ;
541   reply.xselection.property  = None ;
542   reply.xselection.time      = xsrev->time ;
543 
544   XSendEvent( xsrev->display, xsrev->requestor, False, NoEventMask, &reply ) ;
545 }
546 
547 /*
548  * ���ä��褿���٥�Ȥ�����å�����ؿ���
549  */
skkinput_CheckEvent(XEvent * xevent)550 static void skkinput_CheckEvent( XEvent *xevent )
551 {
552   int i, willBeDestroyed ;
553   Arg arg[ 2 ] ;
554   SKKInputRootNode *rNode ;
555 
556 #if 0
557   fprintf( stderr, "Type(%d), Serial(%ld), Window(%ld)\n",
558 	   xevent->type, xevent->xany.serial, xevent->xany.window ) ;
559 #endif
560 
561   /* �⤷�������˲��׵���ä��ꤷ�Ƥޤ����� */
562   if( xevent->type == DestroyNotify ){
563     /* ��ʬ�Ȥ�����׵�Ԥ��Ф��륤�٥�Ȥ��ä����ν�����*/
564     XDestroyWindowEvent *xdwe = ( XDestroyWindowEvent *)xevent ;
565 
566     rNode = skkinputs ;
567     for( i = 0 ; i < MAX_SKKINPUTS ; i ++, rNode ++ ){
568       /* �����Ƥ��ʤ��ͤ�̵�뤹�롣*/
569       if( !rNode->probe )
570 	continue ;
571       /* ���ơ��ɤ줫�ҥåȤ��ޤ������ʡ� */
572       if( rNode->xevent.xclient.data.l[ 1 ] == xdwe->window ){
573 	rNode->req_window = rNode->focus_window = None ;
574 	/* ���㤢���Ĥ��ޤ��礦��*/
575 	XtDestroyWidget( rNode->skkinp ) ;
576 	return ;
577       }
578     }
579   }
580   XtDispatchEvent( xevent ) ;
581 
582   /* ��Ȥ��ʤ���Фʤ�ʤ����ɤ�����Ĵ�٤롣*/
583   rNode = skkinputs ;
584   for( i = 0 ; i < MAX_SKKINPUTS ; i ++, rNode ++ ){
585     if( !rNode->probe )
586       continue ;
587     XtSetArg( arg[ 0 ], XtNwillBeDestroyed, &willBeDestroyed ) ;
588     XtGetValues( rNode->skkinp, arg, 1 ) ;
589     if( willBeDestroyed ){
590       XtDestroyWidget( rNode->skkinp ) ;
591     }
592   }
593   /* ������ѹ������ä����ˤ����Ƥ�����Ф��ƽ�ľ���׵᤬ɬ *
594    * �פǤ��롣���줬�¹ԤǤ���Τϡ������ᥤ�������*/
595   if( skkinput_jisyo_dirty != skkinput_prev_jisyo_dirty ){
596     skkinput_redraw_allskkinputs() ;
597     skkinput_prev_jisyo_dirty = skkinput_jisyo_dirty ;
598   }
599   return ;
600 }
601 
602 /*
603  * skkinput ��λ���ν�����Ԥ��ؿ���
604  *-----
605  * �Ȥ��äƤ⡢main �ؿ��ν�λ������ʬ������Ǥ�������Ǥ����ɡ�
606  * ��λ������ˤ� application context ��������ʤ������ܤʤΤǡ���ä�
607  * �ؿ��Ǥ�������� Selection Owner ������Ǥ��ޤ��Τǡ����Τ��Ҥä���
608  * �뤳�ȤϾ��ʤ��Ȼפ��ΤǤ����ɡ�
609  */
skkinput_Quit(void)610 static void skkinput_Quit( void )
611 {
612   int i ;
613   /* �����Ƥ����뤬���ä��顢�Ĥ��롣*/
614   for( i = 0 ; i < MAX_SKKINPUTS ; i ++ ){
615     if( skkinputs[ i ].probe ){
616       XtDestroyWidget( skkinputs[ i ].skkinp ) ;
617       skkinputs[ i ].probe   = False ;
618       skkinputs[ i ].reserve = False ;
619     }
620   }
621   /* �ᥤ��ؿ��ν�λ�����ؤ����֡�*/
622   longjmp( skkinputQuitEnv, 1 ) ;
623 }
624 
625 #define CS96	0x100	/* 96chars CS */
626 #define MBCS	0x200	/* Multibyte CS */
627 
628 /* convJWStoCT -- Japanese Wide Character String -> COMPOUND_TEXT */
convJWStoCT(char * str,unsigned char * xstr,int jisroman)629 int convJWStoCT( char *str, unsigned char *xstr, int jisroman )
630 {
631   int	g0, g1 ;
632   int	n ;
633   int	g0cs ;
634 
635   g0cs = jisroman ? 'J' : 'B';
636   g0 = 'B' ;
637   g1 = CS96|'A' ;
638 
639   /*
640    * G0, G1 �ϼ��Τ褦�˻Ȥ�ʬ����
641    *  G0: ASCII / JIS-ROMAN
642    *  G1: ���� / ����
643    */
644 #ifdef DEBUG
645   fprintf( stderr, "CONV : " ) ;
646 #endif
647   n = 0 ;
648   while( *str != '\0' ){
649 #ifdef DEBUG
650     fprintf( stderr, "( %d )->", n ) ;
651 #endif
652     if( ( *str ) & 0x80 ){
653       /* ���� */
654       if( g1 != ( MBCS|'B' ) ){
655 	if( xstr != NULL ){
656 	  *xstr++ = 0x1b ;
657 	  *xstr++ = 0x24 ;
658 	  *xstr++ = ')';
659 	  *xstr++ = 0x42 ;
660 	}
661 	n += 4 ;
662 	g1 = MBCS|'B' ;
663       }
664       if( xstr != NULL ){
665 	*xstr++ = ( *str ++ ) & 0xff ;
666 	*xstr++ = *( str ++ ) & 0xff ;
667 	n += 2 ;
668 	continue ;
669       }
670       str ++ ;
671       str ++ ;
672       n += 2 ;
673       continue ;
674     } else {
675       /* ASCII or C0 */
676       if( *str < ' '){
677 	/* C0 */
678 	if( *str == '\t' || *str == '\n') {
679 	  if ( xstr != NULL ){
680 	    *xstr++ = *str ;
681 	  }
682 	  n++ ;
683 	}
684 	str ++ ;
685 	continue ;
686       }
687       if( g0 != g0cs ){
688 	if( xstr != NULL ){
689 	  *xstr++ = 0x1b ;
690 	  *xstr++ = '(' ;
691 	  *xstr++ = g0cs ;
692 	}
693 	n += 3 ;
694 	g0 = g0cs ;
695       }
696       if ( xstr != NULL ){
697 	*xstr++ = ( *str ) & 0x7f ;
698       }
699       str ++ ;
700       n++ ;
701       continue ;
702     }
703   }
704   if ( xstr != NULL )
705     *xstr = '\0' ;
706 #ifdef DEBUG
707   fprintf( stderr, "\n" ) ;
708 #endif
709   return n ;
710 }
711