OSDN Git Service

コンパイル時にNKFを使用して文字コードを変換するようにした
[hengband/hengband.git] / src / japanese.c
1 /* File: japanese.c */
2
3
4 #include "angband.h"
5
6 #ifdef JP
7
8 typedef struct convert_key convert_key;
9
10 struct convert_key
11 {
12         cptr key1;
13         cptr key2;
14 };
15
16 static const convert_key s2j_table[] = {
17         {"mb","nb"}, {"mp","np"}, {"mv","nv"}, {"mm","nm"},
18         {"x","ks"},
19         /* sindar:シンダール  parantir:パランティア  feanor:フェアノール */
20         {"ar$","a-ru$"}, {"ir$","ia$"}, {"or$","o-ru$"},
21         {"ra","ラ"}, {"ri","リ"}, {"ru","ル"}, {"re","レ"}, {"ro","ロ"},
22         {"ir","ia"}, {"ur","ua"}, {"er","ea"}, {"ar","aル"},
23         {"sha","シャ"}, {"shi","シ"}, {"shu","シュ"}, {"she","シェ"}, {"sho","ショ"},
24         {"tha","サ"}, {"thi","シ"}, {"thu","ス"}, {"the","セ"}, {"tho","ソ"},
25         {"cha","ハ"}, {"chi","ヒ"}, {"chu","フ"}, {"che","ヘ"}, {"cho","ホ"},
26         {"dha","ザ"}, {"dhi","ジ"}, {"dhu","ズ"}, {"dhe","ゼ"}, {"dho","ゾ"},
27         {"ba","バ"}, {"bi","ビ"}, {"bu","ブ"}, {"be","ベ"}, {"bo","ボ"},
28         {"ca","カ"}, {"ci","キ"}, {"cu","ク"}, {"ce","ケ"}, {"co","コ"},
29         {"da","ダ"}, {"di","ディ"}, {"du","ドゥ"}, {"de","デ"}, {"do","ド"},
30         {"fa","ファ"}, {"fi","フィ"}, {"fu","フ"}, {"fe","フェ"}, {"fo","フォ"},
31         {"ga","ガ"}, {"gi","ギ"}, {"gu","グ"}, {"ge","ゲ"}, {"go","ゴ"},
32         {"ha","ハ"}, {"hi","ヒ"}, {"hu","フ"}, {"he","ヘ"}, {"ho","ホ"},
33         {"ja","ジャ"}, {"ji","ジ"}, {"ju","ジュ"}, {"je","ジェ"}, {"jo","ジョ"},
34         {"ka","カ"}, {"ki","キ"}, {"ku","ク"}, {"ke","ケ"}, {"ko","コ"},
35         {"la","ラ"}, {"li","リ"}, {"lu","ル"}, {"le","レ"}, {"lo","ロ"},
36         {"ma","マ"}, {"mi","ミ"}, {"mu","ム"}, {"me","メ"}, {"mo","モ"},
37         {"na","ナ"}, {"ni","ニ"}, {"nu","ヌ"}, {"ne","ネ"}, {"no","ノ"},
38         {"pa","パ"}, {"pi","ピ"}, {"pu","プ"}, {"pe","ペ"}, {"po","ポ"},
39         {"qu","ク"},
40         {"sa","サ"}, {"si","シ"}, {"su","ス"}, {"se","セ"}, {"so","ソ"},
41         {"ta","タ"}, {"ti","ティ"}, {"tu","トゥ"}, {"te","テ"}, {"to","ト"},
42         {"va","ヴァ"}, {"vi","ヴィ"}, {"vu","ヴ"}, {"ve","ヴェ"}, {"vo","ヴォ"},
43         {"wa","ワ"}, {"wi","ウィ"}, {"wu","ウ"}, {"we","ウェ"}, {"wo","ウォ"},
44         {"ya","ヤ"}, {"yu","ユ"}, {"yo","ヨ"},
45         {"za","ザ"}, {"zi","ジ"}, {"zu","ズ"}, {"ze","ゼ"}, {"zo","ゾ"},
46         {"dh","ズ"}, {"ch","フ"}, {"th","ス"},
47         {"b","ブ"}, {"c","ク"}, {"d","ド"}, {"f","フ"}, {"g","グ"},
48         {"h","フ"}, {"j","ジュ"}, {"k","ク"}, {"l","ル"}, {"m","ム"},
49         {"n","ン"}, {"p","プ"}, {"q","ク"}, {"r","ル"}, {"s","ス"},
50         {"t","ト"}, {"v","ヴ"}, {"w","ウ"}, {"y","イ"},
51         {"a","ア"}, {"i","イ"}, {"u","ウ"}, {"e","エ"}, {"o","オ"},
52         {"-","ー"},
53         {NULL,NULL}
54 };
55
56 /* シンダリンを日本語の読みに変換する */
57 void sindarin_to_kana(char *kana, const char *sindarin)
58 {
59         char buf[256];
60         int idx;
61
62         sprintf(kana, "%s$", sindarin);
63         for (idx = 0; kana[idx]; idx++)
64                 if (isupper(kana[idx])) kana[idx] = tolower(kana[idx]);
65
66         for (idx = 0; s2j_table[idx].key1 != NULL; idx++)
67         {
68                 cptr pat1 = s2j_table[idx].key1;
69                 cptr pat2 = s2j_table[idx].key2;
70                 int len = strlen(pat1);
71                 char *src = kana;
72                 char *dest = buf;
73
74                 while (*src)
75                 {
76                         if (strncmp(src, pat1, len) == 0)
77                         {
78                                 strcpy(dest, pat2);
79                                 src += len;
80                                 dest += strlen(pat2);
81                         }
82                         else
83                         {
84                                 if (iskanji(*src))
85                                 {
86                                         *dest = *src;
87                                         src++;
88                                         dest++;
89                                 }
90                                 *dest = *src;
91                                 src++;
92                                 dest++;
93                         }
94                 }
95
96                 *dest = 0;
97                 strcpy(kana, buf);
98         }
99
100         idx = 0;
101
102         while (kana[idx] != '$') idx++;
103
104         kana[idx] = '\0';
105 }
106
107
108 /*日本語動詞活用 (打つ>打って,打ち etc) */
109 /* JVERB_AND: 殴る,蹴る > 殴り,蹴る */
110 /* JVERB_TO:  殴る,蹴る > 殴って蹴る */
111 /* JVERB_OR:  殴る,蹴る > 殴ったり蹴ったり */
112
113 static const struct jverb_table_t {
114         const char* from;
115         const char* to[3];
116 } jverb_table[] = {
117         { "する", {"し", "して", "した"}},
118         { "いる", {"いて", "いて", "いた"}},
119
120         { "える", {"え", "えて", "えた"}},
121         { "ける", {"け", "けて", "けた"}},
122         { "げる", {"げ", "えて", "げた"}},
123         { "せる", {"せ", "せて", "せた"}},
124         { "ぜる", {"ぜ", "ぜて", "ぜた"}},
125         { "てる", {"て", "てって", "てった"}},
126         { "でる", {"で", "でて", "でた"}},
127         { "ねる", {"ね", "ねて", "ねた"}},
128         { "へる", {"へ", "へて", "へた"}},
129         { "べる", {"べ", "べて", "べた"}},
130         { "める", {"め", "めて", "めた"}},
131         { "れる", {"れ", "れて", "れた"}},
132
133         { "う", {"い", "って", "った"}},
134         { "く", {"き", "いて", "いた"}},
135         { "ぐ", {"ぎ", "いで", "いだ"}},
136         { "す", {"し", "して", "した"}},
137         { "ず", {"じ", "じて", "じた"}},
138         { "つ", {"ち", "って", "った"}},
139         { "づ", {"ぢ", "って", "った"}},
140         { "ぬ", {"に", "ねて", "ねた"}},
141         { "ふ", {"ひ", "へて", "へた"}},
142         { "ぶ", {"び", "んで", "んだ"}},
143         { "む", {"み", "んで", "んだ"}},
144         { "る", {"り", "って", "った"}},
145         { NULL, {"そして", "ことにより", "ことや"}},
146 };
147
148 void jverb(const char *in , char *out , int flag)
149 {
150         const struct jverb_table_t * p;
151         int in_len = strlen(in);
152
153         strcpy(out, in);
154
155         for (p = jverb_table; p->from; p++) {
156                 int from_len = strlen(p->from);
157                 if (strncmp(&in[in_len-from_len], p->from, from_len) == 0) {
158                         strcpy(&out[in_len - from_len], p->to[flag - 1]);
159                         break;
160                 }
161         }
162
163         if (p->from == NULL)
164                 strcpy(&out[in_len], p->to[flag - 1]);
165 }
166
167
168 /*
169  * Convert SJIS string to EUC string
170  */
171 void sjis2euc(char *str)
172 {
173         int i;
174         unsigned char c1, c2;
175         unsigned char *tmp;
176
177         int len = strlen(str);
178
179         C_MAKE(tmp, len+1, byte);
180
181         for (i = 0; i < len; i++)
182         {
183                 c1 = str[i];
184                 if (c1 & 0x80)
185                 {
186                         i++;
187                         c2 = str[i];
188                         if (c2 >= 0x9f)
189                         {
190                                 c1 = c1 * 2 - (c1 >= 0xe0 ? 0xe0 : 0x60);
191                                 c2 += 2;
192                         }
193                         else
194                         {
195                                 c1 = c1 * 2 - (c1 >= 0xe0 ? 0xe1 : 0x61);
196                                 c2 += 0x60 + (c2 < 0x7f);
197                         }
198                         tmp[i - 1] = c1;
199                         tmp[i] = c2;
200                 }
201                 else
202                         tmp[i] = c1;
203         }
204         tmp[len] = 0;
205         strcpy(str, (char *)tmp);
206
207         C_KILL(tmp, len+1, byte);
208 }  
209
210
211 /*
212  * Convert EUC string to SJIS string
213  */
214 void euc2sjis(char *str)
215 {
216         int i;
217         unsigned char c1, c2;
218         unsigned char *tmp;
219         
220         int len = strlen(str);
221
222         C_MAKE(tmp, len+1, byte);
223
224         for (i = 0; i < len; i++)
225         {
226                 c1 = str[i];
227                 if (c1 & 0x80)
228                 {
229                         i++;
230                         c2 = str[i];
231                         if (c1 % 2)
232                         {
233                                 c1 = (c1 >> 1) + (c1 < 0xdf ? 0x31 : 0x71);
234                                 c2 -= 0x60 + (c2 < 0xe0);
235                         }
236                         else
237                         {
238                                 c1 = (c1 >> 1) + (c1 < 0xdf ? 0x30 : 0x70);
239                                 c2 -= 2;
240                         }
241
242                         tmp[i - 1] = c1;
243                         tmp[i] = c2;
244                 }
245                 else
246                         tmp[i] = c1;
247         }
248         tmp[len] = 0;
249         strcpy(str, (char *)tmp);
250
251         C_KILL(tmp, len+1, byte);
252 }  
253
254
255 /*
256  * strを環境に合った文字コードに変換し、変換前の文字コードを返す。
257  * strの長さに制限はない。
258  *
259  * 0: Unknown
260  * 1: ASCII (Never known to be ASCII in this function.)
261  * 2: EUC
262  * 3: SJIS
263  */
264 byte codeconv(char *str)
265 {
266         byte code = 0;
267         int i;
268
269         for (i = 0; str[i]; i++)
270         {
271                 unsigned char c1;
272                 unsigned char c2;
273
274                 /* First byte */
275                 c1 = str[i];
276
277                 /* ASCII? */
278                 if (!(c1 & 0x80)) continue;
279
280                 /* Second byte */
281                 i++;
282                 c2 = str[i];
283
284                 if (((0xa1 <= c1 && c1 <= 0xdf) || (0xfd <= c1 && c1 <= 0xfe)) &&
285                     (0xa1 <= c2 && c2 <= 0xfe))
286                 {
287                         /* Only EUC is allowed */
288                         if (!code)
289                         {
290                                 /* EUC */
291                                 code = 2;
292                         }
293
294                         /* Broken string? */
295                         else if (code != 2)
296                         {
297                                 /* No conversion */
298                                 return 0;
299                         }
300                 }
301
302                 else if (((0x81 <= c1 && c1 <= 0x9f) &&
303                           ((0x40 <= c2 && c2 <= 0x7e) || (0x80 <= c2 && c2 <= 0xfc))) ||
304                          ((0xe0 <= c1 && c1 <= 0xfc) &&
305                           (0x40 <= c2 && c2 <= 0x7e)))
306                 {
307                         /* Only SJIS is allowed */
308                         if (!code)
309                         {
310                                 /* SJIS */
311                                 code = 3;
312                         }
313
314                         /* Broken string? */
315                         else if (code != 3)
316                         {
317                                 /* No conversion */
318                                 return 0;
319                         }
320                 }
321         }
322
323
324         switch (code)
325         {
326 #ifdef EUC
327         case 3:
328                 /* SJIS -> EUC */
329                 sjis2euc(str);
330                 break;
331 #endif
332
333 #ifdef SJIS
334         case 2:
335                 /* EUC -> SJIS */
336                 euc2sjis(str);
337
338                 break;
339 #endif
340         }
341
342         /* Return kanji code */
343         return code;
344 }
345
346 /* 文字列sのxバイト目が漢字の1バイト目かどうか判定する */
347 bool iskanji2(cptr s, int x)
348 {
349         int i;
350
351         for (i = 0; i < x; i++)
352         {
353                 if (iskanji(s[i])) i++;
354         }
355         if ((x == i) && iskanji(s[x])) return TRUE;
356
357         return FALSE;
358 }
359
360 /*!
361  * @brief 文字列の文字コードがASCIIかどうかを判定する
362  * @param str 判定する文字列へのポインタ
363  * @return 文字列の文字コードがASCIIならTRUE、そうでなければFALSE
364  */
365 static bool is_ascii_str(cptr str)
366 {
367         for (;*str; str++) {
368                 if (!(0x00 < *str && *str <= 0x7f))
369                         return FALSE;
370         }
371         return TRUE;
372 }
373
374 /*!
375  * @brief 文字列の文字コードがUTF-8かどうかを判定する
376  * @param str 判定する文字列へのポインタ
377  * @return 文字列の文字コードがUTF-8ならTRUE、そうでなければFALSE
378  */
379 static bool is_utf8_str(cptr str)
380 {
381         const unsigned char* p;
382         for (p = (const unsigned char*)str; *p; p++) {
383                 int subseq_num = 0;
384                 if (0x00 < *p && *p <= 0x7f) continue;
385                 
386                 if ((*p & 0xe0) == 0xc0) subseq_num = 1;
387                 if ((*p & 0xf0) == 0xe0) subseq_num = 2;
388                 if ((*p & 0xf8) == 0xf0) subseq_num = 3;
389
390                 if (subseq_num == 0) return FALSE;
391                 while (subseq_num--) {
392                         p++;
393                         if (!*p || (*p & 0xc0) != 0x80) return FALSE;
394                 }
395         }
396         return TRUE;
397 }
398
399 #if defined(EUC)
400 #include <iconv.h>
401
402 static const struct ms_to_jis_unicode_conv_t {
403         char from[3];
404         char to[3];
405 } ms_to_jis_unicode_conv[] = {
406         {{0xef, 0xbd, 0x9e}, {0xe3, 0x80, 0x9c}}, /* FULLWIDTH TILDE -> WAVE DASH */
407         {{0xef, 0xbc, 0x8d}, {0xe2, 0x88, 0x92}}, /* FULLWIDTH HYPHEN-MINUS -> MINUS SIGN */
408 };
409
410 static void ms_to_jis_unicode(char* str)
411 {
412         unsigned char* p;
413         for (p = (unsigned char*)str; *p; p++) {
414                 int subseq_num = 0;
415                 if (0x00 < *p && *p <= 0x7f) continue;
416
417                 if ((*p & 0xe0) == 0xc0) subseq_num = 1;
418                 if ((*p & 0xf0) == 0xe0) {
419                         int i;
420                         for (i = 0; i < sizeof(ms_to_jis_unicode_conv) / sizeof(ms_to_jis_unicode_conv[0]); ++ i) {
421                                 const struct ms_to_jis_unicode_conv_t *c = &ms_to_jis_unicode_conv[i];
422                                 if (memcmp(p, c->from, 3) == 0) {
423                                         printf("hoge\n");
424                                         memcpy(p, c->to, 3);
425                                 }
426                         }
427                         subseq_num = 2;
428                 }
429                 if ((*p & 0xf8) == 0xf0) subseq_num = 3;
430
431                 p += subseq_num;
432         }
433 }
434
435 #elif defined(SJIS) && defined(WINDOWS)
436 #include <Windows.h>
437 #endif
438 /*!
439  * @brief 文字コードがUTF-8の文字列をシステムの文字コードに変換する
440  * @param utf8_str 変換するUTF-8の文字列へのポインタ
441  * @param sys_str_buffer 変換したシステムの文字コードの文字列を格納するバッファへのポインタ
442  * @param sys_str_buflen 変換したシステムの文字コードの文字列を格納するバッファの長さ
443  * @return 変換に成功した場合TRUE、失敗した場合FALSEを返す
444  */
445 static bool utf8_to_sys(char* utf8_str, char* sys_str_buffer, size_t sys_str_buflen)
446 {
447 #if defined(EUC)
448
449         iconv_t cd = iconv_open("EUC-JP", "UTF-8");
450         size_t utf8_len = strlen(utf8_str) + 1; /* include termination character */
451         char *from = utf8_str;
452         int ret;
453
454         ms_to_jis_unicode(utf8_str);
455         ret = iconv(cd, &from, &utf8_len, &sys_str_buffer, &sys_str_buflen);
456         iconv_close(cd);
457         return (ret >= 0);
458
459 #elif defined(SJIS) && defined(WINDOWS)
460
461         LPWSTR utf16buf;
462         int input_len = strlen(utf8_str) + 1; /* include termination character */
463
464         C_MAKE(utf16buf, input_len, WCHAR);
465
466         /* UTF-8 -> UTF-16 */
467         if (MultiByteToWideChar( CP_UTF8, 0, utf8_str, input_len, utf16buf, input_len) == 0) {
468                 C_KILL(utf16buf, input_len, WCHAR);
469                 return FALSE;
470         }
471
472         /* UTF-8 -> SJIS(CP932) */
473         if (WideCharToMultiByte( CP_ACP, 0, utf16buf, -1, sys_str_buffer, sys_str_buflen, NULL, NULL ) == 0) {
474                 C_KILL(utf16buf, input_len, WCHAR);
475                 return FALSE;
476         }
477
478         C_KILL(utf16buf, input_len, WCHAR);
479         return TRUE;
480
481 #endif
482 }
483
484 /*!
485  * @brief 受け取った文字列の文字コードを推定し、システムの文字コードへ変換する
486  * @param strbuf 変換する文字列を格納したバッファへのポインタ。
487  *               バッファは変換した文字列で上書きされる。
488  *               UTF-8からSJISもしくはEUCへの変換を想定しているのでバッファの長さが足りなくなることはない。
489  * @param buflen バッファの長さ。
490  * @return なし
491  */
492 void guess_convert_to_system_encoding(char* strbuf, int buflen)
493 {
494         if (is_ascii_str(strbuf)) return;
495
496         if (is_utf8_str(strbuf)) {
497                 char* work;
498                 C_MAKE(work, buflen, char);
499                 my_strcpy(work, strbuf, buflen);
500                 if (!utf8_to_sys(work, strbuf, buflen)) {
501                         msg_print("警告:文字コードの変換に失敗しました");
502                         msg_print(NULL);
503                 }
504                 C_KILL(work, buflen, char);
505         }
506 }
507
508 #endif /* JP */