util/dttypes: remove register keyword
[oweals/cde.git] / cde / programs / dtudcfonted / libfal / _fallcUTF.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* lcUTF.c 1.1 - Fujitsu source for CDEnext    95/11/06 20:32:41        */ 
24 /* $XConsortium: _fallcUTF.c /main/2 1996/09/27 19:03:38 drk $ */
25 /******************************************************************
26
27               Copyright 1993 by SunSoft, Inc.
28
29 Permission to use, copy, modify, distribute, and sell this software
30 and its documentation for any purpose is hereby granted without fee,
31 provided that the above copyright notice appear in all copies and
32 that both that copyright notice and this permission notice appear
33 in supporting documentation, and that the name of SunSoft, Inc.
34 not be used in advertising or publicity pertaining to distribution
35 of the software without specific, written prior permission.
36 SunSoft, Inc. makes no representations about the suitability of
37 this software for any purpose.  It is provided "as is" without
38 express or implied warranty.
39
40 SunSoft Inc. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
41 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
42 IN NO EVENT SHALL SunSoft, Inc. BE LIABLE FOR ANY SPECIAL, INDIRECT
43 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
44 OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
45 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
46 OR PERFORMANCE OF THIS SOFTWARE.
47
48   Author: Hiromu Inukai (inukai@Japan.Sun.COM) SunSoft, inc.
49
50 ******************************************************************/
51 #include "_fallcUTF.h"
52
53 static long     getutfrune();
54 static void our_wctomb(
55 #if NeedFunctionPrototypes
56                        unsigned short r, 
57                        char **bufptr, 
58                        int *buf_len
59 #endif
60 );
61 static int our_mbtowc(
62 #if NeedFunctionPrototypes   
63                       unsigned long *p, 
64                       char *s, 
65                       size_t n
66 #endif
67 );
68 static void     latin2rune(
69 #if NeedFunctionPrototypes
70                            unsigned char c, 
71                            Rune *r
72 #endif
73 );
74 static void     jis02012rune(
75 #if NeedFunctionPrototypes
76                              unsigned char c, 
77                              Rune *r
78 #endif
79 );
80 static void     jis02082rune(
81 #if NeedFunctionPrototypes
82                              unsigned char c, 
83                              Rune *r
84 #endif
85 );
86 static void     ksc2rune(
87 #if NeedFunctionPrototypes
88                          unsigned char c, 
89                          Rune *r
90 #endif
91 );
92 static void     gb2rune(
93 #if NeedFunctionPrototypes
94                         unsigned char c, 
95                         Rune *r
96 #endif
97 );
98 static void     init_latin1tab();
99 static void     init_latin2tab();
100 static void     init_latin3tab();
101 static void     init_latin4tab();
102 static void     init_latin5tab();
103 static void     init_latin6tab();
104 static void     init_latin7tab();
105 static void     init_latin8tab();
106 static void     init_latin9tab();
107 static void     init_jis0201tab();
108 static void     init_jis0208tab();
109 static void     init_ksc5601tab();
110 static void     init_gb2312tab();
111
112
113 static char     *int_locale = NULL;
114 static long     *tabkuten = NULL;
115 static long     *tabksc5601 = NULL;
116 static long     *tabgb = NULL;
117
118 static UtfData utfdata_list = (UtfData)NULL;
119
120 static XlcUTFDataRec default_utf_data[] = 
121 {
122     {"ISO8859-1", XlcGL, init_latin1tab, latin2rune, N11n_none, 0x20},
123     {"ISO8859-1", XlcGR, init_latin1tab, latin2rune, N11n_none, 0x20},
124     {"ISO8859-1", XlcGL, init_latin2tab, latin2rune, N11n_none, 0x20},
125     {"ISO8859-1", XlcGR, init_latin2tab, latin2rune, N11n_none, 0x20},
126     {"ISO8859-1", XlcGL, init_latin3tab, latin2rune, N11n_none, 0x20},
127     {"ISO8859-1", XlcGR, init_latin3tab, latin2rune, N11n_none, 0x20},
128     {"ISO8859-1", XlcGL, init_latin4tab, latin2rune, N11n_none, 0x20},
129     {"ISO8859-1", XlcGR, init_latin4tab, latin2rune, N11n_none, 0x20},
130     {"ISO8859-1", XlcGL, init_latin5tab, latin2rune, N11n_none, 0x20},
131     {"ISO8859-1", XlcGR, init_latin5tab, latin2rune, N11n_none, 0x20},
132     {"ISO8859-1", XlcGL, init_latin6tab, latin2rune, N11n_none, 0x20},
133     {"ISO8859-1", XlcGR, init_latin6tab, latin2rune, N11n_none, 0x20},
134     {"ISO8859-1", XlcGL, init_latin7tab, latin2rune, N11n_none, 0x20},
135     {"ISO8859-1", XlcGR, init_latin7tab, latin2rune, N11n_none, 0x20},
136     {"ISO8859-1", XlcGL, init_latin8tab, latin2rune, N11n_none, 0x20},
137     {"ISO8859-1", XlcGR, init_latin8tab, latin2rune, N11n_none, 0x20},
138     {"ISO8859-1", XlcGL, init_latin9tab, latin2rune, N11n_none, 0x20},
139     {"ISO8859-1", XlcGR, init_latin9tab, latin2rune, N11n_none, 0x20},
140     {"JISX0201.1976-0", XlcGL, init_jis0201tab, jis02012rune, N11n_none, 0x20},
141     {"JISX0201.1976-0", XlcGR, init_jis0201tab, jis02012rune, N11n_none, 0x20},
142     {"JISX0208.1983-0", XlcGL, init_jis0208tab, jis02082rune, N11n_ja, 0x2222},
143     {"JISX0208.1983-0", XlcGR, init_jis0208tab, jis02082rune, N11n_ja, 0x2222},
144     {"KSC5601.1987-0", XlcGL, init_ksc5601tab, ksc2rune, N11n_ko, 0x2160},
145     {"KSC5601.1987-0", XlcGR, init_ksc5601tab, ksc2rune, N11n_ko, 0x2160},
146     {"GB2312.1980-0", XlcGL, init_gb2312tab, gb2rune, N11n_zh, 0x2175},
147     {"GB2312.1980-0", XlcGR, init_gb2312tab, gb2rune, N11n_zh, 0x2175},
148 };
149
150
151 static void
152 set_latin_nop(table, default_val)
153 long    *table;
154 long    default_val;
155 {
156     register int i;
157     for(i = 0; i < 0x1fff; i++)
158         table[i] = default_val;
159     return;
160 }
161
162 static void
163 set_latin_tab(fptr, table, fb_default)
164 FILE    *fptr;
165 long    *table;
166 long    fb_default;
167 {
168     int         i = 0;
169     int         j = 0;
170     int         rv = 0;
171     long        value;
172
173     for(i = 0; i < NRUNE; i++)
174         table[i] = -1;
175     while((rv = fscanf(fptr, "%lx", (long unsigned *) &value)) != EOF) {
176         if(rv != 0 && value >= 0) {
177             table[value] = j++;
178         } else {
179             set_latin_nop(table, fb_default);
180             return;
181         }
182     }
183 }
184
185 extern int _fallcResolveI18NPath();
186 #define TBL_DATA_DIR    "tbl_data"
187
188 static void
189 init_latin1tab(tbl, fb_default)
190 long    *tbl;
191 long    fb_default;
192 {
193     FILE        *fp = NULL;
194     char        dirname[BUFSIZE];
195     char        filename[BUFSIZE];
196     char        *p, *q;
197
198     _fallcResolveI18NPath(dirname);
199     p = dirname;
200     while(p) {
201         q = strchr(p, ':');
202         if(q) {
203             *q = '\0';
204         }
205         sprintf(filename, "%s/%s/%s", p, TBL_DATA_DIR, tab8859_1);
206         fp = fopen(filename, "r");
207         if(fp) {
208             set_latin_tab(fp, tbl, fb_default);
209             fclose(fp);
210             return;
211         }
212         if(q) {
213             p = q + 1;
214         } else {
215             p = q;
216         }
217     }
218     if(!fp) {
219         set_latin_nop(tbl, fb_default);
220     }
221 }
222
223 static void
224 init_latin2tab(tbl, fb_default)
225 long    *tbl;
226 long    fb_default;
227 {
228     FILE        *fp;
229     char        dirname[BUFSIZE];
230     char        filename[BUFSIZE];
231     char        *p, *q;
232
233     _fallcResolveI18NPath(dirname);
234     p = dirname;
235     while(p) {
236         q = strchr(p, ':');
237         if(q) {
238             *q = '\0';
239         }
240         sprintf(filename, "%s/%s/%s", p, TBL_DATA_DIR, tab8859_2);
241         fp = fopen(filename, "r");
242         if(fp) {
243             set_latin_tab(fp, tbl, fb_default);
244             fclose(fp);
245             return;
246         }
247         if(q) {
248             p = q + 1;
249         } else {
250             p = q;
251         }
252     }
253     if(!fp) {
254         set_latin_nop(tbl, fb_default);
255     }
256 }
257
258 static void
259 init_latin3tab(tbl, fb_default)
260 long    *tbl;
261 long    fb_default;
262 {
263     FILE        *fp;
264     char        dirname[BUFSIZE];
265     char        filename[BUFSIZE];
266     char        *p, *q;
267
268     _fallcResolveI18NPath(dirname);
269     p = dirname;
270     while(p) {
271         q = strchr(p, ':');
272         if(q) {
273             *q = '\0';
274         }
275         sprintf(filename, "%s/%s/%s", p, TBL_DATA_DIR, tab8859_3);
276         fp = fopen(filename, "r");
277         if(fp) {
278             set_latin_tab(fp, tbl, fb_default);
279             fclose(fp);
280             return;
281         }
282         if(q) {
283             p = q + 1;
284         } else {
285             p = q;
286         }
287     }
288     if(!fp) {
289         set_latin_nop(tbl, fb_default);
290     }
291 }
292
293 static void
294 init_latin4tab(tbl, fb_default)
295 long    *tbl;
296 long    fb_default;
297 {
298     FILE        *fp;
299     char        dirname[BUFSIZE];
300     char        filename[BUFSIZE];
301     char        *p, *q;
302
303     _fallcResolveI18NPath(dirname);
304     p = dirname;
305     while(p) {
306         q = strchr(p, ':');
307         if(q) {
308             *q = '\0';
309         }
310         sprintf(filename, "%s/%s/%s", p, TBL_DATA_DIR, tab8859_4);
311         fp = fopen(filename, "r");
312         if(fp) {
313             set_latin_tab(fp, tbl, fb_default);
314             fclose(fp);
315             return;
316         }
317         if(q) {
318             p = q + 1;
319         } else {
320             p = q;
321         }
322     }
323     if(!fp) {
324         set_latin_nop(tbl, fb_default);
325     }
326 }
327
328 static void
329 init_latin5tab(tbl, fb_default)
330 long    *tbl;
331 long    fb_default;
332 {
333     FILE        *fp;
334     char        dirname[BUFSIZE];
335     char        filename[BUFSIZE];
336     char        *p, *q;
337
338     _fallcResolveI18NPath(dirname);
339     p = dirname;
340     while(p) {
341         q = strchr(p, ':');
342         if(q) {
343             *q = '\0';
344         }
345         sprintf(filename, "%s/%s/%s", p, TBL_DATA_DIR, tab8859_5);
346         fp = fopen(filename, "r");
347         if(fp) {
348             set_latin_tab(fp, tbl, fb_default);
349             fclose(fp);
350             return;
351         }
352         if(q) {
353             p = q + 1;
354         } else {
355             p = q;
356         }
357     }
358     if(!fp) {
359         set_latin_nop(tbl, fb_default);
360     }
361 }
362
363 static void
364 init_latin6tab(tbl, fb_default)
365 long    *tbl;
366 long    fb_default;
367 {
368     FILE        *fp;
369     char        dirname[BUFSIZE];
370     char        filename[BUFSIZE];
371     char        *p, *q;
372
373     _fallcResolveI18NPath(dirname);
374     p = dirname;
375     while(p) {
376         q = strchr(p, ':');
377         if(q) {
378             *q = '\0';
379         }
380         sprintf(filename, "%s/%s/%s", p, TBL_DATA_DIR, tab8859_6);
381         fp = fopen(filename, "r");
382         if(fp) {
383             set_latin_tab(fp, tbl, fb_default);
384             fclose(fp);
385             return;
386         }
387         if(q) {
388             p = q + 1;
389         } else {
390             p = q;
391         }
392     }
393     if(!fp) {
394         set_latin_nop(tbl, fb_default);
395     }
396 }
397
398 static void
399 init_latin7tab(tbl, fb_default)
400 long    *tbl;
401 long    fb_default;
402 {
403     FILE        *fp;
404     char        dirname[BUFSIZE];
405     char        filename[BUFSIZE];
406     char        *p, *q;
407
408     _fallcResolveI18NPath(dirname);
409     p = dirname;
410     while(p) {
411         q = strchr(p, ':');
412         if(q) {
413             *q = '\0';
414         }
415         sprintf(filename, "%s/%s/%s", p, TBL_DATA_DIR, tab8859_7);
416         fp = fopen(filename, "r");
417         if(fp) {
418             set_latin_tab(fp, tbl, fb_default);
419             fclose(fp);
420             return;
421         }
422         if(q) {
423             p = q + 1;
424         } else {
425             p = q;
426         }
427     }
428     if(!fp) {
429         set_latin_nop(tbl, fb_default);
430     }
431 }
432
433 static void
434 init_latin8tab(tbl, fb_default)
435 long    *tbl;
436 long    fb_default;
437 {
438     FILE        *fp;
439     char        dirname[BUFSIZE];
440     char        filename[BUFSIZE];
441     char        *p, *q;
442
443     _fallcResolveI18NPath(dirname);
444     p = dirname;
445     while(p) {
446         q = strchr(p, ':');
447         if(q) {
448             *q = '\0';
449         }
450         sprintf(filename, "%s/%s/%s", p, TBL_DATA_DIR, tab8859_8);
451         fp = fopen(filename, "r");
452         if(fp) {
453             set_latin_tab(fp, tbl, fb_default);
454             fclose(fp);
455             return;
456         }
457         if(q) {
458             p = q + 1;
459         } else {
460             p = q;
461         }
462     }
463     if(!fp) {
464         set_latin_nop(tbl, fb_default);
465     }
466 }
467
468 static void
469 init_latin9tab(tbl, fb_default)
470 long    *tbl;
471 long    fb_default;
472 {
473     FILE        *fp;
474     char        dirname[BUFSIZE];
475     char        filename[BUFSIZE];
476     char        *p, *q;
477
478     _fallcResolveI18NPath(dirname);
479     p = dirname;
480     while(p) {
481         q = strchr(p, ':');
482         if(q) {
483             *q = '\0';
484         }
485         sprintf(filename, "%s/%s/%s", p, TBL_DATA_DIR, tab8859_9);
486         fp = fopen(filename, "r");
487         if(fp) {
488             set_latin_tab(fp, tbl, fb_default);
489             fclose(fp);
490             return;
491         }
492         if(q) {
493             p = q + 1;
494         } else {
495             p = q;
496         }
497     }
498     if(!fp) {
499         set_latin_nop(tbl, fb_default);
500     }
501 }
502
503 static void
504 init_jis0201tab(tbl, fb_default)
505 long    *tbl;
506 long    fb_default;
507 {
508         int i;
509         for(i = 0; i < NRUNE; i++)
510             tbl[i] = -1;
511 }
512
513 static void
514 set_cjk_nop(to_tbl, to_max, default_val)
515 long    **to_tbl;
516 long    default_val;
517 int     to_max;
518 {
519     register int i;
520     for(i = 0; i < to_max; i++)
521         (*to_tbl)[i] = default_val;
522     return;
523 }
524
525 static void
526 set_table(fptr, to_tbl, from_tbl, to_max, fb_default)
527 FILE    *fptr;
528 long    **to_tbl, *from_tbl;
529 int     to_max;
530 long    fb_default;
531 {
532     register int        i = 0;
533     int         j = 0;
534     int         rv = 0;
535     long        value;
536
537     for(i = 0; i < NRUNE; i++)
538         from_tbl[i] = -1;
539     while((rv = fscanf(fptr, "%lx", (long unsigned *) &value)) != EOF) {
540         if(rv != 0) {
541             (*to_tbl)[j++] = value;
542         } else {
543             set_cjk_nop(to_tbl, to_max, fb_default);
544             break;
545         }
546     }
547     for(i = 0; i < to_max; i++) {
548         if((value = (*to_tbl)[i]) != -1){
549             from_tbl[abs(value)] = i;
550         }
551     }
552 }
553
554
555         
556 static void
557 init_jis0208tab(tbl, fb_default)
558 long    *tbl;
559 long    fb_default;
560 {
561     FILE        *fp;
562     char        dirname[BUFSIZE];
563     char        filename[BUFSIZE];
564     char        *p, *q;
565
566     if((tabkuten = (long *)Xmalloc(KUTENMAX * sizeof(long))) == NULL) {
567         return;
568     }
569     _fallcResolveI18NPath(dirname);
570     p = dirname;
571     while(p) {
572         q = strchr(p, ':');
573         if(q) {
574             *q = '\0';
575         }
576         sprintf(filename, "%s/%s/%s", p, TBL_DATA_DIR, jis0208);
577         fp = fopen(filename, "r");
578         if(fp) {
579             set_table(fp, &tabkuten, tbl, KUTENMAX, fb_default);
580             fclose(fp);
581             return;
582         }
583         if(q) {
584             p = q + 1;
585         } else {
586             p = q;
587         }
588     }
589     if(!fp) {
590         set_cjk_nop(&tabkuten, KUTENMAX, fb_default);
591     }
592 }
593
594 static void
595 init_ksc5601tab(tbl, fb_default)
596 long    *tbl;
597 long    fb_default;
598 {
599     FILE        *fp;
600     char        dirname[BUFSIZE];
601     char        filename[BUFSIZE];
602     char        *p, *q;
603
604     if((tabksc5601 = (long *)Xmalloc(KSCMAX * sizeof(long))) == NULL) {
605         return;
606     }
607     _fallcResolveI18NPath(dirname);
608     p = dirname;
609     while(p) {
610         q = strchr(p, ':');
611         if(q) {
612             *q = '\0';
613         }
614         sprintf(filename, "%s/%s/%s", p, TBL_DATA_DIR, ksc5601);
615         fp = fopen(filename, "r");
616         if(fp) {
617             set_table(fp, &tabksc5601, tbl, KSCMAX, fb_default);
618             fclose(fp);
619             return;
620         }
621         if(q) {
622             p = q + 1;
623         } else {
624             p = q;
625         }
626     }
627     if(!fp) {
628         set_cjk_nop(&tabksc5601, KSCMAX, fb_default);
629     }
630 }
631
632 static void
633 init_gb2312tab(tbl, fb_default)
634 long    *tbl;
635 long    fb_default;
636 {
637     FILE        *fp;
638     char        dirname[BUFSIZE];
639     char        filename[BUFSIZE];
640     char        *p, *q;
641
642     if((tabgb = (long *)Xmalloc(GBMAX * sizeof(long))) == NULL) {
643         return;
644     }
645     _fallcResolveI18NPath(dirname);
646     p = dirname;
647     while(p) {
648         q = strchr(p, ':');
649         if(q) {
650             *q = '\0';
651         }
652         sprintf(filename, "%s/%s/%s", p, TBL_DATA_DIR, gb2312);
653         fp = fopen(filename, "r");
654         if(fp) {
655             set_table(fp, &tabgb, tbl, GBMAX, fb_default);
656             fclose(fp);
657             return;
658         }
659         if(q) {
660             p = q + 1;
661         } else {
662             p = q;
663         }
664     }
665     if(!fp) {
666         set_cjk_nop(&tabgb, GBMAX, fb_default);
667     }
668 }
669
670 static UtfData
671 make_entry()
672 {
673     UtfData tmp = (UtfData)Xmalloc(sizeof(UtfDataRec));
674     bzero(tmp, sizeof(UtfDataRec));
675     return tmp;
676 }
677
678 static int      once = 0;
679 static int
680 _XlcInitUTFInfo(lcd)
681 XLCd    lcd;
682 {
683     if(!once) {
684         int     i;
685         CodeSet *codeset_list = XLC_GENERIC(lcd, codeset_list);
686         int     codeset_num = XLC_GENERIC(lcd, codeset_num);
687         UtfData pdata;
688
689         if(!utfdata_list) {
690             utfdata_list = make_entry();
691         }
692         pdata = utfdata_list;
693         for(i=0; i < codeset_num; i++) {
694             XlcCharSet  charset = *codeset_list[i]->charset_list;
695             while(pdata->next) {
696                 if(charset == pdata->charset) {
697                     break;
698                 }
699                 pdata = pdata->next;
700             }
701             if(pdata->next) {
702                 continue;
703             } else {
704                 int j;
705                 for(j = 0; j < MAX_UTF_CHARSET; j++) {
706                     if(_fallcCompareISOLatin1(charset->encoding_name, default_utf_data[j].name) ||
707                        charset->side != default_utf_data[j].side) {
708                         continue;
709                     } else {
710                         pdata->initialize = default_utf_data[j].initialize;
711                         pdata->fromtbl = (long *)Xmalloc(NRUNE * sizeof(long));
712                         (*pdata->initialize)(pdata->fromtbl, default_utf_data[j].fallback_value);
713                         pdata->already_init = True;
714                         pdata->charset = charset;
715                         pdata->cstorune = default_utf_data[j].cstorune;
716                         pdata->type = default_utf_data[j].type;
717                         pdata->next = make_entry();
718                         break;
719                     }
720                 }
721             }
722         }
723         once = 1;
724     }
725     return 1;
726 }
727
728 static int
729 utftocs(conv, from, from_left, to, to_left, args, num_args)
730     XlcConv     conv;
731     char        **from;
732     int         *from_left;
733     char        **to;
734     int         *to_left;
735     XPointer    *args;
736     int         num_args;
737 {
738     char        *utfptr;
739     char        *bufptr;
740     int         utf_len, buf_len;
741     long        l;
742     XlcCharSet  tmpcharset = (XlcCharSet)NULL;
743     UtfData     pdata = utfdata_list;
744
745     if (from == NULL || *from == NULL)
746         return 0;
747
748     utfptr = *from;
749     bufptr = *to;
750     utf_len = *from_left;
751     buf_len = *to_left;
752
753     while(utf_len > 0 && buf_len > 0) {
754         char *p = utfptr;
755         if((l = getutfrune(&p, &utf_len)) == -2) {
756             return -1;
757         } else {
758             while(pdata->next) {
759                 long    r;
760                 long    *tbl;
761
762                 tbl = pdata->fromtbl;
763                 tbl += l;
764                 if((r = *tbl) == -1) {
765                     if(tmpcharset) {
766                             goto end;
767                     } else {
768                         pdata = pdata->next;
769                         continue;
770                     }
771                 } else {
772                     utfptr = p;
773                     if(!tmpcharset) tmpcharset = pdata->charset;
774                 }
775                 if(r < 128) {
776                     *bufptr++ = r;
777                     buf_len--;
778                 } else {
779                     switch(pdata->type) {
780                         case N11n_ja:
781                             *bufptr++ = (r/100 + ' ');
782                             *bufptr++ = (r%100 + ' ');
783                             break;
784                         case N11n_ko:
785                             *bufptr++ = (r/94 + 0x21);
786                             *bufptr++ = (r%94 + 0x21);
787                             break;
788                         case N11n_zh:
789                             *bufptr++ = 0x20 + (r/100);
790                             *bufptr++ = 0x20 + (r%100);
791                             break;
792                         default:
793                             break;
794                     }
795                     buf_len -= 2;
796                 }
797                 break;
798             }
799             if(!tmpcharset) return (-1); /* Unknown Codepoint */
800         }
801     }
802 end:
803     if((num_args > 0) && tmpcharset)
804         *((XlcCharSet *) args[0]) = tmpcharset;
805
806     *from_left -= utfptr - *from;
807     *from = utfptr;
808
809     *to_left -= bufptr - *to;
810     *to = bufptr;
811
812     return 0;
813 }
814
815 static int
816 utf1tocs(conv, from, from_left, to, to_left, args, num_args)
817     XlcConv     conv;
818     char        **from;
819     int         *from_left;
820     char        **to;
821     int         *to_left;
822     XPointer    *args;
823     int         num_args;
824 {
825     char        **ptr = NULL;
826     char        char_ptr[UTFmax];
827     int         i = 0;
828     unsigned long       dummy = (unsigned long)0;
829
830     if (from == NULL || *from == NULL)
831         return utftocs(conv, from, from_left, to, to_left, args, num_args);
832
833     ptr = from;
834     for(i = 0; i < UTFmax; char_ptr[i++] = *(*ptr)++);
835     i=0;
836     while(our_mbtowc(&dummy, (char*)&char_ptr[0], i) <= 0)
837         i++;
838     utftocs(conv, from, &i, to, to_left, args, num_args);
839 }
840
841 static int
842 ucstocs(conv, from, from_left, to, to_left, args, num_args)
843     XlcConv     conv;
844     XPointer    *from;
845     int         *from_left;
846     char        **to;
847     int         *to_left;
848     XPointer    *args;
849     int         num_args;
850 {
851     wchar_t     *ucsptr;
852     char        *bufptr;
853     int         ucs_len, buf_len;
854     XlcCharSet  tmpcharset = (XlcCharSet)NULL;
855     UtfData     pdata = utfdata_list;
856
857     if (from == NULL || *from == NULL)
858         return 0;
859
860     ucsptr = (wchar_t *)*from;
861     bufptr = *to;
862     ucs_len = *from_left;
863     buf_len = *to_left;
864
865     while(ucs_len > 0 && buf_len > 0) {
866             while(pdata->next) {
867                 long    r;
868                 long    *tbl;
869
870                 tbl = pdata->fromtbl;
871                 tbl += *ucsptr;
872                 if((r = *tbl) == -1) {
873                     if(tmpcharset) {
874                             goto end;
875                     } else {
876                         pdata = pdata->next;
877                         continue;
878                     }
879                 } else {
880                     if(!tmpcharset) tmpcharset = pdata->charset;
881                 }
882                 ucsptr++;
883                 if(r < 128) {
884                     *bufptr++ = r;
885                     ucs_len--;
886                     buf_len--;
887                 } else {
888                     switch(pdata->type) {
889                         case N11n_ja:
890                             *bufptr++ = (r/100 + ' ');
891                             *bufptr++ = (r%100 + ' ');
892                             break;
893                         case N11n_ko:
894                             *bufptr++ = (r/94 + 0x21);
895                             *bufptr++ = (r%94 + 0x21);
896                             break;
897                         case N11n_zh:
898                             *bufptr++ = 0x20 + (r/100);
899                             *bufptr++ = 0x20 + (r%100);
900                             break;
901                         default:
902                             break;
903                     }
904                     ucs_len--;
905                     buf_len -= 2;
906                 }
907                 break;
908             }
909             if(!tmpcharset) return (-1); /* Unknown Codepoint */
910     }
911 end:
912     if((num_args > 0) && tmpcharset)
913         *((XlcCharSet *) args[0]) = tmpcharset;
914
915     *from_left -= ucsptr - (wchar_t *)*from;
916     *from = (XPointer)ucsptr;
917
918     *to_left -= bufptr - *to;
919     *to = bufptr;
920
921     return 0;
922 }
923
924 static long
925 #if NeedFunctionPrototypes
926 getutfrune(char **read_from, int *from_len)
927 #else
928 getutfrune(read_from, from_len)
929 char **read_from;
930 int *from_len;
931 #endif
932 {
933         int c, i;
934         char str[UTFmax]; /* MB_LEN_MAX really */
935         unsigned long l;
936         int n;
937
938         str[0] = '\0';
939         for(i = 0; i <= UTFmax;) {
940                 c = **read_from;
941                 (*read_from)++;
942                 str[i++] = c;
943                 n = our_mbtowc(&l, str, i);
944                 if(n == -1)
945                         return(-2);
946                 if(n > 0) {
947                         *from_len -= n;
948                         return(l);
949                 }
950         }
951         return(-2);
952 }
953
954 static
955 cstoutf(conv, from, from_left, to, to_left, args, num_args)
956     XlcConv conv;
957     char **from;
958     int *from_left;
959     char **to;
960     int *to_left;
961     XPointer *args;
962     int num_args;
963 {
964     XlcCharSet charset;
965     char *csptr, *utfptr;
966     int csstr_len, utf_len;
967     int               cmp_len = 0;
968     void        (*putrune)(
969 #if NeedFunctionPrototypes
970                             unsigned char c,
971                             Rune *r
972 #endif
973                            ) = NULL;
974     Rune        r = (Rune)0;
975     UtfData     pdata = utfdata_list;
976
977     if (from == NULL || *from == NULL)
978         return 0;
979     
980     if (num_args < 1)
981         return -1;
982
983     csptr = *from;
984     utfptr = *to;
985     csstr_len = *from_left;
986     utf_len = *to_left;
987
988     charset = (XlcCharSet)args[0];
989     cmp_len = strchr(charset->name, ':') - charset->name;
990     while(pdata->next) {
991         if(!_fallcNCompareISOLatin1(charset->name, pdata->charset->name, cmp_len)) {
992             putrune = pdata->cstorune;
993             break;
994         } else {
995             pdata = pdata->next;
996         }
997     }
998     if(!putrune)
999         return -1;
1000
1001     while(csstr_len-- > 0 && utf_len > 0) {
1002         (*putrune)(*csptr++, &r);
1003         if(!r) {
1004             continue;
1005         }
1006         our_wctomb(r, &utfptr, &utf_len);
1007         r = 0;
1008     }
1009  
1010     *from_left -= csptr - *from;
1011     *from = csptr;
1012  
1013     *to_left -= utfptr - *to;
1014     *to = utfptr;
1015  
1016     return 0;
1017 }
1018
1019 static
1020 cstoucs(conv, from, from_left, to, to_left, args, num_args)
1021     XlcConv conv;
1022     char **from;
1023     int *from_left;
1024     XPointer *to;
1025     int *to_left;
1026     XPointer *args;
1027     int num_args;
1028 {
1029     XlcCharSet charset;
1030     char *csptr;
1031     wchar_t *ucsptr;
1032     int csstr_len, ucs_len;
1033     int               cmp_len = 0;
1034     void        (*putrune)(
1035 #if NeedFunctionPrototypes
1036                             unsigned char c,
1037                             Rune *r
1038 #endif
1039                            ) = NULL;
1040     Rune        r = (Rune)0;
1041     UtfData     pdata = utfdata_list;
1042
1043     if (from == NULL || *from == NULL)
1044         return 0;
1045     
1046     if (num_args < 1)
1047         return -1;
1048
1049     csptr = *from;
1050     ucsptr = (wchar_t *)*to;
1051     csstr_len = *from_left;
1052     ucs_len = *to_left;
1053     charset = (XlcCharSet)args[0];
1054     cmp_len = strchr(charset->name, ':') - charset->name;
1055
1056     while(pdata->next) {
1057         if(!_fallcNCompareISOLatin1(charset->name, pdata->charset->name, cmp_len)) {
1058             putrune = pdata->cstorune;
1059             break;
1060         } else {
1061             pdata = pdata->next;
1062         }
1063     }
1064     if(!putrune)
1065         return -1;
1066
1067     while(csstr_len-- > 0 && ucs_len > 0) {
1068         (*putrune)(*csptr++, &r);
1069         if(!r) {
1070             continue;
1071         }
1072         *ucsptr = (long)r;
1073         ucsptr++;
1074         ucs_len--;
1075         r = 0;
1076     }
1077  
1078     *from_left -= csptr - *from;
1079     *from = csptr;
1080  
1081     *to_left -= ucsptr - (wchar_t *)*to;
1082     *to = (XPointer)ucsptr;
1083  
1084     return 0;
1085 }
1086
1087 static void
1088 #if NeedFunctionPrototypes
1089 our_wctomb(Rune r, char **utfptr, int *utf_len)
1090 #else
1091 our_wctomb(r, utfptr, utf_len)
1092 Rune r;
1093 char **utfptr;
1094 int *utf_len;
1095 #endif
1096 {
1097         long l = (long)r;
1098
1099         if(!utfptr || !*utfptr)
1100                 return;               /* no shift states */
1101         if(l & ~Wchar2) {
1102                 if(l & ~Wchar4) {
1103                         if(l & ~Wchar5) {
1104                                 /* 6 bytes */
1105                                 *(*utfptr)++ = T6 | ((l >> 5*Bitx) & Mask6);
1106                                 *(*utfptr)++ = Tx | ((l >> 4*Bitx) & Maskx);
1107                                 *(*utfptr)++  = Tx | ((l >> 3*Bitx) & Maskx);
1108                                 *(*utfptr)++  = Tx | ((l >> 2*Bitx) & Maskx);
1109                                 *(*utfptr)++  = Tx | ((l >> 1*Bitx) & Maskx);
1110                                 *(*utfptr)++  = Tx |  (l & Maskx);
1111                                 *utf_len -= 6;
1112                                 return;
1113                         }
1114                         /* 5 bytes */
1115                          *(*utfptr)++ = T5 |  (l >> 4*Bitx);
1116                          *(*utfptr)++ = Tx | ((l >> 3*Bitx) & Maskx);
1117                          *(*utfptr)++ = Tx | ((l >> 2*Bitx) & Maskx);
1118                          *(*utfptr)++ = Tx | ((l >> 1*Bitx) & Maskx);
1119                          *(*utfptr)++ = Tx |  (l & Maskx);
1120                          *utf_len -= 5;
1121                          return;
1122                 }
1123                 if(l & ~Wchar3) {
1124                         /* 4 bytes */
1125                          *(*utfptr)++ = T4 |  (l >> 3*Bitx);
1126                          *(*utfptr)++ = Tx | ((l >> 2*Bitx) & Maskx);
1127                          *(*utfptr)++ = Tx | ((l >> 1*Bitx) & Maskx);
1128                          *(*utfptr)++ = Tx |  (l & Maskx);
1129                          *utf_len -= 4;
1130                          return;
1131                 }
1132                 /* 3 bytes */
1133                  *(*utfptr)++ = T3 |  (l >> 2*Bitx);
1134                  *(*utfptr)++ = Tx | ((l >> 1*Bitx) & Maskx);
1135                  *(*utfptr)++ = Tx |  (l & Maskx);
1136                  *utf_len -= 3;
1137                  return;
1138         }
1139         if(l & ~Wchar1) {
1140                 /* 2 bytes */
1141                  *(*utfptr)++ = T2 | (l >> 1*Bitx);
1142                  *(*utfptr)++ = Tx | (l & Maskx);
1143                  *utf_len -= 2;
1144                  return;
1145         }
1146         /* 1 byte */
1147          *(*utfptr)++ = T1 | l;
1148          *utf_len -= 1;
1149          return;
1150 }
1151
1152 static void
1153 #if NeedFunctionPrototypes
1154 latin2rune(unsigned char c, Rune *r)
1155 #else
1156 latin2rune(c, r)
1157 unsigned char c;
1158 Rune *r;
1159 #endif
1160 {
1161         *r = (Rune)c;
1162         return;
1163 }
1164
1165 static void
1166 #if NeedFunctionPrototypes
1167 ksc2rune(unsigned char c, Rune *r)
1168 #else
1169 ksc2rune(c, r)
1170 unsigned char c;
1171 Rune *r;
1172 #endif
1173 {
1174         static enum { init, cs1last} state = init;
1175         static int korean646 = 1; /* fixed to 1 for now. */
1176         static int lastc;
1177         unsigned char   ch = (c|0x80); /* XXX */
1178         int n;
1179         long l;
1180
1181         switch(state)
1182         {
1183         case init:
1184                 if (ch < 128){
1185                         if(korean646 && (ch=='\\')){
1186                                 emit(0x20A9);
1187                         } else {
1188                                 emit(ch);
1189                         }
1190                 }else{
1191                         lastc = ch;
1192                         state = cs1last;
1193                 }
1194                 return;
1195         
1196         case cs1last: /* 2nd byte of codeset 1 (KSC 5601) */
1197                 n = ((lastc&0x7f)-33)*94 + (ch&0x7f)-33;
1198                 if((l = tabksc5601[n]) == 0){
1199                     emit(BADMAP);
1200                 } else {
1201                         emit(l);
1202                 }
1203                 state = init;
1204                 return;
1205         }
1206 }
1207
1208 static void
1209 #if NeedFunctionPrototypes
1210 jis02012rune(unsigned char c, Rune *r)
1211 #else
1212 jis02012rune(c, r)
1213 unsigned char c;
1214 Rune *r;
1215 #endif
1216 {
1217 /* To Be Implemented */
1218 }
1219
1220 static void
1221 #if NeedFunctionPrototypes
1222 gb2rune(unsigned char c, Rune *r)
1223 #else
1224 gb2rune(c, r)
1225 unsigned char c;
1226 Rune *r;
1227 #endif
1228 {
1229         static enum { state0, state1 } state = state0;
1230         static int lastc;
1231         long n, ch;
1232         unsigned char   ch1 = (c|0x80); /* XXX */
1233
1234 again:
1235         switch(state)
1236         {
1237         case state0:    /* idle state */
1238                 if(ch1 >= 0xA1){
1239                         lastc = ch1;
1240                         state = state1;
1241                         return;
1242                 }
1243                 emit(ch1);
1244                 return;
1245
1246         case state1:    /* seen a font spec */
1247                 if(ch1 >= 0xA1)
1248                         n = (lastc-0xA0)*100 + (ch1-0xA0);
1249                 else {
1250                         emit(BADMAP);
1251                         state = state0;
1252                         return;
1253                 }
1254                 ch = tabgb[n];
1255                 if(ch < 0){
1256                         emit(BADMAP);
1257                 } else
1258                         emit(ch);
1259                 state = state0;
1260         }
1261 }
1262
1263 static void
1264 #if NeedFunctionPrototypes
1265 jis02082rune(unsigned char c, Rune *r)
1266 #else
1267 jis02082rune(c, r)
1268 unsigned char c;
1269 Rune *r;
1270 #endif
1271 {
1272         static enum { state0, state1} state = state0;
1273         static int lastc;
1274         unsigned char   ch = (c|0x80); /* XXX */
1275         int n;
1276         long l;
1277
1278 again:
1279         switch(state)
1280         {
1281         case state0:    /* idle state */
1282                 lastc = ch;
1283                 state = state1;
1284                 return;
1285
1286         case state1:    /* two part char */
1287                 if((lastc&0x80) != (ch&0x80)){
1288                         emit(lastc);
1289                         state = state0;
1290                         goto again;
1291                 }
1292                 if(CANS2J(lastc, ch)){
1293                         int h = lastc, l = ch;
1294                         S2J(h, l);
1295                         n = h*100 + l - 3232;
1296                 } else
1297                         n = (lastc&0x7F)*100 + (ch&0x7f) - 3232; /* kuten */
1298                 if((l = tabkuten[n]) == -1){
1299                         emit(BADMAP);
1300                 } else {          
1301                         if(l < 0){
1302                                 l = -l;
1303                         }
1304                         emit(l);
1305                 }        
1306                 state = state0;
1307         }
1308 }
1309
1310 static int
1311 #if NeedFunctionPrototypes
1312 our_mbtowc(unsigned long *p, char *s, size_t n)
1313 #else
1314 our_mbtowc(p, s, n)
1315 unsigned long *p;
1316 char *s;
1317 size_t n;
1318 #endif
1319 {
1320         unsigned char *us;
1321         int c0, c1, c2, c3, c4, c5;
1322         unsigned long wc;
1323
1324         if(s == 0)
1325                 return 0;               /* no shift states */
1326
1327         if(n < 1)
1328                 goto badlen;
1329         us = (unsigned char*)s;
1330         c0 = us[0];
1331         if(c0 >= T3) {
1332                 if(n < 3)
1333                         goto badlen;
1334                 c1 = us[1] ^ Tx;
1335                 c2 = us[2] ^ Tx;
1336                 if((c1|c2) & T2) {
1337                         goto bad;
1338                 }
1339                 if(c0 >= T5) {
1340                         if(n < 5)
1341                                 goto badlen;
1342                         c3 = us[3] ^ Tx;
1343                         c4 = us[4] ^ Tx;
1344                         if((c3|c4) & T2) {
1345                                 goto bad;
1346                         }
1347                         if(c0 >= T6) {
1348                                 /* 6 bytes */
1349                                 if(n < 6)
1350                                         goto badlen;
1351                                 c5 = us[5] ^ Tx;
1352                                 if(c5 & T2) {
1353                                         goto bad;
1354                                 }
1355                                 wc = ((((((((((c0 & Mask6) << Bitx) |
1356                                         c1) << Bitx) | c2) << Bitx) |
1357                                         c3) << Bitx) | c4) << Bitx) | c5;
1358                                 if(wc <= Wchar5) {
1359                                         goto bad;
1360                                 }
1361                                 *p = wc;
1362                                 return 6;
1363                         }
1364                         /* 5 bytes */
1365                         wc = ((((((((c0 & Mask5) << Bitx) |
1366                                 c1) << Bitx) | c2) << Bitx) |
1367                                 c3) << Bitx) | c4;
1368                         if(wc <= Wchar4) {
1369                                 goto bad;
1370                         }
1371                         *p = wc;
1372                         return 5;
1373                 }
1374                 if(c0 >= T4) {
1375                         /* 4 bytes */
1376                         if(n < 4)
1377                                 goto badlen;
1378                         c3 = us[3] ^ Tx;
1379                         if(c3 & T2) {
1380                                 goto bad;
1381                         }
1382                         wc = ((((((c0 & Mask4) << Bitx) |
1383                                 c1) << Bitx) | c2) << Bitx) |
1384                                 c3;
1385                         if(wc <= Wchar3) {
1386                                 goto bad;
1387                         }
1388                         *p = wc;
1389                         return 4;
1390                 }
1391                 /* 3 bytes */
1392                 wc = ((((c0 & Mask3) << Bitx) |
1393                         c1) << Bitx) | c2;
1394                 if(wc <= Wchar2) {
1395                         goto bad;
1396                 }
1397                 *p = wc;
1398                 return 3;
1399         }
1400         if(c0 >= T2) {
1401                 /* 2 bytes */
1402                 if(n < 2)
1403                         goto badlen;
1404                 c1 = us[1] ^ Tx;
1405                 if(c1 & T2) {
1406                         goto bad;
1407                 }
1408                 wc = ((c0 & Mask2) << Bitx) |
1409                         c1;
1410                 if(wc <= Wchar1) {
1411                         goto bad;
1412                 }
1413                 *p = wc;
1414                 return 2;
1415         }
1416         /* 1 byte */
1417         if(c0 >= Tx) {
1418                 goto bad;
1419         }
1420         *p = c0;
1421         return 1;
1422
1423 bad:
1424         errno = EILSEQ;
1425         return -1;
1426 badlen:
1427         return -2;
1428 }
1429
1430 static void
1431 close_converter(conv)
1432     XlcConv conv;
1433 {
1434     Xfree((char *) conv);
1435 }
1436
1437 static XlcConv
1438 create_conv(lcd, methods)
1439     XLCd        lcd;
1440     XlcConvMethods      methods;
1441 {
1442     XlcConv conv;
1443
1444     conv = (XlcConv) Xmalloc(sizeof(XlcConvRec));
1445     if (conv == (XlcConv) NULL)
1446         return (XlcConv) NULL;
1447
1448     conv->methods = methods;
1449
1450     conv->state = NULL;
1451     _XlcInitUTFInfo(lcd);
1452
1453     return conv;
1454
1455 err:
1456     close_converter(conv);
1457
1458     return (XlcConv) NULL;
1459 }
1460
1461 static XlcConvMethodsRec mbtocs_methods = {
1462     close_converter,
1463     utf1tocs,
1464     NULL
1465 };
1466
1467 static XlcConv
1468 open_mbtocs(from_lcd, from, to_lcd, to)
1469     XLCd from_lcd;
1470     char *from;
1471     XLCd to_lcd;
1472     char *to;
1473 {
1474     return create_conv(from_lcd, &mbtocs_methods);
1475 }
1476
1477 static XlcConvMethodsRec mbstocs_methods = {
1478     close_converter,
1479     utftocs,
1480     NULL
1481 };
1482
1483 static XlcConv
1484 open_mbstocs(from_lcd, from, to_lcd, to)
1485     XLCd from_lcd;
1486     char *from;
1487     XLCd to_lcd;
1488     char *to;
1489 {
1490     return create_conv(from_lcd, &mbstocs_methods);
1491 }
1492
1493 static XlcConvMethodsRec wcstocs_methods = {
1494     close_converter,
1495     ucstocs,
1496     NULL
1497 };
1498
1499 static XlcConv
1500 open_wcstocs(from_lcd, from, to_lcd, to)
1501     XLCd from_lcd;
1502     char *from;
1503     XLCd to_lcd;
1504     char *to;
1505 {
1506     return create_conv(from_lcd, &wcstocs_methods);
1507 }
1508
1509 static XlcConvMethodsRec cstombs_methods = {
1510     close_converter,
1511     cstoutf,
1512     NULL
1513 };
1514
1515 static XlcConv
1516 open_cstombs(from_lcd, from, to_lcd, to)
1517     XLCd from_lcd;
1518     char *from;
1519     XLCd to_lcd;
1520     char *to;
1521 {
1522     return create_conv(from_lcd, &cstombs_methods);
1523 }
1524
1525 static XlcConvMethodsRec cstowcs_methods = {
1526     close_converter,
1527     cstoucs,
1528     NULL
1529 };
1530
1531 static XlcConv
1532 open_cstowcs(from_lcd, from, to_lcd, to)
1533     XLCd from_lcd;
1534     char *from;
1535     XLCd to_lcd;
1536     char *to;
1537 {
1538     return create_conv(from_lcd, &cstowcs_methods);
1539 }
1540
1541
1542 XLCd
1543 _fallcUtfLoader(name)
1544     char *name;
1545 {
1546     XLCd lcd;
1547
1548     lcd = _fallcCreateLC(name, _fallcGenericMethods);
1549     if (lcd == (XLCd) NULL)
1550         return lcd;
1551     
1552     if ((_fallcCompareISOLatin1(XLC_PUBLIC_PART(lcd)->codeset, "utf"))) {
1553         _fallcDestroyLC(lcd);
1554         return (XLCd) NULL;
1555     }
1556
1557     _fallcSetConverter(lcd, XlcNMultiByte, lcd, XlcNCharSet, open_mbstocs);
1558     _fallcSetConverter(lcd, XlcNWideChar, lcd, XlcNCharSet, open_wcstocs);
1559
1560     _fallcSetConverter(lcd, XlcNMultiByte, lcd, XlcNChar, open_mbtocs);
1561
1562     _fallcSetConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte, open_cstombs);
1563     _fallcSetConverter(lcd, XlcNCharSet, lcd, XlcNWideChar, open_cstowcs);
1564
1565     return lcd;
1566 }