1 /* Copyright (c) 2002 Canna Project. All rights reserved.
2 *
3 * Permission to use, copy, modify, distribute and sell this software
4 * and its documentation for any purpose is hereby granted without
5 * fee, provided that the above copyright notice appear in all copies
6 * and that both that copyright notice and this permission notice
7 * appear in supporting documentation, and that the name of the
8 * author and contributors not be used in advertising or publicity
9 * pertaining to distribution of the software without specific, written
10 * prior permission. The author and contributors no representations
11 * about the suitability of this software for any purpose. It is
12 * provided "as is" without express or implied warranty.
13 *
14 * THE AUTHOR AND CONTRIBUTORS DISCLAIMS ALL WARRANTIES WITH REGARD TO
15 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE FOR
17 * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23 #if !defined(lint) && !defined(__CODECENTER__)
24 static char rcsid[] = "$Id: obind.c,v 1.4.2.1 2004/04/26 22:49:21 aida_s Exp $";
25 #endif
26
27 #include "cannaconf.h"
28 #define WARN_REFERENCES_EVAL(sym,msg) WARN_REFERENCES(sym,msg)
29
30 #if SUPPORT_OLD_WCHAR
31
32 #if defined(CANNA_WCHAR16) && !defined(WCHAR16)
33 # define WCHAR16
34 #endif
35
36 #include "widedef.h"
37 #include "canna.h"
38 #undef wcKanjiString
39 #undef wcKanjiControl
40 #undef wcCloseKanjiContext
41
42 typedef struct {
43 wchar_t *echoStr; /* local echo string */
44 int length; /* length of echo string */
45 int revPos; /* reverse position */
46 int revLen; /* reverse length */
47 unsigned long info; /* ����¾�ξ��� */
48 wchar_t *mode; /* �⡼�ɾ��� */
49 struct {
50 wchar_t *line;
51 int length;
52 int revPos;
53 int revLen;
54 } gline; /* ����ɽ���Τ���ξ��� */
55 } owcKanjiStatus;
56
57 typedef struct {
58 int val;
59 wchar_t *buffer;
60 int n_buffer;
61 owcKanjiStatus *ks;
62 } owcKanjiStatusWithValue;
63
64 typedef struct {
65 char *client_data;
66 int (*callback_func) pro((char *, int, wchar_t **, int, int *));
67 } owcListCallbackStruct;
68
69 typedef canna_uint16_t cannawc16;
70 typedef canna_uint32_t cannawc32;
71
72 extern int howToReturnModeInfo;
73 extern char *context_table;
74
75 exp(int) wcKanjiString pro((const int, const int, wchar_t *, const int,
76 owcKanjiStatus *));
77 exp(int) wcKanjiControl pro((const int, const int, char *));
78 exp(int) wcCloseKanjiContext pro((const int, owcKanjiStatusWithValue *));
79
80 static size_t
Oldwcsnlen(owcs,maxlen)81 Oldwcsnlen(owcs, maxlen)
82 const wchar_t *owcs;
83 size_t maxlen;
84 {
85 const wchar_t *p, *endp;
86 for (p = owcs, endp = owcs + maxlen; *p && p < endp; ++p)
87 ;
88 return endp - p;
89 }
90
91 static size_t
wc32stowc16s(wc16s,wc32s,len)92 wc32stowc16s(wc16s, wc32s, len)
93 cannawc16 *wc16s;
94 const cannawc32 *wc32s;
95 {
96 unsigned int i;
97 for (i = 0; i < len && wc32s[i]; i++) {
98 cannawc32 wc32 = wc32s[i];
99 cannawc32 wc16;
100 switch (wc32 >> 28) {
101 case 0:
102 /* ASCII */
103 wc16 = wc32 & 0x7f;
104 break;
105 case 1:
106 /* Ⱦ�ѥ��� */
107 wc16 = 0x80 | (wc32 & 0x7f);
108 break;
109 case 2:
110 /* ���� */
111 wc16 = 0x8000 | ((wc32 & 0x3f80) << 1) | (wc32 & 0x7f);
112 break;
113 case 3:
114 /* ���� */
115 wc16 = 0x8080 | ((wc32 & 0x3f80) << 1) | (wc32 & 0x7f);
116 break;
117 }
118 wc16s[i] = (cannawc16)wc16;
119 }
120 if (i < len)
121 wc16s[i] = (cannawc16)0;
122 return i;
123 }
124
125 static size_t
wc16stowc32s(wc32s,wc16s,len)126 wc16stowc32s(wc32s, wc16s, len)
127 cannawc32 *wc32s;
128 const cannawc16 *wc16s;
129 {
130 unsigned int i;
131 for (i = 0; i < len && wc16s[i]; i++) {
132 cannawc32 wc16 = (cannawc32)wc16s[i];
133 cannawc32 wc32;
134 switch (wc16 & 0x8080) {
135 case 0x0000:
136 /* ASCII */
137 wc32 = wc16 & 0x7f;
138 break;
139 case 0x0080:
140 /* Ⱦ�ѥ��� */
141 wc32 = (1 << 28) | (wc16 & 0x7f);
142 break;
143 case 0x8000:
144 /* ���� */
145 wc32 = (2 << 28) | ((wc16 & 0x7f00) >> 1) | (wc16 & 0x7f);
146 break;
147 case 0x8080:
148 /* ���� */
149 wc32 = (3 << 28) | ((wc16 & 0x7f00) >> 1) | (wc16 & 0x7f);
150 break;
151 }
152 wc32s[i] = wc32;
153 }
154 if (i < len)
155 wc32s[i] = (cannawc32)0;
156 return i;
157 }
158
159 static size_t
OldwcstoWCs(cwcs,owcs,len)160 OldwcstoWCs(cwcs, owcs, len)
161 cannawc *cwcs;
162 const wchar_t *owcs;
163 size_t len;
164 {
165 if (sizeof(wchar_t) == sizeof(cannawc)) {
166 unsigned int i;
167 for (i = 0; i < len && owcs[i]; ++i)
168 cwcs[i] = (cannawc)owcs[i];
169 if (i < len)
170 cwcs[i] = (cannawc)0;
171 return i;
172 } else if (sizeof(wchar_t) == 4 /* && sizeof(cannawc) == 2 */)
173 return wc32stowc16s((cannawc16 *)cwcs, (const cannawc32 *)owcs, len);
174 else /* if (sizeof(wchar_t) == 2 && sizeof(cannawc) == 4) */
175 return wc16stowc32s((cannawc32 *)cwcs, (const cannawc16 *)owcs, len);
176 }
177
178 static size_t
WCstoOldwcs(owcs,cwcs,len)179 WCstoOldwcs(owcs, cwcs, len)
180 wchar_t *owcs;
181 const cannawc *cwcs;
182 size_t len;
183 {
184 if (sizeof(wchar_t) == sizeof(cannawc)) {
185 unsigned int i;
186 for (i = 0; i < len && cwcs[i]; ++i)
187 owcs[i] = (wchar_t)cwcs[i];
188 if (i < len)
189 owcs[i] = (cannawc)0;
190 return i;
191 } else if (sizeof(wchar_t) == 4 /* && sizeof(cannawc) == 2 */)
192 return wc16stowc32s((cannawc32 *)owcs, (const cannawc16 *)cwcs, len);
193 else /* if (sizeof(wchar_t) == 2 && sizeof(cannawc) == 4) */
194 return wc32stowc16s((cannawc16 *)owcs, (const cannawc32 *)cwcs, len);
195 }
196
197 static int
StoreWCtoOldwc(wbuf,wbuflen,wks,owbuf,maxowbuf,owks,ch,nbytes)198 StoreWCtoOldwc(wbuf, wbuflen, wks, owbuf, maxowbuf, owks, ch, nbytes)
199 const cannawc *wbuf;
200 int wbuflen;
201 const wcKanjiStatus *wks;
202 wchar_t *owbuf;
203 int maxowbuf;
204 owcKanjiStatus *owks;
205 wchar_t ch;
206 int nbytes;
207 {
208 int ret, totallen = 0, len;
209 wchar_t *p, *endp;
210 static wchar_t *inbuf = 0;
211 static int inbufsize = 0;
212
213 /* info */
214
215 owks->info = wks->info;
216
217 /* ��� */
218
219 if (owks->info & KanjiThroughInfo) {
220 if (nbytes)
221 owbuf[0] = ch;
222 ret = nbytes;
223 }
224 else {
225 if (wbuflen <= 0)
226 ret = 0;
227 else {
228 size_t fixlen = (wbuflen < maxowbuf) ? wbuflen : maxowbuf;
229 ret = (int)WCstoOldwcs(owbuf, wbuf, fixlen);
230 if (/* ret >= 0 && */ ret < maxowbuf)
231 owbuf[ret] = (wchar_t)0;
232 }
233 if (owks->info & KanjiYomiInfo && wbuflen >= 0 && maxowbuf >= ret + 1) {
234 const cannawc *ep;
235 len = WCstoOldwcs(owbuf + ret + 1, wbuf + wbuflen + 1,
236 maxowbuf - ret - 1);
237 ep = wbuf + wbuflen + 1;
238 while (*ep) ep++;
239 if (maxowbuf >= ret + 1 + len + 1)
240 WCstoOldwcs(owbuf + ret + 1 + len + 1, ep + 1,
241 maxowbuf - ret - 1 - len - 1);
242 }
243 }
244
245 /* �礭������� */
246 if (wks->length > 0)
247 totallen = wks->length + 1;
248 if (wks->info & KanjiModeInfo)
249 totallen += WStrlen(wks->mode) + 1;
250 if (wks->info & KanjiGLineInfo)
251 totallen += wks->gline.length + 1;
252
253 if (inbufsize < totallen) {
254 inbufsize = totallen; /* inbufsize will be greater than 0 */
255 if (inbuf) free(inbuf);
256 inbuf = (wchar_t *)malloc(inbufsize * sizeof(wchar_t));
257 if (!inbuf) {
258 inbufsize = 0;
259 jrKanjiError = "\245\341\245\342\245\352\244\254\302\255\244\352\244\336\244\273\244\363";
260 /* ���꤬��ޤ��� */
261 return -1;
262 }
263 }
264
265 p = inbuf;
266 endp = inbuf + inbufsize;
267
268 if (wks->length < 0) {
269 owks->length = -1;
270 }
271 else {
272 /* ������ʸ�� */
273
274 owks->length = owks->revLen = owks->revPos = 0;
275
276 if (wks->length > 0) {
277 owks->echoStr = p;
278 if (wks->revPos > 0) {
279 len = owks->revPos = WCstoOldwcs(p, wks->echoStr, wks->revPos);
280 p += len;
281 }
282 if (wks->revLen > 0) {
283 len = owks->revLen
284 = WCstoOldwcs(p, wks->echoStr + wks->revPos, wks->revLen);
285 p += len;
286 }
287 len = 0;
288 if (wks->length - wks->revPos - wks->revLen > 0) {
289 len = WCstoOldwcs(p, wks->echoStr + wks->revPos + wks->revLen,
290 wks->length - wks->revPos - wks->revLen);
291 p += len;
292 }
293 owks->length = owks->revLen + owks->revPos + len;
294 *p++ = (wchar_t)0;
295 }
296 }
297
298 /* �⡼��ɽ�� */
299
300 if (wks->info & KanjiModeInfo) {
301 len = WCstoOldwcs(p, wks->mode, endp - p - 1);
302 owks->mode = p;
303 p[len] = (wchar_t)0;
304 p += len + 1;
305 }
306
307 /* ������ɽ�� */
308
309 if (wks->info & KanjiGLineInfo) {
310 owks->gline.length = owks->gline.revLen = owks->gline.revPos = 0;
311
312 if (wks->gline.length > 0) {
313 owks->gline.line = p;
314 if (wks->gline.revPos > 0) {
315 len = owks->gline.revPos
316 = WCstoOldwcs(p, wks->gline.line, wks->gline.revPos);
317 p += len;
318 }
319 if (wks->gline.revLen > 0) {
320 len = owks->gline.revLen
321 = WCstoOldwcs(p, wks->gline.line + wks->gline.revPos, wks->gline.revLen);
322 p += len;
323 }
324 len = 0;
325 if (wks->gline.length - wks->gline.revPos - wks->gline.revLen > 0) {
326 len = WCstoOldwcs(p,
327 wks->gline.line + wks->gline.revPos + wks->gline.revLen,
328 wks->gline.length - wks->gline.revPos - wks->gline.revLen);
329 p += len;
330 }
331 owks->gline.length = owks->gline.revLen + owks->gline.revPos + len;
332 *p++ = (wchar_t)0;
333 }
334 }
335 return ret;
336 }
337
338 static int
owcLookupKanji2(dpy,win,buffer_return,n_buffer,nbytes,functionalChar,kanji_status_return)339 owcLookupKanji2(dpy, win, buffer_return, n_buffer, nbytes, functionalChar,
340 kanji_status_return)
341 unsigned int dpy, win;
342 int functionalChar, nbytes;
343 wchar_t *buffer_return;
344 int n_buffer;
345 owcKanjiStatus *kanji_status_return;
346 {
347 int ret;
348 wcKanjiStatus wks;
349 wchar_t ch;
350 cannawc *inbuf = NULL;
351 int inbufsize;
352 int r;
353
354 /* �����Хåե������Ȥ��� */
355 inbufsize = n_buffer; /* inbufsize will be greater than 0 */
356 inbuf = (cannawc *)malloc(inbufsize * sizeof(cannawc));
357 if (!inbuf) {
358 inbufsize = 0;
359 jrKanjiError = "\245\341\245\342\245\352\244\254\302\255\244\352\244\336\244\273\244\363";
360 /* ���꤬��ޤ��� */
361 return -1;
362 }
363
364 OldwcstoWCs(inbuf, buffer_return, nbytes ? nbytes : 1);
365 ch = buffer_return[0];
366 ret = XwcLookupKanji2(dpy, win, inbuf, inbufsize, nbytes, functionalChar,
367 &wks);
368 if (ret < 0) {
369 free(inbuf);
370 return ret;
371 }
372 if (ret >= inbufsize)
373 ret = inbufsize - 1;
374 inbuf[ret] = (cannawc)0;
375
376 r = StoreWCtoOldwc(inbuf, ret, &wks,
377 buffer_return, n_buffer, kanji_status_return,
378 ch, nbytes);
379 free(inbuf);
380 return r;
381 }
382
383
384 int
owcListCallback(client_data,func,items,nitems,cur_item)385 owcListCallback(client_data, func, items, nitems, cur_item)
386 char *client_data;
387 int func;
388 cannawc **items;
389 int nitems, *cur_item;
390 {
391 const owcListCallbackStruct *owlistcb;
392 int r = -1;
393 wchar_t **owitems = NULL;
394 wchar_t *owbuf = NULL;
395 wchar_t *owp;
396 size_t buflen = 0;
397 int i;
398
399 owlistcb = (const owcListCallbackStruct *)client_data;
400 if (!items) /* CANNA_LIST_Insert sets 'nitems' to the pressed key (!=0) */
401 return owlistcb->callback_func(owlistcb->client_data,
402 func, NULL, nitems, cur_item);
403 for (i = 0; i < nitems; i++)
404 buflen += WStrlen(items[i]) + 1;
405 owbuf = (wchar_t *)malloc(buflen * sizeof(wchar_t));
406 owitems = (wchar_t **)malloc((nitems + 1) * sizeof(wchar_t **));
407 if (!owbuf || !owitems)
408 goto last; /* XXX: ñ��-1���֤��Ƥ����Τ��� */
409 owp = owbuf;
410 for (i = 0; i < nitems; i++) {
411 size_t len = WCstoOldwcs(owp, items[i], owbuf + buflen - owp);
412 owitems[i] = owp;
413 owp += len + 1; /* �Хåե��Ͼ����Ƥ��ƥ̥뽪ü������ */
414 }
415 owitems[nitems] = NULL;
416 r = owlistcb->callback_func(owlistcb->client_data,
417 func, owitems, nitems, cur_item);
418 last:
419 free(owbuf);
420 free(owitems);
421 return r;
422 }
423
424 static int
owcKanjiControl2(display,window,request,arg)425 owcKanjiControl2(display, window, request, arg)
426 unsigned int display, window, request;
427 BYTE *arg;
428 {
429 int ret = -1, len1, len2;
430 wcKanjiStatusWithValue wksv;
431 wcKanjiStatus wks;
432 owcKanjiStatusWithValue *ksvarg = (owcKanjiStatusWithValue *)arg;
433 wchar_t *owarg = (wchar_t *)arg;
434 jrListCallbackStruct list_cb;
435 wchar_t ch;
436 cannawc *arg2, *wbuf, *wbuf1, *wbuf2;
437
438 arg2 = (cannawc *)malloc(sizeof(cannawc) * 256);
439 wbuf = (cannawc *)malloc(sizeof(cannawc) * 320);
440 wbuf1 = (cannawc *)malloc(sizeof(cannawc) * 320);
441 wbuf2 = (cannawc *)malloc(sizeof(cannawc) * 320);
442 if (!arg2 || !wbuf || !wbuf1 || !wbuf2) {
443 free(arg2);
444 free(wbuf);
445 free(wbuf1);
446 free(wbuf2);
447 return ret;
448 }
449
450 wksv.buffer = wbuf;
451 wksv.n_buffer = 320;
452 wksv.ks = &wks;
453
454 switch (request) {
455 case KC_DO: /* val �� buffer_return ������륿���� */
456 wbuf[0] = (cannawc)ksvarg->buffer[0];
457 /* FALLTHROUGH */
458 case KC_CHANGEMODE: /* val ��Ϳ���륿���� */
459 wksv.val = ksvarg->val;
460 goto withksv;
461 case KC_STOREYOMI: /* echoStr �� length �� mode ��Ϳ���륿���� */
462 /* �ޤ� mode ��磻�ɤˤ��Ƥߤ褦 */
463 if (((owcKanjiStatusWithValue *)arg)->ks->mode) {
464 len2 = OldwcstoWCs(wbuf2, ksvarg->ks->mode, 319);
465 wbuf2[len2] = (wchar_t)0;
466 wks.mode = wbuf2;
467 } else
468 wks.mode = NULL;
469 /* FALLTHROUGH */
470 case KC_DEFINEKANJI: /* echoStr �� length ��Ϳ���륿���� */
471 /* echoStr ��磻�ɤˤ���Ϳ���Ƥߤ褦 */
472 len1 = OldwcstoWCs(wbuf1, ksvarg->ks->echoStr, 319);
473 wbuf1[len1] = (wchar_t)0;
474 wks.echoStr = wbuf1;
475 wks.length = len1;
476 /* FALLTHROUGH */
477 case KC_KAKUTEI: /* ����ñ��Ϳ�����֤ä���륿���� */
478 case KC_KILL:
479 goto withksv;
480 case KC_CLOSEUICONTEXT:
481 goto closecont;
482 case KC_QUERYMODE: /* querymode */
483 ret = XwcKanjiControl2(display, window, request, (BYTE *)arg2);
484 if (!ret) {
485 switch (howToReturnModeInfo) {
486 case ModeInfoStyleIsString:
487 WCstoOldwcs(owarg, arg2, 256); /* XXX */
488 break;
489 case ModeInfoStyleIsBaseNumeric:
490 owarg[2] = (wchar_t)arg2[2];
491 case ModeInfoStyleIsExtendedNumeric:
492 owarg[1] = (wchar_t)arg2[1];
493 case ModeInfoStyleIsNumeric:
494 owarg[0] = (wchar_t)arg2[0];
495 break;
496 }
497 }
498 goto return_ret;
499 case KC_SETLISTCALLBACK: /* dirty, dirty hack */
500 /* list_cb��KC_setListCallback��d->elistcb�˰��ñۤ� */
501 list_cb.client_data = (char *)arg;
502 list_cb.callback_func = &owcListCallback;
503 ret = XwcKanjiControl2(display, window, request, (char *)&list_cb);
504 goto return_ret;
505 default: /* ���磻�ɤ��Ѥ��ʤ���� */
506 ret = XwcKanjiControl2(display, window, request, arg);
507 goto return_ret;
508 }
509 withksv:
510 ch = ksvarg->buffer[0];
511 ret = XwcKanjiControl2(display, window, request, (BYTE *)&wksv);
512 if (ret < 0) {
513 goto return_ret;
514 }
515 else {
516 wksv.buffer[ret] = (wchar_t)0;
517 ksvarg->val = StoreWCtoOldwc(wksv.buffer, wksv.val, wksv.ks,
518 ksvarg->buffer, ksvarg->n_buffer, ksvarg->ks,
519 ch, ksvarg->val);
520 ret = ksvarg->val;
521 goto return_ret;
522 }
523 closecont:
524 ch = ksvarg->buffer[0];
525 ret = XwcKanjiControl2(display, window, request, (BYTE *)&wksv);
526 if (ret < 0) {
527 goto return_ret;
528 }
529 else {
530 wksv.val = 0;
531 ksvarg->val = StoreWCtoOldwc(wksv.buffer, wksv.val, wksv.ks,
532 ksvarg->buffer, ksvarg->n_buffer, ksvarg->ks,
533 ch, ksvarg->val);
534 goto return_ret;
535 }
536 return_ret:
537 free(wbuf2);
538 free(wbuf1);
539 free(wbuf);
540 free(arg2);
541 return ret;
542 }
543
544 exp(int)
545 wcKanjiString(context_id, ch, buffer_return, nbuffer, kanji_status_return)
546 int context_id, ch, nbuffer;
547 wchar_t *buffer_return;
548 owcKanjiStatus *kanji_status_return;
549 {
550 *buffer_return = (wchar_t)ch;
551
552 return owcLookupKanji2((unsigned int)0, (unsigned int)context_id,
553 buffer_return, nbuffer,
554 1/* byte */, 1/* functional char*/,
555 kanji_status_return);
556 }
557
558 exp(int)
559 wcKanjiControl(context, request, arg)
560 int context;
561 int request;
562 char *arg;
563 {
564 return owcKanjiControl2((unsigned int)0, (unsigned int)context,
565 request, (BYTE *)arg);
566 }
567
568 exp(int)
569 wcCloseKanjiContext(context,ksva)
570 int context;
571 owcKanjiStatusWithValue *ksva;
572 {
573 /* really working? */
574 context_table[context] = 0;
575 return owcKanjiControl2(0, context, KC_CLOSEUICONTEXT, (BYTE *)ksva);
576 }
577
578 #define WARNSTR "warning: libcanna: using old wchar API; consider to use new one."
579 #else /* !SUPPORT_OLD_WCHAR */
580
581 #include "canna.h"
582 #undef wcKanjiString
583 #undef wcKanjiControl
584 #undef wcCloseKanjiContext
585
586 exp(int) wcKanjiString pro((const int, const int, cannawc *, const int,
587 wcKanjiStatus *));
588 exp(int) wcKanjiControl pro((const int, const int, char *));
589 exp(int) wcCloseKanjiContext pro((const int, wcKanjiStatusWithValue *));
590
591 static int
wc_unsupported()592 wc_unsupported()
593 {
594 jrKanjiError = "Old wide character API is disabled on this environment.";
595 return -1;
596 }
597
598 exp(int)
599 wcKanjiString(context_id, ch, buffer_return, nbuffer, kanji_status_return)
600 int context_id, ch, nbuffer;
601 cannawc *buffer_return;
602 wcKanjiStatus *kanji_status_return;
603 {
604 return wc_unsupported();
605 }
606
607 exp(int)
608 wcKanjiControl(context, request, arg)
609 int context;
610 int request;
611 char *arg;
612 {
613 return wc_unsupported();
614 }
615
616 exp(int)
617 wcCloseKanjiContext(context,ksva)
618 int context;
619 wcKanjiStatusWithValue *ksva;
620 {
621 return wc_unsupported();
622 }
623
624 #define WARNSTR "warning: libcanna: old API is disabled; consider to use new one."
625 #endif /* !SUPPORT_OLD_WCHAR */
626
627 WARN_REFERENCES_EVAL(wcKanjiString, WARNSTR);
628 WARN_REFERENCES_EVAL(wcKanjiControl, WARNSTR);
629 WARN_REFERENCES_EVAL(wcCloseKanjiContext, WARNSTR);
630 /* vim: set sw=2: */
631