1 /*
2  * $Id: xlc_util.c,v 1.2 2001/06/14 18:16:18 ura Exp $
3  */
4 
5 /*
6  * FreeWnn is a network-extensible Kana-to-Kanji conversion system.
7  * This file is part of FreeWnn.
8  *
9  * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999
10  * Copyright 1991, 1992 by Massachusetts Institute of Technology
11  *
12  * Author: OMRON SOFTWARE Co., Ltd. <freewnn@rd.kyoto.omronsoft.co.jp>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2, or (at your option)
17  * any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with GNU Emacs; see the file COPYING.  If not, write to the
26  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27  *
28  * Commentary:
29  *
30  * Change log:
31  *
32  * Last modified date: 8,Feb.1999
33  *
34  * Code:
35  *
36  */
37 /*      Version 4.0
38  */
39 #include <stdio.h>
40 #include <string.h>
41 #include "commonhd.h"
42 #include "sdefine.h"
43 #ifdef  XJUTIL
44 #include "xjutil.h"
45 #include "sxheader.h"
46 #include "xext.h"
47 #else /* XJUTIL */
48 #include "xim.h"
49 #include "sheader.h"
50 #include "ext.h"
51 #endif /* XJUTIL */
52 
53 #ifdef X11R5
54 extern int _XConvertMBToWC (), _XConvertMBToCT (), _XConvertWCToCT ();
55 #ifndef X_WCHAR
56 extern int _XConvertWCToMB ();
57 #endif
58 #else
59 #include "Xlibint.h"
60 #include "XlcPubI.h"
61 
62 #define BadBuffer       (-1)
63 
64 static int
_XConvertWCToMB(lcd,wstr,wc_len,str,mb_bytes,scanned_len)65 _XConvertWCToMB (lcd, wstr, wc_len, str, mb_bytes, scanned_len)
66      XLCd lcd;
67      wchar *wstr;
68      int wc_len;
69      unsigned char *str;
70      int *mb_bytes;
71      int *scanned_len;
72 {
73   /* modified from _Xlcwcstombs in lcStd.c */
74   XlcConv conv;
75   XPointer from, to;
76   int from_left, to_left, ret;
77   int len = *mb_bytes;
78 
79   if (lcd == NULL)
80     {
81       lcd = _XlcCurrentLC ();
82       if (lcd == NULL)
83         return -1;
84     }
85 
86   conv = _XlcOpenConverter (lcd, XlcNWideChar, lcd, XlcNMultiByte);
87   if (conv == NULL)
88     return -1;
89 
90   from = (XPointer) wstr;
91   from_left = wc_len;
92   to = (XPointer) str;
93   to_left = len;
94 
95   if (_XlcConvert (conv, &from, &from_left, &to, &to_left, NULL, 0) < 0)
96     ret = -1;
97   else
98     {
99       ret = len - to_left;
100       if (str && to_left > 0)
101         str[ret] = '\0';
102     }
103 
104   _XlcCloseConverter (conv);
105 
106   *mb_bytes = ret;
107   if (scanned_len)
108     *scanned_len = wc_len - from_left;
109   return ret;
110 
111 }
112 
113 /* ARGSUSED */
114 static int
_XConvertMBToWC(lcd,str,mb_bytes,wstr,wc_len,scanned_bytes,state)115 _XConvertMBToWC (lcd, str, mb_bytes, wstr, wc_len, scanned_bytes, state)
116      XLCd lcd;
117      unsigned char *str;
118      int mb_bytes;
119      wchar *wstr;
120      int *wc_len;
121      int *scanned_bytes;
122      int *state;
123 {
124   /* modified from _Xlcmbstowcs in lcStd.c */
125   XlcConv conv;
126   XPointer from, to;
127   int from_left, to_left, ret;
128   int len = *wc_len;
129 
130   if (lcd == NULL)
131     {
132       lcd = _XlcCurrentLC ();
133       if (lcd == NULL)
134         return -1;
135     }
136 
137   conv = _XlcOpenConverter (lcd, XlcNMultiByte, lcd, XlcNWideChar);
138   if (conv == NULL)
139     return -1;
140 
141   from = (XPointer) str;
142   from_left = mb_bytes;
143   to = (XPointer) wstr;
144   to_left = len;
145 
146   if (_XlcConvert (conv, &from, &from_left, &to, &to_left, NULL, 0) < 0)
147     ret = -1;
148   else
149     {
150       ret = len - to_left;
151       if (wstr && to_left > 0)
152         wstr[ret] = (wchar_t) 0;
153     }
154 
155   _XlcCloseConverter (conv);
156 
157   *wc_len = ret;
158   if (scanned_bytes)
159     *scanned_bytes = mb_bytes - from_left;
160   return 0;
161 }
162 
163 /* ARGSUSED */
164 static int
_XConvertMBToCT(lcd,str,mb_bytes,ctstr,ct_bytes,scanned_bytes,state)165 _XConvertMBToCT (lcd, str, mb_bytes, ctstr, ct_bytes, scanned_bytes, state)
166      XLCd lcd;
167      unsigned char *str;
168      int mb_bytes;
169      unsigned char *ctstr;
170      int *ct_bytes;
171      int *scanned_bytes;
172      int *state;
173 {
174   /* modified from _Xlcmbstowcs in lcStd.c */
175   XlcConv conv;
176   XPointer from, to;
177   int from_left, to_left, ret;
178   int len = *ct_bytes;
179 
180   if (lcd == NULL)
181     {
182       lcd = _XlcCurrentLC ();
183       if (lcd == NULL)
184         return -1;
185     }
186 
187   conv = _XlcOpenConverter (lcd, XlcNMultiByte, lcd, XlcNCompoundText);
188   if (conv == NULL)
189     return -1;
190 
191   from = (XPointer) str;
192   from_left = mb_bytes;
193   to = (XPointer) ctstr;
194   to_left = len;
195 
196   if (_XlcConvert (conv, &from, &from_left, &to, &to_left, NULL, 0) < 0)
197     ret = -1;
198   else
199     {
200       ret = len - to_left;
201       if (ctstr && to_left > 0)
202         ctstr[ret] = '\0';
203     }
204 
205   _XlcCloseConverter (conv);
206 
207   *ct_bytes = ret;
208   if (scanned_bytes)
209     *scanned_bytes = mb_bytes - from_left;
210   return 0;
211 }
212 
213 static int
_XConvertWCToCT(lcd,wstr,wc_len,str,ct_bytes,scanned_len)214 _XConvertWCToCT (lcd, wstr, wc_len, str, ct_bytes, scanned_len)
215      XLCd lcd;
216      wchar *wstr;
217      int wc_len;
218      unsigned char *str;
219      int *ct_bytes;
220      int *scanned_len;
221 {
222   /* modified from _Xlcwcstombs in lcStd.c */
223   XlcConv conv;
224   XPointer from, to;
225   int from_left, to_left, ret;
226   int len = *ct_bytes;
227 
228   if (lcd == NULL)
229     {
230       lcd = _XlcCurrentLC ();
231       if (lcd == NULL)
232         return -1;
233     }
234 
235   conv = _XlcOpenConverter (lcd, XlcNWideChar, lcd, XlcNCompoundText);
236   if (conv == NULL)
237     return -1;
238 
239   from = (XPointer) wstr;
240   from_left = wc_len;
241   to = (XPointer) str;
242   to_left = len;
243 
244   if (_XlcConvert (conv, &from, &from_left, &to, &to_left, NULL, 0) < 0)
245     ret = -1;
246   else
247     {
248       ret = len - to_left;
249       if (str && to_left > 0)
250         str[ret] = '\0';
251     }
252 
253   _XlcCloseConverter (conv);
254 
255   *ct_bytes = ret;
256   if (scanned_len)
257     *scanned_len = wc_len - from_left;
258   return ret;
259 
260 }
261 
262 #endif /* X11R5 */
263 
264 int
alloc_all_buf()265 alloc_all_buf ()
266 {
267   char *wc, *ct, *c;
268 #ifndef X_WCHAR
269   char *w;
270 #endif /* !X_WCHAR */
271   if (((wc = Malloc (sizeof (wchar) * BUF_ALLOC_SIZE)) == NULL) || ((ct = Malloc (sizeof (unsigned char) * BUF_ALLOC_SIZE)) == NULL) || ((c = Malloc (sizeof (unsigned char) * BUF_ALLOC_SIZE)) == NULL)
272 #ifndef X_WCHAR
273       || ((w = Malloc (sizeof (wchar_t) * BUF_ALLOC_SIZE)) == NULL)
274 #endif /* !X_WCHAR */
275     )
276     {
277       malloc_error ("allocation of temporary buffer");
278       return (-1);
279     }
280   wc_buf = (wchar *) wc;
281   ct_buf = (unsigned char *) ct;
282   c_buf = (unsigned char *) c;
283   wc_buf_max = ct_buf_max = c_buf_max = BUF_ALLOC_SIZE;
284 #ifndef X_WCHAR
285   wt_buf = (wchar_t *) w;
286   wt_buf_max = BUF_ALLOC_SIZE;
287 #endif /* !X_WCHAR */
288   return (0);
289 }
290 
291 int
realloc_wc_buf()292 realloc_wc_buf ()
293 {
294   register char *p;
295 
296   if ((p = Malloc (sizeof (wchar) * (wc_buf_max + BUF_ALLOC_SIZE))) == NULL)
297     {
298       malloc_error ("re-allocation of temporary buffer");
299       return (-1);
300     }
301   Free ((char *) wc_buf);
302   wc_buf = (wchar *) p;
303   wc_buf_max += BUF_ALLOC_SIZE;
304   return (0);
305 }
306 
307 int
realloc_ct_buf()308 realloc_ct_buf ()
309 {
310   register char *p;
311   if ((p = Malloc (sizeof (unsigned char) * (ct_buf_max + BUF_ALLOC_SIZE))) == NULL)
312     {
313       malloc_error ("re-allocation of temporary buffer");
314       return (-1);
315     }
316   Free ((char *) ct_buf);
317   ct_buf = (unsigned char *) p;
318   ct_buf_max += BUF_ALLOC_SIZE;
319   return (0);
320 }
321 
322 int
realloc_c_buf()323 realloc_c_buf ()
324 {
325   register char *p;
326 
327   if ((p = Malloc (sizeof (unsigned char) * (c_buf_max + BUF_ALLOC_SIZE))) == NULL)
328     {
329       malloc_error ("re-allocation of temporary buffer");
330       return (-1);
331     }
332   Free ((char *) c_buf);
333   c_buf = (unsigned char *) p;
334   c_buf_max += BUF_ALLOC_SIZE;
335   return (0);
336 }
337 
338 #ifndef X_WCHAR
339 int
realloc_wt_buf()340 realloc_wt_buf ()
341 {
342   register char *p;
343 
344   if ((p = Malloc (sizeof (wchar_t) * (wt_buf_max + BUF_ALLOC_SIZE))) == NULL)
345     {
346       malloc_error ("re-allocation of temporary buffer");
347       return (-1);
348     }
349   Free ((char *) wt_buf);
350   wt_buf = (wchar_t *) p;
351   wt_buf_max += BUF_ALLOC_SIZE;
352   return (0);
353 }
354 #endif /* !X_WCHAR */
355 
356 int
get_columns_wchar(from)357 get_columns_wchar (from)
358      register wchar *from;
359 {
360   register wchar *wc = from;
361 
362   while (*wc == PENDING_WCHAR)
363     wc++;
364   if (*wc)
365     wc++;
366   return (wc - from);
367 }
368 
369 #ifndef X11R5
370 /*
371  * wchar encoding is for EUC in X11R6.
372  * WARNING:  This is rough alorithm, unless we can call ANSI C function.
373  */
374 static int
_XcwGetLength(wc)375 _XcwGetLength (wc)
376      wchar wc;
377 {
378   if (!(wc & ~0xFF))
379     return 1;
380   else
381     return 2;
382 }
383 #endif /* !X11R5 */
384 
385 int
XwcGetColumn(wc)386 XwcGetColumn (wc)
387      wchar wc;
388 {
389   if (wc == PENDING_WCHAR)
390     return (0);
391 #if defined(__STDC__) && defined(_I18N_)
392   return wcwidth (wc);
393 #else
394   return _XcwGetLength (wc);
395 #endif /* defined(__STDC__) && defined(_I18N_) */
396 }
397 
398 int
check_mb(buf,x)399 check_mb (buf, x)
400      register wchar *buf;
401      register int x;
402 {
403   if (*(buf + x) == PENDING_WCHAR)
404     return (1);
405   if (XwcGetColumn (*(buf + x)) > 1)
406     return (2);
407   return (0);
408 }
409 
410 int
w_char_to_char(w,c,n)411 w_char_to_char (w, c, n)
412      register w_char *w;
413      register char *c;
414      register int n;
415 {
416 #ifndef XJUTIL
417   set_cswidth (cur_lang->cswidth_id);
418 #endif /* !XJUTIL */
419   return (ieuc_to_eeuc (c, w, (n * sizeof (w_char))));
420 }
421 
422 int
skip_pending_wchar(to,from)423 skip_pending_wchar (to, from)
424      register wchar *to, *from;
425 {
426   register wchar *wc = to;
427   for (; *from;)
428     {
429       if (*from == PENDING_WCHAR)
430         from++;
431       *wc++ = *from++;
432     }
433   *wc = 0;
434   return (wc - to);
435 }
436 
437 int
put_pending_wchar_and_flg(wc,buf,att,flg)438 put_pending_wchar_and_flg (wc, buf, att, flg)
439      register wchar wc;
440      wchar *buf;
441      unsigned char *att, flg;
442 {
443   register wchar *p = buf;
444   register unsigned char *f = att;
445   register int mb_len, i;
446 
447   mb_len = XwcGetColumn (wc);
448   for (i = 1; i < mb_len; i++)
449     {
450       *p++ = PENDING_WCHAR;
451       *f++ = flg;
452     }
453   *p++ = wc;;
454   *f++ = flg;
455   return (mb_len);
456 }
457 
458 #ifdef  CALLBACKS
459 int
XwcGetChars(wc,end,left)460 XwcGetChars (wc, end, left)
461      register wchar *wc;
462      int end;
463      int *left;
464 {
465   register int i, cnt;
466 
467   *left = 0;
468   for (i = 0, cnt = 0; i < end && *wc; i++, cnt++, wc++)
469     {
470       if (*wc == PENDING_WCHAR)
471         {
472           wc++;
473           i++;
474           if (!(i < end))
475             {
476               for (*left = 1; *wc == PENDING_WCHAR; wc++)
477                 *left += 1;
478               cnt++;
479               return (cnt);
480             }
481         }
482     }
483   return (cnt);
484 }
485 #endif /* CALLBACKS */
486 
487 int
char_to_wchar(xlc,c,wc,len,wc_len)488 char_to_wchar (xlc, c, wc, len, wc_len)
489 #ifdef X11R5
490      XLocale xlc;
491 #else
492      XLCd xlc;
493 #endif /* X11R5 */
494      unsigned char *c;
495      wchar *wc;
496      int len;
497      int wc_len;
498 {
499   int wc_str_len = wc_len;
500   int scanned_byte = 0;
501   int ret;
502 
503   ret = _XConvertMBToWC (xlc, c, len, wc, &wc_str_len, &scanned_byte, NULL);
504   if (ret < 0)
505     {
506       if (ret == BadBuffer)
507         {
508           return (-1);
509         }
510       else
511         {
512           return (-2);
513         }
514     }
515   return (wc_str_len);
516 }
517 
518 int
w_char_to_wchar(xlc,w,wc,len,wc_len)519 w_char_to_wchar (xlc, w, wc, len, wc_len)
520 #ifdef X11R5
521      XLocale xlc;
522 #else
523      XLCd xlc;
524 #endif /* X11R5 */
525      w_char *w;
526      wchar *wc;
527      int len;
528      int wc_len;
529 {
530   int ret;
531 
532   while (c_buf_max < (len * 2))
533     {
534       if (realloc_c_buf () < 0)
535         return (0);
536     }
537   ret = w_char_to_char (w, c_buf, len);
538   if (ret <= 0)
539     return (0);
540 
541   return (char_to_wchar (xlc, (unsigned char *) c_buf, wc, ret, wc_len));
542 }
543 
544 int
w_char_to_ct(xlc,w,ct,len,ct_len)545 w_char_to_ct (xlc, w, ct, len, ct_len)
546 #ifdef X11R5
547      XLocale xlc;
548 #else
549      XLCd xlc;
550 #endif /* X11R5 */
551      w_char *w;
552      unsigned char *ct;
553      int len;
554      int ct_len;
555 {
556   int ret;
557   int ct_str_len = ct_len;
558   int scanned_byte = 0;
559 
560   while (c_buf_max < (len * 2))
561     {
562       if (realloc_c_buf () < 0)
563         return (0);
564     }
565   ret = w_char_to_char (w, c_buf, len);
566   if (ret <= 0)
567     return (0);
568 
569   ret = _XConvertMBToCT (xlc, c_buf, ret, ct, &ct_str_len, &scanned_byte, NULL);
570   if (ret < 0)
571     {
572       if (ret == BadBuffer)
573         {
574           return (-1);
575         }
576       else
577         {
578           return (-2);
579         }
580     }
581   return (ct_str_len);
582 }
583 
584 int
wchar_to_ct(xlc,w,ct,len,ct_len)585 wchar_to_ct (xlc, w, ct, len, ct_len)
586 #ifdef X11R5
587      XLocale xlc;
588 #else
589      XLCd xlc;
590 #endif /* X11R5 */
591      wchar *w;
592      unsigned char *ct;
593      int len;
594      int ct_len;
595 {
596   int scanned_byte;
597   int ct_str_len = ct_len;
598   int ret;
599 
600   ret = _XConvertWCToCT (xlc, w, len, ct, &ct_str_len, &scanned_byte, NULL);
601   if (ret < 0)
602     {
603       if (ret == BadBuffer)
604         {
605           return (-1);
606         }
607       else
608         {
609           return (-2);
610         }
611     }
612   return (ct_str_len);
613 }
614 
615 void
JWOutput(w,fs,gc,start_col,col,flg,offset_x,offset_y,cs,text,text_len)616 JWOutput (w, fs, gc, start_col, col, flg, offset_x, offset_y, cs, text, text_len)
617      Window w;
618      XFontSet fs;
619      GC gc;
620      short start_col, col;
621      unsigned char flg;
622      short offset_x, offset_y;
623      XCharStruct *cs;
624      wchar *text;
625      int text_len;
626 {
627   register int start_x, start_y;
628   wchar_t *w_text;
629   int w_text_len;
630 #ifndef X_WCHAR
631   int mb_buf_len;
632   int scanned_byte;
633   int ret;
634 #endif /* !X_WCHAR */
635 
636 #ifdef  X_WCHAR
637   w_text = (wchar_t *) text;
638   w_text_len = text_len;
639 #else /* X_WCHAR */
640   while (1)
641     {
642       mb_buf_len = c_buf_max;
643       ret = _XConvertWCToMB (
644 #ifdef  XJUTIL
645                               NULL,
646 #else
647                               cur_p->cur_xl->xlc,
648 #endif
649                               text, text_len, c_buf, &mb_buf_len, &scanned_byte, NULL);
650       if (ret < 0)
651         {
652           if (ret == BadBuffer)
653             {
654               if (realloc_c_buf () < 0)
655                 return;
656             }
657           else
658             {
659               return;
660             }
661         }
662       else
663         {
664           break;
665         }
666     }
667   w_text = wt_buf;
668   while (1)
669     {
670       w_text_len = mbstowcs (wt_buf, (char *) c_buf, wt_buf_max);
671       if (w_text_len == wt_buf_max)
672         {
673           if (realloc_wt_buf () < 0)
674             return;
675         }
676       else
677         {
678           break;
679         }
680     }
681 #endif /* X_WCHAR */
682 
683   start_x = (cs->width * start_col) + offset_x;
684   start_y = cs->ascent + offset_y;
685   if (flg & REV_FLAG)
686     {
687       XwcDrawImageString (dpy, w, fs, gc, start_x, start_y, w_text, w_text_len);
688     }
689   else
690     {
691       XClearArea (dpy, w, start_x, offset_y, (cs->width * col), (cs->ascent + cs->descent), False);
692       XwcDrawString (dpy, w, fs, gc, start_x, start_y, w_text, w_text_len);
693     }
694   if (flg & BOLD_FLAG)
695     XwcDrawString (dpy, w, fs, gc, (start_x + 1), start_y, w_text, w_text_len);
696   if (flg & UNDER_FLAG)
697     XDrawLine (dpy, w, gc, start_x, (start_y + 1), (start_x + cs->width * col), start_y + 1);
698   return;
699 }
700 
701 XCharStruct *
get_base_char(fs)702 get_base_char (fs)
703      XFontSet fs;
704 {
705   XCharStruct *cs;
706   XFontStruct **fs_list;
707   char **fn_list;
708 
709   if (XFontsOfFontSet (fs, &fs_list, &fn_list) < 1)
710     {
711       print_out ("I could not get base char struct.");
712       return (NULL);
713     }
714   if (!(cs = (XCharStruct *) Malloc (sizeof (XCharStruct))))
715     {
716       malloc_error ("allocation of base char struct");
717       return (NULL);
718     }
719   cs->width = fs_list[0]->max_bounds.width;
720   cs->ascent = fs_list[0]->ascent;
721   cs->descent = fs_list[0]->descent;
722   return ((XCharStruct *) cs);
723 }
724 
725 /* *INDENT-OFF* */
726 XFontSet
create_font_set(s)727 create_font_set (s)
728      char *s;
729 /* *INDENT-ON* */
730 
731 {
732   XFontSet xfontset;
733   char **missing_charset_list;
734   int missing_charset_count;
735   char *def_string;
736 
737   xfontset = XCreateFontSet (dpy, s, &missing_charset_list, &missing_charset_count, &def_string);
738   if ((xfontset == NULL) /* || (missing_charset_count > 0) */ )
739     {
740       print_out ("Can not create FontSet\n");
741       return ((XFontSet) NULL);
742     }
743   if (missing_charset_count > 0)
744     {
745       XFreeStringList (missing_charset_list);
746     }
747   return ((XFontSet) xfontset);
748 }
749