diff --git a/CHANGELOG b/CHANGELOG index aedb98b99..9bed10550 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -24,10 +24,15 @@ - Report bad sectors recorded in raw CD images as ATAPI read errors. (schellingb) - You can use CONFIG -set langcp=... to change the - current language along with the embedded code page. + current language along with the embedded code page, + or CHCP nnn:... to specify a language file as well. Also improved -langcp option for SBCS code pages, and the Windows installer will also set keyboard layouts for the selected languages. (Wengier) + - Changed menu option "Restart DOSBox-X with language + file..." to "Load language file..." for loading + language files without rebooting DOSBox-X, unless + a guest system is currently running. (Wengier) - When changing TTF font, DOSBox-X will try to show the number of missing characters in the new TTF font (if any). (Wengier) diff --git a/contrib/translations/en/en_US.lng b/contrib/translations/en/en_US.lng index aa966385e..db88fea35 100644 --- a/contrib/translations/en/en_US.lng +++ b/contrib/translations/en/en_US.lng @@ -2145,15 +2145,15 @@ Displays or changes the current DOS code page. . :SHELL_CMD_CHCP_HELP_LONG CHCP [nnn [file]] +CHCP nnn[:[language]] - nnn Specifies a code page number. - file Specifies a code page file. + nnn Specifies a code page number. + file Specifies a code page file. + language Specifies a corresponding language. Supported code pages for changing in the TrueType font output: -437, 737, 775, 808, 850, 852, 853, 855-866, 869, 872, 874, 3021 - -Windows code pages: 1250,1251,1252,1253,1254,1255,1256,1257,1258 +437,737,775,808,850,852,853,855-866,869,872,874,1250-1258,3021 Also double-byte code pages including 932, 936, 949, and 950/951. @@ -3277,8 +3277,8 @@ Restart DOSBox-X instance :MENU:restartconf Restart DOSBox-X with config file... . -:MENU:restartlang -Restart DOSBox-X with language file... +:MENU:loadlang +Load language file... . :MENU:auto_lock_mouse Autolock mouse diff --git a/contrib/translations/es/es_ES.lng b/contrib/translations/es/es_ES.lng index 0b785fbd9..7e5030c73 100644 --- a/contrib/translations/es/es_ES.lng +++ b/contrib/translations/es/es_ES.lng @@ -2142,15 +2142,16 @@ Muestra o cambia el código de página DOS actual. . :SHELL_CMD_CHCP_HELP_LONG -CHCP [nnn] +CHCP [nnn [archivo]] +CHCP nnn[:[idioma]] - nnn Especifica un nº de código de página. + nnn Especifica un nº de código de página. + archivo Especifica un archivo de página de códigos. + idioma Especifica un idioma correspondiente. Códigos de página compatibles para la salida de fuente TrueType: -437, 737, 775, 808, 850, 852, 853, 855-866, 869, 872, 874, 3021 - -Páginas de códigos de Windows: 1250,1251,1252,1253,1254,1255,1256,1257,1258 +437,737,775,808,850,852,853,855-866,869,872,874,1250-1258,3021 También páginas de códigos de doble byte incluyendo 932,936,949,950/951. @@ -3282,8 +3283,8 @@ Reiniciar instancia de DOSBox-X :MENU:restartconf Reiniciar DOSBox-X con archivo config... . -:MENU:restartlang -Reiniciar DOSBox-X con archivo de idioma... +:MENU:loadlang +Cargar archivo de idioma... . :MENU:auto_lock_mouse Autobloqueo de ratón diff --git a/contrib/translations/fr/fr_FR.lng b/contrib/translations/fr/fr_FR.lng index 711219021..daf7fa54c 100644 --- a/contrib/translations/fr/fr_FR.lng +++ b/contrib/translations/fr/fr_FR.lng @@ -2148,16 +2148,16 @@ Affiche ou modifie la page de code DOS actuelle. . :SHELL_CMD_CHCP_HELP_LONG CHCP [nnn [fichier]] +CHCP nnn[:[langue]] nnn Spécifie un numéro de page de code. - fichier Spécifie un fichier de page de code + fichier Spécifie un fichier de page de code. + langue Spécifie une langue correspondante. Pages de code prises en charge pour être modifiées dans la sortie de la police TrueType : -437, 737, 775, 808, 850, 852, 853, 855-866, 869, 872, 874, 3021 - -Pages de codes Windows: 1250,1251,1252,1253,1254,1255,1256,1257,1258 +437,737,775,808,850,852,853,855-866,869,872,874,1250-1258,3021 Également des pages de code à double octet, notamment 932, 936, 949 et 950/951. @@ -3284,8 +3284,8 @@ Redémarrer DOSBox-X :MENU:restartconf Redémarrer avec un fichier de configuration... . -:MENU:restartlang -Redémarrer avec un fichier de langue... +:MENU:loadlang +Charger le fichier de langue... . :MENU:auto_lock_mouse Verrouiller la souris automatiquement diff --git a/contrib/translations/ja/ja_JP.lng b/contrib/translations/ja/ja_JP.lng index be18284b3..adfbba087 100644 --- a/contrib/translations/ja/ja_JP.lng +++ b/contrib/translations/ja/ja_JP.lng @@ -2132,15 +2132,15 @@ ASSOC [.ext[=command] ... ] . :SHELL_CMD_CHCP_HELP_LONG CHCP [nnn [file]] +CHCP nnn[:[language]] - nnn コードページ番号を指定します。 - [file] コードページファイルを指定します。 + nnn コードページ番号を指定します。 + [file] コードページファイルを指定します。 + [language] 対応する言語を指定します。 TrueType フォント出力への変更をサポートするコードページ: -437, 737, 775, 808, 850, 852, 853, 855-866, 869, 872, 874, 3021 - -Windows コードページ: 1250,1251,1252,1253,1254,1255,1256,1257,1258 +437,737,775,808,850,852,853,855-866,869,872,874,1250-1258,3021 932, 936, 949, 950/951 等の2バイト言語のコードページもサポートします。 @@ -3265,8 +3265,8 @@ DOSBox-X インスタンスを再起動 :MENU:restartconf 設定ファイルを用いて DOSBox-X を再起動 ... . -:MENU:restartlang -言語ファイルを用いて DOSBox-X を再起動 ... +:MENU:loadlang +言語ファイルの読込み... . :MENU:auto_lock_mouse マウスを自動ロック diff --git a/contrib/translations/ko/ko_KR.lng b/contrib/translations/ko/ko_KR.lng index 59446e52b..4efc796e7 100644 --- a/contrib/translations/ko/ko_KR.lng +++ b/contrib/translations/ko/ko_KR.lng @@ -2146,15 +2146,15 @@ ASSOC [.ext[=command] ... ] . :SHELL_CMD_CHCP_HELP_LONG CHCP [nnn [file]] +CHCP nnn[:[language]] - nnn 코드 페이지 번호를 지정합니다. - [file] 코드 페이지 파일을 지정합니다. + nnn 코드 페이지 번호를 지정합니다. + [file] 코드 페이지 파일을 지정합니다. + [language] 해당 언어를 지정합니다. TrueType 글꼴 출력에 대한 변경을 지원하는 코드 페이지: -437, 737, 775, 808, 850, 852, 853, 855-866, 869, 872, 874, 3021 - -윈도우즈 코드 페이지: 1250,1251,1252,1253,1254,1255,1256,1257,1258 +437,737,775,808,850,852,853,855-866,869,872,874,1250-1258,3021 932, 936, 949, 950/951 등의 2바이트 언어 코드 페이지도 지원합니다. @@ -3278,8 +3278,8 @@ DOSBox-X 인스턴스를 다시 시작 :MENU:restartconf 구성 파일을 사용하여 DOSBox-X 를 다시 부팅 ... . -:MENU:restartlang -언어 파일을 사용하여 DOSBox-X 를 다시 부팅 ... +:MENU:loadlang +언어 파일 로드 ... . :MENU:auto_lock_mouse 마우스 자동 잠금 diff --git a/contrib/translations/pt/pt_BR.lng b/contrib/translations/pt/pt_BR.lng index cd26b56db..33093c581 100644 --- a/contrib/translations/pt/pt_BR.lng +++ b/contrib/translations/pt/pt_BR.lng @@ -2166,15 +2166,15 @@ Exibe ou define o número da página de código ativa. . :SHELL_CMD_CHCP_HELP_LONG CHCP [nnn [arquivo]] +CHCP nnn[:[idioma]] - nnn Define um número da página de código. + nnn Define um número da página de código. arquivo Especifica um arquivo de página de código. + idioma Especifica um idioma correspondente. Páginas de código compatíveis para a saída de fonte TrueType: -437, 737, 775, 808, 850, 852, 853, 855-866, 869, 872, 874, 3021 - -Páginas de códigos do Windows: 1250,1251,1252,1253,1254,1255,1256,1257,1258 +437,737,775,808,850,852,853,855-866,869,872,874,1250-1258,3021 Também páginas de códigos de duplo byte includindo 932,936,949,950/951. @@ -3300,8 +3300,8 @@ Reiniciar instância do DOSBox-X :MENU:restartconf Reiniciar o DOSBox-X com arquivo config... . -:MENU:restartlang -Reiniciar o DOSBox-X com arquivo de idioma... +:MENU:loadlang +Carregar arquivo de idioma... . :MENU:auto_lock_mouse Travar automaticamente mouse diff --git a/contrib/translations/tr/tr_TR.lng b/contrib/translations/tr/tr_TR.lng index e2515957b..6ad02f543 100644 --- a/contrib/translations/tr/tr_TR.lng +++ b/contrib/translations/tr/tr_TR.lng @@ -2146,17 +2146,17 @@ Geçerli DOS kod sayfasını görüntüler veya değiştirir. . :SHELL_CMD_CHCP_HELP_LONG CHCP [nnn [dosya]] +CHCP nnn[:[dil]] nnn Bir kod sayfası numarası belirtir. dosya Bir kod sayfası dosyası belirtir. + dil İlgili bir dili belirtir. TrueType yazıtipi çıktısında desteklenen kod sayfaları aşağıdaki gibidir: -437, 737, 775, 808, 850, 852, 853, 855-866, 869, 872, 874, 3021 +437,737,775,808,850,852,853,855-866,869,872,874,1250-1258,3021 -Windows kod sayfaları: 1250,1251,1252,1253,1254,1255,1256,1257,1258 - -Ek olarak 932, 936, 949 ve 950/951 numaralı çoklu bit kod sayfaları da desteklenir. +Ek olarak 932,936,949,950/951 numaralı çoklu bit kod sayfaları da desteklenir. Özel kod sayfaları, kod sayfası dosyaları sağlanarak desteklenir. @@ -3278,8 +3278,8 @@ DOSBox-X oturumunu yeniden başlat :MENU:restartconf DOSBox-X'i yapılandırma dosyasıyla yeniden başlat... . -:MENU:restartlang -DOSBox-X'i dil dosyasıyla yeniden başlat... +:MENU:loadlang +Dil dosyasını yükle... . :MENU:auto_lock_mouse Fareyi kendiliğinden kilitle diff --git a/contrib/translations/zh/zh_CN.lng b/contrib/translations/zh/zh_CN.lng index 4cdc857b5..e2b9ead55 100644 --- a/contrib/translations/zh/zh_CN.lng +++ b/contrib/translations/zh/zh_CN.lng @@ -2083,15 +2083,15 @@ ASSOC [.扩展名[=命令] ... ] . :SHELL_CMD_CHCP_HELP_LONG CHCP [nnn [文件]] +CHCP nnn[:[语言]] nnn 指定代码页. 文件 指定代码页文件. + 语言 指定相应的语言. TrueType 字体输出方式所支持的代码页包括: -437, 737, 775, 808, 850, 852, 853, 855-866, 869, 872, 874, 3021 - -Windows 代码页: 1250,1251,1252,1253,1254,1255,1256,1257,1258 +437,737,775,808,850,852,853,855-866,869,872,874,1250-1258,3021 以及双字节代码页,包括: 932, 936, 949, 950/951 @@ -3243,8 +3243,8 @@ DOS 命令 :MENU:restartconf 重启 DOSBox-X 并调用指定配置文件... . -:MENU:restartlang -重启 DOSBox-X 并调用指定语言文件... +:MENU:loadlang +加载语言文件... . :MENU:auto_lock_mouse 自动锁定鼠标 diff --git a/contrib/translations/zh/zh_TW.lng b/contrib/translations/zh/zh_TW.lng index a6ed3181a..6effea354 100644 --- a/contrib/translations/zh/zh_TW.lng +++ b/contrib/translations/zh/zh_TW.lng @@ -2087,15 +2087,15 @@ ASSOC [.副檔名[=命令] ... ] . :SHELL_CMD_CHCP_HELP_LONG CHCP [nnn [檔案]] +CHCP nnn[:[語言]] nnn 指定字碼頁編號. 檔案 指定字碼頁檔案. + 語言 指定相應的語言. 在 TrueType 字型輸出方式所支援變更的字碼頁包括: -437, 737, 775, 808, 850, 852, 853, 855-866, 869, 872, 874, 3021 - -Windows 字碼頁: 1250,1251,1252,1253,1254,1255,1256,1257,1258 +437,737,775,808,850,852,853,855-866,869,872,874,1250-1258,3021 以及雙位元組字碼頁, 包括: 932, 936, 949, 950/951 @@ -3250,8 +3250,8 @@ Turbo (快轉模式) :MENU:restartconf 重開 DOSBox-X 並載入指定組態檔案... . -:MENU:restartlang -重開 DOSBox-X 並載入指定語言檔案... +:MENU:loadlang +載入語言檔案... . :MENU:auto_lock_mouse 自動鎖定滑鼠 diff --git a/include/shell.h b/include/shell.h index 58cc5d158..1a048cf09 100644 --- a/include/shell.h +++ b/include/shell.h @@ -43,6 +43,18 @@ class DOS_Shell; * by "external" programs. (config) */ extern DOS_Shell * first_shell; +const std::map langcp_map { + {437, "en_US"}, + {857, "tr_TR"}, + {858, "es_ES"}, + {859, "fr_FR"}, + {860, "pt_BR"}, + {932, "ja_JP"}, + {936, "zh_CN"}, + {949, "ko_KR"}, + {950, "zh_TW"}, + {951, "zh_TW"}, +}; class BatchFile { public: diff --git a/src/dos/dos.cpp b/src/dos/dos.cpp index eb61ed37a..767b757e0 100644 --- a/src/dos/dos.cpp +++ b/src/dos/dos.cpp @@ -74,7 +74,7 @@ extern bool log_int21, log_fileio, pipetmpdev; #if defined(USE_TTF) extern bool ttf_dosv; #endif -extern int lfn_filefind_handle, autofixwarn, result_errorcode; +extern int autofixwarn, lfn_filefind_handle, result_errorcode; extern uint16_t customcp_to_unicode[256]; int customcp = 0, altcp = 0; unsigned long totalc, freec; @@ -83,6 +83,7 @@ Bitu INT29_HANDLER(void); bool isDBCSCP(); uint32_t BIOS_get_PC98_INT_STUB(void); void ResolvePath(std::string& in); +void SwitchLanguage(int oldcp, int newcp, bool confirm); std::string GetDOSBoxXPath(bool withexe=false); extern std::string prefix_local, prefix_overlay; @@ -136,6 +137,7 @@ bool hidenonrep = true; bool rsize = false; bool reqwin = false; bool packerr = false; +bool incall = false; int file_access_tries = 0; int dos_initial_hma_free = 34*1024; int dos_sda_size = 0x560; @@ -2710,6 +2712,7 @@ static Bitu DOS_21Handler(void) { CALLBACK_SCF(false); break; case 2: + { #if defined(USE_TTF) if (!ttf.inUse) #endif @@ -2728,6 +2731,7 @@ static Bitu DOS_21Handler(void) { reg_ax = dos.errorcode; break; } + int cpbak = dos.loaded_codepage; dos.loaded_codepage = reg_bx; #if defined(USE_TTF) setTTFCodePage(); @@ -2758,8 +2762,12 @@ static Bitu DOS_21Handler(void) { } SetupDBCSTable(); runRescan("-A -Q"); + incall = true; + SwitchLanguage(cpbak, dos.loaded_codepage, false); + incall = false; CALLBACK_SCF(false); break; + } default: dos.errorcode = 1; reg_ax = dos.errorcode; diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index 6be0db628..0b8fc14a9 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -102,15 +102,17 @@ bool qmount = false; bool nowarn = false; bool CodePageHostToGuestUTF8(char *d/*CROSS_LEN*/,const char *s/*CROSS_LEN*/), CodePageHostToGuestUTF16(char *d/*CROSS_LEN*/,const uint16_t *s/*CROSS_LEN*/); extern bool systemmessagebox(char const * aTitle, char const * aMessage, char const * aDialogType, char const * aIconType, int aDefaultButton); -extern bool addovl, addipx, addne2k, prepared, inshell, usecon, uao, morelen, mountfro[26], mountiro[26], resetcolor, staycolors, printfont, tryconvertcp, notrycp, internal_program; +extern bool addovl, addipx, addne2k, prepared, inshell, usecon, uao, loadlang, morelen, mountfro[26], mountiro[26], resetcolor, staycolors, printfont, tryconvertcp, notrycp, internal_program; extern bool clear_screen(), OpenGL_using(void), DOS_SetAnsiAttr(uint8_t attr), isDBCSCP(); -extern int lastcp, FileDirExistCP(const char *name), FileDirExistUTF8(std::string &localname, const char *name); +extern int lastcp, lastmsgcp, FileDirExistCP(const char *name), FileDirExistUTF8(std::string &localname, const char *name); extern uint8_t DOS_GetAnsiAttr(void); -void MSG_Init(), JFONT_Init(), InitFontHandle(), ShutFontHandle(), DOSBox_SetSysMenu(); -void DOS_EnableDriveMenu(char drv), GFX_SetTitle(int32_t cycles, int frameskip, Bits timing, bool paused), UpdateSDLDrawTexture(), toSetCodePage(DOS_Shell *shell, int newCP, int opt); +extern int toSetCodePage(DOS_Shell *shell, int newCP, int opt); +void MSG_Init(), JFONT_Init(), InitFontHandle(), ShutFontHandle(), DOSBox_SetSysMenu(), Load_Language(std::string name); +void DOS_EnableDriveMenu(char drv), GFX_SetTitle(int32_t cycles, int frameskip, Bits timing, bool paused), UpdateSDLDrawTexture(); void runBoot(const char *str), runMount(const char *str), runImgmount(const char *str), runRescan(const char *str), show_prompt(), ttf_reset(void); void getdrivezpath(std::string &path, std::string dirname), drivezRegister(std::string path, std::string dir, bool usecp), UpdateDefaultPrinterFont(void); std::string GetDOSBoxXPath(bool withexe=false); +FILE *testLoadLangFile(const char *fname); #if defined(OS2) #define INCL DOSFILEMGR @@ -196,6 +198,22 @@ void DetachFromBios(imageDisk* image) { } } +void SwitchLanguage(int oldcp, int newcp, bool confirm) { + auto iterold = langcp_map.find(oldcp), iternew = langcp_map.find(newcp); + std::string langold = iterold != langcp_map.end() ? iterold->second : "", langnew = iternew != langcp_map.end() ? iternew->second : ""; + if (loadlang && (oldcp == lastmsgcp || (oldcp == 951 && lastmsgcp == 950)) && oldcp != newcp && newcp == dos.loaded_codepage && langnew.size() && !(langold.size() && langold == langnew)) { + FILE *file = testLoadLangFile(langnew.c_str()); + if (file) { + fclose(file); + std::string msg = "You have changed the active code page to " + std::to_string(newcp) + ". Do you want to load language file " + langnew + " for this code page?"; + if (!confirm || systemmessagebox("DOSBox-X language file", msg.c_str(), "yesno","question", 2)) { + SetVal("dosbox", "language", langnew); + Load_Language(langnew); + } + } + } +} + extern std::string hidefiles, dosbox_title; extern int swapInDisksSpecificDrive; extern bool dos_kernel_disabled, clearline; @@ -1324,6 +1342,7 @@ public: UpdateSDLDrawTexture(); #endif } + SwitchLanguage(cpbak, cp, false); } } #elif defined (OS2) @@ -6388,6 +6407,7 @@ void KEYB::Run(void) { int32_t tried_cp = -1; cmd->FindCommand(2,cp_string); int tocp=!strcmp(temp_line.c_str(), "jp")?932:(!strcmp(temp_line.c_str(), "ko")?949:(!strcmp(temp_line.c_str(), "tw")||!strcmp(temp_line.c_str(), "hk")||!strcmp(temp_line.c_str(), "zht")||(!strcmp(temp_line.c_str(), "zh")&&((cp_string.size()&&(atoi(cp_string.c_str())==950||atoi(cp_string.c_str())==951))||(!cp_string.size()&&(dos.loaded_codepage==950||dos.loaded_codepage==951))))?((cp_string.size()&&atoi(cp_string.c_str())==951)||(!cp_string.size()&&dos.loaded_codepage==951)?951:950):(!strcmp(temp_line.c_str(), "cn")||!strcmp(temp_line.c_str(), "zhs")||!strcmp(temp_line.c_str(), "zh")?936:0))); + int cp = dos.loaded_codepage; if (tocp && !IS_PC98_ARCH) { uint16_t cpbak = dos.loaded_codepage; dos.loaded_codepage=tocp; @@ -6417,6 +6437,7 @@ void KEYB::Run(void) { UpdateSDLDrawTexture(); #endif } + SwitchLanguage(cp, tocp, true); return; } if (cp_string.size()) { @@ -6437,9 +6458,16 @@ void KEYB::Run(void) { } switch (keyb_error) { case KEYB_NOERROR: + { WriteOut(MSG_Get("PROGRAM_KEYB_NOERROR"),temp_line.c_str(),dos.loaded_codepage); runRescan("-A -Q"); +#if C_OPENGL && DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW + if (OpenGL_using() && control->opt_lang.size() && lastcp && lastcp != dos.loaded_codepage) + UpdateSDLDrawTexture(); +#endif + SwitchLanguage(cp, dos.loaded_codepage, true); break; + } case KEYB_FILENOTFOUND: if (temp_line!="/?"&&temp_line!="-?") WriteOut(MSG_Get("PROGRAM_KEYB_FILENOTFOUND"),temp_line.c_str()); WriteOut(MSG_Get("PROGRAM_KEYB_SHOWHELP")); diff --git a/src/gui/menu.cpp b/src/gui/menu.cpp index 228b167ea..50cea6af7 100644 --- a/src/gui/menu.cpp +++ b/src/gui/menu.cpp @@ -137,11 +137,12 @@ static const char *def_menu_main[] = { "mapper_gui", "mapper_mapper", - "--", #if !defined(HX_DOS) + "--", "mapper_quickrun", -#endif + "loadlang", "mapper_loadmap", +#endif "--", "MainSendKey", "MainHostKey", @@ -166,7 +167,6 @@ static const char *def_menu_main[] = "--", "restartinst", "restartconf", - "restartlang", "--", "mapper_shutdown", #endif @@ -1873,6 +1873,8 @@ void DOSBox_SetMenu(void) { } #endif #if DOSBOXMENU_TYPE == DOSBOXMENU_NSMENU /* TODO: Move to menu.cpp DOSBox_SetMenu() and add setmenu(NULL) to DOSBox_NoMenu() @emendelson request showmenu=false */ + if(!menu.gui) return; + menu.toggle=true; void sdl_hax_macosx_setmenu(void *nsMenu); sdl_hax_macosx_setmenu(mainMenu.getNsMenu()); #endif @@ -1912,6 +1914,8 @@ void DOSBox_NoMenu(void) { } #endif #if DOSBOXMENU_TYPE == DOSBOXMENU_NSMENU + if(!menu.gui) return; + menu.toggle=false; void sdl_hax_macosx_setmenu(void *nsMenu); sdl_hax_macosx_setmenu(NULL); #endif diff --git a/src/gui/menu_callback.cpp b/src/gui/menu_callback.cpp index 5ec62dc70..1e56edde2 100644 --- a/src/gui/menu_callback.cpp +++ b/src/gui/menu_callback.cpp @@ -50,8 +50,8 @@ std::string savefilename = ""; extern SHELL_Cmd cmd_list[]; extern unsigned int page, hostkeyalt, sendkeymap; -extern int posx, posy, wheel_key, mbutton, enablelfn, dos_clipboard_device_access, aspect_ratio_x, aspect_ratio_y, disk_data_rate, floppy_data_rate; -extern bool addovl, clearline, pcibus_enable, winrun, window_was_maximized, wheel_guest, clipboard_dosapi, clipboard_biospaste, direct_mouse_clipboard, sync_time, manualtime, pausewithinterrupts_enable, enable_autosave, enable_config_as_shell_commands, noremark_save_state, force_load_state, use_quick_reboot, use_save_file, dpi_aware_enable, pc98_force_ibm_layout, log_int21, log_fileio, x11_on_top, macosx_on_top, rtl, gbk, chinasea; +extern int posx, posy, wheel_key, mbutton, enablelfn, dos_clipboard_device_access, aspect_ratio_x, aspect_ratio_y, disk_data_rate, floppy_data_rate, lastmsgcp; +extern bool addovl, clearline, pcibus_enable, winrun, window_was_maximized, wheel_guest, clipboard_dosapi, clipboard_biospaste, direct_mouse_clipboard, sync_time, manualtime, pausewithinterrupts_enable, enable_autosave, enable_config_as_shell_commands, noremark_save_state, force_load_state, use_quick_reboot, use_save_file, dpi_aware_enable, pc98_force_ibm_layout, log_int21, log_fileio, x11_on_top, macosx_on_top, rtl, gbk, chinasea, uselangcp; extern bool mountfro[26], mountiro[26]; extern struct BuiltinFileBlob bfb_GLIDE2X_OVL; extern const char* RunningProgram; @@ -69,6 +69,7 @@ void VFILE_Remove(const char *name,const char *dir = ""); void VOODOO_Destroy(Section* /*sec*/), VOODOO_OnPowerOn(Section* /*sec*/); void GLIDE_ShutDown(Section* sec), GLIDE_PowerOn(Section* sec); void DOSBox_ShowConsole(void); +void Load_Language(std::string name); void RebootLanguage(std::string filename, bool confirm=false); void MenuBrowseFolder(char drive, std::string drive_type); void MenuBrowseImageFile(char drive, bool arc, bool boot, bool multiple); @@ -89,6 +90,7 @@ int setTTFMap(bool changecp), FileDirExistCP(const char *name), FileDirExistUTF8 size_t GetGameState_Run(void); void DBCSSBCS_mapper_shortcut(bool pressed); void AutoBoxDraw_mapper_shortcut(bool pressed); +extern std::string langname, GetDOSBoxXPath(bool withexe=false); void* GetSetSDLValue(int isget, std::string& target, void* setval) { if (target == "wait_on_error") { @@ -600,7 +602,7 @@ bool a20gate_on_menu_callback(DOSBoxMenu * const menu,DOSBoxMenu::item * const m mainMenu.get_item("enable_a20gate").check(MEM_A20_Enabled()).refresh_item(mainMenu); else { std::string msg = "The A20 gate may be locked and cannot be "+std::string(bef?"disabled":"enabled")+"."; - systemmessagebox("Warning",msg.c_str(),"ok", "info", 1); + systemmessagebox("Warning",msg.c_str(),"ok", "warning", 1); } return true; } @@ -1787,15 +1789,24 @@ void Restart_config_file() { #endif } -void Restart_language_file() { +void Load_language_file() { #if !defined(HX_DOS) char CurrentDir[512]; char * Temp_CurrentDir = CurrentDir; if(getcwd(Temp_CurrentDir, 512) == NULL) { - LOG(LOG_GUI, LOG_ERROR)("Restart_language_file failed to get the current working directory."); + LOG(LOG_GUI, LOG_ERROR)("Load_language_file failed to get the current working directory."); return; } - std::string cwd = std::string(Temp_CurrentDir)+CROSS_FILESPLIT; + struct stat st; + std::string res_path, exepath = GetDOSBoxXPath(); + std::string cwd = std::string(Temp_CurrentDir)+CROSS_FILESPLIT+"languages"+CROSS_FILESPLIT; + Cross::GetPlatformResDir(res_path); + if (stat(cwd.c_str(),&st) != 0 && exepath.size()) + cwd = exepath+(exepath.back()==CROSS_FILESPLIT?"":std::string(1, CROSS_FILESPLIT))+"languages"+CROSS_FILESPLIT; + if (stat(cwd.c_str(),&st) != 0 && res_path.size()) + cwd = res_path+(res_path.back()==CROSS_FILESPLIT?"":std::string(1, CROSS_FILESPLIT))+"languages"+CROSS_FILESPLIT; + if (stat(cwd.c_str(),&st) != 0) + cwd = std::string(Temp_CurrentDir)+CROSS_FILESPLIT; const char *lFilterPatterns[] = {"*.lng","*.LNG","*.txt","*.TXT"}; const char *lFilterDescription = "DOSBox-X language files (*.lng, *.txt)"; char const * lTheOpenFileName = tinyfd_openFileDialog("Select language file",cwd.c_str(),4,lFilterPatterns,lFilterDescription,0); @@ -1814,15 +1825,23 @@ void Restart_language_file() { } if (*name) { - std::string localname = name; - if (!FileDirExistCP(name) && FileDirExistUTF8(localname, name)) - RebootLanguage(localname.c_str(), true); - else - RebootLanguage(name, true); + std::string localname = name, newname = !FileDirExistCP(name) && FileDirExistUTF8(localname, name) ? localname : name; + if (dos_kernel_disabled) + RebootLanguage(newname.c_str(), true); + else { + uselangcp = true; + SetVal("dosbox", "language", newname); + Load_Language(newname); + uselangcp = false; + if (lastmsgcp == dos.loaded_codepage && langname.size()) { + std::string msg = "DOSBox-X has successfully loaded the following language:\n\n" + langname + " [code page " + std::to_string(lastmsgcp) + "]\n\nMessages from this language will be applied from this point."; + systemmessagebox("DOSBox-X language file", msg.c_str(), "ok","info", 2); + } + } } } if(chdir(Temp_CurrentDir) == -1) { - LOG(LOG_GUI, LOG_ERROR)("Restart_language_file failed to change directories."); + LOG(LOG_GUI, LOG_ERROR)("Load_language_file failed to change directories."); } #endif } @@ -2722,10 +2741,10 @@ bool restartconf_menu_callback(DOSBoxMenu * const xmenu, DOSBoxMenu::item * cons return true; } -bool restartlang_menu_callback(DOSBoxMenu * const xmenu, DOSBoxMenu::item * const menuitem) { +bool loadlang_menu_callback(DOSBoxMenu * const xmenu, DOSBoxMenu::item * const menuitem) { (void)xmenu;//UNUSED (void)menuitem;//UNUSED - Restart_language_file(); + Load_language_file(); return true; } @@ -3524,7 +3543,7 @@ void AllocCallback2() { mainMenu.alloc_item(DOSBoxMenu::item_type_id,"showdetails").set_text("Show FPS and RT speed in title bar").set_callback_function(showdetails_menu_callback).check(!menu.hidecycles && menu.showrt); mainMenu.alloc_item(DOSBoxMenu::item_type_id,"restartinst").set_text("Restart DOSBox-X instance").set_callback_function(restartinst_menu_callback); mainMenu.alloc_item(DOSBoxMenu::item_type_id,"restartconf").set_text("Restart DOSBox-X with config file...").set_callback_function(restartconf_menu_callback); - mainMenu.alloc_item(DOSBoxMenu::item_type_id,"restartlang").set_text("Restart DOSBox-X with language file...").set_callback_function(restartlang_menu_callback); + mainMenu.alloc_item(DOSBoxMenu::item_type_id,"loadlang").set_text("Load language file...").set_callback_function(loadlang_menu_callback); mainMenu.alloc_item(DOSBoxMenu::item_type_id,"auto_lock_mouse").set_text("Autolock mouse").set_callback_function(autolock_mouse_menu_callback).check(sdl.mouse.autoenable); #if defined (WIN32) || defined(MACOSX) || defined(C_SDL2) mainMenu.alloc_item(DOSBoxMenu::item_type_id,"clipboard_right").set_text("Via right mouse button").set_callback_function(right_mouse_clipboard_menu_callback).check(mbutton==3); diff --git a/src/gui/sdl_gui.cpp b/src/gui/sdl_gui.cpp index 5aaa5d7d0..4d96dc46d 100644 --- a/src/gui/sdl_gui.cpp +++ b/src/gui/sdl_gui.cpp @@ -475,7 +475,7 @@ static GUI::ScreenSDL *UI_Startup(GUI::ScreenSDL *screen) { DOSBoxMenu::item &item = guiMenu.get_item("ExitGUI"); item.set_text(MSG_Get("CONFIG_TOOL_EXIT")); } -# if DOSBOXMENU_TYPE == DOSBOXMENU_HMENU +# if DOSBOXMENU_TYPE == DOSBOXMENU_HMENU || DOSBOXMENU_TYPE == DOSBOXMENU_NSMENU if (loadlang) guiMenu.unbuild(); # endif } diff --git a/src/gui/sdl_mapper.cpp b/src/gui/sdl_mapper.cpp index 16a77e343..c96b143ac 100644 --- a/src/gui/sdl_mapper.cpp +++ b/src/gui/sdl_mapper.cpp @@ -5201,7 +5201,7 @@ void MAPPER_RunInternal() { DOSBoxMenu::item &item = mapperMenu.get_item("SaveMapper"); item.set_text(MSG_Get("SAVE_MAPPER_FILE")); } -# if DOSBOXMENU_TYPE == DOSBOXMENU_HMENU +# if DOSBOXMENU_TYPE == DOSBOXMENU_HMENU || DOSBOXMENU_TYPE == DOSBOXMENU_NSMENU if (loadlang) mapperMenu.unbuild(); # endif mapperMenu.rebuild(); diff --git a/src/misc/messages.cpp b/src/misc/messages.cpp index 943f8d630..e099f62a7 100644 --- a/src/misc/messages.cpp +++ b/src/misc/messages.cpp @@ -38,14 +38,14 @@ #endif using namespace std; -int msgcodepage = 0, FileDirExistUTF8(std::string &localname, const char *name); Bitu DOS_LoadKeyboardLayout(const char * layoutname, int32_t codepage, const char * codepagefile); +int msgcodepage = 0, lastmsgcp = 0, FileDirExistUTF8(std::string &localname, const char *name), toSetCodePage(DOS_Shell *shell, int newCP, int opt); bool morelen = false, inmsg = false, loadlang = false, uselangcp = false, systemmessagebox(char const * aTitle, char const * aMessage, char const * aDialogType, char const * aIconType, int aDefaultButton), OpenGL_using(void); bool isSupportedCP(int newCP), CodePageHostToGuestUTF8(char *d/*CROSS_LEN*/,const char *s/*CROSS_LEN*/), CodePageGuestToHostUTF8(char *d/*CROSS_LEN*/,const char *s/*CROSS_LEN*/); -void InitFontHandle(void), ShutFontHandle(void), SetIME(void), menu_update_dynamic(void), menu_update_autocycle(void), update_bindbutton_text(void), set_eventbutton_text(const char *eventname, const char *buttonname), JFONT_Init(), DOSBox_SetSysMenu(), toSetCodePage(DOS_Shell *shell, int newCP, int opt), UpdateSDLDrawTexture(), makestdcp950table(), makeseacp951table(); +void InitFontHandle(void), ShutFontHandle(void), SetIME(void), menu_update_dynamic(void), menu_update_autocycle(void), update_bindbutton_text(void), set_eventbutton_text(const char *eventname, const char *buttonname), JFONT_Init(), DOSBox_SetSysMenu(), UpdateSDLDrawTexture(), makestdcp950table(), makeseacp951table(); std::string langname = "", langnote = "", GetDOSBoxXPath(bool withexe=false); -const char *DOS_GetLoadedLayout(); extern int lastcp; +extern const char * RunningProgram; extern bool dos_kernel_disabled, force_conversion, showdbcs, dbcs_sbcs, enableime, tonoime, chinasea; #define LINE_IN_MAXLEN 2048 @@ -203,6 +203,7 @@ void AddMessages() { } void SetKEYBCP() { + if (IS_PC98_ARCH || dos_kernel_disabled || !strcmp(RunningProgram, "LOADLIN")) return; if (msgcodepage == 437) {dos.loaded_codepage=0;DOS_LoadKeyboardLayout("us", 437, "auto");dos.loaded_codepage=437;} else if (msgcodepage == 857) {dos.loaded_codepage=437;DOS_LoadKeyboardLayout("tr", 857, "auto");dos.loaded_codepage=857;} else if (msgcodepage == 858) {dos.loaded_codepage=437;DOS_LoadKeyboardLayout("es", 858, "auto");dos.loaded_codepage=858;} @@ -215,14 +216,9 @@ void SetKEYBCP() { else if (msgcodepage == 951) {dos.loaded_codepage=0;DOS_LoadKeyboardLayout("us", 437, "auto");DOS_LoadKeyboardLayout("hk", 951, "auto");dos.loaded_codepage=951;} } -void LoadMessageFile(const char * fname) { - if (!fname) return; - if(*fname=='\0') return;//empty string=no languagefile - - LOG(LOG_MISC,LOG_DEBUG)("Loading message file %s",fname); +FILE *testLoadLangFile(const char *fname) { std::string config_path, res_path, exepath=GetDOSBoxXPath(); Cross::GetPlatformConfigDir(config_path), Cross::GetPlatformResDir(res_path); - FILE * mfile=fopen(fname,"rt"); if (!mfile) mfile=fopen((fname + std::string(".lng")).c_str(),"rt"); if (!mfile && exepath.size()) mfile=fopen((exepath + fname).c_str(),"rt"); @@ -251,11 +247,22 @@ void LoadMessageFile(const char * fname) { std::string localname = fname; if (!mfile && FileDirExistUTF8(localname, fname) == 1) mfile=fopen(localname.c_str(),"rt"); #endif + return mfile; +} +void LoadMessageFile(const char * fname) { + if (!fname) return; + if(*fname=='\0') return;//empty string=no languagefile + + LOG(LOG_MISC,LOG_DEBUG)("Loading message file %s",fname); + + lastmsgcp = 0; + FILE * mfile=testLoadLangFile(fname); /* This should never happen and since other modules depend on this use a normal printf */ if (!mfile) { 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); + SetVal("dosbox", "language", ""); LOG_MSG("MSG:Cannot load language file: %s",fname); return; } @@ -305,6 +312,7 @@ void LoadMessageFile(const char * fname) { if (c == 950 && !chinasea) makestdcp950table(); if (c == 951 && chinasea) makeseacp951table(); } + lastmsgcp = c; } else if (!strcmp(p, "LANGUAGE")) langname = r+1; else if (!strcmp(p, "REMARK")) diff --git a/src/misc/programs.cpp b/src/misc/programs.cpp index 5202650d5..6d5acec3c 100644 --- a/src/misc/programs.cpp +++ b/src/misc/programs.cpp @@ -56,8 +56,8 @@ extern char lastmount; extern const char *modifier; extern unsigned int sendkeymap; extern std::string langname, configfile, dosbox_title; -extern int autofixwarn, enablelfn, fat32setver, paste_speed, wheel_key, freesizecap, wpType, wpVersion, wpBG, wpFG, lastset, blinkCursor; -extern bool dos_kernel_disabled, force_nocachedir, wpcolon, convertimg, lockmount, enable_config_as_shell_commands, lesssize, load, winrun, winautorun, startcmd, startwait, startquiet, starttranspath, mountwarning, wheel_guest, clipboard_dosapi, noremark_save_state, force_load_state, sync_time, manualtime, ttfswitch, loadlang, showbold, showital, showline, showsout, char512, printfont, rtl, gbk, chinasea, uao, showdbcs, dbcs_sbcs, autoboxdraw, halfwidthkana, ticksLocked, outcon, enable_dbcs_tables, show_recorded_filename, internal_program, pipetmpdev, notrysgf, uselangcp; +extern int autofixwarn, enablelfn, fat32setver, paste_speed, wheel_key, freesizecap, wpType, wpVersion, wpBG, wpFG, lastset, blinkCursor, msgcodepage; +extern bool dos_kernel_disabled, force_nocachedir, wpcolon, convertimg, lockmount, enable_config_as_shell_commands, lesssize, load, winrun, winautorun, startcmd, startwait, startquiet, starttranspath, mountwarning, wheel_guest, clipboard_dosapi, noremark_save_state, force_load_state, sync_time, manualtime, ttfswitch, loadlang, showbold, showital, showline, showsout, char512, printfont, rtl, gbk, chinasea, uao, showdbcs, dbcs_sbcs, autoboxdraw, halfwidthkana, ticksLocked, outcon, enable_dbcs_tables, show_recorded_filename, internal_program, pipetmpdev, notrysgf, uselangcp, incall; /* This registers a file on the virtual drive and creates the correct structure for it*/ @@ -100,7 +100,7 @@ uint8_t DOS_GetAnsiAttr(void); int setTTFMap(bool changecp); char *FormatDate(uint16_t year, uint8_t month, uint8_t day); bool isDBCSCP(void), CheckBoxDrawing(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4), DOS_SetAnsiAttr(uint8_t attr), GFX_GetPreventFullscreen(void), toOutput(const char *what); -void EMS_DoShutDown(void), UpdateDefaultPrinterFont(void), GFX_ForceRedrawScreen(void), resetFontSize(void), ttf_reset_colors(void), makestdcp950table(void), makeseacp951table(void), clearFontCache(void), DOSBox_SetSysMenu(void), MSG_Init(void), initRand(void), PRINTER_Init(void); +void EMS_DoShutDown(void), UpdateDefaultPrinterFont(void), GFX_ForceRedrawScreen(void), resetFontSize(void), ttf_reset_colors(void), makestdcp950table(void), makeseacp951table(void), clearFontCache(void), DOSBox_SetSysMenu(void), MSG_Init(void), initRand(void), PRINTER_Init(void), SetKEYBCP(void); void EMS_Startup(Section* sec), DOSV_SetConfig(Section_prop *section), DOSBOX_UnlockSpeed2(bool pressed), RebootLanguage(std::string filename, bool confirm=false), SetWindowTransparency(int trans), SetOutputSwitch(const char *outputstr), runRescan(const char *str), runSerial(const char *str), runParallel(const char *str), DOS_AddDays(uint8_t days), PRINTER_Shutdown(Section* sec), setAspectRatio(Section_prop * section); void PROGRAMS_Shutdown(void) { @@ -629,6 +629,27 @@ private: void dos_ver_menu(bool start), ReloadMapper(Section_prop *sec, bool init), SetGameState_Run(int value), update_dos_ems_menu(void), MountAllDrives(bool quiet), GFX_SwitchFullScreen(void), RebootConfig(std::string filename, bool confirm=false); bool set_ver(char *s), GFX_IsFullscreen(void); +void Load_Language(std::string name) { + if (control->opt_lang != "") control->opt_lang = name; + MSG_Init(); +#if DOSBOXMENU_TYPE == DOSBOXMENU_HMENU || DOSBOXMENU_TYPE == DOSBOXMENU_NSMENU + mainMenu.unbuild(); + mainMenu.rebuild(); +#endif + if (!GFX_GetPreventFullscreen()) { + if (menu.toggle) DOSBox_SetMenu(); else DOSBox_NoMenu(); + } +#if defined(USE_TTF) + if (TTF_using()) resetFontSize(); +#endif + if (!uselangcp && !incall) { + int oldmsgcp = msgcodepage; + msgcodepage = dos.loaded_codepage; + SetKEYBCP(); + msgcodepage = oldmsgcp; + } +} + void ApplySetting(std::string pvar, std::string inputline, bool quiet) { if (!strcasecmp(pvar.c_str(), "dosbox")||!strcasecmp(pvar.c_str(), "dos")||!strcasecmp(pvar.c_str(), "dosv")||!strcasecmp(pvar.c_str(), "cpu")||!strcasecmp(pvar.c_str(), "sdl")||!strcasecmp(pvar.c_str(), "ttf")||!strcasecmp(pvar.c_str(), "render")||!strcasecmp(pvar.c_str(), "serial")||!strcasecmp(pvar.c_str(), "parallel")||!strcasecmp(pvar.c_str(), "printer")) { Section_prop *section = static_cast(control->GetSection(pvar.c_str())); @@ -662,20 +683,8 @@ void ApplySetting(std::string pvar, std::string inputline, bool quiet) { dosbox_title=section->Get_string("title"); trim(dosbox_title); } - if (!strcasecmp(inputline.substr(0, 9).c_str(), "language=")) { - if (control->opt_lang != "") control->opt_lang = section->Get_string("language"); - MSG_Init(); -#if DOSBOXMENU_TYPE == DOSBOXMENU_HMENU - mainMenu.unbuild(); - mainMenu.rebuild(); -#endif - if (!GFX_GetPreventFullscreen()) { - if (menu.toggle) DOSBox_SetMenu(); else DOSBox_NoMenu(); - } -#if defined(USE_TTF) - if (TTF_using()) resetFontSize(); -#endif - } + if (!strcasecmp(inputline.substr(0, 9).c_str(), "language=")) + Load_Language(section->Get_string("language")); if (!strcasecmp(inputline.substr(0, 16).c_str(), "mapper send key=")) { std::string mapsendkey = section->Get_string("mapper send key"); if (mapsendkey=="winlogo") sendkeymap=1; diff --git a/src/shell/shell.cpp b/src/shell/shell.cpp index e02bd4e2e..89faeffde 100644 --- a/src/shell/shell.cpp +++ b/src/shell/shell.cpp @@ -105,7 +105,7 @@ typedef std::list::iterator auto_it; void VFILE_Remove(const char *name,const char *dir=""); void runRescan(const char *str), DOSBox_SetSysMenu(void); -void toSetCodePage(DOS_Shell *shell, int newCP, int opt); +int toSetCodePage(DOS_Shell *shell, int newCP, int opt); #if defined(WIN32) void MountAllDrives(bool quiet) { @@ -834,7 +834,11 @@ void DOS_Shell::Prepare(void) { if (!IS_PC98_ARCH&&!IS_JEGA_ARCH) { #if defined(USE_TTF) if (ttf.inUse) { - if (newCP) toSetCodePage(this, newCP, control->opt_fastlaunch?1:0); + if (newCP) { + int missing = toSetCodePage(this, newCP, control->opt_fastlaunch?1:0); + WriteOut(MSG_Get("SHELL_CMD_CHCP_ACTIVE"), dos.loaded_codepage); + if (missing > 0) WriteOut(MSG_Get("SHELL_CMD_CHCP_MISSING"), missing); + } else if (r!=NULL) WriteOut(MSG_Get("SHELL_CMD_CHCP_INVALID"), trim(r+1)); } else #endif @@ -1679,7 +1683,7 @@ void SHELL_Init() { MSG_Add("SHELL_CMD_ASSOC_HELP", "Displays or changes file extension associations.\n"); MSG_Add("SHELL_CMD_ASSOC_HELP_LONG", "ASSOC [.ext[=command] ... ]\n\nType ASSOC without parameters to display the current file associations.\nFile extensions must start with a dot (.); wildcards (* and ?) are allowed.\n"); MSG_Add("SHELL_CMD_CHCP_HELP", "Displays or changes the current DOS code page.\n"); - MSG_Add("SHELL_CMD_CHCP_HELP_LONG", "CHCP [nnn [file]]\n\n nnn Specifies a code page number.\n file Specifies a code page file.\n\nSupported code pages for changing in the TrueType font output:\n\n437, 737, 775, 808, 850, 852, 853, 855-866, 869, 872, 874, 3021\n\nWindows code pages: 1250,1251,1252,1253,1254,1255,1256,1257,1258\n\nAlso double-byte code pages including 932, 936, 949, and 950/951.\n\nCustomized code pages are supported by providing code page files.\n"); + MSG_Add("SHELL_CMD_CHCP_HELP_LONG", "CHCP [nnn [file]]\nCHCP nnn[:[language]]\n\n nnn Specifies a code page number.\n file Specifies a code page file.\n language Specifies a corresponding language.\n\nSupported code pages for changing in the TrueType font output:\n\n437,737,775,808,850,852,853,855-866,869,872,874,1250-1258,3021\n\nAlso double-byte code pages including 932, 936, 949, and 950/951.\n\nCustomized code pages are supported by providing code page files.\n"); MSG_Add("SHELL_CMD_CHCP_ACTIVE", "Active code page: %d\n"); MSG_Add("SHELL_CMD_CHCP_MISSING", "ASCII characters not defined in TTF font: %d\n"); MSG_Add("SHELL_CMD_CHCP_INVALID", "Invalid code page number - %s\n"); diff --git a/src/shell/shell_cmds.cpp b/src/shell/shell_cmds.cpp index b7392511c..c63de8503 100644 --- a/src/shell/shell_cmds.cpp +++ b/src/shell/shell_cmds.cpp @@ -124,8 +124,8 @@ const char *GetCmdName(int i) { return i>n?NULL:cmd_list[i].name; } -extern int enablelfn, lfn_filefind_handle, file_access_tries; -extern bool date_host_forced, usecon, outcon, rsize, autoboxdraw, dbcs_sbcs, sync_time, manualtime, inshell, noassoc, dotype; +extern int enablelfn, lfn_filefind_handle, file_access_tries, lastmsgcp; +extern bool date_host_forced, usecon, outcon, rsize, autoboxdraw, dbcs_sbcs, sync_time, manualtime, inshell, noassoc, dotype, loadlang; extern unsigned long freec; extern uint8_t DOS_GetAnsiAttr(void); extern uint16_t countryNo, altcp_to_unicode[256]; @@ -134,8 +134,11 @@ bool Network_IsNetworkResource(const char * filename), DOS_SetAnsiAttr(uint8_t a void DOS_SetCountry(uint16_t countryNo), DOSV_FillScreen(void); extern bool isDBCSCP(), isKanji1(uint8_t chr), shiftjis_lead_byte(int c), TTF_using(void); extern bool CheckBoxDrawing(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4), GFX_GetPreventFullscreen(void); -void MAPPER_AutoType(std::vector &sequence, const uint32_t wait_ms, const uint32_t pace_ms, bool choice); +extern bool systemmessagebox(char const * aTitle, char const * aMessage, char const * aDialogType, char const * aIconType, int aDefaultButton); +extern void Load_Language(std::string name), SwitchLanguage(int oldcp, int newcp, bool confirm); +extern void MAPPER_AutoType(std::vector &sequence, const uint32_t wait_ms, const uint32_t pace_ms, bool choice); std::string GetDOSBoxXPath(bool withexe=false); +FILE *testLoadLangFile(const char *fname); /* support functions */ static char empty_char = 0; @@ -4406,11 +4409,12 @@ void DOS_Shell::CMD_COUNTRY(char * args) { extern bool jfont_init, isDBCSCP(); void runRescan(const char *str), MSG_Init(), JFONT_Init(), InitFontHandle(), ShutFontHandle(), initcodepagefont(), DOSBox_SetSysMenu(); -void toSetCodePage(DOS_Shell *shell, int newCP, int opt) { +int toSetCodePage(DOS_Shell *shell, int newCP, int opt) { if (isSupportedCP(newCP)) { dos.loaded_codepage = newCP; + int missing = 0; #if defined(USE_TTF) - int missing = TTF_using() ? setTTFCodePage() : 0; + missing = TTF_using() ? setTTFCodePage() : 0; #endif if (!TTF_using()) initcodepagefont(); if (opt==-1) { @@ -4424,12 +4428,6 @@ void toSetCodePage(DOS_Shell *shell, int newCP, int opt) { #endif DOSBox_SetSysMenu(); } - if (opt<1 && shell) { - shell->WriteOut(MSG_Get("SHELL_CMD_CHCP_ACTIVE"), dos.loaded_codepage); -#if defined(USE_TTF) - if (missing > 0) shell->WriteOut(MSG_Get("SHELL_CMD_CHCP_MISSING"), missing); -#endif - } if (isDBCSCP()) { ShutFontHandle(); InitFontHandle(); @@ -4438,7 +4436,7 @@ void toSetCodePage(DOS_Shell *shell, int newCP, int opt) { SetupDBCSTable(); runRescan("-A -Q"); #if defined(USE_TTF) - if (opt==-1&&(newCP==932||newCP==936||newCP==949||newCP==950||newCP==951)) { + if (opt==-1&&TTF_using()&&(newCP==932||newCP==936||newCP==949||newCP==950||newCP==951)) { Section_prop * ttf_section = static_cast(control->GetSection("ttf")); const char *font = ttf_section->Get_string("font"); if (!font || !*font) { @@ -4449,8 +4447,11 @@ void toSetCodePage(DOS_Shell *shell, int newCP, int opt) { } } #endif - } else if (opt<1 && shell) + return missing; + } else if (opt<1 && shell) { shell->WriteOut(MSG_Get("SHELL_CMD_CHCP_INVALID"), std::to_string(newCP).c_str()); + return -1; + } } void DOS_Shell::CMD_CHCP(char * args) { @@ -4471,14 +4472,36 @@ void DOS_Shell::CMD_CHCP(char * args) { } int newCP; char buff[256], *r; - int n = sscanf(args, "%d%s", &newCP, buff); + int missing = 0, n = sscanf(args, "%d%s", &newCP, buff); if (!TTF_using() && n && newCP != 932 && newCP != 936 && newCP != 949 && newCP != 950 && newCP != 951) { WriteOut("Changing to this code page is only supported for the TrueType font output.\n"); return; } - if (n == 1) toSetCodePage(this, newCP, -1); - else if (n == 2 && strlen(buff)) { + auto iter = langcp_map.find(newCP); + if (n == 1) { + int cp = dos.loaded_codepage; + missing = toSetCodePage(this, newCP, -1); + if (missing > -1) SwitchLanguage(cp, newCP, true); + WriteOut(MSG_Get("SHELL_CMD_CHCP_ACTIVE"), dos.loaded_codepage); +#if defined(USE_TTF) + if (missing > 0) WriteOut(MSG_Get("SHELL_CMD_CHCP_MISSING"), missing); +#endif + } else if (n == 2 && strlen(buff)) { + if (*buff == ':' && strchr(StripArg(args), ':')) { + std::string name = buff+1; + if (name.empty() && iter != langcp_map.end()) name = iter->second; + missing = toSetCodePage(this, newCP, -1); + if (missing > -1 && name.size() && dos.loaded_codepage == newCP) { + SetVal("dosbox", "language", name); + Load_Language(name); + } + WriteOut(MSG_Get("SHELL_CMD_CHCP_ACTIVE"), dos.loaded_codepage); +#if defined(USE_TTF) + if (missing > 0) WriteOut(MSG_Get("SHELL_CMD_CHCP_MISSING"), missing); +#endif + return; + } altcp = 0; for (int i=0; i<256; i++) altcp_to_unicode[i] = 0; std::string cpfile = buff; @@ -4505,7 +4528,11 @@ void DOS_Shell::CMD_CHCP(char * args) { int map = (int)strtol(r+2, NULL, 16); altcp_to_unicode[ind] = map; } - toSetCodePage(this, newCP, -1); + missing = toSetCodePage(this, newCP, -1); + WriteOut(MSG_Get("SHELL_CMD_CHCP_ACTIVE"), dos.loaded_codepage); +#if defined(USE_TTF) + if (missing > 0) WriteOut(MSG_Get("SHELL_CMD_CHCP_MISSING"), missing); +#endif } else WriteOut(MSG_Get("SHELL_CMD_CHCP_INVALID"), StripArg(args)); if (file) fclose(file);