Files
kichikuou 29a139c8a1 Use the standard integer types
This replaces BYTE, WORD and DWORD types with uint8_t, uint16_t and
uint32_t respectively.
2022-10-29 09:34:21 +09:00

405 lines
14 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* hankaku.c 全角->半角変換
*
* Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
* 1998- <masaki-c@is.aist-nara.ac.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
*/
/* $Id: hankaku.c,v 1.7 2001/03/22 11:10:13 chikama Exp $ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "portab.h"
#include "hankaku.h"
#include "system.h"
static const uint8_t hankakutable[3][192] = {{
// 0x8140 - 0x81ff
' ', 0xa4, 0xa1, ',', '.', 0xa5, ':', ';',
'?', '!', 0xde, 0xdf, 0, '`', 0, '^',
'~', '_', 0, 0, 0, 0, 0, 0,
0, 0, 0, 0xb0, 0, 0, '/', 0,
0, 0, '|', 0, 0, 0, '\'', 0,
'"', '(', ')', 0, 0, '[', ']', '{',
'}', 0, 0, 0, 0, 0xa2, 0xa3, 0,
0, 0, 0, '+', '-', 0, 0, 0,
0, '=', 0, '<', '>', 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, '\\',
'$', 0, 0, '%', '#', '&', '*', '@',
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
},{ // 0x8240 - 0x82ff
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, '0',
'1', '2', '3', '4', '5', '6', '7', '8',
'9', 0, 0, 0, 0, 0, 0, 0,
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 0, 0, 0, 0, 0, 0,
0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
},{ // 0x8340 - 0x83ff
0xa7, 0xb1, 0xa8, 0xb2, 0xa9, 0xb3, 0xaa, 0xb4,
0xab, 0xb5, 0xb6, 0, 0xb7, 0, 0xb8, 0,
0xb9, 0, 0xba, 0, 0xbb, 0, 0xbc, 0,
0xbd, 0, 0xbe, 0, 0xbf, 0, 0xc0, 0,
0xc1, 0, 0xaf, 0xc2, 0, 0xc3, 0, 0xc4,
0, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0,
0, 0xcb, 0, 0, 0xcc, 0, 0, 0xcd,
0, 0, 0xce, 0, 0, 0xcf, 0xd0, 0,
0xd1, 0xd2, 0xd3, 0xac, 0xd4, 0xad, 0xd5, 0xae,
0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0, 0xdc,
0, 0, 0xa6, 0xdd, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
}};
static const uint16_t kanatbl[] = {
0x8140, 0x8142, 0x8175, 0x8176, 0x8141, 0x8145, 0x82f0, 0x829f,
0x82a1, 0x82a3, 0x82a5, 0x82a7, 0x82e1, 0x82e3, 0x82e5, 0x82c1,
0x815b, 0x82a0, 0x82a2, 0x82a4, 0x82a6, 0x82a8, 0x82a9, 0x82ab,
0x82ad, 0x82af, 0x82b1, 0x82b3, 0x82b5, 0x82b7, 0x82b9, 0x82bb,
0x82bd, 0x82bf, 0x82c2, 0x82c4, 0x82c6, 0x82c8, 0x82c9, 0x82ca,
0x82cb, 0x82cc, 0x82cd, 0x82d0, 0x82d3, 0x82d6, 0x82d9, 0x82dc,
0x82dd, 0x82de, 0x82df, 0x82e0, 0x82e2, 0x82e4, 0x82e6, 0x82e7,
0x82e8, 0x82e9, 0x82ea, 0x82eb, 0x82ed, 0x82f1, 0x814a, 0x814b
};
static const char zenkaku_digits[][3] = {
{0x82, 0x4f, 0x00}, /* 0 */
{0x82, 0x50, 0x00}, /* 1 */
{0x82, 0x51, 0x00}, /* 2 */
{0x82, 0x52, 0x00}, /* 3 */
{0x82, 0x53, 0x00}, /* 4 */
{0x82, 0x54, 0x00}, /* 5 */
{0x82, 0x55, 0x00}, /* 6 */
{0x82, 0x56, 0x00}, /* 7 */
{0x82, 0x57, 0x00}, /* 8 */
{0x82, 0x58, 0x00}, /* 9 */
{0x81, 0x40, 0x00}, /* space */
};
static uint8_t *zen2han_sjis(const uint8_t *src) {
uint8_t c0, c1;
char *dst, *_dst;
dst = _dst = malloc(strlen(src) + 1);
if (dst == NULL)
NOMEMERR();
while(0 != (c0 = *src++)) {
if (c0 < 0x81) {
*dst++ = c0;
} else if (c0 <= 0x83) {
c1 = *src++;
uint8_t h = hankakutable[c0 - 0x81][c1 - 0x40];
if (h) {
*dst++ = h;
} else {
*dst++ = c0; *dst++ = c1;
}
} else if (c0 < 0xa0){
*dst++ = c0; *dst++ = *src++;
} else if (c0 < 0xe0){
*dst++ = c0;
} else {
*dst++ = c0; *dst++ = *src++;
}
}
*dst = 0;
return _dst;
}
static char *zen2han_utf8(const char *src) {
char *dst, *_dst;
dst = _dst = malloc(strlen(src) + 1);
if (dst == NULL)
NOMEMERR();
const char *p = src;
while (*p) {
const char *prev = p;
switch (utf8_next_codepoint(&p)) {
case L'’': *dst++ = '\''; break;
case L'”': *dst++ = '"'; break;
case L' ': *dst++ = ' '; break;
case L'、': strcpy(dst, "、"); dst += 3; break;
case L'。': strcpy(dst, "。"); dst += 3; break;
case L'「': strcpy(dst, "「"); dst += 3; break;
case L'」': strcpy(dst, "」"); dst += 3; break;
case L'゛': strcpy(dst, "゙"); dst += 3; break;
case L'゜': strcpy(dst, "゚"); dst += 3; break;
case L'ァ': strcpy(dst, "ァ"); dst += 3; break;
case L'ア': strcpy(dst, "ア"); dst += 3; break;
case L'ィ': strcpy(dst, "ィ"); dst += 3; break;
case L'イ': strcpy(dst, "イ"); dst += 3; break;
case L'ゥ': strcpy(dst, "ゥ"); dst += 3; break;
case L'ウ': strcpy(dst, "ウ"); dst += 3; break;
case L'ェ': strcpy(dst, "ェ"); dst += 3; break;
case L'エ': strcpy(dst, "エ"); dst += 3; break;
case L'ォ': strcpy(dst, "ォ"); dst += 3; break;
case L'オ': strcpy(dst, "オ"); dst += 3; break;
case L'カ': strcpy(dst, "カ"); dst += 3; break;
case L'キ': strcpy(dst, "キ"); dst += 3; break;
case L'ク': strcpy(dst, "ク"); dst += 3; break;
case L'ケ': strcpy(dst, "ケ"); dst += 3; break;
case L'コ': strcpy(dst, "コ"); dst += 3; break;
case L'サ': strcpy(dst, "サ"); dst += 3; break;
case L'シ': strcpy(dst, "シ"); dst += 3; break;
case L'ス': strcpy(dst, "ス"); dst += 3; break;
case L'セ': strcpy(dst, "セ"); dst += 3; break;
case L'ソ': strcpy(dst, "ソ"); dst += 3; break;
case L'タ': strcpy(dst, "タ"); dst += 3; break;
case L'チ': strcpy(dst, "チ"); dst += 3; break;
case L'ッ': strcpy(dst, "ッ"); dst += 3; break;
case L'ツ': strcpy(dst, "ツ"); dst += 3; break;
case L'テ': strcpy(dst, "テ"); dst += 3; break;
case L'ト': strcpy(dst, "ト"); dst += 3; break;
case L'ナ': strcpy(dst, "ナ"); dst += 3; break;
case L'ニ': strcpy(dst, "ニ"); dst += 3; break;
case L'ヌ': strcpy(dst, "ヌ"); dst += 3; break;
case L'ネ': strcpy(dst, "ネ"); dst += 3; break;
case L'ノ': strcpy(dst, "ノ"); dst += 3; break;
case L'ハ': strcpy(dst, "ハ"); dst += 3; break;
case L'ヒ': strcpy(dst, "ヒ"); dst += 3; break;
case L'フ': strcpy(dst, "フ"); dst += 3; break;
case L'ヘ': strcpy(dst, "ヘ"); dst += 3; break;
case L'ホ': strcpy(dst, "ホ"); dst += 3; break;
case L'マ': strcpy(dst, "マ"); dst += 3; break;
case L'ミ': strcpy(dst, "ミ"); dst += 3; break;
case L'ム': strcpy(dst, "ム"); dst += 3; break;
case L'メ': strcpy(dst, "メ"); dst += 3; break;
case L'モ': strcpy(dst, "モ"); dst += 3; break;
case L'ャ': strcpy(dst, "ャ"); dst += 3; break;
case L'ヤ': strcpy(dst, "ヤ"); dst += 3; break;
case L'ュ': strcpy(dst, "ュ"); dst += 3; break;
case L'ユ': strcpy(dst, "ユ"); dst += 3; break;
case L'ョ': strcpy(dst, "ョ"); dst += 3; break;
case L'ヨ': strcpy(dst, "ヨ"); dst += 3; break;
case L'ラ': strcpy(dst, "ラ"); dst += 3; break;
case L'リ': strcpy(dst, "リ"); dst += 3; break;
case L'ル': strcpy(dst, "ル"); dst += 3; break;
case L'レ': strcpy(dst, "レ"); dst += 3; break;
case L'ロ': strcpy(dst, "ロ"); dst += 3; break;
case L'ワ': strcpy(dst, "ワ"); dst += 3; break;
case L'ヲ': strcpy(dst, "ヲ"); dst += 3; break;
case L'ン': strcpy(dst, "ン"); dst += 3; break;
case L'・': strcpy(dst, "・"); dst += 3; break;
case L'ー': strcpy(dst, "ー"); dst += 3; break;
case L'!': *dst++ = '!'; break;
case L'#': *dst++ = '#'; break;
case L'$': *dst++ = '$'; break;
case L'%': *dst++ = '%'; break;
case L'&': *dst++ = '&'; break;
case L'(': *dst++ = '('; break;
case L')': *dst++ = ')'; break;
case L'*': *dst++ = '*'; break;
case L'+': *dst++ = '+'; break;
case L',': *dst++ = ','; break;
case L'-': *dst++ = '-'; break;
case L'.': *dst++ = '.'; break;
case L'/': *dst++ = '/'; break;
case L'0': *dst++ = '0'; break;
case L'1': *dst++ = '1'; break;
case L'2': *dst++ = '2'; break;
case L'3': *dst++ = '3'; break;
case L'4': *dst++ = '4'; break;
case L'5': *dst++ = '5'; break;
case L'6': *dst++ = '6'; break;
case L'7': *dst++ = '7'; break;
case L'8': *dst++ = '8'; break;
case L'9': *dst++ = '9'; break;
case L':': *dst++ = ':'; break;
case L';': *dst++ = ';'; break;
case L'<': *dst++ = '<'; break;
case L'=': *dst++ = '='; break;
case L'>': *dst++ = '>'; break;
case L'?': *dst++ = '?'; break;
case L'@': *dst++ = '@'; break;
case L'A': *dst++ = 'A'; break;
case L'B': *dst++ = 'B'; break;
case L'C': *dst++ = 'C'; break;
case L'D': *dst++ = 'D'; break;
case L'E': *dst++ = 'E'; break;
case L'F': *dst++ = 'F'; break;
case L'G': *dst++ = 'G'; break;
case L'H': *dst++ = 'H'; break;
case L'I': *dst++ = 'I'; break;
case L'J': *dst++ = 'J'; break;
case L'K': *dst++ = 'K'; break;
case L'L': *dst++ = 'L'; break;
case L'M': *dst++ = 'M'; break;
case L'N': *dst++ = 'N'; break;
case L'O': *dst++ = 'O'; break;
case L'P': *dst++ = 'P'; break;
case L'Q': *dst++ = 'Q'; break;
case L'R': *dst++ = 'R'; break;
case L'S': *dst++ = 'S'; break;
case L'T': *dst++ = 'T'; break;
case L'U': *dst++ = 'U'; break;
case L'V': *dst++ = 'V'; break;
case L'W': *dst++ = 'W'; break;
case L'X': *dst++ = 'X'; break;
case L'Y': *dst++ = 'Y'; break;
case L'Z': *dst++ = 'Z'; break;
case L'[': *dst++ = '['; break;
case L']': *dst++ = ']'; break;
case L'^': *dst++ = '^'; break;
case L'_': *dst++ = '_'; break;
case L'`': *dst++ = '`'; break;
case L'a': *dst++ = 'a'; break;
case L'b': *dst++ = 'b'; break;
case L'c': *dst++ = 'c'; break;
case L'd': *dst++ = 'd'; break;
case L'e': *dst++ = 'e'; break;
case L'f': *dst++ = 'f'; break;
case L'g': *dst++ = 'g'; break;
case L'h': *dst++ = 'h'; break;
case L'i': *dst++ = 'i'; break;
case L'j': *dst++ = 'j'; break;
case L'k': *dst++ = 'k'; break;
case L'l': *dst++ = 'l'; break;
case L'm': *dst++ = 'm'; break;
case L'n': *dst++ = 'n'; break;
case L'o': *dst++ = 'o'; break;
case L'p': *dst++ = 'p'; break;
case L'q': *dst++ = 'q'; break;
case L'r': *dst++ = 'r'; break;
case L's': *dst++ = 's'; break;
case L't': *dst++ = 't'; break;
case L'u': *dst++ = 'u'; break;
case L'v': *dst++ = 'v'; break;
case L'w': *dst++ = 'w'; break;
case L'x': *dst++ = 'x'; break;
case L'y': *dst++ = 'y'; break;
case L'z': *dst++ = 'z'; break;
case L'{': *dst++ = '{'; break;
case L'|': *dst++ = '|'; break;
case L'}': *dst++ = '}'; break;
case L' ̄': *dst++ = '~'; break;
case L'¥': *dst++ = '\\'; break;
default:
while (prev < p)
*dst++ = *prev++;
break;
}
}
*dst = 0;
return _dst;
}
uint8_t *zen2han(const uint8_t *src, CharacterEncoding enc) {
switch (enc) {
case SHIFT_JIS:
return zen2han_sjis(src);
case UTF8:
return zen2han_utf8(src);
default:
return (uint8_t *)src;
}
}
uint8_t *han2zen(const uint8_t *src, CharacterEncoding enc) {
if (enc != SHIFT_JIS)
return (uint8_t *)src; // Not implemented
uint8_t c0;
uint8_t *dst, *_dst;
dst = _dst = malloc(strlen(src) * 2 + 1);
if (dst == NULL)
NOMEMERR();
while(0 != (c0 = *src++)) {
if (c0 == 0x20) {
*dst++ = 0x81; *dst++ = 0x40;
} else if (c0 < 0x80) {
*dst++ = c0;
} else if (c0 >= 0xe0) {
*dst++ = (char)c0; *dst++ = *src++;
} else if (c0 >= 0xa0) {
const uint16_t kana = kanatbl[c0 - 0xa0];
*dst++ = kana >> 8; *dst++ = kana & 0xff;
} else {
*dst++ = (char)c0; *dst++ = *src++;
}
}
*dst = 0;
return _dst;
}
char *format_number(int n, int width, char *buf) {
if (width) {
sprintf(buf, "%*d", width, n);
return buf + strlen(buf) - width;
}
sprintf(buf, "%d", n);
return buf;
}
char *format_number_zenkaku(int n, int width, char *buf) {
char work[256];
char *dst = buf;
for (char *s = format_number(n, width, work); *s; s++) {
const char *p = zenkaku_digits[*s == ' ' ? 10 : *s - '0'];
while (*p)
*dst++ = *p++;
}
*dst = '\0';
return buf;
}