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