From d3ea1a7281dee9752c2c8a93cbbeeabe3a0886e2 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Thu, 12 Sep 2019 16:21:31 +0200 Subject: [PATCH 1/2] + chg: "commit" on fflush() for _wfopen_s() in SimpleIni settings file writer + fix: some issues on tmpfile handling --- Versions/build.txt | 2 +- res/Notepad3.exe.manifest.conf | 2 +- src/Config/Config.cpp | 23 +++++++++++++++++--- src/Config/SimpleIni.h | 5 +++-- src/Notepad3.c | 38 +++++++++++++++++++++++++++------- src/Styles.c | 36 +++++++++++++++++++++----------- src/Styles.h | 1 + src/VersionEx.h | 2 +- 8 files changed, 82 insertions(+), 27 deletions(-) diff --git a/Versions/build.txt b/Versions/build.txt index e27075af4..7dcc2b9c8 100644 --- a/Versions/build.txt +++ b/Versions/build.txt @@ -1 +1 @@ -2627 +2629 diff --git a/res/Notepad3.exe.manifest.conf b/res/Notepad3.exe.manifest.conf index 23be18386..c50394e0d 100644 --- a/res/Notepad3.exe.manifest.conf +++ b/res/Notepad3.exe.manifest.conf @@ -3,7 +3,7 @@ Notepad3 BETA diff --git a/src/Config/Config.cpp b/src/Config/Config.cpp index 150c599c7..6d0e0addb 100644 --- a/src/Config/Config.cpp +++ b/src/Config/Config.cpp @@ -54,7 +54,7 @@ extern "C" int s_flagSingleFileInstance; extern "C" int s_flagMultiFileArg; extern "C" int s_flagShellUseSystemMRU; extern "C" int s_flagPrintFileAndLeave; -extern "C" int s_flagDoRelaunchElevated; +extern "C" bool s_flagDoRelaunchElevated; // ---------------------------------------------------------------------------- @@ -250,6 +250,8 @@ extern "C" size_t IniFileGetString(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LP extern "C" bool IniFileSetString(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWSTR lpKeyName, LPCWSTR lpString) { + if (s_flagDoRelaunchElevated) { return false; } + CSimpleIni Ini(s_bIsUTF8, s_bUseMultiKey, s_bUseMultiLine); SI_Error rc = Ini.LoadFile(lpFilePath); if (SI_SUCCESS(rc)) @@ -261,6 +263,7 @@ extern "C" bool IniFileSetString(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCW Ini.SetSpaces(s_bSetSpaces); rc = Ini.SaveFile(lpFilePath, true); } + Ini.Reset(); } return SI_SUCCESS(rc); } @@ -284,6 +287,8 @@ extern "C" int IniFileGetInt(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWSTR extern "C" bool IniFileSetInt(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWSTR lpKeyName, int iValue) { + if (s_flagDoRelaunchElevated) { return false; } + CSimpleIni Ini(s_bIsUTF8, s_bUseMultiKey, s_bUseMultiLine); SI_Error rc = Ini.LoadFile(lpFilePath); if (SI_SUCCESS(rc)) { @@ -291,6 +296,7 @@ extern "C" bool IniFileSetInt(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWSTR Ini.SetSpaces(s_bSetSpaces); rc = Ini.SaveFile(lpFilePath, true); } + Ini.Reset(); return SI_SUCCESS(rc); } // ============================================================================ @@ -313,6 +319,8 @@ extern "C" bool IniFileGetBool(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWST extern "C" bool IniFileSetBool(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWSTR lpKeyName, bool bValue) { + if (s_flagDoRelaunchElevated) { return false; } + CSimpleIni Ini(s_bIsUTF8, s_bUseMultiKey, s_bUseMultiLine); SI_Error rc = Ini.LoadFile(lpFilePath); if (SI_SUCCESS(rc)) { @@ -320,6 +328,7 @@ extern "C" bool IniFileSetBool(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWST Ini.SetSpaces(s_bSetSpaces); rc = Ini.SaveFile(lpFilePath, true); } + Ini.Reset(); return SI_SUCCESS(rc); } // ============================================================================ @@ -327,6 +336,8 @@ extern "C" bool IniFileSetBool(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWST extern "C" bool IniFileDelete(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWSTR lpKeyName, bool bRemoveEmpty) { + if (s_flagDoRelaunchElevated) { return false; } + CSimpleIni Ini(s_bIsUTF8, s_bUseMultiKey, s_bUseMultiLine); SI_Error rc = Ini.LoadFile(lpFilePath); if (SI_SUCCESS(rc)) @@ -335,6 +346,7 @@ extern "C" bool IniFileDelete(LPCWSTR lpFilePath, LPCWSTR lpSectionName, LPCWSTR Ini.SetSpaces(s_bSetSpaces); rc = Ini.SaveFile(lpFilePath, true); } + Ini.Reset(); return SI_SUCCESS(rc); } // ============================================================================ @@ -1188,14 +1200,14 @@ void LoadFlags() bool SaveSettings(bool bSaveSettingsNow) { - if (StrIsEmpty(Globals.IniFile) || !s_bEnableSaveSettings || s_flagDoRelaunchElevated) { return false; } + if (StrIsEmpty(Globals.IniFile) || s_flagDoRelaunchElevated) { return false; } CreateIniFile(); LoadIniFile(Globals.IniFile); const WCHAR* const Settings_Section = L"Settings"; - if (!(Settings.SaveSettings || bSaveSettingsNow)) + if (!Settings.SaveSettings && !bSaveSettingsNow) { if (Settings.SaveSettings != Defaults.SaveSettings) { IniSectionSetBool(Settings_Section, L"SaveSettings", Settings.SaveSettings); @@ -1450,12 +1462,17 @@ bool SaveSettings(bool bSaveSettingsNow) IniSectionDelete(Window_Section, tchZoom, false); } + + bool const ok = SaveIniFile(Globals.IniFile); if (ok) { Style_Save(); // Scintilla Styles Globals.bIniFileFromScratch = false; } + + ReleaseIniFile(); + return ok; } //============================================================================= diff --git a/src/Config/SimpleIni.h b/src/Config/SimpleIni.h index 77897aad7..9118f0876 100644 --- a/src/Config/SimpleIni.h +++ b/src/Config/SimpleIni.h @@ -405,6 +405,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); } @@ -2440,9 +2441,9 @@ 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; SI_Error rc = SaveFile(fp, a_bAddSignature); diff --git a/src/Notepad3.c b/src/Notepad3.c index efbee3c57..db37a450d 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -827,7 +827,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, StringCchCat(s_wchWndClass, COUNTOF(s_wchWndClass), L"B"); } // Try to Relaunch with elevated privileges - if (RelaunchElevated(NULL)) { + s_flagDoRelaunchElevated = RelaunchElevated(NULL); + if (s_flagDoRelaunchElevated) { return 0; } // Try to run multiple instances @@ -1232,8 +1233,18 @@ HWND InitInstance(HINSTANCE hInstance,LPCWSTR pszCmdLine,int nCmdShow) Style_SetLexerFromFile(Globals.hwndEdit, Globals.CurrentFile); } // check for temp file and delete - if (s_bIsElevated && PathFileExists(s_wchTmpFilePath)) { + if (s_IsThisAnElevatedRelaunch && PathFileExists(s_wchTmpFilePath)) + { DeleteFile(s_wchTmpFilePath); + // delete possible .tmp guard + size_t const len = StringCchLen(s_wchTmpFilePath, MAX_PATH); + LPWSTR p = PathFindExtension(s_wchTmpFilePath); + if (p && *p) { + StringCchCopy(p, (MAX_PATH - len), L".tmp"); + } + if (PathFileExists(s_wchTmpFilePath)) { + DeleteFile(s_wchTmpFilePath); + } } SciCall_SetSavePoint(); _SetSaveNeededFlag(true); @@ -7575,7 +7586,7 @@ void ParseCommandLine() lp1 + CSTRLEN(L"tmpfbuf="), len - CSTRLEN(L"tmpfbuf=")); TrimSpcW(s_wchTmpFilePath); NormalizePathEx(s_wchTmpFilePath, COUNTOF(s_wchTmpFilePath), true, s_flagSearchPathIfRelative); - s_IsThisAnElevatedRelaunch = true; + s_bIsElevated = s_IsThisAnElevatedRelaunch = true; } else switch (*CharUpper(lp1)) { @@ -9646,11 +9657,13 @@ bool DoElevatedRelaunch(EditFileIOStatus* pFioStatus) s_flagDoRelaunchElevated = true; LPWSTR lpCmdLine = GetCommandLine(); - size_t const wlen = StringCchLenW(lpCmdLine, 0) + 2; + size_t const wlen = StringCchLen(lpCmdLine, 0) + 2; LPWSTR lpExe = AllocMem(sizeof(WCHAR) * wlen, HEAP_ZERO_MEMORY); LPWSTR lpArgs = AllocMem(sizeof(WCHAR) * wlen, HEAP_ZERO_MEMORY); ExtractFirstArgument(lpCmdLine, lpExe, lpArgs, (int)wlen); + // remove relaunch elevated, we are doing this here already + lpArgs[StringCchLen(lpArgs, 0)] = L' '; // add a space lpArgs = StrCutI(lpArgs, L"/u "); lpArgs = StrCutI(lpArgs, L"-u "); WCHAR wchFlags[32] = { L'\0' }; @@ -10285,7 +10298,13 @@ bool RelaunchMultiInst() { // bool RelaunchElevated(LPWSTR lpNewCmdLnArgs) { - if (!IsVista() || s_bIsElevated || !s_flagDoRelaunchElevated || s_flagDisplayHelp) { return false; } + if (!IsVista() || + !s_flagDoRelaunchElevated || + s_bIsElevated || s_IsThisAnElevatedRelaunch || + s_flagDisplayHelp) + { + return false; + } STARTUPINFO si; si.cb = sizeof(STARTUPINFO); @@ -10302,9 +10321,14 @@ bool RelaunchElevated(LPWSTR lpNewCmdLnArgs) if (lpNewCmdLnArgs) { StringCchCopy(szOrigArgs, COUNTOF(szOrigArgs), lpNewCmdLnArgs); } + size_t const len = StringCchLen(szOrigArgs, 0); + szOrigArgs[len] = L' '; // add a space + szOrigArgs[len+1] = L'\0'; // ensure termination + // remove relaunch elevated, we are doing this here already + StrCutI(szOrigArgs, L"/u "); + StrCutI(szOrigArgs, L"-u "); WCHAR szArguments[2032] = { L'\0' }; - if (StrStrI(szOrigArgs, L"/f ") || StrStrI(szOrigArgs, L"-f ") || StrIsEmpty(Globals.IniFile)) { StringCchCopy(szArguments, COUNTOF(szArguments), szOrigArgs); @@ -10317,7 +10341,7 @@ bool RelaunchElevated(LPWSTR lpNewCmdLnArgs) SHELLEXECUTEINFO sei; ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO)); sei.cbSize = sizeof(SHELLEXECUTEINFO); - sei.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_UNICODE | SEE_MASK_HMONITOR | SEE_MASK_NOZONECHECKS; + sei.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_UNICODE | SEE_MASK_HMONITOR | SEE_MASK_NOZONECHECKS | SEE_MASK_WAITFORINPUTIDLE; sei.hwnd = GetForegroundWindow(); sei.hMonitor = MonitorFromWindow(sei.hwnd, MONITOR_DEFAULTTONEAREST); sei.lpVerb = L"runas"; diff --git a/src/Styles.c b/src/Styles.c index 4f69617d4..8b982c965 100644 --- a/src/Styles.c +++ b/src/Styles.c @@ -704,7 +704,7 @@ bool Style_Export(HWND hwnd) //============================================================================= // -// Style_ExportToFile() +// Style_Export() // #define SAVE_STYLE_IF_NOT_EQ_DEFAULT(TYPE, VARNAME, VALUE, DEFAULT) \ @@ -716,18 +716,9 @@ bool Style_Export(HWND hwnd) // ---------------------------------------------------------------------------- -bool Style_ExportToFile(const WCHAR* szFile, bool bForceAll) +void Style_ToIniSection(bool bForceAll) { - if (StrIsEmpty(szFile)) { - if (s_idxSelectedTheme != 0) { - InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SETTINGSNOTSAVED); - } - return false; - } - - LoadIniFile(szFile); // reset - - // Custom colors + // Custom colors const WCHAR* const CustomColors_Section = L"Custom Colors"; for (int i = 0; i < 16; i++) { @@ -815,6 +806,27 @@ bool Style_ExportToFile(const WCHAR* szFile, bool bForceAll) IniSectionDelete(L"Default Text", NULL, true); IniSectionDelete(L"2nd Default Text", NULL, true); +} + + +//============================================================================= +// +// Style_ExportToFile() +// + +bool Style_ExportToFile(const WCHAR* szFile, bool bForceAll) +{ + if (StrIsEmpty(szFile)) { + if (s_idxSelectedTheme != 0) { + InfoBoxLng(MB_ICONWARNING, NULL, IDS_MUI_SETTINGSNOTSAVED); + } + return false; + } + + LoadIniFile(szFile); // reset + + Style_ToIniSection(bForceAll); + return SaveIniFile(szFile); } diff --git a/src/Styles.h b/src/Styles.h index 5d0cdd64a..9e4870088 100644 --- a/src/Styles.h +++ b/src/Styles.h @@ -34,6 +34,7 @@ bool Style_Import(HWND hwnd); bool Style_ImportFromFile(const WCHAR* szFile); void Style_Save(); bool Style_Export(HWND hwnd); +void Style_ToIniSection(bool bForceAll); bool Style_ExportToFile(const WCHAR* szFile, bool bForceAll); unsigned ThemeItems_CountOf(); diff --git a/src/VersionEx.h b/src/VersionEx.h index e0b4efc28..0eeaa3472 100644 --- a/src/VersionEx.h +++ b/src/VersionEx.h @@ -8,7 +8,7 @@ #define VERSION_MAJOR 5 #define VERSION_MINOR 19 #define VERSION_REV 912 -#define VERSION_BUILD 2627 +#define VERSION_BUILD 2629 #define SCINTILLA_VER 420 #define ONIGURUMA_REGEX_VER 6.9.3 #define UCHARDET_VER 2018.09.27 From 3cdd4ba1c31bf713570a0fd914116de709c92007 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Thu, 12 Sep 2019 18:59:19 +0200 Subject: [PATCH 2/2] + add: 1st draft version of Rainbow/Prism CSV Lexer --- Versions/build.txt | 2 +- language/common_res.h | 12 ++ language/np3_de_de/lexer_de_de.rc | 17 +- language/np3_en_gb/lexer_en_gb.rc | 17 +- language/np3_en_us/lexer_en_us.rc | 15 ++ res/Notepad3.exe.manifest.conf | 2 +- sciXlexers/LexCSV.cxx | 282 +++++++++++++++++++++++++ sciXlexers/SciXLexer.h | 13 ++ scintilla/Scintilla.vcxproj | 1 + scintilla/Scintilla.vcxproj.filters | 3 + scintilla/ScintillaDLL.vcxproj | 1 + scintilla/ScintillaDLL.vcxproj.filters | 3 + scintilla/src/Catalogue.cxx | 1 + src/Notepad3.vcxproj | 1 + src/Notepad3.vcxproj.filters | 3 + src/Notepad3DLL.vcxproj | 1 + src/Notepad3DLL.vcxproj.filters | 3 + src/StyleLexers/EditLexer.h | 1 + src/StyleLexers/styleLexCSV.c | 26 +++ src/StyleLexers/styleLexStandard.c | 2 +- src/Styles.c | 1 + src/Styles.h | 2 +- src/VersionEx.h | 2 +- 23 files changed, 404 insertions(+), 7 deletions(-) create mode 100644 sciXlexers/LexCSV.cxx create mode 100644 src/StyleLexers/styleLexCSV.c diff --git a/Versions/build.txt b/Versions/build.txt index 7dcc2b9c8..207caa936 100644 --- a/Versions/build.txt +++ b/Versions/build.txt @@ -1 +1 @@ -2629 +2630 diff --git a/language/common_res.h b/language/common_res.h index cf7bb05f2..db71223bd 100644 --- a/language/common_res.h +++ b/language/common_res.h @@ -780,6 +780,7 @@ #define IDS_LEX_AHKL 63047 #define IDS_LEX_TEXT_FILES 63048 #define IDS_LEX_TOML_CFG 63049 +#define IDS_LEX_PRISM_CSV 63050 #define IDS_LEX_STD_STYLE 63100 #define IDS_LEX_STD_MARGIN 63101 @@ -1040,6 +1041,17 @@ #define IDS_LEX_STR_63355 63355 #define IDS_LEX_STR_63356 63356 +#define IDS_LEX_CSV_COL_0 63400 +#define IDS_LEX_CSV_COL_1 63401 +#define IDS_LEX_CSV_COL_2 63402 +#define IDS_LEX_CSV_COL_3 63403 +#define IDS_LEX_CSV_COL_4 63404 +#define IDS_LEX_CSV_COL_5 63405 +#define IDS_LEX_CSV_COL_6 63406 +#define IDS_LEX_CSV_COL_7 63407 +#define IDS_LEX_CSV_COL_8 63408 +#define IDS_LEX_CSV_COL_9 63409 + #define RICHEDIT_CONTROL_VER "RichEdit50W" // RICHEDIT_CONTROL_VER #endif //_COMMON_RES_H_ diff --git a/language/np3_de_de/lexer_de_de.rc b/language/np3_de_de/lexer_de_de.rc index 522e14221..58675307b 100644 --- a/language/np3_de_de/lexer_de_de.rc +++ b/language/np3_de_de/lexer_de_de.rc @@ -65,6 +65,7 @@ BEGIN IDS_LEX_WEB_SRC "Web Source Code" IDS_LEX_XML_DOC "XML Document" IDS_LEX_CSS_STYLE "CSS Style Sheets" + IDS_LEX_PRISM_CSV "CSV Prism" IDS_LEX_CPP_SRC "C/C++ Source Code" IDS_LEX_CSHARP_SRC "C# Source Code" IDS_LEX_RESOURCE_SCR "Resource Script" @@ -450,7 +451,21 @@ BEGIN IDS_LEX_STR_63356 "Date-Time" END -#endif // German (Germany) resources +STRINGTABLE +BEGIN + IDS_LEX_CSV_COL_0 "Column 0" + IDS_LEX_CSV_COL_1 "Column 1" + IDS_LEX_CSV_COL_2 "Column 2" + IDS_LEX_CSV_COL_3 "Column 3" + IDS_LEX_CSV_COL_4 "Column 4" + IDS_LEX_CSV_COL_5 "Column 5" + IDS_LEX_CSV_COL_6 "Column 6" + IDS_LEX_CSV_COL_7 "Column 7" + IDS_LEX_CSV_COL_8 "Column 8" + IDS_LEX_CSV_COL_9 "Column 9" +END + +#endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/language/np3_en_gb/lexer_en_gb.rc b/language/np3_en_gb/lexer_en_gb.rc index 547d90a41..46ad06e32 100644 --- a/language/np3_en_gb/lexer_en_gb.rc +++ b/language/np3_en_gb/lexer_en_gb.rc @@ -65,6 +65,7 @@ BEGIN IDS_LEX_WEB_SRC "Web Source Code" IDS_LEX_XML_DOC "XML Document" IDS_LEX_CSS_STYLE "CSS Style Sheets" + IDS_LEX_PRISM_CSV "CSV Prism" IDS_LEX_CPP_SRC "C/C++ Source Code" IDS_LEX_CSHARP_SRC "C# Source Code" IDS_LEX_RESOURCE_SCR "Resource Script" @@ -450,7 +451,21 @@ BEGIN IDS_LEX_STR_63356 "Date-Time" END -#endif // English (United Kingdom) resources +STRINGTABLE +BEGIN + IDS_LEX_CSV_COL_0 "Column 0" + IDS_LEX_CSV_COL_1 "Column 1" + IDS_LEX_CSV_COL_2 "Column 2" + IDS_LEX_CSV_COL_3 "Column 3" + IDS_LEX_CSV_COL_4 "Column 4" + IDS_LEX_CSV_COL_5 "Column 5" + IDS_LEX_CSV_COL_6 "Column 6" + IDS_LEX_CSV_COL_7 "Column 7" + IDS_LEX_CSV_COL_8 "Column 8" + IDS_LEX_CSV_COL_9 "Column 9" +END + +#endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/language/np3_en_us/lexer_en_us.rc b/language/np3_en_us/lexer_en_us.rc index ac5f31240..2d39d1b2d 100644 --- a/language/np3_en_us/lexer_en_us.rc +++ b/language/np3_en_us/lexer_en_us.rc @@ -65,6 +65,7 @@ BEGIN IDS_LEX_WEB_SRC "Web Source Code" IDS_LEX_XML_DOC "XML Document" IDS_LEX_CSS_STYLE "CSS Style Sheets" + IDS_LEX_PRISM_CSV "CSV Prism" IDS_LEX_CPP_SRC "C/C++ Source Code" IDS_LEX_CSHARP_SRC "C# Source Code" IDS_LEX_RESOURCE_SCR "Resource Script" @@ -450,6 +451,20 @@ BEGIN IDS_LEX_STR_63356 "Date-Time" END +STRINGTABLE +BEGIN + IDS_LEX_CSV_COL_0 "Column 0" + IDS_LEX_CSV_COL_1 "Column 1" + IDS_LEX_CSV_COL_2 "Column 2" + IDS_LEX_CSV_COL_3 "Column 3" + IDS_LEX_CSV_COL_4 "Column 4" + IDS_LEX_CSV_COL_5 "Column 5" + IDS_LEX_CSV_COL_6 "Column 6" + IDS_LEX_CSV_COL_7 "Column 7" + IDS_LEX_CSV_COL_8 "Column 8" + IDS_LEX_CSV_COL_9 "Column 9" +END + #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/res/Notepad3.exe.manifest.conf b/res/Notepad3.exe.manifest.conf index c50394e0d..72667cfee 100644 --- a/res/Notepad3.exe.manifest.conf +++ b/res/Notepad3.exe.manifest.conf @@ -3,7 +3,7 @@ Notepad3 BETA diff --git a/sciXlexers/LexCSV.cxx b/sciXlexers/LexCSV.cxx new file mode 100644 index 000000000..140a38012 --- /dev/null +++ b/sciXlexers/LexCSV.cxx @@ -0,0 +1,282 @@ +// Scintilla source code edit control +/** @file LexCSV.cxx +** Rainbow clouring for CSV files +** Written by RaiKoHoff +**/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciXLexer.h" + +#include "StringCopy.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharSetX.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "DefaultLexer.h" + + +using namespace Scintilla; + +namespace { + // Use an unnamed namespace to protect the functions and classes from name conflicts + + struct OptionsCSV { + bool fold; + bool foldCompact; + + OptionsCSV() { + fold = true; + foldCompact = true; + } + }; + + static const char* const csvWordLists[] = { + nullptr + }; + + struct OptionSetCSV : public OptionSet { + OptionSetCSV() { + + DefineProperty("fold", &OptionsCSV::fold, "FOLD COMMENT"); + DefineProperty("fold.compact", &OptionsCSV::foldCompact, "FOLDCOMPACT COMMENT"); + + DefineWordListSets(csvWordLists); + } + }; + + LexicalClass lexicalClasses[] = { + // Lexer CSV SCLEX_CSV SCE_CSV_: + 0, "SCE_CSV_DEFAULT", "default", "Default", + 1, "SCE_CSV_COLUMN_0", "col_0", "Column 0", + 2, "SCE_CSV_COLUMN_1", "col_1", "Column 1", + 3, "SCE_CSV_COLUMN_2", "col_2", "Column 2", + 4, "SCE_CSV_COLUMN_3", "col_3", "Column 3", + 5, "SCE_CSV_COLUMN_4", "col_4", "Column 4", + 6, "SCE_CSV_COLUMN_5", "col_5", "Column 5", + 7, "SCE_CSV_COLUMN_6", "col_6", "Column 6", + 8, "SCE_CSV_COLUMN_7", "col_7", "Column 7", + 9, "SCE_CSV_COLUMN_8", "col_8", "Column 8", + 10, "SCE_CSV_COLUMN_9", "col_9", "Column 9", + }; + + + } // end of namespace + +class LexerCSV : public DefaultLexer { + + WordList keywords; + + OptionsCSV options; + OptionSetCSV osCSV; + +public: + LexerCSV() + : DefaultLexer(lexicalClasses, ELEMENTS(lexicalClasses)) + { } + + virtual ~LexerCSV() { } + + void SCI_METHOD Release() override { + delete this; + } + + int SCI_METHOD Version() const override { + return lvRelease4; + } + + const char* SCI_METHOD PropertyNames() override { + return osCSV.PropertyNames(); + } + + int SCI_METHOD PropertyType(const char* name) override { + return osCSV.PropertyType(name); + } + + const char* SCI_METHOD DescribeProperty(const char* name) override { + return osCSV.DescribeProperty(name); + } + + + const char* SCI_METHOD DescribeWordListSets() override { + return osCSV.DescribeWordListSets(); + } + + void* SCI_METHOD PrivateCall(int, void*) override { + return nullptr; + } + + int SCI_METHOD LineEndTypesSupported() override { + return SC_LINE_END_TYPE_UNICODE; + } + + int SCI_METHOD PrimaryStyleFromStyle(int style) override { + return style; + } + + static ILexer4* LexerFactoryCSV() { + return new LexerCSV(); + } + + // -------------------------------------------------------------------------- + + Sci_Position SCI_METHOD PropertySet(const char* key, const char* val) override; + Sci_Position SCI_METHOD WordListSet(int n, const char* wl) override; + void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument* pAccess) override; + void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument* pAccess) override; + +}; + + +Sci_Position SCI_METHOD LexerCSV::PropertySet(const char* key, const char* val) { + if (osCSV.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + + +Sci_Position SCI_METHOD LexerCSV::WordListSet(int n, const char* wl) +{ + WordList* wordListN = nullptr; + + switch (n) { + case 0: + wordListN = &keywords; + break; + } + + Sci_Position firstModification = -1; + + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} +// ---------------------------------------------------------------------------- + +constexpr int abs_i(const int i) noexcept { return ((i < 0) ? (0 - i) : (0 + i)); } + +// ---------------------------------------------------------------------------- + +constexpr bool IsSingleQuoteChar(const int ch) noexcept +{ + return (ch == '\''); +} +// ---------------------------------------------------------------------------- + +constexpr bool IsDoubleQuoteChar(const int ch) noexcept +{ + return (ch == '"'); +} +// ---------------------------------------------------------------------------- + +constexpr bool IsDelimiter(const int ch) noexcept +{ + return ((ch == ',') || (ch == ';') || (ch == '\t')); +} +// ---------------------------------------------------------------------------- + +constexpr int GetStateByColumn(const int col) noexcept +{ + switch (col % 10) { + case 0: + return SCE_CSV_COLUMN_0; + case 1: + return SCE_CSV_COLUMN_1; + case 2: + return SCE_CSV_COLUMN_2; + case 3: + return SCE_CSV_COLUMN_3; + case 4: + return SCE_CSV_COLUMN_4; + case 5: + return SCE_CSV_COLUMN_5; + case 6: + return SCE_CSV_COLUMN_6; + case 7: + return SCE_CSV_COLUMN_7; + case 8: + return SCE_CSV_COLUMN_8; + case 9: + return SCE_CSV_COLUMN_9; + default: + return SCE_CSV_COLUMN_0; + } + return SCE_CSV_COLUMN_0; +} +// ---------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- + +void SCI_METHOD LexerCSV::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument* pAccess) +{ + Accessor styler(pAccess, nullptr); + StyleContext sc(startPos, length, initStyle, styler); + + int csvColumn = 0; + bool isInSQString = false; + bool isInDQString = false; + + for (; sc.More(); sc.Forward()) + { + // reset context infos + if (sc.atLineStart) { + csvColumn = 0; + isInSQString = false; + isInDQString = false; + sc.SetState(GetStateByColumn(csvColumn)); + } + + if (IsSingleQuoteChar(sc.ch)) { + if (!isInDQString) { + isInSQString = !isInSQString; // toggle + } + } + else if (IsDoubleQuoteChar(sc.ch)) { + if (!isInSQString) { + isInDQString = !isInDQString; // toggle + } + } + else if (IsDelimiter(sc.ch)) { + if (!isInSQString && !isInDQString) { + sc.SetState(GetStateByColumn(++csvColumn)); + } + } + + } + sc.Complete(); +} +// ---------------------------------------------------------------------------- + + + +void SCI_METHOD LexerCSV::Fold(Sci_PositionU startPos, Sci_Position length, int, IDocument* pAccess) +{ + return; +} +// ---------------------------------------------------------------------------- + +LexerModule lmCSV(SCLEX_CSV, LexerCSV::LexerFactoryCSV, "csv", csvWordLists); + +// ---------------------------------------------------------------------------- + diff --git a/sciXlexers/SciXLexer.h b/sciXlexers/SciXLexer.h index 972fba9a8..0bb9f5621 100644 --- a/sciXlexers/SciXLexer.h +++ b/sciXlexers/SciXLexer.h @@ -4,6 +4,7 @@ #define SCLEX_AHKL 200 #define SCLEX_TOML 201 +#define SCLEX_CSV 202 // ----------------------------------------------------------------------------- // !!!!! ADD Lexer Linkage in: scintilla\src\Catalogue.cxx !!!!! @@ -56,4 +57,16 @@ #define SCE_TOML_PARSINGERROR 11 +#define SCE_CSV_DEFAULT 0 +#define SCE_CSV_COLUMN_0 1 +#define SCE_CSV_COLUMN_1 2 +#define SCE_CSV_COLUMN_2 3 +#define SCE_CSV_COLUMN_3 4 +#define SCE_CSV_COLUMN_4 5 +#define SCE_CSV_COLUMN_5 6 +#define SCE_CSV_COLUMN_6 7 +#define SCE_CSV_COLUMN_7 8 +#define SCE_CSV_COLUMN_8 9 +#define SCE_CSV_COLUMN_9 10 + #endif //_SCIXLEXER_H_ diff --git a/scintilla/Scintilla.vcxproj b/scintilla/Scintilla.vcxproj index 2d6a5e446..d3fd3286c 100644 --- a/scintilla/Scintilla.vcxproj +++ b/scintilla/Scintilla.vcxproj @@ -234,6 +234,7 @@ + diff --git a/scintilla/Scintilla.vcxproj.filters b/scintilla/Scintilla.vcxproj.filters index 87aa77cff..06f53a310 100644 --- a/scintilla/Scintilla.vcxproj.filters +++ b/scintilla/Scintilla.vcxproj.filters @@ -342,6 +342,9 @@ sciXlexers + + sciXlexers + diff --git a/scintilla/ScintillaDLL.vcxproj b/scintilla/ScintillaDLL.vcxproj index 00e6937bc..9087c322e 100644 --- a/scintilla/ScintillaDLL.vcxproj +++ b/scintilla/ScintillaDLL.vcxproj @@ -246,6 +246,7 @@ + diff --git a/scintilla/ScintillaDLL.vcxproj.filters b/scintilla/ScintillaDLL.vcxproj.filters index c2043fe0d..e719a7872 100644 --- a/scintilla/ScintillaDLL.vcxproj.filters +++ b/scintilla/ScintillaDLL.vcxproj.filters @@ -345,6 +345,9 @@ sciXlexers + + sciXlexers + diff --git a/scintilla/src/Catalogue.cxx b/scintilla/src/Catalogue.cxx index bada47230..69f5edfce 100644 --- a/scintilla/src/Catalogue.cxx +++ b/scintilla/src/Catalogue.cxx @@ -102,6 +102,7 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmCPPNoCase); //LINK_LEXER(lmCsound); LINK_LEXER(lmCss); + LINK_LEXER(lmCSV); LINK_LEXER(lmD); //LINK_LEXER(lmDataflex); LINK_LEXER(lmDiff); diff --git a/src/Notepad3.vcxproj b/src/Notepad3.vcxproj index 4fe7bb880..d2f038d73 100644 --- a/src/Notepad3.vcxproj +++ b/src/Notepad3.vcxproj @@ -454,6 +454,7 @@ + diff --git a/src/Notepad3.vcxproj.filters b/src/Notepad3.vcxproj.filters index 2941a06fd..37a0c6e47 100644 --- a/src/Notepad3.vcxproj.filters +++ b/src/Notepad3.vcxproj.filters @@ -402,6 +402,9 @@ Source Files\StyleLexers + + Source Files\StyleLexers + diff --git a/src/Notepad3DLL.vcxproj b/src/Notepad3DLL.vcxproj index 3adafd13d..2d2fe2006 100644 --- a/src/Notepad3DLL.vcxproj +++ b/src/Notepad3DLL.vcxproj @@ -454,6 +454,7 @@ + diff --git a/src/Notepad3DLL.vcxproj.filters b/src/Notepad3DLL.vcxproj.filters index c5651db77..3421c19e2 100644 --- a/src/Notepad3DLL.vcxproj.filters +++ b/src/Notepad3DLL.vcxproj.filters @@ -402,6 +402,9 @@ Source Files\Config + + Source Files\StyleLexers + diff --git a/src/StyleLexers/EditLexer.h b/src/StyleLexers/EditLexer.h index 723565e0d..c14cae9f3 100644 --- a/src/StyleLexers/EditLexer.h +++ b/src/StyleLexers/EditLexer.h @@ -107,6 +107,7 @@ extern EDITLEXER lexCmake; // Cmake Script extern EDITLEXER lexCOFFEESCRIPT; // Coffeescript extern EDITLEXER lexPROPS; // Configuration Files extern EDITLEXER lexCSS; // CSS Style Sheets +extern EDITLEXER lexCSV; // CSV Prism Color Lexer extern EDITLEXER lexD; // D Source Code extern EDITLEXER lexDIFF; // Diff Files extern EDITLEXER lexGo; // Go Source Code diff --git a/src/StyleLexers/styleLexCSV.c b/src/StyleLexers/styleLexCSV.c new file mode 100644 index 000000000..306b5c7b3 --- /dev/null +++ b/src/StyleLexers/styleLexCSV.c @@ -0,0 +1,26 @@ +#include "StyleLexers.h" + +// ---------------------------------------------------------------------------- + +KEYWORDLIST KeyWords_CSV = EMPTY_KEYWORDLIST; + +EDITLEXER lexCSV = { +SCLEX_CSV, IDS_LEX_PRISM_CSV, L"CSV Prism", L"csv", L"", +& KeyWords_CSV,{ + //SCE_CSV_DEFAULT + { {STYLE_DEFAULT}, IDS_LEX_STR_63126, L"Default", L"", L"" }, + { {STYLE_LINENUMBER}, IDS_LEX_STD_MARGIN, L"Margins and Line Numbers", L"", L"" }, + { {SCI_SETEXTRAASCENT + SCI_SETEXTRADESCENT}, IDS_LEX_STD_X_SPC, L"Extra Line Spacing (Size)", L"size:-1", L"" }, + { {SCE_CSV_COLUMN_0}, IDS_LEX_CSV_COL_0, L"Column 0", L"fore:#9400D3", L"" }, + { {SCE_CSV_COLUMN_1}, IDS_LEX_CSV_COL_1, L"Column 1", L"fore:#1C01AF", L"" }, + { {SCE_CSV_COLUMN_2}, IDS_LEX_CSV_COL_2, L"Column 2", L"fore:#0162F3", L"" }, + { {SCE_CSV_COLUMN_3}, IDS_LEX_CSV_COL_3, L"Column 3", L"fore:#28A4FF", L"" }, + { {SCE_CSV_COLUMN_4}, IDS_LEX_CSV_COL_4, L"Column 4", L"fore:#01C2C2", L"" }, + { {SCE_CSV_COLUMN_5}, IDS_LEX_CSV_COL_5, L"Column 5", L"fore:#00D530", L"" }, + { {SCE_CSV_COLUMN_6}, IDS_LEX_CSV_COL_6, L"Column 6", L"fore:#80D500", L"" }, + { {SCE_CSV_COLUMN_7}, IDS_LEX_CSV_COL_7, L"Column 7", L"fore:#D3E401", L"" }, + { {SCE_CSV_COLUMN_8}, IDS_LEX_CSV_COL_8, L"Column 8", L"fore:#FE9901", L"" }, + { {SCE_CSV_COLUMN_9}, IDS_LEX_CSV_COL_9, L"Column 9", L"fore:#D90000", L"" }, + + EDITLEXER_SENTINEL } }; + diff --git a/src/StyleLexers/styleLexStandard.c b/src/StyleLexers/styleLexStandard.c index dffb9fbb1..44fccbbc0 100644 --- a/src/StyleLexers/styleLexStandard.c +++ b/src/StyleLexers/styleLexStandard.c @@ -51,7 +51,7 @@ SCLEX_NULL, IDS_LEX_STR_63266, L"2nd Common Base", L"", L"", EDITLEXER lexTEXT = { -SCLEX_NULL, IDS_LEX_TEXT_FILES, L"Text Files", L"txt; text; tmp; log; asc; doc; wtx; csv", L"", +SCLEX_NULL, IDS_LEX_TEXT_FILES, L"Text Files", L"txt; text; tmp; log; asc; doc; wtx", L"", &KeyWords_NULL,{ { {STYLE_DEFAULT}, IDS_LEX_STR_63126, L"Default", L"", L"" }, { {STYLE_LINENUMBER}, IDS_LEX_STD_MARGIN, L"Margins and Line Numbers", L"font:Lucida Console; size:-2", L"" }, diff --git a/src/Styles.c b/src/Styles.c index 8b982c965..8d6f0adb7 100644 --- a/src/Styles.c +++ b/src/Styles.c @@ -67,6 +67,7 @@ static PEDITLEXER g_pLexArray[NUMLEXERS] = &lexCOFFEESCRIPT, // Coffeescript &lexPROPS, // Configuration Files &lexCSS, // CSS Style Sheets + &lexCSV, // CSV Prism Color Lexer &lexD, // D Source Code &lexDIFF, // Diff Files &lexGo, // Go Source Code diff --git a/src/Styles.h b/src/Styles.h index 9e4870088..4fb511d3c 100644 --- a/src/Styles.h +++ b/src/Styles.h @@ -26,7 +26,7 @@ #define MARGIN_SCI_FOLDING 2 // Number of Lexers in pLexArray -#define NUMLEXERS 50 +#define NUMLEXERS 51 #define AVG_NUM_OF_STYLES_PER_LEXER 20 void Style_Load(); diff --git a/src/VersionEx.h b/src/VersionEx.h index 0eeaa3472..f97068b5a 100644 --- a/src/VersionEx.h +++ b/src/VersionEx.h @@ -8,7 +8,7 @@ #define VERSION_MAJOR 5 #define VERSION_MINOR 19 #define VERSION_REV 912 -#define VERSION_BUILD 2629 +#define VERSION_BUILD 2630 #define SCINTILLA_VER 420 #define ONIGURUMA_REGEX_VER 6.9.3 #define UCHARDET_VER 2018.09.27