04eecb543754f44b975412da618b16bbfb9ec4fa
[samba.git] / source3 / lib / kanji.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Kanji Extensions
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21    Adding for Japanese language by <fujita@ainix.isac.co.jp> 1994.9.5
22      and extend coding system to EUC/SJIS/JIS/HEX at 1994.10.11
23      and add all jis codes sequence type at 1995.8.16
24      Notes: Hexadecimal code by <ohki@gssm.otuka.tsukuba.ac.jp>
25 */
26
27 #define _KANJI_C_
28 #include "includes.h"
29
30 /*
31  * Function pointers that get overridden when multi-byte code pages
32  * are loaded.
33  */
34
35 char *(*multibyte_strchr)(char *, int ) = (char *(*)(char *, int )) strchr;
36 char *(*multibyte_strrchr)(char *, int ) = (char *(*)(char *, int )) strrchr;
37 char *(*multibyte_strstr)(char *, char *) = (char *(*)(char *, char *)) strstr;
38 char *(*multibyte_strtok)(char *, char *) = (char *(*)(char *, char *)) strtok;
39
40 /*
41  * Kanji is treated differently here due to historical accident of
42  * it being the first non-English codepage added to Samba.
43  * The define 'KANJI' is being overloaded to mean 'use kanji codepage
44  * by default' and also 'this is the filename-to-disk conversion 
45  * method to use'. This really should be removed and all control
46  * over this left in the smb.conf parameters 'client codepage'
47  * and 'coding system'.
48  */
49
50 #ifndef KANJI
51
52 /*
53  * Set the default conversion to be the functions in
54  * charcnv.c.
55  */
56
57 static int skip_non_multibyte_char(char);
58 static BOOL not_multibyte_char_1(char);
59
60 char *(*_dos_to_unix)(char *, BOOL) = dos2unix_format;
61 char *(*_unix_to_dos)(char *, BOOL) = unix2dos_format;
62 int (*_skip_multibyte_char)(char) = skip_non_multibyte_char;
63 BOOL (*is_multibyte_char_1)(char) = not_multibyte_char_1;
64
65 #else /* KANJI */
66
67 /*
68  * Set the default conversion to be the function
69  * sj_to_sj in this file.
70  */
71
72 static char *sj_to_sj(char *from, BOOL overwrite);
73 static int skip_kanji_multibyte_char(char);
74 static BOOL is_kanji_multibyte_char_1(char);
75
76 char *(*_dos_to_unix)(char *, BOOL) = sj_to_sj;
77 char *(*_unix_to_dos)(char *, BOOL) = sj_to_sj;
78 int (*_skip_multibyte_char)(char) = skip_kanji_multibyte_char;
79 int (*is_multibyte_char_1)(char) = is_kanji_multibyte_char_1;
80
81 #endif /* KANJI */
82
83 /* jis si/so sequence */
84 static char jis_kso = JIS_KSO;
85 static char jis_ksi = JIS_KSI;
86 static char hex_tag = HEXTAG;
87
88 /*******************************************************************
89   SHIFT JIS functions
90 ********************************************************************/
91 /*******************************************************************
92  search token from S1 separated any char of S2
93  S1 contains SHIFT JIS chars.
94 ********************************************************************/
95 static char *sj_strtok(char *s1, char *s2)
96 {
97     static char *s = NULL;
98     char *q;
99     if (!s1) {
100         if (!s) {
101             return NULL;
102         }
103         s1 = s;
104     }
105     for (q = s1; *s1; ) {
106         if (is_shift_jis (*s1)) {
107             s1 += 2;
108         } else if (is_kana (*s1)) {
109             s1++;
110         } else {
111             char *p = strchr (s2, *s1);
112             if (p) {
113                 if (s1 != q) {
114                     s = s1 + 1;
115                     *s1 = '\0';
116                     return q;
117                 }
118                 q = s1 + 1;
119             }
120             s1++;
121         }
122     }
123     s = NULL;
124     if (*q) {
125         return q;
126     }
127     return NULL;
128 }
129
130 /*******************************************************************
131  search string S2 from S1
132  S1 contains SHIFT JIS chars.
133 ********************************************************************/
134 static char *sj_strstr(char *s1, char *s2)
135 {
136     int len = strlen ((char *) s2);
137     if (!*s2) 
138         return (char *) s1;
139     for (;*s1;) {
140         if (*s1 == *s2) {
141             if (strncmp (s1, s2, len) == 0)
142                 return (char *) s1;
143         }
144         if (is_shift_jis (*s1)) {
145             s1 += 2;
146         } else {
147             s1++;
148         }
149     }
150     return 0;
151 }
152
153 /*******************************************************************
154  Search char C from beginning of S.
155  S contains SHIFT JIS chars.
156 ********************************************************************/
157 static char *sj_strchr (char *s, int c)
158 {
159     for (; *s; ) {
160         if (*s == c)
161             return (char *) s;
162         if (is_shift_jis (*s)) {
163             s += 2;
164         } else {
165             s++;
166         }
167     }
168     return 0;
169 }
170
171 /*******************************************************************
172  Search char C end of S.
173  S contains SHIFT JIS chars.
174 ********************************************************************/
175 static char *sj_strrchr(char *s, int c)
176 {
177     char *q;
178
179     for (q = 0; *s; ) {
180         if (*s == c) {
181             q = (char *) s;
182         }
183         if (is_shift_jis (*s)) {
184             s += 2;
185         } else {
186             s++;
187         }
188     }
189     return q;
190 }
191
192 /*******************************************************************
193  Kanji multibyte char skip function.
194 *******************************************************************/
195    
196 static int skip_kanji_multibyte_char(char c)
197 {
198   if(is_shift_jis(c)) {
199     return 2;
200   } else if (is_kana(c)) {
201     return 1;
202   }
203   return 0;
204 }
205
206 /*******************************************************************
207  Kanji multibyte char identification.
208 *******************************************************************/
209    
210 static BOOL is_kanji_multibyte_char_1(char c)
211 {
212   return is_shift_jis(c);
213 }
214
215 /*******************************************************************
216  The following functions are the only ones needed to do multibyte
217  support for Hangul, Big5 and Simplified Chinese. Most of the
218  real work for these codepages is done in the generic multibyte
219  functions. The only reason these functions are needed at all
220  is that the is_xxx(c) calls are really preprocessor macros.
221 ********************************************************************/
222
223 /*******************************************************************
224   Hangul (Korean - code page 949) function.
225 ********************************************************************/
226
227 static BOOL hangul_is_multibyte_char_1(char c)
228 {
229   return is_hangul(c);
230 }
231
232 /*******************************************************************
233   Big5 Traditional Chinese (code page 950) function.
234 ********************************************************************/
235
236 static BOOL big5_is_multibyte_char_1(char c)
237 {
238   return is_big5_c1(c);
239 }
240
241 /*******************************************************************
242   Simplified Chinese (code page 936) function.
243 ********************************************************************/
244
245 static BOOL simpch_is_multibyte_char_1(char c)
246 {
247   return is_simpch_c1(c);
248 }
249
250 /*******************************************************************
251   Generic multibyte functions - used by Hangul, Big5 and Simplified
252   Chinese codepages.
253 ********************************************************************/
254
255 /*******************************************************************
256  search token from S1 separated any char of S2
257  S1 contains generic multibyte chars.
258 ********************************************************************/
259
260 static char *generic_multibyte_strtok(char *s1, char *s2)
261 {
262     static char *s = NULL;
263     char *q;
264     if (!s1) {
265         if (!s) {
266             return NULL;
267         }
268         s1 = s;
269     }
270     for (q = s1; *s1; ) {
271         if ((*is_multibyte_char_1)(*s1)) {
272             s1 += 2;
273         } else {
274             char *p = strchr (s2, *s1);
275             if (p) {
276                 if (s1 != q) {
277                     s = s1 + 1;
278                     *s1 = '\0';
279                     return q;
280                 }
281                 q = s1 + 1;
282             }
283             s1++;
284         }
285     }
286     s = NULL;
287     if (*q) {
288         return q;
289     }
290     return NULL;
291 }
292
293 /*******************************************************************
294  search string S2 from S1
295  S1 contains generic multibyte chars.
296 ********************************************************************/
297
298 static char *generic_multibyte_strstr(char *s1, char *s2)
299 {
300     int len = strlen ((char *) s2);
301     if (!*s2)
302         return (char *) s1;
303     for (;*s1;) {
304         if (*s1 == *s2) {
305             if (strncmp (s1, s2, len) == 0)
306                 return (char *) s1;
307         }
308         if ((*is_multibyte_char_1)(*s1)) {
309             s1 += 2;
310         } else {
311             s1++;
312         }
313     }
314     return 0;
315 }
316
317 /*******************************************************************
318  Search char C from beginning of S.
319  S contains generic multibyte chars.
320 ********************************************************************/
321
322 static char *generic_multibyte_strchr(char *s, int c)
323 {
324     for (; *s; ) {
325         if (*s == c)
326             return (char *) s;
327         if ((*is_multibyte_char_1)(*s)) {
328             s += 2;
329         } else {
330             s++;
331         }
332     }
333     return 0;
334 }
335
336 /*******************************************************************
337  Search char C end of S.
338  S contains generic multibyte chars.
339 ********************************************************************/
340
341 static char *generic_multibyte_strrchr(char *s, int c)
342 {
343     char *q;
344  
345     for (q = 0; *s; ) {
346         if (*s == c) {
347             q = (char *) s;
348         }
349         if ((*is_multibyte_char_1)(*s)) {
350             s += 2;
351         } else {
352             s++;
353         }
354     }
355     return q;
356 }
357
358 /*******************************************************************
359  Generic multibyte char skip function.
360 *******************************************************************/
361
362 static int skip_generic_multibyte_char(char c)
363 {
364   if( (*is_multibyte_char_1)(c)) {
365     return 2;
366   }
367   return 0;
368 }
369
370 /*******************************************************************
371   Code conversion
372 ********************************************************************/
373 /* convesion buffer */
374 static char cvtbuf[1024];
375
376 /*******************************************************************
377   EUC <-> SJIS
378 ********************************************************************/
379 static int euc2sjis (int hi, int lo)
380 {
381     if (hi & 1)
382         return ((hi / 2 + (hi < 0xdf ? 0x31 : 0x71)) << 8) |
383             (lo - (lo >= 0xe0 ? 0x60 : 0x61));
384     else
385         return ((hi / 2 + (hi < 0xdf ? 0x30 : 0x70)) << 8) | (lo - 2);
386 }
387
388 static int sjis2euc (int hi, int lo)
389 {
390     if (lo >= 0x9f)
391         return ((hi * 2 - (hi >= 0xe0 ? 0xe0 : 0x60)) << 8) | (lo + 2);
392     else
393         return ((hi * 2 - (hi >= 0xe0 ? 0xe1 : 0x61)) << 8) |
394             (lo + (lo >= 0x7f ? 0x60 : 0x61));
395 }
396
397 /*******************************************************************
398  Convert FROM contain SHIFT JIS codes to EUC codes
399  return converted buffer
400 ********************************************************************/
401 static char *sj_to_euc(char *from, BOOL overwrite)
402 {
403     char *out;
404     char *save;
405
406     save = (char *) from;
407     for (out = cvtbuf; *from;) {
408         if (is_shift_jis (*from)) {
409             int code = sjis2euc ((int) from[0] & 0xff, (int) from[1] & 0xff);
410             *out++ = (code >> 8) & 0xff;
411             *out++ = code;
412             from += 2;
413         } else if (is_kana (*from)) {
414             *out++ = (char)euc_kana;
415             *out++ = *from++;
416         } else {
417             *out++ = *from++;
418         }
419     }
420     *out = 0;
421     if (overwrite) {
422         pstrcpy((char *) save, (char *) cvtbuf);
423         return (char *) save;
424     } else {
425         return cvtbuf;
426     }
427 }
428
429 /*******************************************************************
430  Convert FROM contain EUC codes to SHIFT JIS codes
431  return converted buffer
432 ********************************************************************/
433 static char *euc_to_sj(char *from, BOOL overwrite)
434 {
435     char *out;
436     char *save;
437
438     save = (char *) from;
439     for (out = cvtbuf; *from; ) {
440         if (is_euc (*from)) {
441             int code = euc2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff);
442             *out++ = (code >> 8) & 0xff;
443             *out++ = code;
444             from += 2;
445         } else if (is_euc_kana (*from)) {
446             *out++ = from[1];
447             from += 2;
448         } else {
449             *out++ = *from++;
450         }
451     }
452     *out = 0;
453     if (overwrite) {
454         pstrcpy(save, (char *) cvtbuf);
455         return save;
456     } else {
457         return cvtbuf;
458     }
459 }
460
461 /*******************************************************************
462   JIS7,JIS8,JUNET <-> SJIS
463 ********************************************************************/
464 static int sjis2jis(int hi, int lo)
465 {
466     if (lo >= 0x9f)
467         return ((hi * 2 - (hi >= 0xe0 ? 0x160 : 0xe0)) << 8) | (lo - 0x7e);
468     else
469         return ((hi * 2 - (hi >= 0xe0 ? 0x161 : 0xe1)) << 8) |
470             (lo - (lo >= 0x7f ? 0x20 : 0x1f));
471 }
472
473 static int jis2sjis(int hi, int lo)
474 {
475     if (hi & 1)
476         return ((hi / 2 + (hi < 0x5f ? 0x71 : 0xb1)) << 8) |
477             (lo + (lo >= 0x60 ? 0x20 : 0x1f));
478     else
479         return ((hi / 2 + (hi < 0x5f ? 0x70 : 0xb0)) << 8) | (lo + 0x7e);
480 }
481
482 /*******************************************************************
483  Convert FROM contain JIS codes to SHIFT JIS codes
484  return converted buffer
485 ********************************************************************/
486 static char *jis8_to_sj(char *from, BOOL overwrite)
487 {
488     char *out;
489     int shifted;
490     char *save;
491
492     shifted = _KJ_ROMAN;
493     save = (char *) from;
494     for (out = cvtbuf; *from;) {
495         if (is_esc (*from)) {
496             if (is_so1 (from[1]) && is_so2 (from[2])) {
497                 shifted = _KJ_KANJI;
498                 from += 3;
499             } else if (is_si1 (from[1]) && is_si2 (from[2])) {
500                 shifted = _KJ_ROMAN;
501                 from += 3;
502             } else {                    /* sequence error */
503                 goto normal;
504             }
505         } else {
506         normal:
507             switch (shifted) {
508             default:
509             case _KJ_ROMAN:
510                 *out++ = *from++;
511                 break;
512             case _KJ_KANJI:
513                 {
514                     int code = jis2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff);
515                     *out++ = (code >> 8) & 0xff;
516                     *out++ = code;
517                     from += 2;
518                 }
519                 break;
520             }
521         }
522     }
523     *out = 0;
524     if (overwrite) {
525         pstrcpy (save, (char *) cvtbuf);
526         return save;
527     } else {
528         return cvtbuf;
529     }
530 }
531
532 /*******************************************************************
533  Convert FROM contain SHIFT JIS codes to JIS codes
534  return converted buffer
535 ********************************************************************/
536 static char *sj_to_jis8(char *from, BOOL overwrite)
537 {
538     char *out;
539     int shifted;
540     char *save;
541
542     shifted = _KJ_ROMAN;
543     save = (char *) from;
544     for (out = cvtbuf; *from; ) {
545         if (is_shift_jis (*from)) {
546             int code;
547             switch (shifted) {
548             case _KJ_ROMAN:             /* to KANJI */
549                 *out++ = jis_esc;
550                 *out++ = jis_so1;
551                 *out++ = jis_kso;
552                 shifted = _KJ_KANJI;
553                 break;
554             }
555             code = sjis2jis ((int) from[0] & 0xff, (int) from[1] & 0xff);
556             *out++ = (code >> 8) & 0xff;
557             *out++ = code;
558             from += 2;
559         } else {
560             switch (shifted) {
561             case _KJ_KANJI:             /* to ROMAN/KANA */
562                 *out++ = jis_esc;
563                 *out++ = jis_si1;
564                 *out++ = jis_ksi;
565                 shifted = _KJ_ROMAN;
566                 break;
567             }
568             *out++ = *from++;
569         }
570     }
571     switch (shifted) {
572     case _KJ_KANJI:                     /* to ROMAN/KANA */
573         *out++ = jis_esc;
574         *out++ = jis_si1;
575         *out++ = jis_ksi;
576         shifted = _KJ_ROMAN;
577         break;
578     }
579     *out = 0;
580     if (overwrite) {
581         pstrcpy (save, (char *) cvtbuf);
582         return save;
583     } else {
584         return cvtbuf;
585     }
586 }
587
588 /*******************************************************************
589  Convert FROM contain 7 bits JIS codes to SHIFT JIS codes
590  return converted buffer
591 ********************************************************************/
592 static char *jis7_to_sj(char *from, BOOL overwrite)
593 {
594     char *out;
595     int shifted;
596     char *save;
597
598     shifted = _KJ_ROMAN;
599     save = (char *) from;
600     for (out = cvtbuf; *from;) {
601         if (is_esc (*from)) {
602             if (is_so1 (from[1]) && is_so2 (from[2])) {
603                 shifted = _KJ_KANJI;
604                 from += 3;
605             } else if (is_si1 (from[1]) && is_si2 (from[2])) {
606                 shifted = _KJ_ROMAN;
607                 from += 3;
608             } else {                    /* sequence error */
609                 goto normal;
610             }
611         } else if (is_so (*from)) {
612             shifted = _KJ_KANA;         /* to KANA */
613             from++;
614         } else if (is_si (*from)) {
615             shifted = _KJ_ROMAN;        /* to ROMAN */
616             from++;
617         } else {
618         normal:
619             switch (shifted) {
620             default:
621             case _KJ_ROMAN:
622                 *out++ = *from++;
623                 break;
624             case _KJ_KANJI:
625                 {
626                     int code = jis2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff);
627                     *out++ = (code >> 8) & 0xff;
628                     *out++ = code;
629                     from += 2;
630                 }
631                 break;
632             case _KJ_KANA:
633                 *out++ = ((int) from[0]) + 0x80;
634                 break;
635             }
636         }
637     }
638     *out = 0;
639     if (overwrite) {
640         pstrcpy (save, (char *) cvtbuf);
641         return save;
642     } else {
643         return cvtbuf;
644     }
645 }
646
647 /*******************************************************************
648  Convert FROM contain SHIFT JIS codes to 7 bits JIS codes
649  return converted buffer
650 ********************************************************************/
651 static char *sj_to_jis7(char *from, BOOL overwrite)
652 {
653     char *out;
654     int shifted;
655     char *save;
656
657     shifted = _KJ_ROMAN;
658     save = (char *) from;
659     for (out = cvtbuf; *from; ) {
660         if (is_shift_jis (*from)) {
661             int code;
662             switch (shifted) {
663             case _KJ_KANA:
664                 *out++ = jis_si;        /* to ROMAN and through down */
665             case _KJ_ROMAN:             /* to KANJI */
666                 *out++ = jis_esc;
667                 *out++ = jis_so1;
668                 *out++ = jis_kso;
669                 shifted = _KJ_KANJI;
670                 break;
671             }
672             code = sjis2jis ((int) from[0] & 0xff, (int) from[1] & 0xff);
673             *out++ = (code >> 8) & 0xff;
674             *out++ = code;
675             from += 2;
676         } else if (is_kana (from[0])) {
677             switch (shifted) {
678             case _KJ_KANJI:             /* to ROMAN */
679                 *out++ = jis_esc;
680                 *out++ = jis_si1;
681                 *out++ = jis_ksi;
682             case _KJ_ROMAN:             /* to KANA */
683                 *out++ = jis_so;
684                 shifted = _KJ_KANA;
685                 break;
686             }
687             *out++ = ((int) *from++) - 0x80;
688         } else {
689             switch (shifted) {
690             case _KJ_KANA:
691                 *out++ = jis_si;        /* to ROMAN */
692                 shifted = _KJ_ROMAN;
693                 break;
694             case _KJ_KANJI:             /* to ROMAN */
695                 *out++ = jis_esc;
696                 *out++ = jis_si1;
697                 *out++ = jis_ksi;
698                 shifted = _KJ_ROMAN;
699                 break;
700             }
701             *out++ = *from++;
702         }
703     }
704     switch (shifted) {
705     case _KJ_KANA:
706         *out++ = jis_si;                /* to ROMAN */
707         break;
708     case _KJ_KANJI:                     /* to ROMAN */
709         *out++ = jis_esc;
710         *out++ = jis_si1;
711         *out++ = jis_ksi;
712         break;
713     }
714     *out = 0;
715     if (overwrite) {
716         pstrcpy (save, (char *) cvtbuf);
717         return save;
718     } else {
719         return cvtbuf;
720     }
721 }
722
723 /*******************************************************************
724  Convert FROM contain 7 bits JIS(junet) codes to SHIFT JIS codes
725  return converted buffer
726 ********************************************************************/
727 static char *junet_to_sj(char *from, BOOL overwrite)
728 {
729     char *out;
730     int shifted;
731     char *save;
732
733     shifted = _KJ_ROMAN;
734     save = (char *) from;
735     for (out = cvtbuf; *from;) {
736         if (is_esc (*from)) {
737             if (is_so1 (from[1]) && is_so2 (from[2])) {
738                 shifted = _KJ_KANJI;
739                 from += 3;
740             } else if (is_si1 (from[1]) && is_si2 (from[2])) {
741                 shifted = _KJ_ROMAN;
742                 from += 3;
743             } else if (is_juk1(from[1]) && is_juk2 (from[2])) {
744                 shifted = _KJ_KANA;
745                 from += 3;
746             } else {                    /* sequence error */
747                 goto normal;
748             }
749         } else {
750         normal:
751             switch (shifted) {
752             default:
753             case _KJ_ROMAN:
754                 *out++ = *from++;
755                 break;
756             case _KJ_KANJI:
757                 {
758                     int code = jis2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff);
759                     *out++ = (code >> 8) & 0xff;
760                     *out++ = code;
761                     from += 2;
762                 }
763                 break;
764             case _KJ_KANA:
765                 *out++ = ((int) from[0]) + 0x80;
766                 break;
767             }
768         }
769     }
770     *out = 0;
771     if (overwrite) {
772         pstrcpy (save, (char *) cvtbuf);
773         return save;
774     } else {
775         return cvtbuf;
776     }
777 }
778
779 /*******************************************************************
780  Convert FROM contain SHIFT JIS codes to 7 bits JIS(junet) codes
781  return converted buffer
782 ********************************************************************/
783 static char *sj_to_junet(char *from, BOOL overwrite)
784 {
785     char *out;
786     int shifted;
787     char *save;
788
789     shifted = _KJ_ROMAN;
790     save = (char *) from;
791     for (out = cvtbuf; *from; ) {
792         if (is_shift_jis (*from)) {
793             int code;
794             switch (shifted) {
795             case _KJ_KANA:
796             case _KJ_ROMAN:             /* to KANJI */
797                 *out++ = jis_esc;
798                 *out++ = jis_so1;
799                 *out++ = jis_so2;
800                 shifted = _KJ_KANJI;
801                 break;
802             }
803             code = sjis2jis ((int) from[0] & 0xff, (int) from[1] & 0xff);
804             *out++ = (code >> 8) & 0xff;
805             *out++ = code;
806             from += 2;
807         } else if (is_kana (from[0])) {
808             switch (shifted) {
809             case _KJ_KANJI:             /* to ROMAN */
810             case _KJ_ROMAN:             /* to KANA */
811                 *out++ = jis_esc;
812                 *out++ = junet_kana1;
813                 *out++ = junet_kana2;
814                 shifted = _KJ_KANA;
815                 break;
816             }
817             *out++ = ((int) *from++) - 0x80;
818         } else {
819             switch (shifted) {
820             case _KJ_KANA:
821             case _KJ_KANJI:             /* to ROMAN */
822                 *out++ = jis_esc;
823                 *out++ = jis_si1;
824                 *out++ = jis_si2;
825                 shifted = _KJ_ROMAN;
826                 break;
827             }
828             *out++ = *from++;
829         }
830     }
831     switch (shifted) {
832     case _KJ_KANA:
833     case _KJ_KANJI:                     /* to ROMAN */
834         *out++ = jis_esc;
835         *out++ = jis_si1;
836         *out++ = jis_si2;
837         break;
838     }
839     *out = 0;
840     if (overwrite) {
841         pstrcpy (save, (char *) cvtbuf);
842         return save;
843     } else {
844         return cvtbuf;
845     }
846 }
847
848 /*******************************************************************
849   HEX <-> SJIS
850 ********************************************************************/
851 /* ":xx" -> a byte */
852 static char *hex_to_sj(char *from, BOOL overwrite)
853 {
854     char *sp, *dp;
855     
856     sp = (char *) from;
857     dp = cvtbuf;
858     while (*sp) {
859         if (*sp == hex_tag && isxdigit((int)sp[1]) && isxdigit((int)sp[2])) {
860             *dp++ = (hex2bin (sp[1])<<4) | (hex2bin (sp[2]));
861             sp += 3;
862         } else
863             *dp++ = *sp++;
864     }
865     *dp = '\0';
866     if (overwrite) {
867         pstrcpy ((char *) from, (char *) cvtbuf);
868         return (char *) from;
869     } else {
870         return cvtbuf;
871     }
872 }
873  
874 /*******************************************************************
875   kanji/kana -> ":xx" 
876 ********************************************************************/
877 static char *sj_to_hex(char *from, BOOL overwrite)
878 {
879     unsigned char *sp, *dp;
880     
881     sp = (unsigned char*) from;
882     dp = (unsigned char*) cvtbuf;
883     while (*sp) {
884         if (is_kana(*sp)) {
885             *dp++ = hex_tag;
886             *dp++ = bin2hex (((*sp)>>4)&0x0f);
887             *dp++ = bin2hex ((*sp)&0x0f);
888             sp++;
889         } else if (is_shift_jis (*sp) && is_shift_jis2 (sp[1])) {
890             *dp++ = hex_tag;
891             *dp++ = bin2hex (((*sp)>>4)&0x0f);
892             *dp++ = bin2hex ((*sp)&0x0f);
893             sp++;
894             *dp++ = hex_tag;
895             *dp++ = bin2hex (((*sp)>>4)&0x0f);
896             *dp++ = bin2hex ((*sp)&0x0f);
897             sp++;
898         } else
899             *dp++ = *sp++;
900     }
901     *dp = '\0';
902     if (overwrite) {
903         pstrcpy ((char *) from, (char *) cvtbuf);
904         return (char *) from;
905     } else {
906         return cvtbuf;
907     }
908 }
909
910 /*******************************************************************
911   CAP <-> SJIS
912 ********************************************************************/
913 /* ":xx" CAP -> a byte */
914 static char *cap_to_sj(char *from, BOOL overwrite)
915 {
916     char *sp, *dp;
917
918     sp = (char *) from;
919     dp = cvtbuf;
920     while (*sp) {
921         /*
922          * The only change between this and hex_to_sj is here. sj_to_cap only
923          * translates characters greater or equal to 0x80 - make sure that here
924          * we only do the reverse (that's why the strchr is used rather than
925          * isxdigit. Based on fix from ado@elsie.nci.nih.gov (Arthur David Olson).
926          */
927         if (*sp == hex_tag && (strchr ("89abcdefABCDEF", sp[1]) != NULL) && isxdigit((int)sp[2])) {
928             *dp++ = (hex2bin (sp[1])<<4) | (hex2bin (sp[2]));
929             sp += 3;
930         } else
931             *dp++ = *sp++;
932     }
933     *dp = '\0';
934     if (overwrite) {
935         pstrcpy ((char *) from, (char *) cvtbuf);
936         return (char *) from;
937     } else {
938         return cvtbuf;
939     }
940 }
941
942 /*******************************************************************
943   kanji/kana -> ":xx" - CAP format.
944 ********************************************************************/
945 static char *sj_to_cap(char *from, BOOL overwrite)
946 {
947     unsigned char *sp, *dp;
948
949     sp = (unsigned char*) from;
950     dp = (unsigned char*) cvtbuf;
951     while (*sp) {
952         if (*sp >= 0x80) {
953             *dp++ = hex_tag;
954             *dp++ = bin2hex (((*sp)>>4)&0x0f);
955             *dp++ = bin2hex ((*sp)&0x0f);
956             sp++;
957         } else {
958             *dp++ = *sp++;
959         }
960     }
961     *dp = '\0';
962     if (overwrite) {
963         pstrcpy ((char *) from, (char *) cvtbuf);
964         return (char *) from;
965     } else {
966         return cvtbuf;
967     }
968 }
969
970 /*******************************************************************
971  sj to sj
972 ********************************************************************/
973 static char *sj_to_sj(char *from, BOOL overwrite)
974 {
975     if (!overwrite) {
976         pstrcpy (cvtbuf, (char *) from);
977         return cvtbuf;
978     } else {
979         return (char *) from;
980     }
981 }
982
983 /************************************************************************
984  conversion:
985  _dos_to_unix           _unix_to_dos
986 ************************************************************************/
987
988 static void setup_string_function(int codes)
989 {
990     switch (codes) {
991     default:
992         _dos_to_unix = dos2unix_format;
993         _unix_to_dos = unix2dos_format;
994         break;
995
996     case SJIS_CODE:
997         _dos_to_unix = sj_to_sj;
998         _unix_to_dos = sj_to_sj;
999         break;
1000         
1001     case EUC_CODE:
1002         _dos_to_unix = sj_to_euc;
1003         _unix_to_dos = euc_to_sj;
1004         break;
1005         
1006     case JIS7_CODE:
1007         _dos_to_unix = sj_to_jis7;
1008         _unix_to_dos = jis7_to_sj;
1009         break;
1010
1011     case JIS8_CODE:
1012         _dos_to_unix = sj_to_jis8;
1013         _unix_to_dos = jis8_to_sj;
1014         break;
1015
1016     case JUNET_CODE:
1017         _dos_to_unix = sj_to_junet;
1018         _unix_to_dos = junet_to_sj;
1019         break;
1020
1021     case HEX_CODE:
1022         _dos_to_unix = sj_to_hex;
1023         _unix_to_dos = hex_to_sj;
1024         break;
1025
1026     case CAP_CODE:
1027         _dos_to_unix = sj_to_cap;
1028         _unix_to_dos = cap_to_sj;
1029         break;
1030     }
1031 }
1032
1033 /************************************************************************
1034  Interpret coding system.
1035 ************************************************************************/
1036
1037 void interpret_coding_system(char *str)
1038 {
1039     int codes = UNKNOWN_CODE;
1040     
1041     if (strequal (str, "sjis")) {
1042         codes = SJIS_CODE;
1043     } else if (strequal (str, "euc")) {
1044         codes = EUC_CODE;
1045     } else if (strequal (str, "cap")) {
1046         codes = CAP_CODE;
1047         hex_tag = HEXTAG;
1048     } else if (strequal (str, "hex")) {
1049         codes = HEX_CODE;
1050         hex_tag = HEXTAG;
1051     } else if (!strncasecmp (str, "hex", 3)) {
1052         codes = HEX_CODE;
1053         hex_tag = (str[3] ? str[3] : HEXTAG);
1054     } else if (strequal (str, "j8bb")) {
1055         codes = JIS8_CODE;
1056         jis_kso = 'B';
1057         jis_ksi = 'B';
1058     } else if (strequal (str, "j8bj") || strequal (str, "jis8")) {
1059         codes = JIS8_CODE;
1060         jis_kso = 'B';
1061         jis_ksi = 'J';
1062     } else if (strequal (str, "j8bh")) {
1063         codes = JIS8_CODE;
1064         jis_kso = 'B';
1065         jis_ksi = 'H';
1066     } else if (strequal (str, "j8@b")) {
1067         codes = JIS8_CODE;
1068         jis_kso = '@';
1069         jis_ksi = 'B';
1070     } else if (strequal (str, "j8@j")) {
1071         codes = JIS8_CODE;
1072         jis_kso = '@';
1073         jis_ksi = 'J';
1074     } else if (strequal (str, "j8@h")) {
1075         codes = JIS8_CODE;
1076         jis_kso = '@';
1077         jis_ksi = 'H';
1078     } else if (strequal (str, "j7bb")) {
1079         codes = JIS7_CODE;
1080         jis_kso = 'B';
1081         jis_ksi = 'B';
1082     } else if (strequal (str, "j7bj") || strequal (str, "jis7")) {
1083         codes = JIS7_CODE;
1084         jis_kso = 'B';
1085         jis_ksi = 'J';
1086     } else if (strequal (str, "j7bh")) {
1087         codes = JIS7_CODE;
1088         jis_kso = 'B';
1089         jis_ksi = 'H';
1090     } else if (strequal (str, "j7@b")) {
1091         codes = JIS7_CODE;
1092         jis_kso = '@';
1093         jis_ksi = 'B';
1094     } else if (strequal (str, "j7@j")) {
1095         codes = JIS7_CODE;
1096         jis_kso = '@';
1097         jis_ksi = 'J';
1098     } else if (strequal (str, "j7@h")) {
1099         codes = JIS7_CODE;
1100         jis_kso = '@';
1101         jis_ksi = 'H';
1102     } else if (strequal (str, "jubb")) {
1103         codes = JUNET_CODE;
1104         jis_kso = 'B';
1105         jis_ksi = 'B';
1106     } else if (strequal (str, "jubj") || strequal (str, "junet")) {
1107         codes = JUNET_CODE;
1108         jis_kso = 'B';
1109         jis_ksi = 'J';
1110     } else if (strequal (str, "jubh")) {
1111         codes = JUNET_CODE;
1112         jis_kso = 'B';
1113         jis_ksi = 'H';
1114     } else if (strequal (str, "ju@b")) {
1115         codes = JUNET_CODE;
1116         jis_kso = '@';
1117         jis_ksi = 'B';
1118     } else if (strequal (str, "ju@j")) {
1119         codes = JUNET_CODE;
1120         jis_kso = '@';
1121         jis_ksi = 'J';
1122     } else if (strequal (str, "ju@h")) {
1123         codes = JUNET_CODE;
1124         jis_kso = '@';
1125         jis_ksi = 'H';
1126     }   
1127     setup_string_function (codes);
1128 }
1129
1130 /*******************************************************************
1131  Non multibyte char function.
1132 *******************************************************************/
1133    
1134 static int skip_non_multibyte_char(char c)
1135 {
1136   return 0;
1137 }
1138
1139 /*******************************************************************
1140  Function that always says a character isn't multibyte.
1141 *******************************************************************/
1142
1143 static BOOL not_multibyte_char_1(char c)
1144 {
1145   return False;
1146 }
1147
1148 /*******************************************************************
1149  Setup the function pointers for the functions that are replaced
1150  when multi-byte codepages are used.
1151
1152  The dos_to_unix and unix_to_dos function pointers are only
1153  replaced by setup_string_function called by interpret_coding_system
1154  above.
1155 *******************************************************************/
1156
1157 void initialize_multibyte_vectors( int client_codepage)
1158 {
1159   switch( client_codepage )
1160   {
1161   case KANJI_CODEPAGE:
1162     multibyte_strchr = (char *(*)(char *, int )) sj_strchr;
1163     multibyte_strrchr = (char *(*)(char *, int )) sj_strrchr;
1164     multibyte_strstr = (char *(*)(char *, char *)) sj_strstr;
1165     multibyte_strtok = (char *(*)(char *, char *)) sj_strtok;
1166     _skip_multibyte_char = skip_kanji_multibyte_char;
1167     is_multibyte_char_1 = is_kanji_multibyte_char_1;
1168     break;
1169   case HANGUL_CODEPAGE:
1170     multibyte_strchr = (char *(*)(char *, int )) generic_multibyte_strchr;
1171     multibyte_strrchr = (char *(*)(char *, int )) generic_multibyte_strrchr;
1172     multibyte_strstr = (char *(*)(char *, char *)) generic_multibyte_strstr;
1173     multibyte_strtok = (char *(*)(char *, char *)) generic_multibyte_strtok;
1174     _skip_multibyte_char = skip_generic_multibyte_char;
1175     is_multibyte_char_1 = hangul_is_multibyte_char_1;
1176     break;
1177   case BIG5_CODEPAGE:
1178     multibyte_strchr = (char *(*)(char *, int )) generic_multibyte_strchr;
1179     multibyte_strrchr = (char *(*)(char *, int )) generic_multibyte_strrchr;
1180     multibyte_strstr = (char *(*)(char *, char *)) generic_multibyte_strstr;
1181     multibyte_strtok = (char *(*)(char *, char *)) generic_multibyte_strtok;
1182     _skip_multibyte_char = skip_generic_multibyte_char;
1183     is_multibyte_char_1 = big5_is_multibyte_char_1;
1184     break;
1185   case SIMPLIFIED_CHINESE_CODEPAGE:
1186     multibyte_strchr = (char *(*)(char *, int )) generic_multibyte_strchr;
1187     multibyte_strrchr = (char *(*)(char *, int )) generic_multibyte_strrchr;
1188     multibyte_strstr = (char *(*)(char *, char *)) generic_multibyte_strstr;
1189     multibyte_strtok = (char *(*)(char *, char *)) generic_multibyte_strtok;
1190     _skip_multibyte_char = skip_generic_multibyte_char;
1191     is_multibyte_char_1 = simpch_is_multibyte_char_1;
1192     break;
1193   /*
1194    * Single char size code page.
1195    */
1196   default:
1197     multibyte_strchr = (char *(*)(char *, int )) strchr;
1198     multibyte_strrchr = (char *(*)(char *, int )) strrchr;
1199     multibyte_strstr = (char *(*)(char *, char *)) strstr;
1200     multibyte_strtok = (char *(*)(char *, char *)) strtok;
1201     _skip_multibyte_char = skip_non_multibyte_char;
1202     is_multibyte_char_1 = not_multibyte_char_1;
1203     break; 
1204   }
1205 }