OSDN Git Service

Add options for disabling weak encryption methods.
[ffftp/ffftp.git] / codecnv.c
1 /*=============================================================================\r
2 *\r
3 *                                                       漢字コード変換/改行コード変換\r
4 *\r
5 ===============================================================================\r
6 / Copyright (C) 1997-2007 Sota. All rights reserved.\r
7 /\r
8 / Redistribution and use in source and binary forms, with or without \r
9 / modification, are permitted provided that the following conditions \r
10 / are met:\r
11 /\r
12 /  1. Redistributions of source code must retain the above copyright \r
13 /     notice, this list of conditions and the following disclaimer.\r
14 /  2. Redistributions in binary form must reproduce the above copyright \r
15 /     notice, this list of conditions and the following disclaimer in the \r
16 /     documentation and/or other materials provided with the distribution.\r
17 /\r
18 / THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR \r
19 / IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES \r
20 / OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
21 / IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, \r
22 / INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
23 / BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF \r
24 / USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \r
25 / ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
26 / (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF \r
27 / THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
28 /============================================================================*/\r
29 \r
30 #define STRICT\r
31 #include <stdio.h>\r
32 #include <stdlib.h>\r
33 #include <string.h>\r
34 // IPv6対応\r
35 //#include <winsock.h>\r
36 #include <winsock2.h>\r
37 #include <mbstring.h>\r
38 #include <windowsx.h>\r
39 // UTF-8対応\r
40 #include <winnls.h>\r
41 \r
42 #include "common.h"\r
43 #include "resource.h"\r
44 \r
45 \r
46 \r
47 #define CONV_ASCII              0               /* ASCII文字処理中 */\r
48 #define CONV_KANJI              1               /* 漢字処理中 */\r
49 #define CONV_KANA               2               /* 半角カタカナ処理中 */\r
50 \r
51 \r
52 /*===== プロトタイプ =====*/\r
53 \r
54 static char *ConvEUCtoSJISkanaProc(CODECONVINFO *cInfo, char Dt, char *Put);\r
55 static char *ConvJIStoSJISkanaProc(CODECONVINFO *cInfo, char Dt, char *Put);\r
56 static char *ConvSJIStoEUCkanaProc(CODECONVINFO *cInfo, char Dt, char *Put);\r
57 static char *ConvSJIStoJISkanaProc(CODECONVINFO *cInfo, char Dt, char *Put);\r
58 static int HanKataToZen(char Ch);\r
59 static int AskDakuon(char Ch, char Daku);\r
60 \r
61 static int CheckOnSJIS(uchar *Pos, uchar *Btm);\r
62 static int CheckOnEUC(uchar *Pos, uchar *Btm);\r
63 static int ConvertIBMExtendedChar(int code);\r
64 \r
65 \r
66 typedef enum _NORM_FORM\r
67 {\r
68         NormalizationOther = 0,\r
69         NormalizationC = 0x1,\r
70         NormalizationD = 0x2,\r
71         NormalizationKC = 0x5,\r
72         NormalizationKD = 0x6\r
73 } NORM_FORM;\r
74 \r
75 typedef int (WINAPI* _NormalizeString)(NORM_FORM, LPCWSTR, int, LPWSTR, int);\r
76 \r
77 HMODULE hUnicodeNormalizationDll;\r
78 _NormalizeString p_NormalizeString;\r
79 \r
80 #if 0\r
81 /*----- 漢字コード変換のテストプログラム ------------------------------------*/\r
82 \r
83 void CodeCnvTest(void)\r
84 {\r
85         #define BUFBUF  43\r
86         #define BUFBUF2 BUFBUF+3\r
87 \r
88         CODECONVINFO cInfo;\r
89         char Buf[BUFBUF];\r
90         char Buf2[BUFBUF2];\r
91         FILE *Strm1;\r
92         FILE *Strm2;\r
93         int Byte;\r
94         int Continue;\r
95 \r
96 //      DoPrintf("---START ZEN");\r
97 \r
98         Strm1 = fopen("in.txt", "rb");\r
99         Strm2 = fopen("out_zen.txt", "wb");\r
100 \r
101         InitCodeConvInfo(&cInfo);\r
102         cInfo.KanaCnv = YES;\r
103 \r
104 \r
105         while((Byte = fread(Buf, 1, BUFBUF, Strm1)) != 0)\r
106         {\r
107                 cInfo.Str = Buf;\r
108                 cInfo.StrLen = Byte;\r
109                 cInfo.Buf = Buf2;\r
110                 cInfo.BufSize = BUFBUF2;\r
111 \r
112 //              DoPrintf("READ %d", Byte);\r
113 \r
114                 do\r
115                 {\r
116 //                      Continue = ConvEUCtoSJIS(&cInfo);\r
117 //                      Continue = ConvJIStoSJIS(&cInfo);\r
118 //                      Continue = ConvSJIStoEUC(&cInfo);\r
119 //                      Continue = ConvSJIStoJIS(&cInfo);\r
120                         Continue = ConvSMBtoSJIS(&cInfo);\r
121 //                      Continue = ConvSJIStoSMB_HEX(&cInfo);\r
122 //                      Continue = ConvSJIStoSMB_CAP(&cInfo);\r
123 \r
124                         fwrite(Buf2, cInfo.OutLen, 1, Strm2);\r
125 //                      DoPrintf("WRITE %d", cInfo.OutLen);\r
126 \r
127                 }\r
128                 while(Continue == YES);\r
129         }\r
130 \r
131         cInfo.Buf = Buf2;\r
132         cInfo.BufSize = BUFBUF2;\r
133         FlushRestData(&cInfo);\r
134         fwrite(Buf2, cInfo.OutLen, 1, Strm2);\r
135 //      DoPrintf("WRITE %d", cInfo.OutLen);\r
136 \r
137 \r
138         fclose(Strm1);\r
139         fclose(Strm2);\r
140 \r
141 \r
142 //      DoPrintf("---START HAN");\r
143 \r
144         Strm1 = fopen("in.txt", "rb");\r
145         Strm2 = fopen("out_han.txt", "wb");\r
146 \r
147         InitCodeConvInfo(&cInfo);\r
148         cInfo.KanaCnv = NO;\r
149 \r
150 \r
151         while((Byte = fread(Buf, 1, BUFBUF, Strm1)) != 0)\r
152         {\r
153                 cInfo.Str = Buf;\r
154                 cInfo.StrLen = Byte;\r
155                 cInfo.Buf = Buf2;\r
156                 cInfo.BufSize = BUFBUF2;\r
157 \r
158 //              DoPrintf("READ %d", Byte);\r
159 \r
160                 do\r
161                 {\r
162 //                      Continue = ConvEUCtoSJIS(&cInfo);\r
163 //                      Continue = ConvJIStoSJIS(&cInfo);\r
164 //                      Continue = ConvSJIStoEUC(&cInfo);\r
165 //                      Continue = ConvSJIStoJIS(&cInfo);\r
166                         Continue = ConvSMBtoSJIS(&cInfo);\r
167 //                      Continue = ConvSJIStoSMB_HEX(&cInfo);\r
168 //                      Continue = ConvSJIStoSMB_CAP(&cInfo);\r
169                         fwrite(Buf2, cInfo.OutLen, 1, Strm2);\r
170 //                      DoPrintf("WRITE %d", cInfo.OutLen);\r
171 \r
172                 }\r
173                 while(Continue == YES);\r
174         }\r
175 \r
176         cInfo.Buf = Buf2;\r
177         cInfo.BufSize = BUFBUF2;\r
178         FlushRestData(&cInfo);\r
179         fwrite(Buf2, cInfo.OutLen, 1, Strm2);\r
180 //      DoPrintf("WRITE %d", cInfo.OutLen);\r
181 \r
182         fclose(Strm1);\r
183         fclose(Strm2);\r
184 \r
185 //      DoPrintf("---END");\r
186 \r
187         return;\r
188 }\r
189 #endif\r
190 \r
191 \r
192 \r
193 #if 0\r
194 /*----- 改行コード変換のテストプログラム ------------------------------------*/\r
195 \r
196 void TermCodeCnvTest(void)\r
197 {\r
198         #define BUFBUF  10\r
199         #define BUFBUF2 BUFBUF\r
200 \r
201         TERMCODECONVINFO cInfo;\r
202         char Buf[BUFBUF];\r
203         char Buf2[BUFBUF2];\r
204         FILE *Strm1;\r
205         FILE *Strm2;\r
206         int Byte;\r
207         int Continue;\r
208 \r
209 //      DoPrintf("---START");\r
210 \r
211         Strm1 = fopen("in.txt", "rb");\r
212         Strm2 = fopen("out.txt", "wb");\r
213 \r
214         InitTermCodeConvInfo(&cInfo);\r
215 \r
216         while((Byte = fread(Buf, 1, BUFBUF, Strm1)) != 0)\r
217         {\r
218                 cInfo.Str = Buf;\r
219                 cInfo.StrLen = Byte;\r
220                 cInfo.Buf = Buf2;\r
221                 cInfo.BufSize = BUFBUF2;\r
222 \r
223 //              DoPrintf("READ %d", Byte);\r
224 \r
225                 do\r
226                 {\r
227                         Continue = ConvTermCodeToCRLF(&cInfo);\r
228 \r
229                         fwrite(Buf2, cInfo.OutLen, 1, Strm2);\r
230 //                      DoPrintf("WRITE %d", cInfo.OutLen);\r
231 \r
232                 }\r
233                 while(Continue == YES);\r
234         }\r
235 \r
236         cInfo.Buf = Buf2;\r
237         cInfo.BufSize = BUFBUF2;\r
238         FlushRestTermCodeConvData(&cInfo);\r
239         fwrite(Buf2, cInfo.OutLen, 1, Strm2);\r
240 //      DoPrintf("WRITE %d", cInfo.OutLen);\r
241 \r
242         fclose(Strm1);\r
243         fclose(Strm2);\r
244 \r
245 //      DoPrintf("---END");\r
246 \r
247         return;\r
248 }\r
249 #endif\r
250 \r
251 \r
252 \r
253 \r
254 \r
255 \r
256 \r
257 \r
258 \r
259 \r
260 \r
261 \r
262 /*----- 改行コード変換情報を初期化 --------------------------------------------\r
263 *\r
264 *       Parameter\r
265 *               TERMCODECONVINFO *cInfo : 改行コード変換情報\r
266 *\r
267 *       Return Value\r
268 *               なし\r
269 *----------------------------------------------------------------------------*/\r
270 \r
271 void InitTermCodeConvInfo(TERMCODECONVINFO *cInfo)\r
272 {\r
273         cInfo->Term = 0;\r
274         return;\r
275 }\r
276 \r
277 \r
278 /*----- 改行コード変換の残り情報を出力 ----------------------------------------\r
279 *\r
280 *       Parameter\r
281 *               TERMCODECONVINFO *cInfo : 改行コード変換情報\r
282 *\r
283 *       Return Value\r
284 *               int くり返しフラグ (=NO)\r
285 *\r
286 *       Note\r
287 *               改行コード変換の最後に呼ぶ事\r
288 *----------------------------------------------------------------------------*/\r
289 \r
290 int FlushRestTermCodeConvData(TERMCODECONVINFO *cInfo)\r
291 {\r
292         char *Put;\r
293 \r
294         Put = cInfo->Buf;\r
295 \r
296         if(cInfo->Term == 0x0D)\r
297                 *Put++ = 0x0A;\r
298 \r
299         cInfo->OutLen = Put - cInfo->Buf;\r
300 \r
301         return(NO);\r
302 }\r
303 \r
304 \r
305 /*----- 改行コードをCRLFに変換 -------------------------------------------------\r
306 *\r
307 *       Parameter\r
308 *               TERMCODECONVINFO *cInfo : 改行コード変換情報\r
309 *\r
310 *       Return Value\r
311 *               int くり返しフラグ (YES/NO)\r
312 *\r
313 *       Note\r
314 *               くり返しフラグがYESの時は、cInfoの内容を変えずにもう一度呼ぶこと\r
315 *----------------------------------------------------------------------------*/\r
316 \r
317 int ConvTermCodeToCRLF(TERMCODECONVINFO *cInfo)\r
318 {\r
319         char *Str;\r
320         char *Put;\r
321         char *Limit;\r
322         int Continue;\r
323 \r
324         Continue = NO;\r
325         Str = cInfo->Str;\r
326         Put = cInfo->Buf;\r
327         Limit = cInfo->Buf + cInfo->BufSize - 1;\r
328 \r
329         for(; cInfo->StrLen > 0; cInfo->StrLen--)\r
330         {\r
331                 if(Put >= Limit)\r
332                 {\r
333                         Continue = YES;\r
334                         break;\r
335                 }\r
336 \r
337                 if(*Str == 0x0D)\r
338                 {\r
339                         if(cInfo->Term == 0x0D)\r
340                                 *Put++ = 0x0A;\r
341                         *Put++ = 0x0D;\r
342                         cInfo->Term = *Str++;\r
343                 }\r
344                 else\r
345                 {\r
346                         if(*Str == 0x0A)\r
347                         {\r
348                                 if(cInfo->Term != 0x0D)\r
349                                         *Put++ = 0x0D;\r
350                         }\r
351                         else\r
352                         {\r
353                                 if(cInfo->Term == 0x0D)\r
354                                         *Put++ = 0x0A;\r
355                         }\r
356                         cInfo->Term = 0;\r
357                         *Put++ = *Str++;\r
358                 }\r
359         }\r
360 \r
361         cInfo->Str = Str;\r
362         cInfo->OutLen = Put - cInfo->Buf;\r
363 \r
364         return(Continue);\r
365 }\r
366 \r
367 \r
368 /*----- 漢字コード変換情報を初期化 --------------------------------------------\r
369 *\r
370 *       Parameter\r
371 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
372 *\r
373 *       Return Value\r
374 *               なし\r
375 *----------------------------------------------------------------------------*/\r
376 \r
377 void InitCodeConvInfo(CODECONVINFO *cInfo)\r
378 {\r
379         cInfo->KanaCnv = YES;\r
380 \r
381         cInfo->EscProc = 0;\r
382         cInfo->KanjiMode = CONV_ASCII;\r
383         cInfo->KanjiFst = 0;\r
384         cInfo->KanaPrev = 0;\r
385         cInfo->KanaProc = NULL;\r
386         // UTF-8対応\r
387         cInfo->EscUTF8Len = 0;\r
388         cInfo->EscFlush = NO;\r
389         cInfo->FlushProc = NULL;\r
390         return;\r
391 }\r
392 \r
393 \r
394 /*----- 漢字コード変換の残り情報を出力 ----------------------------------------\r
395 *\r
396 *       Parameter\r
397 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
398 *\r
399 *       Return Value\r
400 *               int くり返しフラグ (=NO)\r
401 *\r
402 *       Note\r
403 *               漢字コード変換の最後に呼ぶ事\r
404 *----------------------------------------------------------------------------*/\r
405 \r
406 int FlushRestData(CODECONVINFO *cInfo)\r
407 {\r
408         char *Put;\r
409 \r
410         // UTF-8対応\r
411         if(cInfo->FlushProc != NULL)\r
412         {\r
413                 cInfo->EscFlush = YES;\r
414                 return cInfo->FlushProc(cInfo);\r
415         }\r
416 \r
417         Put = cInfo->Buf;\r
418 \r
419         if(cInfo->KanaProc != NULL)\r
420                 Put = (cInfo->KanaProc)(cInfo, 0, Put);\r
421 \r
422         if(cInfo->KanjiFst != 0)\r
423                 *Put++ = cInfo->KanjiFst;\r
424         if(cInfo->EscProc >= 1)\r
425                 *Put++ = cInfo->EscCode[0];\r
426         if(cInfo->EscProc == 2)\r
427                 *Put++ = cInfo->EscCode[1];\r
428 \r
429         cInfo->OutLen = Put - cInfo->Buf;\r
430 \r
431         return(NO);\r
432 }\r
433 \r
434 \r
435 // UTF-8対応\r
436 int ConvNoConv(CODECONVINFO *cInfo)\r
437 {\r
438         int Continue;\r
439         Continue = NO;\r
440         if(cInfo->BufSize >= cInfo->StrLen)\r
441                 cInfo->OutLen = cInfo->StrLen;\r
442         else\r
443         {\r
444                 cInfo->OutLen = cInfo->BufSize;\r
445                 Continue = YES;\r
446         }\r
447         memcpy(cInfo->Buf, cInfo->Str, sizeof(char) * cInfo->OutLen);\r
448         cInfo->Str += cInfo->OutLen;\r
449         cInfo->StrLen -= cInfo->OutLen;\r
450         return Continue;\r
451 }\r
452 \r
453 /*----- EUC漢字コードをSHIFT-JIS漢字コードに変換 ------------------------------\r
454 *\r
455 *       Parameter\r
456 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
457 *\r
458 *       Return Value\r
459 *               int くり返しフラグ (YES/NO)\r
460 *\r
461 *       Note\r
462 *               くり返しフラグがYESの時は、cInfoの内容を変えずにもう一度呼ぶこと\r
463 *----------------------------------------------------------------------------*/\r
464 \r
465 int ConvEUCtoSJIS(CODECONVINFO *cInfo)\r
466 {\r
467         int Kcode;\r
468         char *Str;\r
469         char *Put;\r
470         char *Limit;\r
471         int Continue;\r
472 \r
473         cInfo->KanaProc = &ConvEUCtoSJISkanaProc;\r
474 \r
475         Continue = NO;\r
476         Str = cInfo->Str;\r
477         Put = cInfo->Buf;\r
478         Limit = cInfo->Buf + cInfo->BufSize - 2;\r
479 \r
480         for(; cInfo->StrLen > 0; cInfo->StrLen--)\r
481         {\r
482                 if(Put >= Limit)\r
483                 {\r
484                         Continue = YES;\r
485                         break;\r
486                 }\r
487 \r
488                 if((*Str & 0x80) != 0)\r
489                 {\r
490                         if(cInfo->KanjiFst == 0)\r
491                                 cInfo->KanjiFst = *Str++;\r
492                         else\r
493                         {\r
494                                 if((uchar)cInfo->KanjiFst == (uchar)0x8E)       /* 半角カタカナ */\r
495                                 {\r
496                                         Put = ConvEUCtoSJISkanaProc(cInfo, *Str++, Put);\r
497                                 }\r
498                                 else\r
499                                 {\r
500                                         Put = ConvEUCtoSJISkanaProc(cInfo, 0, Put);\r
501 \r
502                                         Kcode = _mbcjistojms(((cInfo->KanjiFst & 0x7F) * 0x100) + (*Str++ & 0x7F));\r
503                                         *Put++ = HIGH8(Kcode);\r
504                                         *Put++ = LOW8(Kcode);\r
505                                 }\r
506                                 cInfo->KanjiFst = 0;\r
507                         }\r
508                 }\r
509                 else\r
510                 {\r
511                         Put = ConvEUCtoSJISkanaProc(cInfo, 0, Put);\r
512 \r
513                         if(cInfo->KanjiFst != 0)\r
514                         {\r
515                                 *Put++ = cInfo->KanjiFst;\r
516                                 cInfo->KanjiFst = 0;\r
517                         }\r
518                         *Put++ = *Str++;\r
519                 }\r
520         }\r
521 \r
522         cInfo->Str = Str;\r
523         cInfo->OutLen = Put - cInfo->Buf;\r
524 \r
525         return(Continue);\r
526 }\r
527 \r
528 \r
529 /*----- EUC-->SHIFT-JIS漢字コードに変換の半角カタカナの処理 -------------------\r
530 *\r
531 *       Parameter\r
532 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
533 *               char Dt : 文字\r
534 *               char *Put : データセット位置\r
535 *\r
536 *       Return Value\r
537 *               char *次のデータセット位置\r
538 *----------------------------------------------------------------------------*/\r
539 \r
540 static char *ConvEUCtoSJISkanaProc(CODECONVINFO *cInfo, char Dt, char *Put)\r
541 {\r
542         int Kcode;\r
543         int Daku;\r
544 \r
545         if(cInfo->KanaCnv == NO)\r
546         {\r
547                 if(Dt != 0)\r
548                         *Put++ = Dt;\r
549         }\r
550         else\r
551         {\r
552                 if(cInfo->KanaPrev != 0)\r
553                 {\r
554                         Daku = AskDakuon(cInfo->KanaPrev, Dt);\r
555 \r
556                         Kcode = _mbcjistojms(HanKataToZen(cInfo->KanaPrev)) + Daku;\r
557                         *Put++ = HIGH8(Kcode);\r
558                         *Put++ = LOW8(Kcode);\r
559 \r
560                         if(Daku == 0)\r
561                                 cInfo->KanaPrev = Dt;\r
562                         else\r
563                                 cInfo->KanaPrev = 0;\r
564                 }\r
565                 else\r
566                         cInfo->KanaPrev = Dt;\r
567         }\r
568         return(Put);\r
569 }\r
570 \r
571 \r
572 /*----- JIS漢字コードをSHIFT-JIS漢字コードに変換 ------------------------------\r
573 *\r
574 *       Parameter\r
575 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
576 *\r
577 *       Return Value\r
578 *               int くり返しフラグ (YES/NO)\r
579 *\r
580 *       Note\r
581 *               くり返しフラグがYESの時は、cInfoの内容を変えずにもう一度呼ぶこと\r
582 *\r
583 *               エスケープコードは、次のものに対応している\r
584 *                       漢字開始            <ESC>$B         <ESC>$@\r
585 *                       半角カナ開始      <ESC>(I\r
586 *                       漢字終了            <ESC>(B         <ESC>(J         <ESC>(H\r
587 *----------------------------------------------------------------------------*/\r
588 \r
589 int ConvJIStoSJIS(CODECONVINFO *cInfo)\r
590 {\r
591         int Kcode;\r
592         char *Str;\r
593         char *Put;\r
594         char *Limit;\r
595         int Continue;\r
596 \r
597         cInfo->KanaProc = &ConvJIStoSJISkanaProc;\r
598 \r
599         Continue = NO;\r
600         Str = cInfo->Str;\r
601         Put = cInfo->Buf;\r
602         Limit = cInfo->Buf + cInfo->BufSize - 3;\r
603 \r
604         for(; cInfo->StrLen > 0; cInfo->StrLen--)\r
605         {\r
606                 if(Put >= Limit)\r
607                 {\r
608                         Continue = YES;\r
609                         break;\r
610                 }\r
611 \r
612                 if(cInfo->EscProc == 0)\r
613                 {\r
614                         if(*Str == 0x1B)\r
615                         {\r
616                                 if(cInfo->KanjiFst != 0)\r
617                                 {\r
618                                         *Put++ = cInfo->KanjiFst;\r
619                                         cInfo->KanjiFst = 0;\r
620                                 }\r
621                                 Put = ConvJIStoSJISkanaProc(cInfo, 0, Put);\r
622 \r
623                                 cInfo->EscCode[cInfo->EscProc] = *Str++;\r
624                                 cInfo->EscProc++;\r
625                         }\r
626                         else\r
627                         {\r
628                                 if(cInfo->KanjiMode == CONV_KANA)\r
629                                 {\r
630                                         if(cInfo->KanjiFst != 0)\r
631                                         {\r
632                                                 *Put++ = cInfo->KanjiFst;\r
633                                                 cInfo->KanjiFst = 0;\r
634                                         }\r
635 \r
636                                         if((*Str >= 0x21) && (*Str <= 0x5F))\r
637                                         {\r
638                                                 Put = ConvJIStoSJISkanaProc(cInfo, *Str++, Put);\r
639                                         }\r
640                                         else\r
641                                         {\r
642                                                 Put = ConvJIStoSJISkanaProc(cInfo, 0, Put);\r
643                                                 *Put++ = *Str++;\r
644                                         }\r
645                                 }\r
646                                 else if(cInfo->KanjiMode == CONV_KANJI)\r
647                                 {\r
648                                         Put = ConvJIStoSJISkanaProc(cInfo, 0, Put);\r
649                                         if((*Str >= 0x21) && (*Str <= 0x7E))\r
650                                         {\r
651                                                 if(cInfo->KanjiFst == 0)\r
652                                                         cInfo->KanjiFst = *Str++;\r
653                                                 else\r
654                                                 {\r
655                                                         Kcode = _mbcjistojms((cInfo->KanjiFst * 0x100) + *Str++);\r
656                                                         *Put++ = HIGH8(Kcode);\r
657                                                         *Put++ = LOW8(Kcode);\r
658                                                         cInfo->KanjiFst = 0;\r
659                                                 }\r
660                                         }\r
661                                         else\r
662                                         {\r
663                                                 if(cInfo->KanjiFst == 0)\r
664                                                         *Put++ = *Str++;\r
665                                                 else\r
666                                                 {\r
667                                                         *Put++ = cInfo->KanjiFst;\r
668                                                         *Put++ = *Str++;\r
669                                                         cInfo->KanjiFst = 0;\r
670                                                 }\r
671                                         }\r
672                                 }\r
673                                 else\r
674                                 {\r
675                                         Put = ConvJIStoSJISkanaProc(cInfo, 0, Put);\r
676                                         *Put++ = *Str++;\r
677                                 }\r
678                         }\r
679                 }\r
680                 else if(cInfo->EscProc == 1)\r
681                 {\r
682                         if((*Str == '$') || (*Str == '('))\r
683                         {\r
684                                 cInfo->EscCode[cInfo->EscProc] = *Str++;\r
685                                 cInfo->EscProc++;\r
686                         }\r
687                         else\r
688                         {\r
689                                 *Put++ = cInfo->EscCode[0];\r
690                                 *Put++ = *Str++;\r
691                                 cInfo->EscProc = 0;\r
692                         }\r
693                 }\r
694                 else if(cInfo->EscProc == 2)\r
695                 {\r
696                         if((cInfo->EscCode[1] == '$') && ((*Str == 'B') || (*Str == '@')))\r
697                                 cInfo->KanjiMode = CONV_KANJI;\r
698                         else if((cInfo->EscCode[1] == '(') && (*Str == 'I'))\r
699                                 cInfo->KanjiMode = CONV_KANA;\r
700                         else if((cInfo->EscCode[1] == '(') && ((*Str == 'B') || (*Str == 'J') || (*Str == 'H')))\r
701                                 cInfo->KanjiMode = CONV_ASCII;\r
702                         else\r
703                         {\r
704                                 *Put++ = cInfo->EscCode[0];\r
705                                 *Put++ = cInfo->EscCode[1];\r
706                                 if((cInfo->KanjiMode == CONV_KANJI) && ((*Str >= 0x21) && (*Str <= 0x7E)))\r
707                                         cInfo->KanjiFst = *Str;\r
708                                 else\r
709                                         *Put++ = *Str;\r
710                         }\r
711                         Str++;\r
712                         cInfo->EscProc = 0;\r
713                 }\r
714         }\r
715 \r
716         cInfo->Str = Str;\r
717         cInfo->OutLen = Put - cInfo->Buf;\r
718 \r
719         return(Continue);\r
720 }\r
721 \r
722 \r
723 /*----- JIS-->SHIFT-JIS漢字コードに変換の半角カタカナの処理 -------------------\r
724 *\r
725 *       Parameter\r
726 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
727 *               char Dt : 文字\r
728 *               char *Put : データセット位置\r
729 *\r
730 *       Return Value\r
731 *               char *次のデータセット位置\r
732 *----------------------------------------------------------------------------*/\r
733 \r
734 static char *ConvJIStoSJISkanaProc(CODECONVINFO *cInfo, char Dt, char *Put)\r
735 {\r
736         int Kcode;\r
737         int Daku;\r
738 \r
739         Dt = (uchar)Dt + (uchar)0x80;\r
740         if(cInfo->KanaCnv == NO)\r
741         {\r
742                 if((uchar)Dt != (uchar)0x80)\r
743                         *Put++ = Dt;\r
744         }\r
745         else\r
746         {\r
747                 if(cInfo->KanaPrev != 0)\r
748                 {\r
749                         Daku = AskDakuon(cInfo->KanaPrev, Dt);\r
750                         Kcode = _mbcjistojms(HanKataToZen(cInfo->KanaPrev)) + Daku;\r
751                         *Put++ = HIGH8(Kcode);\r
752                         *Put++ = LOW8(Kcode);\r
753 \r
754                         if((Daku == 0) && ((uchar)Dt != (uchar)0x80))\r
755                                 cInfo->KanaPrev = Dt;\r
756                         else\r
757                                 cInfo->KanaPrev = 0;\r
758                 }\r
759                 else if((uchar)Dt != (uchar)0x80)\r
760                         cInfo->KanaPrev = Dt;\r
761         }\r
762         return(Put);\r
763 }\r
764 \r
765 \r
766 /*----- Samba-HEX/Samba-CAP漢字コードをSHIFT-JIS漢字コードに変換 --------------\r
767 *\r
768 *       Parameter\r
769 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
770 *\r
771 *       Return Value\r
772 *               int くり返しフラグ (YES/NO)\r
773 *\r
774 *       Note\r
775 *               くり返しフラグがYESの時は、cInfoの内容を変えずにもう一度呼ぶこと\r
776 *               分割された入力文字列の変換はサポートしていない\r
777 *               半角カタカナの変換設定には対応していない\r
778 *----------------------------------------------------------------------------*/\r
779 \r
780 int ConvSMBtoSJIS(CODECONVINFO *cInfo)\r
781 {\r
782         char *Str;\r
783         char *Put;\r
784         char *Limit;\r
785         int Continue;\r
786 \r
787         Continue = NO;\r
788         Str = cInfo->Str;\r
789         Put = cInfo->Buf;\r
790         Limit = cInfo->Buf + cInfo->BufSize - 2;\r
791 \r
792         for(; cInfo->StrLen > 0; cInfo->StrLen--)\r
793         {\r
794                 if(Put >= Limit)\r
795                 {\r
796                         Continue = YES;\r
797                         break;\r
798                 }\r
799 \r
800                 if((*Str == SAMBA_HEX_TAG) && (cInfo->StrLen >= 3))\r
801                 {\r
802                         if(isxdigit(*(Str+1)) && isxdigit(*(Str+2)))\r
803                         {\r
804                                 *Put++ = N2INT(hex2bin(*(Str+1)), hex2bin(*(Str+2)));\r
805                                 Str += 3;\r
806                                 cInfo->StrLen -= 2;\r
807                         }\r
808                         else\r
809                                 *Put++ = *Str++;\r
810                 }\r
811                 else\r
812                         *Put++ = *Str++;\r
813         }\r
814 \r
815         cInfo->Str = Str;\r
816         cInfo->OutLen = Put - cInfo->Buf;\r
817 \r
818         return(Continue);\r
819 }\r
820 \r
821 \r
822 /*----- SHIFT-JIS漢字コードをEUC漢字コードに変換 ------------------------------\r
823 *\r
824 *       Parameter\r
825 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
826 *\r
827 *       Return Value\r
828 *               int くり返しフラグ (YES/NO)\r
829 *\r
830 *       Note\r
831 *               くり返しフラグがYESの時は、cInfoの内容を変えずにもう一度呼ぶこと\r
832 *----------------------------------------------------------------------------*/\r
833 \r
834 int ConvSJIStoEUC(CODECONVINFO *cInfo)\r
835 {\r
836         int Kcode;\r
837         char *Str;\r
838         char *Put;\r
839         char *Limit;\r
840         int Continue;\r
841 \r
842         cInfo->KanaProc = &ConvSJIStoEUCkanaProc;\r
843 \r
844         Continue = NO;\r
845         Str = cInfo->Str;\r
846         Put = cInfo->Buf;\r
847         Limit = cInfo->Buf + cInfo->BufSize - 2;\r
848 \r
849         for(; cInfo->StrLen > 0; cInfo->StrLen--)\r
850         {\r
851                 if(Put >= Limit)\r
852                 {\r
853                         Continue = YES;\r
854                         break;\r
855                 }\r
856 \r
857                 if(cInfo->KanjiFst == 0)\r
858                 {\r
859                         if((((uchar)*Str >= (uchar)0x81) && ((uchar)*Str <= (uchar)0x9F)) ||\r
860                            ((uchar)*Str >= (uchar)0xE0))\r
861                         {\r
862                                 Put = ConvSJIStoEUCkanaProc(cInfo, 0, Put);\r
863                                 cInfo->KanjiFst = *Str++;\r
864                         }\r
865                         else if(((uchar)*Str >= (uchar)0xA0) && ((uchar)*Str <= (uchar)0xDF))\r
866                         {\r
867                                 Put = ConvSJIStoEUCkanaProc(cInfo, *Str++, Put);\r
868                         }\r
869                         else\r
870                         {\r
871                                 Put = ConvSJIStoEUCkanaProc(cInfo, 0, Put);\r
872                                 *Put++ = *Str++;\r
873                         }\r
874                 }\r
875                 else\r
876                 {\r
877                         if((uchar)*Str >= (uchar)0x40)\r
878                         {\r
879                                 Kcode = ConvertIBMExtendedChar(((uchar)cInfo->KanjiFst * 0x100) + (uchar)*Str++);\r
880                                 Kcode = _mbcjmstojis(Kcode);\r
881                                 *Put++ = HIGH8(Kcode) | 0x80;\r
882                                 *Put++ = LOW8(Kcode) | 0x80;\r
883                         }\r
884                         else\r
885                         {\r
886                                 *Put++ = cInfo->KanjiFst;\r
887                                 *Put++ = *Str++;\r
888                         }\r
889                         cInfo->KanjiFst = 0;\r
890                 }\r
891         }\r
892 \r
893         cInfo->Str = Str;\r
894         cInfo->OutLen = Put - cInfo->Buf;\r
895 \r
896         return(Continue);\r
897 }\r
898 \r
899 \r
900 /*----- SHIFT-JIS-->EUC漢字コードに変換の半角カタカナの処理 -------------------\r
901 *\r
902 *       Parameter\r
903 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
904 *               char Dt : 文字\r
905 *               char *Put : データセット位置\r
906 *\r
907 *       Return Value\r
908 *               char *次のデータセット位置\r
909 *----------------------------------------------------------------------------*/\r
910 \r
911 static char *ConvSJIStoEUCkanaProc(CODECONVINFO *cInfo, char Dt, char *Put)\r
912 {\r
913         int Kcode;\r
914         int Daku;\r
915 \r
916         if(cInfo->KanaCnv == NO)\r
917         {\r
918                 if(Dt != 0)\r
919                 {\r
920                         Kcode = 0x8E00 + (uchar)Dt;\r
921                         *Put++ = HIGH8(Kcode) | 0x80;\r
922                         *Put++ = LOW8(Kcode) | 0x80;\r
923                 }\r
924         }\r
925         else\r
926         {\r
927                 if(cInfo->KanaPrev != 0)\r
928                 {\r
929                         Daku = AskDakuon(cInfo->KanaPrev, Dt);\r
930                         Kcode = HanKataToZen(cInfo->KanaPrev) + Daku;\r
931                         *Put++ = HIGH8(Kcode) | 0x80;\r
932                         *Put++ = LOW8(Kcode) | 0x80;\r
933 \r
934                         if(Daku == 0)\r
935                                 cInfo->KanaPrev = Dt;\r
936                         else\r
937                                 cInfo->KanaPrev = 0;\r
938                 }\r
939                 else\r
940                         cInfo->KanaPrev = Dt;\r
941         }\r
942         return(Put);\r
943 }\r
944 \r
945 \r
946 /*----- SHIFT-JIS漢字コードをJIS漢字コードに変換 ------------------------------\r
947 *\r
948 *       Parameter\r
949 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
950 *\r
951 *       Return Value\r
952 *               int くり返しフラグ (YES/NO)\r
953 *\r
954 *       Note\r
955 *               くり返しフラグがYESの時は、cInfoの内容を変えずにもう一度呼ぶこと\r
956 *\r
957 *               エスケープコードは、次のものを使用する\r
958 *                       漢字開始            <ESC>$B\r
959 *                       半角カナ開始      <ESC>(I\r
960 *                       漢字終了            <ESC>(B\r
961 *----------------------------------------------------------------------------*/\r
962 \r
963 int ConvSJIStoJIS(CODECONVINFO *cInfo)\r
964 {\r
965         int Kcode;\r
966         char *Str;\r
967         char *Put;\r
968         char *Limit;\r
969         int Continue;\r
970 \r
971         cInfo->KanaProc = &ConvSJIStoJISkanaProc;\r
972 \r
973         Continue = NO;\r
974         Str = cInfo->Str;\r
975         Put = cInfo->Buf;\r
976         Limit = cInfo->Buf + cInfo->BufSize - 5;\r
977 \r
978         for(; cInfo->StrLen > 0; cInfo->StrLen--)\r
979         {\r
980                 if(Put >= Limit)\r
981                 {\r
982                         Continue = YES;\r
983                         break;\r
984                 }\r
985 \r
986                 if(cInfo->KanjiFst == 0)\r
987                 {\r
988                         if((((uchar)*Str >= (uchar)0x81) && ((uchar)*Str <= (uchar)0x9F)) ||\r
989                            ((uchar)*Str >= (uchar)0xE0))\r
990                         {\r
991                                 Put = ConvSJIStoJISkanaProc(cInfo, 0, Put);\r
992                                 cInfo->KanjiFst = *Str++;\r
993                         }\r
994                         else if(((uchar)*Str >= (uchar)0xA0) && ((uchar)*Str <= (uchar)0xDF))\r
995                         {\r
996                                 Put = ConvSJIStoJISkanaProc(cInfo, *Str++, Put);\r
997                         }\r
998                         else\r
999                         {\r
1000                                 Put = ConvSJIStoJISkanaProc(cInfo, 0, Put);\r
1001                                 if(cInfo->KanjiMode != CONV_ASCII)\r
1002                                 {\r
1003                                         *Put++ = 0x1B;\r
1004                                         *Put++ = '(';\r
1005                                         *Put++ = 'B';\r
1006                                         cInfo->KanjiMode = CONV_ASCII;\r
1007                                 }\r
1008                                 *Put++ = *Str++;\r
1009                         }\r
1010                 }\r
1011                 else\r
1012                 {\r
1013                         Put = ConvSJIStoJISkanaProc(cInfo, 0, Put);\r
1014                         if((uchar)*Str >= (uchar)0x40)\r
1015                         {\r
1016                                 if(cInfo->KanjiMode != CONV_KANJI)\r
1017                                 {\r
1018                                         *Put++ = 0x1B;\r
1019                                         *Put++ = '$';\r
1020                                         *Put++ = 'B';\r
1021                                         cInfo->KanjiMode = CONV_KANJI;\r
1022                                 }\r
1023 \r
1024                                 Kcode = ConvertIBMExtendedChar(((uchar)cInfo->KanjiFst * 0x100) + (uchar)*Str++);\r
1025                                 Kcode = _mbcjmstojis(Kcode);\r
1026                                 *Put++ = HIGH8(Kcode);\r
1027                                 *Put++ = LOW8(Kcode);\r
1028                         }\r
1029                         else\r
1030                         {\r
1031                                 if(cInfo->KanjiMode != CONV_ASCII)\r
1032                                 {\r
1033                                         *Put++ = 0x1B;\r
1034                                         *Put++ = '(';\r
1035                                         *Put++ = 'B';\r
1036                                         cInfo->KanjiMode = CONV_ASCII;\r
1037                                 }\r
1038                                 *Put++ = cInfo->KanjiFst;\r
1039                                 *Put++ = *Str++;\r
1040                         }\r
1041                         cInfo->KanjiFst = 0;\r
1042                 }\r
1043         }\r
1044 \r
1045         cInfo->Str = Str;\r
1046         cInfo->OutLen = Put - cInfo->Buf;\r
1047 \r
1048         return(Continue);\r
1049 }\r
1050 \r
1051 \r
1052 /*----- SHIFT-JIS-->JIS漢字コードに変換の半角カタカナの処理 -------------------\r
1053 *\r
1054 *       Parameter\r
1055 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
1056 *               char Dt : 文字\r
1057 *               char *Put : データセット位置\r
1058 *\r
1059 *       Return Value\r
1060 *               char *次のデータセット位置\r
1061 *----------------------------------------------------------------------------*/\r
1062 \r
1063 static char *ConvSJIStoJISkanaProc(CODECONVINFO *cInfo, char Dt, char *Put)\r
1064 {\r
1065         int Kcode;\r
1066         int Daku;\r
1067 \r
1068         if(cInfo->KanaCnv == NO)\r
1069         {\r
1070                 if(Dt != 0)\r
1071                 {\r
1072                         if(cInfo->KanjiMode != CONV_KANA)\r
1073                         {\r
1074                                 *Put++ = 0x1B;\r
1075                                 *Put++ = '(';\r
1076                                 *Put++ = 'I';\r
1077                                 cInfo->KanjiMode = CONV_KANA;\r
1078                         }\r
1079                         *Put++ = (uchar)Dt - (uchar)0x80;\r
1080                 }\r
1081         }\r
1082         else\r
1083         {\r
1084                 if(cInfo->KanaPrev != 0)\r
1085                 {\r
1086                         if(cInfo->KanjiMode != CONV_KANJI)\r
1087                         {\r
1088                                 *Put++ = 0x1B;\r
1089                                 *Put++ = '$';\r
1090                                 *Put++ = 'B';\r
1091                                 cInfo->KanjiMode = CONV_KANJI;\r
1092                         }\r
1093                         Daku = AskDakuon(cInfo->KanaPrev, Dt);\r
1094                         Kcode = HanKataToZen(cInfo->KanaPrev) + Daku;\r
1095                         *Put++ = HIGH8(Kcode);\r
1096                         *Put++ = LOW8(Kcode);\r
1097 \r
1098                         if(Daku == 0)\r
1099                                 cInfo->KanaPrev = Dt;\r
1100                         else\r
1101                                 cInfo->KanaPrev = 0;\r
1102                 }\r
1103                 else\r
1104                         cInfo->KanaPrev = Dt;\r
1105         }\r
1106         return(Put);\r
1107 }\r
1108 \r
1109 \r
1110 /*----- SHIFT-JIS漢字コードをSamba-HEX漢字コードに変換 ------------------------\r
1111 *\r
1112 *       Parameter\r
1113 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
1114 *\r
1115 *       Return Value\r
1116 *               int くり返しフラグ (YES/NO)\r
1117 *\r
1118 *       Note\r
1119 *               くり返しフラグがYESの時は、cInfoの内容を変えずにもう一度呼ぶこと\r
1120 *               分割された入力文字列の変換はサポートしていない\r
1121 *               半角カタカナの変換設定には対応していない\r
1122 *----------------------------------------------------------------------------*/\r
1123 \r
1124 int ConvSJIStoSMB_HEX(CODECONVINFO *cInfo)\r
1125 {\r
1126         char *Str;\r
1127         char *Put;\r
1128         char *Limit;\r
1129         int Continue;\r
1130 \r
1131         Continue = NO;\r
1132         Str = cInfo->Str;\r
1133         Put = cInfo->Buf;\r
1134         Limit = cInfo->Buf + cInfo->BufSize - 6;\r
1135 \r
1136         for(; cInfo->StrLen > 0; cInfo->StrLen--)\r
1137         {\r
1138                 if(Put >= Limit)\r
1139                 {\r
1140                         Continue = YES;\r
1141                         break;\r
1142                 }\r
1143 \r
1144                 if((cInfo->StrLen >= 2) &&\r
1145                    ((((uchar)*Str >= (uchar)0x81) && ((uchar)*Str <= (uchar)0x9F)) ||\r
1146                     ((uchar)*Str >= (uchar)0xE0)))\r
1147                 {\r
1148                         sprintf(Put, "%c%02x%c%02x", SAMBA_HEX_TAG, (uchar)*Str, SAMBA_HEX_TAG, (uchar)*(Str+1));\r
1149                         Str += 2;\r
1150                         Put += 6;\r
1151                         cInfo->StrLen--;\r
1152                 }\r
1153                 else if((uchar)*Str >= (uchar)0x80)\r
1154                 {\r
1155                         sprintf(Put, "%c%02x", SAMBA_HEX_TAG, (uchar)*Str++);\r
1156                         Put += 3;\r
1157                 }\r
1158                 else\r
1159                         *Put++ = *Str++;\r
1160         }\r
1161 \r
1162         cInfo->Str = Str;\r
1163         cInfo->OutLen = Put - cInfo->Buf;\r
1164 \r
1165         return(Continue);\r
1166 }\r
1167 \r
1168 \r
1169 /*----- SHIFT-JIS漢字コードをSamba-CAP漢字コードに変換 ------------------------\r
1170 *\r
1171 *       Parameter\r
1172 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
1173 *\r
1174 *       Return Value\r
1175 *               int くり返しフラグ (YES/NO)\r
1176 *\r
1177 *       Note\r
1178 *               くり返しフラグがYESの時は、cInfoの内容を変えずにもう一度呼ぶこと\r
1179 *               分割された入力文字列の変換はサポートしていない\r
1180 *----------------------------------------------------------------------------*/\r
1181 \r
1182 int ConvSJIStoSMB_CAP(CODECONVINFO *cInfo)\r
1183 {\r
1184         char *Str;\r
1185         char *Put;\r
1186         char *Limit;\r
1187         int Continue;\r
1188 \r
1189         Continue = NO;\r
1190         Str = cInfo->Str;\r
1191         Put = cInfo->Buf;\r
1192         Limit = cInfo->Buf + cInfo->BufSize - 6;\r
1193 \r
1194         for(; cInfo->StrLen > 0; cInfo->StrLen--)\r
1195         {\r
1196                 if(Put >= Limit)\r
1197                 {\r
1198                         Continue = YES;\r
1199                         break;\r
1200                 }\r
1201 \r
1202                 if((uchar)*Str >= (uchar)0x80)\r
1203                 {\r
1204                         sprintf(Put, "%c%02x", SAMBA_HEX_TAG, (uchar)*Str++);\r
1205                         Put += 3;\r
1206                 }\r
1207                 else\r
1208                         *Put++ = *Str++;\r
1209         }\r
1210 \r
1211         cInfo->Str = Str;\r
1212         cInfo->OutLen = Put - cInfo->Buf;\r
1213 \r
1214         return(Continue);\r
1215 }\r
1216 \r
1217 \r
1218 /*----- 1バイトカタカナをJIS漢字コードに変換 ---------------------------------\r
1219 *\r
1220 *       Parameter\r
1221 *               char Ch : 1バイトカタカナコード\r
1222 *\r
1223 *       Return Value\r
1224 *               int JIS漢字コード\r
1225 *----------------------------------------------------------------------------*/\r
1226 \r
1227 static int HanKataToZen(char Ch)\r
1228 {\r
1229         static const int Katakana[] = {\r
1230                 0x2121, 0x2123, 0x2156, 0x2157, 0x2122, 0x2126, 0x2572, 0x2521, \r
1231                 0x2523, 0x2525, 0x2527, 0x2529, 0x2563, 0x2565, 0x2567, 0x2543, \r
1232                 0x213C, 0x2522, 0x2524, 0x2526, 0x2528, 0x252A, 0x252B, 0x252D, \r
1233                 0x252F, 0x2531, 0x2533, 0x2535, 0x2537, 0x2539, 0x253B, 0x253D, \r
1234                 0x253F, 0x2541, 0x2544, 0x2546, 0x2548, 0x254A, 0x254B, 0x254C, \r
1235                 0x254D, 0x254E, 0x254F, 0x2552, 0x2555, 0x2558, 0x255B, 0x255E, \r
1236                 0x255F, 0x2560, 0x2561, 0x2562, 0x2564, 0x2566, 0x2568, 0x2569, \r
1237                 0x256A, 0x256B, 0x256C, 0x256D, 0x256F, 0x2573, 0x212B, 0x212C\r
1238         };\r
1239 \r
1240         return(Katakana[(uchar)Ch - (uchar)0xA0]);\r
1241 }\r
1242 \r
1243 \r
1244 /*----- 濁音/半濁音になる文字かチェック --------------------------------------\r
1245 *\r
1246 *       Parameter\r
1247 *               char Ch : 1バイトカタカナコード\r
1248 *               char Daku : 濁点/半濁点\r
1249 *\r
1250 *       Return Value\r
1251 *               int 文字コードに加える値 (0=濁音/半濁音にならない)\r
1252 *----------------------------------------------------------------------------*/\r
1253 \r
1254 static int AskDakuon(char Ch, char Daku)\r
1255 {\r
1256         int Ret;\r
1257 \r
1258         Ret = 0;\r
1259         if((uchar)Daku == (uchar)0xDE)\r
1260         {\r
1261                 if((((uchar)Ch >= (uchar)0xB6) && ((uchar)Ch <= (uchar)0xC4)) ||\r
1262                    (((uchar)Ch >= (uchar)0xCA) && ((uchar)Ch <= (uchar)0xCE)))\r
1263                 {\r
1264                         Ret = 1;\r
1265                 }\r
1266         }\r
1267         else if((uchar)Daku == (uchar)0xDF)\r
1268         {\r
1269                 if(((uchar)Ch >= (uchar)0xCA) && ((uchar)Ch <= (uchar)0xCE))\r
1270                 {\r
1271                         Ret = 2;\r
1272                 }\r
1273         }\r
1274         return(Ret);\r
1275 }\r
1276 \r
1277 \r
1278 \r
1279 \r
1280 \r
1281 \r
1282 \r
1283 \r
1284 \r
1285 \r
1286 \r
1287 \r
1288 /*----- 文字列の漢字コードを調べ、Shift-JISに変換 -----------------------------\r
1289 *\r
1290 *       Parameter\r
1291 *               char *Text : 文字列\r
1292 *               int Pref : SJIS/EUCの優先指定\r
1293 *                     KANJI_SJIS / KANJI_EUC / KANJI_NOCNV=SJIS/EUCのチェックはしない\r
1294 *\r
1295 *       Return Value\r
1296 *               なし\r
1297 *----------------------------------------------------------------------------*/\r
1298 \r
1299 void ConvAutoToSJIS(char *Text, int Pref)\r
1300 {\r
1301         int Code;\r
1302         char *Buf;\r
1303         CODECONVINFO cInfo;\r
1304 \r
1305         Code = CheckKanjiCode(Text, strlen(Text), Pref);\r
1306         if(Code != KANJI_SJIS)\r
1307         {\r
1308                 Buf = malloc(strlen(Text)+1);\r
1309                 if(Buf != NULL)\r
1310                 {\r
1311                         InitCodeConvInfo(&cInfo);\r
1312                         cInfo.KanaCnv = NO;\r
1313                         cInfo.Str = Text;\r
1314                         cInfo.StrLen = strlen(Text);\r
1315                         cInfo.Buf = Buf;\r
1316                         cInfo.BufSize = strlen(Text);\r
1317 \r
1318                         switch(Code)\r
1319                         {\r
1320                                 case KANJI_JIS :\r
1321                                         ConvJIStoSJIS(&cInfo);\r
1322                                         break;\r
1323 \r
1324                                 case KANJI_EUC :\r
1325                                         ConvEUCtoSJIS(&cInfo);\r
1326                                         break;\r
1327                         }\r
1328 \r
1329                         *(Buf + cInfo.OutLen) = NUL;\r
1330                         strcpy(Text, Buf);\r
1331                         free(Buf);\r
1332                 }\r
1333         }\r
1334         return;\r
1335 }\r
1336 \r
1337 \r
1338 /*----- 使われている漢字コードを調べる ----------------------------------------\r
1339 *\r
1340 *       Parameter\r
1341 *               char *Text : 文字列\r
1342 *               int Size : 文字列の長さ\r
1343 *               int Pref : SJIS/EUCの優先指定\r
1344 *                     KANJI_SJIS / KANJI_EUC / KANJI_NOCNV=SJIS/EUCのチェックはしない\r
1345 *\r
1346 *       Return Value\r
1347 *               int 漢字コード (KANJI_xxx)\r
1348 *----------------------------------------------------------------------------*/\r
1349 \r
1350 int CheckKanjiCode(char *Text, int Size, int Pref)\r
1351 {\r
1352         uchar *Pos;\r
1353         uchar *Btm;\r
1354         int Ret;\r
1355         int PointSJIS;\r
1356         int PointEUC;\r
1357 \r
1358         Ret = KANJI_SJIS;\r
1359         if(Size >= 2)\r
1360         {\r
1361                 Ret = -1;\r
1362                 Btm = Text + Size;\r
1363 \r
1364                 /* JIS漢字コードのチェック */\r
1365                 Pos = Text;\r
1366                 while((Pos = memchr(Pos, 0x1b, Btm-Pos-2)) != NULL)\r
1367                 {\r
1368                         Pos++;\r
1369                         if((memcmp(Pos, "$B", 2) == 0) ||       /* <ESC>$B */\r
1370                            (memcmp(Pos, "$@", 2) == 0) ||       /* <ESC>$@ */\r
1371                            (memcmp(Pos, "(I", 2) == 0))         /* <ESC>(I */\r
1372                         {\r
1373                                 Ret = KANJI_JIS;\r
1374                                 break;\r
1375                         }\r
1376                 }\r
1377 \r
1378                 /* EUCとSHIFT-JIS漢字コードのチェック */\r
1379                 if(Ret == -1)\r
1380                 {\r
1381                         if(Pref != KANJI_NOCNV)\r
1382                         {\r
1383                                 Ret = Pref;\r
1384                                 Pos = Text;\r
1385                                 while(Pos < Btm)\r
1386                                 {\r
1387                                         PointSJIS = CheckOnSJIS(Pos, Btm);\r
1388                                         PointEUC = CheckOnEUC(Pos, Btm);\r
1389                                         if(PointSJIS > PointEUC)\r
1390                                         {\r
1391                                                 Ret = KANJI_SJIS;\r
1392                                                 break;\r
1393                                         }\r
1394                                         if(PointSJIS < PointEUC)\r
1395                                         {\r
1396                                                 Ret = KANJI_EUC;\r
1397                                                 break;\r
1398                                         }\r
1399                                         if((Pos = memchr(Pos, '\n', Btm-Pos)) == NULL)\r
1400                                                 break;\r
1401                                         Pos++;\r
1402                                 }\r
1403                         }\r
1404                         else\r
1405                                 Ret = KANJI_SJIS;\r
1406                 }\r
1407         }\r
1408         return(Ret);\r
1409 }\r
1410 \r
1411 \r
1412 /*----- SHIFT-JISコードの可能性があるかチェック --------------------------------\r
1413 *\r
1414 *       Parameter\r
1415 *               uchar *Pos : 文字列\r
1416 *               uchar *Btm : 文字列の末尾\r
1417 *\r
1418 *       Return Value\r
1419 *               int 得点\r
1420 *\r
1421 *       Note\r
1422 *               High    81-FF (A0-DFは半角)  (EB以降はほとんど無い)\r
1423 *               Low             40-FC\r
1424 *----------------------------------------------------------------------------*/\r
1425 \r
1426 static int CheckOnSJIS(uchar *Pos, uchar *Btm)\r
1427 {\r
1428         int FstOnTwo;\r
1429         int Point;\r
1430 \r
1431         FstOnTwo = NO;\r
1432         Point = 100;\r
1433         while((Point > 0) && (Pos < Btm) && (*Pos != '\n'))\r
1434         {\r
1435                 if(FstOnTwo == YES)\r
1436                 {\r
1437                         if((*Pos < 0x40) || (*Pos > 0xFC))      /* 2バイト目は 0x40~0xFC */\r
1438                                 Point = 0;\r
1439                         FstOnTwo = NO;\r
1440                 }\r
1441                 else if(*Pos >= 0x81)\r
1442                 {\r
1443                         if((*Pos < 0xA0) || (*Pos > 0xDF))      /* 半角カナでなければ */\r
1444                         {\r
1445                                 if(*Pos >= 0xEB)                /* 1バイト目は0xEB以降はほとんど無い */\r
1446                                         Point -= 50;\r
1447                                 FstOnTwo = YES;\r
1448                         }\r
1449                 }\r
1450                 Pos++;\r
1451         }\r
1452         if(FstOnTwo == YES)             /* 1バイト目で終わっているのはおかしい  */\r
1453                 Point = 0;\r
1454 \r
1455         return(Point);\r
1456 }\r
1457 \r
1458 \r
1459 /*----- EUCコードの可能性があるかチェック -------------------------------------\r
1460 *\r
1461 *       Parameter\r
1462 *               uchar *Pos : 文字列\r
1463 *               uchar *Btm : 文字列の末尾\r
1464 *\r
1465 *       Return Value\r
1466 *               int 得点\r
1467 *\r
1468 *       Note\r
1469 *               High    A1-FE , 8E\r
1470 *               Low             A1-FE\r
1471 *----------------------------------------------------------------------------*/\r
1472 \r
1473 static int CheckOnEUC(uchar *Pos, uchar *Btm)\r
1474 {\r
1475         int FstOnTwo;\r
1476         int Point;\r
1477 \r
1478         FstOnTwo = 0;\r
1479         Point = 100;\r
1480         while((Point > 0) && (Pos < Btm) && (*Pos != '\n'))\r
1481         {\r
1482                 if(FstOnTwo == 1)\r
1483                 {\r
1484                         if((*Pos < 0xA1) || (*Pos > 0xFE))      /* 2バイト目は 0xA1~0xFE */\r
1485                                 Point = 0;\r
1486                         FstOnTwo = 0;\r
1487                 }\r
1488                 else if(FstOnTwo == 2)          /* 半角カナ */\r
1489                 {\r
1490                         if((*Pos < 0xA0) || (*Pos > 0xDF))      /* 2バイト目は 0xA0~0xDF */\r
1491                                 Point = 0;\r
1492                         FstOnTwo = 0;\r
1493                 }\r
1494                 else\r
1495                 {\r
1496                         if(*Pos == 0x8E)                /* 0x8E??は半角カナ */\r
1497                                 FstOnTwo = 2;\r
1498                         else if((*Pos >= 0xA1) && (*Pos <= 0xFE))\r
1499                                 FstOnTwo = 1;\r
1500                 }\r
1501                 Pos++;\r
1502         }\r
1503         if(FstOnTwo != 0)               /* 1バイト目で終わっているのはおかしい  */\r
1504                 Point = 0;\r
1505 \r
1506         return(Point);\r
1507 }\r
1508 \r
1509 \r
1510 // UTF-8対応 ここから↓\r
1511 /*----- UTF-8漢字コードをSHIFT-JIS漢字コードに変換 ------------------------------\r
1512 *\r
1513 *       Parameter\r
1514 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
1515 *\r
1516 *       Return Value\r
1517 *               int くり返しフラグ (YES/NO)\r
1518 *\r
1519 *       Note\r
1520 *               くり返しフラグがYESの時は、cInfoの内容を変えずにもう一度呼ぶこと\r
1521 *----------------------------------------------------------------------------*/\r
1522 \r
1523 // UTF-8対応\r
1524 // UTF-8からShift_JISへの変換後のバイト列が確定可能な長さを変換後の長さで返す\r
1525 // バイナリ            UTF-8       戻り値 Shift_JIS\r
1526 // E3 81 82 E3 81 84   あい     -> 2      82 A0   あ+結合文字の先頭バイトの可能性(い゛等)\r
1527 // E3 81 82 E3 81      あ+E3 81 -> 0              結合文字の先頭バイトの可能性\r
1528 // E3 81 82 E3         あ+E3    -> 0              結合文字の先頭バイトの可能性\r
1529 // E3 81 82            あ       -> 0              結合文字の先頭バイトの可能性\r
1530 int ConvUTF8NtoSJIS_TruncateToDelimiter(char* pUTF8, int UTF8Length, int* pNewUTF8Length)\r
1531 {\r
1532         int UTF16Length;\r
1533         wchar_t* pUTF16;\r
1534         int SJISLength;\r
1535         int NewSJISLength;\r
1536         int NewUTF16Length;\r
1537         // UTF-8の場合、不完全な文字は常に変換されない\r
1538         // バイナリ            UTF-8       バイナリ      UTF-16 LE\r
1539         // E3 81 82 E3 81 84   あい     -> 42 30 44 30   あい\r
1540         // E3 81 82 E3 81      あ+E3 81 -> 42 30         あ\r
1541         // E3 81 82 E3         あ+E3    -> 42 30         あ\r
1542         UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, NULL, 0);\r
1543         if(!(pUTF16 = (wchar_t*)malloc(sizeof(wchar_t) * UTF16Length)))\r
1544                 return -1;\r
1545         // Shift_JISへ変換した時に文字数が増減する位置がUnicode結合文字の区切り\r
1546         UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, pUTF16, UTF16Length);\r
1547         SJISLength = WideCharToMultiByte(CP_ACP, 0, pUTF16, UTF16Length, NULL, 0, NULL, NULL);\r
1548         NewSJISLength = SJISLength;\r
1549         while(UTF8Length > 0 && NewSJISLength >= SJISLength)\r
1550         {\r
1551                 UTF8Length--;\r
1552                 UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, pUTF16, UTF16Length);\r
1553                 NewSJISLength = WideCharToMultiByte(CP_ACP, 0, pUTF16, UTF16Length, NULL, 0, NULL, NULL);\r
1554         }\r
1555         free(pUTF16);\r
1556         // UTF-16 LE変換した時に文字数が増減する位置がUTF-8の区切り\r
1557         if(pNewUTF8Length)\r
1558         {\r
1559                 NewUTF16Length = UTF16Length;\r
1560                 while(UTF8Length > 0 && NewUTF16Length >= UTF16Length)\r
1561                 {\r
1562                         UTF8Length--;\r
1563                         NewUTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, NULL, 0);\r
1564                 }\r
1565                 if(UTF16Length > 0)\r
1566                         UTF8Length++;\r
1567                 *pNewUTF8Length = UTF8Length;\r
1568         }\r
1569         return NewSJISLength;\r
1570 }\r
1571 \r
1572 int ConvUTF8NtoSJIS(CODECONVINFO *cInfo)\r
1573 {\r
1574         int Continue;\r
1575 \r
1576 //      char temp_string[2048];\r
1577 //      int string_length;\r
1578 \r
1579         // 大きいサイズに対応\r
1580         // 終端のNULLを含むバグを修正\r
1581         int SrcLength;\r
1582         char* pSrc;\r
1583         wchar_t* pUTF16;\r
1584         int UTF16Length;\r
1585 \r
1586         Continue = NO;\r
1587 \r
1588         // 生成される中間コードのサイズを調べる\r
1589 //      string_length = MultiByteToWideChar(\r
1590 //                                              CP_UTF8,                // 変換先文字コード\r
1591 //                                              0,                              // フラグ(0:なし)\r
1592 //                                              cInfo->Str,             // 変換元文字列\r
1593 //                                              -1,                             // 変換元文字列バイト数(-1:自動)\r
1594 //                                              NULL,                   // 変換した文字列の格納先\r
1595 //                                              0                               // 格納先サイズ\r
1596 //                                      );\r
1597         // 前回の変換不能な残りの文字列を入力の先頭に結合\r
1598         SrcLength = cInfo->StrLen + cInfo->EscUTF8Len;\r
1599         if(!(pSrc = (char*)malloc(sizeof(char) * (SrcLength + 1))))\r
1600         {\r
1601                 *(cInfo->Buf) = '\0';\r
1602                 cInfo->BufSize = 0;\r
1603                 return Continue;\r
1604         }\r
1605         memcpy(pSrc, cInfo->EscUTF8, sizeof(char) * cInfo->EscUTF8Len);\r
1606         memcpy(pSrc + cInfo->EscUTF8Len, cInfo->Str, sizeof(char) * cInfo->StrLen);\r
1607         *(pSrc + SrcLength) = '\0';\r
1608         if(cInfo->EscFlush == NO)\r
1609         {\r
1610                 // バッファに収まらないため変換文字数を半減\r
1611                 while(SrcLength > 0 && ConvUTF8NtoSJIS_TruncateToDelimiter(pSrc, SrcLength, &SrcLength) > cInfo->BufSize)\r
1612                 {\r
1613                         SrcLength = SrcLength / 2;\r
1614                 }\r
1615         }\r
1616         UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pSrc, SrcLength, NULL, 0);\r
1617 \r
1618         // サイズ0 or バッファサイズより大きい場合は\r
1619         // cInfo->Bufの最初に'\0'を入れて、\r
1620         // cInfo->BufSizeに0を入れて返す。\r
1621 //      if( string_length == 0 ||\r
1622 //              string_length >= 1024 ){\r
1623 //              *(cInfo->Buf) = '\0';\r
1624 //              cInfo->BufSize = 0;\r
1625 //              return(Continue);\r
1626 //      }\r
1627         if(!(pUTF16 = (wchar_t*)malloc(sizeof(wchar_t) * UTF16Length)))\r
1628         {\r
1629                 free(pSrc);\r
1630                 *(cInfo->Buf) = '\0';\r
1631                 cInfo->BufSize = 0;\r
1632                 return Continue;\r
1633         }\r
1634 \r
1635         // 中間コード(unicode)に変換\r
1636 //      MultiByteToWideChar(\r
1637 //              CP_UTF8,                                                // 変換先文字コード\r
1638 //              0,                                                              // フラグ(0:なし)\r
1639 //              cInfo->Str,                                             // 変換元文字列\r
1640 //              -1,                                                             // 変換元文字列バイト数(-1:自動)\r
1641 //              (unsigned short *)temp_string,  // 変換した文字列の格納先\r
1642 //              1024                                                    // 格納先サイズ\r
1643 //      );\r
1644         MultiByteToWideChar(CP_UTF8, 0, pSrc, SrcLength, pUTF16, UTF16Length);\r
1645 \r
1646         // 生成されるUTF-8コードのサイズを調べる\r
1647 //      string_length = WideCharToMultiByte(\r
1648 //                                              CP_ACP,                 // 変換先文字コード\r
1649 //                                              0,                              // フラグ(0:なし)\r
1650 //                                              (unsigned short *)temp_string,  // 変換元文字列\r
1651 //                                              -1,                             // 変換元文字列バイト数(-1:自動)\r
1652 //                                              NULL,                   // 変換した文字列の格納先\r
1653 //                                              0,                              // 格納先サイズ\r
1654 //                                              NULL,NULL\r
1655 //                                      );\r
1656 \r
1657         // サイズ0 or 出力バッファサイズより大きい場合は、\r
1658         // cInfo->Bufの最初に'\0'を入れて、\r
1659         // cInfo->BufSizeに0を入れて返す。\r
1660 //      if( string_length == 0 ||\r
1661 //              string_length >= cInfo->BufSize ){\r
1662 //              *(cInfo->Buf) = '\0';\r
1663 //              cInfo->BufSize = 0;\r
1664 //              return(Continue);\r
1665 //      }\r
1666 \r
1667         // 出力サイズを設定\r
1668 //      cInfo->OutLen = string_length;\r
1669 \r
1670         // UTF-8コードに変換\r
1671 //      WideCharToMultiByte(\r
1672 //              CP_ACP,                                                 // 変換先文字コード\r
1673 //              0,                                                              // フラグ(0:なし)\r
1674 //              (unsigned short *)temp_string,  // 変換元文字列\r
1675 //              -1,                                                             // 変換元文字列バイト数(-1:自動)\r
1676 //              cInfo->Buf,                                             // 変換した文字列の格納先(BOM:3bytes)\r
1677 //              cInfo->BufSize,                                 // 格納先サイズ\r
1678 //              NULL,NULL\r
1679 //      );\r
1680         cInfo->OutLen = WideCharToMultiByte(CP_ACP, 0, pUTF16, UTF16Length, cInfo->Buf, cInfo->BufSize, NULL, NULL);\r
1681         cInfo->Str += SrcLength - cInfo->EscUTF8Len;\r
1682         cInfo->StrLen -= SrcLength - cInfo->EscUTF8Len;\r
1683         cInfo->EscUTF8Len = 0;\r
1684         if(ConvUTF8NtoSJIS_TruncateToDelimiter(cInfo->Str, cInfo->StrLen, NULL) > 0)\r
1685                 Continue = YES;\r
1686         else\r
1687         {\r
1688                 // 変換不能なため次の入力の先頭に結合\r
1689                 memcpy(cInfo->EscUTF8, cInfo->Str, sizeof(char) * cInfo->StrLen);\r
1690                 cInfo->EscUTF8Len = cInfo->StrLen;\r
1691                 cInfo->Str += cInfo->StrLen;\r
1692                 cInfo->StrLen = 0;\r
1693                 cInfo->FlushProc = ConvUTF8NtoSJIS;\r
1694                 Continue = NO;\r
1695         }\r
1696 \r
1697         free(pSrc);\r
1698         free(pUTF16);\r
1699 \r
1700         return(Continue);\r
1701 }\r
1702 \r
1703 /*----- SHIFT-JIS漢字コードをUTF-8漢字コードに変換 ------------------------------\r
1704 *\r
1705 *       Parameter\r
1706 *               CODECONVINFO *cInfo : 漢字コード変換情報\r
1707 *\r
1708 *       Return Value\r
1709 *               int くり返しフラグ (YES/NO)\r
1710 *\r
1711 *       Note\r
1712 *               くり返しフラグがYESの時は、cInfoの内容を変えずにもう一度呼ぶこと\r
1713 *----------------------------------------------------------------------------*/\r
1714 int ConvSJIStoUTF8N(CODECONVINFO *cInfo)\r
1715 {\r
1716         int Continue;\r
1717 \r
1718 //      char temp_string[2048];\r
1719         int string_length;\r
1720 \r
1721         // 大きいサイズに対応\r
1722         // 終端のNULLを含むバグを修正\r
1723         int SrcLength;\r
1724         char* pSrc;\r
1725         wchar_t* pUTF16;\r
1726         int UTF16Length;\r
1727         int Count;\r
1728 \r
1729         Continue = NO;\r
1730 \r
1731         // 生成される中間コードのサイズを調べる\r
1732 //      string_length = MultiByteToWideChar(\r
1733 //                                              CP_ACP,                 // 変換先文字コード\r
1734 //                                              0,                              // フラグ(0:なし)\r
1735 //                                              cInfo->Str,             // 変換元文字列\r
1736 //                                              -1,                             // 変換元文字列バイト数(-1:自動)\r
1737 //                                              NULL,                   // 変換した文字列の格納先\r
1738 //                                              0                               // 格納先サイズ\r
1739 //                                      );\r
1740         // 前回の変換不能な残りの文字列を入力の先頭に結合\r
1741         SrcLength = cInfo->StrLen + cInfo->EscUTF8Len;\r
1742         if(!(pSrc = (char*)malloc(sizeof(char) * (SrcLength + 1))))\r
1743         {\r
1744                 *(cInfo->Buf) = '\0';\r
1745                 cInfo->BufSize = 0;\r
1746                 return Continue;\r
1747         }\r
1748         memcpy(pSrc, cInfo->EscUTF8, sizeof(char) * cInfo->EscUTF8Len);\r
1749         memcpy(pSrc + cInfo->EscUTF8Len, cInfo->Str, sizeof(char) * cInfo->StrLen);\r
1750         *(pSrc + SrcLength) = '\0';\r
1751         if(cInfo->EscFlush == NO)\r
1752         {\r
1753                 // Shift_JISの場合、不完全な文字でも変換されることがあるため、末尾の不完全な部分を削る\r
1754                 Count = 0;\r
1755                 while(Count < SrcLength)\r
1756                 {\r
1757                         if(((unsigned char)*(pSrc + Count) >= 0x81 && (unsigned char)*(pSrc + Count) <= 0x9f) || (unsigned char)*(pSrc + Count) >= 0xe0)\r
1758                         {\r
1759                                 if((unsigned char)*(pSrc + Count + 1) >= 0x40)\r
1760                                         Count += 2;\r
1761                                 else\r
1762                                 {\r
1763                                         if(Count + 2 > SrcLength)\r
1764                                                 break;\r
1765                                         Count += 1;\r
1766                                 }\r
1767                         }\r
1768                         else\r
1769                                 Count += 1;\r
1770                 }\r
1771                 SrcLength = Count;\r
1772         }\r
1773         UTF16Length = MultiByteToWideChar(CP_ACP, 0, pSrc, SrcLength, NULL, 0);\r
1774 \r
1775         // サイズ0 or バッファサイズより大きい場合は、\r
1776         // cInfo->Bufの最初に'\0'を入れて、\r
1777         // cInfo->BufSizeに0を入れて返す。\r
1778 //      if( string_length == 0 ||\r
1779 //              string_length >= 1024 ){\r
1780 //              *(cInfo->Buf) = '\0';\r
1781 //              cInfo->BufSize = 0;\r
1782 //              return(Continue);\r
1783 //      }\r
1784         if(!(pUTF16 = (wchar_t*)malloc(sizeof(wchar_t) * UTF16Length)))\r
1785         {\r
1786                 free(pSrc);\r
1787                 *(cInfo->Buf) = '\0';\r
1788                 cInfo->BufSize = 0;\r
1789                 return Continue;\r
1790         }\r
1791 \r
1792         // 中間コード(unicode)に変換\r
1793 //      MultiByteToWideChar(\r
1794 //              CP_ACP,                                                 // 変換先文字コード\r
1795 //              0,                                                              // フラグ(0:なし)\r
1796 //              cInfo->Str,                                             // 変換元文字列\r
1797 //              -1,                                                             // 変換元文字列バイト数(-1:自動)\r
1798 //              (unsigned short *)temp_string,  // 変換した文字列の格納先\r
1799 //              1024                                                    // 格納先サイズ\r
1800 //      );\r
1801         MultiByteToWideChar(CP_ACP, 0, pSrc, SrcLength, pUTF16, UTF16Length);\r
1802 \r
1803         // 生成されるUTF-8コードのサイズを調べる\r
1804 //      string_length = WideCharToMultiByte(\r
1805 //                                              CP_UTF8,                // 変換先文字コード\r
1806 //                                              0,                              // フラグ(0:なし)\r
1807 //                                              (unsigned short *)temp_string,  // 変換元文字列\r
1808 //                                              -1,                             // 変換元文字列バイト数(-1:自動)\r
1809 //                                              NULL,                   // 変換した文字列の格納先\r
1810 //                                              0,                              // 格納先サイズ\r
1811 //                                              NULL,NULL\r
1812 //                                      );\r
1813         string_length = WideCharToMultiByte(CP_UTF8, 0, pUTF16, UTF16Length, NULL, 0, NULL, NULL);\r
1814 \r
1815         // サイズ0 or 出力バッファサイズより大きい場合は、\r
1816         // cInfo->Bufの最初に'\0'を入れて、\r
1817         // cInfo->BufSizeに0を入れて返す。\r
1818 //      if( string_length == 0 ||\r
1819 //              string_length >= cInfo->BufSize ){\r
1820 //              *(cInfo->Buf) = '\0';\r
1821 //              cInfo->BufSize = 0;\r
1822 //              return(Continue);\r
1823 //      }\r
1824 \r
1825         // 出力サイズを設定\r
1826 //      cInfo->OutLen = string_length;\r
1827 \r
1828         /*\r
1829         // ↓付けちゃだめ コマンドにも追加されてしまう\r
1830         // 出力文字列の先頭にBOM(byte order mark)をつける\r
1831         *(cInfo->Buf) = (char)0xef;\r
1832         *(cInfo->Buf+1) = (char)0xbb;\r
1833         *(cInfo->Buf+2) = (char)0xbf;\r
1834         */\r
1835 \r
1836         // UTF-8コードに変換\r
1837 //      WideCharToMultiByte(\r
1838 //              CP_UTF8,                                                // 変換先文字コード\r
1839 //              0,                                                              // フラグ(0:なし)\r
1840 //              (unsigned short *)temp_string,  // 変換元文字列\r
1841 //              -1,                                                             // 変換元文字列バイト数(-1:自動)\r
1842 //              cInfo->Buf,                                     // 変換した文字列の格納先(BOM:3bytes)\r
1843 //              cInfo->BufSize,                                 // 格納先サイズ\r
1844 //              NULL,NULL\r
1845 //      );\r
1846         cInfo->OutLen = WideCharToMultiByte(CP_UTF8, 0, pUTF16, UTF16Length, cInfo->Buf, cInfo->BufSize, NULL, NULL);\r
1847         // バッファに収まらないため変換文字数を半減\r
1848         while(cInfo->OutLen == 0 && UTF16Length > 0)\r
1849         {\r
1850                 UTF16Length = UTF16Length / 2;\r
1851                 cInfo->OutLen = WideCharToMultiByte(CP_UTF8, 0, pUTF16, UTF16Length, cInfo->Buf, cInfo->BufSize, NULL, NULL);\r
1852         }\r
1853         // 変換された元の文字列での文字数を取得\r
1854         Count = WideCharToMultiByte(CP_ACP, 0, pUTF16, UTF16Length, NULL, 0, NULL, NULL);\r
1855         // 変換可能な残りの文字数を取得\r
1856         UTF16Length = MultiByteToWideChar(CP_ACP, 0, pSrc + Count, SrcLength - Count, NULL, 0);\r
1857         cInfo->Str += Count - cInfo->EscUTF8Len;\r
1858         cInfo->StrLen -= Count - cInfo->EscUTF8Len;\r
1859         cInfo->EscUTF8Len = 0;\r
1860         if(UTF16Length > 0)\r
1861                 Continue = YES;\r
1862         else\r
1863         {\r
1864                 // 変換不能なため次の入力の先頭に結合\r
1865                 memcpy(cInfo->EscUTF8, cInfo->Str, sizeof(char) * cInfo->StrLen);\r
1866                 cInfo->EscUTF8Len = cInfo->StrLen;\r
1867                 cInfo->Str += cInfo->StrLen;\r
1868                 cInfo->StrLen = 0;\r
1869                 cInfo->FlushProc = ConvSJIStoUTF8N;\r
1870                 Continue = NO;\r
1871         }\r
1872 \r
1873         free(pSrc);\r
1874         free(pUTF16);\r
1875 \r
1876         return(Continue);\r
1877 }\r
1878 // UTF-8対応 ここまで↑\r
1879 \r
1880 // UTF-8 HFS+対応\r
1881 int ConvUTF8NtoUTF8HFSX(CODECONVINFO *cInfo)\r
1882 {\r
1883         int Continue;\r
1884         int SrcLength;\r
1885         char* pSrc;\r
1886         char* pSrcCur;\r
1887         char* pSrcEnd;\r
1888         char* pSrcNext;\r
1889         char* pDstCur;\r
1890         char* pDstEnd;\r
1891         DWORD Code;\r
1892         int Count;\r
1893         wchar_t Temp1[4];\r
1894         wchar_t Temp2[4];\r
1895         char Temp3[16];\r
1896         char* Temp3Cur;\r
1897         char* Temp3End;\r
1898         int TempCount;\r
1899         if(IsUnicodeNormalizationDllLoaded() == NO)\r
1900                 return ConvNoConv(cInfo);\r
1901         Continue = NO;\r
1902         SrcLength = cInfo->StrLen + cInfo->EscUTF8Len;\r
1903         if(!(pSrc = (char*)malloc(sizeof(char) * (SrcLength + 1))))\r
1904         {\r
1905                 *(cInfo->Buf) = '\0';\r
1906                 cInfo->BufSize = 0;\r
1907                 return Continue;\r
1908         }\r
1909         memcpy(pSrc, cInfo->EscUTF8, sizeof(char) * cInfo->EscUTF8Len);\r
1910         memcpy(pSrc + cInfo->EscUTF8Len, cInfo->Str, sizeof(char) * cInfo->StrLen);\r
1911         *(pSrc + SrcLength) = '\0';\r
1912         cInfo->OutLen = 0;\r
1913         pSrcCur = pSrc;\r
1914         pSrcEnd = pSrc + SrcLength;\r
1915         pSrcNext = pSrc;\r
1916         pDstCur = cInfo->Buf;\r
1917         pDstEnd = cInfo->Buf + cInfo->BufSize;\r
1918         while(pSrcCur < pSrcEnd)\r
1919         {\r
1920                 Code = GetNextCharM(pSrcCur, pSrcEnd, (LPCSTR*)&pSrcNext);\r
1921                 if(Code == 0x80000000)\r
1922                 {\r
1923                         if(pSrcNext == pSrcEnd)\r
1924                                 // 入力の末尾が不完全\r
1925                                 break;\r
1926                 }\r
1927                 else if((Code >= 0x00002000 && Code <= 0x00002fff)\r
1928                         || (Code >= 0x0000f900 && Code <= 0x0000faff)\r
1929                         || (Code >= 0x0002f800 && Code <= 0x0002faff))\r
1930                 {\r
1931                         // HFS+特有の例外\r
1932                         Count = PutNextCharM(pDstCur, pDstEnd, &pDstCur, Code);\r
1933                         if(Count > 0)\r
1934                                 cInfo->OutLen += Count;\r
1935                         else\r
1936                         {\r
1937                                 // 出力バッファが不足\r
1938                                 Continue = YES;\r
1939                                 break;\r
1940                         }\r
1941                 }\r
1942                 else\r
1943                 {\r
1944                         // Normalization Form Dに変換\r
1945                         Count = MultiByteToWideChar(CP_UTF8, 0, pSrcCur, (int)(pSrcNext - pSrcCur), Temp1, 4);\r
1946                         Count = p_NormalizeString(NormalizationD, Temp1, Count, Temp2, 4);\r
1947                         Count = WideCharToMultiByte(CP_UTF8, 0, Temp2, Count, Temp3, 16, NULL, NULL);\r
1948                         Temp3Cur = Temp3;\r
1949                         Temp3End = Temp3 + Count;\r
1950                         TempCount = 0;\r
1951                         while(Temp3Cur < Temp3End)\r
1952                         {\r
1953                                 Code = GetNextCharM(Temp3Cur, Temp3End, (LPCSTR*)&Temp3Cur);\r
1954                                 Count = PutNextCharM(pDstCur, pDstEnd, &pDstCur, Code);\r
1955                                 if(Count > 0)\r
1956                                         TempCount += Count;\r
1957                                 else\r
1958                                 {\r
1959                                         // 出力バッファが不足\r
1960                                         Continue = YES;\r
1961                                         break;\r
1962                                 }\r
1963                         }\r
1964                         cInfo->OutLen += TempCount;\r
1965                 }\r
1966                 pSrcCur = pSrcNext;\r
1967         }\r
1968         cInfo->Str += (int)(pSrcCur - pSrc) - cInfo->EscUTF8Len;\r
1969         cInfo->StrLen -= (int)(pSrcCur - pSrc) - cInfo->EscUTF8Len;\r
1970         cInfo->EscUTF8Len = 0;\r
1971         free(pSrc);\r
1972         if(Continue == NO)\r
1973         {\r
1974                 memcpy(cInfo->EscUTF8, cInfo->Str, sizeof(char) * cInfo->StrLen);\r
1975                 cInfo->EscUTF8Len = cInfo->StrLen;\r
1976                 cInfo->Str += cInfo->StrLen;\r
1977                 cInfo->StrLen = 0;\r
1978                 cInfo->FlushProc = ConvUTF8NtoUTF8HFSX;\r
1979         }\r
1980         return YES;\r
1981 }\r
1982 \r
1983 // バグの可能性あり\r
1984 // 確認するまで複数個のバッファを用いた変換には用いないこと\r
1985 // UTF-8 Nomalization Form DからCへの変換後のバイト列が確定可能な長さを変換後のコードポイントの個数で返す\r
1986 // バイナリ            UTF-8       戻り値\r
1987 // E3 81 82 E3 81 84   あい     -> 1   あ+結合文字の先頭バイトの可能性(い゛等)\r
1988 // E3 81 82 E3 81      あ+E3 81 -> 0   結合文字の先頭バイトの可能性\r
1989 // E3 81 82 E3         あ+E3    -> 0   結合文字の先頭バイトの可能性\r
1990 // E3 81 82            あ       -> 0   結合文字の先頭バイトの可能性\r
1991 int ConvUTF8HFSXtoUTF8N_TruncateToDelimiter(char* pUTF8, int UTF8Length, int* pNewUTF8Length)\r
1992 {\r
1993         int UTF16Length;\r
1994         wchar_t* pUTF16;\r
1995         int UTF16HFSXLength;\r
1996         wchar_t* pUTF16HFSX;\r
1997         int CodeCount;\r
1998         int NewCodeCount;\r
1999         int NewUTF16Length;\r
2000         UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, NULL, 0);\r
2001         if(!(pUTF16 = (wchar_t*)malloc(sizeof(wchar_t) * UTF16Length)))\r
2002                 return -1;\r
2003         UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, pUTF16, UTF16Length);\r
2004         UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, NULL, 0);\r
2005         if(!(pUTF16HFSX = (wchar_t*)malloc(sizeof(wchar_t) * UTF16HFSXLength)))\r
2006         {\r
2007                 free(pUTF16);\r
2008                 return -1;\r
2009         }\r
2010         UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, pUTF16HFSX, UTF16HFSXLength);\r
2011         // 変換した時にコードポイントの個数が増減する位置がUnicode結合文字の区切り\r
2012         CodeCount = GetCodeCountW(pUTF16HFSX, UTF16HFSXLength);\r
2013         NewCodeCount = CodeCount;\r
2014         while(UTF8Length > 0 && NewCodeCount >= CodeCount)\r
2015         {\r
2016                 UTF8Length--;\r
2017                 UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, pUTF16, UTF16Length);\r
2018                 UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, pUTF16HFSX, UTF16HFSXLength);\r
2019                 NewCodeCount = GetCodeCountW(pUTF16HFSX, UTF16HFSXLength);\r
2020         }\r
2021         free(pUTF16);\r
2022         free(pUTF16HFSX);\r
2023         // UTF-16 LE変換した時に文字数が増減する位置がUTF-8の区切り\r
2024         if(pNewUTF8Length)\r
2025         {\r
2026                 NewUTF16Length = UTF16Length;\r
2027                 while(UTF8Length > 0 && NewUTF16Length >= UTF16Length)\r
2028                 {\r
2029                         UTF8Length--;\r
2030                         NewUTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, NULL, 0);\r
2031                 }\r
2032                 if(UTF16Length > 0)\r
2033                         UTF8Length++;\r
2034                 *pNewUTF8Length = UTF8Length;\r
2035         }\r
2036         return NewCodeCount;\r
2037 }\r
2038 \r
2039 int ConvUTF8HFSXtoUTF8N(CODECONVINFO *cInfo)\r
2040 {\r
2041         int Continue;\r
2042         int SrcLength;\r
2043         char* pSrc;\r
2044         int UTF16Length;\r
2045         wchar_t* pUTF16;\r
2046         int UTF16HFSXLength;\r
2047         wchar_t* pUTF16HFSX;\r
2048         CODECONVINFO Temp;\r
2049         int Count;\r
2050         if(IsUnicodeNormalizationDllLoaded() == NO)\r
2051                 return ConvNoConv(cInfo);\r
2052         Continue = NO;\r
2053         // 前回の変換不能な残りの文字列を入力の先頭に結合\r
2054         SrcLength = cInfo->StrLen + cInfo->EscUTF8Len;\r
2055         if(!(pSrc = (char*)malloc(sizeof(char) * (SrcLength + 1))))\r
2056         {\r
2057                 *(cInfo->Buf) = '\0';\r
2058                 cInfo->BufSize = 0;\r
2059                 return Continue;\r
2060         }\r
2061         memcpy(pSrc, cInfo->EscUTF8, sizeof(char) * cInfo->EscUTF8Len);\r
2062         memcpy(pSrc + cInfo->EscUTF8Len, cInfo->Str, sizeof(char) * cInfo->StrLen);\r
2063         *(pSrc + SrcLength) = '\0';\r
2064         UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pSrc, SrcLength, NULL, 0);\r
2065         if(!(pUTF16 = (wchar_t*)malloc(sizeof(wchar_t) * UTF16Length)))\r
2066         {\r
2067                 free(pSrc);\r
2068                 *(cInfo->Buf) = '\0';\r
2069                 cInfo->BufSize = 0;\r
2070                 return Continue;\r
2071         }\r
2072         MultiByteToWideChar(CP_UTF8, 0, pSrc, SrcLength, pUTF16, UTF16Length);\r
2073         UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, NULL, 0);\r
2074         if(!(pUTF16HFSX = (wchar_t*)malloc(sizeof(wchar_t) * UTF16HFSXLength)))\r
2075         {\r
2076                 free(pSrc);\r
2077                 free(pUTF16);\r
2078                 *(cInfo->Buf) = '\0';\r
2079                 cInfo->BufSize = 0;\r
2080                 return Continue;\r
2081         }\r
2082         UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, pUTF16HFSX, UTF16HFSXLength);\r
2083         cInfo->OutLen = WideCharToMultiByte(CP_UTF8, 0, pUTF16HFSX, UTF16HFSXLength, cInfo->Buf, cInfo->BufSize, NULL, NULL);\r
2084         if(cInfo->OutLen == 0 && UTF16HFSXLength > 0)\r
2085         {\r
2086                 // バッファに収まらないため変換文字数を半減\r
2087                 Temp = *cInfo;\r
2088                 Temp.StrLen = cInfo->StrLen / 2;\r
2089                 ConvUTF8HFSXtoUTF8N(&Temp);\r
2090                 cInfo->OutLen = Temp.OutLen;\r
2091                 Count = cInfo->StrLen / 2 + cInfo->EscUTF8Len - Temp.StrLen - Temp.EscUTF8Len;\r
2092                 cInfo->Str += Count - cInfo->EscUTF8Len;\r
2093                 cInfo->StrLen -= Count - cInfo->EscUTF8Len;\r
2094                 cInfo->EscUTF8Len = 0;\r
2095         }\r
2096         else\r
2097         {\r
2098                 cInfo->Str += SrcLength - cInfo->EscUTF8Len;\r
2099                 cInfo->StrLen -= SrcLength - cInfo->EscUTF8Len;\r
2100                 cInfo->EscUTF8Len = 0;\r
2101         }\r
2102         if(ConvUTF8HFSXtoUTF8N_TruncateToDelimiter(cInfo->Str, cInfo->StrLen, NULL) > 0)\r
2103                 Continue = YES;\r
2104         else\r
2105         {\r
2106                 // 変換不能なため次の入力の先頭に結合\r
2107                 memcpy(cInfo->EscUTF8, cInfo->Str, sizeof(char) * cInfo->StrLen);\r
2108                 cInfo->EscUTF8Len = cInfo->StrLen;\r
2109                 cInfo->Str += cInfo->StrLen;\r
2110                 cInfo->StrLen = 0;\r
2111                 cInfo->FlushProc = ConvUTF8HFSXtoUTF8N;\r
2112                 Continue = NO;\r
2113         }\r
2114         free(pSrc);\r
2115         free(pUTF16);\r
2116         free(pUTF16HFSX);\r
2117         return Continue;\r
2118 }\r
2119 \r
2120 \r
2121 /*----- IBM拡張漢字をNEC選定IBM拡張漢字等に変換 -------------------------------\r
2122 *\r
2123 *       Parameter\r
2124 *               code    漢字コード\r
2125 *\r
2126 *       Return Value\r
2127 *               int 漢字コード\r
2128 *----------------------------------------------------------------------------*/\r
2129 static int ConvertIBMExtendedChar(int code)\r
2130 {\r
2131         if((code >= 0xfa40) && (code <= 0xfa49))                code -= (0xfa40 - 0xeeef);\r
2132         else if((code >= 0xfa4a) && (code <= 0xfa53))   code -= (0xfa4a - 0x8754);\r
2133         else if((code >= 0xfa54) && (code <= 0xfa57))   code -= (0xfa54 - 0xeef9);\r
2134         else if(code == 0xfa58)                                                 code = 0x878a;\r
2135         else if(code == 0xfa59)                                                 code = 0x8782;\r
2136         else if(code == 0xfa5a)                                                 code = 0x8784;\r
2137         else if(code == 0xfa5b)                                                 code = 0x879a;\r
2138         else if((code >= 0xfa5c) && (code <= 0xfa7e))   code -= (0xfa5c - 0xed40);\r
2139         else if((code >= 0xfa80) && (code <= 0xfa9b))   code -= (0xfa80 - 0xed63);\r
2140         else if((code >= 0xfa9c) && (code <= 0xfafc))   code -= (0xfa9c - 0xed80);\r
2141         else if((code >= 0xfb40) && (code <= 0xfb5b))   code -= (0xfb40 - 0xede1);\r
2142         else if((code >= 0xfb5c) && (code <= 0xfb7e))   code -= (0xfb5c - 0xee40);\r
2143         else if((code >= 0xfb80) && (code <= 0xfb9b))   code -= (0xfb80 - 0xee63);\r
2144         else if((code >= 0xfb9c) && (code <= 0xfbfc))   code -= (0xfb9c - 0xee80);\r
2145         else if((code >= 0xfc40) && (code <= 0xfc4b))   code -= (0xfc40 - 0xeee1);\r
2146         return code;\r
2147 }\r
2148 \r
2149 // UTF-8対応\r
2150 int LoadUnicodeNormalizationDll()\r
2151 {\r
2152         int Sts;\r
2153         char CurDir[FMAX_PATH+1];\r
2154         char SysDir[FMAX_PATH+1];\r
2155         Sts = FFFTP_FAIL;\r
2156         if(GetCurrentDirectory(FMAX_PATH, CurDir) > 0)\r
2157         {\r
2158                 if(GetSystemDirectory(SysDir, FMAX_PATH) > 0)\r
2159                 {\r
2160                         if(SetCurrentDirectory(SysDir))\r
2161                         {\r
2162                                 if((hUnicodeNormalizationDll = LoadLibrary("normaliz.dll")) != NULL)\r
2163                                 {\r
2164                                         if((p_NormalizeString = (_NormalizeString)GetProcAddress(hUnicodeNormalizationDll, "NormalizeString")) != NULL)\r
2165                                                 Sts = FFFTP_SUCCESS;\r
2166                                 }\r
2167                                 SetCurrentDirectory(CurDir);\r
2168                         }\r
2169                 }\r
2170         }\r
2171         return Sts;\r
2172 }\r
2173 \r
2174 void FreeUnicodeNormalizationDll()\r
2175 {\r
2176         if(hUnicodeNormalizationDll != NULL)\r
2177                 FreeLibrary(hUnicodeNormalizationDll);\r
2178         hUnicodeNormalizationDll = NULL;\r
2179         p_NormalizeString = NULL;\r
2180 }\r
2181 \r
2182 int IsUnicodeNormalizationDllLoaded()\r
2183 {\r
2184         int Sts;\r
2185         Sts = FFFTP_FAIL;\r
2186         if(hUnicodeNormalizationDll != NULL && p_NormalizeString != NULL)\r
2187                 Sts = FFFTP_SUCCESS;\r
2188         return Sts;\r
2189 }\r
2190 \r