Refactor LoadMessageFile()

This commit is contained in:
maron2000
2025-04-26 10:52:45 +09:00
parent a45168c7e5
commit 9148698602

View File

@@ -36,6 +36,8 @@
#include <string> #include <string>
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
#include <fstream>
#include <iostream>
#if defined(__MINGW32__) && !defined(HX_DOS) #if defined(__MINGW32__) && !defined(HX_DOS)
#include <imm.h> #include <imm.h>
#endif #endif
@@ -316,18 +318,19 @@ FILE* testLoadLangFile(const char* fname) {
} }
char loaded_fname[LINE_IN_MAXLEN + 1024]; static std::string loaded_fname;
void LoadMessageFile(const char* fname) { void LoadMessageFile(const char* fname) {
if (!fname) return; if(!fname || *fname == '\0') return;
if(*fname=='\0') return;//empty string=no languagefile
if (!strcmp(fname, loaded_fname)){ if(loaded_fname == fname) {
//LOG_MSG("Message file %s already loaded.",fname);
return; return;
} }
LOG(LOG_MISC, LOG_DEBUG)("Loading message file %s", fname); LOG(LOG_MISC, LOG_DEBUG)("Loading message file %s", fname);
FILE* mfile = testLoadLangFile(fname); FILE* mfile = testLoadLangFile(fname);
/* This should never happen and since other modules depend on this use a normal printf */
if(!mfile) { if(!mfile) {
std::string message = "Could not load language message file " + std::string(fname) + ". The default language will be used."; std::string message = "Could not load language message file " + std::string(fname) + ". The default language will be used.";
systemmessagebox("Warning", message.c_str(), "ok", "warning", 1); systemmessagebox("Warning", message.c_str(), "ok", "warning", 1);
@@ -336,46 +339,57 @@ void LoadMessageFile(const char * fname) {
control->opt_lang = ""; control->opt_lang = "";
return; return;
} }
strcpy(loaded_fname, fname);
langname = langnote = ""; loaded_fname = fname;
char linein[LINE_IN_MAXLEN+1024]; langname.clear();
char name[LINE_IN_MAXLEN+1024], menu_name[LINE_IN_MAXLEN], mapper_name[LINE_IN_MAXLEN]; langnote.clear();
char string[LINE_IN_MAXLEN*10], temp[4096]; std::string linein, name, menu_name, mapper_name, string;
/* Start out with empty strings */
name[0]=0;string[0]=0;
morelen = inmsg = true; morelen = inmsg = true;
bool res = true; bool res = true;
bool loadlangcp = false; bool loadlangcp = false;
int cp = dos.loaded_codepage; int cp = dos.loaded_codepage;
if(!dos.loaded_codepage) res = InitCodePage(); if(!dos.loaded_codepage) res = InitCodePage();
while(fgets(linein, LINE_IN_MAXLEN+1024, mfile)) {
/* Parse the read line */
/* First remove characters 10 and 13 from the line */
char * parser=linein;
char * writer=linein;
while (*parser) { const size_t buffer_size = LINE_IN_MAXLEN + 1024;
if (*parser != 10 && *parser != 13) char* buffer = new char[buffer_size];
*writer++ = *parser;
while(fgets(buffer, buffer_size, mfile)) {
linein = buffer;
// Remove \r and \n
linein.erase(std::remove(linein.begin(), linein.end(), '\r'), linein.end());
linein.erase(std::remove(linein.begin(), linein.end(), '\n'), linein.end());
if(linein.empty()) continue;
std::string trimmed = linein.substr(1);
trim(trimmed);
parser++;
}
*writer=0;
/* New string name */
if(linein[0] == ':') { if(linein[0] == ':') {
string[0]=0; string.clear();
if (!strncasecmp(linein+1, "DOSBOX-X:", 9)) {
char *p = linein+10; if(!strncasecmp(linein.c_str() + 1, "DOSBOX-X:", 9)) {
char *r = strchr(p, ':'); std::string p = linein.substr(10);
if (*p && r!=NULL && r>p && *(r+1)) { size_t colon_pos = p.find(':');
*r=0; if(colon_pos != std::string::npos && colon_pos > 0 && colon_pos + 1 < p.size()) {
if (!strcmp(p, "CODEPAGE")) { std::string key = p.substr(0, colon_pos);
int c = atoi(r+1); std::string val = p.substr(colon_pos + 1);
if(key == "CODEPAGE") {
int c = std::atoi(val.c_str());
if(!isSupportedCP(c)) { if(!isSupportedCP(c)) {
LOG_MSG("Language file: Invalid codepage :DOSBOX-X:CODEPAGE:%d", c); LOG_MSG("Language file: Invalid codepage :DOSBOX-X:CODEPAGE:%d", c);
loadlangcp = false; loadlangcp = false;
} }
else if (((IS_PC98_ARCH||IS_JEGA_ARCH) && c!=437 && c!=932 && !systemmessagebox("DOSBox-X language file", "You have specified a language file which uses a code page incompatible with the Japanese PC-98 or JEGA/AX system.\n\nAre you sure to use the language file for this machine type?", "yesno","question", 2)) || (((IS_JDOSV && c!=932) || (IS_PDOSV && c!=936) || (IS_KDOSV && c!=949) || (IS_TDOSV && c!=950 && c!=951)) && c!=437 && !systemmessagebox("DOSBox-X language file", "You have specified a language file which uses a code page incompatible with the current DOS/V system.\n\nAre you sure to use the language file for this system type?", "yesno","question", 2))) { else if(((IS_PC98_ARCH || IS_JEGA_ARCH) && c != 437 && c != 932 &&
!systemmessagebox("DOSBox-X language file",
"You have specified a language file which uses a code page incompatible with the Japanese PC-98 or JEGA/AX system.\n\nAre you sure to use the language file for this machine type?",
"yesno", "question", 2)) ||
(((IS_JDOSV && c != 932) || (IS_PDOSV && c != 936) ||
(IS_KDOSV && c != 949) || (IS_TDOSV && c != 950 && c != 951)) &&
c != 437 &&
!systemmessagebox("DOSBox-X language file",
"You have specified a language file which uses a code page incompatible with the current DOS/V system.\n\nAre you sure to use the language file for this system type?",
"yesno", "question", 2))) {
fclose(mfile); fclose(mfile);
dos.loaded_codepage = cp; dos.loaded_codepage = cp;
return; return;
@@ -386,7 +400,8 @@ void LoadMessageFile(const char * fname) {
msgcodepage = c; msgcodepage = c;
lastmsgcp = msgcodepage; lastmsgcp = msgcodepage;
} }
if(c != dos.loaded_codepage && (control->opt_langcp || uselangcp || !CHCP_changed || CheckDBCSCP(c) || !loadlang || (loadlang && systemmessagebox("DOSBox-X language file", msg.c_str(), "yesno", "question", 1)))) { if(c != dos.loaded_codepage && (control->opt_langcp || uselangcp || !CHCP_changed || CheckDBCSCP(c) || !loadlang ||
(loadlang && systemmessagebox("DOSBox-X language file", msg.c_str(), "yesno", "question", 1)))) {
loadlangcp = true; loadlangcp = true;
if(c == 950 && dos.loaded_codepage == 951) msgcodepage = 951; // zh_tw defaults to CP950, but CP951 is acceptable as well so keep it if(c == 950 && dos.loaded_codepage == 951) msgcodepage = 951; // zh_tw defaults to CP950, but CP951 is acceptable as well so keep it
else if(c == 951 && dos.loaded_codepage == 950) msgcodepage = 950; // And vice versa for lang files requiring CP951 else if(c == 951 && dos.loaded_codepage == 950) msgcodepage = 950; // And vice versa for lang files requiring CP951
@@ -397,71 +412,87 @@ void LoadMessageFile(const char * fname) {
lastmsgcp = c; lastmsgcp = c;
} }
} }
} else if (!strcmp(p, "LANGUAGE"))
langname = r+1;
else if (!strcmp(p, "REMARK"))
langnote = r+1;
*r=':';
} }
} else if (!strncasecmp(linein+1, "MENU:", 5)&&strlen(linein+6)<LINE_IN_MAXLEN) { else if(key == "LANGUAGE") {
*name=0; langname = val;
*mapper_name=0;
strcpy(menu_name,linein+6);
} else if (!strncasecmp(linein+1, "MAPPER:", 7)&&strlen(linein+8)<LINE_IN_MAXLEN) {
*name=0;
*menu_name=0;
strcpy(mapper_name,linein+8);
} else {
*menu_name=0;
*mapper_name=0;
strcpy(name,linein+1);
} }
/* End of string marker */ else if(key == "REMARK") {
} else if (linein[0]=='.'&&!strlen(trim(linein+1))) { langnote = val;
/* Replace/Add the string to the internal languagefile */
/* Remove last newline (marker is \n.\n) */
size_t ll = strlen(string);
if(ll && string[ll - 1] == '\n') string[ll - 1] = 0; //Second if should not be needed, but better be safe.
if (strlen(name))
MSG_Replace(name,string);
else if (strlen(menu_name)>6&&!strncmp(menu_name, "drive_", 6))
for (char c='A'; c<='Z'; c++) {
std::string mname = "drive_"+std::string(1, c)+(menu_name+5);
if (mainMenu.item_exists(mname)) mainMenu.get_item(mname).set_text(string);
} }
else if (strlen(menu_name)&&mainMenu.item_exists(menu_name)) { }
}
else if(!strncasecmp(linein.c_str() + 1, "MENU:", 5) && linein.size() > 6) {
name.clear(); mapper_name.clear();
menu_name = linein.substr(6);
}
else if(!strncasecmp(linein.c_str() + 1, "MAPPER:", 7) && linein.size() > 8) {
name.clear(); menu_name.clear();
mapper_name = linein.substr(8);
}
else {
menu_name.clear(); mapper_name.clear();
name = linein.substr(1);
}
}
else if(linein[0] == '.' && trimmed.empty()) {
if(!string.empty() && string.back() == '\n') string.pop_back();
if(!name.empty()) {
MSG_Replace(name.c_str(), string.c_str());
}
else if(menu_name.size() > 6 && menu_name.rfind("drive_", 0) == 0) {
for(char c = 'A'; c <= 'Z'; ++c) {
std::string mname = "drive_" + std::string(1, c) + menu_name.substr(5);
if(mainMenu.item_exists(mname)) {
mainMenu.get_item(mname).set_text(string);
}
}
}
else if(!menu_name.empty() && mainMenu.item_exists(menu_name)) {
mainMenu.get_item(menu_name).set_text(string); mainMenu.get_item(menu_name).set_text(string);
if (strlen(menu_name)>7&&!strncmp(menu_name, "mapper_", 7)) set_eventbutton_text(menu_name+7, string); if(menu_name.rfind("mapper_", 0) == 0 && menu_name.size() > 7) {
} set_eventbutton_text(menu_name.c_str() + 7, string.c_str());
else if (strlen(mapper_name))
set_eventbutton_text(mapper_name, string);
} else {
/* Normal string to be added */
if (!CodePageHostToGuestUTF8(temp,linein))
strcat(string,linein);
else
strcat(string,temp);
strcat(string,"\n");
} }
} }
else if(!mapper_name.empty()) {
set_eventbutton_text(mapper_name.c_str(), string.c_str());
}
}
else {
size_t temp_size = linein.size() * 3 + 1; // Converting to UTF-8 will expand to max. 3-bytes / character + null terminator
std::vector<char> temp(temp_size);
if(!CodePageHostToGuestUTF8(temp.data(), linein.c_str())) {
string += linein + "\n";
}
else {
string += std::string(temp.data()) + "\n";
}
}
}
morelen = inmsg = false; morelen = inmsg = false;
delete[] buffer;
fclose(mfile); fclose(mfile);
menu_update_dynamic(); menu_update_dynamic();
menu_update_autocycle(); menu_update_autocycle();
update_bindbutton_text(); update_bindbutton_text();
dos.loaded_codepage = cp; dos.loaded_codepage = cp;
if(loadlangcp && msgcodepage > 0) { if(loadlangcp && msgcodepage > 0) {
const char* layoutname = DOS_GetLoadedLayout(); const char* layoutname = DOS_GetLoadedLayout();
if(!IS_DOSV && !IS_JEGA_ARCH && !IS_PC98_ARCH && layoutname != NULL) { if(!IS_DOSV && !IS_JEGA_ARCH && !IS_PC98_ARCH && layoutname != nullptr) {
toSetCodePage(NULL, msgcodepage, -1); toSetCodePage(nullptr, msgcodepage, -1);
} }
} }
refreshExtChar(); refreshExtChar();
LOG_MSG("LoadMessageFile: Loaded language file: %s", fname); LOG_MSG("LoadMessageFile: Loaded language file: %s", fname);
loadlang = true; loadlang = true;
} }
bool MSG_Write(const char* location, const char* name) { bool MSG_Write(const char* location, const char* name) {
std::unique_ptr<char[]> temp(new char[4096]); std::unique_ptr<char[]> temp(new char[4096]);