From 79fb67e2485318a1f98271bd91a314fe1b437d53 Mon Sep 17 00:00:00 2001 From: akruphi <92621645+akruphi@users.noreply.github.com> Date: Mon, 1 Jul 2024 18:50:57 +0300 Subject: [PATCH] Advanced compare: add (in)sensitive option compare * add functions `LStrcmp` and `LStrncmp` in plugin api * add option "case sensitive file names" in Advanced compare plugin Fix #2115 Fix part of #2029 --- compare/configs/plug/CmpEng.hlf | 3 ++ compare/configs/plug/CmpRus.hlf | 3 ++ compare/configs/plug/CompBel.lng | 1 + compare/configs/plug/CompEng.lng | 1 + compare/configs/plug/CompRus.lng | 1 + compare/src/Compare.cpp | 54 ++++++++++++++++++-------------- far2l/far2sdk/farplug-mb.h | 2 ++ far2l/far2sdk/farplug-wide.h | 4 +++ far2l/src/plug/PluginW.cpp | 2 ++ far2l/src/plug/plugapi.cpp | 10 ++++++ far2l/src/plug/plugapi.hpp | 2 ++ 11 files changed, 59 insertions(+), 24 deletions(-) diff --git a/compare/configs/plug/CmpEng.hlf b/compare/configs/plug/CmpEng.hlf index f9dfe662d..c17b99e48 100644 --- a/compare/configs/plug/CmpEng.hlf +++ b/compare/configs/plug/CmpEng.hlf @@ -21,6 +21,9 @@ but it also provides additional compare options: #Compare:# + #case sensitive# Compare file names with/witout + #file names# case sensitive. + #time# Compare file modification time. Unlike the internal FAR command, this option will mark files on both panels, diff --git a/compare/configs/plug/CmpRus.hlf b/compare/configs/plug/CmpRus.hlf index 0a02325ca..7bc30e994 100644 --- a/compare/configs/plug/CmpRus.hlf +++ b/compare/configs/plug/CmpRus.hlf @@ -23,6 +23,9 @@ $ #Расширенное сравнение# #Сравнивать:# + #учитывать регистр# Сравнивать имена файлов с/без + #имен файлов# учета регистра. + #время# Сравнивать время изменения файлов. В отличие от встроенной команды FAR, будут помечены файлы на обеих панелях, diff --git a/compare/configs/plug/CompBel.lng b/compare/configs/plug/CompBel.lng index 94a12ff5c..e54d969f1 100644 --- a/compare/configs/plug/CompBel.lng +++ b/compare/configs/plug/CompBel.lng @@ -11,6 +11,7 @@ "&найбольшы узровень укладзенасці:" "т&олькі адзначаныя файлы/каталогі" "параўнаць:" +"&улічваць рэгістр імёны файлаў" "&час" "дзвухсекундная &дакладнасць" "&ігнараваць адрозненні з-за гадзінных паясоў" diff --git a/compare/configs/plug/CompEng.lng b/compare/configs/plug/CompEng.lng index ed485a129..bf87ef2a6 100644 --- a/compare/configs/plug/CompEng.lng +++ b/compare/configs/plug/CompEng.lng @@ -11,6 +11,7 @@ "&maximum folder depth:" "s&elected items only" "Compare:" +"c&ase sensitive file names" "&time" "two seconds &precision" "&ignore possible time zone differences" diff --git a/compare/configs/plug/CompRus.lng b/compare/configs/plug/CompRus.lng index 88525b4d9..9c5d15714 100644 --- a/compare/configs/plug/CompRus.lng +++ b/compare/configs/plug/CompRus.lng @@ -11,6 +11,7 @@ "&максимальный уровень вложенности:" "только п&омеченные файлы/папки" "Сравнивать:" +"&учитывать регистр имен файлов" "&время" "двухсекундная &точность" "&игнорировать различия из-за часовых поясов" diff --git a/compare/src/Compare.cpp b/compare/src/Compare.cpp index cfb9eec3e..6bea6e631 100644 --- a/compare/src/Compare.cpp +++ b/compare/src/Compare.cpp @@ -45,6 +45,7 @@ enum CompareLng MUseMaxScanDepth, MProcessSelected, MCompareBox, + MCompareCaseFileNames, MCompareTime, MCompareLowPrecision, MCompareIgnoreTimeZone, @@ -80,7 +81,8 @@ enum CompareLng ****************************************************************************/ struct Options { - int ProcessSubfolders, UseMaxScanDepth, MaxScanDepth, ProcessSelected, ProcessHidden, CompareTime, + int ProcessSubfolders, UseMaxScanDepth, MaxScanDepth, ProcessSelected, ProcessHidden, + CompareCaseFileNames, CompareTime, LowPrecisionTime, IgnorePossibleTimeZoneDifferences, CompareSize, CompareContents, CompareContentsIgnore, IgnoreWhitespace, IgnoreNewLines, MessageWhenNoDiff; } Opt; @@ -227,7 +229,7 @@ static bool ShowDialog(bool bPluginPanels, bool bSelectionPresent) unsigned int Flags; int *StoreTo; } InitItems[] = { - /* 0*/ {DI_DOUBLEBOX, 3, 1, 62, 20, MCmpTitle, 0, NULL, 0, NULL}, + /* 0*/ {DI_DOUBLEBOX, 3, 1, 62, 21, MCmpTitle, 0, NULL, 0, NULL}, /* 1*/ {DI_TEXT, 5, 2, 0, 0, MProcessBox, 0, NULL, 0, NULL}, /* 2*/ {DI_CHECKBOX, 5, 3, 0, 0, MProcessSubfolders, 0, ("ProcessSubfolders"), 0, @@ -241,32 +243,33 @@ static bool ShowDialog(bool bPluginPanels, bool bSelectionPresent) {DI_CHECKBOX, 5, 5, 0, 0, MProcessSelected, 0, ("ProcessSelected"), 0, &Opt.ProcessSelected}, /* 6*/ {DI_TEXT, 0, 6, 0, 0, MNoLngStringDefined, 0, NULL, DIF_SEPARATOR, NULL}, /* 7*/ {DI_TEXT, 5, 7, 0, 0, MCompareBox, 0, NULL, 0, NULL}, - /* 8*/ {DI_CHECKBOX, 5, 8, 0, 0, MCompareTime, 1, ("CompareTime"), 0, &Opt.CompareTime}, - /* 9*/ - {DI_CHECKBOX, 9, 9, 0, 0, MCompareLowPrecision, 1, ("LowPrecisionTime"), 0, - &Opt.LowPrecisionTime}, + /* 8*/ {DI_CHECKBOX, 5, 8, 0, 0, MCompareCaseFileNames, 1, ("CompareCaseFileNames"), 0, &Opt.CompareCaseFileNames}, + /* 9*/ {DI_CHECKBOX, 5, 9, 0, 0, MCompareTime, 1, ("CompareTime"), 0, &Opt.CompareTime}, /*10*/ - {DI_CHECKBOX, 9, 10, 0, 0, MCompareIgnoreTimeZone, 1, ("IgnorePossibleTimeZoneDifferences"), 0, + {DI_CHECKBOX, 9, 10, 0, 0, MCompareLowPrecision, 1, ("LowPrecisionTime"), 0, + &Opt.LowPrecisionTime}, + /*11*/ + {DI_CHECKBOX, 9, 11, 0, 0, MCompareIgnoreTimeZone, 1, ("IgnorePossibleTimeZoneDifferences"), 0, &Opt.IgnorePossibleTimeZoneDifferences}, - /*11*/ {DI_CHECKBOX, 5, 11, 0, 0, MCompareSize, 1, ("CompareSize"), 0, &Opt.CompareSize}, - /*12*/ - {DI_CHECKBOX, 5, 12, 0, 0, MCompareContents, 0, ("CompareContents"), 0, &Opt.CompareContents}, + /*12*/ {DI_CHECKBOX, 5, 12, 0, 0, MCompareSize, 1, ("CompareSize"), 0, &Opt.CompareSize}, /*13*/ - {DI_CHECKBOX, 9, 13, 0, 0, MCompareContentsIgnore, 0, ("CompareContentsIgnore"), 0, - &Opt.CompareContentsIgnore}, + {DI_CHECKBOX, 5, 13, 0, 0, MCompareContents, 0, ("CompareContents"), 0, &Opt.CompareContents}, /*14*/ - {DI_RADIOBUTTON, 13, 14, 0, 0, MCompareIgnoreNewLines, 1, ("IgnoreNewLines"), DIF_GROUP, - &Opt.IgnoreNewLines}, + {DI_CHECKBOX, 9, 14, 0, 0, MCompareContentsIgnore, 0, ("CompareContentsIgnore"), 0, + &Opt.CompareContentsIgnore}, /*15*/ - {DI_RADIOBUTTON, 13, 15, 0, 0, MCompareIgnoreWhitespace, 0, ("IgnoreWhitespace"), 0, + {DI_RADIOBUTTON, 13, 15, 0, 0, MCompareIgnoreNewLines, 1, ("IgnoreNewLines"), DIF_GROUP, + &Opt.IgnoreNewLines}, + /*16*/ + {DI_RADIOBUTTON, 13, 16, 0, 0, MCompareIgnoreWhitespace, 0, ("IgnoreWhitespace"), 0, &Opt.IgnoreWhitespace}, - /*16*/ {DI_TEXT, 0, 16, 0, 0, MNoLngStringDefined, 0, NULL, DIF_SEPARATOR, NULL}, - /*17*/ - {DI_CHECKBOX, 5, 17, 0, 0, MMessageWhenNoDiff, 0, ("MessageWhenNoDiff"), 0, + /*17*/ {DI_TEXT, 0, 17, 0, 0, MNoLngStringDefined, 0, NULL, DIF_SEPARATOR, NULL}, + /*18*/ + {DI_CHECKBOX, 5, 18, 0, 0, MMessageWhenNoDiff, 0, ("MessageWhenNoDiff"), 0, &Opt.MessageWhenNoDiff}, - /*18*/ {DI_TEXT, 0, 18, 0, 0, MNoLngStringDefined, 0, NULL, DIF_SEPARATOR, NULL}, - /*19*/ {DI_BUTTON, 0, 19, 0, 0, MOK, 0, NULL, DIF_CENTERGROUP, NULL}, - /*20*/ {DI_BUTTON, 0, 19, 0, 0, MCancel, 0, NULL, DIF_CENTERGROUP, NULL}}; + /*19*/ {DI_TEXT, 0, 19, 0, 0, MNoLngStringDefined, 0, NULL, DIF_SEPARATOR, NULL}, + /*20*/ {DI_BUTTON, 0, 20, 0, 0, MOK, 0, NULL, DIF_CENTERGROUP, NULL}, + /*21*/ {DI_BUTTON, 0, 20, 0, 0, MCancel, 0, NULL, DIF_CENTERGROUP, NULL}}; struct FarDialogItem DialogItems[ARRAYSIZE(InitItems)]; TCHAR Mask[] = _T("99999"); #ifdef UNICODE @@ -394,10 +397,10 @@ static bool ShowDialog(bool bPluginPanels, bool bSelectionPresent) } #ifndef UNICODE - int ExitCode = Info.DialogEx(Info.ModuleNumber, -1, -1, 66, 22, _T("Contents"), DialogItems, + int ExitCode = Info.DialogEx(Info.ModuleNumber, -1, -1, 66, 23, _T("Contents"), DialogItems, ARRAYSIZE(DialogItems), 0, 0, ShowDialogProc, DlgData); #else - HANDLE hDlg = Info.DialogInit(Info.ModuleNumber, -1, -1, 66, 22, _T("Contents"), DialogItems, + HANDLE hDlg = Info.DialogInit(Info.ModuleNumber, -1, -1, 66, 23, _T("Contents"), DialogItems, ARRAYSIZE(DialogItems), 0, 0, ShowDialogProc, DlgData); if (hDlg == INVALID_HANDLE_VALUE) return false; @@ -511,7 +514,10 @@ static int __cdecl PICompare(const void *el1, const void *el2) return 1; } - return -FSF.LStricmp(ppi1->FindData._cFileName, ppi2->FindData._cFileName); + if (Opt.CompareCaseFileNames) + return -FSF.LStrcmp(ppi1->FindData._cFileName, ppi2->FindData._cFileName); + else + return -FSF.LStricmp(ppi1->FindData._cFileName, ppi2->FindData._cFileName); } /**************************************************************************** diff --git a/far2l/far2sdk/farplug-mb.h b/far2l/far2sdk/farplug-mb.h index 758f5fcab..62638d54c 100644 --- a/far2l/far2sdk/farplug-mb.h +++ b/far2l/far2sdk/farplug-mb.h @@ -1497,6 +1497,8 @@ namespace oldfar typedef void (WINAPI *FARSTDLOCALSTRLWR)(char *s1); typedef int (WINAPI *FARSTDLOCALSTRICMP)(const char *s1,const char *s2); typedef int (WINAPI *FARSTDLOCALSTRNICMP)(const char *s1,const char *s2,int n); + typedef int (WINAPI *FARSTDLOCALSTRCMP)(const char *s1,const char *s2); + typedef int (WINAPI *FARSTDLOCALSTRNCMP)(const char *s1,const char *s2,int n); enum PROCESSNAME_FLAGS { diff --git a/far2l/far2sdk/farplug-wide.h b/far2l/far2sdk/farplug-wide.h index cbd5431cc..015560a3b 100644 --- a/far2l/far2sdk/farplug-wide.h +++ b/far2l/far2sdk/farplug-wide.h @@ -1894,6 +1894,8 @@ typedef void (WINAPI *FARSTDLOCALSTRUPR)(wchar_t *s1); typedef void (WINAPI *FARSTDLOCALSTRLWR)(wchar_t *s1); typedef int (WINAPI *FARSTDLOCALSTRICMP)(const wchar_t *s1,const wchar_t *s2); typedef int (WINAPI *FARSTDLOCALSTRNICMP)(const wchar_t *s1,const wchar_t *s2,int n); +typedef int (WINAPI *FARSTDLOCALSTRCMP)(const wchar_t *s1,const wchar_t *s2); +typedef int (WINAPI *FARSTDLOCALSTRNCMP)(const wchar_t *s1,const wchar_t *s2,int n); enum PROCESSNAME_FLAGS { @@ -2082,6 +2084,8 @@ typedef struct FarStandardFunctions FARSTDLOCALSTRLWR LStrlwr; FARSTDLOCALSTRICMP LStricmp; FARSTDLOCALSTRNICMP LStrnicmp; + FARSTDLOCALSTRICMP LStrcmp; + FARSTDLOCALSTRNICMP LStrncmp; FARSTDUNQUOTE Unquote; FARSTDLTRIM LTrim; diff --git a/far2l/src/plug/PluginW.cpp b/far2l/src/plug/PluginW.cpp index 8f8a9a5b8..12a1c4e71 100644 --- a/far2l/src/plug/PluginW.cpp +++ b/far2l/src/plug/PluginW.cpp @@ -419,6 +419,8 @@ void CreatePluginStartupInfo(Plugin *pPlugin, PluginStartupInfo *PSI, FarStandar StandardFunctions.LStrlwr = farStrLower; StandardFunctions.LStricmp = farStrCmpI; StandardFunctions.LStrnicmp = farStrCmpNI; + StandardFunctions.LStrcmp = farStrCmp; + StandardFunctions.LStrncmp = farStrCmpN; StandardFunctions.Unquote = Unquote; StandardFunctions.LTrim = RemoveLeadingSpaces; StandardFunctions.RTrim = RemoveTrailingSpaces; diff --git a/far2l/src/plug/plugapi.cpp b/far2l/src/plug/plugapi.cpp index 32154c287..ab31e9ef8 100644 --- a/far2l/src/plug/plugapi.cpp +++ b/far2l/src/plug/plugapi.cpp @@ -2056,6 +2056,16 @@ int WINAPI farStrCmpI(const wchar_t *s1, const wchar_t *s2) return StrCmpI(s1, s2); } +int WINAPI farStrCmpN(const wchar_t *s1, const wchar_t *s2, int n) +{ + return StrCmpN(s1, s2, n); +} + +int WINAPI farStrCmp(const wchar_t *s1, const wchar_t *s2) +{ + return StrCmp(s1, s2); +} + int WINAPI farIsLower(wchar_t Ch) { return IsLower(Ch); diff --git a/far2l/src/plug/plugapi.hpp b/far2l/src/plug/plugapi.hpp index 6c6f2fbec..25f22a651 100644 --- a/far2l/src/plug/plugapi.hpp +++ b/far2l/src/plug/plugapi.hpp @@ -56,6 +56,8 @@ wchar_t WINAPI farUpper(wchar_t Ch); wchar_t WINAPI farLower(wchar_t Ch); int WINAPI farStrCmpNI(const wchar_t *s1, const wchar_t *s2, int n); int WINAPI farStrCmpI(const wchar_t *s1, const wchar_t *s2); +int WINAPI farStrCmpN(const wchar_t *s1, const wchar_t *s2, int n); +int WINAPI farStrCmp(const wchar_t *s1, const wchar_t *s2); int WINAPI farIsLower(wchar_t Ch); int WINAPI farIsUpper(wchar_t Ch); int WINAPI farIsAlpha(wchar_t Ch);