1 /* # skkinput (Simple Kana-Kanji Input)
2  *
3  * This file is part of skkinput.
4  * Copyright (C) 2002
5  * Takashi SAKAMOTO (PXG01715@nifty.ne.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 "AfxWin.h"
22 #include <stdio.h>
23 #include <locale.h>
24 #include <signal.h>
25 #include "skkinput.h"
26 #include "dispatch.h"
27 #if defined (SUPPORT_KINPUT)
28 #include "KinputServer.h"
29 #endif
30 #if defined (SUPPORT_XIM)
31 #include "XIMServer.h"
32 #endif
33 #include "kanji.h"
34 
35 /*========================================================================*
36  *	�ץ�ȥ����������
37  *========================================================================*/
38 static	Boolean	skkinputApp_initApplication		(int*, char*[]) ;
39 static	Boolean	skkinputApp_exitApplication		(void) ;
40 static	Boolean	skkinputApp_initInstance		(void) ;
41 static	Boolean	skkinputApp_exitInstance		(void) ;
42 static	Boolean	skkinputApp_mainLoop			(void) ;
43 static	Boolean	skkinputApp_initLispMgr			(void) ;
44 static	int		skkinputApp_getExitFlag			(void) ;
45 static	void	skkinputApp_onProtocolDestroy	(Widget, XtPointer, XtPointer) ;
46 static	int		skkinputApp_onXIoError			(Display*) ;
47 static	void	skkinputApp_onSignal			(int) ;
48 static	void	skkinputApp_showUsage			(int*, char*[]) ;
49 #if defined (DEBUG_CONSOLE)
50 static	void	skkinputApp_testModeMainLoop	(void) ;
51 #endif
52 
53 /*========================================================================*
54  *	�����Х��ѿ���
55  *========================================================================*/
56 static SkkinputApp	theApp ;
57 
58 #if !defined (XtNlispMachine)
59 #define	XtNlispMachine			"lispMachine"
60 #endif
61 
62 typedef struct {
63 #if defined (SUPPORT_KINPUT)
64 	Boolean		m_fUseKinputProtocol ;
65 #endif
66 #if defined (SUPPORT_XIM)
67 	Boolean		m_fUseXIMProtocol ;
68 #endif
69 	String		m_strServerHost ;
70 	int			m_nPortNum ;
71 	String		m_strConfigPath ;
72 #if defined (DEBUG_CONSOLE)
73 	Boolean		m_fTestMode ;
74 #endif
75 }	SkkinputAppResRec ;
76 
77 static SkkinputAppResRec	theAppRes ;
78 
79 #define	offset(field)	XtOffsetOf(SkkinputAppResRec,field)
80 
81 static XtResource		rresSkkinputApp []	= {
82 #if defined (SUPPORT_KINPUT)
83 	{ "useKinputProtocol",	"UseKinputProtocol",	XtRBoolean,
84 	  sizeof (Boolean),		offset (m_fUseKinputProtocol),
85 	  XtRImmediate,			(XtPointer) True, },
86 #endif
87 #if defined (SUPPORT_XIM)
88 	{ "useXIMProtocol",		"UseXIMProtocol",		XtRBoolean,
89 	  sizeof (Boolean),		offset (m_fUseXIMProtocol),
90 	  XtRImmediate,			(XtPointer) True, },
91 #endif
92 	{ "serverHost",			"SkkserverHost",		XtRString,
93 	  sizeof (String),		offset (m_strServerHost),
94 	  XtRImmediate,			(XtPointer)"", },
95 	{ "portnum",			"Portnum",				XtRInt,
96 	  sizeof (int),			offset (m_nPortNum),
97 	  XtRImmediate,			(XtPointer)-1, },
98 	{ "configPath",			"ConfigPath",			XtRString,
99 	  sizeof (String),		offset (m_strConfigPath),
100 	  XtRImmediate,			(XtPointer) ELISP_DIR, },
101 #if defined (DEBUG_CONSOLE)
102 	{ "testMode",			"TestMode",				XtRBoolean,
103 	  sizeof (Boolean),		offset (m_fTestMode),
104 	  XtRImmediate,			(XtPointer) False, },
105 #endif
106 } ;
107 
108 #undef	offset
109 
110 static XrmOptionDescRec	roptDescSkkinputApp [] = {
111 #if defined (SUPPORT_KINPUT)
112 	{ "-kinput",	".useKinputProtocol",	XrmoptionNoArg,		"True", },
113 	{ "+kinput",	".useKinputProtocol",	XrmoptionNoArg,		"False", },
114 #endif
115 #if defined (SUPPORT_XIM)
116 	{ "-xim",		".useXIMProtocol",		XrmoptionNoArg,		"True", },
117 	{ "+xim",		".useXIMProtocol",		XrmoptionNoArg,		"False", },
118 #endif
119 	{ "-server",	".serverHost",			XrmoptionSepArg,	NULL, },
120 	{ "-portnum",	".portnum",				XrmoptionSepArg,	NULL, },
121 	{ "-config",	".configPath",			XrmoptionSepArg,	NULL, },
122 	{ "-fontset",	"*fontSet",				XrmoptionSepArg,	NULL, },
123 	{ "-rv",		"*reverseVideo",		XrmoptionNoArg,		"True", },
124 	{ "+rv",		"*reverseVideo",		XrmoptionNoArg,		"False", },
125 	{ "-fg",		"*foreground",			XrmoptionSepArg,	NULL, },
126 	{ "-bg",		"*background",			XrmoptionSepArg,	NULL, },
127 	{ "-bd",		"*borderColor",			XrmoptionSepArg,	NULL, },
128 #if defined (DEBUG_CONSOLE)
129 	{ "-test",		".testMode",			XrmoptionNoArg,		"True", },
130 	{ "+test",		".testMode",			XrmoptionNoArg,		"False", },
131 #endif
132 } ;
133 
134 int
main(int iArgc,char * rpArgv[])135 main (int iArgc, char* rpArgv [])
136 {
137 	register void	(*pOrgSigHandler)(int) ;
138 
139 	setlocale (LC_ALL, "japanese") ;
140 
141 	if (! skkinputApp_initApplication (&iArgc, rpArgv))
142 		return	EXIT_FAILURE ;
143 
144 #if defined (DEBUG_CONSOLE)
145 	if (theAppRes.m_fTestMode) {
146 		skkinputApp_testModeMainLoop () ;
147 	} else {
148 #endif
149 		pOrgSigHandler		= signal (SIGHUP, SIG_IGN) ;
150 		theApp.m_pLispMgr	= NULL ;
151 		do {
152 			theApp.m_fContinue	= False ;
153 			theApp.m_fExitFlag	= False ;
154 
155 			if (! skkinputApp_initInstance ())
156 				return	EXIT_FAILURE ;
157 
158 			(void) signal (SIGHUP,  skkinputApp_onSignal) ;
159 			(void) signal (SIGINT,  skkinputApp_onSignal) ;
160 			(void) signal (SIGQUIT, skkinputApp_onSignal) ;
161 			if (theApp.m_nProtocol > 0)
162 				skkinputApp_mainLoop () ;
163 			(void) signal (SIGHUP,  SIG_IGN) ;
164 			(void) signal (SIGINT,  SIG_IGN) ;
165 			(void) signal (SIGQUIT, SIG_IGN) ;
166 			skkinputApp_exitInstance () ;
167 		}	while (theApp.m_fContinue) ;
168 
169 		(void) signal (SIGHUP, pOrgSigHandler) ;
170 #if defined (DEBUG_CONSOLE)
171 	}
172 #endif
173 	skkinputApp_exitApplication () ;
174 
175 	return	EXIT_SUCCESS ; ;
176 }
177 
178 #if defined (DEBUG)
179 TLispManager*
skkinputApp_GetLispMgr(void)180 skkinputApp_GetLispMgr (void)
181 {
182 	return	theApp.m_pLispMgr ;
183 }
184 #endif
185 
186 /*========================================================================*
187  *	������ؿ���
188  *========================================================================*/
189 Boolean
skkinputApp_initApplication(register int * pnArgc,register char * pArgv[])190 skkinputApp_initApplication (
191 	register int*	pnArgc,
192 	register char*	pArgv [])
193 {
194 	/*register TEditorClient*	pClient ;*/
195 	register Widget		wgToplevel ;
196 	Arg					rArg [8] ;
197 	register int		nArg, nArgc ;
198 
199 	wgToplevel	= XtAppInitialize (&theApp.m_appContext, "Skkinput", roptDescSkkinputApp, XtNumber (roptDescSkkinputApp), pnArgc, pArgv, NULL, NULL, (Cardinal) 0) ;
200 	nArgc	= *pnArgc ;
201 	if (nArgc > 1) {
202 		skkinputApp_showUsage (pnArgc, pArgv) ;
203 		return	False ;
204 	}
205 	if (wgToplevel == NULL)
206 		return	False ;
207 
208 	nArg	= 0 ;
209 	XtSetArg (rArg [nArg], XtNmappedWhenManaged,	False) ;	nArg ++ ;
210 	XtSetArg (rArg [nArg], XtNwidth,				1) ;	nArg ++ ;
211 	XtSetArg (rArg [nArg], XtNheight,				1) ;	nArg ++ ;
212 	XtSetValues (wgToplevel, rArg, nArg) ;
213 
214 	XtGetApplicationResources (wgToplevel, &theAppRes, rresSkkinputApp, XtNumber (rresSkkinputApp), NULL, 0) ;
215 	AfxWinInitialize (wgToplevel) ;
216 	XtRealizeWidget (wgToplevel) ;
217 	theApp.m_wgToplevel	= wgToplevel ;
218 	return	True ;
219 }
220 
221 Boolean
skkinputApp_initInstance(void)222 skkinputApp_initInstance (void)
223 {
224 	/*register TEditorClient*	pClient ;*/
225 	register Widget		wgToplevel ;
226 #if defined (SUPPORT_KINPUT)
227 	register Widget		wgKinputProtocol ;
228 #endif
229 #if defined (SUPPORT_XIM)
230 	register Widget		wgXIMProtocol ;
231 #endif
232 	Arg					rArg [8] ;
233 	register int		nArg ;
234 
235 	theApp.m_nProtocol	= 0 ;
236 	wgToplevel	= theApp.m_wgToplevel ;
237 
238 	/*	lisp manager �ν������*/
239 	if (TFAILED (skkinputApp_initLispMgr ()))
240 		return	False ;
241 
242 	nArg		= 0 ;
243 	XtSetArg (rArg [nArg], XtNlispMachine,			theApp.m_pLM) ;	nArg ++ ;
244 
245 #if defined (SUPPORT_KINPUT)
246     /* Kinput Protocol ���Ѥ��뤿��ν������Ԥ���*/
247 	if (theAppRes.m_fUseKinputProtocol) {
248 		wgKinputProtocol	= XtCreateManagedWidget ("kinput2", kinputServerWidgetClass, wgToplevel, rArg, nArg) ;
249 		if (wgKinputProtocol != NULL) {
250 			XtAddCallback (wgKinputProtocol, XtNdestroyCallback, skkinputApp_onProtocolDestroy, 0) ;
251 			XtRealizeWidget (wgKinputProtocol) ;
252 			theApp.m_nProtocol	++ ;
253 		}
254 	} else {
255 		wgKinputProtocol		= NULL ;
256 	}
257 	theApp.m_wgKinputProtocol	= wgKinputProtocol ;
258 #endif
259 #if defined (SUPPORT_XIM)
260 	/*	XIMProtocol ¦�ν�����*/
261 	if (theAppRes.m_fUseXIMProtocol) {
262 		wgXIMProtocol		= XtCreateManagedWidget ("xim", ximServerWidgetClass, wgToplevel, rArg, nArg) ;
263 		if (wgXIMProtocol != NULL) {
264 			XtAddCallback (wgXIMProtocol, XtNdestroyCallback, skkinputApp_onProtocolDestroy, 0) ;
265 			XtRealizeWidget (wgXIMProtocol) ;
266 			theApp.m_nProtocol	++ ;
267 		}
268 	} else {
269 		wgXIMProtocol		= NULL ;
270 	}
271 	theApp.m_wgXIMProtocol		= wgXIMProtocol ;
272 #endif
273 	if (theApp.m_nProtocol <= 0) {
274 		fprintf (stderr, "No protocol server is available.\n") ;
275 		return	False ;
276 	}
277 	return	True ;
278 }
279 
280 Boolean
skkinputApp_exitInstance(void)281 skkinputApp_exitInstance (void)
282 {
283 #if defined (SUPPORT_KINPUT)
284 	if (theApp.m_wgKinputProtocol != NULL) {
285 		XtDestroyWidget (theApp.m_wgKinputProtocol) ;
286 		theApp.m_wgKinputProtocol	= NULL ;
287 	}
288 #endif
289 #if defined (SUPPORT_XIM)
290 	if (theApp.m_wgXIMProtocol != NULL) {
291 		XtDestroyWidget (theApp.m_wgXIMProtocol) ;
292 		theApp.m_wgXIMProtocol	= NULL ;
293 	}
294 #endif
295 	theApp.m_nProtocol	= 0 ;
296 	TLispClient_ClassFinalize (theApp.m_pLM) ;
297 	theApp.m_pLM		= NULL ;
298 	return	True ;
299 }
300 
301 Boolean
skkinputApp_exitApplication(void)302 skkinputApp_exitApplication (void)
303 {
304 	register Display*	pDisplay ;
305 
306 	pDisplay			= XtDisplay (theApp.m_wgToplevel) ;
307 	XtDestroyWidget (theApp.m_wgToplevel) ;
308     XtDestroyApplicationContext (theApp.m_appContext) ;
309 	return	True ;
310 }
311 
312 Boolean
skkinputApp_mainLoop(void)313 skkinputApp_mainLoop (void)
314 {
315 	register int	(*pOrgHandler)(Display*, XErrorEvent*) ;
316 	register int	(*pOrgIOHandler)(Display*) ;
317 
318 #if defined (DEBUG)
319 	fprintf (stderr, "skkinputApp_mainLoop(): enter\n") ;
320 #endif
321 	pOrgHandler		= XSetErrorHandler   (AfxHandleXError) ;
322 	pOrgIOHandler	= XSetIOErrorHandler (skkinputApp_onXIoError) ;
323 	TLispClient_MainLoop (theApp.m_appContext, theApp.m_pLM, &skkinputApp_getExitFlag) ;
324 	(void) XSetIOErrorHandler (pOrgIOHandler) ;
325 	(void) XSetErrorHandler (pOrgHandler) ;
326 #if defined (DEBUG)
327 	fprintf (stderr, "skkinputApp_mainLoop(): leave\n") ;
328 #endif
329 	return	True ;
330 }
331 
332 Boolean
skkinputApp_initLispMgr(void)333 skkinputApp_initLispMgr (void)
334 {
335 	register Boolean		fCreate	;
336 	register const char*	strConfigPath ;
337 	register const char*	strServerHost ;
338 	register int			nPortNum ;
339 
340 	fCreate			= (theApp.m_pLispMgr == NULL) ;
341 	strConfigPath	= theAppRes.m_strConfigPath ;
342 	strServerHost	= theAppRes.m_strServerHost ;
343 	nPortNum		= theAppRes.m_nPortNum ;
344 	if (TFAILED (TLispClient_ClassInitialize (&theApp.m_pLispMgr, &theApp.m_pLM, strConfigPath, strServerHost, nPortNum, fCreate))) {
345 		fprintf (stderr, "skkinput: failed: initialize lisp manager.\n") ;
346 		return	False ;
347 	}
348 	return	True ;
349 }
350 
351 int
skkinputApp_getExitFlag(void)352 skkinputApp_getExitFlag (void)
353 {
354 	return	theApp.m_fExitFlag ;
355 }
356 
357 void
skkinputApp_onSignal(register int nSignal)358 skkinputApp_onSignal (
359 	register int		nSignal)
360 {
361 	register Display*	pDisplay ;
362 	XEvent				xev ;
363 
364 #if defined (DEBUG)
365 	fprintf (stderr, "Catch SIGHUP (%d)\n", nSignal) ;
366 #endif
367 	theApp.m_fContinue			= (nSignal == SIGHUP)? True : False ;
368 	theApp.m_fExitFlag			= True ;
369 
370 	pDisplay					= XtDisplay (theApp.m_wgToplevel) ;
371 	memset (&xev, 0, sizeof (xev)) ;
372 	xev.xclient.type			= ClientMessage ;
373 	xev.xclient.serial			= 0UL ;
374 	xev.xclient.window			= XtWindow (theApp.m_wgToplevel) ;
375 	xev.xclient.display			= pDisplay ;
376 	xev.xclient.message_type	= None ;
377 	xev.xclient.format			= 8 ;
378 	XSendEvent (pDisplay, XtWindow (theApp.m_wgToplevel), True, NoEventMask, &xev) ;
379 	XFlush (pDisplay) ;
380 	return ;
381 }
382 
383 void
skkinputApp_onProtocolDestroy(register Widget gw,register XtPointer closure,register XtPointer call_data)384 skkinputApp_onProtocolDestroy (
385 	register Widget		gw,
386 	register XtPointer	closure,
387 	register XtPointer	call_data)
388 {
389 #if defined (SUPPORT_KINPUT)
390 	if (gw == theApp.m_wgKinputProtocol) {
391 		theApp.m_nProtocol	-- ;
392 		theApp.m_wgKinputProtocol	= NULL ;
393 	}
394 #endif
395 #if defined (SUPPORT_XIM)
396 	if (gw == theApp.m_wgXIMProtocol) {
397 		theApp.m_nProtocol	-- ;
398 		theApp.m_wgXIMProtocol		= NULL ;
399 	}
400 #endif
401 #if defined (DEBUG)
402 	fprintf (stderr, "theApp.m_nProtocol = %d\n", theApp.m_nProtocol) ;
403 #endif
404 	if (theApp.m_nProtocol <= 0)
405 		theApp.m_fExitFlag	= True ;
406 	return ;
407 }
408 
409 /*	X IO Error �Υϥ�ɥ顣
410  */
411 int
skkinputApp_onXIoError(register Display * pDisplay)412 skkinputApp_onXIoError (
413 	register Display*	pDisplay)
414 {
415 #if defined (DEBUG)
416 	fprintf (stderr, "skkinputApp_onXIoError (%p)\n", pDisplay) ;
417 #endif
418 	if (theApp.m_pLispMgr != NULL &&
419 		theApp.m_pLM != NULL) {
420 		TLispClient_ClassFinalize (theApp.m_pLM) ;
421 	}
422 	exit (0) ;
423 }
424 
425 void
skkinputApp_showUsage(register int * pnArgc,register char * pArgv[])426 skkinputApp_showUsage (
427 	register int*		pnArgc,
428 	register char*		pArgv [])
429 {
430 	register int	i, nArgc ;
431 
432 	nArgc	= *pnArgc ;
433 	for (i = 1 ; i < nArgc ; i ++) {
434 		if (strcmp (pArgv [i], "-v") && strcmp (pArgv [i], "-version"))
435 			fprintf (stderr, "Unknown option: %s\n", pArgv [i]) ;
436 	}
437 	fprintf (stderr, "skkinput version 3.0.6\n") ;
438 	fprintf (stderr, "[usage]\n") ;
439 	fprintf (stderr, " -v, -version:  show version\n") ;
440 #if defined (SUPPORT_KINPUT)
441 	fprintf (stderr, " -/+kinput:     enable/disable kinput protocol server\n") ;
442 #endif
443 #if defined (SUPPORT_XIM)
444 	fprintf (stderr, " -/+xim:        enable/disable XIM protocol server\n") ;
445 #endif
446 	fprintf (stderr, " -server:       specify skk-server-host\n") ;
447 	fprintf (stderr, " -portnum:      specify skk-portnum\n") ;
448 	fprintf (stderr, " -config:       specify load-path (default:%s)\n", ELISP_DIR) ;
449 	fprintf (stderr, " -fontset:      specify default fontset\n") ;
450 	fprintf (stderr, " -fg:           specify default foreground pixel\n") ;
451 	fprintf (stderr, " -bg:           specify default background pixel\n") ;
452 	fprintf (stderr, " -bd:           specify default border pixel\n") ;
453 	fprintf (stderr, " -/+rv:         enable/disable reverse video\n") ;
454 	return ;
455 }
456 
457 #if defined (DEBUG_CONSOLE)
458 void
skkinputApp_testModeMainLoop(void)459 skkinputApp_testModeMainLoop (void)
460 {
461 	register TLispManager*	pLispMgr ;
462 	register TLispMachine*	pLM ;
463 	TLispEntity*			pEntBuffer ;
464 	register TLispEntity*	pEntity ;
465 	char	rbuf [256] ;
466 	register int			nLength ;
467 
468 	/*	lisp manager �ν������*/
469 	if (TFAILED (TLispMgr_Create (&theApp.m_pLispMgr)))
470 		return ;
471 	pLispMgr	= theApp.m_pLispMgr ;
472 	if (TFAILED (TLispMachine_Create (pLispMgr, NULL, &theApp.m_pLM)))
473 		return ;
474 	pLM			= theApp.m_pLM ;
475 	lispMgr_CreateBuffer (pLispMgr, &pEntBuffer) ;
476 	lispMachine_InsertBuffer (pLM, pEntBuffer) ;
477 	lispMachineCode_SetCurrentBuffer (pLM, pEntBuffer) ;
478 
479 	while (! feof (stdin)) {
480 		printf ("> ") ;
481 		fflush (stdout) ;
482 		if (fgets (rbuf, NELEMENTS (rbuf), stdin) == NULL)
483 			break ;
484 		nLength	= strlen (rbuf) ;
485 		if (nLength > 0) {
486 			while (nLength > 0 && (rbuf [nLength - 1] == '\n' || rbuf [nLength - 1] == '\r'))
487 				nLength	-- ;
488 			rbuf [nLength]	= '\0' ;
489 		}
490 		if (nLength <= 0)
491 			continue ;
492 
493 		pEntity	= lispMgr_ParseStringA (pLispMgr, rbuf, nLength, NULL) ;
494 		if (pEntity != NULL)
495 			TLispMachine_Test (pLM, pEntity) ;
496 		fflush (stderr) ;
497 		lispMgr_CollectGarbage (pLispMgr) ;
498 		lispMgr_CollectGarbage (pLispMgr) ;
499 		lispMgr_CollectGarbage (pLispMgr) ;
500 		lispMgr_CollectGarbage (pLispMgr) ;
501 	}
502 	return ;
503 }
504 #endif
505 
506