From b94777ed9e215f39c01263e7558a891c80de721c Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Tue, 5 Nov 2019 10:42:19 +0100 Subject: [PATCH] + fix: some more utf-8 corrections + rev: keep UTF-8-SIG for .INI files --- Build/Notepad3.ini | 2 +- Build/Notepad3_redirector.ini | Bin 120 -> 60 bytes Build/Themes/Dark.ini | 2 +- Build/Themes/Obsidian.ini | 2 +- Build/minipath.ini | 2 +- minipath/src/Config.cpp | 15 +- minipath/src/SimpleIni.h | 181 +++++++++++++----- .../App/Notepad3/x64/minipath.ini | Bin 138 -> 69 bytes .../App/Notepad3/x64/np3/Notepad3.ini | Bin 138 -> 69 bytes .../App/Notepad3/x86/minipath.ini | Bin 138 -> 69 bytes .../App/Notepad3/x86/np3/Notepad3.ini | Bin 138 -> 69 bytes src/Config/Config.cpp | 44 ++++- src/Config/Config.h | 8 +- src/Config/SimpleIni.h | 93 ++++++++- src/Helpers.c | 67 +++++++ src/Helpers.h | 11 ++ test/config/Notepad3_distrib.ini | Bin 1258 -> 602 bytes 17 files changed, 360 insertions(+), 67 deletions(-) diff --git a/Build/Notepad3.ini b/Build/Notepad3.ini index 8318fc855..4bbf08c5e 100644 --- a/Build/Notepad3.ini +++ b/Build/Notepad3.ini @@ -1,4 +1,4 @@ -[Notepad3] +[Notepad3] ;Notepad3.ini=%USERPROFILE%\Notepad3.ini ;Notepad3.ini=%APPDATA%\Rizonesoft\Notepad3\Notepad3.ini [Settings] diff --git a/Build/Notepad3_redirector.ini b/Build/Notepad3_redirector.ini index 3635bc8efee3434f18a1f83fc0eab1d99fde88e9..a6df6bfcb43c69f674e1b66830a303a673433709 100644 GIT binary patch literal 60 zcmaFAdw;ZFeo1OUVv2Dr7mTHsnU`s+>gONg8sO++?Cb9m>f`F-8KfG6tbhvuvZxf& literal 120 zcmezWFPg!RA)ldyA(f$kA(0`4!I&YIftP^`LsX9;lOYd?Z5dR7a{de<46Y0T42}#g cKpnn7z6(PrgAY*5g~5{{2&g6orwJg_0cVL6fB*mh diff --git a/Build/Themes/Dark.ini b/Build/Themes/Dark.ini index 79af25a61..d94ea8e34 100644 --- a/Build/Themes/Dark.ini +++ b/Build/Themes/Dark.ini @@ -1,4 +1,4 @@ -# Lexer Styles "Dark" taken from Axl Cash (https://www.axlcash.com/notepad2-dark-theme-schemes-style-or-whatever-you-call-it) +# Lexer Styles "Dark" taken from Axl Cash (https://www.axlcash.com/notepad2-dark-theme-schemes-style-or-whatever-you-call-it) [Custom Colors] 01=#252526 02=#1346CE diff --git a/Build/Themes/Obsidian.ini b/Build/Themes/Obsidian.ini index f1d0468a3..9e61cb419 100644 --- a/Build/Themes/Obsidian.ini +++ b/Build/Themes/Obsidian.ini @@ -1,4 +1,4 @@ -# Lexer Styles "Obsidian" taken from xCONFLiCTiONx (https://gist.github.com/xCONFLiCTiONx/43c035627909a92572334559b5685cf0) +# Lexer Styles "Obsidian" taken from xCONFLiCTiONx (https://gist.github.com/xCONFLiCTiONx/43c035627909a92572334559b5685cf0) [Custom Colors] 01=#000000 02=#0A246A diff --git a/Build/minipath.ini b/Build/minipath.ini index d639d8c2e..b04e2f226 100644 --- a/Build/minipath.ini +++ b/Build/minipath.ini @@ -1,4 +1,4 @@ -[minipath] +[minipath] ;minipath.ini=%USERPROFILE%\minipath.ini ;minipath.ini=%APPDATA%\Rizonesoft\Notepad3\minipath.ini [Settings] diff --git a/minipath/src/Config.cpp b/minipath/src/Config.cpp index 8da02c6e0..65fff834f 100644 --- a/minipath/src/Config.cpp +++ b/minipath/src/Config.cpp @@ -55,13 +55,14 @@ extern "C" int flagPosParam; // ============================================================================ static BOOL const s_bIsUTF8 = TRUE; +static BOOL const s_bWriteSIG = TRUE; // BOM static BOOL const s_bUseMultiKey = FALSE; static BOOL const s_bUseMultiLine = FALSE; static BOOL const s_bSetSpaces = FALSE; // ---------------------------------------------------------------------------- -#define SI_SUCCESS(RC) ((BOOL)((RC) >= SI_OK)) +#define SI_SUCCESS(RC) ((BOOL)((RC) >= SI_Error::SI_OK)) // ============================================================================ @@ -78,7 +79,7 @@ extern "C" BOOL LoadIniFile(LPCWSTR lpIniFilePath) extern "C" BOOL SaveIniFile(LPCWSTR lpIniFilePath) { s_INI.SetSpaces(s_bSetSpaces); - SI_Error const rc = s_INI.SaveFile(lpIniFilePath, true); + SI_Error const rc = s_INI.SaveFile(lpIniFilePath, s_bWriteSIG); if (SI_SUCCESS(rc)) { s_INI.Reset(); // done } @@ -241,11 +242,11 @@ extern "C" BOOL IniFileSetString(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCW if (SI_SUCCESS(rc)) { SI_Error const res = Ini.SetValue(lpSectionName, lpKeyName, lpString, nullptr, !s_bUseMultiKey); - rc = SI_SUCCESS(res) ? SI_OK : SI_FAIL; + rc = SI_SUCCESS(res) ? SI_Error::SI_OK : SI_Error::SI_FAIL; if (SI_SUCCESS(rc)) { Ini.SetSpaces(s_bSetSpaces); - rc = Ini.SaveFile(lpFilePath, true); + rc = Ini.SaveFile(lpFilePath, s_bWriteSIG); } } return SI_SUCCESS(rc); @@ -275,7 +276,7 @@ extern "C" BOOL IniFileSetInt(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWSTR if (SI_SUCCESS(rc)) { Ini.SetLongValue(lpSectionName, lpKeyName, (long)iValue, nullptr, false, !s_bUseMultiKey); Ini.SetSpaces(s_bSetSpaces); - rc = Ini.SaveFile(lpFilePath, true); + rc = Ini.SaveFile(lpFilePath, s_bWriteSIG); } return SI_SUCCESS(rc); } @@ -304,7 +305,7 @@ extern "C" BOOL IniFileSetBool(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWST if (SI_SUCCESS(rc)) { Ini.SetBoolValue(lpSectionName, lpKeyName, bValue, nullptr, !s_bUseMultiKey); Ini.SetSpaces(s_bSetSpaces); - rc = Ini.SaveFile(lpFilePath, true); + rc = Ini.SaveFile(lpFilePath, s_bWriteSIG); } return SI_SUCCESS(rc); } @@ -319,7 +320,7 @@ extern "C" BOOL IniFileDelete(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWSTR { Ini.Delete(lpSectionName, lpKeyName, bRemoveEmpty); Ini.SetSpaces(s_bSetSpaces); - rc = Ini.SaveFile(lpFilePath, true); + rc = Ini.SaveFile(lpFilePath, s_bWriteSIG); } return SI_SUCCESS(rc); } diff --git a/minipath/src/SimpleIni.h b/minipath/src/SimpleIni.h index dec1238f4..52255ff2f 100644 --- a/minipath/src/SimpleIni.h +++ b/minipath/src/SimpleIni.h @@ -260,7 +260,7 @@ # define SI_ASSERT(x) #endif -enum SI_Error { +enum class SI_Error : int { SI_OK = 0, //!< No error SI_UPDATED = 1, //!< An existing value was updated SI_INSERTED = 2, //!< A new value was inserted @@ -271,6 +271,7 @@ enum SI_Error { SI_FILE = -3 //!< File error (see errno for detail error) }; + #define SI_UTF8_SIGNATURE "\xEF\xBB\xBF" #define SI_UTF16LE_SIGNATURE "\xFF\xFE" #define SI_UTF16BE_SIGNATURE "\xFE\xFF" @@ -406,6 +407,7 @@ public: FILE * m_file; public: explicit FileWriter(FILE * a_file) : m_file(a_file) { } + ~FileWriter() { fflush(m_file); } void Write(const char * a_pBuf) override { fputs(a_pBuf, m_file); } @@ -664,7 +666,7 @@ public: */ SI_Error SaveFile( const char * a_pszFile, - bool a_bAddSignature = true + bool a_bAddSignature = false ) const; #ifdef SI_HAS_WIDE_FILE @@ -680,7 +682,7 @@ public: */ SI_Error SaveFile( const SI_WCHAR_T * a_pwszFile, - bool a_bAddSignature = true + bool a_bAddSignature = false ) const; #endif // _WIN32 @@ -721,7 +723,7 @@ public: being used by SimpleIni. To add a BOM to UTF-8 data, write it out manually at the very beginning - like is done in SaveFile when a_bUseBOM is true. + like is done in SaveFile when a_bAddSignature is true. @param a_oOutput Output writer to write the data to. @@ -920,6 +922,13 @@ public: bool * a_pHasMultiple = nullptr ) const; + long long GetLongLongValue( + const SI_CHAR* a_pSection, + const SI_CHAR* a_pKey, + long long a_nDefault = 0, + bool* a_pHasMultiple = nullptr + ) const; + /** Retrieve a numeric value for a specific key. If multiple keys are enabled (see SetMultiKey) then only the first value associated with that key will be returned, see GetAllValues for getting all values with multikey. @@ -1037,6 +1046,15 @@ public: bool a_bForceReplace = false ); + SI_Error SetLongLongValue( + const SI_CHAR* a_pSection, + const SI_CHAR* a_pKey, + long long a_nValue, + const SI_CHAR* a_pComment = NULL, + bool a_bUseHex = false, + bool a_bForceReplace = false + ); + /** Add or update a double value. This will always insert when multiple keys are enabled. @@ -1387,7 +1405,7 @@ CSimpleIniTempl::LoadFile( #else // !__STDC_WANT_SECURE_LIB__ fp = _wfopen(a_pwszFile, L"rb"); #endif // __STDC_WANT_SECURE_LIB__ - if (!fp) return SI_FILE; + if (!fp) return SI_Error::SI_FILE; SI_Error rc = LoadFile(fp); fclose(fp); return rc; @@ -1408,20 +1426,20 @@ CSimpleIniTempl::LoadFile( // load the raw file data int retval = fseek(a_fpFile, 0, SEEK_END); if (retval != 0) { - return SI_FILE; + return SI_Error::SI_FILE; } long lSize = ftell(a_fpFile); if (lSize < 0) { - return SI_FILE; + return SI_Error::SI_FILE; } if (lSize == 0) { - return SI_OK; + return SI_Error::SI_OK; } // allocate and ensure NULL terminated auto * pData = new(std::nothrow) char[lSize+1]; if (!pData) { - return SI_NOMEM; + return SI_Error::SI_NOMEM; } pData[lSize] = 0; @@ -1430,7 +1448,7 @@ CSimpleIniTempl::LoadFile( size_t uRead = fread(pData, sizeof(char), lSize, a_fpFile); if (uRead != (size_t) lSize) { delete[] pData; - return SI_FILE; + return SI_Error::SI_FILE; } // convert the raw data to unicode @@ -1447,7 +1465,7 @@ CSimpleIniTempl::LoadData( ) { if (!a_pData) { - return SI_OK; + return SI_Error::SI_OK; } char* pDataUTF16toUTF8 = nullptr; @@ -1472,14 +1490,14 @@ CSimpleIniTempl::LoadData( // convert to UTF-8 pDataUTF16toUTF8 = new(std::nothrow) char[a_uDataLen * 3 + 1]; if (!pDataUTF16toUTF8) { - return SI_NOMEM; + return SI_Error::SI_NOMEM; } auto const convCnt = (size_t)WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)a_pData + 1, (int)(a_uDataLen / sizeof(WCHAR) - 1), (LPSTR)pDataUTF16toUTF8, (int)(a_uDataLen * 3 + 1), nullptr, nullptr); if (convCnt == 0) { delete[] pDataUTF16toUTF8; - return SI_FAIL; + return SI_Error::SI_FAIL; } pDataUTF16toUTF8[convCnt] = '\0'; @@ -1492,7 +1510,7 @@ CSimpleIniTempl::LoadData( if (a_uDataLen == 0) { delete[] pDataUTF16toUTF8; - return SI_OK; + return SI_Error::SI_OK; } // determine the length of the converted data @@ -1500,7 +1518,7 @@ CSimpleIniTempl::LoadData( size_t uLen = converter.SizeFromStore(a_pData, a_uDataLen); if (uLen == (size_t)(-1)) { delete[] pDataUTF16toUTF8; - return SI_FAIL; + return SI_Error::SI_FAIL; } // allocate memory for the data, ensure that there is a NULL @@ -1508,7 +1526,7 @@ CSimpleIniTempl::LoadData( auto * pData = new(std::nothrow) SI_CHAR[uLen+1]; if (!pData) { delete[] pDataUTF16toUTF8; - return SI_NOMEM; + return SI_Error::SI_NOMEM; } memset(pData, 0, sizeof(SI_CHAR)*(uLen+1)); @@ -1516,7 +1534,7 @@ CSimpleIniTempl::LoadData( if (!converter.ConvertFromStore(a_pData, a_uDataLen, pData, uLen)) { delete[] pDataUTF16toUTF8; delete[] pData; - return SI_FAIL; + return SI_Error::SI_FAIL; } delete[] pDataUTF16toUTF8; // done @@ -1537,12 +1555,12 @@ CSimpleIniTempl::LoadData( // find a file comment if it exists, this is a comment that starts at the // beginning of the file and continues until the first blank line. SI_Error rc = FindFileComment(pWork, bCopyStrings); - if (rc < 0) return rc; + if (rc < SI_Error::SI_OK) return rc; // add every entry in the file to the data table while (FindEntry(pWork, pSection, pItem, pVal, pComment)) { rc = AddEntry(pSection, pItem, pVal, pComment, false, bCopyStrings); - if (rc < 0) return rc; + if (rc < SI_Error::SI_OK) return rc; } // store these strings if we didn't copy them @@ -1553,7 +1571,7 @@ CSimpleIniTempl::LoadData( m_pData = pData; m_uDataLen = uLen+1; } - return SI_OK; + return SI_Error::SI_OK; } #ifdef SI_SUPPORT_IOSTREAMS @@ -1583,22 +1601,22 @@ CSimpleIniTempl::FindFileComment( { // there can only be a single file comment if (m_pFileComment) { - return SI_OK; + return SI_Error::SI_OK; } // Load the file comment as multi-line text, this will modify all of // the newline characters to be single \n chars if (!LoadMultiLineText(a_pData, m_pFileComment, NULL, false)) { - return SI_OK; + return SI_Error::SI_OK; } // copy the string if necessary if (a_bCopyStrings) { SI_Error rc = CopyString(m_pFileComment); - if (rc < 0) return rc; + if (rc < SI_Error::SI_OK) return rc; } - return SI_OK; + return SI_Error::SI_OK; } template @@ -1936,12 +1954,12 @@ CSimpleIniTempl::CopyString( ++uLen; // NULL character auto * pCopy = new(std::nothrow) SI_CHAR[uLen]; if (!pCopy) { - return SI_NOMEM; + return SI_Error::SI_NOMEM; } memcpy(pCopy, a_pString, sizeof(SI_CHAR)*uLen); m_strings.push_back(pCopy); a_pString = pCopy; - return SI_OK; + return SI_Error::SI_OK; } template @@ -1964,7 +1982,7 @@ CSimpleIniTempl::AddEntry( // because we will need it when we add the entry. if (a_bCopyStrings && a_pComment) { rc = CopyString(a_pComment); - if (rc < 0) return rc; + if (rc < SI_Error::SI_OK) return rc; } // create the section entry if necessary @@ -1974,7 +1992,7 @@ CSimpleIniTempl::AddEntry( // string needs to last beyond the end of this function if (a_bCopyStrings) { rc = CopyString(a_pSection); - if (rc < 0) return rc; + if (rc < SI_Error::SI_OK) return rc; } // only set the comment if this is a section only entry @@ -1991,7 +2009,7 @@ CSimpleIniTempl::AddEntry( } if (!a_pKey || !a_pValue) { // section only entries are specified with pItem and pVal as NULL - return bInserted ? SI_INSERTED : SI_UPDATED; + return bInserted ? SI_Error::SI_INSERTED : SI_Error::SI_UPDATED; } // check for existence of the key @@ -2027,12 +2045,12 @@ CSimpleIniTempl::AddEntry( // string needs to last beyond the end of this function // because we will be inserting the key next rc = CopyString(a_pKey); - if (rc < 0) return rc; + if (rc < SI_Error::SI_OK) return rc; } // we always need a copy of the value rc = CopyString(a_pValue); - if (rc < 0) return rc; + if (rc < SI_Error::SI_OK) return rc; } // create the key entry @@ -2046,7 +2064,7 @@ CSimpleIniTempl::AddEntry( bInserted = true; } iKey->second = a_pValue; - return bInserted ? SI_INSERTED : SI_UPDATED; + return bInserted ? SI_Error::SI_INSERTED : SI_Error::SI_UPDATED; } template @@ -2137,7 +2155,7 @@ CSimpleIniTempl::SetLongValue( ) { // use SetValue to create sections - if (!a_pSection || !a_pKey) return SI_FAIL; + if (!a_pSection || !a_pKey) return SI_Error::SI_FAIL; // convert to an ASCII string char szInput[64]; @@ -2157,6 +2175,77 @@ CSimpleIniTempl::SetLongValue( return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true); } +template +long long +CSimpleIniTempl::GetLongLongValue( + const SI_CHAR* a_pSection, + const SI_CHAR* a_pKey, + long long a_nDefault, + bool* a_pHasMultiple +) const +{ + // return the default if we don't have a value + const SI_CHAR* pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple); + if (!pszValue || !*pszValue) return a_nDefault; + + // convert to UTF-8/MBCS which for a numeric value will be the same as ASCII + char szValue[128] = { 0 }; + SI_CONVERTER c(m_bStoreIsUtf8); + if (!c.ConvertToStore(pszValue, szValue, sizeof(szValue))) { + return a_nDefault; + } + + // handle the value as hex if prefaced with "0x" + long long nValue = a_nDefault; + char* pszSuffix = szValue; + if (szValue[0] == '0' && (szValue[1] == 'x' || szValue[1] == 'X')) { + if (!szValue[2]) return a_nDefault; + nValue = strtoll(&szValue[2], &pszSuffix, 16); + } + else { + nValue = strtoll(szValue, &pszSuffix, 10); + } + + // any invalid strings will return the default value + if (*pszSuffix) { + return a_nDefault; + } + + return nValue; +} + +template +SI_Error +CSimpleIniTempl::SetLongLongValue( + const SI_CHAR* a_pSection, + const SI_CHAR* a_pKey, + long long a_nValue, + const SI_CHAR* a_pComment, + bool a_bUseHex, + bool a_bForceReplace +) +{ + // use SetValue to create sections + if (!a_pSection || !a_pKey) return SI_Error::SI_FAIL; + + // convert to an ASCII string + char szInput[128]; +#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE + sprintf_s(szInput, a_bUseHex ? "0x%llx" : "%lld", a_nValue); +#else // !__STDC_WANT_SECURE_LIB__ + sprintf(szInput, a_bUseHex ? "0x%llx" : "%lld", a_nValue); +#endif // __STDC_WANT_SECURE_LIB__ + + // convert to output text + SI_CHAR szOutput[64]; + SI_CONVERTER c(m_bStoreIsUtf8); + c.ConvertFromStore(szInput, strlen(szInput) + 1, + szOutput, sizeof(szOutput) / sizeof(SI_CHAR)); + + // actually add it + return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true); +} + template double CSimpleIniTempl::GetDoubleValue( @@ -2199,7 +2288,7 @@ CSimpleIniTempl::SetDoubleValue( ) { // use SetValue to create sections - if (!a_pSection || !a_pKey) return SI_FAIL; + if (!a_pSection || !a_pKey) return SI_Error::SI_FAIL; // convert to an ASCII string char szInput[64]; @@ -2267,7 +2356,7 @@ CSimpleIniTempl::SetBoolValue( ) { // use SetValue to create sections - if (!a_pSection || !a_pKey) return SI_FAIL; + if (!a_pSection || !a_pKey) return SI_Error::SI_FAIL; // convert to an ASCII string const char * pszInput = a_bValue ? "true" : "false"; @@ -2441,11 +2530,11 @@ CSimpleIniTempl::SaveFile( #ifdef _WIN32 FILE * fp = nullptr; #if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE - _wfopen_s(&fp, a_pwszFile, L"wb"); + _wfopen_s(&fp, a_pwszFile, L"wbc"); #else // !__STDC_WANT_SECURE_LIB__ - fp = _wfopen(a_pwszFile, L"wb"); + fp = _wfopen(a_pwszFile, L"wbc"); #endif // __STDC_WANT_SECURE_LIB__ - if (!fp) return SI_FILE; + if (!fp) return SI_Error::SI_FILE; SI_Error rc = SaveFile(fp, a_bAddSignature); fclose(fp); return rc; @@ -2497,7 +2586,7 @@ CSimpleIniTempl::Save( bool bNeedNewLine = false; if (m_pFileComment) { if (!OutputMultiLineText(a_oOutput, convert, m_pFileComment)) { - return SI_FAIL; + return SI_Error::SI_FAIL; } bNeedNewLine = true; } @@ -2513,7 +2602,7 @@ CSimpleIniTempl::Save( bNeedNewLine = false; } if (!OutputMultiLineText(a_oOutput, convert, iSection->pComment)) { - return SI_FAIL; + return SI_Error::SI_FAIL; } } @@ -2526,7 +2615,7 @@ CSimpleIniTempl::Save( // write the section (unless there is no section name) if (*iSection->pItem) { if (!convert.ConvertToStore(iSection->pItem)) { - return SI_FAIL; + return SI_Error::SI_FAIL; } //a_oOutput.Write(SI_NEWLINE_A); // before new section a_oOutput.Write("["); @@ -2563,19 +2652,19 @@ CSimpleIniTempl::Save( bNeedNewLine = false; } if (!OutputMultiLineText(a_oOutput, convert, iValue->pComment)) { - return SI_FAIL; + return SI_Error::SI_FAIL; } } // write the key if (!convert.ConvertToStore(iKey->pItem)) { - return SI_FAIL; + return SI_Error::SI_FAIL; } a_oOutput.Write(convert.Data()); // write the value if (!convert.ConvertToStore(iValue->pItem)) { - return SI_FAIL; + return SI_Error::SI_FAIL; } a_oOutput.Write(m_bSpaces ? " = " : "="); if (m_bAllowMultiLine && IsMultiLineData(iValue->pItem)) { @@ -2584,7 +2673,7 @@ CSimpleIniTempl::Save( a_oOutput.Write("<<pItem)) { - return SI_FAIL; + return SI_Error::SI_FAIL; } a_oOutput.Write("END_OF_TEXT"); } @@ -2598,7 +2687,7 @@ CSimpleIniTempl::Save( //§§§bNeedNewLine = true; } - return SI_OK; + return SI_Error::SI_OK; } template diff --git a/np3portableapp/Notepad3Portable/App/Notepad3/x64/minipath.ini b/np3portableapp/Notepad3Portable/App/Notepad3/x64/minipath.ini index 2fd0c30db377e1392d3aa3e2a3a8abc0831fbe8b..47b1a33a7a00f50617b77ecd9cd100d66fc5c7b7 100644 GIT binary patch literal 69 zcmaFAdw;ZVW?p7MVo63U7mTF`6tPwH^AB+iaC9+_5AY8Padh%=jSqGW3GwuE4_1xI N1*#|j>H(?b0sx8>7)byC literal 138 zcmezWFPg!ZA(J5whyxfB8A=#37-AWC8MrV+^`NS38B`hk82lMR7+irm92r~~j2YsA sEPsX|pqL|r6N3*>CY~V}NQMBRCs4IJkf+KJ!;lL#qX23X%uJAd02bL7_W%F@ diff --git a/np3portableapp/Notepad3Portable/App/Notepad3/x64/np3/Notepad3.ini b/np3portableapp/Notepad3Portable/App/Notepad3/x64/np3/Notepad3.ini index b62b57fec44c256e4f969626514a78d4998c1528..68e5f5766beea9bf9d378650679d46d563b75ac3 100644 GIT binary patch literal 69 zcmaFAdw;ZFeo1OUVv2Dr7mTHsnU`s+>gONg8sO++93S8x6yoUQ;~F3A8WQ5^=N_yY IgRGJZ0DP|(wEzGB literal 138 zcmezWFPg!RA)ldyA(f$kA(0`4!I&YIftP^`LsX9;lOYd?Z5dR7a{de<46Y0T42}#g pKppWwmOn!fP|T6RiNOab6VDI~BtwAE6R6r9$WvvA!D%MQJ^=cl7h?bb diff --git a/np3portableapp/Notepad3Portable/App/Notepad3/x86/minipath.ini b/np3portableapp/Notepad3Portable/App/Notepad3/x86/minipath.ini index 2fd0c30db377e1392d3aa3e2a3a8abc0831fbe8b..47b1a33a7a00f50617b77ecd9cd100d66fc5c7b7 100644 GIT binary patch literal 69 zcmaFAdw;ZVW?p7MVo63U7mTF`6tPwH^AB+iaC9+_5AY8Padh%=jSqGW3GwuE4_1xI N1*#|j>H(?b0sx8>7)byC literal 138 zcmezWFPg!ZA(J5whyxfB8A=#37-AWC8MrV+^`NS38B`hk82lMR7+irm92r~~j2YsA sEPsX|pqL|r6N3*>CY~V}NQMBRCs4IJkf+KJ!;lL#qX23X%uJAd02bL7_W%F@ diff --git a/np3portableapp/Notepad3Portable/App/Notepad3/x86/np3/Notepad3.ini b/np3portableapp/Notepad3Portable/App/Notepad3/x86/np3/Notepad3.ini index b62b57fec44c256e4f969626514a78d4998c1528..68e5f5766beea9bf9d378650679d46d563b75ac3 100644 GIT binary patch literal 69 zcmaFAdw;ZFeo1OUVv2Dr7mTHsnU`s+>gONg8sO++93S8x6yoUQ;~F3A8WQ5^=N_yY IgRGJZ0DP|(wEzGB literal 138 zcmezWFPg!RA)ldyA(f$kA(0`4!I&YIftP^`LsX9;lOYd?Z5dR7a{de<46Y0T42}#g pKppWwmOn!fP|T6RiNOab6VDI~BtwAE6R6r9$WvvA!D%MQJ^=cl7h?bb diff --git a/src/Config/Config.cpp b/src/Config/Config.cpp index 69fe64841..34b69ef1b 100644 --- a/src/Config/Config.cpp +++ b/src/Config/Config.cpp @@ -67,6 +67,7 @@ extern "C" THEMEFILES Theme_Files[]; // ============================================================================ static bool const s_bIsUTF8 = true; +static bool const s_bWriteSIG = true; // BOM static bool const s_bUseMultiKey = false; static bool const s_bUseMultiLine = false; static bool const s_bSetSpaces = false; @@ -100,7 +101,7 @@ extern "C" bool LoadIniFile(LPCWSTR lpIniFilePath) extern "C" bool SaveIniFile(LPCWSTR lpIniFilePath) { s_INI.SetSpaces(s_bSetSpaces); - SI_Error const rc = s_INI.SaveFile(lpIniFilePath, true); + SI_Error const rc = s_INI.SaveFile(lpIniFilePath, s_bWriteSIG); if (SI_SUCCESS(rc)) { s_INI.Reset(); // done } @@ -142,6 +143,26 @@ extern "C" int IniSectionGetInt(LPCWSTR lpSectionName, LPCWSTR lpKeyName, int iD // ============================================================================ +extern "C" long IniSectionGetLong(LPCWSTR lpSectionName, LPCWSTR lpKeyName, long lDefault) +{ + bool bHasMultiple = false; + auto const lValue = s_INI.GetLongValue(lpSectionName, lpKeyName, lDefault, &bHasMultiple); + //assert(!bHasMultiple); + return lValue; +} +// ============================================================================ + + +extern "C" long long IniSectionGetLongLong(LPCWSTR lpSectionName, LPCWSTR lpKeyName, long long llDefault) +{ + bool bHasMultiple = false; + auto const lValue = s_INI.GetLongLongValue(lpSectionName, lpKeyName, llDefault, &bHasMultiple); + //assert(!bHasMultiple); + return lValue; +} +// ============================================================================ + + extern "C" double IniSectionGetDouble(LPCWSTR lpSectionName, LPCWSTR lpKeyName, double dDefault) { bool bHasMultiple = false; @@ -175,6 +196,19 @@ extern "C" bool IniSectionSetInt(LPCWSTR lpSectionName, LPCWSTR lpKeyName, int i SI_Error const rc = s_INI.SetLongValue(lpSectionName, lpKeyName, (long)iValue, nullptr, false, !s_bUseMultiKey); return SI_SUCCESS(rc); } + +extern "C" bool IniSectionSetLong(LPCWSTR lpSectionName, LPCWSTR lpKeyName, long lValue) +{ + SI_Error const rc = s_INI.SetLongValue(lpSectionName, lpKeyName, lValue, nullptr, false, !s_bUseMultiKey); + return SI_SUCCESS(rc); +} + +extern "C" bool IniSectionSetLongLong(LPCWSTR lpSectionName, LPCWSTR lpKeyName, long long llValue) +{ + SI_Error const rc = s_INI.SetLongLongValue(lpSectionName, lpKeyName, llValue, nullptr, false, !s_bUseMultiKey); + return SI_SUCCESS(rc); +} + extern "C" bool IniSectionSetHex(LPCWSTR lpSectionName, LPCWSTR lpKeyName, int iValue) { SI_Error const rc = s_INI.SetLongValue(lpSectionName, lpKeyName, (long)iValue, nullptr, true, !s_bUseMultiKey); @@ -267,7 +301,7 @@ extern "C" bool IniFileSetString(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCW if (SI_SUCCESS(rc)) { Ini.SetSpaces(s_bSetSpaces); - rc = Ini.SaveFile(lpFilePath, true); + rc = Ini.SaveFile(lpFilePath, s_bWriteSIG); } Ini.Reset(); } @@ -298,7 +332,7 @@ extern "C" bool IniFileSetInt(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWSTR if (SI_SUCCESS(rc)) { Ini.SetLongValue(lpSectionName, lpKeyName, (long)iValue, nullptr, false, !s_bUseMultiKey); Ini.SetSpaces(s_bSetSpaces); - rc = Ini.SaveFile(lpFilePath, true); + rc = Ini.SaveFile(lpFilePath, s_bWriteSIG); } Ini.Reset(); return SI_SUCCESS(rc); @@ -328,7 +362,7 @@ extern "C" bool IniFileSetBool(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWST if (SI_SUCCESS(rc)) { Ini.SetBoolValue(lpSectionName, lpKeyName, bValue, nullptr, !s_bUseMultiKey); Ini.SetSpaces(s_bSetSpaces); - rc = Ini.SaveFile(lpFilePath, true); + rc = Ini.SaveFile(lpFilePath, s_bWriteSIG); } Ini.Reset(); return SI_SUCCESS(rc); @@ -344,7 +378,7 @@ extern "C" bool IniFileDelete(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWSTR { Ini.Delete(lpSectionName, lpKeyName, bRemoveEmpty); Ini.SetSpaces(s_bSetSpaces); - rc = Ini.SaveFile(lpFilePath, true); + rc = Ini.SaveFile(lpFilePath, s_bWriteSIG); } Ini.Reset(); return SI_SUCCESS(rc); diff --git a/src/Config/Config.h b/src/Config/Config.h index 104eee9da..f0ecefe3a 100644 --- a/src/Config/Config.h +++ b/src/Config/Config.h @@ -46,23 +46,27 @@ void ReleaseIniFile(); size_t IniSectionGetString(LPCWSTR lpSectionName, LPCWSTR lpKeyName, LPCWSTR lpDefault, LPWSTR lpReturnedString, size_t cchReturnedString); int IniSectionGetInt(LPCWSTR lpSectionName, LPCWSTR lpKeyName, int iDefault); +long IniSectionGetLong(LPCWSTR lpSectionName, LPCWSTR lpKeyName, long lDefault); +long long IniSectionGetLongLong(LPCWSTR lpSectionName, LPCWSTR lpKeyName, long long llDefault); double IniSectionGetDouble(LPCWSTR lpSectionName, LPCWSTR lpKeyName, double dDefault); bool IniSectionGetBool(LPCWSTR lpSectionName, LPCWSTR lpKeyName, bool bDefault); inline DocPos IniSectionGetPos(LPCWSTR lpSectionName, LPCWSTR lpKeyName, DocPos posDefault) { - return (DocPos)IniSectionGetInt(lpSectionName, lpKeyName, (MBWC_DocPos_Cast)posDefault); + return (DocPos)IniSectionGetLongLong(lpSectionName, lpKeyName, posDefault); } // ---------------------------------------------------------------------------- bool IniSectionSetString(LPCWSTR lpSectionName, LPCWSTR lpKeyName, LPCWSTR lpString); bool IniSectionSetInt(LPCWSTR lpSectionName, LPCWSTR lpKeyName, int iValue); +bool IniSectionSetLong(LPCWSTR lpSectionName, LPCWSTR lpKeyName, long lValue); +bool IniSectionSetLongLong(LPCWSTR lpSectionName, LPCWSTR lpKeyName, long long llValue); bool IniSectionSetHex(LPCWSTR lpSectionName, LPCWSTR lpKeyName, int iValue); bool IniSectionSetDouble(LPCWSTR lpSectionName, LPCWSTR lpKeyName, double dValue); bool IniSectionSetBool(LPCWSTR lpSectionName, LPCWSTR lpName, bool bValue); inline bool IniSectionSetPos(LPCWSTR lpSectionName, LPCWSTR lpKeyName, DocPos posValue) { - return IniSectionSetInt(lpSectionName, lpKeyName, (MBWC_DocPos_Cast)posValue); + return IniSectionSetLongLong(lpSectionName, lpKeyName, posValue); } // ---------------------------------------------------------------------------- diff --git a/src/Config/SimpleIni.h b/src/Config/SimpleIni.h index ee865d013..52255ff2f 100644 --- a/src/Config/SimpleIni.h +++ b/src/Config/SimpleIni.h @@ -666,7 +666,7 @@ public: */ SI_Error SaveFile( const char * a_pszFile, - bool a_bAddSignature = true + bool a_bAddSignature = false ) const; #ifdef SI_HAS_WIDE_FILE @@ -682,7 +682,7 @@ public: */ SI_Error SaveFile( const SI_WCHAR_T * a_pwszFile, - bool a_bAddSignature = true + bool a_bAddSignature = false ) const; #endif // _WIN32 @@ -723,7 +723,7 @@ public: being used by SimpleIni. To add a BOM to UTF-8 data, write it out manually at the very beginning - like is done in SaveFile when a_bUseBOM is true. + like is done in SaveFile when a_bAddSignature is true. @param a_oOutput Output writer to write the data to. @@ -922,6 +922,13 @@ public: bool * a_pHasMultiple = nullptr ) const; + long long GetLongLongValue( + const SI_CHAR* a_pSection, + const SI_CHAR* a_pKey, + long long a_nDefault = 0, + bool* a_pHasMultiple = nullptr + ) const; + /** Retrieve a numeric value for a specific key. If multiple keys are enabled (see SetMultiKey) then only the first value associated with that key will be returned, see GetAllValues for getting all values with multikey. @@ -1039,6 +1046,15 @@ public: bool a_bForceReplace = false ); + SI_Error SetLongLongValue( + const SI_CHAR* a_pSection, + const SI_CHAR* a_pKey, + long long a_nValue, + const SI_CHAR* a_pComment = NULL, + bool a_bUseHex = false, + bool a_bForceReplace = false + ); + /** Add or update a double value. This will always insert when multiple keys are enabled. @@ -2159,6 +2175,77 @@ CSimpleIniTempl::SetLongValue( return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true); } +template +long long +CSimpleIniTempl::GetLongLongValue( + const SI_CHAR* a_pSection, + const SI_CHAR* a_pKey, + long long a_nDefault, + bool* a_pHasMultiple +) const +{ + // return the default if we don't have a value + const SI_CHAR* pszValue = GetValue(a_pSection, a_pKey, NULL, a_pHasMultiple); + if (!pszValue || !*pszValue) return a_nDefault; + + // convert to UTF-8/MBCS which for a numeric value will be the same as ASCII + char szValue[128] = { 0 }; + SI_CONVERTER c(m_bStoreIsUtf8); + if (!c.ConvertToStore(pszValue, szValue, sizeof(szValue))) { + return a_nDefault; + } + + // handle the value as hex if prefaced with "0x" + long long nValue = a_nDefault; + char* pszSuffix = szValue; + if (szValue[0] == '0' && (szValue[1] == 'x' || szValue[1] == 'X')) { + if (!szValue[2]) return a_nDefault; + nValue = strtoll(&szValue[2], &pszSuffix, 16); + } + else { + nValue = strtoll(szValue, &pszSuffix, 10); + } + + // any invalid strings will return the default value + if (*pszSuffix) { + return a_nDefault; + } + + return nValue; +} + +template +SI_Error +CSimpleIniTempl::SetLongLongValue( + const SI_CHAR* a_pSection, + const SI_CHAR* a_pKey, + long long a_nValue, + const SI_CHAR* a_pComment, + bool a_bUseHex, + bool a_bForceReplace +) +{ + // use SetValue to create sections + if (!a_pSection || !a_pKey) return SI_Error::SI_FAIL; + + // convert to an ASCII string + char szInput[128]; +#if __STDC_WANT_SECURE_LIB__ && !_WIN32_WCE + sprintf_s(szInput, a_bUseHex ? "0x%llx" : "%lld", a_nValue); +#else // !__STDC_WANT_SECURE_LIB__ + sprintf(szInput, a_bUseHex ? "0x%llx" : "%lld", a_nValue); +#endif // __STDC_WANT_SECURE_LIB__ + + // convert to output text + SI_CHAR szOutput[64]; + SI_CONVERTER c(m_bStoreIsUtf8); + c.ConvertFromStore(szInput, strlen(szInput) + 1, + szOutput, sizeof(szOutput) / sizeof(SI_CHAR)); + + // actually add it + return AddEntry(a_pSection, a_pKey, szOutput, a_pComment, a_bForceReplace, true); +} + template double CSimpleIniTempl::GetDoubleValue( diff --git a/src/Helpers.c b/src/Helpers.c index 526bf825a..a844a83dd 100644 --- a/src/Helpers.c +++ b/src/Helpers.c @@ -1654,6 +1654,73 @@ void TransformMetaChars(char* pszInput, bool bRegEx, int iEOLMode) } +//============================================================================= +// +// WideCharToMultiByteEx() +// +ptrdiff_t WideCharToMultiByteEx( + UINT CodePage, DWORD dwFlags, LPCWCH lpWideCharStr, ptrdiff_t cchWideChar, + LPSTR lpMultiByteStr, ptrdiff_t cbMultiByte) +{ + LPCWCH inPtr = lpWideCharStr; + ptrdiff_t inBufCnt = cchWideChar; + LPSTR outPtr = (cbMultiByte == 0LL) ? NULL : lpMultiByteStr; + ptrdiff_t outBufSiz = cbMultiByte; + ptrdiff_t bytesConv = 0LL; + + while ((inBufCnt > 0LL) || (inBufCnt == -1LL)) + { + int const cnt = (inBufCnt > INT_MAX) ? INT_MAX : ((inBufCnt > 0LL) ? (int)inBufCnt : -1); + int const siz = (outBufSiz > INT_MAX) ? INT_MAX : (int)outBufSiz; + int const bytes = WideCharToMultiByte(CodePage, dwFlags, inPtr, cnt, outPtr, siz, NULL, NULL); + if (bytes == 0) { break; } + bytesConv += (ptrdiff_t)bytes; + if (outPtr) { + outPtr += (ptrdiff_t)bytes; + outBufSiz -= (ptrdiff_t)bytes; + } + if (inBufCnt > 0LL) { + inBufCnt -= (ptrdiff_t)cnt; + } + inPtr += (ptrdiff_t)cnt; + } + return bytesConv; +} + +//============================================================================= +// +// MultiByteToWideCharEx() +// +ptrdiff_t MultiByteToWideCharEx( + UINT CodePage, DWORD dwFlags, LPCCH lpMultiByteStr, ptrdiff_t cbMultiByte, + LPWSTR lpWideCharStr, ptrdiff_t cchWideChar) +{ + LPCCH inPtr = lpMultiByteStr; + ptrdiff_t inBufSiz = cbMultiByte; + LPWSTR outPtr = (cchWideChar == 0LL) ? NULL : lpWideCharStr; + ptrdiff_t outBufCnt = cchWideChar; + ptrdiff_t wcharConv = 0LL; + + while ((inBufSiz > 0LL) || (inBufSiz == -1LL)) + { + int const siz = (inBufSiz > INT_MAX) ? INT_MAX : ((inBufSiz > 0LL) ? (int)inBufSiz : -1); + int const cnt = (outBufCnt > INT_MAX) ? INT_MAX : (int)outBufCnt; + int const wchars = MultiByteToWideChar(CodePage, dwFlags, inPtr, siz, outPtr, cnt); + if (wchars == 0) { break; } + wcharConv += (ptrdiff_t)wchars; + int const usedMBC = WideCharToMultiByte(CodePage, dwFlags, outPtr, wchars, NULL, 0, NULL, NULL); + if (outPtr) { + outPtr += (ptrdiff_t)wchars; + outBufCnt -= (ptrdiff_t)wchars; + } + if (inBufSiz > 0LL) { + inBufSiz -= (ptrdiff_t)usedMBC; + } + inPtr += (ptrdiff_t)usedMBC; + } + return wcharConv; +} + /* diff --git a/src/Helpers.h b/src/Helpers.h index e048ee97d..c2359cb92 100644 --- a/src/Helpers.h +++ b/src/Helpers.h @@ -340,6 +340,17 @@ unsigned int UnSlash(char* s, UINT cpEdit); void TransformBackslashes(char* pszInput,bool,UINT cpEdit,int* iReplaceMsg); void TransformMetaChars(char* pszInput,bool,int iEOLMode); + +//==== Large Text Conversion ================================================== +ptrdiff_t WideCharToMultiByteEx( + UINT CodePage, DWORD dwFlags, LPCWCH lpWideCharStr, ptrdiff_t cchWideChar, + LPSTR lpMultiByteStr, ptrdiff_t cbMultiByte); + +ptrdiff_t MultiByteToWideCharEx( + UINT CodePage, DWORD dwFlags, LPCCH lpMultiByteStr, ptrdiff_t cbMultiByte, + LPWSTR lpWideCharStr, ptrdiff_t cchWideChar); + + //==== MinimizeToTray Functions - see comments in Helpers.c =================== bool GetDoAnimateMinimize(VOID); VOID MinimizeWndToTray(HWND hWnd); diff --git a/test/config/Notepad3_distrib.ini b/test/config/Notepad3_distrib.ini index 1f621e1bac78912dc84f0f82f2666958202a2eb7..26615576092e9a8a5701e2c7aac607a5d3c956c9 100644 GIT binary patch literal 602 zcmYjP!EW0y487|sblI^@?4)Z}Kp3)R1_C%m7bnXh&4H0wTbL|)5>qVS*26w&zc4Co z(g6m=_bAa%kNW%aXM67nd#Fb{v8|BExF+tzIs1Vj8t+slDtN{-`v#Y&(NSS6MrIy> z+I#4*@Sy`@qJU=~3~}-L@sdA^73||QRy}C03=`a#np!m$3kW|;@0!xMQ^!kQn$D1# z48@sQ_!{{SrH6W2eVxxCu2;o`yA|elI{nSn=^m-Q_jV8A%Yn!{mML>NmLoZoH}WIL zTRD-Rc+L3B(wcL~$0_78Py4cw%o5IS5}87F`|eb}6AuBOFa)eiaLoZ4EWHMc$qI$; zYF&wnwOC9(&0QpLI%%(3w07F}>xdy;$IfT!Jc`#MSE^$q>=w&)I-t$W1k|)irmj%8 z>gvQ6-qH61SVPCeY;eEAuD3v#sg|gZcY{IWJxjROz8ge@pxe*C)Q9;0-du_8>pN|d*;k#{pa^YAGOq0l~yWL>Y2Xiu^wrn9NU&>u7zgWH1^CjTB`jOrp|H?Bo&hn|?93XO1|G@mbFAU?v2MVcg0B6> zm5s39661`Od(IZ$Vm|Ho$FP+iyRYYNA98N3Z~EYQ&Ujm0x@sSK40G?g`sy|Oho~WZ zB|I@7^IIRzQ1?z3JO%2mH6o*4tI}%qtJUxxC8g`JKJ7DE!c~*4DSxXUWGy725jo5?NsI*VP}k4%a{5tZT+c72uO=%yHuxM z--q*-H4}G<`bu9}Yu}aRU6ApNj0%1$@5z+CO;4PaKKq4^s9f&+c~c+5#7VmVv7si$ zW>XM*kTY`?Y&Bh2@mzzl=&@HdT{#DRcysLD?9YZ%xpp3-ViJbBf@>dTil%dx1|obdx;Hs#D;&QX6Eff5^x(Idjo+Goz4kAt gx2{A?j{cqNjjW-<85Jq1qs>S`U21T9Y`hJB0hFl8%>V!Z