Files
kichikuou_xsystem35-sdl2/src/cmdm.c
T
kichikuou bc9fc924ed [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.
2020-08-09 21:24:56 +09:00

387 lines
9.0 KiB
C
Raw 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.
/*
* cmdm.c SYSTEM35 M command
*
* 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: cmdm.c,v 1.27 2002/12/21 12:28:35 chikama Exp $ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "portab.h"
#include "xsystem35.h"
#include "utfsjis.h"
#include "menu.h"
#include "ags.h"
#include "message.h"
#include "gametitle.h"
#include "hankaku.h"
/* defined by cmds.c */
extern boolean dummy_pcm_su_flag;
/* defined by cmds.c */
extern boolean Y3waitCancel;
/* MI 用パラメータ */
INPUTSTRING_PARAM mi_param;
boolean have_eng_mp_patch = FALSE;
void commandMS() {
/* Xコマンドで表示される文字列領域に文字列を入れる */
int num = getCaliValue();
char *str = sys_getString(':');
if (num > 0) { /* thanx tajiri@wizard */
v_strcpy(num - 1, str);
} else {
WARNING("MS: num(%d) <= 0\n", num);
}
DEBUG_COMMAND("MS %d,%s:\n",num,str);
}
void commandMP() {
/* 指定の文字列を指定文字数だけ表示する(Xコマンドの桁数指定) */
int num1 = getCaliValue();
int num2 = getCaliValue();
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 * strlen(fullwidth_blank[nact->encoding]) + 1, 1);
if (NULL == str) {
NOMEMERR();
}
strcpy(str, src);
}
else {
str = calloc(num2 * MAX_BYTES_PAR_CHAR(nact->encoding) + 1, 1);
if (NULL == str) {
NOMEMERR();
}
const char *p = src;
while (*p && chars > 0) {
p = advance_char(p, nact->encoding);
chars--;
}
strncpy(str, src, p - src);
}
while (chars-- > 0) {
strcat(str, fullwidth_blank[nact->encoding]);
}
sys_addMsg(str);
DEBUG_COMMAND("MP %d,%d:\n",num1,num2);
free(str);
}
void commandMI() { /* T2 */
/* ユーザーによる文字列の入力 */
int dst_no = getCaliValue();
int max_len = getCaliValue();
char *title = sys_getString(':');
char *t1, *t2, *t3;
t1 = toUTF8(title);
t2 = toUTF8(v_str(dst_no -1));
mi_param.title = t1;
mi_param.oldstring = t2;
mi_param.max = max_len;
menu_inputstring(&mi_param);
if (mi_param.newstring == NULL) {
v_strcpy(dst_no -1, NULL);
free(t1); free(t2);
return;
}
t3 = fromUTF8(mi_param.newstring);
/* 全角文字以外は不可 */
if (nact->encoding != SHIFT_JIS ||!sjis_has_hankaku(t3)) {
v_strcpy(dst_no -1, t3);
}
free(t1);
free(t2);
free(t3);
DEBUG_COMMAND("MI %d,%d,%s:\n",dst_no,max_len, title);
}
void commandMA() {
/* num1 の文字列の後ろに num2 をつなげる */
int num1 = getCaliValue();
int num2 = getCaliValue();
if (num1 == num2) {
char *buf = strdup(v_str(num2 - 1));
v_strcat(num1 - 1, buf);
free(buf);
} else {
v_strcat(num1 - 1, v_str(num2 - 1));
}
DEBUG_COMMAND("MA %d,%d:\n",num1,num2);
}
void commandMC() {
/* num1 , num2 を比較して結果を RND に返す (RND=0 不一致 , RND=1 一致) */
int num1 = getCaliValue();
int num2 = getCaliValue();
sysVar[0] = strcmp(v_str(num1 - 1), v_str(num2 - 1)) == 0 ? 1 : 0;
DEBUG_COMMAND("MC %d,%d:\n",num1,num2);
}
void commandMT() {
/* ウインドウのタイトル文字列を設定する */
char *str = sys_getString(':');
if (nact->game_title_utf8)
free(nact->game_title_utf8);
nact->game_title_utf8 = toUTF8(str);
ags_setWindowTitle(str);
/* 闘神都市II 対策 */
if (0 == strcmp(nact->game_title_utf8, GT_TOSHIN2)) {
dummy_pcm_su_flag = TRUE;
}
/* Rance4 対策? */
if (0 == strcmp(nact->game_title_utf8, GT_RANCE4)) {
Y3waitCancel = FALSE;
}
DEBUG_COMMAND("MT %s:\n",str);
}
void commandMM() {
/* num1 の文字列に num2 をコピーする */
int num1 = getCaliValue();
int num2 = getCaliValue();
if (num1 != num2)
v_strcpy(num1 - 1, v_str(num2 - 1));
DEBUG_COMMAND("MM %d,%d:\n",num1, num2);
}
void commandMH() {
/* 数値を文字列に変換する (参考 Hコマンド) */
int num1 = getCaliValue();
int fig = getCaliValue();
int num2 = getCaliValue();
char buf[512];
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);
}
void commandMV() {
/* シナリオバージョンをシステムへ通知する */
int version = getCaliValue();
nact->scenario_version = version;
DEBUG_COMMAND("MV %d:\n",version);
}
void commandML() {
/* 文字列の長さを取得する */
int *var = getCaliVariable();
int str_no = getCaliValue();
*var = v_strlen(str_no -1);
DEBUG_COMMAND("ML %p,%d:\n",var, str_no);
}
void commandMD() {
/* 文字列変数を指定長さ分コピーする */
int dst_str_no = getCaliValue();
int src_str_no = getCaliValue();
int len = getCaliValue();
v_strncpy(dst_str_no - 1, 0, src_str_no - 1, 0, len);
DEBUG_COMMAND("MD %d,%d,%d:\n",dst_str_no, src_str_no, len);
}
void commandME() {
/* 位置指定つきの文字列コピー */
int dst_str_no = getCaliValue();
int dst_pos = getCaliValue();
int src_str_no = getCaliValue();
int src_pos = getCaliValue();
int len = getCaliValue();
v_strncpy(dst_str_no - 1, dst_pos, src_str_no - 1, src_pos, len);
DEBUG_COMMAND("ME %d,%d,%d,%d,%d:\n",dst_str_no, dst_pos, src_str_no, src_pos, len);
}
void commandMF() {
/* 文字列中から指定文字列の位置を探す */
int *var = getCaliVariable();
int dst_no = getCaliValue();
int key_no = getCaliValue();
int start_pos = getCaliValue();
int pos = v_strstr(dst_no - 1, start_pos, v_str(key_no - 1));
if (pos < 0) {
sysVar[0] = 255;
} else {
*var = pos;
sysVar[0] = 0;
}
DEBUG_COMMAND("MF %p,%d,%d,%d:\n",var, dst_no, key_no, start_pos);
}
void commandMZ0() {
/* 文字列変数の文字数・個数の設定の変更 */
int max_len = getCaliValue();
int max_num = getCaliValue();
int rsv = getCaliValue();
DEBUG_COMMAND("MZ0 %d,%d,%d:\n",max_len, max_num, rsv);
/* いつからか、文字列変数の最大長さは∞になったようだ */
if (max_len == 0) max_len = STRVAR_LEN * 2;
v_initStringVars(max_num,max_len * 2 + 1);
}
void commandMG() {
int no = sys_getc();
int sw = 0, *var;
switch(no) {
case 0:
sw = getCaliValue();
nact->msg.mg_getString = sw == 1 ? TRUE : FALSE;
break;
case 1:
sw = getCaliValue();
nact->msg.mg_startStrVarNo = sw;
break;
case 2:
sw = getCaliValue();
nact->msg.mg_policyR = sw;
break;
case 3:
sw = getCaliValue();
nact->msg.mg_policyA = sw;
break;
case 4:
sw = getCaliValue();
nact->msg.mg_curStrVarNo = nact->msg.mg_startStrVarNo + sw;
v_strcpy(nact->msg.mg_curStrVarNo -1, "");
break;
case 5:
var = getCaliVariable();
*var = nact->msg.mg_curStrVarNo;
break;
case 6:
sw = getCaliValue();
msg_mg6_command(sw);
break;
case 7:
var = getCaliVariable();
*var = v_strlen(nact->msg.mg_curStrVarNo -1);
break;
case 100:
sw = getCaliValue();
nact->msg.mg_dspMsg = sw == 1 ? TRUE : FALSE;
break;
default:
sw = getCaliValue();
WARNING("Unknown MG command %d,%d\n", no, sw);
break;
}
DEBUG_COMMAND("MG %d,%d:\n",no, sw);
}
void commandMJ() {
/* 文字列入力 (ウィンド無し) */
int num = getCaliValue();
int x = getCaliValue();
int y = getCaliValue();
int h = getCaliValue();
int max_len = getCaliValue();
INPUTSTRING_PARAM mj_param;
char *t1, *t2;
t1 = toUTF8(v_str(num -1));
mj_param.max = max_len;
mj_param.x = x;
mj_param.y = y;
mj_param.h = h;
mj_param.oldstring = t1;
ags_setCursorLocation(x, y, FALSE); /* XXX */
menu_inputstring2(&mj_param);
if (mj_param.newstring == NULL) return;
t2 = fromUTF8(mj_param.newstring);
if (nact->encoding != SHIFT_JIS || !sjis_has_hankaku(t2)) {
v_strcpy(num -1, t2);
}
free(t1);
free(t2);
DEBUG_COMMAND("MJ %d,%d,%d,%d,%d:\n", num, x, y, h, max_len);
}
void commandMN() {
int no = sys_getc();
int num = getCaliValue();
int *var = getCaliVariable();
int i, len;
const char *b;
switch(no) {
case 0:
/* 文字列を配列に変換する */
sysVar[0] = v_strToVars(num - 1, var);
break;
case 1:
/* 配列を文字列に変換する */
v_strFromVars(num - 1, var);
break;
default:
WARNING("UnKnown MN command(%d)\n", no);
}
DEBUG_COMMAND("MN %d,%d,%d:\n",no, num, *var);
}