diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 77a44e032..593ad4763 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -246,6 +246,16 @@ Notepad3 follows a **portable-app** design for its configuration file (`Notepad3 - **MiniPath** follows the same portable INI and admin-redirect pattern (`minipath\src\Config.cpp`). Redirect targets are auto-created via `CreateIniFileEx()`. - **New parameters**: When adding new `Settings2` (or other INI) parameters, always document them as commented entries in `Build\Notepad3.ini` +### Settings Save/Load Macros (`src\Config\Config.cpp`) + +**`Encoding_MapIniSetting` direction** — CPI constants (`CPI_UTF8=6`, `CPI_OEM=1`, etc.) do NOT equal their INI storage values (`3`, `5`, etc.). The mapping is asymmetric: +- `Encoding_MapIniSetting(true, val)` = INI integer → CPI constant (**loading**) +- `Encoding_MapIniSetting(false, val)` = CPI constant → INI integer (**saving**) + +Passing a CPI value with `bLoad=true` produces wrong results. Reference: `MRU_Save()` correctly uses `false` for saving. + +**Conditional defaults and `SAVE_VALUE_IF_NOT_EQ_DEFAULT`** — Some settings have defaults that depend on `DefaultEncoding` (e.g., `SkipANSICodePageDetection`, `LoadASCIIasUTF8`). If the encoding can change at runtime (via the Encoding dialog), the dependent `Defaults.*` fields must be recalculated in `_SaveSettings()` before the comparison macros fire — otherwise stale defaults cause incorrect save/delete decisions. See the `bCurrentEncUTF8` block in `_SaveSettings()`. + ### Creating Directories Use `Path_CreateDirectoryEx(hpth)` (PathLib wrapper around `SHCreateDirectoryExW`) to recursively create directory trees. Check result: `SUCCEEDED(hr) || (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS))`. See `CreateIniFile()` in `src\Config\Config.cpp` for the reference pattern. diff --git a/CLAUDE.md b/CLAUDE.md index 8acf004bc..a294691e4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -142,6 +142,16 @@ Resource-based MUI system with 27+ locales. Each locale has a `np3_LANG_COUNTRY\ - **MiniPath** follows the same portable INI and admin-redirect pattern (`minipath\src\Config.cpp`). Redirect targets are auto-created via `CreateIniFileEx()`. - **New parameters**: When adding new `Settings2` (or other INI) parameters, always document them as commented entries in `Build\Notepad3.ini` +### Settings Save/Load Macros (`src\Config\Config.cpp`) + +**`Encoding_MapIniSetting` direction** — CPI constants (`CPI_UTF8=6`, `CPI_OEM=1`, etc.) do NOT equal their INI storage values (`3`, `5`, etc.). The mapping is asymmetric: +- `Encoding_MapIniSetting(true, val)` = INI integer → CPI constant (**loading**) +- `Encoding_MapIniSetting(false, val)` = CPI constant → INI integer (**saving**) + +Passing a CPI value with `bLoad=true` produces wrong results. Reference: `MRU_Save()` correctly uses `false` for saving. + +**Conditional defaults and `SAVE_VALUE_IF_NOT_EQ_DEFAULT`** — Some settings have defaults that depend on `DefaultEncoding` (e.g., `SkipANSICodePageDetection`, `LoadASCIIasUTF8`). If the encoding can change at runtime (via the Encoding dialog), the dependent `Defaults.*` fields must be recalculated in `_SaveSettings()` before the comparison macros fire — otherwise stale defaults cause incorrect save/delete decisions. See the `bCurrentEncUTF8` block in `_SaveSettings()`. + ### Creating Directories Use `Path_CreateDirectoryEx(hpth)` (PathLib wrapper around `SHCreateDirectoryExW`) to recursively create directory trees. Check result: `SUCCEEDED(hr) || (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS))`. See `CreateIniFile()` in `src\Config\Config.cpp` for the reference pattern. diff --git a/src/Config/Config.cpp b/src/Config/Config.cpp index 8c3767408..d6f3e9b82 100644 --- a/src/Config/Config.cpp +++ b/src/Config/Config.cpp @@ -2008,7 +2008,7 @@ void LoadSettings() // encoding: internal<->external mapping #define SAVE_ENC_IF_NOT_EQ_DEFAULT(TYPE, VARNAME) \ if (Settings.VARNAME != Defaults.VARNAME) { \ - int const encValMapped = Encoding_MapIniSetting(true, (int)Settings.VARNAME); \ + int const encValMapped = Encoding_MapIniSetting(false, (int)Settings.VARNAME); \ IniSectionSetInt(IniSecSettings, _W(_STRG(VARNAME)), encValMapped); \ } \ else { \ @@ -2169,6 +2169,11 @@ static bool _SaveSettings(bool bForceSaveSettings) SAVE_VALUE_IF_NOT_EQ_DEFAULT(Bool, ViewWhiteSpace); SAVE_VALUE_IF_NOT_EQ_DEFAULT(Bool, ViewEOLs); + // recalculate encoding-dependent defaults before save comparison + bool const bCurrentEncUTF8 = (Settings.DefaultEncoding == CPI_UTF8 || Settings.DefaultEncoding == CPI_UTF8SIGN); + Defaults.LoadASCIIasUTF8 = bCurrentEncUTF8; + Defaults.SkipANSICodePageDetection = !bCurrentEncUTF8; + SAVE_ENC_IF_NOT_EQ_DEFAULT(Int, DefaultEncoding); SAVE_VALUE_IF_NOT_EQ_DEFAULT(Bool, UseDefaultForFileEncoding); diff --git a/src/Dialogs.c b/src/Dialogs.c index d9cd58b9a..aec986d87 100644 --- a/src/Dialogs.c +++ b/src/Dialogs.c @@ -3589,22 +3589,6 @@ CASE_WM_CTLCOLOR_SET: } } - // auto-toggle detection settings when encoding selection changes - if (LOWORD(wParam) == IDC_ENCODINGLIST) { - if (s_iEnc == CPI_ANSI_DEFAULT) { - s_bLoadASCIIasUTF8 = false; - CheckDlgButton(hwnd, IDC_ASCIIASUTF8, SetBtn(false)); - CheckDlgButton(hwnd, IDC_NOANSICPDETECTION, SetBtn(false)); - DialogEnableControl(hwnd, IDC_ANSI_CONFIDENCE_LEVEL, false); - DialogEnableControl(hwnd, IDC_ANSI_CONFIDENCE_SPIN, false); - } else if (s_iEnc == CPI_UTF8) { - s_bLoadASCIIasUTF8 = true; - CheckDlgButton(hwnd, IDC_ASCIIASUTF8, SetBtn(true)); - CheckDlgButton(hwnd, IDC_NOANSICPDETECTION, SetBtn(true)); - DialogEnableControl(hwnd, IDC_ANSI_CONFIDENCE_LEVEL, true); - DialogEnableControl(hwnd, IDC_ANSI_CONFIDENCE_SPIN, true); - } - } } break; diff --git a/src/MuiLanguage.c b/src/MuiLanguage.c index db7cc940c..4feb3f830 100644 --- a/src/MuiLanguage.c +++ b/src/MuiLanguage.c @@ -87,37 +87,6 @@ unsigned grepWinLang_CountOf() { return COUNTOF(grepWinLangResName); }; -#if 0 -grepWinLng_t grepWinLangResName[] = { - { L"en-US", L"English (United States) [en-US].lang" }, - { L"af-ZA", L"Afrikaans (Suid-Afrika) [af-ZA].lang" }, - { L"be-BY", L"Беларуская (Беларусь) [be-BY].lang" }, - { L"de-DE", L"Deutsch (Deutschland) [de-DE].lang" }, - { L"el-GR", L"Ελληνικά (Ελλάδα) [el-GR].lang" }, - { L"en-GB", L"English (United Kingdom) [en-GB].lang" }, - { L"es-ES", L"Español (España) [es-ES].lang" }, - { L"fi-FI", L"suomi (Suomi) [fi-FI].lang" }, - { L"fr-FR", L"Français (France) [fr-FR].lang" }, - { L"hi-IN", L"हिन्दी (भारत) [hi-IN].lang" }, - { L"hu-HU", L"Magyar (Magyarország) [hu-HU].lang" }, - { L"id-ID", L"Bahasa Indonesia (Indonesia) [id-ID].lang" }, - { L"it-IT", L"Italiano (Italia) [it-IT].lang" }, - { L"ja-JP", L"日本語 (日本) [ja-JP].lang" }, - { L"ko-KR", L"한국어 (대한민국) [ko-KR].lang" }, - { L"nl-NL", L"Nederlands (Nederland) [nl-NL].lang" }, - { L"pl-PL", L"Polski (Polska) [pl-PL].lang" }, - { L"pt-BR", L"Português Brasileiro (Brasil) [pt-BR].lang" }, - { L"pt-PT", L"Português (Portugal) [pt-PT].lang" }, - { L"ru-RU", L"Русский (Pоссия) [ru-RU].lang" }, - { L"sk-SK", L"Slovenčina (Slovensko) [sk-SK].lang" }, - { L"sv-SE", L"Svenska (Sverige) [sv-SE].lang" }, - { L"tr-TR", L"Türkçe (Türkiye) [tr-TR].lang" }, - { L"vi-VN", L"Tiếng Việt (Việt Nam) [vi-VN].lang" }, - { L"zh-CN", L"简体中文 (中国大陆) [zh-CN].lang" }, - { L"zh-TW", L"正體中文 (中國台灣) [zh-TW].lang" } -}; -#endif - //============================================================================= // // _LngStrToMultiLngStr