Mercurial > kinput2.yaz
comparison lib/imlib/imconv.c @ 0:92745d501b9a
initial import from kinput2-v3.1
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Mon, 08 Mar 2010 04:44:30 +0900 |
parents | |
children | 1f9e9cb00c6c eda83436b27e |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:92745d501b9a |
---|---|
1 #ifndef lint | |
2 static char *rcsid = "$Id: imconv.c,v 1.25 2002/01/24 09:07:19 ishisone Exp $"; | |
3 #endif | |
4 /* | |
5 * Copyright (c) 1991, 1994 Software Research Associates, Inc. | |
6 * | |
7 * Permission to use, copy, modify, and distribute this software and its | |
8 * documentation for any purpose and without fee is hereby granted, provided | |
9 * that the above copyright notice appear in all copies and that both that | |
10 * copyright notice and this permission notice appear in supporting | |
11 * documentation, and that the name of Software Research Associates not be | |
12 * used in advertising or publicity pertaining to distribution of the | |
13 * software without specific, written prior permission. Software Research | |
14 * Associates makes no representations about the suitability of this software | |
15 * for any purpose. It is provided "as is" without express or implied | |
16 * warranty. | |
17 * | |
18 * Author: Makoto Ishisone, Software Research Associates, Inc., Japan | |
19 */ | |
20 | |
21 #define COMMIT_SYNC | |
22 #define STATUS_SYNC | |
23 #include "im.h" | |
24 #include "ConvMgr.h" | |
25 #include "OverConv.h" | |
26 #include "OffConv.h" | |
27 #include "OnConv.h" | |
28 #include "InputConv.h" | |
29 | |
30 static void fillDefaultAttributesForStartup _Pt_((IMIC *icp)); | |
31 static unsigned long makeConvAttributesForStartup _Pt_((IMIC *icp, | |
32 ConversionAttributes *attrp)); | |
33 static void commitString _Pt_((IMIC *icp, char *str, int len, int sync)); | |
34 static void fixCallback _Pt_((Widget w, XtPointer client_data, | |
35 XtPointer call_data)); | |
36 static void detachConverter _Pt_((IMIC *icp)); | |
37 static void endCallback _Pt_((Widget w, XtPointer client_data, | |
38 XtPointer call_data)); | |
39 static void unusedEventCallback _Pt_((Widget w, XtPointer client_data, | |
40 XtPointer call_data)); | |
41 static void preeditStartCallback _Pt_((Widget w, XtPointer client_data, | |
42 XtPointer call_data)); | |
43 static void preeditDoneCallback _Pt_((Widget w, XtPointer client_data, | |
44 XtPointer call_data)); | |
45 static void preeditDrawCallback _Pt_((Widget w, XtPointer client_data, | |
46 XtPointer call_data)); | |
47 static void preeditCaretCallback _Pt_((Widget w, XtPointer client_data, | |
48 XtPointer call_data)); | |
49 static void statusStartCallback _Pt_((Widget w, XtPointer client_data, | |
50 XtPointer call_data)); | |
51 static void statusDoneCallback _Pt_((Widget w, XtPointer client_data, | |
52 XtPointer call_data)); | |
53 static void statusDrawCallback _Pt_((Widget w, XtPointer client_data, | |
54 XtPointer call_data)); | |
55 static void preeditStart _Pt_((IMIC *icp)); | |
56 static void preeditDone _Pt_((IMIC *icp)); | |
57 static void preeditDraw _Pt_((IMIC *icp, OCCPreeditDrawArg *data)); | |
58 static void preeditCaret _Pt_((IMIC *icp, int caret)); | |
59 static void statusStart _Pt_((IMIC *icp)); | |
60 static void statusDone _Pt_((IMIC *icp)); | |
61 static void statusDraw _Pt_((IMIC *icp, OCCPreeditDrawArg *data)); | |
62 static void setEventMask _Pt_((IMIC *icp, unsigned long forward_mask, | |
63 unsigned long synchronous_mask)); | |
64 | |
65 | |
66 /*- fillDefaultAttributesForStartup: put default necessary for conv. start -*/ | |
67 static void | |
68 fillDefaultAttributesForStartup(icp) | |
69 IMIC *icp; | |
70 { | |
71 unsigned long cmask, pmask, smask; | |
72 | |
73 cmask = ATTR_MASK_FOCUS | ATTR_MASK_PREEDIT_STATE | ATTR_MASK_RESET_STATE; | |
74 | |
75 switch (icp->style) { | |
76 case IMSTYLE_OVER_THE_SPOT: | |
77 pmask = ATTR_MASK_FOREGROUND | ATTR_MASK_BACKGROUND | | |
78 ATTR_MASK_FONT_SET; | |
79 smask = 0; | |
80 break; | |
81 case IMSTYLE_OFF_THE_SPOT: | |
82 pmask = ATTR_MASK_FOREGROUND | ATTR_MASK_BACKGROUND | | |
83 ATTR_MASK_FONT_SET | ATTR_MASK_AREA; | |
84 smask = ATTR_MASK_AREA; | |
85 break; | |
86 case IMSTYLE_ON_THE_SPOT: | |
87 pmask = 0; | |
88 smask = 0; | |
89 break; | |
90 default: | |
91 pmask = 0; | |
92 smask = 0; | |
93 } | |
94 IMFillDefault(icp, cmask, pmask, smask); | |
95 } | |
96 | |
97 /*- makeConvAttributesForStartup: get conv. attrs needed for startup -*/ | |
98 static unsigned long | |
99 makeConvAttributesForStartup(icp, attrp) | |
100 IMIC *icp; | |
101 ConversionAttributes *attrp; | |
102 { | |
103 icp->common_attr.change_mask = icp->common_attr.set_mask; | |
104 icp->preedit_attr.change_mask = icp->preedit_attr.set_mask; | |
105 icp->status_attr.change_mask = icp->status_attr.set_mask; | |
106 return IMMakeConvAttributes(icp, attrp); | |
107 } | |
108 | |
109 /*- commitString: commmit converted string to client -*/ | |
110 static void | |
111 commitString(icp, str, len, sync) | |
112 IMIC *icp; | |
113 char *str; | |
114 int len; | |
115 int sync; | |
116 { | |
117 int offset; | |
118 IMConnection *conn = icp->im->connection; | |
119 unsigned int flag; | |
120 | |
121 TRACE(("imlib:commitString()\n")); | |
122 | |
123 if (DDEBUG_CONDITION(5)) { | |
124 unsigned char *p = (unsigned char *)str; | |
125 int i; | |
126 | |
127 /* | |
128 * Dump commiting string. | |
129 */ | |
130 printf("* commit string:\n\t"); | |
131 for (i = 0; i < len; i++, p++) { | |
132 if (*p == '\033') { | |
133 printf("ESC "); | |
134 } else if (*p < ' ') { | |
135 printf("^%c ", *p + '@'); | |
136 } else if (*p == ' ') { | |
137 printf("sp "); | |
138 } else if (*p >= 0x7f) { | |
139 printf("%x ", *p); | |
140 } else { | |
141 printf("%c ", *p); | |
142 } | |
143 } | |
144 printf("\n"); | |
145 } | |
146 | |
147 flag = XIM_FLAG_X_LOOKUP_CHARS; | |
148 if (sync) flag |= XIM_FLAG_SYNCHRONOUS; | |
149 | |
150 offset = IMPutHeader(conn, XIM_COMMIT, 0, 0); | |
151 IMPutC16(conn, icp->im->id); | |
152 IMPutC16(conn, icp->id); | |
153 IMPutC16(conn, flag); | |
154 IMPutC16(conn, (unsigned int)len); | |
155 IMPutString(conn, str, len); | |
156 IMFinishRequest(conn, offset); | |
157 } | |
158 | |
159 /*- fixCallback: fix callback -*/ | |
160 /* ARGSUSED */ | |
161 static void | |
162 fixCallback(w, client_data, call_data) | |
163 Widget w; | |
164 XtPointer client_data; | |
165 XtPointer call_data; | |
166 { | |
167 IMIC *icp = (IMIC *)client_data; | |
168 IMConnection *conn = icp->im->connection; | |
169 Widget proto = conn->proto_widget; | |
170 Atom ctext = IMCtextAtom(proto); | |
171 CCTextCallbackArg *arg = (CCTextCallbackArg *)call_data; | |
172 | |
173 TRACE(("imlib:fixCallback()\n")); | |
174 | |
175 /* check encoding and format */ | |
176 if (arg->encoding != ctext || arg->format != 8) { | |
177 /* | |
178 * since every conversion object must support COMPOUND_TEXT, | |
179 * it is a serious error. | |
180 */ | |
181 String params[2]; | |
182 Cardinal num_params; | |
183 WidgetClass ioc = icp->im->converter->input_object_class; | |
184 | |
185 params[0] = XtClass(proto)->core_class.class_name; | |
186 params[1] = ioc->core_class.class_name; | |
187 num_params = 2; | |
188 | |
189 XtAppErrorMsg(XtWidgetToApplicationContext(proto), | |
190 "encodingError", "convertedString", "WidgetError", | |
191 "%s: encoding of the converted string is not COMPOUND_STRING. check inputObject %s", | |
192 params, &num_params); | |
193 } | |
194 | |
195 /* | |
196 * Send fixed string via XIM_COMMIT message. | |
197 * Since kinput2 uses full-synchronous mode, | |
198 * synchronous flag must be turned off. | |
199 */ | |
200 commitString(icp, arg->text, arg->length, 0); | |
201 | |
202 #ifdef COMMIT_SYNC | |
203 /* | |
204 * Send XIM_SYNC_REPLY so that synchronize with clients here. | |
205 */ | |
206 if (icp->state & IC_FORWARDING) { | |
207 icp->state &= ~IC_FORWARDING; | |
208 IMSendRequestWithIC(conn, XIM_SYNC_REPLY, 0, icp); | |
209 } | |
210 #endif /* COMMIT_SYNC */ | |
211 } | |
212 | |
213 /*- detachConverter: detach conversion widget from specified IC -*/ | |
214 static void | |
215 detachConverter(icp) | |
216 IMIC *icp; | |
217 { | |
218 Widget conv; | |
219 | |
220 TRACE(("imlib:detachConverter()\n")); | |
221 | |
222 conv = icp->conversion; | |
223 XtRemoveCallback(conv, XtNtextCallback, fixCallback, (XtPointer)icp); | |
224 XtRemoveCallback(conv, XtNendCallback, endCallback, (XtPointer)icp); | |
225 XtRemoveCallback(conv, XtNunusedEventCallback, unusedEventCallback, (XtPointer)icp); | |
226 if (icp->style == IMSTYLE_ON_THE_SPOT) { | |
227 XtRemoveCallback(conv, XtNpreeditStartCallback, preeditStartCallback, | |
228 (XtPointer)icp); | |
229 XtRemoveCallback(conv, XtNpreeditDoneCallback, preeditDoneCallback, | |
230 (XtPointer)icp); | |
231 XtRemoveCallback(conv, XtNpreeditDrawCallback, preeditDrawCallback, | |
232 (XtPointer)icp); | |
233 XtRemoveCallback(conv, XtNpreeditCaretCallback, preeditCaretCallback, | |
234 (XtPointer)icp); | |
235 XtRemoveCallback(conv, XtNstatusStartCallback, statusStartCallback, | |
236 (XtPointer)icp); | |
237 XtRemoveCallback(conv, XtNstatusDoneCallback, statusDoneCallback, | |
238 (XtPointer)icp); | |
239 XtRemoveCallback(conv, XtNstatusDrawCallback, statusDrawCallback, | |
240 (XtPointer)icp); | |
241 } | |
242 | |
243 CMReleaseConverter(XtParent(icp->im->connection->proto_widget), conv); | |
244 icp->conversion = NULL; | |
245 } | |
246 | |
247 /*- endCallback: conversion end callback -*/ | |
248 /* ARGSUSED */ | |
249 static void | |
250 endCallback(w, client_data, call_data) | |
251 Widget w; | |
252 XtPointer client_data; | |
253 XtPointer call_data; | |
254 { | |
255 IMIC *icp = (IMIC *)client_data; | |
256 | |
257 TRACE(("imlib:endCallback()\n")); | |
258 | |
259 if (icp->state & IC_CONVERTING) { | |
260 detachConverter(icp); | |
261 icp->state &= ~IC_CONVERTING; | |
262 } | |
263 } | |
264 | |
265 /*- unusedEventCallback: unused key event callback -*/ | |
266 /* ARGSUSED */ | |
267 static void | |
268 unusedEventCallback(w, client_data, call_data) | |
269 Widget w; | |
270 XtPointer client_data; | |
271 XtPointer call_data; | |
272 { | |
273 IMIC *icp = (IMIC *)client_data; | |
274 IMConnection *conn = icp->im->connection; | |
275 XKeyEvent *ev = (XKeyEvent *)call_data; | |
276 int offset; | |
277 | |
278 TRACE(("imlib:unusedEventCallback()\n")); | |
279 | |
280 if (icp->im->mask & XIM_EXT_FORWARD_KEYEVENT_MASK) { | |
281 offset = IMPutHeader(conn, XIM_EXT_FORWARD_KEYEVENT, 0, 0); | |
282 IMPutC16(conn, icp->im->id); | |
283 IMPutC16(conn, icp->id); | |
284 IMPutC16(conn, 0); | |
285 IMPutC16(conn, (unsigned int)(ev->serial & 0xffff)); | |
286 IMPutC8(conn, ev->type); | |
287 IMPutC8(conn, (int)ev->keycode); | |
288 IMPutC16(conn, (unsigned int)ev->state); | |
289 IMPutC32(conn, ev->time); | |
290 IMPutC32(conn, ev->window); | |
291 IMFinishRequest(conn, offset); | |
292 } else { | |
293 offset = IMPutHeader(conn, XIM_FORWARD_EVENT, 0, 0); | |
294 IMPutC16(conn, icp->im->id); | |
295 IMPutC16(conn, icp->id); | |
296 IMPutC16(conn, 0); /* ?? */ | |
297 IMPutC16(conn, (unsigned int)((ev->serial >> 16) & 0xffff)); | |
298 | |
299 IMPutC8(conn, ev->type); | |
300 IMPutC8(conn, (int)ev->keycode); | |
301 IMPutC16(conn, (unsigned int)(ev->serial & 0xffff)); | |
302 IMPutC32(conn, ev->time); | |
303 IMPutC32(conn, ev->root); | |
304 IMPutC32(conn, ev->window); | |
305 IMPutC32(conn, ev->subwindow); | |
306 IMPutI16(conn, ev->x_root); | |
307 IMPutI16(conn, ev->y_root); | |
308 IMPutI16(conn, ev->x); | |
309 IMPutI16(conn, ev->y); | |
310 IMPutC16(conn, ev->state); | |
311 IMPutC8(conn, ev->same_screen); | |
312 | |
313 IMFinishRequest(conn, offset); | |
314 } | |
315 } | |
316 | |
317 /*- preeditStartCallback: preedit start -*/ | |
318 /* ARGSUSED */ | |
319 static void | |
320 preeditStartCallback(w, client_data, call_data) | |
321 Widget w; | |
322 XtPointer client_data; | |
323 XtPointer call_data; | |
324 { | |
325 IMIC *icp = (IMIC *)client_data; | |
326 | |
327 TRACE(("preeditStartCallback(icp=0x%lx)\n", icp)); | |
328 | |
329 if (!(icp->common_attr.input_style & XIMPreeditCallbacks)) | |
330 return; | |
331 | |
332 preeditStart(icp); | |
333 } | |
334 | |
335 /*- preeditDoneCallback: preedit done -*/ | |
336 /* ARGSUSED */ | |
337 static void | |
338 preeditDoneCallback(w, client_data, call_data) | |
339 Widget w; | |
340 XtPointer client_data; | |
341 XtPointer call_data; | |
342 { | |
343 IMIC *icp = (IMIC *)client_data; | |
344 | |
345 TRACE(("preeditDoneCallback(icp=0x%lx)\n", icp)); | |
346 | |
347 if (!(icp->common_attr.input_style & XIMPreeditCallbacks)) | |
348 return; | |
349 | |
350 preeditDone(icp); | |
351 } | |
352 | |
353 /*- preeditDrawCallback: preedit draw -*/ | |
354 /* ARGSUSED */ | |
355 static void | |
356 preeditDrawCallback(w, client_data, call_data) | |
357 Widget w; | |
358 XtPointer client_data; | |
359 XtPointer call_data; | |
360 { | |
361 IMIC *icp = (IMIC *)client_data; | |
362 OCCPreeditDrawArg *arg = (OCCPreeditDrawArg *)call_data; | |
363 IMConnection *conn = icp->im->connection; | |
364 Widget proto = conn->proto_widget; | |
365 Atom ctext = IMCtextAtom(proto); | |
366 | |
367 TRACE(("preeditDrawCallback(icp=0x%lx, length=%d)\n",icp,arg->text_length)); | |
368 | |
369 if (!(icp->common_attr.input_style & XIMPreeditCallbacks)) | |
370 return; | |
371 | |
372 /* check encoding and format */ | |
373 if (arg->encoding != ctext || arg->format != 8) { | |
374 /* | |
375 * since every conversion object must support COMPOUND_TEXT, | |
376 * it is a serious error. | |
377 */ | |
378 String params[2]; | |
379 Cardinal num_params; | |
380 WidgetClass ioc = icp->im->converter->input_object_class; | |
381 | |
382 params[0] = XtClass(proto)->core_class.class_name; | |
383 params[1] = ioc->core_class.class_name; | |
384 num_params = 2; | |
385 | |
386 XtAppErrorMsg(XtWidgetToApplicationContext(proto), | |
387 "encodingError", "preeditString", "WidgetError", | |
388 "%s: encoding of the preedit string is not COMPOUND_STRING. check inputObject %s", | |
389 params, &num_params); | |
390 } | |
391 | |
392 preeditDraw(icp, arg); | |
393 } | |
394 | |
395 /*- preeditCaretCallback: preedit caret -*/ | |
396 /* ARGSUSED */ | |
397 static void | |
398 preeditCaretCallback(w, client_data, call_data) | |
399 Widget w; | |
400 XtPointer client_data; | |
401 XtPointer call_data; | |
402 { | |
403 IMIC *icp = (IMIC *)client_data; | |
404 int caret = (int)call_data; | |
405 | |
406 TRACE(("preeditCaretCallback(icp=0x%lx, caret=%d)\n", icp, caret)); | |
407 | |
408 if (!(icp->common_attr.input_style & XIMPreeditCallbacks)) | |
409 return; | |
410 | |
411 preeditCaret(icp, caret); | |
412 } | |
413 | |
414 /*- statusStartCallback: status start -*/ | |
415 /* ARGSUSED */ | |
416 static void | |
417 statusStartCallback(w, client_data, call_data) | |
418 Widget w; | |
419 XtPointer client_data; | |
420 XtPointer call_data; | |
421 { | |
422 IMIC *icp = (IMIC *)client_data; | |
423 | |
424 TRACE(("statusStartCallback(icp=0x%lx)\n", icp)); | |
425 | |
426 if (!(icp->common_attr.input_style & XIMStatusCallbacks)) | |
427 return; | |
428 | |
429 statusStart(icp); | |
430 } | |
431 | |
432 /*- statusDoneCallback: status done -*/ | |
433 /* ARGSUSED */ | |
434 static void | |
435 statusDoneCallback(w, client_data, call_data) | |
436 Widget w; | |
437 XtPointer client_data; | |
438 XtPointer call_data; | |
439 { | |
440 IMIC *icp = (IMIC *)client_data; | |
441 | |
442 TRACE(("statusDoneCallback(icp=0x%lx)\n", icp)); | |
443 | |
444 if (!(icp->common_attr.input_style & XIMStatusCallbacks)) | |
445 return; | |
446 | |
447 statusDone(icp); | |
448 } | |
449 | |
450 /*- statusDrawCallback: status draw -*/ | |
451 /* ARGSUSED */ | |
452 static void | |
453 statusDrawCallback(w, client_data, call_data) | |
454 Widget w; | |
455 XtPointer client_data; | |
456 XtPointer call_data; | |
457 { | |
458 IMIC *icp = (IMIC *)client_data; | |
459 OCCPreeditDrawArg *arg = (OCCPreeditDrawArg *)call_data; | |
460 IMConnection *conn = icp->im->connection; | |
461 Widget proto = conn->proto_widget; | |
462 Atom ctext = IMCtextAtom(proto); | |
463 | |
464 TRACE(("statusDrawCallback(icp=0x%lx, length=%d)\n", icp,arg->text_length)); | |
465 | |
466 if (!(icp->common_attr.input_style & XIMStatusCallbacks)) | |
467 return; | |
468 | |
469 /* check encoding and format */ | |
470 if (arg->encoding != ctext || arg->format != 8) { | |
471 /* | |
472 * since every conversion object must support COMPOUND_TEXT, | |
473 * it is a serious error. | |
474 */ | |
475 String params[2]; | |
476 Cardinal num_params; | |
477 WidgetClass ioc = icp->im->converter->input_object_class; | |
478 | |
479 params[0] = XtClass(proto)->core_class.class_name; | |
480 params[1] = ioc->core_class.class_name; | |
481 num_params = 2; | |
482 | |
483 XtAppErrorMsg(XtWidgetToApplicationContext(proto), | |
484 "encodingError", "statusString", "WidgetError", | |
485 "%s: encoding of the status string is not COMPOUND_STRING. check inputObject %s", | |
486 params, &num_params); | |
487 } | |
488 | |
489 statusDraw(icp, arg); | |
490 } | |
491 | |
492 /*- preeditStart: do preedit start -*/ | |
493 static void | |
494 preeditStart(icp) | |
495 IMIC *icp; | |
496 { | |
497 if (!(icp->state & IC_IN_PREEDIT)) { | |
498 int offset; | |
499 IMConnection *conn = icp->im->connection; | |
500 | |
501 TRACE(("imlib:preeditStart()\n")); | |
502 | |
503 offset = IMPutHeader(conn, XIM_PREEDIT_START, 0, 0); | |
504 IMPutC16(conn, icp->im->id); | |
505 IMPutC16(conn, icp->id); | |
506 IMFinishRequest(conn, offset); | |
507 icp->state |= IC_IN_PREEDIT; | |
508 } | |
509 } | |
510 | |
511 /*- preeditDone: do preedit done -*/ | |
512 static void | |
513 preeditDone(icp) | |
514 IMIC *icp; | |
515 { | |
516 if (icp->state & IC_IN_PREEDIT) { | |
517 int offset; | |
518 IMConnection *conn = icp->im->connection; | |
519 | |
520 TRACE(("imlib:preeditDone()\n")); | |
521 | |
522 offset = IMPutHeader(conn, XIM_PREEDIT_DONE, 0, 0); | |
523 IMPutC16(conn, icp->im->id); | |
524 IMPutC16(conn, icp->id); | |
525 IMFinishRequest(conn, offset); | |
526 icp->state &= ~IC_IN_PREEDIT; | |
527 } | |
528 } | |
529 | |
530 /*- preeditDraw: do actual preedit draw -*/ | |
531 static void | |
532 preeditDraw(icp, data) | |
533 IMIC *icp; | |
534 OCCPreeditDrawArg *data; | |
535 { | |
536 IMConnection *conn = icp->im->connection; | |
537 int offset; | |
538 unsigned int status; | |
539 XIMFeedback feedback; | |
540 int i; | |
541 | |
542 if (icp->state & IC_RESETTING) return; | |
543 | |
544 preeditStart(icp); | |
545 | |
546 TRACE(("imlib:preeditDraw()\n")); | |
547 | |
548 if (DDEBUG_CONDITION(5)) { | |
549 unsigned char *p = (unsigned char *)data->text; | |
550 | |
551 /* | |
552 * Dump preedit string. | |
553 */ | |
554 printf("* preedit string:\n\t"); | |
555 for (i = 0; i < data->text_length; i++, p++) { | |
556 if (*p == '\033') { | |
557 printf("ESC "); | |
558 } else if (*p < ' ') { | |
559 printf("^%c ", *p + '@'); | |
560 } else if (*p == ' ') { | |
561 printf("sp "); | |
562 } else if (*p >= 0x7f) { | |
563 printf("%x ", *p); | |
564 } else { | |
565 printf("%c ", *p); | |
566 } | |
567 } | |
568 printf("\n"); | |
569 } | |
570 | |
571 offset = IMPutHeader(conn, XIM_PREEDIT_DRAW, 0, 0); | |
572 IMPutC16(conn, icp->im->id); | |
573 IMPutC16(conn, icp->id); | |
574 IMPutC32(conn, data->caret); | |
575 IMPutC32(conn, data->chg_first); | |
576 IMPutC32(conn, data->chg_length); | |
577 status = 0; | |
578 if (data->text_length == 0) status |= 0x1; /* no string */ | |
579 if (data->attrs_length == 0) status |= 0x2; /* no feedback */ | |
580 IMPutC32(conn, status); | |
581 IMPutC16(conn, (unsigned int)data->text_length); | |
582 if (data->text_length > 0) { | |
583 IMPutString(conn, data->text, data->text_length); | |
584 } | |
585 IMPutPad(conn); | |
586 IMPutC16(conn, (unsigned int)(data->attrs_length * 4)); | |
587 IMPutC16(conn, 0L); /* unused */ | |
588 if (data->attrs_length > 0) { | |
589 for (i = 0; i < data->attrs_length; i++) { | |
590 IMPutC32(conn, data->attrs[i]); | |
591 } | |
592 } | |
593 IMFinishRequest(conn, offset); | |
594 } | |
595 | |
596 /*- preeditCaret: do actual preedit caret -*/ | |
597 static void | |
598 preeditCaret(icp, caret) | |
599 IMIC *icp; | |
600 int caret; | |
601 { | |
602 IMConnection *conn = icp->im->connection; | |
603 int offset; | |
604 | |
605 if (icp->state & IC_RESETTING) return; | |
606 | |
607 preeditStart(icp); | |
608 | |
609 TRACE(("imlib:preeditCaret()\n")); | |
610 | |
611 offset = IMPutHeader(conn, XIM_PREEDIT_CARET, 0, 0); | |
612 IMPutC16(conn, icp->im->id); | |
613 IMPutC16(conn, icp->id); | |
614 IMPutC32(conn, caret); | |
615 IMPutC32(conn, (long)XIMAbsolutePosition); | |
616 IMPutC32(conn, (long)XIMPrimary); | |
617 IMFinishRequest(conn, offset); | |
618 } | |
619 | |
620 /*- statusStart: do status start -*/ | |
621 static void | |
622 statusStart(icp) | |
623 IMIC *icp; | |
624 { | |
625 if (!(icp->state & IC_IN_STATUS)) { | |
626 int offset; | |
627 IMConnection *conn = icp->im->connection; | |
628 | |
629 TRACE(("imlib:statusStart()\n")); | |
630 | |
631 offset = IMPutHeader(conn, XIM_STATUS_START, 0, 0); | |
632 IMPutC16(conn, icp->im->id); | |
633 IMPutC16(conn, icp->id); | |
634 IMFinishRequest(conn, offset); | |
635 icp->state |= IC_IN_STATUS; | |
636 #ifdef STATUS_SYNC | |
637 IMFlush(conn); | |
638 #endif /* STATUS_SYNC */ | |
639 } | |
640 } | |
641 | |
642 /*- statusDone: do status done -*/ | |
643 static void | |
644 statusDone(icp) | |
645 IMIC *icp; | |
646 { | |
647 if (icp->state & IC_IN_STATUS) { | |
648 int offset; | |
649 IMConnection *conn = icp->im->connection; | |
650 | |
651 TRACE(("imlib:statusDone()\n")); | |
652 | |
653 offset = IMPutHeader(conn, XIM_STATUS_DONE, 0, 0); | |
654 IMPutC16(conn, icp->im->id); | |
655 IMPutC16(conn, icp->id); | |
656 IMFinishRequest(conn, offset); | |
657 icp->state &= ~IC_IN_STATUS; | |
658 #ifdef STATUS_SYNC | |
659 IMFlush(conn); | |
660 #endif /* STATUS_SYNC */ | |
661 } | |
662 } | |
663 | |
664 /*- statusDraw: do actual status draw -*/ | |
665 static void | |
666 statusDraw(icp, data) | |
667 IMIC *icp; | |
668 OCCPreeditDrawArg *data; | |
669 { | |
670 IMConnection *conn = icp->im->connection; | |
671 int offset; | |
672 unsigned int status; | |
673 | |
674 if (icp->state & IC_RESETTING) return; | |
675 | |
676 statusStart(icp); | |
677 | |
678 TRACE(("imlib:statusDraw()\n")); | |
679 | |
680 offset = IMPutHeader(conn, XIM_STATUS_DRAW, 0, 0); | |
681 IMPutC16(conn, icp->im->id); | |
682 IMPutC16(conn, icp->id); | |
683 IMPutC32(conn, 0L); /* text type */ | |
684 status = 0; | |
685 if (data->text_length == 0) status |= 0x1; /* no string */ | |
686 if (data->attrs_length == 0) status |= 0x2; /* no feedback */ | |
687 IMPutC32(conn, status); | |
688 IMPutC16(conn, (unsigned int)data->text_length); | |
689 if (data->text_length > 0) { | |
690 IMPutString(conn, data->text, data->text_length); | |
691 } | |
692 IMPutPad(conn); | |
693 IMPutC16(conn, (unsigned int)(data->attrs_length * 32)); | |
694 IMPutC16(conn, 0L); /* unused */ | |
695 if (data->attrs_length > 0) { | |
696 int i; | |
697 for (i = 0; i < data->attrs_length; i++) { | |
698 IMPutC32(conn, 0L); | |
699 } | |
700 } | |
701 IMFinishRequest(conn, offset); | |
702 #ifdef STATUS_SYNC | |
703 IMFlush(conn); | |
704 #endif /* STATUS_SYNC */ | |
705 } | |
706 | |
707 /*- setEventMask: put XIM_SET_EVENT_MASK request on the output stream -*/ | |
708 static void | |
709 setEventMask(icp, forward_mask, synchronous_mask) | |
710 IMIC *icp; | |
711 unsigned long forward_mask; | |
712 unsigned long synchronous_mask; | |
713 { | |
714 IMConnection *conn = icp->im->connection; | |
715 | |
716 (void)IMPutHeader(conn, XIM_SET_EVENT_MASK, 0, 12); | |
717 IMPutC16(conn, icp->im->id); | |
718 IMPutC16(conn, icp->id); | |
719 IMPutC32(conn, forward_mask); | |
720 IMPutC32(conn, synchronous_mask); | |
721 IMSchedule(conn, SCHED_WRITE); | |
722 } | |
723 | |
724 | |
725 /* | |
726 * Public functions | |
727 */ | |
728 | |
729 int | |
730 IMStartConversion(icp) | |
731 IMIC *icp; | |
732 { | |
733 IMIM *imp = icp->im; | |
734 Widget proto = imp->connection->proto_widget; | |
735 Widget converter; | |
736 WidgetClass class; | |
737 unsigned long attrmask; | |
738 ConversionAttributes attrs; | |
739 | |
740 TRACE(("IMStartConversion()\n")); | |
741 | |
742 if (icp->state & IC_CONVERTING) return 0; | |
743 | |
744 /* | |
745 * Check required attributes i.e. client window. | |
746 */ | |
747 if (!(icp->common_attr.set_mask & ATTR_MASK_CLIENT)) { | |
748 IMSendError(icp->im->connection, IMBadSomething, icp->im->id, icp->id, | |
749 "client window required"); | |
750 return -1; | |
751 } | |
752 | |
753 /* | |
754 * Fill in default values for unspecified attributes. | |
755 */ | |
756 fillDefaultAttributesForStartup(icp); | |
757 | |
758 /* | |
759 * Get appropriate converter class. | |
760 */ | |
761 if (icp->style == IMSTYLE_OVER_THE_SPOT) { | |
762 class = overTheSpotConversionWidgetClass; | |
763 } else if (icp->style == IMSTYLE_OFF_THE_SPOT) { | |
764 class = offTheSpotConversionWidgetClass; | |
765 } else if (icp->style == IMSTYLE_ON_THE_SPOT) { | |
766 class = onTheSpotConversionWidgetClass; | |
767 } else { | |
768 class = separateConversionWidgetClass; | |
769 } | |
770 | |
771 /* | |
772 * Compute conversion attributes to be passed to the converter. | |
773 */ | |
774 attrmask = makeConvAttributesForStartup(icp, &attrs); | |
775 | |
776 icp->state &= ~IC_RESETTING; | |
777 | |
778 /* | |
779 * Attach converter to this IC. | |
780 */ | |
781 converter = CMGetConverter(XtParent(proto), | |
782 icp->common_attr.client, class, | |
783 imp->converter->input_object_class, | |
784 imp->converter->display_object_class); | |
785 if (converter == NULL) { | |
786 IMSendError(imp->connection, IMBadSomething, imp->id, icp->id, | |
787 "can't attach converter to this IC"); | |
788 return -1; | |
789 } | |
790 icp->conversion = converter; | |
791 | |
792 /* | |
793 * Add callback functions. | |
794 */ | |
795 XtAddCallback(converter, XtNtextCallback, fixCallback, (XtPointer)icp); | |
796 XtAddCallback(converter, XtNendCallback, endCallback, (XtPointer)icp); | |
797 XtAddCallback(converter, XtNunusedEventCallback, unusedEventCallback, (XtPointer)icp); | |
798 if (icp->style == IMSTYLE_ON_THE_SPOT) { | |
799 XtAddCallback(converter, XtNpreeditStartCallback, preeditStartCallback, | |
800 (XtPointer)icp); | |
801 XtAddCallback(converter, XtNpreeditDoneCallback, preeditDoneCallback, | |
802 (XtPointer)icp); | |
803 XtAddCallback(converter, XtNpreeditDrawCallback, preeditDrawCallback, | |
804 (XtPointer)icp); | |
805 XtAddCallback(converter, XtNpreeditCaretCallback, preeditCaretCallback, | |
806 (XtPointer)icp); | |
807 XtAddCallback(converter, XtNstatusStartCallback, statusStartCallback, | |
808 (XtPointer)icp); | |
809 XtAddCallback(converter, XtNstatusDoneCallback, statusDoneCallback, | |
810 (XtPointer)icp); | |
811 XtAddCallback(converter, XtNstatusDrawCallback, statusDrawCallback, | |
812 (XtPointer)icp); | |
813 } | |
814 | |
815 /* | |
816 * Start conversion | |
817 */ | |
818 /* !!! if front-end method is used, ESMethodSelectFocus should be used */ | |
819 XtVaSetValues(converter, XtNeventSelectMethod, ESMethodNone, NULL); | |
820 CControlStartConversion(converter, icp->common_attr.client, | |
821 attrmask, &attrs); | |
822 | |
823 icp->state |= IC_CONVERTING; | |
824 | |
825 if (icp->common_attr.input_style & XIMPreeditCallbacks) | |
826 preeditStart(icp); | |
827 | |
828 /* | |
829 * Send XIM_SET_EVENT_MASK to let the client forward the key events. | |
830 */ | |
831 IMStartForwarding(icp); | |
832 | |
833 return 0; | |
834 } | |
835 | |
836 void | |
837 IMStopConversion(icp) | |
838 IMIC *icp; | |
839 { | |
840 TRACE(("IMStopConversion()\n")); | |
841 | |
842 if (!(icp->state & IC_CONVERTING)) return; | |
843 | |
844 /* | |
845 * Terminate conversion. | |
846 */ | |
847 CControlEndConversion(icp->conversion); | |
848 | |
849 if (icp->common_attr.input_style & XIMPreeditCallbacks) | |
850 preeditDone(icp); | |
851 IMStatusDone(icp); | |
852 | |
853 /* | |
854 * Detach converter. | |
855 */ | |
856 detachConverter(icp); | |
857 | |
858 /* | |
859 * Stop forwarding key events unless this IC is being destroyed. | |
860 */ | |
861 if (!(icp->state & IC_DESTROYING)) { | |
862 IMStopForwarding(icp); | |
863 } | |
864 | |
865 icp->state &= ~IC_CONVERTING; | |
866 } | |
867 | |
868 int | |
869 IMResetIC(icp, preedit_strp) | |
870 IMIC *icp; | |
871 char **preedit_strp; | |
872 { | |
873 int num_bytes = 0; | |
874 | |
875 TRACE(("IMResetIC()\n")); | |
876 | |
877 *preedit_strp = NULL; | |
878 | |
879 if (icp->state & IC_CONVERTING) { | |
880 /* | |
881 * get input object by asking conversion widget of XtNinputObject | |
882 * resource. however, it is not recommended since protocol widget | |
883 * should interact with input object only through conversion | |
884 * widget. | |
885 */ | |
886 CCTextCallbackArg arg; | |
887 Widget input_obj; | |
888 Widget w = icp->im->connection->proto_widget; | |
889 | |
890 XtVaGetValues(icp->conversion, XtNinputObject, &input_obj, NULL); | |
891 arg.encoding = IMCtextAtom(w); | |
892 #ifdef notdef | |
893 if (ICGetConvertedString(input_obj, &arg.encoding, &arg.format, | |
894 &arg.length, &arg.text) >= 0) { | |
895 num_bytes = arg.length; | |
896 *preedit_strp = (char *)arg.text; | |
897 } | |
898 #else | |
899 /* | |
900 * Canna seems to have some problem with ICGetConvertedString(). | |
901 * Use ICGetPreeditString instead. | |
902 */ | |
903 if (ICGetPreeditString(input_obj, 0, 0, &arg.encoding, &arg.format, | |
904 &arg.length, &arg.text) >= 0) { | |
905 num_bytes = arg.length; | |
906 *preedit_strp = (char *)arg.text; | |
907 } | |
908 #endif | |
909 ICClearConversion(input_obj); | |
910 TRACE(("\twas converting. %d bytes left\n", num_bytes)); | |
911 | |
912 if (icp->common_attr.reset_state == XIMInitialState) { | |
913 /* Force to end the conversion. */ | |
914 TRACE(("\tback to the initial state\n")); | |
915 IMStopConversion(icp); | |
916 } | |
917 } | |
918 return num_bytes; | |
919 } | |
920 | |
921 void | |
922 IMForwardEvent(icp, ev) | |
923 IMIC *icp; | |
924 XEvent *ev; | |
925 { | |
926 TRACE(("IMForwardEvent()\n")); | |
927 | |
928 if (icp->conversion == NULL) return; | |
929 XtCallActionProc(icp->conversion, "to-inputobj", ev, | |
930 (String *)NULL, (Cardinal)0); | |
931 } | |
932 | |
933 /* ARGSUSED */ | |
934 void | |
935 IMSetFocus(icp) | |
936 IMIC *icp; | |
937 { | |
938 TRACE(("IMSetFocus(ic%d)\n", icp->id)); | |
939 if (icp->conversion != NULL) { | |
940 CControlChangeFocus(icp->conversion, 1); | |
941 } | |
942 } | |
943 | |
944 /* ARGSUSED */ | |
945 void | |
946 IMUnsetFocus(icp) | |
947 IMIC *icp; | |
948 { | |
949 TRACE(("IMUnsetFocus(ic%d)\n", icp->id)); | |
950 if (icp->conversion != NULL) { | |
951 CControlChangeFocus(icp->conversion, 0); | |
952 } | |
953 } | |
954 | |
955 /* ARGSUSED */ | |
956 void | |
957 IMStatusStart(icp) | |
958 IMIC *icp; | |
959 { | |
960 TRACE(("IMStatusStart(ic%d)\n", icp->id)); | |
961 if (!(icp->common_attr.input_style & XIMStatusCallbacks)) | |
962 return; | |
963 statusStart(icp); | |
964 } | |
965 | |
966 /* ARGSUSED */ | |
967 void | |
968 IMStatusDone(icp) | |
969 IMIC *icp; | |
970 { | |
971 TRACE(("IMStatusDone(ic%d)\n", icp->id)); | |
972 if (!(icp->common_attr.input_style & XIMStatusCallbacks)) | |
973 return; | |
974 statusDone(icp); | |
975 } | |
976 | |
977 void | |
978 IMStartForwarding(icp) | |
979 IMIC *icp; | |
980 { | |
981 /* | |
982 * Make the client forward key events to us. | |
983 */ | |
984 TRACE(("IMStartForwarding(ic%d)\n", icp->id)); | |
985 | |
986 #define FORWARD_MASK (KeyPressMask|KeyReleaseMask) | |
987 | |
988 #ifdef notdef | |
989 if (synchronous) { | |
990 setEventMask(icp, FORWARD_MASK, FORWARD_MASK); | |
991 } else { | |
992 setEventMask(icp, FORWARD_MASK, NoEventMask); | |
993 } | |
994 #else | |
995 /* using full-synchronous method */ | |
996 setEventMask(icp, FORWARD_MASK, FORWARD_MASK); | |
997 #endif | |
998 | |
999 #undef FORWARD_MASK | |
1000 } | |
1001 | |
1002 void | |
1003 IMStopForwarding(icp) | |
1004 IMIC *icp; | |
1005 { | |
1006 /* | |
1007 * Make the client stop sending key events. | |
1008 */ | |
1009 TRACE(("IMStopForwarding(ic%d)\n", icp->id)); | |
1010 setEventMask(icp, NoEventMask, NoEventMask); | |
1011 } |