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