[FarGroup/FarManager] master: Refactoring, tests (e3f71149b)

0 views
Skip to first unread message

farg...@farmanager.com

unread,
Mar 23, 2026, 6:45:52 PM (4 days ago) Mar 23
to farco...@googlegroups.com
Repository : https://github.com/FarGroup/FarManager
On branch : master
Link : https://github.com/FarGroup/FarManager/commit/e3f71149b41d744cea72f2e471e60b6071fb0d3a

>---------------------------------------------------------------

commit e3f71149b41d744cea72f2e471e60b6071fb0d3a
Author: Alex Alabuzhev <alab...@gmail.com>
Date: Mon Mar 23 22:35:31 2026 +0000

Refactoring, tests


>---------------------------------------------------------------

e3f71149b41d744cea72f2e471e60b6071fb0d3a
far/changelog | 5 +++
far/console.cpp | 106 ++++++++++++++++++++++++++++++++++++++++------------
far/encoding.cpp | 2 +-
far/interf.cpp | 7 +---
far/interf.hpp | 1 -
far/keyboard.cpp | 2 +-
far/platform.fs.cpp | 27 +++++--------
far/platform.fs.hpp | 3 --
far/strmix.cpp | 86 ++++++++++++++++++++++++++++++------------
far/vbuild.m4 | 2 +-
far/vc_crt_fix.asm | 4 ++
11 files changed, 168 insertions(+), 77 deletions(-)

diff --git a/far/changelog b/far/changelog
index e90b70eb2..acfe48d6d 100644
--- a/far/changelog
+++ b/far/changelog
@@ -1,3 +1,8 @@
+--------------------------------------------------------------------------------
+drkns 2026-03-23 22:34:47+00:00 - build 6665
+
+1. Refactoring, tests.
+
--------------------------------------------------------------------------------
drkns 2026-03-21 23:34:45+00:00 - build 6664

diff --git a/far/console.cpp b/far/console.cpp
index d51dee083..432e8afce 100644
--- a/far/console.cpp
+++ b/far/console.cpp
@@ -2155,6 +2155,8 @@ protected:

static size_t GetPaletteVT_partial(std::array<COLORREF, 256>& Palette, size_t const Offset, size_t const Count)
{
+ assert(Offset + Count <= Palette.size());
+
try
{
const auto
@@ -3315,39 +3317,97 @@ NIFTY_DEFINE(console_detail::console, console);

TEST_CASE("console.vt_color")
{
- const auto I = FCF_INDEXMASK;
+ constexpr auto idx = [](COLORREF const Color) { return colors::single_color{Color, true}; };
+ constexpr auto rgb = [](COLORREF const Color) { return colors::single_color{Color, false}; };

- static const struct
+ static constexpr struct
{
- FarColor Color;
- string_view Fg, Bg;
+ colors::single_color Color;
+ string_view Strings[3];
}
Tests[]
{
- { { I, { 0x0 }, { 0x0 } }, L"30"sv, L"40"sv, },
- { { I, { 0x1 }, { 0x1 } }, L"34"sv, L"44"sv, },
- { { I, { 0x7 }, { 0x7 } }, L"37"sv, L"47"sv, },
- { { I, { 0x8 }, { 0x8 } }, L"90"sv, L"100"sv, },
- { { I, { 0x9 }, { 0x9 } }, L"94"sv, L"104"sv, },
- { { I, { 0xF }, { 0xF } }, L"97"sv, L"107"sv, },
- { { I, { 0x10 }, { 0x10 } }, L"38;5;16"sv, L"48;5;16"sv, },
- { { I, { 0xC0 }, { 0xC0 } }, L"38;5;192"sv, L"48;5;192"sv, },
- { { I, { 0xFF }, { 0xFF } }, L"38;5;255"sv, L"48;5;255"sv, },
- { { 0, { 0x000000 }, { 0x000000 } }, L"38;2;0;0;0"sv, L"48;2;0;0;0"sv, },
- { { 0, { 0x123456 }, { 0x654321 } }, L"38;2;86;52;18"sv, L"48;2;33;67;101"sv, },
- { { 0, { 0x00D5FF }, { 0xBB5B00 } }, L"38;2;255;213;0"sv, L"48;2;0;91;187"sv, },
- { { 0, { 0xABCDEF }, { 0xFEDCBA } }, L"38;2;239;205;171"sv, L"48;2;186;220;254"sv, },
- { { 0, { 0xFFFFFF }, { 0xFFFFFF } }, L"38;2;255;255;255"sv, L"48;2;255;255;255"sv, },
+ { idx(0x0), { L"30"sv, L"40"sv, L"58:5:0"sv }, },
+ { idx(0x1), { L"34"sv, L"44"sv, L"58:5:4"sv }, },
+ { idx(0x2), { L"32"sv, L"42"sv, L"58:5:2"sv }, },
+ { idx(0x3), { L"36"sv, L"46"sv, L"58:5:6"sv }, },
+ { idx(0x4), { L"31"sv, L"41"sv, L"58:5:1"sv }, },
+ { idx(0x5), { L"35"sv, L"45"sv, L"58:5:5"sv }, },
+ { idx(0x6), { L"33"sv, L"43"sv, L"58:5:3"sv }, },
+ { idx(0x7), { L"37"sv, L"47"sv, L"58:5:7"sv }, },
+ { idx(0x8), { L"90"sv, L"100"sv, L"58:5:8"sv }, },
+ { idx(0x9), { L"94"sv, L"104"sv, L"58:5:12"sv }, },
+ { idx(0xA), { L"92"sv, L"102"sv, L"58:5:10"sv }, },
+ { idx(0xB), { L"96"sv, L"106"sv, L"58:5:14"sv }, },
+ { idx(0xC), { L"91"sv, L"101"sv, L"58:5:9"sv }, },
+ { idx(0xD), { L"95"sv, L"105"sv, L"58:5:13"sv }, },
+ { idx(0xE), { L"93"sv, L"103"sv, L"58:5:11"sv }, },
+ { idx(0xF), { L"97"sv, L"107"sv, L"58:5:15"sv }, },
+ { idx(0x10), { L"38;5;16"sv, L"48;5;16"sv, L"58:5:16"sv }, },
+ { idx(0xC0), { L"38;5;192"sv, L"48;5;192"sv, L"58:5:192"sv }, },
+ { idx(0xFF), { L"38;5;255"sv, L"48;5;255"sv, L"58:5:255"sv }, },
+ { rgb(0x000000), { L"38;2;0;0;0"sv, L"48;2;0;0;0"sv, L"58:2::0:0:0"sv }, },
+ { rgb(0x010203), { L"38;2;3;2;1"sv, L"48;2;3;2;1"sv, L"58:2::3:2:1"sv }, },
+ { rgb(0x123456), { L"38;2;86;52;18"sv, L"48;2;86;52;18"sv, L"58:2::86:52:18"sv }, },
+ { rgb(0x654321), { L"38;2;33;67;101"sv, L"48;2;33;67;101"sv, L"58:2::33:67:101"sv }, },
+ { rgb(0x00D5FF), { L"38;2;255;213;0"sv, L"48;2;255;213;0"sv, L"58:2::255:213:0"sv }, },
+ { rgb(0xBB5B00), { L"38;2;0;91;187"sv, L"48;2;0;91;187"sv, L"58:2::0:91:187"sv }, },
+ { rgb(0xABCDEF), { L"38;2;239;205;171"sv, L"48;2;239;205;171"sv, L"58:2::239:205:171"sv }, },
+ { rgb(0xFEDCBA), { L"38;2;186;220;254"sv, L"48;2;186;220;254"sv, L"58:2::186:220:254"sv }, },
+ { rgb(0xFFFFFF), { L"38;2;255;255;255"sv, L"48;2;255;255;255"sv, L"58:2::255:255:255"sv }, },
};

for (const auto& i: Tests)
{
- string Str[2];
- console_detail::make_vt_color(colors::single_color::foreground(i.Color), console_detail::colors_mapping_type::foreground, Str[0]);
- console_detail::make_vt_color(colors::single_color::background(i.Color), console_detail::colors_mapping_type::background, Str[1]);
- REQUIRE(Str[0] == i.Fg);
- REQUIRE(Str[1] == i.Bg);
+ for (const auto& Str: i.Strings)
+ {
+ string Result;
+ console_detail::make_vt_color(i.Color, static_cast<console_detail::colors_mapping_type>(&Str - i.Strings), Result);
+ REQUIRE(Str == Result);
+ }
+ }
+}
+
+TEST_CASE("console.vt_style")
+{
+ static constexpr struct tests
+ {
+ FARCOLORFLAGS Style;
+ string_view On, Off;
}
+ Tests[]
+ {
+ { FCF_FG_BOLD, L"1"sv, L"22"sv },
+ { FCF_FG_ITALIC, L"3"sv, L"23"sv },
+ { FCF_FG_OVERLINE, L"53"sv, L"55"sv },
+ { FCF_FG_STRIKEOUT, L"9"sv, L"29"sv },
+ { FCF_FG_FAINT, L"2"sv, L"22"sv },
+ { FCF_FG_BLINK, L"5"sv, L"25"sv },
+ { FCF_INVERSE, L"7"sv, L"27"sv },
+ { FCF_FG_INVISIBLE, L"8"sv, L"28"sv },
+ };
+
+ for (const auto& i: Tests)
+ {
+ string On, Off;
+ console_detail::make_vt_style(i.Style, On, 0);
+ console_detail::make_vt_style(0, Off, i.Style);
+ REQUIRE(i.On == On);
+ REQUIRE(i.Off == Off);
+ }
+
+ const auto AllStyles = static_cast<FARCOLORFLAGS>(-1);
+
+ const auto
+ AllOn = join(L";"sv, Tests | std::views::transform(&tests::On)),
+ AllOff = join(L";"sv, Tests | std::views::transform(&tests::Off));
+
+ string On, Off;
+ console_detail::make_vt_style(AllStyles, On, 0);
+ console_detail::make_vt_style(0, Off, AllStyles);
+
+ REQUIRE(AllOn == On);
+ REQUIRE(AllOff == Off);
}

TEST_CASE("console.vt_sequence")
diff --git a/far/encoding.cpp b/far/encoding.cpp
index 6ba942761..606be3905 100644
--- a/far/encoding.cpp
+++ b/far/encoding.cpp
@@ -621,7 +621,7 @@ string encoding::utf8_or_ansi::get_chars(std::string_view const Str, diagnostics

string encoding::ascii::get_chars(std::string_view const Str)
{
- assert(std::ranges::all_of(Str, [](char const Char) { return Char < 128; }));
+ assert(std::ranges::all_of(Str, [](unsigned char const Char) { return Char < 128; }));

return { ALL_CONST_RANGE(Str) };
}
diff --git a/far/interf.cpp b/far/interf.cpp
index dbd53cd33..f3ee65023 100644
--- a/far/interf.cpp
+++ b/far/interf.cpp
@@ -402,7 +402,7 @@ void CloseConsole()
MoveRealCursor(0, ScrY);
console.SetCursorInfo(InitialCursorInfo);

- SetRealColor(colors::default_color());
+ console.SetTextAttributes(colors::default_color());

if (InitialConsoleMode)
{
@@ -1333,11 +1333,6 @@ void SetColor(const FarColor& Color)
CurColor=Color;
}

-void SetRealColor(const FarColor& Color)
-{
- console.SetTextAttributes(Color);
-}
-
const FarColor& GetColor()
{
return CurColor;
diff --git a/far/interf.hpp b/far/interf.hpp
index 92fb290cf..2422b4482 100644
--- a/far/interf.hpp
+++ b/far/interf.hpp
@@ -229,7 +229,6 @@ void DropShadow(rectangle Where);
void SetColor(int Color);
void SetColor(PaletteColors Color);
void SetColor(const FarColor& Color);
-void SetRealColor(const FarColor& Color);
const FarColor& GetColor();

void Box(rectangle Where, const FarColor& Color,int Type);
diff --git a/far/keyboard.cpp b/far/keyboard.cpp
index 7f6807050..fca6a9b7f 100644
--- a/far/keyboard.cpp
+++ b/far/keyboard.cpp
@@ -1533,7 +1533,7 @@ string KeyToLocalizedText(unsigned int const Key)

string KeysListToLocalizedText(std::span<unsigned int const> const Keys)
{
- return join(L" "sv, Keys | std::views::transform([](unsigned int const Key){ return KeyToLocalizedText(Key); }));
+ return join(L" "sv, Keys | std::views::transform(&KeyToLocalizedText));
}

static int key_to_vk(unsigned int const Key)
diff --git a/far/platform.fs.cpp b/far/platform.fs.cpp
index 05045d19f..0d31e3885 100644
--- a/far/platform.fs.cpp
+++ b/far/platform.fs.cpp
@@ -203,11 +203,6 @@ namespace os::fs
return { Letter, L':' };
}

- string get_device_path(size_t const Number)
- {
- return { get_letter(Number), L':' };
- }
-
string get_win32nt_device_path(wchar_t Letter)
{
return { L'\\', L'\\', L'?', L'\\', Letter, L':' };
@@ -2638,17 +2633,16 @@ TEST_CASE("drives")
{
wchar_t DriveLetter;
string_view DriveDevicePath, Win32NtDriveDevicePath, DriveRootDirectory, Win32NtDriveRootDirectory;
- bool Standard;
- size_t Number;
+ std::optional<size_t> Number;
}
Tests[]
{
- { L'A', L"A:"sv, L"\\\\?\\A:"sv, L"A:\\"sv, L"\\\\?\\A:\\"sv, true, 0, },
- { L'B', L"B:"sv, L"\\\\?\\B:"sv, L"B:\\"sv, L"\\\\?\\B:\\"sv, true, 1, },
- { L'C', L"C:"sv, L"\\\\?\\C:"sv, L"C:\\"sv, L"\\\\?\\C:\\"sv, true, 2, },
- { L'Z', L"Z:"sv, L"\\\\?\\Z:"sv, L"Z:\\"sv, L"\\\\?\\Z:\\"sv, true, 25, },
- { L'1', L"1:"sv, L"\\\\?\\1:"sv, L"1:\\"sv, L"\\\\?\\1:\\"sv, false, 42, },
- { L'λ', L"λ:"sv, L"\\\\?\\λ:"sv, L"λ:\\"sv, L"\\\\?\\λ:\\"sv, false, 42, },
+ { L'A', L"A:"sv, L"\\\\?\\A:"sv, L"A:\\"sv, L"\\\\?\\A:\\"sv, 0, },
+ { L'B', L"B:"sv, L"\\\\?\\B:"sv, L"B:\\"sv, L"\\\\?\\B:\\"sv, 1, },
+ { L'C', L"C:"sv, L"\\\\?\\C:"sv, L"C:\\"sv, L"\\\\?\\C:\\"sv, 2, },
+ { L'Z', L"Z:"sv, L"\\\\?\\Z:"sv, L"Z:\\"sv, L"\\\\?\\Z:\\"sv, 25, },
+ { L'1', L"1:"sv, L"\\\\?\\1:"sv, L"1:\\"sv, L"\\\\?\\1:\\"sv, {}, },
+ { L'λ', L"λ:"sv, L"\\\\?\\λ:"sv, L"λ:\\"sv, L"\\\\?\\λ:\\"sv, {}, },
};

for (const auto& i: Tests)
@@ -2659,13 +2653,12 @@ TEST_CASE("drives")
REQUIRE(osd::get_win32nt_device_path(i.DriveLetter) == i.Win32NtDriveDevicePath);
REQUIRE(osd::get_root_directory(i.DriveLetter) == i.DriveRootDirectory);
REQUIRE(osd::get_win32nt_root_directory(i.DriveLetter) == i.Win32NtDriveRootDirectory);
- REQUIRE(osd::is_standard_letter(i.DriveLetter) == i.Standard);
+ REQUIRE(osd::is_standard_letter(i.DriveLetter) == i.Number.has_value());

- if (i.Standard)
+ if (i.Number)
{
REQUIRE(osd::get_number(i.DriveLetter) == i.Number);
- REQUIRE(osd::get_letter(i.Number) == i.DriveLetter);
- REQUIRE(osd::get_device_path(i.Number) == i.DriveDevicePath);
+ REQUIRE(osd::get_letter(*i.Number) == i.DriveLetter);
}
}
}
diff --git a/far/platform.fs.hpp b/far/platform.fs.hpp
index b9d12e699..57457c09e 100644
--- a/far/platform.fs.hpp
+++ b/far/platform.fs.hpp
@@ -121,9 +121,6 @@ namespace os::fs
[[nodiscard]]
string get_device_path(wchar_t Letter);

- [[nodiscard]]
- string get_device_path(size_t Number);
-
[[nodiscard]]
string get_win32nt_device_path(wchar_t Letter);

diff --git a/far/strmix.cpp b/far/strmix.cpp
index f4ea7f908..1a5405f00 100644
--- a/far/strmix.cpp
+++ b/far/strmix.cpp
@@ -103,26 +103,6 @@ string GroupDigitsInvariant(unsigned long long Value)
return GroupDigitsImpl(Value, invariant_locale());
}

-static wchar_t* legacy_InsertQuotes(wchar_t *Str)
-{
- const auto QuoteChar = L'"';
- size_t l = std::wcslen(Str);
-
- if (*Str != QuoteChar)
- {
- std::copy_n(Str, ++l, Str + 1);
- *Str=QuoteChar;
- }
-
- if (l==1 || Str[l-1] != QuoteChar)
- {
- Str[l++] = QuoteChar;
- Str[l] = 0;
- }
-
- return Str;
-}
-
string InsertRegexpQuote(string strStr)
{
//выражение вида /regexp/i не дополняем слешами
@@ -137,8 +117,29 @@ string InsertRegexpQuote(string strStr)

wchar_t* legacy::QuoteSpaceOnly(wchar_t* Str)
{
- if (contains(Str, L' '))
- legacy_InsertQuotes(Str);
+ if (!contains(Str, L' '))
+ return Str;
+
+ const auto QuoteChar = L'"';
+
+ const auto
+ Begin = Str,
+ End = Str + std::wcslen(Str);
+
+ const auto StartsWithQuote = *Begin == QuoteChar;
+
+ if (!StartsWithQuote)
+ {
+ std::copy_backward(Begin, End + 1, End + 2);
+ *Begin = QuoteChar;
+ }
+
+ const auto NewEnd = End + !StartsWithQuote;
+ if (*(NewEnd - 1) != QuoteChar)
+ {
+ *NewEnd = QuoteChar;
+ *(NewEnd + 1) = L'\0';
+ }

return Str;
}
@@ -1418,6 +1419,10 @@ string HexMask(size_t ByteCount)
template<typename T>
static void xncpy(T* dest, const T* src, size_t DestSize)
{
+ assert(src);
+ assert(dest);
+ assert(DestSize);
+
while (DestSize > 1 && (*dest++ = *src++) != 0)
{
DestSize--;
@@ -1462,6 +1467,38 @@ TEST_CASE("InsertRegexpQuote")
}
}

+TEST_CASE("QuoteSpaceOnly")
+{
+ static const struct
+ {
+ string_view Str, Result;
+ }
+ Tests[]
+ {
+ {},
+ { L"!"sv, L"!"sv },
+ { L" ["sv, L"\" [\""sv },
+ { L"] "sv, L"\"] \""sv },
+ { L"[ ]"sv, L"\"[ ]\""sv },
+ { L" | "sv, L"\" | \""sv },
+ { L"\""sv, L"\""sv },
+ { L"\"<"sv, L"\"<"sv },
+ { L"\"< "sv, L"\"< \""sv },
+ { L">\""sv, L">\""sv },
+ { L" >\""sv, L"\" >\""sv },
+ };
+
+ for (const auto& i: Tests)
+ {
+ wchar_t Buffer[256];
+ assert(i.Str.size() < std::size(Buffer));
+
+ *std::ranges::copy(i.Str, Buffer).out = L'\0';
+ REQUIRE(legacy::QuoteSpaceOnly(Buffer) == i.Result);
+ }
+}
+
+
TEST_CASE("ConvertFileSizeString")
{
constexpr auto
@@ -1494,8 +1531,8 @@ TEST_CASE("ConvertFileSizeString")
{ L"2G"sv, 2 * G },
{ L"3T"sv, 3 * T },
{ L"42P"sv, 42 * P },
- { L"12E"sv, 12 * E },
{ L"0E"sv, 0 * E },
+ { L"18E"sv, 18 * E },
};

for (const auto& i: Tests)
@@ -1519,6 +1556,7 @@ TEST_CASE("ReplaceBrackets")
{ L"dorime"sv },
{ L"meow"sv, L"${a }$cat$"sv, {}, {}, {}, L"Invalid group name"sv },
{ L"Ni!"sv, L"$0$0$0"sv, L"Ni!Ni!Ni!"sv, { { 0, 3 } } },
+ { L"pe"sv, L"$$$0$0$$"sv, L"$pepe$"sv, { { 0, 2} } },
{ L"Fus Ro Dah"sv, L"$3-${first}-$2-$1-${oops$"sv, L"Dah-Fus-Ro-Fus-${oops$"sv, { { 0, 10 }, { 0, 3 }, { 4, 6 }, { 7, 10 } }, { { L"first"sv, 1 } } },
{ L"foobar"sv, L"${name2}-${name1}"sv, L"-foo"sv, { { 0, 3 }, { 0, 3 }, { 3, 3 } }, { { L"name1"sv, 1 }, { L"name2"sv, 2 } } },
};
@@ -2241,7 +2279,7 @@ TEST_CASE("xwcsncpy")

const auto MaxBufferSize = std::ranges::fold_left(Tests, 0uz, [](size_t const Value, auto const& Item){ return std::max(Value, Item.Src.size()); }) + 1;

- for (const auto BufferSize: std::views::iota(0uz, MaxBufferSize + 1))
+ for (const auto BufferSize: std::views::iota(1uz, MaxBufferSize + 1))
{
for (const auto& i: Tests)
{
diff --git a/far/vbuild.m4 b/far/vbuild.m4
index 23083da15..c5bb2ec1d 100644
--- a/far/vbuild.m4
+++ b/far/vbuild.m4
@@ -1 +1 @@
-6664
+6665
diff --git a/far/vc_crt_fix.asm b/far/vc_crt_fix.asm
index b9af5667c..1d47488ca 100644
--- a/far/vc_crt_fix.asm
+++ b/far/vc_crt_fix.asm
@@ -44,7 +44,11 @@ else
endif

WRAPPER proto stdcall DARGS
+ifdef X64
IMP dq WRAPPER
+else
+ IMP dd WRAPPER
+endif
public IMP
ENDM



Reply all
Reply to author
Forward
0 new messages