include/kanji.h include/proto.h lib/kanji.c: Added const parameters in string wrappers.
[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)(const char *, int ) = (char *(*)(const char *, int )) strchr;
36 char *(*multibyte_strrchr)(const char *, int ) = (char *(*)(const char *, int )) strrchr;
37 char *(*multibyte_strstr)(const char *, const char *) = (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 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 /*******************************************************************
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 char *sj_strstr(const char *s1, const char *s2)
138 {
139   size_t len = strlen (s2);
140   if (!*s2) 
141     return (char *) s1;
142   for (;*s1;) {
143     if (*s1 == *s2) {
144       if (strncmp (s1, s2, len) == 0)
145         return (char *) s1;
146     }
147     if (is_shift_jis (*s1)) {
148       s1 += 2;
149     } else {
150       s1++;
151     }
152   }
153   return 0;
154 }
155
156 /*******************************************************************
157  Search char C from beginning of S.
158  S contains SHIFT JIS chars.
159 ********************************************************************/
160
161 static char *sj_strchr (const char *s, int c)
162 {
163   for (; *s; ) {
164     if (*s == c)
165       return (char *) s;
166     if (is_shift_jis (*s)) {
167       s += 2;
168     } else {
169       s++;
170     }
171   }
172   return 0;
173 }
174
175 /*******************************************************************
176  Search char C end of S.
177  S contains SHIFT JIS chars.
178 ********************************************************************/
179
180 static char *sj_strrchr(const char *s, int c)
181 {
182   char *q;
183
184   for (q = 0; *s; ) {
185     if (*s == c) {
186       q = (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 int 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 char *generic_multibyte_strstr(const char *s1, const char *s2)
304 {
305   size_t len = strlen (s2);
306   if (!*s2)
307     return (char *) s1;
308   for (;*s1;) {
309     if (*s1 == *s2) {
310       if (strncmp (s1, s2, len) == 0)
311         return (char *) s1;
312     }
313     if ((*is_multibyte_char_1)(*s1)) {
314       s1 += 2;
315     } else {
316       s1++;
317     }
318   }
319   return 0;
320 }
321
322 /*******************************************************************
323  Search char C from beginning of S.
324  S contains generic multibyte chars.
325 ********************************************************************/
326
327 static char *generic_multibyte_strchr(const char *s, int c)
328 {
329   for (; *s; ) {
330     if (*s == c)
331       return (char *) s;
332     if ((*is_multibyte_char_1)(*s)) {
333       s += 2;
334     } else {
335       s++;
336     }
337   }
338   return 0;
339 }
340
341 /*******************************************************************
342  Search char C end of S.
343  S contains generic multibyte chars.
344 ********************************************************************/
345
346 static char *generic_multibyte_strrchr(const char *s, int c)
347 {
348   char *q;
349  
350   for (q = 0; *s; ) {
351     if (*s == c) {
352       q = (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 int 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[1024];
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;) {
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; ) {
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;) {
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         normal:
518             switch (shifted) {
519             default:
520             case _KJ_ROMAN:
521                 *out++ = *from++;
522                 break;
523             case _KJ_KANJI:
524                 {
525                     int code = jis2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff);
526                     *out++ = (code >> 8) & 0xff;
527                     *out++ = code;
528                     from += 2;
529                 }
530                 break;
531             }
532         }
533     }
534     *out = 0;
535     if (overwrite) {
536         pstrcpy (save, (char *) cvtbuf);
537         return save;
538     } else {
539         return cvtbuf;
540     }
541 }
542
543 /*******************************************************************
544  Convert FROM contain SHIFT JIS codes to JIS codes
545  return converted buffer
546 ********************************************************************/
547
548 static char *sj_to_jis8(char *from, BOOL overwrite)
549 {
550     char *out;
551     int shifted;
552     char *save;
553
554     shifted = _KJ_ROMAN;
555     save = (char *) from;
556     for (out = cvtbuf; *from; ) {
557         if (is_shift_jis (*from)) {
558             int code;
559             switch (shifted) {
560             case _KJ_ROMAN:             /* to KANJI */
561                 *out++ = jis_esc;
562                 *out++ = jis_so1;
563                 *out++ = jis_kso;
564                 shifted = _KJ_KANJI;
565                 break;
566             }
567             code = sjis2jis ((int) from[0] & 0xff, (int) from[1] & 0xff);
568             *out++ = (code >> 8) & 0xff;
569             *out++ = code;
570             from += 2;
571         } else {
572             switch (shifted) {
573             case _KJ_KANJI:             /* to ROMAN/KANA */
574                 *out++ = jis_esc;
575                 *out++ = jis_si1;
576                 *out++ = jis_ksi;
577                 shifted = _KJ_ROMAN;
578                 break;
579             }
580             *out++ = *from++;
581         }
582     }
583     switch (shifted) {
584     case _KJ_KANJI:                     /* to ROMAN/KANA */
585         *out++ = jis_esc;
586         *out++ = jis_si1;
587         *out++ = jis_ksi;
588         shifted = _KJ_ROMAN;
589         break;
590     }
591     *out = 0;
592     if (overwrite) {
593         pstrcpy (save, (char *) cvtbuf);
594         return save;
595     } else {
596         return cvtbuf;
597     }
598 }
599
600 /*******************************************************************
601  Convert FROM contain 7 bits JIS codes to SHIFT JIS codes
602  return converted buffer
603 ********************************************************************/
604 static char *jis7_to_sj(char *from, BOOL overwrite)
605 {
606     char *out;
607     int shifted;
608     char *save;
609
610     shifted = _KJ_ROMAN;
611     save = (char *) from;
612     for (out = cvtbuf; *from;) {
613         if (is_esc (*from)) {
614             if (is_so1 (from[1]) && is_so2 (from[2])) {
615                 shifted = _KJ_KANJI;
616                 from += 3;
617             } else if (is_si1 (from[1]) && is_si2 (from[2])) {
618                 shifted = _KJ_ROMAN;
619                 from += 3;
620             } else {                    /* sequence error */
621                 goto normal;
622             }
623         } else if (is_so (*from)) {
624             shifted = _KJ_KANA;         /* to KANA */
625             from++;
626         } else if (is_si (*from)) {
627             shifted = _KJ_ROMAN;        /* to ROMAN */
628             from++;
629         } else {
630         normal:
631             switch (shifted) {
632             default:
633             case _KJ_ROMAN:
634                 *out++ = *from++;
635                 break;
636             case _KJ_KANJI:
637                 {
638                     int code = jis2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff);
639                     *out++ = (code >> 8) & 0xff;
640                     *out++ = code;
641                     from += 2;
642                 }
643                 break;
644             case _KJ_KANA:
645                 *out++ = ((int) from[0]) + 0x80;
646                 break;
647             }
648         }
649     }
650     *out = 0;
651     if (overwrite) {
652         pstrcpy (save, (char *) cvtbuf);
653         return save;
654     } else {
655         return cvtbuf;
656     }
657 }
658
659 /*******************************************************************
660  Convert FROM contain SHIFT JIS codes to 7 bits JIS codes
661  return converted buffer
662 ********************************************************************/
663 static char *sj_to_jis7(char *from, BOOL overwrite)
664 {
665     char *out;
666     int shifted;
667     char *save;
668
669     shifted = _KJ_ROMAN;
670     save = (char *) from;
671     for (out = cvtbuf; *from; ) {
672         if (is_shift_jis (*from)) {
673             int code;
674             switch (shifted) {
675             case _KJ_KANA:
676                 *out++ = jis_si;        /* to ROMAN and through down */
677             case _KJ_ROMAN:             /* to KANJI */
678                 *out++ = jis_esc;
679                 *out++ = jis_so1;
680                 *out++ = jis_kso;
681                 shifted = _KJ_KANJI;
682                 break;
683             }
684             code = sjis2jis ((int) from[0] & 0xff, (int) from[1] & 0xff);
685             *out++ = (code >> 8) & 0xff;
686             *out++ = code;
687             from += 2;
688         } else if (is_kana (from[0])) {
689             switch (shifted) {
690             case _KJ_KANJI:             /* to ROMAN */
691                 *out++ = jis_esc;
692                 *out++ = jis_si1;
693                 *out++ = jis_ksi;
694             case _KJ_ROMAN:             /* to KANA */
695                 *out++ = jis_so;
696                 shifted = _KJ_KANA;
697                 break;
698             }
699             *out++ = ((int) *from++) - 0x80;
700         } else {
701             switch (shifted) {
702             case _KJ_KANA:
703                 *out++ = jis_si;        /* to ROMAN */
704                 shifted = _KJ_ROMAN;
705                 break;
706             case _KJ_KANJI:             /* to ROMAN */
707                 *out++ = jis_esc;
708                 *out++ = jis_si1;
709                 *out++ = jis_ksi;
710                 shifted = _KJ_ROMAN;
711                 break;
712             }
713             *out++ = *from++;
714         }
715     }
716     switch (shifted) {
717     case _KJ_KANA:
718         *out++ = jis_si;                /* to ROMAN */
719         break;
720     case _KJ_KANJI:                     /* to ROMAN */
721         *out++ = jis_esc;
722         *out++ = jis_si1;
723         *out++ = jis_ksi;
724         break;
725     }
726     *out = 0;
727     if (overwrite) {
728         pstrcpy (save, (char *) cvtbuf);
729         return save;
730     } else {
731         return cvtbuf;
732     }
733 }
734
735 /*******************************************************************
736  Convert FROM contain 7 bits JIS(junet) codes to SHIFT JIS codes
737  return converted buffer
738 ********************************************************************/
739 static char *junet_to_sj(char *from, BOOL overwrite)
740 {
741     char *out;
742     int shifted;
743     char *save;
744
745     shifted = _KJ_ROMAN;
746     save = (char *) from;
747     for (out = cvtbuf; *from;) {
748         if (is_esc (*from)) {
749             if (is_so1 (from[1]) && is_so2 (from[2])) {
750                 shifted = _KJ_KANJI;
751                 from += 3;
752             } else if (is_si1 (from[1]) && is_si2 (from[2])) {
753                 shifted = _KJ_ROMAN;
754                 from += 3;
755             } else if (is_juk1(from[1]) && is_juk2 (from[2])) {
756                 shifted = _KJ_KANA;
757                 from += 3;
758             } else {                    /* sequence error */
759                 goto normal;
760             }
761         } else {
762         normal:
763             switch (shifted) {
764             default:
765             case _KJ_ROMAN:
766                 *out++ = *from++;
767                 break;
768             case _KJ_KANJI:
769                 {
770                     int code = jis2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff);
771                     *out++ = (code >> 8) & 0xff;
772                     *out++ = code;
773                     from += 2;
774                 }
775                 break;
776             case _KJ_KANA:
777                 *out++ = ((int) from[0]) + 0x80;
778                 break;
779             }
780         }
781     }
782     *out = 0;
783     if (overwrite) {
784         pstrcpy (save, (char *) cvtbuf);
785         return save;
786     } else {
787         return cvtbuf;
788     }
789 }
790
791 /*******************************************************************
792  Convert FROM contain SHIFT JIS codes to 7 bits JIS(junet) codes
793  return converted buffer
794 ********************************************************************/
795 static char *sj_to_junet(char *from, BOOL overwrite)
796 {
797     char *out;
798     int shifted;
799     char *save;
800
801     shifted = _KJ_ROMAN;
802     save = (char *) from;
803     for (out = cvtbuf; *from; ) {
804         if (is_shift_jis (*from)) {
805             int code;
806             switch (shifted) {
807             case _KJ_KANA:
808             case _KJ_ROMAN:             /* to KANJI */
809                 *out++ = jis_esc;
810                 *out++ = jis_so1;
811                 *out++ = jis_so2;
812                 shifted = _KJ_KANJI;
813                 break;
814             }
815             code = sjis2jis ((int) from[0] & 0xff, (int) from[1] & 0xff);
816             *out++ = (code >> 8) & 0xff;
817             *out++ = code;
818             from += 2;
819         } else if (is_kana (from[0])) {
820             switch (shifted) {
821             case _KJ_KANJI:             /* to ROMAN */
822             case _KJ_ROMAN:             /* to KANA */
823                 *out++ = jis_esc;
824                 *out++ = junet_kana1;
825                 *out++ = junet_kana2;
826                 shifted = _KJ_KANA;
827                 break;
828             }
829             *out++ = ((int) *from++) - 0x80;
830         } else {
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                 shifted = _KJ_ROMAN;
838                 break;
839             }
840             *out++ = *from++;
841         }
842     }
843     switch (shifted) {
844     case _KJ_KANA:
845     case _KJ_KANJI:                     /* to ROMAN */
846         *out++ = jis_esc;
847         *out++ = jis_si1;
848         *out++ = jis_si2;
849         break;
850     }
851     *out = 0;
852     if (overwrite) {
853         pstrcpy (save, (char *) cvtbuf);
854         return save;
855     } else {
856         return cvtbuf;
857     }
858 }
859
860 /*******************************************************************
861   HEX <-> SJIS
862 ********************************************************************/
863 /* ":xx" -> a byte */
864 static char *hex_to_sj(char *from, BOOL overwrite)
865 {
866     char *sp, *dp;
867     
868     sp = (char *) from;
869     dp = cvtbuf;
870     while (*sp) {
871         if (*sp == hex_tag && isxdigit((int)sp[1]) && isxdigit((int)sp[2])) {
872             *dp++ = (hex2bin (sp[1])<<4) | (hex2bin (sp[2]));
873             sp += 3;
874         } else
875             *dp++ = *sp++;
876     }
877     *dp = '\0';
878     if (overwrite) {
879         pstrcpy ((char *) from, (char *) cvtbuf);
880         return (char *) from;
881     } else {
882         return cvtbuf;
883     }
884 }
885  
886 /*******************************************************************
887   kanji/kana -> ":xx" 
888 ********************************************************************/
889 static char *sj_to_hex(char *from, BOOL overwrite)
890 {
891     unsigned char *sp, *dp;
892     
893     sp = (unsigned char*) from;
894     dp = (unsigned char*) cvtbuf;
895     while (*sp) {
896         if (is_kana(*sp)) {
897             *dp++ = hex_tag;
898             *dp++ = bin2hex (((*sp)>>4)&0x0f);
899             *dp++ = bin2hex ((*sp)&0x0f);
900             sp++;
901         } else if (is_shift_jis (*sp) && is_shift_jis2 (sp[1])) {
902             *dp++ = hex_tag;
903             *dp++ = bin2hex (((*sp)>>4)&0x0f);
904             *dp++ = bin2hex ((*sp)&0x0f);
905             sp++;
906             *dp++ = hex_tag;
907             *dp++ = bin2hex (((*sp)>>4)&0x0f);
908             *dp++ = bin2hex ((*sp)&0x0f);
909             sp++;
910         } else
911             *dp++ = *sp++;
912     }
913     *dp = '\0';
914     if (overwrite) {
915         pstrcpy ((char *) from, (char *) cvtbuf);
916         return (char *) from;
917     } else {
918         return cvtbuf;
919     }
920 }
921
922 /*******************************************************************
923   CAP <-> SJIS
924 ********************************************************************/
925 /* ":xx" CAP -> a byte */
926 static char *cap_to_sj(char *from, BOOL overwrite)
927 {
928     char *sp, *dp;
929
930     sp = (char *) from;
931     dp = cvtbuf;
932     while (*sp) {
933         /*
934          * The only change between this and hex_to_sj is here. sj_to_cap only
935          * translates characters greater or equal to 0x80 - make sure that here
936          * we only do the reverse (that's why the strchr is used rather than
937          * isxdigit. Based on fix from ado@elsie.nci.nih.gov (Arthur David Olson).
938          */
939         if (*sp == hex_tag && (strchr ("89abcdefABCDEF", sp[1]) != NULL) && isxdigit((int)sp[2])) {
940             *dp++ = (hex2bin (sp[1])<<4) | (hex2bin (sp[2]));
941             sp += 3;
942         } else
943             *dp++ = *sp++;
944     }
945     *dp = '\0';
946     if (overwrite) {
947         pstrcpy ((char *) from, (char *) cvtbuf);
948         return (char *) from;
949     } else {
950         return cvtbuf;
951     }
952 }
953
954 /*******************************************************************
955   kanji/kana -> ":xx" - CAP format.
956 ********************************************************************/
957 static char *sj_to_cap(char *from, BOOL overwrite)
958 {
959     unsigned char *sp, *dp;
960
961     sp = (unsigned char*) from;
962     dp = (unsigned char*) cvtbuf;
963     while (*sp) {
964         if (*sp >= 0x80) {
965             *dp++ = hex_tag;
966             *dp++ = bin2hex (((*sp)>>4)&0x0f);
967             *dp++ = bin2hex ((*sp)&0x0f);
968             sp++;
969         } else {
970             *dp++ = *sp++;
971         }
972     }
973     *dp = '\0';
974     if (overwrite) {
975         pstrcpy ((char *) from, (char *) cvtbuf);
976         return (char *) from;
977     } else {
978         return cvtbuf;
979     }
980 }
981
982 /*******************************************************************
983  sj to sj
984 ********************************************************************/
985 static char *sj_to_sj(char *from, BOOL overwrite)
986 {
987     if (!overwrite) {
988         pstrcpy (cvtbuf, (char *) from);
989         return cvtbuf;
990     } else {
991         return (char *) from;
992     }
993 }
994
995 /************************************************************************
996  conversion:
997  _dos_to_unix           _unix_to_dos
998 ************************************************************************/
999
1000 static void setup_string_function(int codes)
1001 {
1002     switch (codes) {
1003     default:
1004         _dos_to_unix = dos2unix_format;
1005         _unix_to_dos = unix2dos_format;
1006         break;
1007
1008     case SJIS_CODE:
1009         _dos_to_unix = sj_to_sj;
1010         _unix_to_dos = sj_to_sj;
1011         break;
1012         
1013     case EUC_CODE:
1014         _dos_to_unix = sj_to_euc;
1015         _unix_to_dos = euc_to_sj;
1016         break;
1017         
1018     case JIS7_CODE:
1019         _dos_to_unix = sj_to_jis7;
1020         _unix_to_dos = jis7_to_sj;
1021         break;
1022
1023     case JIS8_CODE:
1024         _dos_to_unix = sj_to_jis8;
1025         _unix_to_dos = jis8_to_sj;
1026         break;
1027
1028     case JUNET_CODE:
1029         _dos_to_unix = sj_to_junet;
1030         _unix_to_dos = junet_to_sj;
1031         break;
1032
1033     case HEX_CODE:
1034         _dos_to_unix = sj_to_hex;
1035         _unix_to_dos = hex_to_sj;
1036         break;
1037
1038     case CAP_CODE:
1039         _dos_to_unix = sj_to_cap;
1040         _unix_to_dos = cap_to_sj;
1041         break;
1042     }
1043 }
1044
1045 /************************************************************************
1046  Interpret coding system.
1047 ************************************************************************/
1048
1049 void interpret_coding_system(char *str)
1050 {
1051     int codes = UNKNOWN_CODE;
1052     
1053     if (strequal (str, "sjis")) {
1054         codes = SJIS_CODE;
1055     } else if (strequal (str, "euc")) {
1056         codes = EUC_CODE;
1057     } else if (strequal (str, "cap")) {
1058         codes = CAP_CODE;
1059         hex_tag = HEXTAG;
1060     } else if (strequal (str, "hex")) {
1061         codes = HEX_CODE;
1062         hex_tag = HEXTAG;
1063     } else if (!strncasecmp (str, "hex", 3)) {
1064         codes = HEX_CODE;
1065         hex_tag = (str[3] ? str[3] : HEXTAG);
1066     } else if (strequal (str, "j8bb")) {
1067         codes = JIS8_CODE;
1068         jis_kso = 'B';
1069         jis_ksi = 'B';
1070     } else if (strequal (str, "j8bj") || strequal (str, "jis8")) {
1071         codes = JIS8_CODE;
1072         jis_kso = 'B';
1073         jis_ksi = 'J';
1074     } else if (strequal (str, "j8bh")) {
1075         codes = JIS8_CODE;
1076         jis_kso = 'B';
1077         jis_ksi = 'H';
1078     } else if (strequal (str, "j8@b")) {
1079         codes = JIS8_CODE;
1080         jis_kso = '@';
1081         jis_ksi = 'B';
1082     } else if (strequal (str, "j8@j")) {
1083         codes = JIS8_CODE;
1084         jis_kso = '@';
1085         jis_ksi = 'J';
1086     } else if (strequal (str, "j8@h")) {
1087         codes = JIS8_CODE;
1088         jis_kso = '@';
1089         jis_ksi = 'H';
1090     } else if (strequal (str, "j7bb")) {
1091         codes = JIS7_CODE;
1092         jis_kso = 'B';
1093         jis_ksi = 'B';
1094     } else if (strequal (str, "j7bj") || strequal (str, "jis7")) {
1095         codes = JIS7_CODE;
1096         jis_kso = 'B';
1097         jis_ksi = 'J';
1098     } else if (strequal (str, "j7bh")) {
1099         codes = JIS7_CODE;
1100         jis_kso = 'B';
1101         jis_ksi = 'H';
1102     } else if (strequal (str, "j7@b")) {
1103         codes = JIS7_CODE;
1104         jis_kso = '@';
1105         jis_ksi = 'B';
1106     } else if (strequal (str, "j7@j")) {
1107         codes = JIS7_CODE;
1108         jis_kso = '@';
1109         jis_ksi = 'J';
1110     } else if (strequal (str, "j7@h")) {
1111         codes = JIS7_CODE;
1112         jis_kso = '@';
1113         jis_ksi = 'H';
1114     } else if (strequal (str, "jubb")) {
1115         codes = JUNET_CODE;
1116         jis_kso = 'B';
1117         jis_ksi = 'B';
1118     } else if (strequal (str, "jubj") || strequal (str, "junet")) {
1119         codes = JUNET_CODE;
1120         jis_kso = 'B';
1121         jis_ksi = 'J';
1122     } else if (strequal (str, "jubh")) {
1123         codes = JUNET_CODE;
1124         jis_kso = 'B';
1125         jis_ksi = 'H';
1126     } else if (strequal (str, "ju@b")) {
1127         codes = JUNET_CODE;
1128         jis_kso = '@';
1129         jis_ksi = 'B';
1130     } else if (strequal (str, "ju@j")) {
1131         codes = JUNET_CODE;
1132         jis_kso = '@';
1133         jis_ksi = 'J';
1134     } else if (strequal (str, "ju@h")) {
1135         codes = JUNET_CODE;
1136         jis_kso = '@';
1137         jis_ksi = 'H';
1138     }   
1139     setup_string_function (codes);
1140 }
1141
1142 /*******************************************************************
1143  Non multibyte char function.
1144 *******************************************************************/
1145    
1146 static int skip_non_multibyte_char(char c)
1147 {
1148   return 0;
1149 }
1150
1151 /*******************************************************************
1152  Function that always says a character isn't multibyte.
1153 *******************************************************************/
1154
1155 static BOOL not_multibyte_char_1(char c)
1156 {
1157   return False;
1158 }
1159
1160 /*******************************************************************
1161  Function to determine if we are in a multibyte code page.
1162 *******************************************************************/
1163
1164 static BOOL is_multibyte_codepage_val = False;
1165
1166 BOOL is_multibyte_codepage(void)
1167 {
1168   return is_multibyte_codepage_val;
1169 }
1170
1171 /*******************************************************************
1172  Setup the function pointers for the functions that are replaced
1173  when multi-byte codepages are used.
1174
1175  The dos_to_unix and unix_to_dos function pointers are only
1176  replaced by setup_string_function called by interpret_coding_system
1177  above.
1178 *******************************************************************/
1179
1180 void initialize_multibyte_vectors( int client_codepage)
1181 {
1182   switch( client_codepage )
1183   {
1184   case KANJI_CODEPAGE:
1185     multibyte_strchr = sj_strchr;
1186     multibyte_strrchr = sj_strrchr;
1187     multibyte_strstr = sj_strstr;
1188     multibyte_strtok = sj_strtok;
1189     _skip_multibyte_char = skip_kanji_multibyte_char;
1190     is_multibyte_char_1 = is_kanji_multibyte_char_1;
1191     is_multibyte_codepage_val = True;
1192     break;
1193   case HANGUL_CODEPAGE:
1194     multibyte_strchr = generic_multibyte_strchr;
1195     multibyte_strrchr = generic_multibyte_strrchr;
1196     multibyte_strstr = generic_multibyte_strstr;
1197     multibyte_strtok = generic_multibyte_strtok;
1198     _skip_multibyte_char = skip_generic_multibyte_char;
1199     is_multibyte_char_1 = hangul_is_multibyte_char_1;
1200     is_multibyte_codepage_val = True;
1201     break;
1202   case BIG5_CODEPAGE:
1203     multibyte_strchr = generic_multibyte_strchr;
1204     multibyte_strrchr = generic_multibyte_strrchr;
1205     multibyte_strstr = generic_multibyte_strstr;
1206     multibyte_strtok = generic_multibyte_strtok;
1207     _skip_multibyte_char = skip_generic_multibyte_char;
1208     is_multibyte_char_1 = big5_is_multibyte_char_1;
1209     is_multibyte_codepage_val = True;
1210     break;
1211   case SIMPLIFIED_CHINESE_CODEPAGE:
1212     multibyte_strchr = generic_multibyte_strchr;
1213     multibyte_strrchr = generic_multibyte_strrchr;
1214     multibyte_strstr = generic_multibyte_strstr;
1215     multibyte_strtok = generic_multibyte_strtok;
1216     _skip_multibyte_char = skip_generic_multibyte_char;
1217     is_multibyte_char_1 = simpch_is_multibyte_char_1;
1218     is_multibyte_codepage_val = True;
1219     break;
1220   /*
1221    * Single char size code page.
1222    */
1223   default:
1224     multibyte_strchr = (char *(*)(const char *, int )) strchr;
1225     multibyte_strrchr = (char *(*)(const char *, int )) strrchr;
1226     multibyte_strstr = (char *(*)(const char *, const char *)) strstr;
1227     multibyte_strtok = (char *(*)(char *, const char *)) strtok;
1228     _skip_multibyte_char = skip_non_multibyte_char;
1229     is_multibyte_char_1 = not_multibyte_char_1;
1230     is_multibyte_codepage_val = False;
1231     break; 
1232   }
1233 }