mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-09-22 22:48:08 +03:00
[experimental] Unicode mode
This adds "Unicode mode", in which scenarios can be written in any language. xsys35c 1.2.0 and later can produce Unicode scenarios. - nact->encoding represents the current scenario encoding. The initial value is SJIS, and ZU command changes it to UTF8. - Use conversion macros that switch the behavior by the scenario encoding. For example, toUTF8() calls sjis2utf() if the scenario encoding is SJIS, and calls strdup() if it is UTF8. - Fix various string processing functions to work with UTF8.
This commit is contained in:
@@ -104,7 +104,7 @@ void ntmsg_init() {
|
||||
|
||||
|
||||
// 主人公名前
|
||||
nt_sstr_regist_replace(utf2sjis(SNAME_RYO), utf2sjis(SNAME_RYO_DEF));
|
||||
nt_sstr_regist_replace(fromUTF8(SNAME_RYO), fromUTF8(SNAME_RYO_DEF));
|
||||
|
||||
night.msg.cbmove = cb_mousemove;
|
||||
night.msg.cbrelease = cb_keyrelease;
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
#define LOGMSG_LINES 6
|
||||
|
||||
static const char *logmsg[LOGMSG_LINES] = {
|
||||
static const char *logmsg_utf8[LOGMSG_LINES] = {
|
||||
"\n",
|
||||
"※バックログ操作方法※",
|
||||
"[ESC]またはマウス右クリックでゲームに戻る",
|
||||
@@ -110,15 +110,15 @@ static void draw_log() {
|
||||
|
||||
|
||||
int sblog_start(void) {
|
||||
static char *logmsg_sjis[6];
|
||||
if (!logmsg_sjis[0]) {
|
||||
static char *logmsg[LOGMSG_LINES];
|
||||
if (!logmsg[0]) {
|
||||
for (int i = 0; i < LOGMSG_LINES; i++)
|
||||
logmsg_sjis[i] = utf2sjis(logmsg[i]);
|
||||
logmsg[i] = fromUTF8(logmsg_utf8[i]);
|
||||
}
|
||||
|
||||
// 説明文章を追加
|
||||
for (int i = 0; i < LOGMSG_LINES; i++)
|
||||
sact.log = list_append(sact.log, logmsg_sjis[i]);
|
||||
sact.log = list_append(sact.log, logmsg[i]);
|
||||
|
||||
back = sf_dup(sf0);
|
||||
chr = sf_create_surface(sf0->width, sf0->height, 8);
|
||||
|
||||
@@ -186,16 +186,16 @@ void ags_setViewArea(int x, int y, int width, int height) {
|
||||
|
||||
void ags_setWindowTitle(const char *src) {
|
||||
#define TITLEHEAD "XSystem35 Version "VERSION":"
|
||||
BYTE *dst, *d;
|
||||
BYTE *utf, *d;
|
||||
|
||||
dst = sjis2utf(src);
|
||||
if (NULL == (d = malloc(strlen(dst) + strlen(TITLEHEAD) + 1))) {
|
||||
utf = toUTF8(src);
|
||||
if (NULL == (d = malloc(strlen(utf) + strlen(TITLEHEAD) + 1))) {
|
||||
NOMEMERR();
|
||||
}
|
||||
strcpy(d, TITLEHEAD);
|
||||
strcat(d, dst);
|
||||
strcat(d, utf);
|
||||
SetWindowTitle(d);
|
||||
free(dst);
|
||||
free(utf);
|
||||
free(d);
|
||||
}
|
||||
|
||||
@@ -402,7 +402,7 @@ int ags_drawString(int x, int y, const char *src, int col) {
|
||||
if (!check_param_xy(&x, &y)) return 0;
|
||||
|
||||
DspDeviceSync();
|
||||
char *utf8 = sjis2utf(src);
|
||||
char *utf8 = toUTF8(src);
|
||||
w = DrawString(x, y, utf8, col);
|
||||
free(utf8);
|
||||
|
||||
@@ -410,7 +410,7 @@ int ags_drawString(int x, int y, const char *src, int col) {
|
||||
}
|
||||
|
||||
agsurface_t *ags_drawStringToSurface(const char *str) {
|
||||
char *utf8 = sjis2utf(str);
|
||||
char *utf8 = toUTF8(str);
|
||||
agsurface_t *sf = nact->ags.font->get_glyph(utf8);
|
||||
free(utf8);
|
||||
return sf;
|
||||
|
||||
+16
-16
@@ -367,7 +367,7 @@ void commands2F23() {
|
||||
int y = getCaliValue();
|
||||
char *vFileName = sys_getString(0);
|
||||
|
||||
char *fname_utf8 = sjis2utf(vFileName);
|
||||
char *fname_utf8 = toUTF8(vFileName);
|
||||
sysVar[0] = cg_load_with_filename(fname_utf8, x, y);
|
||||
free(fname_utf8);
|
||||
|
||||
@@ -380,7 +380,7 @@ void commands2F24() {
|
||||
int *var = NULL, _var = 0;
|
||||
int num = 0;
|
||||
|
||||
char *fname_utf8 = sjis2utf(file_name);
|
||||
char *fname_utf8 = toUTF8(file_name);
|
||||
switch(type) {
|
||||
case 0:
|
||||
var = getCaliVariable();
|
||||
@@ -412,8 +412,8 @@ void commands2F26() {
|
||||
char *title = sys_getString(0);
|
||||
char *t1, *t2, *t3;
|
||||
|
||||
t1 = sjis2utf(title);
|
||||
t2 = sjis2utf(v_str(dst_no -1));
|
||||
t1 = toUTF8(title);
|
||||
t2 = toUTF8(v_str(dst_no -1));
|
||||
|
||||
mi_param.title = t1;
|
||||
mi_param.oldstring = t2;
|
||||
@@ -426,10 +426,10 @@ void commands2F26() {
|
||||
return;
|
||||
}
|
||||
|
||||
t3 = utf2sjis(mi_param.newstring);
|
||||
t3 = fromUTF8(mi_param.newstring);
|
||||
|
||||
/* 全角文字以外は不可 */
|
||||
if (!sjis_has_hankaku(t3)) {
|
||||
if (nact->encoding != SHIFT_JIS || !sjis_has_hankaku(t3)) {
|
||||
v_strcpy(dst_no -1, t3);
|
||||
}
|
||||
free(t1);
|
||||
@@ -457,7 +457,7 @@ void commands2F28() {
|
||||
|
||||
if (nact->game_title_utf8)
|
||||
free(nact->game_title_utf8);
|
||||
nact->game_title_utf8 = sjis2utf(title);
|
||||
nact->game_title_utf8 = toUTF8(title);
|
||||
|
||||
ags_setWindowTitle(title);
|
||||
|
||||
@@ -478,7 +478,7 @@ void commands2F29() {
|
||||
if (ni_param.title != NULL) {
|
||||
free(ni_param.title);
|
||||
}
|
||||
t = sjis2utf(title);
|
||||
t = toUTF8(title);
|
||||
ni_param.title = t;
|
||||
|
||||
DEBUG_COMMAND("NT(new) %s:\n", title);
|
||||
@@ -489,7 +489,7 @@ void commands2F2A() {
|
||||
char *file_name = sys_getString(0);
|
||||
int *var, _var = 0, cnt;
|
||||
|
||||
char *fname_utf8 = sjis2utf(file_name);
|
||||
char *fname_utf8 = toUTF8(file_name);
|
||||
switch(type) {
|
||||
case 0:
|
||||
var = getCaliVariable();
|
||||
@@ -924,8 +924,8 @@ void commands2F57() {
|
||||
char *t1, *t2, *t3;
|
||||
INPUTSTRING_PARAM p;
|
||||
|
||||
t1 = sjis2utf(sTitle);
|
||||
t2 = sjis2utf(v_str(eStrVar -1));
|
||||
t1 = toUTF8(sTitle);
|
||||
t2 = toUTF8(v_str(eStrVar -1));
|
||||
p.title = t1;
|
||||
p.oldstring = t2;
|
||||
p.max = eLength;
|
||||
@@ -934,10 +934,10 @@ void commands2F57() {
|
||||
if (p.newstring == NULL) {
|
||||
*vResult = 65535;
|
||||
} else {
|
||||
t3 = utf2sjis(p.newstring);
|
||||
if (!sjis_has_hankaku(t3)) {
|
||||
t3 = fromUTF8(p.newstring);
|
||||
if (nact->encoding != SHIFT_JIS || !sjis_has_hankaku(t3)) {
|
||||
v_strcpy(eStrVar -1, t3);
|
||||
*vResult = sjis_count_char(t3);
|
||||
*vResult = v_strlen(eStrVar -1);
|
||||
} else {
|
||||
*vResult = 65535;
|
||||
}
|
||||
@@ -971,7 +971,7 @@ void commands2F5A() {
|
||||
char *sText = sys_getString(0);
|
||||
char *t1;
|
||||
|
||||
t1 = sjis2utf(sText);
|
||||
t1 = toUTF8(sText);
|
||||
menu_msgbox_open(t1);
|
||||
free(t1);
|
||||
|
||||
@@ -982,7 +982,7 @@ void commands2F5B() {
|
||||
int eNum = getCaliValue();
|
||||
char *t1;
|
||||
|
||||
t1 = sjis2utf(v_str(eNum) - 1);
|
||||
t1 = toUTF8(v_str(eNum) - 1);
|
||||
menu_msgbox_open(t1);
|
||||
free(t1);
|
||||
|
||||
|
||||
@@ -1098,6 +1098,8 @@ void check_command(int c0) {
|
||||
undeferr();
|
||||
}
|
||||
break;
|
||||
case 'U':
|
||||
commandZU(); break;
|
||||
case 'Z':
|
||||
switch(sl_getc()) {
|
||||
case 0:
|
||||
|
||||
@@ -304,6 +304,7 @@ extern void commandZI();
|
||||
extern void commandZA();
|
||||
extern void commandZK();
|
||||
extern void commandZR();
|
||||
extern void commandZU();
|
||||
|
||||
/* define in cmd2F.c */
|
||||
extern void commands2F00();
|
||||
|
||||
+5
-1
@@ -22,9 +22,11 @@
|
||||
/* $Id: cmdh.c,v 1.5 2000/09/10 10:39:48 chikama Exp $ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "portab.h"
|
||||
#include "xsystem35.h"
|
||||
#include "utfsjis.h"
|
||||
#include "hankaku.h"
|
||||
|
||||
void commandH() {
|
||||
@@ -32,7 +34,9 @@ void commandH() {
|
||||
int num = getCaliValue();
|
||||
char buf[512];
|
||||
|
||||
sys_addMsg(format_number_zenkaku(num, fig, buf));
|
||||
char *s = fromSJIS(format_number_zenkaku(num, fig, buf));
|
||||
sys_addMsg(s);
|
||||
free(s);
|
||||
|
||||
DEBUG_COMMAND("H %d,%d:\n",fig,num);
|
||||
}
|
||||
|
||||
+2
-2
@@ -112,7 +112,7 @@ void commandLE() {
|
||||
int *var, _var = 0;
|
||||
int num;
|
||||
|
||||
char *fname_utf8 = sjis2utf(filename);
|
||||
char *fname_utf8 = toUTF8(filename);
|
||||
switch(type) {
|
||||
case 0: /* T2 */
|
||||
var = getCaliVariable();
|
||||
@@ -246,7 +246,7 @@ void commandLC() {
|
||||
int y = getCaliValue();
|
||||
char *filename = sys_getString(':');
|
||||
|
||||
char *fname_utf8 = sjis2utf(filename);
|
||||
char *fname_utf8 = toUTF8(filename);
|
||||
sysVar[0] = cg_load_with_filename(fname_utf8, x, y);
|
||||
free(fname_utf8);
|
||||
|
||||
|
||||
+20
-15
@@ -62,34 +62,37 @@ void commandMP() {
|
||||
/* 指定の文字列を指定文字数だけ表示する(Xコマンドの桁数指定) */
|
||||
int num1 = getCaliValue();
|
||||
int num2 = getCaliValue();
|
||||
const char bstr[3] = "\x81\x40"; // full-width whitespace
|
||||
const char *fullwidth_blank[CHARACTER_ENCODING_MAX + 1] = {
|
||||
[SHIFT_JIS] = "\x81\x40",
|
||||
[UTF8] = " ",
|
||||
};
|
||||
const char *src = v_str(num1 - 1);
|
||||
int chars = num2;
|
||||
char *str;
|
||||
|
||||
/* Patched English executable appends num2 spaces instead of truncating */
|
||||
if (have_eng_mp_patch) {
|
||||
str = calloc(strlen(src) + num2 * 2 + 1, 1);
|
||||
str = calloc(strlen(src) + num2 * strlen(fullwidth_blank[nact->encoding]) + 1, 1);
|
||||
if (NULL == str) {
|
||||
NOMEMERR();
|
||||
}
|
||||
strcpy(str, src);
|
||||
}
|
||||
else {
|
||||
str = calloc(num2 * 2 + 1, 1);
|
||||
str = calloc(num2 * MAX_BYTES_PAR_CHAR(nact->encoding) + 1, 1);
|
||||
if (NULL == str) {
|
||||
NOMEMERR();
|
||||
}
|
||||
|
||||
const char *p = src;
|
||||
while (*p && chars > 0) {
|
||||
p += CHECKSJIS1BYTE(*p) ? 2 : 1;
|
||||
p = advance_char(p, nact->encoding);
|
||||
chars--;
|
||||
}
|
||||
strncpy(str, src, p - src);
|
||||
}
|
||||
while (chars-- > 0) {
|
||||
strcat(str, bstr);
|
||||
strcat(str, fullwidth_blank[nact->encoding]);
|
||||
}
|
||||
|
||||
sys_addMsg(str);
|
||||
@@ -105,8 +108,8 @@ void commandMI() { /* T2 */
|
||||
char *title = sys_getString(':');
|
||||
char *t1, *t2, *t3;
|
||||
|
||||
t1 = sjis2utf(title);
|
||||
t2 = sjis2utf(v_str(dst_no -1));
|
||||
t1 = toUTF8(title);
|
||||
t2 = toUTF8(v_str(dst_no -1));
|
||||
|
||||
mi_param.title = t1;
|
||||
mi_param.oldstring = t2;
|
||||
@@ -119,10 +122,10 @@ void commandMI() { /* T2 */
|
||||
return;
|
||||
}
|
||||
|
||||
t3 = utf2sjis(mi_param.newstring);
|
||||
t3 = fromUTF8(mi_param.newstring);
|
||||
|
||||
/* 全角文字以外は不可 */
|
||||
if (!sjis_has_hankaku(t3)) {
|
||||
if (nact->encoding != SHIFT_JIS ||!sjis_has_hankaku(t3)) {
|
||||
v_strcpy(dst_no -1, t3);
|
||||
}
|
||||
free(t1);
|
||||
@@ -163,7 +166,7 @@ void commandMT() {
|
||||
|
||||
if (nact->game_title_utf8)
|
||||
free(nact->game_title_utf8);
|
||||
nact->game_title_utf8 = sjis2utf(str);
|
||||
nact->game_title_utf8 = toUTF8(str);
|
||||
ags_setWindowTitle(str);
|
||||
|
||||
/* 闘神都市II 対策 */
|
||||
@@ -197,7 +200,9 @@ void commandMH() {
|
||||
int num2 = getCaliValue();
|
||||
|
||||
char buf[512];
|
||||
v_strcpy(num1 - 1, format_number_zenkaku(num2, fig, buf));
|
||||
char *s = fromSJIS(format_number_zenkaku(num2, fig, buf));
|
||||
v_strcpy(num1 - 1, s);
|
||||
free(s);
|
||||
|
||||
DEBUG_COMMAND("MH %d,%d,%d:\n",num1,fig,num2);
|
||||
}
|
||||
@@ -215,7 +220,7 @@ void commandML() {
|
||||
int *var = getCaliVariable();
|
||||
int str_no = getCaliValue();
|
||||
|
||||
*var = sjis_count_char(v_str(str_no -1));
|
||||
*var = v_strlen(str_no -1);
|
||||
|
||||
DEBUG_COMMAND("ML %p,%d:\n",var, str_no);
|
||||
}
|
||||
@@ -338,7 +343,7 @@ void commandMJ() {
|
||||
INPUTSTRING_PARAM mj_param;
|
||||
char *t1, *t2;
|
||||
|
||||
t1 = sjis2utf(v_str(num -1));
|
||||
t1 = toUTF8(v_str(num -1));
|
||||
mj_param.max = max_len;
|
||||
mj_param.x = x;
|
||||
mj_param.y = y;
|
||||
@@ -349,8 +354,8 @@ void commandMJ() {
|
||||
menu_inputstring2(&mj_param);
|
||||
if (mj_param.newstring == NULL) return;
|
||||
|
||||
t2 = utf2sjis(mj_param.newstring);
|
||||
if (!sjis_has_hankaku(t2)) {
|
||||
t2 = fromUTF8(mj_param.newstring);
|
||||
if (nact->encoding != SHIFT_JIS || !sjis_has_hankaku(t2)) {
|
||||
v_strcpy(num -1, t2);
|
||||
}
|
||||
free(t1);
|
||||
|
||||
+2
-6
@@ -375,13 +375,9 @@ void commandNI() { /* From Panyo */
|
||||
void commandNT() { /* From Panyo */
|
||||
/* NIコマンドで表示するタイトルを設定する。*/
|
||||
char *str = sys_getString(':');
|
||||
char *t;
|
||||
|
||||
if (ni_param.title != NULL) {
|
||||
free(ni_param.title);
|
||||
}
|
||||
t = sjis2utf(str);
|
||||
ni_param.title = t;
|
||||
free(ni_param.title);
|
||||
ni_param.title = toUTF8(str);
|
||||
|
||||
DEBUG_COMMAND("NT %p:\n", str);
|
||||
}
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ void commandQE() {
|
||||
char *filename = sys_getString(':');
|
||||
int *var, _var = 0, cnt;
|
||||
|
||||
char *fname_utf8 = sjis2utf(filename);
|
||||
char *fname_utf8 = toUTF8(filename);
|
||||
switch(type) {
|
||||
case 0:
|
||||
var = getCaliVariable();
|
||||
|
||||
+10
@@ -525,3 +525,13 @@ void commandZR() {
|
||||
|
||||
DEBUG_COMMAND("ZR %d,%d:\n", num, *var);
|
||||
}
|
||||
|
||||
void commandZU() {
|
||||
/* xsystem35 extension: sets unicode mode */
|
||||
int sw = getCaliValue();
|
||||
|
||||
if (sw <= CHARACTER_ENCODING_MAX)
|
||||
sys_setCharacterEncoding(sw);
|
||||
|
||||
DEBUG_COMMAND("ZU %d:\n",sw);
|
||||
}
|
||||
|
||||
+1
-29
@@ -34,6 +34,7 @@
|
||||
#include "system.h"
|
||||
#include "font.h"
|
||||
#include "ags.h"
|
||||
#include "utfsjis.h"
|
||||
|
||||
extern const unsigned short *s2u[];
|
||||
|
||||
@@ -59,35 +60,6 @@ static FONT *this;
|
||||
static void pixmap2comimg(BYTE *src, int x, int y, int w, int h, int src_bpl);
|
||||
static void pixmapmono2comimg(BYTE *src, int x, int y, int w, int h, int src_bpl);
|
||||
|
||||
static int utf8_next_codepoint(const char **msg) {
|
||||
int code;
|
||||
const unsigned char *s = (const unsigned char *)*msg;
|
||||
|
||||
if (*s <= 0x7f) {
|
||||
code = *s++;
|
||||
} else if (*s <= 0xbf) {
|
||||
WARNING("Invalid UTF-8 sequence %02x\n", *s);
|
||||
code = '?';
|
||||
s++;
|
||||
} else if (*s <= 0xdf) {
|
||||
code = (s[0] & 0x1f) << 6 | (s[1] & 0x3f);
|
||||
s += 2;
|
||||
} else if (*s <= 0xef) {
|
||||
code = (s[0] & 0xf) << 12 | (s[1] & 0x3f) << 6 | (s[2] & 0x3f);
|
||||
s += 3;
|
||||
} else if (*s <= 0xf7) {
|
||||
code = (s[0] & 0x7) << 18 | (s[1] & 0x3f) << 12 | (s[2] & 0x3f) << 6 | (s[3] & 0x3f);
|
||||
s += 4;
|
||||
} else {
|
||||
code = 0xfffd; // REPLACEMENT CHARACTER
|
||||
s++;
|
||||
while (0x80 <= *s && *s <= 0xbf)
|
||||
s++;
|
||||
}
|
||||
*msg = (const char *)s;
|
||||
return code;
|
||||
}
|
||||
|
||||
static boolean select_charmap(FT_Face f, int type) {
|
||||
int i;
|
||||
|
||||
|
||||
+196
-2
@@ -140,7 +140,7 @@ static const char zenkaku_digits[][3] = {
|
||||
0x81,0x40,0x00, /* space */
|
||||
};
|
||||
|
||||
BYTE *zen2han(const BYTE *src) {
|
||||
static BYTE *zen2han_sjis(const BYTE *src) {
|
||||
BYTE c0, c1;
|
||||
char *dst, *_dst;
|
||||
|
||||
@@ -173,7 +173,201 @@ BYTE *zen2han(const BYTE *src) {
|
||||
return _dst;
|
||||
}
|
||||
|
||||
BYTE *han2zen(const BYTE *src) {
|
||||
static char *zen2han_utf8(const char *src) {
|
||||
char *dst, *_dst;
|
||||
dst = _dst = malloc(strlen(src) + 1);
|
||||
if (dst == NULL) {
|
||||
fprintf(stderr, "zen2han(): Out of Memory (size %zu)", strlen(src) + 1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BYTE *zen2han(const BYTE *src, CharacterEncoding enc) {
|
||||
switch (enc) {
|
||||
case SHIFT_JIS:
|
||||
return zen2han_sjis(src);
|
||||
case UTF8:
|
||||
return zen2han_utf8(src);
|
||||
default:
|
||||
return (BYTE *)src;
|
||||
}
|
||||
}
|
||||
|
||||
BYTE *han2zen(const BYTE *src, CharacterEncoding enc) {
|
||||
if (enc != SHIFT_JIS)
|
||||
return (BYTE *)src; // Not implemented
|
||||
|
||||
BYTE c0;
|
||||
BYTE *dst, *_dst;
|
||||
dst = _dst = malloc(strlen(src) * 2 + 1);
|
||||
|
||||
+3
-2
@@ -24,9 +24,10 @@
|
||||
#define __HANKAKU_H__
|
||||
|
||||
#include "portab.h"
|
||||
#include "utfsjis.h"
|
||||
|
||||
extern BYTE *zen2han(const BYTE *src);
|
||||
extern BYTE *han2zen(const BYTE *src);
|
||||
extern BYTE *zen2han(const BYTE *src, CharacterEncoding enc);
|
||||
extern BYTE *han2zen(const BYTE *src, CharacterEncoding enc);
|
||||
extern char *format_number(int n, int width, char *buf);
|
||||
extern char *format_number_zenkaku(int n, int width, char *buf);
|
||||
|
||||
|
||||
+4
-2
@@ -52,9 +52,11 @@ static void zen2han_test(void) {
|
||||
"ベペボポヮヰヱヴヵヶΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩα"
|
||||
"βγδεζηθικλμνξοπρστυφχψω";
|
||||
for (const Zen2hanTestCase *tc = testcases; tc->zen; tc++) {
|
||||
ASSERT_STRCMP(sjis2utf(zen2han(utf2sjis(tc->zen))), tc->han);
|
||||
ASSERT_STRCMP(sjis2utf(zen2han(utf2sjis(tc->zen), SHIFT_JIS)), tc->han);
|
||||
ASSERT_STRCMP(zen2han(tc->zen, UTF8), tc->han);
|
||||
}
|
||||
ASSERT_STRCMP(sjis2utf(zen2han(utf2sjis(unconvertable))), unconvertable);
|
||||
ASSERT_STRCMP(sjis2utf(zen2han(utf2sjis(unconvertable), SHIFT_JIS)), unconvertable);
|
||||
ASSERT_STRCMP(zen2han(unconvertable, UTF8), unconvertable);
|
||||
}
|
||||
|
||||
static void format_number_test(void) {
|
||||
|
||||
+5
-2
@@ -326,11 +326,14 @@ void msg_getMessageLocation(MyPoint *loc) {
|
||||
|
||||
void msg_hitAnyKey() {
|
||||
int w;
|
||||
static BYTE hak[] = {0x81, 0xa5, 0x00}; /* ▼ */
|
||||
const char *prompt[CHARACTER_ENCODING_MAX + 1] = {
|
||||
[SHIFT_JIS] = "\x81\xa5",
|
||||
[UTF8] = "▼",
|
||||
};
|
||||
|
||||
w = ags_drawString(msg.win->x + msg.win->width - msg.MsgFontSize,
|
||||
msg.win->y + msg.win->height - msg.MsgFontSize,
|
||||
hak, msg.HitAnyKeyMsgColor);
|
||||
prompt[nact->encoding], msg.HitAnyKeyMsgColor);
|
||||
ags_updateArea(msg.win->x + msg.win->width - msg.MsgFontSize,
|
||||
msg.win->y + msg.win->height - msg.MsgFontSize,
|
||||
w, msg.MsgFontSize);
|
||||
|
||||
+11
-5
@@ -70,6 +70,10 @@ void sys_setHankakuMode(int mode) {
|
||||
msg_msgHankakuMode = mode;
|
||||
}
|
||||
|
||||
void sys_setCharacterEncoding(CharacterEncoding encoding) {
|
||||
nact->encoding = encoding;
|
||||
}
|
||||
|
||||
/* 文字列の取り出し */
|
||||
char *sys_getString(char term) {
|
||||
int c0;
|
||||
@@ -103,9 +107,9 @@ void sys_addMsg(const char *str) {
|
||||
|
||||
switch(msg_msgHankakuMode) {
|
||||
case 0:
|
||||
msg = han2zen(str); break;
|
||||
msg = han2zen(str, nact->encoding); break;
|
||||
case 1:
|
||||
msg = zen2han(str); break;
|
||||
msg = zen2han(str, nact->encoding); break;
|
||||
case 2:
|
||||
msg = str; break;
|
||||
default:
|
||||
@@ -126,7 +130,7 @@ void sys_addMsg(const char *str) {
|
||||
}
|
||||
}
|
||||
|
||||
if (msg && msg_msgHankakuMode < 2) {
|
||||
if (msg != str) {
|
||||
free((char *)msg);
|
||||
}
|
||||
}
|
||||
@@ -136,8 +140,10 @@ static int checkMessage() {
|
||||
char *index = msgbuf;
|
||||
int c0 = sl_getc();
|
||||
|
||||
while (c0 == 0x20 || c0 > 0x80) {
|
||||
if (c0 == 0x20) {
|
||||
while (c0 == 0x20 || c0 >= 0x80) {
|
||||
if (nact->encoding == UTF8) {
|
||||
*index++ = (char)c0;
|
||||
} else if (c0 == 0x20) {
|
||||
*index++ = (char)c0;
|
||||
} else if (c0 >= 0xe0) {
|
||||
*index++ = (char)c0; *index++ = (char)sl_getc();
|
||||
|
||||
@@ -32,6 +32,12 @@
|
||||
#include "selection.h"
|
||||
#include "message.h"
|
||||
#include "ags.h"
|
||||
#include "utfsjis.h"
|
||||
|
||||
#define toUTF8(s) codeconv(UTF8, nact->encoding, s)
|
||||
#define toSJIS(s) codeconv(SHIFT_JIS, nact->encoding, s)
|
||||
#define fromUTF8(s) codeconv(nact->encoding, UTF8, s)
|
||||
#define fromSJIS(s) codeconv(nact->encoding, SHIFT_JIS, s)
|
||||
|
||||
/* コマンド解析時に参照する */
|
||||
#define sys_getc sl_getc
|
||||
@@ -46,6 +52,7 @@ extern int *getVariable();
|
||||
extern char *sys_getString(char term);
|
||||
extern void sys_addMsg(const char *str);
|
||||
extern void sys_setHankakuMode(int mode);
|
||||
extern void sys_setCharacterEncoding(CharacterEncoding encoding);
|
||||
extern char *sys_getConstString();
|
||||
|
||||
// extern boolean sys_nact_engine();
|
||||
@@ -61,6 +68,7 @@ typedef struct {
|
||||
boolean is_message_locked; /* pointer 等の event handler を呼び出さない */
|
||||
boolean popupmenu_opened; /* popup menu が 開いているか */
|
||||
boolean mmx_is_ok; /* MMX が有効かどうか */
|
||||
CharacterEncoding encoding;
|
||||
|
||||
char *game_title_utf8;
|
||||
int scenario_version;
|
||||
|
||||
+50
-10
@@ -33,6 +33,18 @@
|
||||
#include "utfsjis.h"
|
||||
#include "s2utbl.h"
|
||||
|
||||
char* codeconv(CharacterEncoding tocode,
|
||||
CharacterEncoding fromcode,
|
||||
const char *str) {
|
||||
if (tocode == fromcode)
|
||||
return strdup(str);
|
||||
if (tocode == UTF8 && fromcode == SHIFT_JIS)
|
||||
return (char *)sjis2utf((char *)str);
|
||||
if (tocode == SHIFT_JIS && fromcode == UTF8)
|
||||
return (char *)utf2sjis((char *)str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BYTE *sjis2utf(const BYTE *src) {
|
||||
BYTE* dst = malloc(strlen(src) * 3 + 1);
|
||||
BYTE* dstp = dst;
|
||||
@@ -147,15 +159,43 @@ boolean sjis_has_zenkaku(const BYTE *src) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* src 中の文字数を数える 全角文字も1文字 */
|
||||
int sjis_count_char(const BYTE *src) {
|
||||
int c = 0;
|
||||
|
||||
while(*src) {
|
||||
if (CHECKSJIS1BYTE(*src)) {
|
||||
src++;
|
||||
}
|
||||
c++; src++;
|
||||
int utf8_next_codepoint(const char **msg) {
|
||||
int code;
|
||||
const unsigned char *s = (const unsigned char *)*msg;
|
||||
|
||||
if (*s <= 0x7f) {
|
||||
code = *s++;
|
||||
} else if (*s <= 0xbf) {
|
||||
// Invalid UTF-8 sequence
|
||||
code = '?';
|
||||
s++;
|
||||
} else if (*s <= 0xdf) {
|
||||
code = (s[0] & 0x1f) << 6 | (s[1] & 0x3f);
|
||||
s += 2;
|
||||
} else if (*s <= 0xef) {
|
||||
code = (s[0] & 0xf) << 12 | (s[1] & 0x3f) << 6 | (s[2] & 0x3f);
|
||||
s += 3;
|
||||
} else if (*s <= 0xf7) {
|
||||
code = (s[0] & 0x7) << 18 | (s[1] & 0x3f) << 12 | (s[2] & 0x3f) << 6 | (s[3] & 0x3f);
|
||||
s += 4;
|
||||
} else {
|
||||
code = 0xfffd; // REPLACEMENT CHARACTER
|
||||
s++;
|
||||
while (0x80 <= *s && *s <= 0xbf)
|
||||
s++;
|
||||
}
|
||||
return c;
|
||||
*msg = (const char *)s;
|
||||
return code;
|
||||
}
|
||||
|
||||
char *advance_char(const char *s, CharacterEncoding e) {
|
||||
switch (e) {
|
||||
case SHIFT_JIS:
|
||||
return (char *)s + ((CHECKSJIS1BYTE(*s) && *(s + 1)) ? 2 : 1);
|
||||
case UTF8:
|
||||
while (UTF8_TRAIL_BYTE(*++s))
|
||||
;
|
||||
return (char *)s;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+19
-1
@@ -26,12 +26,30 @@
|
||||
|
||||
#include "portab.h"
|
||||
|
||||
typedef enum {
|
||||
SHIFT_JIS,
|
||||
UTF8,
|
||||
CHARACTER_ENCODING_MAX = UTF8
|
||||
} CharacterEncoding;
|
||||
|
||||
#define MAX_SJIS_BYTES_PAR_CHAR 2
|
||||
#define MAX_UTF8_BYTES_PAR_CHAR 4
|
||||
#define MAX_BYTES_PAR_CHAR(encoding) \
|
||||
((encoding) == SHIFT_JIS ? MAX_SJIS_BYTES_PAR_CHAR : MAX_UTF8_BYTES_PAR_CHAR)
|
||||
|
||||
#define UTF8_TRAIL_BYTE(b) ((signed char)(b) < -0x40)
|
||||
#define CHECKSJIS1BYTE(b) ( ((b) & 0xe0) == 0x80 || ((b) & 0xe0) == 0xe0 )
|
||||
|
||||
extern char* codeconv(CharacterEncoding tocode,
|
||||
CharacterEncoding fromcode,
|
||||
const char *str);
|
||||
|
||||
extern BYTE* sjis2utf(const BYTE *src);
|
||||
extern BYTE* utf2sjis(const BYTE *src);
|
||||
extern boolean sjis_has_hankaku(const BYTE *src);
|
||||
extern boolean sjis_has_zenkaku(const BYTE *src);
|
||||
extern int sjis_count_char(const BYTE *src);
|
||||
extern int utf8_next_codepoint(const char **msg);
|
||||
|
||||
extern char *advance_char(const char *s, CharacterEncoding e);
|
||||
|
||||
#endif /* __UTFSJIS__ */
|
||||
|
||||
+10
-3
@@ -45,7 +45,7 @@ int strvar_len = STRVAR_LEN;
|
||||
|
||||
static char *advance(const char *s, int n) {
|
||||
while (*s && n > 0) {
|
||||
s += (CHECKSJIS1BYTE(*s) && *(s + 1)) ? 2 : 1;
|
||||
s = advance_char(s, nact->encoding);
|
||||
n--;
|
||||
}
|
||||
return (char *)s;
|
||||
@@ -175,7 +175,14 @@ void v_strcat(int no, const char *str) {
|
||||
|
||||
/* 文字変数の長さ */
|
||||
size_t v_strlen(int no) {
|
||||
return sjis_count_char(v_str(no));
|
||||
const char *s = v_str(no);
|
||||
|
||||
int c = 0;
|
||||
while (*s) {
|
||||
s = advance_char(s, nact->encoding);
|
||||
c++;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Width of a string (2 for full-width characters, 1 for half-width) */
|
||||
@@ -207,7 +214,7 @@ int v_strstr(int no, int start, const char *str) {
|
||||
return -1;
|
||||
int n = start;
|
||||
while (p < found) {
|
||||
p += CHECKSJIS1BYTE(*p) ? 2 : 1;
|
||||
p = advance_char(p, nact->encoding);
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
|
||||
Reference in New Issue
Block a user