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 "local.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <sys/types.h>
26 #include <X11/X.h>
27 #include <X11/Xlib.h>
28 #include <X11/Xatom.h>
29 #include <X11/IntrinsicP.h>
30 #include <X11/StringDefs.h>
31 #include <X11/Shell.h>
32 #include "XIMServerP.h"
33 #include "XIMProtocol.h"
34 #include "lispyevent.h"
35 
36 #define offset(field)  XtOffsetOf(XIMServerRec, ximServer.field)
37 #define goffset(field) XtOffsetOf(WidgetRec, core.field)
38 
39 static XtResource	srXIMServerResources [] = {
40 	{	XtNwidth,		XtCWidth,		XtRDimension,	sizeof (Dimension),
41 		goffset (width),			XtRImmediate,	(XtPointer) 1, },
42 	{	XtNheight,		XtCHeight,		XtRDimension,	sizeof (Dimension),
43 		goffset (height),			XtRImmediate,	(XtPointer) 1, },
44 	{	XtNmappedWhenManaged,	XtCMappedWhenManaged,	XtRBoolean,	sizeof (Boolean),
45 		goffset (mapped_when_managed),	XtRImmediate,	(XtPointer)False, },
46 	{	XtNlispMachine,	XtCLispMachine,	XtRPointer,		sizeof (XtPointer),
47 		offset (m_pLispMachine),	XtRImmediate,	(XtPointer) 0, },
48 	{	XtNsupportedLocales,		XtCSupportedLocales,
49 		XtRString,					sizeof (String),
50 		offset (m_strLocales),		XtRImmediate,
51 		(XtPointer) "ja_JP.SJIS,ja_JP.eucJP,ja_JP.EUC,ja_JP,japanese,japan,ja", },
52 	{	XtNconversionStartKeys,			XtCConversionStartKeys,
53 		XtRString,						sizeof (String),
54 		offset (m_strConvStartKeys),	XtRImmediate,
55 		(XtPointer) "[S-space], [S-kp-space]", },
56 	{	XtNdestroyCallback,			XtCCallback,
57 		XtRCallback,				sizeof (XtCallbackList),
58 		offset (m_lstCbkDestroy),	XtRCallback,		(XtPointer) NULL, },
59 } ;
60 
61 #undef offset
62 #undef goffset
63 
64 static	void		ximServer_onInitialize	(Widget, Widget, ArgList, Cardinal*) ;
65 static	void		ximServer_onRealize		(Widget, XtValueMask*, XSetWindowAttributes*) ;
66 static	Boolean		ximServer_onSetValues	(Widget, Widget, Widget, ArgList, Cardinal*) ;
67 static	void		ximServer_onDestroy		(Widget) ;
68 
69 static	void		ximServer_onClientMessage		(Widget, XEvent*, String*, Cardinal*) ;
70 static	void		ximServer_onSelectionRequest	(Widget, XEvent*, String*, Cardinal*) ;
71 static	void		ximServer_onSelectionClear		(Widget, XEvent*, String*, Cardinal*) ;
72 static	void		ximServer_onClientDestroy		(Widget, XtPointer, XtPointer) ;
73 
74 static	Boolean		ximServer_setServerProfile		(Widget) ;
75 static	Boolean		ximServer_parseConversionStartKey (Widget) ;
76 
77 static	Widget		ximServer_newClient				(Widget, Window) ;
78 static	Widget		ximServer_findClient			(Widget, Window) ;
79 static	void		ximServer_removeClient			(Widget, Widget) ;
80 static	void		ximServer_destroyAllClient		(Widget) ;
81 static	Boolean		ximServer_isValidWindow			(Display*, Window) ;
82 
83 static XtActionsRec		srXIMServerActionsTable [] = {
84 	{	"client-message",				ximServer_onClientMessage, },
85 	{	"selection-request",			ximServer_onSelectionRequest, },
86 	{	"selection-clear",				ximServer_onSelectionClear, },
87 } ;
88 
89 static char	sstrXIMServerTranslations []	=
90 "<Message>:                            client-message()\n\
91  <SelReq>:                             selection-request()\n\
92  <SelClr>:                             selection-clear()" ;
93 
94 XIMServerClassRec	ximServerClassRec = {
95     {	/* core fields 			*/
96 		/* superclass			*/	&widgetClassRec,
97 		/* class_name			*/	"XIMServer",
98 		/* size					*/	sizeof (XIMServerRec),
99 		/* class_initialize		*/	NULL,
100 		/* class_part_initialize*/	NULL,
101 		/* class_inited			*/	FALSE,
102 		/* initialize			*/	ximServer_onInitialize,
103 		/* initialize_hook		*/	NULL,
104 		/* realize				*/	ximServer_onRealize,
105 		/* actions				*/	srXIMServerActionsTable,
106 		/* num_actions			*/	XtNumber (srXIMServerActionsTable),
107 		/* resources			*/	srXIMServerResources,
108 		/* num_resources		*/	XtNumber (srXIMServerResources),
109 		/* xrm_class			*/	NULLQUARK,
110 		/* compress_motion		*/	TRUE,
111 		/* compress_exposure	*/	TRUE,
112 		/* compress_enterleave	*/	TRUE,
113 		/* visible_interest		*/	FALSE,
114 		/* destroy				*/	ximServer_onDestroy,
115 		/* resize				*/	NULL,
116 		/* expose				*/	NULL,
117 		/* set_values			*/	ximServer_onSetValues,
118 		/* set_values_hook		*/	NULL,
119 		/* set_values_almost	*/	XtInheritSetValuesAlmost,
120 		/* get_values_hook		*/	NULL,
121 		/* accept_focus			*/	NULL,
122 		/* version				*/	XtVersion,
123 		/* callback_private		*/	NULL,
124 		/* tm_table				*/	sstrXIMServerTranslations,
125 		/* query_geometry		*/	XtInheritQueryGeometry,
126     }, {
127 		/* dummy				*/	0,
128 	}
129 } ;
130 
131 WidgetClass ximServerWidgetClass = (WidgetClass)&ximServerClassRec ;
132 
133 
134 void
ximServer_onInitialize(register Widget greq,register Widget gnew,register ArgList args,register Cardinal * num_args)135 ximServer_onInitialize (
136 	register Widget		greq,
137 	register Widget		gnew,
138 	register ArgList	args,
139 	register Cardinal*	num_args)
140 {
141 	register XIMServerWidget	wgThis		= (XIMServerWidget) gnew ;
142 	register Display*			pDisplay	= XtDisplay (gnew) ;
143 
144 #if defined (DEBUG)
145 	fprintf (stderr, "ximServer_onInitizlize (%p)\n", wgThis) ;
146 #endif
147 	TVarbuffer_Initialize (&wgThis->ximServer.m_vbufClient, sizeof (Widget)) ;
148 #define MakeAtom(s)	XInternAtom(pDisplay,s,False)
149 	wgThis->ximServer.m_atServer		= MakeAtom ("@server=" XIM_SERVER_NAME) ;
150 	wgThis->ximServer.m_atCompoundText	= MakeAtom ("COMPOUND_TEXT") ;
151 	wgThis->ximServer.m_atLocales		= MakeAtom ("LOCALES") ;
152 	wgThis->ximServer.m_atTransport		= MakeAtom ("TRANSPORT") ;
153 	wgThis->ximServer.m_atXConnect		= MakeAtom ("_XIM_XCONNECT") ;
154 	wgThis->ximServer.m_atSkkComm		= MakeAtom ("_SKKINPUT_COMM") ;
155 #undef MakeAtom
156 	wgThis->ximServer.m_lstHotKeyTrigger	= NULL ;
157 	wgThis->ximServer.m_nHotKeyTrigger		= 0 ;
158 	return ;
159 }
160 
161 void
ximServer_onRealize(register Widget gw,register XtValueMask * pValueMask,register XSetWindowAttributes * pXSWA)162 ximServer_onRealize (
163 	register Widget					gw,
164 	register XtValueMask*			pValueMask,
165 	register XSetWindowAttributes*	pXSWA)
166 {
167 	register Display*			pDisplay	= XtDisplay (gw) ;
168 	register XIMServerWidget	wgThis	= (XIMServerWidget) gw ;
169 	register CoreWidgetClass	super	= (CoreWidgetClass) XtClass (gw)->core_class.superclass ;
170 
171 	(*super->core_class.realize)(gw, pValueMask, pXSWA) ;
172 
173 	XSetSelectionOwner (pDisplay, wgThis->ximServer.m_atServer, XtWindow (gw), CurrentTime) ;
174 	if (XGetSelectionOwner (pDisplay, wgThis->ximServer.m_atServer) != XtWindow (gw)) {
175 #if defined (DEBUG)
176 		fprintf (stderr, "ximServer_onRealize() : failed.\n") ;
177 #endif
178 		XtDestroyWidget (gw) ;
179 		return ;
180 	}
181 	ximServer_setServerProfile (gw) ;
182 	ximServer_parseConversionStartKey (gw) ;
183 #if defined (DEBUG)
184 	fprintf (stderr, "ximServer_onRealize() : done.\n") ;
185 #endif
186 	return ;
187 }
188 
189 Boolean
ximServer_onSetValues(register Widget gwCurrent,register Widget gwRequest,register Widget gwNeww,register ArgList args,register Cardinal * num_args)190 ximServer_onSetValues (
191 	register Widget		gwCurrent,
192 	register Widget		gwRequest,
193 	register Widget		gwNeww,
194 	register ArgList	args,
195 	register Cardinal*	num_args)
196 {
197 	return	False ;
198 }
199 
200 void
ximServer_onDestroy(register Widget gw)201 ximServer_onDestroy (
202 	register Widget		gw)
203 {
204 	register XIMServerWidget	wgThis	= (XIMServerWidget) gw ;
205 
206 #if defined (DEBUG)
207 	fprintf (stderr, "ximServer_onDestroy (%p)\n", gw) ;
208 #endif
209 	XtCallCallbacks (gw, XtNdestroyCallback, 0) ;
210 	ximServer_destroyAllClient (gw) ;
211 
212 	if (wgThis->ximServer.m_lstHotKeyTrigger != NULL) {
213 		FREE (wgThis->ximServer.m_lstHotKeyTrigger) ;
214 		wgThis->ximServer.m_lstHotKeyTrigger	= NULL ;
215 	}
216 	return ;
217 }
218 
219 void
ximServer_onSelectionClear(register Widget gw,register XEvent * pXEvent,register String * params,register Cardinal * num_params)220 ximServer_onSelectionClear (
221 	register Widget		gw,
222 	register XEvent*	pXEvent,
223 	register String*	params,
224 	register Cardinal*	num_params)
225 {
226 	register XIMServerWidget		wgThis	= (XIMServerWidget) gw ;
227 	register XSelectionClearEvent*	pEvent	= &pXEvent->xselectionclear ;
228 
229 #if defined (DEBUG)
230 	fprintf (stderr, "ximServer_onSelectionClear ()\n") ;
231 #endif
232 	if (pEvent->selection != wgThis->ximServer.m_atServer)
233 		return ;
234 
235 	XtDestroyWidget (gw) ;
236 	return ;
237 }
238 
239 void
ximServer_onSelectionRequest(register Widget gw,register XEvent * pXEvent,register String * params,register Cardinal * num_params)240 ximServer_onSelectionRequest (
241 	register Widget		gw,
242 	register XEvent*	pXEvent,
243 	register String*	params,
244 	register Cardinal*	num_params)
245 {
246 	register XIMServerWidget			wgThis		= (XIMServerWidget) gw ;
247 	register XSelectionRequestEvent*	pEvent		= &pXEvent->xselectionrequest ;
248 	register Display*					pDisplay	= XtDisplay (gw) ;
249 	register unsigned char*		pValue ;
250 	register int				iLength ;
251 	register int				iFormat ;
252 	XEvent				xev ;
253 	Atom				atTarget ;
254 	Atom				atTargets [2] ;
255 
256 #if defined (DEBUG)
257 	{
258 		char*	pSelection	= XGetAtomName (pDisplay, pEvent->selection) ;
259 		char*	pAtomName	= XGetAtomName (pDisplay, pEvent->target) ;
260 
261 		fprintf (stderr, "ximServer_onSelectionRequest: ") ;
262 		if (pSelection != NULL) {
263 			fprintf (stderr, "Selection: \"%s\", ", pSelection) ;
264 			XFree (pSelection) ;
265 		}
266 		if (pAtomName != NULL) {
267 			fprintf (stderr, "Target: \"%s\"\n", pAtomName) ;
268 			XFree (pAtomName) ;
269 		}
270 	}
271 #endif
272 	if (pEvent->selection != wgThis->ximServer.m_atServer)
273 		return ;
274 
275 	pValue	= NULL ;
276 	iLength	= 0 ;
277 	if (pEvent->target == XInternAtom (pDisplay, "TARGETS", False)){
278 		atTargets [0]	= wgThis->ximServer.m_atLocales ;
279 		atTargets [1]	= wgThis->ximServer.m_atTransport ;
280 		pValue			= (unsigned char*)&atTargets ;
281 		iLength		= 2 ;
282 		iFormat		= 32 ;
283 		atTarget		= XA_ATOM ;
284 	} else if (pEvent->target == wgThis->ximServer.m_atLocales){
285 		static char*	sstrLocales	= NULL ;
286 		static int		snstrLocales ;
287 
288 		if (sstrLocales == NULL) {
289 			static const char	sstrAtLocal []	= "@locale=" ;
290 			register int	nNeed ;
291 			nNeed		= strlen (wgThis->ximServer.m_strLocales) + NELEMENTS (sstrAtLocal) + 1 ;
292 			sstrLocales	= MALLOC (nNeed + 1) ;
293 			assert (sstrLocales != NULL) ;
294 			strcpy (sstrLocales, sstrAtLocal) ;
295 			strcat (sstrLocales, wgThis->ximServer.m_strLocales) ;
296 			snstrLocales	= strlen (sstrLocales) ;
297 		}
298 		pValue		= sstrLocales ;
299 		iLength		= snstrLocales ;
300 		iFormat		= 8 ;
301 		atTarget	= pEvent->target ;
302 	} else if (pEvent->target == wgThis->ximServer.m_atTransport){
303 		static char	rchTransport []	= "@transport=X/" ;
304 		pValue		= rchTransport ;
305 		iLength		= NELEMENTS (rchTransport) ;
306 		iFormat		= 8 ;
307 		atTarget	= pEvent->target ;
308 	} else {
309 #if defined (DEBUG)
310 		fprintf (stderr, "ximServer_onSelectionRequest: invalid request\n") ;
311 #endif
312 		return ;
313 	}
314 	if (pValue == NULL || iLength <= 0)
315 		return ;
316 
317 	XChangeProperty (pDisplay, pEvent->requestor, pEvent->property, atTarget, iFormat, PropModeReplace, pValue, iLength) ;
318 	xev.xselection.type			= SelectionNotify ;
319 	xev.xselection.selection	= pEvent->selection ;
320 	xev.xselection.target		= atTarget ;
321 	xev.xselection.property		= pEvent->property ;
322 	xev.xselection.requestor	= pEvent->requestor ;
323 	xev.xselection.send_event	= True ;
324 	xev.xselection.time			= CurrentTime ;
325 	xev.xselection.display		= pDisplay ;
326 	XSendEvent (pDisplay, pEvent->requestor, False, 0L, &xev) ;
327 	return ;
328 }
329 
330 void
ximServer_onClientMessage(register Widget gw,register XEvent * pXEvent,register String * params,register Cardinal * num_params)331 ximServer_onClientMessage (
332 	register Widget		gw,
333 	register XEvent*	pXEvent,
334 	register String*	params,
335 	register Cardinal*	num_params)
336 {
337 	register XIMServerWidget		wgThis	= (XIMServerWidget) gw ;
338 	register XClientMessageEvent*	pEvent	= (XClientMessageEvent*)&pXEvent->xclient ;
339 	register Widget					wgClient ;
340 	register Window					wndClient ;
341 	XEvent							xev ;
342 
343 	if (pEvent->display      != XtDisplay (gw) ||
344 		pEvent->window       != XtWindow  (gw) ||
345 		pEvent->message_type != wgThis->ximServer.m_atXConnect ||
346 		pEvent->format       != 32)
347 		return ;
348 
349 	wndClient	= (Window) pEvent->data.l [0] ;
350 	if (!ximServer_isValidWindow (XtDisplay (gw), wndClient)) {
351 		return ;
352 	}
353 	wgClient		= ximServer_findClient (gw, wndClient) ;
354 	if (wgClient == NULL) {
355 		wgClient	= ximServer_newClient (gw, wndClient) ;
356 	}
357 	assert (wgClient != NULL) ;
358 	xev.xclient.type			= ClientMessage ;
359 	xev.xclient.window			= wndClient ;
360 	xev.xclient.message_type	= wgThis->ximServer.m_atXConnect ;
361 	xev.xclient.format			= 32 ;
362 	xev.xclient.data.l [0]		= XtWindow (wgClient) ;
363 	xev.xclient.data.l [1]		= XIM_SERVERMAJOR_TRANSPORT_VERSION ;
364 	xev.xclient.data.l [2]		= XIM_SERVERMINOR_TRANSPORT_VERSION ;
365 	xev.xclient.data.l [3]		= XTRANSPORT_DIVIDING_SIZE ;
366 	XSendEvent (XtDisplay (gw), wndClient, False, NoEventMask, &xev) ;
367 	return ;
368 }
369 
370 void
ximServer_onClientDestroy(register Widget gw,register XtPointer closure,register XtPointer call_data)371 ximServer_onClientDestroy (
372 	register Widget		gw,
373 	register XtPointer	closure,
374 	register XtPointer	call_data)
375 {
376 	register Widget		wgServer	= (Widget) closure ;
377 
378 #if defined (DEBUG)
379 	fprintf (stderr, "ximServer_removeClient (%p, %p)\n", wgServer, call_data) ;
380 #endif
381 	ximServer_removeClient (wgServer, call_data) ;
382 	return ;
383 }
384 
385 Boolean
ximServer_setServerProfile(register Widget gw)386 ximServer_setServerProfile (
387 	register Widget		gw)
388 {
389 	register XIMServerWidget	wgThis	= (XIMServerWidget) gw ;
390 	register Display*		pDisplay ;
391 	register Atom			atServers ;
392 	register Atom			atServer ;
393 	register int			iOperation ;
394 	register Boolean		fNoRegistration ;
395 	unsigned long			lData ;
396 
397 	assert (gw != NULL) ;
398 
399 	pDisplay		= XtDisplay (gw) ;
400 	atServers		= XInternAtom (pDisplay, "XIM_SERVERS", False) ;
401 	atServer		= wgThis->ximServer.m_atServer ;
402 	iOperation		= PropModePrepend ;
403 	fNoRegistration	= False ;
404 
405 	{
406 		Atom		atType ;
407 		int			iFormat ;
408 		unsigned long	ulItems ;
409 		unsigned long	ulBytesAfter ;
410 		unsigned char*	pValue ;
411 
412 		/* �ޤ�������°�������ꤵ��Ƥ��뤫�ɤ������ɤࡣ*/
413 		if (XGetWindowProperty (pDisplay, DefaultRootWindow (pDisplay), atServers, 0L, 1024L, False, AnyPropertyType, &atType, &iFormat, &ulItems, &ulBytesAfter, &pValue) == Success){
414 			if (atType != XA_ATOM || iFormat != 32){
415 				iOperation	= PropModeReplace ;
416 			} else {
417 				Atom*	pAtom	= (Atom*)pValue ;
418 				while (ulItems > 0){
419 					if (*pAtom == wgThis->ximServer.m_atServer){
420 						fNoRegistration	= True ;
421 						break ;
422 					}
423 					pAtom	++ ;
424 					ulItems	-- ;
425 				}
426 			}
427 			if (pValue)
428 				XFree (pValue) ;
429 		}
430 	}
431 	lData = wgThis->ximServer.m_atServer ;
432 	if (!fNoRegistration){
433 		XChangeProperty (pDisplay, DefaultRootWindow (pDisplay), atServers, XA_ATOM, 32, iOperation, (unsigned char *)&lData, 1) ;
434 	} else {
435 		XChangeProperty (pDisplay, DefaultRootWindow (pDisplay), atServers, XA_ATOM, 32, PropModeAppend, (unsigned char*)&lData, 0) ;
436 	}
437 	return	True ;
438 }
439 
440 Boolean
ximServer_parseConversionStartKey(register Widget gw)441 ximServer_parseConversionStartKey (
442 	register Widget		gw)
443 {
444 	register XIMServerWidget	wgThis	= (XIMServerWidget) gw ;
445 	register Display*		pDisplay ;
446 	const char*				pString ;
447 	int						nString ;
448 	KeySym					rKeysym [2] ;
449 	unsigned int			ruState [2] ;
450 	TVarbuffer				vbufHotKey ;
451 	register int				nHotKey, nRetval ;
452 	register XIMHotKeyTrigger*	pHotKey ;
453 	register Boolean			fRetval	= False ;
454 
455 	assert (wgThis->ximServer.m_lstHotKeyTrigger == NULL) ;
456 
457 	pDisplay	= XtDisplay (gw) ;
458 	pString		= wgThis->ximServer.m_strConvStartKeys ;
459 	if (pString == NULL)
460 		return	False ;
461 
462 	if (TFAILED (TVarbuffer_Initialize (&vbufHotKey, sizeof (XIMHotKeyTrigger))))
463 		return	False ;
464 
465 	nString	= strlen (pString) ;
466 	while (nString > 0) {
467 		nRetval	= string2keysymlist (pDisplay, &pString, &nString, rKeysym, ruState, 2) ;
468 		if (nRetval < 0)
469 			break ;
470 
471 		if (nRetval == 1) {
472 			XIMHotKeyTrigger	hotkey ;
473 
474 			hotkey.keysym			= rKeysym [0] ;
475 			hotkey.modifier			= ruState [0] ;
476 			hotkey.modifier_mask	= ruState [0] ;
477 #if defined (DEBUG)
478 			fprintf (stderr, "XIMHotKeyTrigger(%lx, %x)\n",
479 					 hotkey.keysym,
480 					 hotkey.modifier) ;
481 #endif
482 			if (TFAILED (TVarbuffer_Add (&vbufHotKey, &hotkey, 1)))
483 				goto	error ;
484 		}
485 
486 		if (nString > 0 && *pString == ',') {
487 			pString	++ ;
488 			nString	-- ;
489 		}
490 	}
491 
492 	nHotKey	= TVarbuffer_GetUsage (&vbufHotKey) ;
493 	if (nHotKey > 0) {
494 		register XIMHotKeyTrigger*	pSrc ;
495 		register int 				nSize ;
496 
497 		nSize	= sizeof (XIMHotKeyTrigger) * nHotKey ;
498 		pSrc	= TVarbuffer_GetBuffer (&vbufHotKey) ;
499 		pHotKey	= MALLOC (nSize) ;
500 		if (pHotKey != NULL) {
501 			memcpy (pHotKey, pSrc, sizeof (XIMHotKeyTrigger) * nHotKey) ;
502 			fRetval	= True ;
503 		}
504 	} else {
505 		pHotKey	= NULL ;
506 		fRetval	= True ;
507 	}
508 	if (fRetval) {
509 		wgThis->ximServer.m_lstHotKeyTrigger	= pHotKey ;
510 		wgThis->ximServer.m_nHotKeyTrigger		= nHotKey ;
511 	}
512 
513   error:
514 	TVarbuffer_Uninitialize (&vbufHotKey) ;
515 	return	fRetval ;
516 }
517 
518 Widget
ximServer_newClient(register Widget gw,register Window wndClient)519 ximServer_newClient (
520 	register Widget		gw,
521 	register Window		wndClient)
522 {
523 	register XIMServerWidget	wgThis		= (XIMServerWidget) gw ;
524 	Widget						wgClient ;
525 	Arg							rArg [8] ;
526 	register int				nArg ;
527 
528 	nArg	= 0 ;
529 	XtSetArg (rArg [nArg], XtNmappedWhenManaged, False) ;	nArg ++ ;
530 	XtSetArg (rArg [nArg], XtNclientWindow, wndClient) ;	nArg ++ ;
531 	XtSetArg (rArg [nArg], XtNprotocolWidget, gw) ; nArg ++ ;
532 	wgClient	= XtCreateWidget ("ximClient", ximClientWidgetClass, gw, rArg, nArg) ;
533 	if (wgClient == NULL)
534 		return	NULL ;
535 	if (TFAILED (TVarbuffer_Add (&wgThis->ximServer.m_vbufClient, &wgClient, 1))) {
536 		XtDestroyWidget (wgClient) ;
537 		return	NULL ;
538 	}
539 	XtAddCallback (wgClient, XtNdestroyCallback, ximServer_onClientDestroy, gw) ;
540 	XtRealizeWidget (wgClient) ;
541 	return	wgClient ;
542 }
543 
544 void
ximServer_removeClient(register Widget gw,register Widget gwClient)545 ximServer_removeClient (
546 	register Widget		gw,
547 	register Widget		gwClient)
548 {
549 	register XIMServerWidget	wgThis	= (XIMServerWidget) gw ;
550 	register Widget*			pClient ;
551 	register Widget*			pLast ;
552 	register int				i, nClient ;
553 
554 	pClient	= TVarbuffer_GetBuffer (&wgThis->ximServer.m_vbufClient) ;
555 	nClient	= TVarbuffer_GetUsage  (&wgThis->ximServer.m_vbufClient) ;
556 	pLast	= pClient + nClient - 1 ;
557 	for (i = 0 ; i < nClient ; i ++) {
558 		if (*pClient == gwClient) {
559 			if (pClient != pLast)
560 				*pClient	= *pLast ;
561 			TVarbuffer_Sub (&wgThis->ximServer.m_vbufClient, 1) ;
562 			XtRemoveAllCallbacks (gwClient, XtNdestroyCallback) ;
563 			return ;
564 		}
565 		pClient	++ ;
566 	}
567 	return ;
568 }
569 
570 Widget
ximServer_findClient(register Widget gw,register Window wndClient)571 ximServer_findClient (
572 	register Widget		gw,
573 	register Window		wndClient)
574 {
575 	register XIMServerWidget	wgThis	= (XIMServerWidget) gw ;
576 	register Widget*			pClient ;
577 	register int				nClient ;
578 
579 	pClient	= TVarbuffer_GetBuffer (&wgThis->ximServer.m_vbufClient) ;
580 	nClient	= TVarbuffer_GetUsage  (&wgThis->ximServer.m_vbufClient) ;
581 	while (nClient -- > 0) {
582 		if (XtWindow (*pClient) == wndClient)
583 			return	*pClient ;
584 		pClient	++ ;
585 	}
586 	return	NULL ;
587 }
588 
589 void
ximServer_destroyAllClient(register Widget gw)590 ximServer_destroyAllClient (
591 	register Widget		gw)
592 {
593 	register XIMServerWidget	wgThis	= (XIMServerWidget) gw ;
594 	register Widget*			pClient ;
595 	register int				nClient ;
596 
597 	pClient	= TVarbuffer_GetBuffer (&wgThis->ximServer.m_vbufClient) ;
598 	nClient	= TVarbuffer_GetUsage  (&wgThis->ximServer.m_vbufClient) ;
599 
600 	/*	remoteClient ���ƤӽФ���ʤ��褦��դ��롣*/
601 	while (nClient -- > 0) {
602 		XtRemoveAllCallbacks (*pClient, XtNdestroyCallback) ;
603 		XtDestroyWidget (*pClient ++) ;
604 	}
605 	TVarbuffer_Uninitialize (&wgThis->ximServer.m_vbufClient) ;
606 	return ;
607 }
608 
609 Boolean
ximServer_isValidWindow(register Display * pDisplay,register Window wnd)610 ximServer_isValidWindow (
611 	register Display*	pDisplay,
612 	register Window		wnd)
613 {
614 	XWindowAttributes	xwa ;
615 
616 	/*	������ XError ����ٻߤ�Ƥ����Ƥ��顢XGetWindowAttributes ���ơ�
617 	 *	�����֤��ͤ��롣���� XErrorHandler �������ʬ���ʤ��ġ�
618 	 */
619 	return	XGetWindowAttributes (pDisplay, wnd, &xwa) ;
620 }
621 
622 int
XIMServer_GetConversionStartKey(register Widget gw,register const XIMHotKeyTrigger ** ppHotKey)623 XIMServer_GetConversionStartKey (
624 	register Widget		gw,
625 	register const XIMHotKeyTrigger**	ppHotKey)
626 {
627 	register XIMServerWidget	wgThis	= (XIMServerWidget) gw ;
628 
629 	assert (gw != NULL) ;
630 
631 	if (XtClass (gw) != ximServerWidgetClass)
632 		return	0 ;
633 
634 	if (ppHotKey != NULL)
635 		*ppHotKey	= wgThis->ximServer.m_lstHotKeyTrigger ;
636 
637 	return	wgThis->ximServer.m_nHotKeyTrigger ;
638 }
639 
640