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,69 +318,81 @@ FILE* testLoadLangFile(const char* fname) {
} }
char loaded_fname[LINE_IN_MAXLEN + 1024]; static std::string loaded_fname;
void LoadMessageFile(const char * fname) {
if (!fname) return; void LoadMessageFile(const char* fname) {
if(*fname=='\0') return;//empty string=no languagefile if(!fname || *fname == '\0') return;
if (!strcmp(fname, loaded_fname)){
//LOG_MSG("Message file %s already loaded.",fname); if(loaded_fname == fname) {
return; return;
} }
LOG(LOG_MISC,LOG_DEBUG)("Loading message file %s",fname);
FILE * mfile=testLoadLangFile(fname); LOG(LOG_MISC, LOG_DEBUG)("Loading message file %s", fname);
/* This should never happen and since other modules depend on this use a normal printf */
if (!mfile) { FILE* mfile = testLoadLangFile(fname);
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); if(!mfile) {
SetVal("dosbox", "language", ""); std::string message = "Could not load language message file " + std::string(fname) + ". The default language will be used.";
LOG_MSG("MSG:Cannot load language file: %s",fname); systemmessagebox("Warning", message.c_str(), "ok", "warning", 1);
control->opt_lang = ""; SetVal("dosbox", "language", "");
return; LOG_MSG("MSG:Cannot load language file: %s", fname);
} control->opt_lang = "";
strcpy(loaded_fname, fname); return;
langname = langnote = ""; }
char linein[LINE_IN_MAXLEN+1024];
char name[LINE_IN_MAXLEN+1024], menu_name[LINE_IN_MAXLEN], mapper_name[LINE_IN_MAXLEN]; loaded_fname = fname;
char string[LINE_IN_MAXLEN*10], temp[4096]; langname.clear();
/* Start out with empty strings */ langnote.clear();
name[0]=0;string[0]=0; std::string linein, name, menu_name, mapper_name, string;
morelen=inmsg=true;
bool res=true; morelen = inmsg = 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;
parser++; while(fgets(buffer, buffer_size, mfile)) {
} linein = buffer;
*writer=0; // Remove \r and \n
/* New string name */ linein.erase(std::remove(linein.begin(), linein.end(), '\r'), linein.end());
if (linein[0]==':') { linein.erase(std::remove(linein.begin(), linein.end(), '\n'), linein.end());
string[0]=0;
if (!strncasecmp(linein+1, "DOSBOX-X:", 9)) { if(linein.empty()) continue;
char *p = linein+10;
char *r = strchr(p, ':'); std::string trimmed = linein.substr(1);
if (*p && r!=NULL && r>p && *(r+1)) { trim(trimmed);
*r=0;
if (!strcmp(p, "CODEPAGE")) { if(linein[0] == ':') {
int c = atoi(r+1); string.clear();
if(!strncasecmp(linein.c_str() + 1, "DOSBOX-X:", 9)) {
std::string p = linein.substr(10);
size_t colon_pos = p.find(':');
if(colon_pos != std::string::npos && colon_pos > 0 && colon_pos + 1 < p.size()) {
std::string key = p.substr(0, colon_pos);
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 &&
fclose(mfile); !systemmessagebox("DOSBox-X language file",
dos.loaded_codepage = cp; "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?",
return; "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);
dos.loaded_codepage = cp;
return;
} }
else { else {
std::string msg = "The specified language file uses code page " + std::to_string(c) + ". Do you want to change to this code page accordingly?"; std::string msg = "The specified language file uses code page " + std::to_string(c) + ". Do you want to change to this code page accordingly?";
@@ -386,82 +400,99 @@ 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
else msgcodepage = c; else msgcodepage = c;
dos.loaded_codepage = c; dos.loaded_codepage = c;
if (c == 950 && !chinasea) makestdcp950table(); if(c == 950 && !chinasea) makestdcp950table();
if (c == 951 && chinasea) makeseacp951table(); if(c == 951 && chinasea) makeseacp951table();
lastmsgcp = c; lastmsgcp = c;
} }
} }
} else if (!strcmp(p, "LANGUAGE")) }
langname = r+1; else if(key == "LANGUAGE") {
else if (!strcmp(p, "REMARK")) langname = val;
langnote = r+1; }
*r=':'; else if(key == "REMARK") {
langnote = val;
}
} }
} else if (!strncasecmp(linein+1, "MENU:", 5)&&strlen(linein+6)<LINE_IN_MAXLEN) {
*name=0;
*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(!strncasecmp(linein.c_str() + 1, "MENU:", 5) && linein.size() > 6) {
} else if (linein[0]=='.'&&!strlen(trim(linein+1))) { name.clear(); mapper_name.clear();
/* Replace/Add the string to the internal languagefile */ menu_name = linein.substr(6);
/* Remove last newline (marker is \n.\n) */ }
size_t ll = strlen(string); else if(!strncasecmp(linein.c_str() + 1, "MAPPER:", 7) && linein.size() > 8) {
if(ll && string[ll - 1] == '\n') string[ll - 1] = 0; //Second if should not be needed, but better be safe. name.clear(); menu_name.clear();
if (strlen(name)) mapper_name = linein.substr(8);
MSG_Replace(name,string); }
else if (strlen(menu_name)>6&&!strncmp(menu_name, "drive_", 6)) else {
for (char c='A'; c<='Z'; c++) { menu_name.clear(); mapper_name.clear();
std::string mname = "drive_"+std::string(1, c)+(menu_name+5); name = linein.substr(1);
if (mainMenu.item_exists(mname)) mainMenu.get_item(mname).set_text(string); }
}
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 (strlen(menu_name)&&mainMenu.item_exists(menu_name)) { }
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)) else if(!mapper_name.empty()) {
set_eventbutton_text(mapper_name, string); set_eventbutton_text(mapper_name.c_str(), string.c_str());
} else { }
/* Normal string to be added */ }
if (!CodePageHostToGuestUTF8(temp,linein)) else {
strcat(string,linein); size_t temp_size = linein.size() * 3 + 1; // Converting to UTF-8 will expand to max. 3-bytes / character + null terminator
else std::vector<char> temp(temp_size);
strcat(string,temp); if(!CodePageHostToGuestUTF8(temp.data(), linein.c_str())) {
strcat(string,"\n"); string += linein + "\n";
} }
} else {
morelen=inmsg=false; string += std::string(temp.data()) + "\n";
fclose(mfile); }
}
}
morelen = inmsg = false;
delete[] buffer;
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]);