From 34dcb538f3239ab0adae6f50bc901a72f46e15bc Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Mon, 6 Nov 2023 18:36:02 +0000 Subject: [PATCH 01/16] Clang Fix build Fix warnings Remove outdated workarounds Bump version --- far/colormix.cpp | 4 ++-- far/common.tests.cpp | 3 +-- far/common/chrono.hpp | 2 +- far/common/enum_tokens.hpp | 3 +-- far/dialog.cpp | 4 +--- far/disabled_warnings.hpp | 1 + far/exception_handler.cpp | 14 ++++++++------ far/filepanels.cpp | 2 ++ far/filepanels.hpp | 1 + far/findfile.cpp | 4 +--- far/headers.hpp | 4 ++-- far/hook_wow64.cpp | 6 ++++++ far/imports.cpp | 4 ---- far/imports.hpp | 3 --- far/notification.cpp | 6 +----- far/platform.chrono.hpp | 2 +- far/platform.com.cpp | 5 +---- far/tinyxml.cpp | 1 + far/tracer.cpp | 9 ++++++--- 19 files changed, 37 insertions(+), 41 deletions(-) diff --git a/far/colormix.cpp b/far/colormix.cpp index 1dc382e1d1b..77db9eac8db 100644 --- a/far/colormix.cpp +++ b/far/colormix.cpp @@ -838,8 +838,8 @@ TEST_CASE("colors.default") FarColor Color { 0, - 0xFFFFFFFF, - 0xFFFFFFFF, + { 0xFFFFFFFF }, + { 0xFFFFFFFF }, }; REQUIRE(!Color.IsFgDefault()); diff --git a/far/common.tests.cpp b/far/common.tests.cpp index 8e55ca748d7..d45331a4f4e 100644 --- a/far/common.tests.cpp +++ b/far/common.tests.cpp @@ -1112,10 +1112,9 @@ TEST_CASE("range.static") { const auto TestImpl = [](auto& ContainerVersion) { - auto Range = range(ContainerVersion); - const auto TestType = [&](const auto & ContainerGetter, const auto & RangeGetter) { + range const Range(ContainerVersion); STATIC_REQUIRE(std::same_as); }; diff --git a/far/common/chrono.hpp b/far/common/chrono.hpp index 12ef222f91c..9e5196eb1ed 100644 --- a/far/common/chrono.hpp +++ b/far/common/chrono.hpp @@ -74,7 +74,7 @@ class split_duration: public std::tuple inline namespace literals { [[nodiscard]] - consteval auto operator"" _d(unsigned long long const Value) noexcept + consteval auto operator""_d(unsigned long long const Value) noexcept { return std::chrono::days(Value); } diff --git a/far/common/enum_tokens.hpp b/far/common/enum_tokens.hpp index 03ba6aa334b..2ad3c2abfdb 100644 --- a/far/common/enum_tokens.hpp +++ b/far/common/enum_tokens.hpp @@ -83,8 +83,7 @@ namespace detail auto& get_opt() { constexpr auto HasOperation = requires { operation>(); }; - // This idiotic cast to std::tuple is for clang - return std::get(static_cast(*this)); + return std::get(*this); } template diff --git a/far/dialog.cpp b/far/dialog.cpp index a434c70696b..aaccca6b9e1 100644 --- a/far/dialog.cpp +++ b/far/dialog.cpp @@ -382,9 +382,7 @@ void Dialog::Construct(span const SrcItems) { for (const auto& [ItemAuto, SrcItemAuto]: zip(Item.Auto, SrcItem.Auto)) { - // https://github.com/llvm/llvm-project/issues/54300 - // TODO: remove once we have it. - const auto SrcItemIterator = std::find_if(ALL_CONST_RANGE(SrcItems), [&SrcItemAuto = SrcItemAuto](const DialogItemEx& i) + const auto SrcItemIterator = std::find_if(ALL_CONST_RANGE(SrcItems), [&](const DialogItemEx& i) { return &i == SrcItemAuto.Owner; }); diff --git a/far/disabled_warnings.hpp b/far/disabled_warnings.hpp index bc3eefa7c10..534c4831fd1 100644 --- a/far/disabled_warnings.hpp +++ b/far/disabled_warnings.hpp @@ -154,6 +154,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma clang diagnostic ignored "-Wreserved-id-macro" #pragma clang diagnostic ignored "-Wshadow-field-in-constructor" #pragma clang diagnostic ignored "-Wshadow-field" +#pragma clang diagnostic ignored "-Wshadow-uncaptured-local" #pragma clang diagnostic ignored "-Wsign-conversion" #pragma clang diagnostic ignored "-Wswitch-enum" #pragma clang diagnostic ignored "-Wundefined-func-template" diff --git a/far/exception_handler.cpp b/far/exception_handler.cpp index 5c71105bef6..873247baada 100644 --- a/far/exception_handler.cpp +++ b/far/exception_handler.cpp @@ -306,12 +306,8 @@ static bool write_minidump(const exception_context& Context, string_view const F struct writer_context { DWORD const ThreadId{ GetCurrentThreadId() }; - } - WriterContext; - MINIDUMP_CALLBACK_INFORMATION Mci - { - [](void* const Param, MINIDUMP_CALLBACK_INPUT* const Input, MINIDUMP_CALLBACK_OUTPUT*) + static BOOL WINAPI callback(void* const Param, MINIDUMP_CALLBACK_INPUT* const Input, MINIDUMP_CALLBACK_OUTPUT*) { const auto& Ctx = *static_cast(Param); @@ -319,7 +315,13 @@ static bool write_minidump(const exception_context& Context, string_view const F return FALSE; return TRUE; - }, + } + } + WriterContext; + + MINIDUMP_CALLBACK_INFORMATION Mci + { + &writer_context::callback, &WriterContext }; diff --git a/far/filepanels.cpp b/far/filepanels.cpp index 69867cc91f0..eaf703c7842 100644 --- a/far/filepanels.cpp +++ b/far/filepanels.cpp @@ -77,6 +77,8 @@ FilePanels::FilePanels(private_tag): { } +FilePanels::~FilePanels() = default; + filepanels_ptr FilePanels::create(bool CreateRealPanels, int DirCount) { const auto FilePanelsPtr = std::make_shared(private_tag()); diff --git a/far/filepanels.hpp b/far/filepanels.hpp index 55f551c4a9d..dd1622632b4 100644 --- a/far/filepanels.hpp +++ b/far/filepanels.hpp @@ -59,6 +59,7 @@ class FilePanels final: public window, public ViewerContainer static filepanels_ptr create(bool CreateRealPanels, int DirCount); explicit FilePanels(private_tag); + ~FilePanels() override; bool ProcessKey(const Manager::Key& Key) override; bool ProcessMouse(const MOUSE_EVENT_RECORD *MouseEvent) override; diff --git a/far/findfile.cpp b/far/findfile.cpp index 88dcd907cad..6927d799527 100644 --- a/far/findfile.cpp +++ b/far/findfile.cpp @@ -552,9 +552,7 @@ void background_searcher::InitInFileSearch() if (Value & (hasSelected? CPST_FIND : CPST_FAVORITE)) { // Проверяем дубли - // https://github.com/llvm/llvm-project/issues/54300 - // TODO: remove once we have it. - if (hasSelected || !std::any_of(ALL_CONST_RANGE(m_CodePages), [&Name = Name](const CodePageInfo& cp) { return cp.CodePage == Name; })) + if (hasSelected || !std::any_of(ALL_CONST_RANGE(m_CodePages), [&](const CodePageInfo& cp) { return cp.CodePage == Name; })) m_CodePages.emplace_back(Name); } } diff --git a/far/headers.hpp b/far/headers.hpp index d2618704a22..81813217bc6 100644 --- a/far/headers.hpp +++ b/far/headers.hpp @@ -41,8 +41,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #error Visual C++ 2019 Update 16.11.24 (or higher) required #elif !CHECK_COMPILER(GCC, 10, 0, 0) #error GCC 10.0.0 (or higher) required -#elif !CHECK_COMPILER(CLANG, 10, 0, 0) -#error Clang 10.0.0 (or higher) required +#elif !CHECK_COMPILER(CLANG, 16, 0, 0) +#error Clang 16.0.0 (or higher) required #endif #ifdef __GNUC__ diff --git a/far/hook_wow64.cpp b/far/hook_wow64.cpp index 64e0eec7134..d7eaaedb358 100644 --- a/far/hook_wow64.cpp +++ b/far/hook_wow64.cpp @@ -69,6 +69,9 @@ static struct } Error; +WARNING_PUSH() +WARNING_DISABLE_GCC("-Wmissing-declarations") +WARNING_DISABLE_CLANG("-Wmissing-prototypes") std::pair get_hook_wow64_error() { static const string_view Messages[] @@ -92,6 +95,7 @@ std::pair get_hook_wow64_error() return { Messages[static_cast(Error.Hook)], Error.Win32 }; } +WARNING_POP() static thread_local void* SavedState; @@ -389,7 +393,9 @@ __attribute__((section(".CRT$XLY"))) WARNING_POP() +#if COMPILER(CL) // for ulink #pragma comment(linker, "/include:_hook_wow64_tlscb") +#endif #endif diff --git a/far/imports.cpp b/far/imports.cpp index bc05721c8e0..256fe90a619 100644 --- a/far/imports.cpp +++ b/far/imports.cpp @@ -53,10 +53,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace imports_detail { - imports::imports() - { - } - void* imports::get_pointer_impl(os::rtdl::module const& Module, const char* Name) { // imports is the lowest level. Everything else depends on it, including logging. diff --git a/far/imports.hpp b/far/imports.hpp index 1fd605f4d5e..7d1b2b1df1f 100644 --- a/far/imports.hpp +++ b/far/imports.hpp @@ -52,9 +52,6 @@ namespace imports_detail class imports { -public: - imports(); - private: #define MODULE(MODULE) m_##MODULE{WIDE_SV(#MODULE)} diff --git a/far/notification.cpp b/far/notification.cpp index cd77f8adb04..6852c1c7e33 100644 --- a/far/notification.cpp +++ b/far/notification.cpp @@ -180,13 +180,9 @@ bool message_manager::dispatch() const auto& [EventId, Payload] = EventData; - // https://github.com/llvm/llvm-project/issues/54300 - // TODO: remove once we have it. - const auto& EventIdRef = EventId; - const auto find_eligible_from = [&](handlers_map const& Handlers) { - for (const auto& [Key, Value]: range(Handlers.equal_range(EventIdRef))) + for (const auto& [Key, Value]: range(Handlers.equal_range(EventId))) { EligibleHandlers.emplace(Value, false); } diff --git a/far/platform.chrono.hpp b/far/platform.chrono.hpp index cf05c6dbfa6..acde402120a 100644 --- a/far/platform.chrono.hpp +++ b/far/platform.chrono.hpp @@ -105,7 +105,7 @@ namespace os::chrono namespace literals { [[nodiscard]] - consteval auto operator"" _hns(unsigned long long const Value) noexcept + consteval auto operator""_hns(unsigned long long const Value) noexcept { return hectonanoseconds(Value); } diff --git a/far/platform.com.cpp b/far/platform.com.cpp index 70934690acc..29452dc7605 100644 --- a/far/platform.com.cpp +++ b/far/platform.com.cpp @@ -142,10 +142,7 @@ namespace os::com COM_INVOKE(imports.SHCreateAssociationRegistration, (IID_IApplicationAssociationRegistration, IID_PPV_ARGS_Helper(&ptr_setter(AAR)))); memory Association; - // https://github.com/llvm/llvm-project/issues/54300 - // TODO: remove once we have it. - const auto& ExtRef = Ext; - COM_INVOKE(AAR->QueryCurrentDefault, (null_terminated(ExtRef).c_str(), AT_FILEEXTENSION, AL_EFFECTIVE, &ptr_setter(Association))); + COM_INVOKE(AAR->QueryCurrentDefault, (null_terminated(Ext).c_str(), AT_FILEEXTENSION, AL_EFFECTIVE, &ptr_setter(Association))); return Association.get(); } diff --git a/far/tinyxml.cpp b/far/tinyxml.cpp index 830961bb7cc..a9f115b94fd 100644 --- a/far/tinyxml.cpp +++ b/far/tinyxml.cpp @@ -58,6 +58,7 @@ WARNING_DISABLE_MSC(5262) // implicit fall-through occurs here; are you missing WARNING_DISABLE_GCC("-Wdouble-promotion") WARNING_DISABLE_GCC("-Wimplicit-fallthrough") WARNING_DISABLE_GCC("-Wold-style-cast") +WARNING_DISABLE_GCC("-Wundef") WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant") WARNING_DISABLE_CLANG("-Weverything") diff --git a/far/tracer.cpp b/far/tracer.cpp index 3ed90d3a91f..49944a41e41 100644 --- a/far/tracer.cpp +++ b/far/tracer.cpp @@ -60,9 +60,12 @@ static auto format_address(uintptr_t const Value) { // It is unlikely that RVAs will be above 4 GiB, // so we can save some screen space here. - const auto Width = Value > std::numeric_limits::max()? - width_in_hex_chars : - width_in_hex_chars; + const auto Width = +#ifdef _WIN64 + Value > std::numeric_limits::max()? + width_in_hex_chars : +#endif + width_in_hex_chars; return far::format(L"{:0{}X}"sv, Value, Width); } From 2a1cc45628fcc867e6816348541aa746fbcb6dbe Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Mon, 6 Nov 2023 18:36:02 +0000 Subject: [PATCH 02/16] Refactoring --- far/api_test.c | 7 + far/color_picker.cpp | 674 +++++++++++++++++++++------------------ far/color_picker_256.cpp | 32 +- far/color_picker_rgb.cpp | 65 ++-- far/colormix.cpp | 93 ++++-- far/colormix.hpp | 14 + far/console.cpp | 292 +++++++++-------- far/console.hpp | 3 +- far/far.vcxproj | 48 +-- far/far.vcxproj.filters | 41 +-- far/hilight.cpp | 18 +- far/palette.cpp | 3 +- far/scrbuf.cpp | 21 +- 13 files changed, 691 insertions(+), 620 deletions(-) diff --git a/far/api_test.c b/far/api_test.c index 65620219ef7..f6479074e17 100644 --- a/far/api_test.c +++ b/far/api_test.c @@ -33,3 +33,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Include/plugin.hpp" #include "Include/farcolor.hpp" + +#ifdef __cplusplus +static_assert(FCF_INDEXMASK == (FCF_FG_INDEX | FCF_BG_INDEX)); +static_assert(FCF_FG_4BIT == FCF_FG_INDEX); +static_assert(FCF_BG_4BIT == FCF_BG_INDEX); +static_assert(FCF_4BITMASK == FCF_INDEXMASK); +#endif diff --git a/far/color_picker.cpp b/far/color_picker.cpp index f365b90bbe2..53c9f137f49 100644 --- a/far/color_picker.cpp +++ b/far/color_picker.cpp @@ -85,12 +85,12 @@ static_assert(std::size(control_by_color) == std::size(IndexColors)); static constexpr auto color_by_control = column_major_iota(); static_assert(std::size(color_by_control) == std::size(IndexColors)); -static string color_code(COLORREF const Color, bool const IsIndex, bool const IsDefault) +static auto color_code(colors::single_color const Color) { - return IsIndex? IsDefault? - far::format(L"{:02X} "sv, colors::alpha_value(Color)) : - far::format(L"{:02X} {:02X}"sv, colors::alpha_value(Color), colors::index_value(Color)) : - far::format(L"{:08X}"sv, colors::ARGB2ABGR(Color)); + return Color.IsIndex? colors::is_default(Color.Value)? + far::format(L"{:02X} "sv, colors::alpha_value(Color.Value)) : + far::format(L"{:02X} {:02X}"sv, colors::alpha_value(Color.Value), colors::index_value(Color.Value)) : + far::format(L"{:08X}"sv, colors::ARGB2ABGR(Color.Value)); } static std::optional parse_color(string_view const Str, bool const IsIndex) @@ -123,318 +123,306 @@ static std::optional parse_color(string_view const Str, bool const IsI static bool IgnoreEditChange = false; static bool IgnoreColorIndexClick = false; -struct color_state -{ - FarColor CurColor, BaseColor; - bool TransparencyEnabled; -}; - constexpr auto MaskIndex = L"HH HH"sv, MaskARGB = L"HHHHHHHH"sv, MaskDef = L"HH "sv; -enum color_dialog_items +namespace color_basic +{ + enum controls + { + color_text, + color_active_checkbox, + color_first_radio, + color_last_radio = color_first_radio + colors::index::nt_last + 1, + color_default_radio = color_last_radio, + color_default_text, + + colorcode_text, + colorcode_edit, + + button_256, + button_rgb, + + count + }; +} + +namespace cb = color_basic; + +namespace color_dialog { - cd_border, - - cd_separator_before_hint, - cd_separator_before_buttons, - cd_separator_vertical_before_style, - cd_separator_after_foreground, - cd_separator_after_background, - cd_separator_style, - - cd_fg_text, - cd_fg_active, - cd_fg_color_first, - cd_fg_color_last = cd_fg_color_first + colors::index::nt_last + 1, - cd_fg_color_default = cd_fg_color_last, - cd_fg_color_default_label, - - cd_fg_colorcode_title, - cd_fg_colorcode, - cd_fg_256, - cd_fg_rgb, - - cd_bg_text, - cd_bg_active, - cd_bg_color_first, - cd_bg_color_last = cd_bg_color_first + colors::index::nt_last + 1, - cd_bg_color_default = cd_bg_color_last, - cd_bg_color_default_label, - - cd_bg_colorcode_title, - cd_bg_colorcode, - cd_bg_256, - cd_bg_rgb, - - cd_style, - cd_style_first, - cd_style_inherit = cd_style_first, - cd_style_bold, - cd_style_italic, - cd_style_underline, - cd_style_underline2, - cd_style_overline, - cd_style_strikeout, - cd_style_faint, - cd_style_blink, - cd_style_inverse, - cd_style_invisible, - cd_style_last = cd_style_invisible, - - cd_sample_first, - cd_sample_last = cd_sample_first + 2, - - cd_vt_hint_text_intro, - cd_vt_hint_text_supported, - cd_vt_hint_text_not_supported, - - cd_button_ok, - cd_button_reset, - cd_button_enable_vt, - cd_button_cancel, - - cd_count + enum controls + { + border, + + separator_before_hint, + separator_before_buttons, + separator_vertical_before_style, + separator_after_foreground, + separator_after_background, + separator_style, + + fg_first, + fg_last = fg_first + cb::count - 1, + + bg_first, + bg_last = bg_first + cb::count - 1, + + style_text, + style_checkbox_first, + style_checkbox_inherit = style_checkbox_first, + style_checkbox_bold, + style_checkbox_italic, + style_checkbox_underline, + style_checkbox_underline2, + style_checkbox_overline, + style_checkbox_strikeout, + style_checkbox_faint, + style_checkbox_blink, + style_checkbox_inverse, + style_checkbox_invisible, + style_checkbox_last = style_checkbox_invisible, + + sample_text_first, + sample_text_last = sample_text_first + 2, + + vt_hint_text_intro, + vt_hint_text_supported, + vt_hint_text_not_supported, + + button_ok, + button_reset, + button_enable_vt, + button_cancel, + + count + }; +} + +namespace cd = color_dialog; + +static consteval auto fg_item(cb::controls const Item) +{ + return static_cast(cd::fg_first + static_cast(Item)); +} + +static consteval auto bg_item(cb::controls const Item) +{ + return static_cast(cd::bg_first + static_cast(Item)); +} + +static const std::pair StyleMapping[] +{ + { cd::style_checkbox_inherit, FCF_INHERIT_STYLE }, + { cd::style_checkbox_bold, FCF_FG_BOLD }, + { cd::style_checkbox_italic, FCF_FG_ITALIC }, + { cd::style_checkbox_underline, FCF_FG_UNDERLINE }, + { cd::style_checkbox_underline2, FCF_FG_UNDERLINE2 }, + { cd::style_checkbox_overline, FCF_FG_OVERLINE }, + { cd::style_checkbox_strikeout, FCF_FG_STRIKEOUT }, + { cd::style_checkbox_faint, FCF_FG_FAINT }, + { cd::style_checkbox_blink, FCF_FG_BLINK }, + { cd::style_checkbox_inverse, FCF_FG_INVERSE }, + { cd::style_checkbox_invisible, FCF_FG_INVISIBLE }, }; -static const std::pair StyleMapping[] +struct single_color_state { - { cd_style_inherit, FCF_INHERIT_STYLE }, - { cd_style_bold, FCF_FG_BOLD }, - { cd_style_italic, FCF_FG_ITALIC }, - { cd_style_underline, FCF_FG_UNDERLINE }, - { cd_style_underline2, FCF_FG_UNDERLINE2 }, - { cd_style_overline, FCF_FG_OVERLINE }, - { cd_style_strikeout, FCF_FG_STRIKEOUT }, - { cd_style_faint, FCF_FG_FAINT }, - { cd_style_blink, FCF_FG_BLINK }, - { cd_style_inverse, FCF_FG_INVERSE }, - { cd_style_invisible, FCF_FG_INVISIBLE }, + colors::single_color CurColor; + bool TransparencyEnabled; + std::function RefreshColor; + size_t Offset; + + intptr_t GetSingleColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2); }; -static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2) +struct color_state { - auto& ColorState = edit_as(Dlg->SendMessage(DM_GETDLGDATA, 0, nullptr)); - auto& CurColor = ColorState.CurColor; + FarColor CurColor, BaseColor; + bool TransparencyEnabled; + single_color_state Fg, Bg; - const auto GetColor = [Param1](size_t const Offset) + void refresh_fg() { - if (any_of(Param1, cd_fg_color_default, cd_bg_color_default)) + CurColor.SetFgIndex(Fg.CurColor.IsIndex); + CurColor.ForegroundColor = Fg.CurColor.Value; + } + + void refresh_bg() + { + CurColor.SetBgIndex(Bg.CurColor.IsIndex); + CurColor.BackgroundColor = Bg.CurColor.Value; + } + + std::optional delegate_proc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2) + { + if (in_closed_range(cd::fg_first, Param1, cd::fg_last)) + return Fg.GetSingleColorDlgProc(Dlg, Msg, Param1, Param2); + + if (in_closed_range(cd::bg_first, Param1, cd::bg_last)) + return Bg.GetSingleColorDlgProc(Dlg, Msg, Param1, Param2); + + return {}; + } + + intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2); +}; + +static const auto DM_UPDATECOLORCODE = DM_USER + 1; + +intptr_t single_color_state::GetSingleColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2) +{ + const auto GetColor = [&] + { + if (Param1 - Offset == cb::color_default_radio) { - auto Color = colors::resolve_defaults(colors::default_color()); - if (Offset == cd_fg_color_first) - { - using std::swap; - swap(Color.ForegroundColor, Color.BackgroundColor); - } + auto Color = colors::default_color(); + if (Offset == cd::fg_first) + Color.Flags |= FCF_FG_INVERSE; return Color; } - auto Color = colors::NtColorToFarColor(IndexColors[color_by_control[Param1 - Offset]]); + auto Color = colors::NtColorToFarColor(IndexColors[color_by_control[Param1 - Offset - cb::color_first_radio]]); flags::clear(Color.Flags, FCF_INHERIT_STYLE); return Color; }; - const auto FlagIndex = [](bool const IsFg) - { - return IsFg? FCF_FG_INDEX : FCF_BG_INDEX; - }; - - const auto SetComponentColorValue = [&CurColor](bool const IsFg, COLORREF const Value) - { - auto& Component = IsFg? CurColor.ForegroundColor : CurColor.BackgroundColor; - colors::set_color_value(Component, Value); - }; - - const auto DM_UPDATECOLORCODE = DM_USER + 1; - switch (Msg) { case DN_INITDIALOG: - Dlg->SendMessage(DM_EDITUNCHANGEDFLAG, cd_fg_colorcode, {}); - Dlg->SendMessage(DM_EDITUNCHANGEDFLAG, cd_bg_colorcode, {}); + Dlg->SendMessage(DM_EDITUNCHANGEDFLAG, Offset + cb::colorcode_edit, {}); break; case DN_CTLCOLORDLGITEM: + if (in_closed_range(cb::color_first_radio, Param1 - Offset, cb::color_last_radio)) { - const auto preview_or_disabled = [&](COLORREF const Color, size_t const Index) - { - return ColorState.TransparencyEnabled && colors::is_transparent(Color)? - colors::PaletteColorToFarColor(COL_DIALOGDISABLED) : - GetColor(Index); - }; + if (TransparencyEnabled && colors::is_transparent(CurColor.Value)) + return FALSE; const auto& Colors = *static_cast(Param2); + Colors.Colors[0] = GetColor(); - if (Param1 >= cd_fg_color_first && Param1 <= cd_fg_color_last) - { - Colors.Colors[0] = preview_or_disabled(CurColor.ForegroundColor, cd_fg_color_first); - return TRUE; - } - - if (Param1 >= cd_bg_color_first && Param1 <= cd_bg_color_last) - { - Colors.Colors[0] = preview_or_disabled(CurColor.BackgroundColor, cd_bg_color_first); - return TRUE; - } - - if (Param1 >= cd_sample_first && Param1 <= cd_sample_last) - { - Colors.Colors[0] = colors::merge(ColorState.BaseColor, ColorState.CurColor); - return TRUE; - } - + return TRUE; } break; case DN_BTNCLICK: + if (Param2 && in_closed_range(cb::color_first_radio, Param1 - Offset, cb::color_last_radio)) { - if (Param2 && (in_closed_range(cd_fg_color_first, Param1, cd_fg_color_last) || in_closed_range(cd_bg_color_first, Param1, cd_bg_color_last))) - { - if (IgnoreColorIndexClick) - return TRUE; + if (IgnoreColorIndexClick) + return TRUE; - const auto IsFg = in_closed_range(cd_fg_color_first, Param1, cd_fg_color_last); - const auto First = IsFg? cd_fg_color_first : cd_bg_color_first; + CurColor.Value = Param1 - Offset == cb::color_default_radio? + colors::default_colorref() : + GetColor().BackgroundColor; - auto& Component = IsFg? CurColor.ForegroundColor : CurColor.BackgroundColor; - Component = GetColor(First).BackgroundColor; + CurColor.IsIndex = true; - CurColor.Flags |= FlagIndex(IsFg); + RefreshColor(); - if (Param1 == cd_fg_color_default) - CurColor.SetFgDefault(); - else if (Param1 == cd_bg_color_default) - CurColor.SetBgDefault(); + Dlg->SendMessage(DM_UPDATECOLORCODE, Offset + cb::colorcode_edit, {}); - Dlg->SendMessage(DM_UPDATECOLORCODE, IsFg? cd_fg_colorcode : cd_bg_colorcode, {}); + return TRUE; + } - return TRUE; - } + if (Param1 - Offset == cb::color_active_checkbox) + { + Param2? colors::make_opaque(CurColor.Value) : colors::make_transparent(CurColor.Value); + RefreshColor(); - if (in_closed_range(cd_style_first, Param1, cd_style_last)) + SCOPED_ACTION(Dialog::suppress_redraw)(Dlg); + for (const auto& i: irange(colors::index::nt_size + 2)) { - flags::change(CurColor.Flags, StyleMapping[Param1 - cd_style_first].second, Param2 != nullptr); - return TRUE; + Dlg->SendMessage(DM_ENABLE, Offset + cb::color_first_radio + i, Param2); } - if (any_of(Param1, cd_fg_active, cd_bg_active)) - { - const auto IsFg = Param1 == cd_fg_active; - auto& Component = IsFg? CurColor.ForegroundColor : CurColor.BackgroundColor; - Param2? colors::make_opaque(Component) : colors::make_transparent(Component); - - SCOPED_ACTION(Dialog::suppress_redraw)(Dlg); - const auto Offset = IsFg? cd_fg_color_first : cd_bg_color_first; - for (const auto& i: irange(colors::index::nt_size)) - { - Dlg->SendMessage(DM_ENABLE, i + Offset, Param2); - } + Dlg->SendMessage(DM_UPDATECOLORCODE, Offset + cb::colorcode_edit, {}); - Dlg->SendMessage(DM_UPDATECOLORCODE, IsFg? cd_fg_colorcode : cd_bg_colorcode, {}); + Dlg->SendMessage(DM_ENABLE, Offset + cb::colorcode_edit, Param2); + Dlg->SendMessage(DM_ENABLE, Offset + cb::colorcode_text, Param2); + Dlg->SendMessage(DM_ENABLE, Offset + cb::button_256, Param2); + Dlg->SendMessage(DM_ENABLE, Offset + cb::button_rgb, Param2); - Dlg->SendMessage(DM_ENABLE, IsFg? cd_fg_colorcode : cd_bg_colorcode, Param2); - Dlg->SendMessage(DM_ENABLE, IsFg? cd_fg_256 : cd_bg_256, Param2); - Dlg->SendMessage(DM_ENABLE, IsFg? cd_fg_rgb : cd_bg_rgb, Param2); + return TRUE; + } - return TRUE; - } + if (Param1 - Offset == cb::button_256) + { + FarColor FakeColor{ .BackgroundColor = CurColor.Value }; + FakeColor.SetBgIndex(CurColor.IsIndex); - if (any_of(Param1, cd_fg_256, cd_bg_256)) + if (auto Color = colors::index_value(colors::FarColorToConsole256Color(FakeColor).BackgroundIndex); pick_color_256(Color)) { - const auto IsFg = Param1 == cd_fg_256; - const auto Index = colors::FarColorToConsole256Color(CurColor); - const auto& Component = IsFg? Index.ForegroundIndex : Index.BackgroundIndex; - - auto Color = colors::index_value(Component); - - if (pick_color_256(Color)) - { - SetComponentColorValue(IsFg, Color); - - CurColor.Flags |= FlagIndex(IsFg); + colors::set_index_value(CurColor.Value, Color); + CurColor.IsIndex = true; + RefreshColor(); - Dlg->SendMessage(DM_SETCHECK, IsFg? cd_fg_color_first : cd_bg_color_first, ToPtr(BSTATE_3STATE)); - Dlg->SendMessage(DM_UPDATECOLORCODE, IsFg? cd_fg_colorcode : cd_bg_colorcode, {}); + Dlg->SendMessage(DM_SETCHECK, Offset + cb::color_first_radio, ToPtr(BSTATE_3STATE)); + Dlg->SendMessage(DM_UPDATECOLORCODE, Offset + cb::colorcode_edit, {}); - } - return TRUE; } + return TRUE; + } - if (any_of(Param1, cd_fg_rgb, cd_bg_rgb)) - { - const auto IsFg = Param1 == cd_fg_rgb; - const auto ResolvedColor = colors::resolve_defaults(CurColor); - const auto& Component = IsFg? ResolvedColor.ForegroundColor : ResolvedColor.BackgroundColor; - - auto Color = colors::color_value( - CurColor.Flags & FlagIndex(IsFg)? - colors::ConsoleIndexToTrueColor(Component) : - Component - ); - - if (auto CustomColors = Global->Opt->Palette.GetCustomColors(); pick_color_rgb(Color, CustomColors)) - { - SetComponentColorValue(IsFg, Color); - CurColor.Flags &= ~FlagIndex(IsFg); - - Dlg->SendMessage(DM_SETCHECK, IsFg? cd_fg_color_first : cd_bg_color_first, ToPtr(BSTATE_3STATE)); - Dlg->SendMessage(DM_UPDATECOLORCODE, IsFg? cd_fg_colorcode : cd_bg_colorcode, {}); - Global->Opt->Palette.SetCustomColors(CustomColors); - } + if (Param1 - Offset == cb::button_rgb) + { + const auto ResolvedColor = colors::resolve_default(CurColor.Value, Offset == cd::fg_first); - return TRUE; - } + auto Color = colors::color_value( + CurColor.IsIndex? + colors::ConsoleIndexToTrueColor(ResolvedColor) : + ResolvedColor + ); - if (Param1 == cd_button_enable_vt) + if (auto CustomColors = Global->Opt->Palette.GetCustomColors(); pick_color_rgb(Color, CustomColors)) { - Global->Opt->VirtualTerminalRendering = true; - SetFarConsoleMode(); - - Dlg->SendMessage(DM_ENABLE, cd_button_enable_vt, ToPtr(FALSE)); + colors::set_color_value(CurColor.Value, Color); + CurColor.IsIndex = false; + RefreshColor(); - return TRUE; + Dlg->SendMessage(DM_SETCHECK, Offset + cb::color_first_radio, ToPtr(BSTATE_3STATE)); + Dlg->SendMessage(DM_UPDATECOLORCODE, Offset + cb::colorcode_edit, {}); + Global->Opt->Palette.SetCustomColors(CustomColors); } + + return TRUE; } break; case DN_EDITCHANGE: - if (!IgnoreEditChange && any_of(Param1, cd_fg_colorcode, cd_bg_colorcode)) + if (!IgnoreEditChange && Param1 - Offset == cb::colorcode_edit) { const auto& Item = *static_cast(Param2); const auto Iterator = null_iterator(Item.Data); - if (std::any_of(Iterator, Iterator.end(), std::iswxdigit)) - { - const auto IsFg = Param1 == cd_fg_colorcode; - const auto IsIndex = IsFg? CurColor.IsFgIndex() : CurColor.IsBgIndex(); - auto& Component = IsFg? CurColor.ForegroundColor : CurColor.BackgroundColor; + if (!std::any_of(Iterator, Iterator.end(), std::iswxdigit)) + return false; - const auto ParsedColor = parse_color(Item.Data, IsIndex); - if (!ParsedColor) - return false; + const auto ParsedColor = parse_color(Item.Data, CurColor.IsIndex); + if (!ParsedColor) + return false; - const auto OldColorValue = colors::color_value(Component); - Component = *ParsedColor; + const auto OldColorValue = colors::color_value(CurColor.Value); + CurColor.Value = *ParsedColor; + RefreshColor(); - if (IsIndex) + if (CurColor.IsIndex) + { + if (const auto NewColorValue = colors::color_value(CurColor.Value); NewColorValue != OldColorValue) { - if (const auto NewColorValue = colors::color_value(Component); NewColorValue != OldColorValue) - { - IgnoreColorIndexClick = true; - SCOPE_EXIT{ IgnoreColorIndexClick = false; }; - const auto ColorButtonIndex = NewColorValue < 8? NewColorValue * 2 : (NewColorValue - 8) * 2 + 1; - Dlg->SendMessage(DM_SETCHECK, (IsFg? cd_fg_color_first : cd_bg_color_first) + ColorButtonIndex, ToPtr(BSTATE_CHECKED)); - } + IgnoreColorIndexClick = true; + SCOPE_EXIT{ IgnoreColorIndexClick = false; }; + const auto ColorButtonIndex = NewColorValue < 8? NewColorValue * 2 : (NewColorValue - 8) * 2 + 1; + Dlg->SendMessage(DM_SETCHECK, Offset + cb::color_first_radio + ColorButtonIndex, ToPtr(BSTATE_CHECKED)); } + } - if (ColorState.TransparencyEnabled && colors::is_transparent(Component)) - { - Dlg->SendMessage(DM_SETCHECK, IsFg? cd_fg_active : cd_bg_active, ToPtr(BSTATE_UNCHECKED)); - Dlg->SendMessage(DN_BTNCLICK, IsFg? cd_fg_active : cd_bg_active, ToPtr(BSTATE_UNCHECKED)); - } + if (TransparencyEnabled && colors::is_transparent(CurColor.Value)) + { + Dlg->SendMessage(DM_SETCHECK, Offset + cb::color_active_checkbox, ToPtr(BSTATE_UNCHECKED)); + Dlg->SendMessage(DN_BTNCLICK, Offset + cb::color_active_checkbox, ToPtr(BSTATE_UNCHECKED)); } } break; @@ -443,21 +431,18 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void { IgnoreEditChange = true; SCOPE_EXIT{ IgnoreEditChange = false; }; - const auto IsFg = Param1 == cd_fg_colorcode; FarDialogItem Item; - if (!Dlg->SendMessage(DM_GETDLGITEMSHORT, Param1, &Item)) + if (!Dlg->SendMessage(DM_GETDLGITEMSHORT, Offset + cb::colorcode_edit, &Item)) return false; - const auto Color = IsFg? CurColor.ForegroundColor : CurColor.BackgroundColor; - const auto IsIndex = IsFg? CurColor.IsFgIndex() : CurColor.IsBgIndex(); - const auto IsDefault = IsFg? CurColor.IsFgDefault() : CurColor.IsBgDefault(); - const auto Value = color_code(Color, IsIndex, IsDefault); + const auto IsDefault = colors::is_default(CurColor.Value); + const auto Value = color_code(CurColor); - Item.Mask = (IsIndex? IsDefault? MaskDef : MaskIndex: MaskARGB).data(); + Item.Mask = (CurColor.IsIndex? IsDefault? MaskDef : MaskIndex: MaskARGB).data(); Item.Data = UNSAFE_CSTR(Value); - Dlg->SendMessage(DM_SETDLGITEM, Param1, &Item); + Dlg->SendMessage(DM_SETDLGITEM, Offset + cb::colorcode_edit, &Item); constexpr lng Titles[][3] { @@ -466,8 +451,8 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void }; Dlg->SendMessage(DM_SETTEXTPTR, - IsFg? cd_fg_colorcode_title : cd_bg_colorcode_title, - UNSAFE_CSTR(msg(Titles[IsFg? 0 : 1][IsIndex? IsDefault? 2 : 0 : 1])) + Offset + cb::colorcode_text, + UNSAFE_CSTR(msg(Titles[Offset == cd::fg_first? 0 : 1][CurColor.IsIndex? IsDefault? 2 : 0 : 1])) ); } return TRUE; @@ -479,6 +464,73 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void return Dlg->DefProc(Msg, Param1, Param2); } +intptr_t color_state::GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2) +{ + switch (Msg) + { + case DN_INITDIALOG: + Fg.GetSingleColorDlgProc(Dlg, Msg, Param1, Param2); + Bg.GetSingleColorDlgProc(Dlg, Msg, Param1, Param2); + break; + + case DN_CTLCOLORDLGITEM: + if (const auto Result = delegate_proc(Dlg, Msg, Param1, Param2)) + return *Result; + + if (in_closed_range(cd::sample_text_first, Param1, cd::sample_text_last)) + { + const auto& Colors = *static_cast(Param2); + Colors.Colors[0] = colors::merge(BaseColor, CurColor); + return TRUE; + } + break; + + case DN_BTNCLICK: + if (const auto Result = delegate_proc(Dlg, Msg, Param1, Param2)) + return *Result; + + if (in_closed_range(cd::style_checkbox_first, Param1, cd::style_checkbox_last)) + { + flags::change(CurColor.Flags, StyleMapping[Param1 - cd::style_checkbox_first].second, Param2 != nullptr); + return TRUE; + } + + if (Param1 == cd::button_enable_vt) + { + Global->Opt->VirtualTerminalRendering = true; + SetFarConsoleMode(); + + Dlg->SendMessage(DM_ENABLE, cd::button_enable_vt, ToPtr(FALSE)); + + return TRUE; + } + break; + + case DN_EDITCHANGE: + if (const auto Result = delegate_proc(Dlg, Msg, Param1, Param2)) + return *Result; + + break; + + case DM_UPDATECOLORCODE: + if (delegate_proc(Dlg, Msg, Param1, Param2)) + { + SCOPED_ACTION(Dialog::suppress_redraw)(Dlg); + for (const auto& i : irange(cd::sample_text_first, cd::sample_text_last + 1)) + { + Dlg->SendMessage(DM_SHOWITEM, i, ToPtr(1)); + } + return TRUE; + } + return FALSE; + + default: + break; + } + + return Dlg->DefProc(Msg, Param1, Param2); +} + bool GetColorDialog(FarColor& Color, bool const bCentered, const FarColor* const BaseColor, bool* const Reset) { const auto IsVtActive = console.IsVtActive(); @@ -500,7 +552,7 @@ bool GetColorDialog(FarColor& Color, bool const bCentered, const FarColor* const HintW = 55, ButtonY = 19 - (ShowVtHint? 0 : 3); - auto ColorDlg = MakeDialogItems( + auto ColorDlg = MakeDialogItems( { { DI_DOUBLEBOX, {{3, 1 }, {62, ButtonY+1}}, DIF_NONE, msg(lng::MSetColorTitle), }, @@ -579,44 +631,58 @@ bool GetColorDialog(FarColor& Color, bool const bCentered, const FarColor* const { DI_BUTTON, {{0, ButtonY}, {0, ButtonY}}, DIF_CENTERGROUP, msg(lng::MSetColorCancel), }, }); - ColorDlg[cd_fg_color_first].Flags |= DIF_GROUP; - ColorDlg[cd_bg_color_first].Flags |= DIF_GROUP; + ColorDlg[fg_item(cb::color_first_radio)].Flags |= DIF_GROUP; + ColorDlg[bg_item(cb::color_first_radio)].Flags |= DIF_GROUP; - ColorDlg[cd_separator_vertical_before_style].strMask = { BoxSymbols[BS_T_H2V1], BoxSymbols[BS_V1], BoxSymbols[BS_B_H1V1] }; - ColorDlg[cd_separator_after_foreground].strMask = ColorDlg[cd_separator_after_background].strMask = { BoxSymbols[BS_L_H1V2], BoxSymbols[BS_H1], BoxSymbols[BS_R_H1V1] }; - ColorDlg[cd_separator_style].strMask = { BoxSymbols[BS_H1], BoxSymbols[BS_H1], BoxSymbols[BS_H1] }; + ColorDlg[cd::separator_vertical_before_style].strMask = { BoxSymbols[BS_T_H2V1], BoxSymbols[BS_V1], BoxSymbols[BS_B_H1V1] }; + ColorDlg[cd::separator_after_foreground].strMask = ColorDlg[cd::separator_after_background].strMask = { BoxSymbols[BS_L_H1V2], BoxSymbols[BS_H1], BoxSymbols[BS_R_H1V1] }; + ColorDlg[cd::separator_style].strMask = { BoxSymbols[BS_H1], BoxSymbols[BS_H1], BoxSymbols[BS_H1] }; - ColorDlg[cd_fg_colorcode].strData = color_code(Color.ForegroundColor, Color.IsFgIndex(), Color.IsFgDefault()); - ColorDlg[cd_bg_colorcode].strData = color_code(Color.BackgroundColor, Color.IsBgIndex(), Color.IsBgDefault()); - ColorDlg[cd_fg_colorcode].strMask = Color.IsFgIndex()? Color.IsFgDefault()? MaskDef : MaskIndex : MaskARGB; - ColorDlg[cd_bg_colorcode].strMask = Color.IsBgIndex()? Color.IsBgDefault()? MaskDef : MaskIndex : MaskARGB; + ColorDlg[fg_item(cb::colorcode_edit)].strData = color_code(colors::single_color::foreground(Color)); + ColorDlg[bg_item(cb::colorcode_edit)].strData = color_code(colors::single_color::background(Color)); + ColorDlg[fg_item(cb::colorcode_edit)].strMask = Color.IsFgIndex()? Color.IsFgDefault()? MaskDef : MaskIndex : MaskARGB; + ColorDlg[bg_item(cb::colorcode_edit)].strMask = Color.IsBgIndex()? Color.IsBgDefault()? MaskDef : MaskIndex : MaskARGB; color_state ColorState { - Color, - BaseColor? *BaseColor : colors::NtColorToFarColor(F_BLACK | B_BLACK), - BaseColor != nullptr + .CurColor = Color, + .BaseColor = BaseColor? *BaseColor : colors::NtColorToFarColor(F_BLACK | B_BLACK), + .TransparencyEnabled = BaseColor != nullptr, + .Fg + { + .CurColor = colors::single_color::foreground(Color), + .TransparencyEnabled = !!BaseColor, + .RefreshColor = [&]{ ColorState.refresh_fg(); }, + .Offset = cd::fg_first, + }, + .Bg + { + .CurColor = colors::single_color::background(Color), + .TransparencyEnabled = !!BaseColor, + .RefreshColor = [&]{ ColorState.refresh_bg(); }, + .Offset = cd::bg_first, + }, }; auto ForegroundColorControlActivated = false, BackgroundColorControlActivated = false; - const auto get_control_id = [&](COLORREF const ColorPart, int const ControlGroup) -> std::optional + const auto get_control_id = [&](COLORREF const ColorPart, size_t const Offset) -> std::optional { if (colors::is_default(ColorPart)) - return ControlGroup + colors::index::nt_size; + return Offset + cb::color_first_radio + colors::index::nt_size; const auto Index = colors::index_value(ColorPart); if (Index > colors::index::nt_last) return {}; - return ControlGroup + control_by_color[Index]; + return Offset + cb::color_first_radio + control_by_color[Index]; }; - const auto activate_control = [&](COLORREF const ColorPart, int const ControlGroup) + const auto activate_control = [&](COLORREF const ColorPart, size_t const Offset) { - const auto ControlId = get_control_id(ColorPart, ControlGroup); + const auto ControlId = get_control_id(ColorPart, Offset); if (!ControlId) return false; @@ -626,13 +692,13 @@ bool GetColorDialog(FarColor& Color, bool const bCentered, const FarColor* const }; if (Color.IsFgIndex()) - ForegroundColorControlActivated = activate_control(Color.ForegroundColor, cd_fg_color_first); + ForegroundColorControlActivated = activate_control(Color.ForegroundColor, cd::fg_first); if (Color.IsBgIndex()) - BackgroundColorControlActivated = activate_control(Color.BackgroundColor, cd_bg_color_first); + BackgroundColorControlActivated = activate_control(Color.BackgroundColor, cd::bg_first); if (!ForegroundColorControlActivated && !BackgroundColorControlActivated) - ColorDlg[cd_fg_colorcode].Flags |= DIF_FOCUS; + ColorDlg[fg_item(cb::colorcode_edit)].Flags |= DIF_FOCUS; for (const auto& [Index, Flag]: StyleMapping) { @@ -641,55 +707,43 @@ bool GetColorDialog(FarColor& Color, bool const bCentered, const FarColor* const if (BaseColor) { - ColorDlg[cd_fg_text].Flags |= DIF_HIDDEN | DIF_DISABLE; - ColorDlg[cd_bg_text].Flags |= DIF_HIDDEN | DIF_DISABLE; + ColorDlg[fg_item(cb::color_text)].Flags |= DIF_HIDDEN | DIF_DISABLE; + ColorDlg[bg_item(cb::color_text)].Flags |= DIF_HIDDEN | DIF_DISABLE; - if (colors::is_transparent(Color.ForegroundColor)) + const auto disable_if_needed = [&](size_t const Offset) { - for (const auto& i: irange(cd_fg_color_first, cd_fg_color_last + 1)) + if (colors::is_transparent(Offset == cd::fg_first? Color.ForegroundColor : Color.BackgroundColor)) { - ColorDlg[i].Flags |= DIF_DISABLE; - } - - ColorDlg[cd_fg_color_default_label].Flags |= DIF_DISABLE; - ColorDlg[cd_fg_colorcode].Flags |= DIF_DISABLE; - ColorDlg[cd_fg_256].Flags |= DIF_DISABLE; - ColorDlg[cd_fg_rgb].Flags |= DIF_DISABLE; - } - else - { - ColorDlg[cd_fg_active].Selected = BSTATE_CHECKED; - } + for (const auto& i: irange(cb::color_first_radio, cb::color_last_radio + 2)) + { + ColorDlg[Offset + i].Flags |= DIF_DISABLE; + } - if (colors::is_transparent(Color.BackgroundColor)) - { - for (const auto& i: irange(cd_bg_color_first, cd_bg_color_last + 1)) + ColorDlg[Offset + cb::colorcode_edit].Flags |= DIF_DISABLE; + ColorDlg[Offset + cb::colorcode_text].Flags |= DIF_DISABLE; + ColorDlg[Offset + cb::button_256].Flags |= DIF_DISABLE; + ColorDlg[Offset + cb::button_rgb].Flags |= DIF_DISABLE; + } + else { - ColorDlg[i].Flags |= DIF_DISABLE; + ColorDlg[Offset + cb::color_active_checkbox].Selected = BSTATE_CHECKED; } + }; - ColorDlg[cd_bg_color_default_label].Flags |= DIF_DISABLE; - ColorDlg[cd_bg_colorcode].Flags |= DIF_DISABLE; - ColorDlg[cd_bg_256].Flags |= DIF_DISABLE; - ColorDlg[cd_bg_rgb].Flags |= DIF_DISABLE; - } - else - { - ColorDlg[cd_bg_active].Selected = BSTATE_CHECKED; - } - + disable_if_needed(cd::fg_first); + disable_if_needed(cd::bg_first); } else { - ColorDlg[cd_fg_active].Flags |= DIF_HIDDEN | DIF_DISABLE; - ColorDlg[cd_bg_active].Flags |= DIF_HIDDEN | DIF_DISABLE; + ColorDlg[fg_item(cb::color_active_checkbox)].Flags |= DIF_HIDDEN | DIF_DISABLE; + ColorDlg[bg_item(cb::color_active_checkbox)].Flags |= DIF_HIDDEN | DIF_DISABLE; } - const auto Dlg = Dialog::create(ColorDlg, GetColorDlgProc, &ColorState); + const auto Dlg = Dialog::create(ColorDlg, &color_state::GetColorDlgProc, &ColorState); const auto - DlgWidth = static_cast(ColorDlg[cd_border].X2) + 4, - DlgHeight = static_cast(ColorDlg[cd_border].Y2) + 2; + DlgWidth = static_cast(ColorDlg[cd::border].X2) + 4, + DlgHeight = static_cast(ColorDlg[cd::border].Y2) + 2; if (bCentered) Dlg->SetPosition({ -1, -1, DlgWidth, DlgHeight }); @@ -707,11 +761,11 @@ bool GetColorDialog(FarColor& Color, bool const bCentered, const FarColor* const switch (Dlg->GetExitCode()) { - case cd_button_ok: + case cd::button_ok: Color = ColorState.CurColor; return true; - case cd_button_reset: + case cd::button_reset: if (Reset) *Reset = true; [[fallthrough]]; diff --git a/far/color_picker_256.cpp b/far/color_picker_256.cpp index e71b3a99a22..0b31e062a87 100644 --- a/far/color_picker_256.cpp +++ b/far/color_picker_256.cpp @@ -240,6 +240,8 @@ struct color_256_state { CurColor = RGB; } + + intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2); }; static auto cube_index(color_256_state const& ColorState, color_256_dialog_items const Button) @@ -273,10 +275,8 @@ static void init_cube(color_256_state& ColorState) } } -static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2) +intptr_t color_256_state::GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2) { - auto& ColorState = edit_as(Dlg->SendMessage(DM_GETDLGDATA, 0, nullptr)); - switch (Msg) { case DN_CTLCOLORDLGITEM: @@ -285,7 +285,7 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void if (in_closed_range(cd_cube_first, Param1, cd_cube_last)) { - const auto ColorIndex = cube_index(ColorState, static_cast(Param1)); + const auto ColorIndex = cube_index(*this, static_cast(Param1)); Colors.Colors[0] = Console256ColorToFarColor({ distinct_cube_map[ColorIndex], cube_color(ColorIndex) }); return true; } @@ -302,7 +302,7 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void case cd_text_rgb: { // Foreground color is irrelevant - Colors.Colors[0] = Console256ColorToFarColor({ 0, ColorState.CurColor }); + Colors.Colors[0] = Console256ColorToFarColor({ 0, CurColor }); return true; } @@ -311,7 +311,7 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void case cd_text_b: { const auto Context = get_rgb_context(Item); - auto RGB = ColorState.as_rgb(); + auto RGB = as_rgb(); auto& Channel = std::invoke(Context.Channel, RGB); const auto SavedValue = Channel; RGB = {}; @@ -330,19 +330,19 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void case DN_BTNCLICK: { const auto Button = static_cast(Param1); - if (on_button_click(Dlg, Button, ColorState)) + if (on_button_click(Dlg, Button, *this)) return true; if (Param2 && in_closed_range(cd_cube_first, Button, cd_cube_last)) { - ColorState.CurColor = cube_color(cube_index(ColorState, Button)); - update_rgb_control(Dlg, ColorState.as_rgb()); + CurColor = cube_color(cube_index(*this, Button)); + update_rgb_control(Dlg, as_rgb()); return true; } if (Param2 && in_closed_range(cd_grey_first, Button, cd_grey_last)) { - ColorState.CurColor = grey_color(grey_stripe_mapping[grey_index_by_control[Button - cd_grey_first]]); + CurColor = grey_color(grey_stripe_mapping[grey_index_by_control[Button - cd_grey_first]]); update_rgb_control(Dlg, rgb{}); return true; } @@ -350,8 +350,8 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void switch (Button) { case cd_button_home: - init_cube(ColorState); - ColorState.Cube.Slice = 0; + init_cube(*this); + Cube.Slice = 0; Dlg->SendMessage(DM_ONCUBECHANGE, 0, {}); return true; @@ -363,15 +363,15 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void case DM_ONCUBECHANGE: { - if (is_rgb(ColorState.CurColor)) + if (is_rgb(CurColor)) Dlg->SendMessage(DM_SETCHECK, cd_cube_first, ToPtr(BSTATE_3STATE)); - const auto& Plane = ColorState.Cube.Cube[ColorState.Cube.Slice]; + const auto& Plane = Cube.Cube[Cube.Slice]; for (const auto& Line: Plane) { for (const auto& Point: Line) { - if (cube_color(Point) == ColorState.CurColor) + if (cube_color(Point) == CurColor) { const auto ControlId = cd_cube_first + cube_rc_mapping[&Point - &Plane[0][0]]; Dlg->SendMessage(DM_SETCHECK, ControlId, ToPtr(BSTATE_CHECKED)); @@ -479,7 +479,7 @@ bool pick_color_256(uint8_t& Color) ColorDlg[ControlId].Flags |= DIF_FOCUS; } - const auto Dlg = Dialog::create(ColorDlg, GetColorDlgProc, &ColorState); + const auto Dlg = Dialog::create(ColorDlg, &color_256_state::GetColorDlgProc, &ColorState); const auto DlgWidth = static_cast(ColorDlg[cd_border].X2) + 4, diff --git a/far/color_picker_rgb.cpp b/far/color_picker_rgb.cpp index f6cac4ac97f..2818ead5b45 100644 --- a/far/color_picker_rgb.cpp +++ b/far/color_picker_rgb.cpp @@ -201,6 +201,9 @@ struct color_rgb_state { CurColor = colors::to_color(RGB); } + + intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2); + }; static rgb cube_rgb(cube const& Cube, uint8_t const x, uint8_t const y, uint8_t const z, bool const IsZoomed) @@ -401,10 +404,8 @@ static void zoom(Dialog* const Dlg, color_rgb_state& ColorState) Dlg->SendMessage(DM_ONCUBECHANGE, 0, {}); } -static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2) +intptr_t color_rgb_state::GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2) { - auto& ColorState = edit_as(Dlg->SendMessage(DM_GETDLGDATA, 0, nullptr)); - switch (Msg) { case DN_CTLCOLORDLGITEM: @@ -413,14 +414,14 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void if (in_closed_range(cd_cube_first, Param1, cd_cube_last)) { - const auto RGB = cube_rgb(ColorState, Param1 - cd_cube_first, true); + const auto RGB = cube_rgb(*this, Param1 - cd_cube_first, true); Colors.Colors[0] = TrueColorToFarColorDistinct(colors::to_color(RGB)); return true; } if (in_closed_range(cd_custom_first, Param1, cd_custom_last)) { - Colors.Colors[0] = TrueColorToFarColorDistinct(ColorState.CustomColors[Param1 - cd_custom_first]); + Colors.Colors[0] = TrueColorToFarColorDistinct(CustomColors[Param1 - cd_custom_first]); return true; } @@ -429,7 +430,7 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void case cd_text_rgb: { // Foreground color is irrelevant - Colors.Colors[0] = TrueColorToFarColor(ColorState.CurColor); + Colors.Colors[0] = TrueColorToFarColor(CurColor); return true; } @@ -438,7 +439,7 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void case cd_text_b: { const auto Context = get_rgb_context(Item); - auto RGB = ColorState.as_rgb(); + auto RGB = as_rgb(); auto& Channel = std::invoke(Context.Channel, RGB); const auto SavedValue = Channel; RGB = {}; @@ -456,54 +457,54 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void case DN_BTNCLICK: { const auto Button = static_cast(Param1); - if (on_button_click(Dlg, Button, ColorState)) + if (on_button_click(Dlg, Button, *this)) return true; if (Param2 && in_closed_range(cd_cube_first, Button, cd_cube_last)) { - ColorState.Cube.Index = Button - cd_cube_first; - const auto RGB = cube_rgb(ColorState, ColorState.Cube.Index); - ColorState.from_rgb(RGB); + Cube.Index = Button - cd_cube_first; + const auto RGB = cube_rgb(*this, Cube.Index); + from_rgb(RGB); update_rgb_control(Dlg, RGB); return true; } if (Param2 && in_closed_range(cd_custom_first, Button, cd_custom_last)) { - ColorState.CustomIndex = Button - cd_custom_first; - ColorState.CurColor = ColorState.CustomColors[*ColorState.CustomIndex]; - update_rgb_control(Dlg, ColorState.as_rgb()); + CustomIndex = Button - cd_custom_first; + CurColor = CustomColors[*CustomIndex]; + update_rgb_control(Dlg, as_rgb()); return true; } switch (Button) { case cd_button_home: - init_cube(ColorState); - ColorState.Cube.Slice = 0; + init_cube(*this); + Cube.Slice = 0; Dlg->SendMessage(DM_ONCUBECHANGE, 0, {}); return true; case cd_button_zoom: - zoom(Dlg, ColorState); + zoom(Dlg, *this); return true; case cd_button_system: { - const auto SavedColor = ColorState.CurColor; - const auto SavedCustomColors = ColorState.CustomColors; + const auto SavedColor = CurColor; + const auto SavedCustomColors = CustomColors; - if (!pick_color_rgb_gui(ColorState.CurColor, ColorState.CustomColors)) + if (!pick_color_rgb_gui(CurColor, CustomColors)) return true; - if (ColorState.CurColor != SavedColor) + if (CurColor != SavedColor) { - update_rgb_control(Dlg, ColorState.as_rgb()); + update_rgb_control(Dlg, as_rgb()); } - if (ColorState.CustomColors != SavedCustomColors) + if (CustomColors != SavedCustomColors) { - const auto Range = zip(SavedCustomColors, ColorState.CustomColors, irange(std::size(SavedCustomColors))); + const auto Range = zip(SavedCustomColors, CustomColors, irange(std::size(SavedCustomColors))); const auto Changed = [](auto const Old, auto const New, auto){ return Old != New; }; const auto Index = [](auto, auto, auto i){ return i; }; @@ -518,12 +519,12 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void case cd_button_save: { uint8_t Index = 0; - if (ColorState.CustomIndex) - Index = *ColorState.CustomIndex; - else if (const auto Iterator = std::find(ALL_CONST_RANGE(ColorState.CustomColors), RGB(255, 255, 255)); Iterator != std::cend(ColorState.CustomColors)) - Index = Iterator - std::cbegin(ColorState.CustomColors); + if (CustomIndex) + Index = *CustomIndex; + else if (const auto Iterator = std::find(ALL_CONST_RANGE(CustomColors), RGB(255, 255, 255)); Iterator != std::cend(CustomColors)) + Index = Iterator - std::cbegin(CustomColors); - ColorState.CustomColors[Index] = ColorState.CurColor; + CustomColors[Index] = CurColor; Dlg->SendMessage(DM_SHOWITEM, Index, ToPtr(1)); return true; } @@ -538,13 +539,13 @@ static intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void { Dlg->SendMessage(DM_SETCHECK, cd_cube_first, ToPtr(BSTATE_3STATE)); - const auto& Plane = ColorState.Cube.Cube[ColorState.Cube.Slice]; + const auto& Plane = Cube.Cube[Cube.Slice]; for (const auto& Line: Plane) { for (const auto& Point: Line) { const auto Index = &Point - &Plane[0][0]; - if (colors::to_color(cube_rgb(ColorState, Index)) == ColorState.CurColor) + if (colors::to_color(cube_rgb(*this, Index)) == CurColor) { Dlg->SendMessage(DM_SETCHECK, cd_cube_first + Index, ToPtr(BSTATE_CHECKED)); break; @@ -687,7 +688,7 @@ static bool pick_color_rgb_tui(COLORREF& Color, [[maybe_unused]] std::array(ColorDlg[cd_border].X2) + 4, diff --git a/far/colormix.cpp b/far/colormix.cpp index 77db9eac8db..c15d847e35a 100644 --- a/far/colormix.cpp +++ b/far/colormix.cpp @@ -61,6 +61,21 @@ enum namespace colors { + single_color single_color::foreground(FarColor const& Color) + { + return { Color.ForegroundColor, Color.IsFgIndex() }; + } + + single_color single_color::background(FarColor const& Color) + { + return { Color.BackgroundColor, Color.IsBgIndex() }; + } + + single_color single_color::default_color() + { + return { default_colorref(), true }; + } + uint8_t index_bits(COLORREF const Colour) { return Colour & INDEXMASK; @@ -212,9 +227,6 @@ namespace colors { static FarColor LastResult, LastBottom, LastTop; - Top = resolve_defaults(Top); - Bottom = resolve_defaults(Bottom); - if (Bottom == LastBottom && Top == LastTop) { LastResult.Reserved[0] = Bottom.Reserved[0]; @@ -260,8 +272,11 @@ namespace colors return colors::to_rgba(IsIndex? ConsoleIndexToTrueColor(Color) : Color); }; - const auto TopRGBA = to_rgba(TopValue, (Top.Flags & Flag) != 0); - const auto BottomRGBA = to_rgba(BottomValue, (Bottom.Flags & Flag) != 0); + const auto ResolvedTopValue = resolve_default(TopValue, Flag == FCF_FG_INDEX); + const auto ResolvedBottomValue = resolve_default(BottomValue, Flag == FCF_FG_INDEX); + + const auto TopRGBA = to_rgba(ResolvedTopValue, (Top.Flags & Flag) != 0); + const auto BottomRGBA = to_rgba(ResolvedBottomValue, (Bottom.Flags & Flag) != 0); const auto calc_channel = [&](unsigned char rgba::*Accessor) { @@ -526,16 +541,23 @@ static index_color_256 FarColorToConsoleColor(FarColor Color, FarColor& LastColo return Index; } +static bool not_the_same_index(const FarColor& a, const FarColor& b) +{ + return + a.ForegroundColor != b.ForegroundColor || + a.BackgroundColor != b.BackgroundColor || + ( + flags::check_all(a.Flags, FCF_FG_INDEX | FCF_BG_INDEX) != + flags::check_all(b.Flags, FCF_FG_INDEX | FCF_BG_INDEX) + ); +} + WORD FarColorToConsoleColor(const FarColor& Color) { static FarColor LastColor{}; static index_color_256 Result{}; - if ( - Color.BackgroundColor != LastColor.BackgroundColor || - Color.ForegroundColor != LastColor.ForegroundColor || - (Color.Flags & FCF_INDEXMASK) != (LastColor.Flags & FCF_INDEXMASK) - ) + if (not_the_same_index(Color, LastColor)) { static const auto Palette = console_palette(); Result = FarColorToConsoleColor(Color, LastColor, Palette); @@ -559,11 +581,7 @@ index_color_256 FarColorToConsole256Color(const FarColor& Color) static FarColor LastColor{}; static index_color_256 Result{}; - if (!( - Color.BackgroundColor == LastColor.BackgroundColor && - Color.ForegroundColor == LastColor.ForegroundColor && - (Color.Flags & FCF_INDEXMASK) == (LastColor.Flags & FCF_INDEXMASK) - )) + if (not_the_same_index(Color, LastColor)) Result = FarColorToConsoleColor(Color, LastColor, Index8ToRGB); return Result; @@ -573,7 +591,7 @@ FarColor NtColorToFarColor(WORD Color) { return { - FCF_FG_INDEX | FCF_BG_INDEX | FCF_INHERIT_STYLE | (Color & FCF_RAWATTR_MASK), + FCF_INDEXMASK | FCF_INHERIT_STYLE | (Color & FCF_RAWATTR_MASK), { opaque(index_bits(Color >> ConsoleFgShift) & index::nt_mask) }, { opaque(index_bits(Color >> ConsoleBgShift) & index::nt_mask) } }; @@ -727,27 +745,37 @@ unsigned long long ColorStringToFlags(string_view const Flags) return StringToFlags(Flags, ColorFlagNames); } -static FarColor s_ResolvedIndexColor +static FarColor s_ResolvedDefaultColor { FCF_INDEXMASK, - colors::opaque(F_LIGHTGRAY), - colors::opaque(F_BLACK), + { opaque(F_LIGHTGRAY) }, + { opaque(F_BLACK) }, }; +COLORREF resolve_default(COLORREF Color, bool IsForeground) +{ + if (!is_default(Color)) + return Color; + + const auto ResolvedColor = IsForeground? + s_ResolvedDefaultColor.ForegroundColor: + s_ResolvedDefaultColor.BackgroundColor; + + return alpha_bits(Color) | color_bits(ResolvedColor); +} + FarColor resolve_defaults(FarColor const& Color) { auto Result = Color; if (Result.IsFgDefault()) { - Result.ForegroundIndex.i = s_ResolvedIndexColor.ForegroundIndex.i; - Result.ForegroundIndex.reserved1 = 0; + Result.ForegroundColor = alpha_bits(Result.ForegroundColor) | color_bits(s_ResolvedDefaultColor.ForegroundColor); } if (Result.IsBgDefault()) { - Result.BackgroundIndex.i = s_ResolvedIndexColor.BackgroundIndex.i; - Result.BackgroundIndex.reserved1 = 0; + Result.BackgroundColor = alpha_bits(Result.BackgroundColor) | color_bits(s_ResolvedDefaultColor.BackgroundColor); } return Result; @@ -757,10 +785,10 @@ FarColor unresolve_defaults(FarColor const& Color) { auto Result = Color; - if (Result.IsFgIndex() && Result.ForegroundIndex.i == s_ResolvedIndexColor.ForegroundIndex.i) + if (single_color::foreground(Result) == single_color::foreground(s_ResolvedDefaultColor)) Result.SetFgDefault(); - if (Result.IsBgIndex() && Result.BackgroundIndex.i == s_ResolvedIndexColor.BackgroundIndex.i) + if (single_color::background(Result) == single_color::background(s_ResolvedDefaultColor)) Result.SetBgDefault(); return Result; @@ -768,13 +796,18 @@ FarColor unresolve_defaults(FarColor const& Color) constexpr auto default_color_bit = bit(23); +COLORREF default_colorref() +{ + return opaque(default_color_bit); +} + FarColor default_color() { return { FCF_INDEXMASK | FCF_INHERIT_STYLE, - opaque(default_color_bit), - opaque(default_color_bit), + { default_colorref() }, + { default_colorref() }, }; } @@ -785,8 +818,7 @@ bool is_default(COLORREF const Color) void store_default_color(FarColor const& Color) { - assert(flags::check_all(Color.Flags, FCF_INDEXMASK)); - s_ResolvedIndexColor = Color; + s_ResolvedDefaultColor = Color; } } @@ -853,9 +885,6 @@ TEST_CASE("colors.default") REQUIRE(Color.ForegroundColor == 0xFF800000); REQUIRE(Color.ForegroundColor == 0xFF800000); - - REQUIRE((Color.Flags & FCF_INDEXMASK) == FCF_INDEXMASK); - } TEST_CASE("colors.merge") diff --git a/far/colormix.hpp b/far/colormix.hpp index b047459af34..570351d37ee 100644 --- a/far/colormix.hpp +++ b/far/colormix.hpp @@ -65,6 +65,18 @@ namespace colors grey_count = grey_last - grey_first + 1; } + struct single_color + { + COLORREF Value{}; + bool IsIndex{}; + + bool operator==(single_color const&) const = default; + + static single_color foreground(FarColor const& Color); + static single_color background(FarColor const& Color); + static single_color default_color(); + }; + uint8_t index_bits(COLORREF Colour); COLORREF color_bits(COLORREF Colour); COLORREF alpha_bits(COLORREF Colour); @@ -162,8 +174,10 @@ namespace colors [[nodiscard]] unsigned long long ColorStringToFlags(string_view Flags); + COLORREF resolve_default(COLORREF Color, bool IsForeground); FarColor resolve_defaults(FarColor const& Color); FarColor unresolve_defaults(FarColor const& Color); + COLORREF default_colorref(); FarColor default_color(); bool is_default(COLORREF Color); void store_default_color(FarColor const& Color); diff --git a/far/console.cpp b/far/console.cpp index 42fc3174126..69c63f942c6 100644 --- a/far/console.cpp +++ b/far/console.cpp @@ -170,7 +170,7 @@ static bool sanitise_dbsc_pair(FAR_CHAR_INFO& First, FAR_CHAR_INFO& Second) flags::clear(First.Attributes.Flags, COMMON_LVB_LEADING_BYTE); flags::clear(Second.Attributes.Flags, COMMON_LVB_TRAILING_BYTE); - if (First == Second) + if (IsFirst && IsSecond && First == Second) { // Valid DBSC, awesome flags::set(First.Attributes.Flags, COMMON_LVB_LEADING_BYTE); @@ -200,7 +200,7 @@ static bool sanitise_surrogate_pair(FAR_CHAR_INFO& First, FAR_CHAR_INFO& Second) return false; } - if (encoding::utf16::is_valid_surrogate_pair(First.Char, Second.Char) && First.Attributes == Second.Attributes) + if (IsFirst && IsSecond && First.Attributes == Second.Attributes) { // Valid surrogate, awesome return false; @@ -215,9 +215,9 @@ static bool sanitise_surrogate_pair(FAR_CHAR_INFO& First, FAR_CHAR_INFO& Second) return true; } -void sanitise_pair(FAR_CHAR_INFO& First, FAR_CHAR_INFO& Second) +bool sanitise_pair(FAR_CHAR_INFO& First, FAR_CHAR_INFO& Second) { - sanitise_dbsc_pair(First, Second) || sanitise_surrogate_pair(First, Second); + return sanitise_dbsc_pair(First, Second) || sanitise_surrogate_pair(First, Second); } bool get_console_screen_buffer_info(HANDLE ConsoleOutput, CONSOLE_SCREEN_BUFFER_INFO* ConsoleScreenBufferInfo) @@ -439,6 +439,7 @@ namespace console_detail if (ChangeColour) { + CurrentColor = colors::unresolve_defaults(CurrentColor); ::console.SetTextAttributes(colors::merge(CurrentColor, *m_Colour)); } @@ -501,7 +502,7 @@ namespace console_detail static FarColor fg_color(int const NtColor) { auto Color = colors::NtColorToFarColor(NtColor); - colors::make_transparent(Color.BackgroundColor); + Color.SetBgDefault(); return Color; } @@ -1130,8 +1131,11 @@ namespace console_detail return true; } - static constexpr uint8_t vt_base_color_index(uint8_t const Index) + static constexpr uint8_t vt_color_index(uint8_t const Index) { + if (Index > colors::index::nt_last) + return Index; + // NT is RGB, VT is BGR constexpr uint8_t Table[] { @@ -1146,24 +1150,24 @@ namespace console_detail 0b111, // 111 }; - return Table[Index & 0b111]; - } - - static constexpr uint8_t vt_color_index(uint8_t const Index) - { - return (Index & 0b11111000) | vt_base_color_index(Index); + return (Index & 0b1000) | Table[Index & 0b111]; } static constexpr struct { - COLORREF FarColor::* Color; FARCOLORFLAGS Flags; string_view Normal, Intense, ExtendedColour, Default; } ColorsMapping[] { - { &FarColor::ForegroundColor, FCF_FG_INDEX, L"3"sv, L"9"sv, L"38"sv, L"39"sv }, - { &FarColor::BackgroundColor, FCF_BG_INDEX, L"4"sv, L"10"sv, L"48"sv, L"49"sv }, + { FCF_FG_INDEX, L"3"sv, L"9"sv, L"38"sv, L"39"sv }, + { FCF_BG_INDEX, L"4"sv, L"10"sv, L"48"sv, L"49"sv }, + }; + + enum class colors_mapping_type + { + foreground, + background, }; static constexpr struct @@ -1189,68 +1193,64 @@ namespace console_detail static_assert(StyleMapping[UnderlineIndex].Style == FCF_FG_UNDERLINE); static_assert(StyleMapping[UnderlineIndex + 1].Style == FCF_FG_UNDERLINE2); - static void make_vt_color(const FarColor& Attributes, string& Str, size_t const MappingIndex) + static void make_vt_color(colors::single_color const Color, colors_mapping_type const MappingType, string& Str) { - const auto& Mapping = ColorsMapping[MappingIndex]; - const auto ColorPart = std::invoke(Mapping.Color, Attributes); + const auto& Mapping = ColorsMapping[std::to_underlying(MappingType)]; - if (Attributes.Flags & Mapping.Flags) + if (Color.IsIndex) { - if (colors::is_default(ColorPart)) + if (colors::is_default(Color.Value)) append(Str, Mapping.Default); - else if (const auto Index = colors::index_value(ColorPart); Index < colors::index::nt_size) - append(Str, ColorPart & FOREGROUND_INTENSITY? Mapping.Intense : Mapping.Normal, static_cast(L'0' + vt_base_color_index(Index))); + else if (const auto Index = vt_color_index(colors::index_value(Color.Value)); Index < colors::index::nt_size) + append(Str, Color.Value & FOREGROUND_INTENSITY? Mapping.Intense : Mapping.Normal, static_cast(L'0' + (Index & 0b111))); else far::format_to(Str, L"{};5;{}"sv, Mapping.ExtendedColour, Index); } else { - const auto RGBA = colors::to_rgba(ColorPart); + const auto RGBA = colors::to_rgba(Color.Value); far::format_to(Str, L"{};2;{};{};{}"sv, Mapping.ExtendedColour, RGBA.r, RGBA.g, RGBA.b); } } - static void make_vt_style(const FarColor& Attributes, string& Str, std::optional const& LastColor) + static void make_vt_style(FARCOLORFLAGS const Style, string& Str, FARCOLORFLAGS const LastStyle) { auto UnderlineSet = false; for (const auto& i: StyleMapping) { - if (Attributes.Flags & i.Style) - { - if (!LastColor.has_value() || !(LastColor->Flags & i.Style)) - { - append(Str, i.On, L';'); + const auto Was = (LastStyle & i.Style) != 0; + const auto Is = (Style & i.Style) != 0; - // See below - if (i.Style == FCF_FG_UNDERLINE) - UnderlineSet = true; - } + if (Was == Is) + continue; + + if (Is > Was) + { + if (i.Style == FCF_FG_UNDERLINE) + UnderlineSet = true; } else { - if (LastColor.has_value() && LastColor->Flags & i.Style) + if (i.Style == FCF_FG_UNDERLINE2 && Style & FCF_FG_UNDERLINE) { - if (i.Style == FCF_FG_UNDERLINE2 && Attributes.Flags & FCF_FG_UNDERLINE) - { - // Both Underline and Double Underline have the same off code. 🤦 - // VT is a bloody joke. Whoever invented it should be punished. + // Both Underline and Double Underline have the same off code. 🤦 + // VT is a bloody joke. Whoever invented it should be punished. - // D is checked after U. - // We're dropping D now, so, if we have already enabled U on the previous iteration, this will kill it. - // To address this, we undo U if needed, emit the off code and enable U. - constexpr auto UnderlineOn = StyleMapping[UnderlineIndex].On; + // D is checked after U. + // We're dropping D now, so, if we have already enabled U on the previous iteration, this will kill it. + // To address this, we undo U if needed, emit the off code and enable U. + constexpr auto UnderlineOn = StyleMapping[UnderlineIndex].On; - if (UnderlineSet) - Str.resize(Str.size() - UnderlineOn.size() - 1); - - append(Str, i.Off, L';', UnderlineOn, L';'); - continue; - } + if (UnderlineSet) + Str.resize(Str.size() - UnderlineOn.size() - 1); - append(Str, i.Off, L';'); + append(Str, i.Off, L';', UnderlineOn, L';'); + continue; } } + + append(Str, Is > Was? i.On : i.Off, L';'); } // We should only enter this function if the style has changed and it should add or remove at least something, @@ -1258,41 +1258,58 @@ namespace console_detail Str.pop_back(); } - static void make_vt_attributes(const FarColor& Attributes, string& Str, std::optional const& LastColor) + static void make_vt_attributes(const FarColor& Color, string& Str, FarColor const& LastColor) { - const auto SameFgColor = LastColor && LastColor->IsFgIndex() == Attributes.IsFgIndex() && LastColor->ForegroundColor == Attributes.ForegroundColor; - const auto SameBgColor = LastColor && LastColor->IsBgIndex() == Attributes.IsBgIndex() && LastColor->BackgroundColor == Attributes.BackgroundColor; - const auto SameStyle = LastColor && ((LastColor->Flags & FCF_STYLEMASK) == (Attributes.Flags & FCF_STYLEMASK)); + using colors::single_color; - if (SameFgColor && SameBgColor && SameStyle) + struct expanded_state { - assert(false); - return; + single_color ForegroundColor, BackgroundColor; + FARCOLORFLAGS Style; + bool operator==(expanded_state const&) const = default; + + explicit expanded_state(FarColor const& Color): + ForegroundColor(single_color::foreground(Color)), + BackgroundColor(single_color::background(Color)), + Style(Color.Flags & FCF_STYLEMASK) + { + } } + const + Current(Color), Last(LastColor); + + assert(Current != Last); Str += CSI ""sv; - if (!SameFgColor) + auto ModeAdded = false; + + if (Current.ForegroundColor != Last.ForegroundColor) { - make_vt_color(Attributes, Str, 0); + make_vt_color(Current.ForegroundColor, colors_mapping_type::foreground, Str); + ModeAdded = true; } - if (!SameBgColor) + if (Current.BackgroundColor != Last.BackgroundColor) { - if (!SameFgColor) + if (ModeAdded) Str += L';'; - make_vt_color(Attributes, Str, 1); + make_vt_color(Current.BackgroundColor, colors_mapping_type::background, Str); + ModeAdded = true; } - if (!SameStyle) + if (Current.Style != Last.Style) { - if (!SameFgColor || !SameBgColor) + if (ModeAdded) Str += L';'; - make_vt_style(Attributes, Str, LastColor); + make_vt_style(Current.Style, Str, Last.Style); + ModeAdded = true; } + assert(ModeAdded); + Str += L'm'; } @@ -1310,7 +1327,7 @@ namespace console_detail a.Reserved[1] == b.Reserved[1]; } - static void make_vt_sequence(span Input, string& Str, std::optional& LastColor) + static void make_vt_sequence(span Input, string& Str, FarColor& LastColor) { const auto CharWidthEnabled = char_width::is_enabled(); @@ -1386,7 +1403,7 @@ WARNING_POP() } } - if (!LastColor.has_value() || !is_same_color(Cell.Attributes, *LastColor)) + if (!is_same_color(Cell.Attributes, LastColor)) { make_vt_attributes(Cell.Attributes, Str, LastColor); LastColor = Cell.Attributes; @@ -1410,8 +1427,16 @@ WARNING_POP() class console::implementation { public: - static bool WriteOutputVT(matrix& Buffer, rectangle const SubRect, rectangle const& WriteRegion) + static bool WriteOutputVT(matrix& Buffer, point const BufferCoord, rectangle const& WriteRegion) { + const rectangle SubRect + { + BufferCoord.x, + BufferCoord.y, + BufferCoord.x + WriteRegion.width() - 1, + BufferCoord.y + WriteRegion.height() - 1 + }; + const auto Out = ::console.GetOutputHandle(); CONSOLE_SCREEN_BUFFER_INFO csbi; @@ -1454,7 +1479,7 @@ WARNING_POP() if (const auto Area = SubRect.width() * SubRect.height(); Area > 4) Str.reserve(std::max(1024, Area * 2)); - std::optional LastColor; + auto LastColor = colors::default_color(); point ViewportSize; { @@ -1494,10 +1519,12 @@ WARNING_POP() ANSISYSRC // Restore cursor position CSI L"1B" // Move cursor down ANSISYSSC // Save again - L""sv; - // For some reason restoring the cursor position affects colors - LastColor.reset(); + // conhost used to preserve colors after ANSISYSRC, but it is not the case anymore (see terminal#14612) + // Explicitly reset them here for consistency across implementations. + CSI L"m"sv; + + LastColor = colors::default_color(); } make_vt_sequence(Buffer[i].subspan(SubRect.left, SubRect.width()), Str, LastColor); @@ -1519,7 +1546,7 @@ WARNING_POP() } - return ::console.Write(CSI L"0m"sv); + return ::console.Write(CSI L"m"sv); } class cursor_suppressor: public hide_cursor @@ -1563,32 +1590,16 @@ WARNING_POP() return true; } - static bool WriteOutputNTImplDebug(CHAR_INFO* const Buffer, point const BufferSize, rectangle const& WriteRegion) + static bool WriteOutputNT(matrix& Buffer, point const BufferCoord, rectangle const& WriteRegion) { - if constexpr ((false)) + const rectangle SubRect { - assert(BufferSize.x == WriteRegion.width()); - assert(BufferSize.y == WriteRegion.height()); - - const auto invert_colors = [&] - { - for (auto& i: span(Buffer, BufferSize.x* BufferSize.y)) - i.Attributes = (i.Attributes & FCF_RAWATTR_MASK) | extract_integer(~i.Attributes); - }; - - invert_colors(); - - WriteOutputNTImpl(Buffer, BufferSize, WriteRegion); - Sleep(50); - - invert_colors(); - } - - return WriteOutputNTImpl(Buffer, BufferSize, WriteRegion) != FALSE; - } + BufferCoord.x, + BufferCoord.y, + BufferCoord.x + WriteRegion.width() - 1, + BufferCoord.y + WriteRegion.height() - 1 + }; - static bool WriteOutputNT(matrix& Buffer, rectangle const SubRect, rectangle const& WriteRegion) - { std::vector ConsoleBuffer; ConsoleBuffer.reserve(SubRect.width() * SubRect.height()); @@ -1659,13 +1670,13 @@ WARNING_POP() PartialWriteRegion.height() }; - if (!WriteOutputNTImplDebug(ConsoleBuffer.data() + i * PartialBufferSize.x, PartialBufferSize, PartialWriteRegion)) + if (!WriteOutputNTImpl(ConsoleBuffer.data() + i * PartialBufferSize.x, PartialBufferSize, PartialWriteRegion)) return false; } } else { - if (!WriteOutputNTImplDebug(ConsoleBuffer.data(), BufferSize, WriteRegion)) + if (!WriteOutputNTImpl(ConsoleBuffer.data(), BufferSize, WriteRegion)) return false; } @@ -1743,6 +1754,15 @@ WARNING_POP() bool console::WriteOutput(matrix& Buffer, point BufferCoord, const rectangle& WriteRegionRelative) const { + if (IsVtActive()) + { + const int Delta = sWindowMode? GetDelta() : 0; + auto WriteRegion = WriteRegionRelative; + WriteRegion.top += Delta; + WriteRegion.bottom += Delta; + return implementation::WriteOutputVT(Buffer, BufferCoord, WriteRegion); + } + if (ExternalConsole.Imports.pWriteOutput) { const COORD BufferSize{ static_cast(Buffer.width()), static_cast(Buffer.height()) }; @@ -1755,15 +1775,19 @@ WARNING_POP() WriteRegion.top += Delta; WriteRegion.bottom += Delta; - const rectangle SubRect + return implementation::WriteOutputNT(Buffer, BufferCoord, WriteRegion); + } + + bool console::WriteOutputGather(matrix& Buffer, span WriteRegions) const + { + // TODO: VT can handle this in one go + for (const auto& i: WriteRegions) { - BufferCoord.x, - BufferCoord.y, - BufferCoord.x + WriteRegion.width() - 1, - BufferCoord.y + WriteRegion.height() - 1 - }; + if (!WriteOutput(Buffer, { i.left, i.top }, i)) + return false; + } - return (IsVtActive()? implementation::WriteOutputVT : implementation::WriteOutputNT)(Buffer, SubRect, WriteRegion); + return true; } bool console::Read(span const Buffer, size_t& Size) const @@ -2538,8 +2562,8 @@ TEST_CASE("console.vt_color") for (const auto& i: Tests) { string Str[2]; - console_detail::make_vt_color(i.Color, Str[0], 0); - console_detail::make_vt_color(i.Color, Str[1], 1); + 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); } @@ -2547,31 +2571,51 @@ TEST_CASE("console.vt_color") TEST_CASE("console.vt_sequence") { + FAR_CHAR_INFO const def{ L' ', colors::default_color() }; + + const auto check = [](span const Buffer, string_view const Expected) { - FAR_CHAR_INFO Buffer[3]{}; - Buffer[0].Char = L' '; - Buffer[0].Attributes.Flags = FCF_BG_INDEX | FCF_FG_INDEX | FCF_FG_BOLD; - Buffer[0].Attributes.BackgroundColor = 1; - Buffer[0].Attributes.ForegroundColor = 10; + string Actual; + auto LastColor = colors::default_color(); + console_detail::make_vt_sequence(Buffer, Actual, LastColor); + REQUIRE(Expected == Actual); + }; + +#define SGR(modes) CSI #modes "m" + + { + FAR_CHAR_INFO Buffer[]{ def }; + check(Buffer, L" "sv); + } + + { + FAR_CHAR_INFO Buffer[]{ def, def, def, def }; + Buffer[1].Attributes.BackgroundColor = colors::opaque(F_MAGENTA); + Buffer[2].Attributes.ForegroundColor = colors::opaque(F_GREEN); + Buffer[3].Attributes.Flags |= FCF_FG_BOLD; + check(Buffer, L" " SGR(45) L" " SGR(32;49) " " SGR(39;1) " "sv); + } + + { + FAR_CHAR_INFO Buffer[]{ def, def, def }; + Buffer[0].Attributes.Flags |= FCF_FG_BOLD; + Buffer[0].Attributes.BackgroundColor = colors::opaque(F_BLUE); + Buffer[0].Attributes.ForegroundColor = colors::opaque(F_LIGHTGREEN); Buffer[1] = Buffer[0]; Buffer[2] = Buffer[1]; flags::clear(Buffer[2].Attributes.Flags, FCF_FG_BOLD); - string Str; - std::optional LastColor; - console_detail::make_vt_sequence(Buffer, Str, LastColor); - - REQUIRE(Str == CSI L"92;44;1m" L" " CSI L"22m" L" "sv); + check(Buffer, SGR(92;44;1) L" " SGR(22) L" "sv); } { - FAR_CHAR_INFO Buffer[3]{}; - Buffer[0].Char = L' '; + FAR_CHAR_INFO Buffer[]{ def, def, def }; + Buffer[0].Attributes.Flags = FCF_BG_INDEX | FCF_FG_INDEX | FCF_FG_UNDERLINE2; - Buffer[0].Attributes.BackgroundColor = 1; - Buffer[0].Attributes.ForegroundColor = 10; + Buffer[0].Attributes.BackgroundColor = colors::opaque(F_BLUE); + Buffer[0].Attributes.ForegroundColor = colors::opaque(F_LIGHTGREEN); Buffer[1] = Buffer[0]; @@ -2579,12 +2623,10 @@ TEST_CASE("console.vt_sequence") flags::clear(Buffer[2].Attributes.Flags, FCF_FG_UNDERLINE2); flags::set(Buffer[2].Attributes.Flags, FCF_FG_UNDERLINE); - string Str; - std::optional LastColor; - console_detail::make_vt_sequence(Buffer, Str, LastColor); - - REQUIRE(Str == CSI L"92;44;21m" L" " CSI L"24;4m" L" "sv); + check(Buffer, SGR(92;44;21) L" " SGR(24;4) L" "sv); } + +#undef SGR } #endif diff --git a/far/console.hpp b/far/console.hpp index aab61b91313..fcaadd3dba4 100644 --- a/far/console.hpp +++ b/far/console.hpp @@ -59,7 +59,7 @@ enum CLEAR_REGION }; wchar_t ReplaceControlCharacter(wchar_t Char); -void sanitise_pair(FAR_CHAR_INFO& First, FAR_CHAR_INFO& Second); +bool sanitise_pair(FAR_CHAR_INFO& First, FAR_CHAR_INFO& Second); bool get_console_screen_buffer_info(HANDLE ConsoleOutput, CONSOLE_SCREEN_BUFFER_INFO* ConsoleScreenBufferInfo); namespace console_detail @@ -121,6 +121,7 @@ namespace console_detail bool ReadOutput(matrix& Buffer, const rectangle& ReadRegion) const { return ReadOutput(Buffer, {}, ReadRegion); } bool WriteOutput(matrix& Buffer, point BufferCoord, rectangle const& WriteRegionRelative) const; bool WriteOutput(matrix& Buffer, rectangle const& WriteRegion) const { return WriteOutput(Buffer, {}, WriteRegion); } + bool WriteOutputGather(matrix& Buffer, span WriteRegions) const; bool Read(span Buffer, size_t& Size) const; bool Write(string_view Str) const; bool Commit() const; diff --git a/far/far.vcxproj b/far/far.vcxproj index 3f56f3cacf3..9d4f9ab4e50 100644 --- a/far/far.vcxproj +++ b/far/far.vcxproj @@ -461,48 +461,14 @@ cl /nologo /c /Fo"$(IntDir)%(Filename)_c++.testobj" /TP api_test.c - + Transforming %(Identity) to redistributable form... - $(M4Cmd) -DINPUT=%(Identity) headers.m4 > Include\farcolor.hpp - headers.m4;farversion.m4;vbuild.m4;%(AdditionalInputs) - Include\%(Identity);%(Outputs) - - - Transforming %(Identity) to redistributable form... - $(M4Cmd) -DINPUT=%(Identity) headers.m4 > Include\plugin.hpp + $(M4Cmd) -DINPUT=%(Identity) headers.m4 > Include\%(Identity) headers.m4;farversion.m4;vbuild.m4;%(AdditionalInputs) Include\%(Identity);%(Outputs) - - Document - Compiling %(Identity)... - $(M4Cmd) %(Identity) > $(BootstrapDir)%(FileName) - farversion.m4;vbuild.m4;%(AdditionalInputs) - $(BootstrapDir)%(FileName);%(Outputs) - - - Document - Compiling %(Identity)... - $(M4Cmd) %(Identity) > $(BootstrapDir)%(FileName) - farversion.m4;vbuild.m4;%(AdditionalInputs) - $(BootstrapDir)%(FileName);%(Outputs) - - - Document - Compiling %(Identity)... - $(M4Cmd) %(Identity) > $(BootstrapDir)%(FileName) - farversion.m4;vbuild.m4;%(AdditionalInputs) - $(BootstrapDir)%(FileName);%(Outputs) - - - Document - Compiling %(Identity)... - $(M4Cmd) %(Identity) > $(BootstrapDir)%(FileName) - farversion.m4;vbuild.m4;%(AdditionalInputs) - $(BootstrapDir)%(FileName);%(Outputs) - - + Document Compiling %(Identity)... $(M4Cmd) %(Identity) > $(BootstrapDir)%(FileName) @@ -535,14 +501,8 @@ cl /nologo /c /Fo"$(IntDir)%(Filename)_c++.testobj" /TP api_test.c true - - - - - + - - diff --git a/far/far.vcxproj.filters b/far/far.vcxproj.filters index 7a1df14ff96..6676f138819 100644 --- a/far/far.vcxproj.filters +++ b/far/far.vcxproj.filters @@ -1,5 +1,5 @@  - + {ee8269df-ee5e-4cb1-b5e2-41705afcbbb0} @@ -1176,25 +1176,7 @@ - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - - Resource Files - - + Resource Files @@ -1217,33 +1199,18 @@ Generated Files - - Dependencies - - + Dependencies - - Dependencies - - + Header Files - - Dependencies - - - Dependencies - Dependencies Dependencies - - Header Files - Source Files diff --git a/far/hilight.cpp b/far/hilight.cpp index d07b4c44874..2c1dd7392ff 100644 --- a/far/hilight.cpp +++ b/far/hilight.cpp @@ -304,21 +304,19 @@ static void ApplyBlackOnBlackColor(highlight::element::colors_array::value_type& { const auto InheritColor = [](FarColor& Color, const FarColor& Base) { - if (colors::color_bits(Color.ForegroundColor) || colors::color_bits(Color.BackgroundColor)) - return; + const auto LegacyUseDefaultPaletteColor = + colors::is_opaque(Color.ForegroundColor) && !colors::color_value(Color.ForegroundColor) && + colors::is_opaque(Color.BackgroundColor) && !colors::color_value(Color.BackgroundColor); - colors::set_color_value(Color.BackgroundColor, Base.BackgroundColor); - colors::set_color_value(Color.ForegroundColor, Base.ForegroundColor); - flags::copy(Color.Flags, FCF_INDEXMASK, Base.Flags); + if (!LegacyUseDefaultPaletteColor) + return; - if (Color.Flags & FCF_INHERIT_STYLE) - flags::set(Color.Flags, Base.Flags & FCF_STYLEMASK); + colors::make_transparent(Color.ForegroundColor); + colors::make_transparent(Color.BackgroundColor); + Color = colors::merge(Base, Color); }; - //Применим black on black. - //Для файлов возьмем цвета панели не изменяя прозрачность. InheritColor(Colors.FileColor, Global->Opt->Palette[PaletteColor]); - //Для пометки возьмем цвета файла включая прозрачность. InheritColor(Colors.MarkColor, Colors.FileColor); } diff --git a/far/palette.cpp b/far/palette.cpp index 992ca43b735..4fd804584eb 100644 --- a/far/palette.cpp +++ b/far/palette.cpp @@ -236,7 +236,8 @@ void palette::Reset(bool const RGB) if (i.Index == ColorsInit::Default) return Color; - flags::clear(Color.Flags, FCF_INDEXMASK); + Color.SetFgIndex(false); + Color.SetBgIndex(false); colors::set_color_bits(Color.ForegroundColor, Palette[colors::index_bits(Color.ForegroundColor)]); colors::set_color_bits(Color.BackgroundColor, Palette[colors::index_bits(Color.BackgroundColor)]); return Color; diff --git a/far/scrbuf.cpp b/far/scrbuf.cpp index 79baa6735bb..a1d8e91186b 100644 --- a/far/scrbuf.cpp +++ b/far/scrbuf.cpp @@ -100,14 +100,15 @@ static void invalidate_broken_pairs_in_cache(matrixconst& Buf, ma &Buf0 = BufRowData[X1X2.first], &Buf1 = BufRowData[X1X2.second]; - std::array Pair{ Buf0, Buf1 }; - sanitise_pair(Pair[0], Pair[1]); - - if (Pair[0] != Buf0) - ShadowRowData[X1X2.first] = {}; + auto Pair0 = Buf0, Pair1 = Buf1; + if (sanitise_pair(Pair0, Pair1)) + { + if (Pair0 != Buf0) + ShadowRowData[X1X2.first] = {}; - if (Pair[1] != Buf1) - ShadowRowData[X1X2.second] = {}; + if (Pair1 != Buf1) + ShadowRowData[X1X2.second] = {}; + } } ScreenBuf::ScreenBuf(): @@ -670,11 +671,7 @@ void ScreenBuf::Flush(flush_type FlushType) Shadow = Buf; - for (const auto& i: WriteList) - { - console.WriteOutput(Shadow, { i.left, i.top }, i); - } - + console.WriteOutputGather(Shadow, WriteList); console.Commit(); } From d68079ba27e04eaf058fb484b77e4b0ac7d94d55 Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Mon, 6 Nov 2023 18:36:02 +0000 Subject: [PATCH 03/16] Build & changelog --- far/changelog | 11 +++++++++++ far/vbuild.m4 | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/far/changelog b/far/changelog index cfbe82d5791..8ec2ddfbcbd 100644 --- a/far/changelog +++ b/far/changelog @@ -1,3 +1,14 @@ +-------------------------------------------------------------------------------- +drkns 2023-11-06 18:35:45+00:00 - build 6208 + +1. Refactoring. + +2. Clang: + - Fix build + - Fix warnings + - Remove outdated workarounds + - Bump version + -------------------------------------------------------------------------------- yjh 2023-11-02 09:24:30+03:00 - build 6207 diff --git a/far/vbuild.m4 b/far/vbuild.m4 index 2c5c6bae979..7251971d339 100644 --- a/far/vbuild.m4 +++ b/far/vbuild.m4 @@ -1 +1 @@ -6207 +6208 From 054c606d3d2dd573a30ba73f8497eb79a5ff2a60 Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Mon, 6 Nov 2023 23:54:25 +0000 Subject: [PATCH 04/16] More clang --- far/api_test.c | 8 ++++---- far/desktop.cpp | 2 ++ far/desktop.hpp | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/far/api_test.c b/far/api_test.c index f6479074e17..8b366eae26f 100644 --- a/far/api_test.c +++ b/far/api_test.c @@ -35,8 +35,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Include/farcolor.hpp" #ifdef __cplusplus -static_assert(FCF_INDEXMASK == (FCF_FG_INDEX | FCF_BG_INDEX)); -static_assert(FCF_FG_4BIT == FCF_FG_INDEX); -static_assert(FCF_BG_4BIT == FCF_BG_INDEX); -static_assert(FCF_4BITMASK == FCF_INDEXMASK); +static_assert(FCF_INDEXMASK == (FCF_FG_INDEX | FCF_BG_INDEX), ""); +static_assert(FCF_FG_4BIT == FCF_FG_INDEX, ""); +static_assert(FCF_BG_4BIT == FCF_BG_INDEX, ""); +static_assert(FCF_4BITMASK == FCF_INDEXMASK, ""); #endif diff --git a/far/desktop.cpp b/far/desktop.cpp index 7b70a5ce932..f1c90bf16c3 100644 --- a/far/desktop.cpp +++ b/far/desktop.cpp @@ -60,6 +60,8 @@ desktop::desktop(private_tag) SetMacroMode(MACROAREA_DESKTOP); } +desktop::~desktop() = default; + desktop_ptr desktop::create() { return std::make_shared(private_tag()); diff --git a/far/desktop.hpp b/far/desktop.hpp index 33cefe937b4..24ca5a0cbf4 100644 --- a/far/desktop.hpp +++ b/far/desktop.hpp @@ -53,6 +53,7 @@ class desktop final: public window public: static desktop_ptr create(); explicit desktop(private_tag); + ~desktop() override; int GetType() const override { return windowtype_desktop; } int GetTypeAndName(string& Type, string& Name) override { Type = GetTitle(); return GetType(); } From cc396f0bc21ea875b51c5d8c6115865d3188b3ba Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Tue, 7 Nov 2023 01:49:03 +0000 Subject: [PATCH 05/16] Correction of 6204 --- far/changelog | 5 +++++ far/console.cpp | 2 +- far/vbuild.m4 | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/far/changelog b/far/changelog index 8ec2ddfbcbd..85fd50ea4d6 100644 --- a/far/changelog +++ b/far/changelog @@ -1,3 +1,8 @@ +-------------------------------------------------------------------------------- +drkns 2023-11-07 01:48:43+00:00 - build 6219 + +1. Correction of 6204. + -------------------------------------------------------------------------------- drkns 2023-11-06 18:35:45+00:00 - build 6208 diff --git a/far/console.cpp b/far/console.cpp index 69c63f942c6..3ccc0f6bff2 100644 --- a/far/console.cpp +++ b/far/console.cpp @@ -1529,7 +1529,7 @@ WARNING_POP() make_vt_sequence(Buffer[i].subspan(SubRect.left, SubRect.width()), Str, LastColor); - if (SubRect.right == csbi.srWindow.Right && i != csbi.srWindow.Bottom - ::GetDelta(csbi)) + if (SubRect.right == ScrX && i != ScrY) { // Explicitly ending rows with \n should (hopefully) give a hint to the host // that we're writing something structured and not just a stream, diff --git a/far/vbuild.m4 b/far/vbuild.m4 index 7251971d339..dffad32e566 100644 --- a/far/vbuild.m4 +++ b/far/vbuild.m4 @@ -1 +1 @@ -6208 +6209 From 9b93fa3b9e02832fdffbae411409a72406f99975 Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Tue, 7 Nov 2023 21:27:28 +0000 Subject: [PATCH 06/16] Add missing log entry --- far/changelog | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/far/changelog b/far/changelog index 85fd50ea4d6..3fe85aed3cb 100644 --- a/far/changelog +++ b/far/changelog @@ -14,6 +14,17 @@ drkns 2023-11-06 18:35:45+00:00 - build 6208 - Remove outdated workarounds - Bump version +3. Clarification of "black on black - default color" logic in Files highlighting: + black on black is now considered "default" (or "transparent") only when both + foreground and background are fully opaque. + If you noticed a sudden black color somewhere where it shouldn't be - make sure + that both foreground and background are either fully opaque or fully transparent, + either via the UI or: + 1. export the config + 2. search for: background="00000000" foreground="FF000000" + replace with: background="00000000" foreground="00000000" + 3. save and import. + -------------------------------------------------------------------------------- yjh 2023-11-02 09:24:30+03:00 - build 6207 From adb8db1f6804ff04438ba2226d0b0f53d3b0ade3 Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Wed, 8 Nov 2023 19:24:38 +0000 Subject: [PATCH 07/16] Typo --- far/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/far/changelog b/far/changelog index 3fe85aed3cb..a07a13d34e7 100644 --- a/far/changelog +++ b/far/changelog @@ -1,5 +1,5 @@ -------------------------------------------------------------------------------- -drkns 2023-11-07 01:48:43+00:00 - build 6219 +drkns 2023-11-07 01:48:43+00:00 - build 6209 1. Correction of 6204. From f54550d5397cce4499cd2196e17cf34e032c911b Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Sat, 11 Nov 2023 23:44:29 +0000 Subject: [PATCH 08/16] M#4019: restore elevation requests for network paths --- far/dirmix.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/far/dirmix.cpp b/far/dirmix.cpp index 371555628c5..940a163dacf 100644 --- a/far/dirmix.cpp +++ b/far/dirmix.cpp @@ -109,13 +109,6 @@ bool FarChDir(string_view const NewDir) const auto IsNetworkPath = PathType == root_type::remote || PathType == root_type::unc_remote; - std::optional NoElevation; - - // It's usually useless over the network anyway - // TODO: a more generic/common way - if (IsNetworkPath) - NoElevation.emplace(); - if (os::fs::set_current_directory(Directory)) { set_drive_env_curdir(Directory); From c13020ac49d4fbea083f8c3b03d7ff4eba73af4b Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Sat, 11 Nov 2023 23:44:30 +0000 Subject: [PATCH 09/16] gh-747: Build 6209 crashes on start with the profile from build 5629 --- far/config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/far/config.cpp b/far/config.cpp index 11e3b2157bc..45b7aae65ae 100644 --- a/far/config.cpp +++ b/far/config.cpp @@ -2266,7 +2266,7 @@ void Options::ReadSortLayers() for (auto& [Layers, i]: enumerate(PanelSortLayers)) { string LayersStr; - if (ConfigProvider().GeneralCfg()->GetValue(NKeyPanelSortLayers, str(i), LayersStr)) + if (ConfigProvider().GeneralCfg()->GetValue(NKeyPanelSortLayers, str(i), LayersStr) && !LayersStr.empty()) Layers = deserialise_sort_layers(LayersStr); if (Layers.empty()) From e332efb8c07423b4613dc8fb6268df541440b051 Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Sat, 11 Nov 2023 23:44:30 +0000 Subject: [PATCH 10/16] Refactoring --- far/color_picker.cpp | 173 ++++++++++++++++++++++++------------------- far/colormix.cpp | 32 ++++---- far/configdb.cpp | 93 +++++++++++++---------- far/console.cpp | 19 ++++- far/scrbuf.cpp | 64 ++++++++-------- far/vmenu.cpp | 3 - 6 files changed, 216 insertions(+), 168 deletions(-) diff --git a/far/color_picker.cpp b/far/color_picker.cpp index 53c9f137f49..b08c3812652 100644 --- a/far/color_picker.cpp +++ b/far/color_picker.cpp @@ -93,7 +93,7 @@ static auto color_code(colors::single_color const Color) far::format(L"{:08X}"sv, colors::ARGB2ABGR(Color.Value)); } -static std::optional parse_color(string_view const Str, bool const IsIndex) +static std::optional parse_color(string_view const Str, bool const IsIndex, bool const IsDefault) { if (IsIndex) { @@ -101,13 +101,22 @@ static std::optional parse_color(string_view const Str, bool const IsI if (!from_string(Str.substr(0, 2), Alpha, {}, 16)) return {}; - unsigned Index; - if (!from_string(Str.substr(6, 2), Index, {}, 16)) - return {}; - COLORREF Result{}; + + if (IsDefault) + { + Result = colors::default_colorref(); + } + else + { + unsigned Index; + if (!from_string(Str.substr(6, 2), Index, {}, 16)) + return {}; + + colors::set_index_value(Result, Index); + } + colors::set_alpha_value(Result, Alpha); - colors::set_index_value(Result, Index); return Result; } @@ -270,7 +279,9 @@ struct color_state intptr_t GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2); }; -static const auto DM_UPDATECOLORCODE = DM_USER + 1; +static const auto + DM_UPDATECOLORCODE = DM_USER + 1, + DM_UPDATEPREVIEW = DM_USER + 2; intptr_t single_color_state::GetSingleColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2) { @@ -279,7 +290,7 @@ intptr_t single_color_state::GetSingleColorDlgProc(Dialog* Dlg, intptr_t Msg, in if (Param1 - Offset == cb::color_default_radio) { auto Color = colors::default_color(); - if (Offset == cd::fg_first) + if (Offset != cd::bg_first) Color.Flags |= FCF_FG_INVERSE; return Color; @@ -351,7 +362,9 @@ intptr_t single_color_state::GetSingleColorDlgProc(Dialog* Dlg, intptr_t Msg, in if (Param1 - Offset == cb::button_256) { - FarColor FakeColor{ .BackgroundColor = CurColor.Value }; + const auto ResolvedColor = colors::resolve_default(CurColor.Value, Offset != cd::bg_first); + + FarColor FakeColor{ .BackgroundColor = ResolvedColor }; FakeColor.SetBgIndex(CurColor.IsIndex); if (auto Color = colors::index_value(colors::FarColorToConsole256Color(FakeColor).BackgroundIndex); pick_color_256(Color)) @@ -369,7 +382,7 @@ intptr_t single_color_state::GetSingleColorDlgProc(Dialog* Dlg, intptr_t Msg, in if (Param1 - Offset == cb::button_rgb) { - const auto ResolvedColor = colors::resolve_default(CurColor.Value, Offset == cd::fg_first); + const auto ResolvedColor = colors::resolve_default(CurColor.Value, Offset != cd::bg_first); auto Color = colors::color_value( CurColor.IsIndex? @@ -400,7 +413,7 @@ intptr_t single_color_state::GetSingleColorDlgProc(Dialog* Dlg, intptr_t Msg, in if (!std::any_of(Iterator, Iterator.end(), std::iswxdigit)) return false; - const auto ParsedColor = parse_color(Item.Data, CurColor.IsIndex); + const auto ParsedColor = parse_color(Item.Data, CurColor.IsIndex, colors::is_default(CurColor.Value)); if (!ParsedColor) return false; @@ -464,6 +477,63 @@ intptr_t single_color_state::GetSingleColorDlgProc(Dialog* Dlg, intptr_t Msg, in return Dlg->DefProc(Msg, Param1, Param2); } +#define COLOR_COLUMN(x, y, index) \ + COLOR_CELL(x + 3 * index, y + 0), \ + COLOR_CELL(x + 3 * index, y + 1) + +#define COLOR_PLANE(column, x, y) \ + column(x, y, 0), \ + column(x, y, 1), \ + column(x, y, 2), \ + column(x, y, 3), \ + column(x, y, 4), \ + column(x, y, 5), \ + column(x, y, 6), \ + column(x, y, 7) + +static std::optional get_control_id(COLORREF const ColorPart, size_t const Offset) +{ + if (colors::is_default(ColorPart)) + return Offset + cb::color_first_radio + colors::index::nt_size; + + const auto Index = colors::index_value(ColorPart); + if (Index > colors::index::nt_last) + return {}; + + return Offset + cb::color_first_radio + control_by_color[Index]; +} + +static auto activate_control(COLORREF const Color, span ColorDlgItems, size_t const Offset) +{ + const auto ControlId = get_control_id(Color, Offset); + if (!ControlId) + return false; + + ColorDlgItems[*ControlId].Selected = true; + ColorDlgItems[*ControlId].Flags |= DIF_FOCUS; + return true; +} + +static void disable_if_needed(COLORREF const Color, span ColorDlgItems, size_t const Offset) +{ + if (colors::is_transparent(Color)) + { + for (const auto& i: irange(cb::color_first_radio, cb::color_last_radio + 2)) + { + ColorDlgItems[Offset + i].Flags |= DIF_DISABLE; + } + + ColorDlgItems[Offset + cb::colorcode_edit].Flags |= DIF_DISABLE; + ColorDlgItems[Offset + cb::colorcode_text].Flags |= DIF_DISABLE; + ColorDlgItems[Offset + cb::button_256].Flags |= DIF_DISABLE; + ColorDlgItems[Offset + cb::button_rgb].Flags |= DIF_DISABLE; + } + else + { + ColorDlgItems[Offset + cb::color_active_checkbox].Selected = BSTATE_CHECKED; + } +}; + intptr_t color_state::GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2) { switch (Msg) @@ -512,8 +582,7 @@ intptr_t color_state::GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1 break; - case DM_UPDATECOLORCODE: - if (delegate_proc(Dlg, Msg, Param1, Param2)) + case DM_UPDATEPREVIEW: { SCOPED_ACTION(Dialog::suppress_redraw)(Dlg); for (const auto& i : irange(cd::sample_text_first, cd::sample_text_last + 1)) @@ -522,6 +591,13 @@ intptr_t color_state::GetColorDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1 } return TRUE; } + + case DM_UPDATECOLORCODE: + if (delegate_proc(Dlg, Msg, Param1, Param2)) + { + Dlg->SendMessage(DM_UPDATEPREVIEW, 0, {}); + return TRUE; + } return FALSE; default: @@ -566,20 +642,6 @@ bool GetColorDialog(FarColor& Color, bool const bCentered, const FarColor* const { DI_TEXT, {{Fg4X, Fg4Y}, {0, Fg4Y}}, DIF_NONE, msg(lng::MSetColorForeground), }, { DI_CHECKBOX, {{Fg4X, Fg4Y}, {0, Fg4Y}}, DIF_NONE, msg(lng::MSetColorForeground), }, -#define COLOR_COLUMN(x, y, index) \ - COLOR_CELL(x + 3 * index, y + 0), \ - COLOR_CELL(x + 3 * index, y + 1) - -#define COLOR_PLANE(column, x, y) \ - column(x, y, 0), \ - column(x, y, 1), \ - column(x, y, 2), \ - column(x, y, 3), \ - column(x, y, 4), \ - column(x, y, 5), \ - column(x, y, 6), \ - column(x, y, 7) - COLOR_PLANE(COLOR_COLUMN, Fg4X, Fg4Y + 1), COLOR_CELL(Fg4X, Fg4Y + 3), { DI_TEXT, { { Fg4X + 4, Fg4Y + 3 }, { 0, Fg4Y + 3 } }, DIF_NONE, msg(lng::MSetColorForegroundDefault) }, @@ -596,9 +658,6 @@ bool GetColorDialog(FarColor& Color, bool const bCentered, const FarColor* const COLOR_CELL(Bg4X, Bg4Y + 3), { DI_TEXT, { { Bg4X + 4, Bg4Y + 3 }, { 0, Bg4Y + 3 } }, DIF_NONE, msg(lng::MSetColorBackgroundDefault) }, -#undef COLOR_PLANE -#undef COLOR_COLUMN - { DI_TEXT, {{30, 7 }, {0, 7 }}, DIF_NONE, msg(Color.IsBgIndex()? Color.IsBgDefault()? lng::MSetColorBackDefault : lng::MSetColorBackIndex : lng::MSetColorBackAARRGGBB) }, { DI_FIXEDIT, {{30, 8 }, {37, 8 }}, DIF_MASKEDIT, }, { DI_BUTTON, {{30, 9 }, {37, 9 }}, DIF_NONE, msg(lng::MSetColorBack256), }, @@ -668,34 +727,11 @@ bool GetColorDialog(FarColor& Color, bool const bCentered, const FarColor* const ForegroundColorControlActivated = false, BackgroundColorControlActivated = false; - const auto get_control_id = [&](COLORREF const ColorPart, size_t const Offset) -> std::optional - { - if (colors::is_default(ColorPart)) - return Offset + cb::color_first_radio + colors::index::nt_size; - - const auto Index = colors::index_value(ColorPart); - if (Index > colors::index::nt_last) - return {}; - - return Offset + cb::color_first_radio + control_by_color[Index]; - }; - - const auto activate_control = [&](COLORREF const ColorPart, size_t const Offset) - { - const auto ControlId = get_control_id(ColorPart, Offset); - if (!ControlId) - return false; - - ColorDlg[*ControlId].Selected = true; - ColorDlg[*ControlId].Flags |= DIF_FOCUS; - return true; - }; - if (Color.IsFgIndex()) - ForegroundColorControlActivated = activate_control(Color.ForegroundColor, cd::fg_first); + ForegroundColorControlActivated = activate_control(Color.ForegroundColor, ColorDlg, cd::fg_first); if (Color.IsBgIndex()) - BackgroundColorControlActivated = activate_control(Color.BackgroundColor, cd::bg_first); + BackgroundColorControlActivated = activate_control(Color.BackgroundColor, ColorDlg, cd::bg_first); if (!ForegroundColorControlActivated && !BackgroundColorControlActivated) ColorDlg[fg_item(cb::colorcode_edit)].Flags |= DIF_FOCUS; @@ -710,28 +746,8 @@ bool GetColorDialog(FarColor& Color, bool const bCentered, const FarColor* const ColorDlg[fg_item(cb::color_text)].Flags |= DIF_HIDDEN | DIF_DISABLE; ColorDlg[bg_item(cb::color_text)].Flags |= DIF_HIDDEN | DIF_DISABLE; - const auto disable_if_needed = [&](size_t const Offset) - { - if (colors::is_transparent(Offset == cd::fg_first? Color.ForegroundColor : Color.BackgroundColor)) - { - for (const auto& i: irange(cb::color_first_radio, cb::color_last_radio + 2)) - { - ColorDlg[Offset + i].Flags |= DIF_DISABLE; - } - - ColorDlg[Offset + cb::colorcode_edit].Flags |= DIF_DISABLE; - ColorDlg[Offset + cb::colorcode_text].Flags |= DIF_DISABLE; - ColorDlg[Offset + cb::button_256].Flags |= DIF_DISABLE; - ColorDlg[Offset + cb::button_rgb].Flags |= DIF_DISABLE; - } - else - { - ColorDlg[Offset + cb::color_active_checkbox].Selected = BSTATE_CHECKED; - } - }; - - disable_if_needed(cd::fg_first); - disable_if_needed(cd::bg_first); + disable_if_needed(Color.ForegroundColor, ColorDlg, cd::fg_first); + disable_if_needed(Color.BackgroundColor, ColorDlg, cd::bg_first); } else { @@ -775,3 +791,6 @@ bool GetColorDialog(FarColor& Color, bool const bCentered, const FarColor* const } } + +#undef COLOR_PLANE +#undef COLOR_COLUMN diff --git a/far/colormix.cpp b/far/colormix.cpp index c15d847e35a..65b87850a3c 100644 --- a/far/colormix.cpp +++ b/far/colormix.cpp @@ -591,7 +591,7 @@ FarColor NtColorToFarColor(WORD Color) { return { - FCF_INDEXMASK | FCF_INHERIT_STYLE | (Color & FCF_RAWATTR_MASK), + FCF_FG_INDEX | FCF_BG_INDEX | FCF_INHERIT_STYLE | (Color & FCF_RAWATTR_MASK), { opaque(index_bits(Color >> ConsoleFgShift) & index::nt_mask) }, { opaque(index_bits(Color >> ConsoleBgShift) & index::nt_mask) } }; @@ -663,6 +663,9 @@ static bool ExtractColor(string_view const Str, COLORREF& Target, FARCOLORFLAGS& TargetFlags |= SetFlag; } + if (is_transparent(Target)) + make_opaque(Target); + return true; } @@ -883,8 +886,8 @@ TEST_CASE("colors.default") REQUIRE(Color.IsFgDefault()); REQUIRE(Color.IsBgDefault()); - REQUIRE(Color.ForegroundColor == 0xFF800000); - REQUIRE(Color.ForegroundColor == 0xFF800000); + REQUIRE(Color.ForegroundColor == colors::default_colorref()); + REQUIRE(Color.ForegroundColor == colors::default_colorref()); } TEST_CASE("colors.merge") @@ -918,18 +921,17 @@ TEST_CASE("colors.parser") } ValidTests[] { - { L"()"sv, { } }, - { L"(:)"sv, { } }, - { L"(::)"sv, { } }, - { L"(E)"sv, { FCF_FG_INDEX, {0xE}, {0} } }, - { L"(E)"sv, { FCF_FG_INDEX, {0xE}, {0} } }, - { L"(:F)"sv, { FCF_BG_INDEX, {0}, {0xF} } }, - { L"(B:C)"sv, { FCF_FG_INDEX | FCF_BG_INDEX, {0xB}, {0xC} } }, - { L"(AE)"sv, { FCF_FG_INDEX, { 0xAE }, { 0 } } }, - { L"(:AF)"sv, { FCF_BG_INDEX, { 0 }, { 0xAF } } }, - { L"(AB:AC:blink)"sv, { FCF_FG_INDEX | FCF_BG_INDEX | FCF_FG_BLINK, {0xAB}, {0xAC} } }, - { L"(T00CCCC:TE34234)"sv, { 0, {0x00CCCC00}, {0x003442E3} } }, - { L"(::bold italic)"sv, { FCF_FG_BOLD | FCF_FG_ITALIC, {0}, {0} } }, + { L"()"sv, }, + { L"(:)"sv, }, + { L"(::)"sv, }, + { L"(E)"sv, { FCF_FG_INDEX, { 0xFF00000E } } }, + { L"(:F)"sv, { FCF_BG_INDEX, {}, { 0xFF00000F } } }, + { L"(B:C)"sv, { FCF_FG_INDEX | FCF_BG_INDEX, { 0xFF00000B }, { 0xFF00000C } } }, + { L"(AE)"sv, { FCF_FG_INDEX, { 0xFF0000AE } } }, + { L"(:AF)"sv, { FCF_BG_INDEX, {}, { 0xFF0000AF } } }, + { L"(AB:AC:blink)"sv, { FCF_FG_INDEX | FCF_BG_INDEX | FCF_FG_BLINK, { 0xFF0000AB }, { 0xFF0000AC } } }, + { L"(T00CCCC:TE34234)"sv, { FCF_NONE, { 0xFFCCCC00 }, { 0xFF3442E3 } } }, + { L"(::bold italic)"sv, { FCF_FG_BOLD | FCF_FG_ITALIC } }, }; for (const auto& i: ValidTests) diff --git a/far/configdb.cpp b/far/configdb.cpp index 768b0885191..ee43e81b2d4 100644 --- a/far/configdb.cpp +++ b/far/configdb.cpp @@ -848,6 +848,50 @@ const std::pair LegacyColorFlagNames[] { FCF_BG_INDEX, L"bg4bit"sv }, }; +void color_to_xml(bytes_view const Blob, tinyxml::XMLElement& e) +{ + const auto process_color = [&](const char* const Name, COLORREF const Color) + { + if (Color) + SetAttribute(e, Name, encoding::utf8::get_bytes(to_hex_wstring(Color))); + }; + + FarColor Color; + if (!deserialise(Blob, Color)) + return; + + process_color("background", Color.BackgroundColor); + process_color("foreground", Color.ForegroundColor); + + if (Color.Flags) + { + if (const auto StrFlags = encoding::utf8::get_bytes(colors::ColorFlagsToString(Color.Flags)); !StrFlags.empty()) + SetAttribute(e, "flags", StrFlags); + } +} + +FarColor color_from_xml(tinyxml::XMLElement const& e) +{ + const auto process_color = [&](const char* const Name, COLORREF& Color) + { + if (const auto Value = e.Attribute(Name)) + Color = std::strtoul(Value, nullptr, 16); + }; + + FarColor Color{}; + + process_color("background", Color.BackgroundColor); + process_color("foreground", Color.ForegroundColor); + + if (const auto flags = e.Attribute("flags")) + { + const auto FlagsStr = encoding::utf8::get_chars(flags); + Color.Flags = colors::ColorStringToFlags(FlagsStr) | StringToFlags(FlagsStr, LegacyColorFlagNames); + } + + return Color; +} + class HighlightHierarchicalConfigDb final: public HierarchicalConfigDb { public: @@ -870,15 +914,9 @@ class HighlightHierarchicalConfigDb final: public HierarchicalConfigDb if (contains(ColorKeys, Name)) { - FarColor Color; - if (deserialise(Blob, Color)) - { - SetAttribute(e, "type", "color"sv); - SetAttribute(e, "background", encoding::utf8::get_bytes(to_hex_wstring(Color.BackgroundColor))); - SetAttribute(e, "foreground", encoding::utf8::get_bytes(to_hex_wstring(Color.ForegroundColor))); - SetAttribute(e, "flags", encoding::utf8::get_bytes(colors::ColorFlagsToString(Color.Flags))); - return; - } + SetAttribute(e, "type", "color"sv); + color_to_xml(Blob, e); + return; } return HierarchicalConfigDb::SerializeBlob(Name, Blob, e); @@ -887,21 +925,7 @@ class HighlightHierarchicalConfigDb final: public HierarchicalConfigDb bytes DeserializeBlob(const char* Type, const char* Value, const tinyxml::XMLElement& e) const override { if(Type == "color"sv) - { - FarColor Color{}; - - if (const auto background = e.Attribute("background")) - Color.BackgroundColor = std::strtoul(background, nullptr, 16); - if (const auto foreground = e.Attribute("foreground")) - Color.ForegroundColor = std::strtoul(foreground, nullptr, 16); - if (const auto flags = e.Attribute("flags")) - { - const auto FlagsStr = encoding::utf8::get_chars(flags); - Color.Flags = colors::ColorStringToFlags(FlagsStr) | StringToFlags(FlagsStr, LegacyColorFlagNames); - } - - return bytes(view_bytes(Color)); - } + return bytes(view_bytes(color_from_xml(e))); return HierarchicalConfigDb::DeserializeBlob(Type, Value, e); } @@ -918,6 +942,8 @@ class ColorsConfigDb final: public ColorsConfig, public sqlite_boilerplate private: static void Initialise(const db_initialiser& Db) { + Db.add_numeric_collation(); + static const std::string_view Schema[] { "CREATE TABLE IF NOT EXISTS colors(name TEXT NOT NULL PRIMARY KEY, value BLOB);"sv, @@ -953,19 +979,13 @@ class ColorsConfigDb final: public ColorsConfig, public sqlite_boilerplate { auto& root = CreateChild(Representation.Root(), "colors"); - const auto stmtEnumAllValues = create_stmt("SELECT name, value FROM colors ORDER BY name;"sv); + const auto stmtEnumAllValues = create_stmt("SELECT name, value FROM colors ORDER BY name COLLATE numeric;"sv); while (stmtEnumAllValues.Step()) { auto& e = CreateChild(root, "object"); - SetAttribute(e, "name", stmtEnumAllValues.GetColTextUTF8(0)); - if (FarColor Color; deserialise(stmtEnumAllValues.GetColBlob(1), Color)) - { - SetAttribute(e, "background", encoding::utf8::get_bytes(to_hex_wstring(Color.BackgroundColor))); - SetAttribute(e, "foreground", encoding::utf8::get_bytes(to_hex_wstring(Color.ForegroundColor))); - SetAttribute(e, "flags", encoding::utf8::get_bytes(colors::ColorFlagsToString(Color.Flags))); - } + color_to_xml(stmtEnumAllValues.GetColBlob(1), e); } } @@ -975,21 +995,14 @@ class ColorsConfigDb final: public ColorsConfig, public sqlite_boilerplate for (const auto& e: xml_enum(Representation.Root().FirstChildElement("colors"), "object")) { const auto name = e.Attribute("name"); - const auto background = e.Attribute("background"); - const auto foreground = e.Attribute("foreground"); - const auto flags = e.Attribute("flags"); if (!name) continue; const auto Name = encoding::utf8::get_chars(name); - if(background && foreground && flags) + if (const auto Color = color_from_xml(e); Color != FarColor{}) { - FarColor Color{}; - Color.BackgroundColor = std::strtoul(background, nullptr, 16); - Color.ForegroundColor = std::strtoul(foreground, nullptr, 16); - Color.Flags = colors::ColorStringToFlags(encoding::utf8::get_chars(flags)); SetValue(Name, Color); } else diff --git a/far/console.cpp b/far/console.cpp index 3ccc0f6bff2..e5d94cd5c45 100644 --- a/far/console.cpp +++ b/far/console.cpp @@ -2582,6 +2582,7 @@ TEST_CASE("console.vt_sequence") }; #define SGR(modes) CSI #modes "m" +#define VTSTR(str) L"" str ""sv { FAR_CHAR_INFO Buffer[]{ def }; @@ -2593,7 +2594,12 @@ TEST_CASE("console.vt_sequence") Buffer[1].Attributes.BackgroundColor = colors::opaque(F_MAGENTA); Buffer[2].Attributes.ForegroundColor = colors::opaque(F_GREEN); Buffer[3].Attributes.Flags |= FCF_FG_BOLD; - check(Buffer, L" " SGR(45) L" " SGR(32;49) " " SGR(39;1) " "sv); + check(Buffer, VTSTR( + " " + SGR(45) " " + SGR(32;49) " " + SGR(39;1) " " + )); } { @@ -2607,7 +2613,10 @@ TEST_CASE("console.vt_sequence") Buffer[2] = Buffer[1]; flags::clear(Buffer[2].Attributes.Flags, FCF_FG_BOLD); - check(Buffer, SGR(92;44;1) L" " SGR(22) L" "sv); + check(Buffer, VTSTR( + SGR(92;44;1) " " + SGR(22) " " + )); } { @@ -2623,9 +2632,13 @@ TEST_CASE("console.vt_sequence") flags::clear(Buffer[2].Attributes.Flags, FCF_FG_UNDERLINE2); flags::set(Buffer[2].Attributes.Flags, FCF_FG_UNDERLINE); - check(Buffer, SGR(92;44;21) L" " SGR(24;4) L" "sv); + check(Buffer, VTSTR( + SGR(92;44;21) L" " + SGR(24;4) " " + )); } +#undef VTSTR #undef SGR } diff --git a/far/scrbuf.cpp b/far/scrbuf.cpp index a1d8e91186b..8faee8ccfe6 100644 --- a/far/scrbuf.cpp +++ b/far/scrbuf.cpp @@ -303,45 +303,49 @@ void ScreenBuf::ApplyShadow(rectangle Where, bool const IsLegacy) colors::set_index_value(Element.Attributes.BackgroundColor, F_BLACK) : colors::set_color_value(Element.Attributes.BackgroundColor, 0); - if (Element.Attributes.IsFgIndex()) + const auto apply_shadow = [](COLORREF& ColorRef, bool const IsIndex) { - const auto Mask = FOREGROUND_INTENSITY; - auto ForegroundColor = colors::index_value(Element.Attributes.ForegroundColor); - - if (ForegroundColor <= colors::index::nt_last) - { - if (ForegroundColor != Mask) - ForegroundColor &= ~Mask; - } - else if (ForegroundColor <= colors::index::cube_last) + if (IsIndex) { - // Just to stop GCC from complaining about identical branches - [[maybe_unused]] constexpr auto Cube = true; + auto Color = colors::index_value(ColorRef); + + if (Color <= colors::index::nt_last) + { + if (Color == F_LIGHTGRAY) + Color = F_DARKGRAY; + else if (const auto Mask = FOREGROUND_INTENSITY; Color != Mask) + Color &= ~Mask; + } + else if (Color <= colors::index::cube_last) + { + colors::rgb6 rgb(Color); + + rgb.r = std::min(rgb.r, 2); + rgb.g = std::min(rgb.g, 2); + rgb.b = std::min(rgb.b, 2); + + Color = rgb; + } + else + { + Color = std::min(Color, colors::index::grey_first + colors::index::grey_count / 2); + } - // Subpar - colors::set_index_value(Element.Attributes.ForegroundColor, F_DARKGRAY); + colors::set_index_value(ColorRef, Color); } else { - // Just to stop GCC from complaining about identical branches - [[maybe_unused]] constexpr auto Ramp = true; + const auto Mask = 0x808080; + auto Color = colors::color_value(ColorRef); - // Subpar - colors::set_index_value(Element.Attributes.ForegroundColor, F_DARKGRAY); - } - - colors::set_index_value(Element.Attributes.ForegroundColor, ForegroundColor); - } - else - { - const auto Mask = 0x808080; - auto ForegroundColor = colors::color_value(Element.Attributes.ForegroundColor); + if (Color != Mask) + Color &= ~Mask; - if (ForegroundColor != Mask) - ForegroundColor &= ~Mask; + colors::set_color_value(ColorRef, Color); + } + }; - colors::set_color_value(Element.Attributes.ForegroundColor, ForegroundColor); - } + apply_shadow(Element.Attributes.ForegroundColor, Element.Attributes.IsFgIndex()); } else if (IsTrueColorAvailable) { diff --git a/far/vmenu.cpp b/far/vmenu.cpp index 55e2caf40fb..1ae315f49b9 100644 --- a/far/vmenu.cpp +++ b/far/vmenu.cpp @@ -2288,9 +2288,6 @@ void VMenu::ShowMenu(bool IsParent) if (!Items[I].Annotations.empty()) { size_t Pos = 0; - FarColor InvColor = CurColor; - using std::swap; - swap(InvColor.ForegroundColor, InvColor.BackgroundColor); for (const auto& [AnnPos, AnnSize]: Items[I].Annotations) { const int StartOffset = 1; // 1 is '<<' placeholder size From 87154c58588b1cdc6e010c290fa4ebfa717af4c8 Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Sat, 11 Nov 2023 23:44:30 +0000 Subject: [PATCH 11/16] Build & changelog --- far/changelog | 9 +++++++++ far/vbuild.m4 | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/far/changelog b/far/changelog index a07a13d34e7..0da4177d025 100644 --- a/far/changelog +++ b/far/changelog @@ -1,3 +1,12 @@ +-------------------------------------------------------------------------------- +drkns 2023-11-11 23:43:42+00:00 - build 6210 + +1. M#4019: restore elevation requests for network paths + +2. gh-747: Build 6209 crashes on start with the profile from build 5629. + +3. Refactoring. + -------------------------------------------------------------------------------- drkns 2023-11-07 01:48:43+00:00 - build 6209 diff --git a/far/vbuild.m4 b/far/vbuild.m4 index dffad32e566..162f3d67c33 100644 --- a/far/vbuild.m4 +++ b/far/vbuild.m4 @@ -1 +1 @@ -6209 +6210 From 960cc4ca4a2aefb068e06f2472e3bf20d6647b74 Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Mon, 13 Nov 2023 00:12:59 +0000 Subject: [PATCH 12/16] Support compilation with libc++ --- far/common/library.hpp | 5 +++++ far/setcolor.cpp | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/far/common/library.hpp b/far/common/library.hpp index ad1323d433c..678ce0649d8 100644 --- a/far/common/library.hpp +++ b/far/common/library.hpp @@ -46,6 +46,11 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define STANDARD_LIBRARY_VERSION_MAJOR _GLIBCXX_RELEASE #define STANDARD_LIBRARY_VERSION_MINOR 0 #define STANDARD_LIBRARY_VERSION_PATCH __GLIBCXX__ +#elif defined(_LIBCPP_VERSION) +#define STANDARD_LIBRARY_NAME L"libc++" +#define STANDARD_LIBRARY_VERSION_MAJOR (_LIBCPP_VERSION / 10000) +#define STANDARD_LIBRARY_VERSION_MINOR ((_LIBCPP_VERSION % 10000) / 100) +#define STANDARD_LIBRARY_VERSION_PATCH (_LIBCPP_VERSION % 100) #else #define STANDARD_LIBRARY_NAME L"Unknown standard library" #define STANDARD_LIBRARY_VERSION_MAJOR 0 diff --git a/far/setcolor.cpp b/far/setcolor.cpp index b7986f990ef..6f6f15705a6 100644 --- a/far/setcolor.cpp +++ b/far/setcolor.cpp @@ -104,14 +104,46 @@ enum list_mode list_modes_count }; +struct color_item; + +class color_item_span +{ +public: + constexpr color_item_span() = default; + + template + explicit(false) constexpr color_item_span(color_item const (&Items)[N]): + data(Items), + size(N) + { + } + + constexpr bool empty() const + { + return !size; + } + + constexpr operator span() const; + +private: + color_item const* data{}; + size_t size{}; +}; + struct color_item { lng LngId; PaletteColors Color; - span SubColor; + // libc++ decided to follow the standard literally and prohibit incomplete types in spans :( + color_item_span SubColor; PaletteColors const* BottomColor; }; +constexpr color_item_span::operator span() const +{ + return { data, data + size }; +} + static void SetItemColors(span const Items, point Position = {}) { const auto ItemsMenu = VMenu2::create(msg(lng::MSetColorItemsTitle), {}); From bc7f237757d990b722ff982d772c8fcfb91cca79 Mon Sep 17 00:00:00 2001 From: Shmuel Zeigerman Date: Mon, 13 Nov 2023 20:25:12 +0200 Subject: [PATCH 13/16] Refactoring --- far/changelog | 5 ++ far/macro.cpp | 146 +++++++++++++++++++++++++------------------------- far/vbuild.m4 | 2 +- 3 files changed, 78 insertions(+), 75 deletions(-) diff --git a/far/changelog b/far/changelog index 0da4177d025..822feb8d926 100644 --- a/far/changelog +++ b/far/changelog @@ -1,3 +1,8 @@ +-------------------------------------------------------------------------------- +shmuel 2023-11-13 20:19:31+02:00 - build 6211 + +1. Refactoring. + -------------------------------------------------------------------------------- drkns 2023-11-11 23:43:42+00:00 - build 6210 diff --git a/far/macro.cpp b/far/macro.cpp index c2c800e4c9a..3111fb30c17 100644 --- a/far/macro.cpp +++ b/far/macro.cpp @@ -1106,12 +1106,9 @@ static bool CheckAll(FARMACROAREA Area, MACROFLAGS_MFLAGS CurFlags) static int Set3State(DWORD Flags,DWORD Chk1,DWORD Chk2) { - const auto Chk12 = Chk1 | Chk2, FlagsChk12 = Flags & Chk12; - - if (FlagsChk12 == Chk12 || !FlagsChk12) - return 2; - else - return (Flags & Chk1)? 1 : 0; + bool b1 = (Flags & Chk1) != 0; + bool b2 = (Flags & Chk2) != 0; + return b1==b2 ? 2 : b1 ? 1 : 0; } enum MACROSETTINGSDLG @@ -1122,7 +1119,7 @@ enum MACROSETTINGSDLG MS_TEXT_DESCR, MS_EDIT_DESCR, MS_SEPARATOR1, - MS_CHECKBOX_OUPUT, + MS_CHECKBOX_OUTPUT, MS_CHECKBOX_START, MS_SEPARATOR2, MS_CHECKBOX_A_PANEL, @@ -1251,7 +1248,7 @@ bool KeyMacro::GetMacroSettings(int Key, unsigned long long& Flags, string_view MacroSettingsDlg[MS_DOUBLEBOX].strData = far::vformat(msg(lng::MMacroSettingsTitle), KeyToText(Key)); //if(!(Key&0x7F000000)) //MacroSettingsDlg[3].Flags|=DIF_DISABLE; - MacroSettingsDlg[MS_CHECKBOX_OUPUT].Selected=Flags&MFLAGS_ENABLEOUTPUT?1:0; + MacroSettingsDlg[MS_CHECKBOX_OUTPUT].Selected=Flags&MFLAGS_ENABLEOUTPUT?1:0; MacroSettingsDlg[MS_CHECKBOX_START].Selected=Flags&MFLAGS_RUNAFTERFARSTART?1:0; MacroSettingsDlg[MS_CHECKBOX_A_PLUGINPANEL].Selected=Set3State(Flags,MFLAGS_NOFILEPANELS,MFLAGS_NOPLUGINPANELS); MacroSettingsDlg[MS_CHECKBOX_A_FOLDERS].Selected=Set3State(Flags,MFLAGS_NOFILES,MFLAGS_NOFOLDERS); @@ -1306,7 +1303,7 @@ bool KeyMacro::GetMacroSettings(int Key, unsigned long long& Flags, string_view }; Flags = - get_flag(MS_CHECKBOX_OUPUT, key_output) | + get_flag(MS_CHECKBOX_OUTPUT, key_output) | get_flag(MS_CHECKBOX_START, key_start) | get_flag(MS_CHECKBOX_CMDLINE, key_cmdline) | get_flag(MS_CHECKBOX_SELBLOCK, key_selblock); @@ -1399,6 +1396,7 @@ class FarMacroApi public: explicit FarMacroApi(FarMacroCall* Data) : mData(Data) {} + std::vector parseParams(size_t Count) const; void PassBoolean(bool b) const; void PassError(const wchar_t* str) const; void PassValue(long long Int) const; @@ -1533,12 +1531,12 @@ void FarMacroApi::PassValue(const TVar& Var) const PassValue(Var.asInteger()); } -static auto parseParams(size_t Count, const FarMacroCall* Data) +std::vector FarMacroApi::parseParams(size_t Count) const { - const auto argNum = std::min(Data->Count, Count); + const auto argNum = std::min(mData->Count, Count); std::vector Params; Params.reserve(Count); - std::transform(Data->Values, Data->Values + argNum, std::back_inserter(Params), [](const auto& i) + std::transform(mData->Values, mData->Values + argNum, std::back_inserter(Params), [](const auto& i) { switch (i.Type) { @@ -2326,7 +2324,7 @@ void KeyMacro::CallFar(intptr_t CheckCode, FarMacroCall* Data) case MCODE_F_BM_PUSH: // N=BM.Push() - сохранить текущую позицию в виде закладки в конце стека case MCODE_F_BM_POP: // N=BM.Pop() - восстановить текущую позицию из закладки в конце стека и удалить закладку { - auto Params = parseParams(2, Data); + auto Params = api.parseParams(2); auto& p1 = Params[0]; auto& p2 = Params[1]; @@ -2340,7 +2338,7 @@ void KeyMacro::CallFar(intptr_t CheckCode, FarMacroCall* Data) case MCODE_F_MENU_GETVALUE: // S=Menu.GetValue([N]) case MCODE_F_MENU_GETHOTKEY: // S=gethotkey([N]) { - auto Params = parseParams(1, Data); + auto Params = api.parseParams(1); TVar tmpVar=Params[0]; tmpVar.toInteger(); @@ -2390,7 +2388,7 @@ void KeyMacro::CallFar(intptr_t CheckCode, FarMacroCall* Data) case MCODE_F_MENU_SELECT: // N=Menu.Select(S[,N[,Dir]]) case MCODE_F_MENU_CHECKHOTKEY: // N=checkhotkey(S[,N]) { - auto Params = parseParams(3, Data); + auto Params = api.parseParams(3); long long Result=-1; long long tmpDir=0; @@ -2423,7 +2421,7 @@ void KeyMacro::CallFar(intptr_t CheckCode, FarMacroCall* Data) case MCODE_F_MENU_FILTER: // N=Menu.Filter([Action[,Mode]]) case MCODE_F_MENU_FILTERSTR: // S=Menu.FilterStr([Action[,S]]) { - auto Params = parseParams(2, Data); + auto Params = api.parseParams(2); bool success=false; auto& tmpAction = Params[0]; @@ -2475,7 +2473,7 @@ void KeyMacro::CallFar(intptr_t CheckCode, FarMacroCall* Data) // S=trim(S[,N]) void FarMacroApi::trimFunc() const { - auto Params = parseParams(2, mData); + auto Params = parseParams(2); auto Str = Params[0].toString(); @@ -2515,7 +2513,7 @@ void FarMacroApi::substrFunc() const если length = 0 если ... */ - auto Params = parseParams(3, mData); + auto Params = parseParams(3); auto start = static_cast(Params[1].asInteger()); const auto& Str = Params[0].toString(); const auto length_str = static_cast(Str.size()); @@ -2586,7 +2584,7 @@ static void SplitPath(string_view const FullPath, string& Dest, int Flags) // S=fsplit(S,N) void FarMacroApi::fsplitFunc() const { - auto Params = parseParams(2, mData); + auto Params = parseParams(2); string strPath; SplitPath(Params[0].toString(), strPath, Params[1].asInteger()); @@ -2597,7 +2595,7 @@ void FarMacroApi::fsplitFunc() const // N=atoi(S[,radix]) void FarMacroApi::atoiFunc() const { - auto Params = parseParams(2, mData); + auto Params = parseParams(2); long long Value = 0; PassValue(from_string(Params[0].toString(), Value, nullptr, static_cast(Params[1].toInteger()))? Value : 0); } @@ -2608,7 +2606,7 @@ void FarMacroApi::windowscrollFunc() const if (!Global->Opt->WindowMode) return PassBoolean(false); - const auto Params = parseParams(2, mData); + const auto Params = parseParams(2); int Lines = static_cast(Params[0].asInteger()), Columns = 0; @@ -2624,7 +2622,7 @@ void FarMacroApi::windowscrollFunc() const // S=itoa(N[,radix]) void FarMacroApi::itowFunc() const { - auto Params = parseParams(2, mData); + auto Params = parseParams(2); if (Params[0].isInteger() || Params[0].isDouble()) { @@ -2643,7 +2641,7 @@ void FarMacroApi::itowFunc() const // os::chrono::sleep_for(Nms) void FarMacroApi::sleepFunc() const { - const auto Params = parseParams(1, mData); + const auto Params = parseParams(1); const auto Period = Params[0].asInteger(); if (Period > 0) @@ -2668,7 +2666,7 @@ void FarMacroApi::keybarshowFunc() const 3 - swap ret: prev mode or -1 - KeyBar not found */ - const auto Params = parseParams(1, mData); + const auto Params = parseParams(1); const auto f = Global->WindowManager->GetCurrentWindow(); PassValue(f? f->VMProcess(MCODE_F_KEYBAR_SHOW, nullptr, Params[0].asInteger()) - 1 : -1); @@ -2678,7 +2676,7 @@ void FarMacroApi::keybarshowFunc() const // S=key(V) void FarMacroApi::keyFunc() const { - const auto Params = parseParams(1, mData); + const auto Params = parseParams(1); string strKeyText; if (Params[0].isInteger() || Params[0].isDouble()) @@ -2699,7 +2697,7 @@ void FarMacroApi::keyFunc() const // V=waitkey([N,[T]]) void FarMacroApi::waitkeyFunc() const { - const auto Params = parseParams(2, mData); + const auto Params = parseParams(2); const auto Type = static_cast(Params[1].asInteger()); std::optional TimeoutOpt; @@ -2724,21 +2722,21 @@ void FarMacroApi::waitkeyFunc() const // n=min(n1,n2) void FarMacroApi::minFunc() const { - const auto Params = parseParams(2, mData); + const auto Params = parseParams(2); PassValue(std::min(Params[0], Params[1])); } // n=max(n1,n2) void FarMacroApi::maxFunc() const { - const auto Params = parseParams(2, mData); + const auto Params = parseParams(2); PassValue(std::max(Params[0], Params[1])); } // n=mod(n1,n2) void FarMacroApi::modFunc() const { - const auto Params = parseParams(2, mData); + const auto Params = parseParams(2); const auto NumeratorType = Params[0].ParseType(); const auto DenominatorType = Params[1].ParseType(); @@ -2798,7 +2796,7 @@ void FarMacroApi::modFunc() const // N=index(S1,S2[,Mode]) void FarMacroApi::indexFunc() const { - auto Params = parseParams(3, mData); + auto Params = parseParams(3); const auto& s = Params[0].toString(); const auto& p = Params[1].toString(); @@ -2813,7 +2811,7 @@ void FarMacroApi::indexFunc() const // S=rindex(S1,S2[,Mode]) void FarMacroApi::rindexFunc() const { - auto Params = parseParams(3, mData); + auto Params = parseParams(3); const auto& s = Params[0].toString(); const auto& p = Params[1].toString(); @@ -2828,7 +2826,7 @@ void FarMacroApi::rindexFunc() const // S=Size2Str(Size,Flags[,Width]) void FarMacroApi::size2strFunc() const { - const auto Params = parseParams(3, mData); + const auto Params = parseParams(3); const auto Width = static_cast(Params[2].asInteger()); PassValue(FileSizeToStr(Params[0].asInteger(), Width, Params[1].asInteger())); } @@ -2836,7 +2834,7 @@ void FarMacroApi::size2strFunc() const // S=date([S]) void FarMacroApi::dateFunc() const { - auto Params = parseParams(1, mData); + auto Params = parseParams(1); if (Params[0].isInteger() && !Params[0].asInteger()) Params[0] = L""sv; @@ -2853,7 +2851,7 @@ void FarMacroApi::dateFunc() const */ void FarMacroApi::xlatFunc() const { - auto Params = parseParams(2, mData); + auto Params = parseParams(2); auto StrParam = Params[0].toString(); Xlat(StrParam, Params[1].asInteger()); PassValue(StrParam); @@ -2862,7 +2860,7 @@ void FarMacroApi::xlatFunc() const // N=beep([N]) void FarMacroApi::beepFunc() const { - const auto Params = parseParams(1, mData); + const auto Params = parseParams(1); PassBoolean(MessageBeep(static_cast(Params[0].asInteger())) != FALSE); } @@ -2880,7 +2878,7 @@ Res=kbdLayout([N]) // N=kbdLayout([N]) void FarMacroApi::kbdLayoutFunc() const { - const auto Params = parseParams(1, mData); + const auto Params = parseParams(1); const auto dwLayout = static_cast(Params[0].asInteger()); auto Ret = true; @@ -2922,7 +2920,7 @@ void FarMacroApi::kbdLayoutFunc() const // S=prompt(["Title"[,"Prompt"[,flags[, "Src"[, "History"]]]]]) void FarMacroApi::promptFunc() const { - const auto Params = parseParams(5, mData); + const auto Params = parseParams(5); const auto& ValHistory = Params[4]; const auto& ValSrc = Params[3]; const auto Flags = static_cast(Params[2].asInteger()); @@ -2963,7 +2961,7 @@ void FarMacroApi::promptFunc() const // N=msgbox(["Title"[,"Text"[,flags]]]) void FarMacroApi::msgBoxFunc() const { - auto Params = parseParams(3, mData); + auto Params = parseParams(3); auto& ValT = Params[0]; string_view title; @@ -3003,7 +3001,7 @@ void FarMacroApi::msgBoxFunc() const //0x800 - void FarMacroApi::menushowFunc() const { - auto Params = parseParams(6, mData); + auto Params = parseParams(6); auto& VY = Params[5]; auto& VX = Params[4]; auto& VFindOrFilter(Params[3]); @@ -3318,7 +3316,7 @@ void FarMacroApi::menushowFunc() const // S=Env(S[,Mode[,Value]]) void FarMacroApi::environFunc() const { - auto Params = parseParams(3, mData); + auto Params = parseParams(3); auto& Value = Params[2]; const auto& Mode = Params[1]; auto& S = Params[0]; @@ -3336,7 +3334,7 @@ void FarMacroApi::environFunc() const // V=Panel.Select(panelType,Action[,Mode[,Items]]) void FarMacroApi::panelselectFunc() const { - auto Params = parseParams(4, mData); + auto Params = parseParams(4); auto& ValItems = Params[3]; const auto Mode = static_cast(Params[2].asInteger()); const auto Action = static_cast(Params[1].asInteger()); @@ -3388,7 +3386,7 @@ void FarMacroApi::fattrFuncImpl(int Type) const if (any_of(Type, f_fattr_fs, f_fexist_fs)) { - auto Params = parseParams(1, mData); + auto Params = parseParams(1); auto& Str = Params[0]; // get_find_data to support wildcards @@ -3399,7 +3397,7 @@ void FarMacroApi::fattrFuncImpl(int Type) const } else { - auto Params = parseParams(2, mData); + auto Params = parseParams(2); auto& S = Params[1]; const auto& Str = S.toString(); @@ -3465,7 +3463,7 @@ void FarMacroApi::panelfexistFunc() const */ void FarMacroApi::flockFunc() const { - const auto Params = parseParams(2, mData); + const auto Params = parseParams(2); int Ret = -1; const auto stateFLock = static_cast(Params[1].asInteger()); auto vkKey = static_cast(Params[0].asInteger()); @@ -3495,7 +3493,7 @@ void FarMacroApi::flockFunc() const // N=Dlg->SetFocus([ID]) void FarMacroApi::dlgsetfocusFunc() const { - const auto Params = parseParams(1, mData); + const auto Params = parseParams(1); const auto Index = static_cast(Params[0].asInteger()) - 1; @@ -3519,7 +3517,7 @@ void FarMacroApi::dlgsetfocusFunc() const // V=Far.Cfg.Get(Key,Name) void FarMacroApi::farcfggetFunc() const { - const auto Params = parseParams(2, mData); + const auto Params = parseParams(2); const auto& Name = Params[1]; const auto& Key = Params[0]; @@ -3569,7 +3567,7 @@ void FarMacroApi::fargetconfigFunc() const // V=Dlg->GetValue([Pos[,InfoID]]) void FarMacroApi::dlggetvalueFunc() const { - auto Params = parseParams(2, mData); + auto Params = parseParams(2); TVar Ret(-1); if (Global->CtrlObject->Macro.GetArea()==MACROAREA_DIALOG) @@ -3766,7 +3764,7 @@ void FarMacroApi::editorposFunc() const { SCOPED_ACTION(LockOutput)(IsTopMacroOutputDisabled()); - auto Params = parseParams(3, mData); + auto Params = parseParams(3); TVar Ret(-1); int Where = static_cast(Params[2].asInteger()); int What = static_cast(Params[1].asInteger()); @@ -3882,7 +3880,7 @@ void FarMacroApi::editorposFunc() const // OldVar=Editor.Set(Idx,Value) void FarMacroApi::editorsetFunc() const { - auto Params = parseParams(2, mData); + auto Params = parseParams(2); TVar Ret(-1); auto& Value = Params[1]; int Index = static_cast(Params[0].asInteger()); @@ -4110,7 +4108,7 @@ void FarMacroApi::editorsetFunc() const // V=Clip(N[,V]) void FarMacroApi::clipFunc() const { - auto Params = parseParams(2, mData); + auto Params = parseParams(2); auto& Val = Params[1]; const auto cmdType = static_cast(Params[0].asInteger()); @@ -4196,7 +4194,7 @@ void FarMacroApi::clipFunc() const */ void FarMacroApi::panelsetposidxFunc() const { - const auto Params = parseParams(3, mData); + const auto Params = parseParams(3); const auto InSelection = static_cast(Params[2].asInteger()); auto idxItem = static_cast(Params[1].asInteger()); long long Ret=0; @@ -4304,7 +4302,7 @@ void FarMacroApi::panelsetposidxFunc() const // N=Panel.SetPos(panelType,fileName) void FarMacroApi::panelsetposFunc() const { - const auto Params = parseParams(2, mData); + const auto Params = parseParams(2); const auto& Val = Params[1]; const auto& fileName=Val.asString(); @@ -4349,7 +4347,7 @@ Str=="" return "" void FarMacroApi::replaceFunc() const { - const auto Params = parseParams(5, mData); + const auto Params = parseParams(5); auto Src = Params[0].asString(); const auto& Find = Params[1].asString(); const auto& Repl = Params[2].asString(); @@ -4363,7 +4361,7 @@ void FarMacroApi::replaceFunc() const // V=Panel.Item(typePanel,Index,TypeInfo) void FarMacroApi::panelitemFunc() const { - auto Params = parseParams(3, mData); + auto Params = parseParams(3); auto& P2 = Params[2]; auto& P1 = Params[1]; @@ -4465,13 +4463,13 @@ void FarMacroApi::panelitemFunc() const // N=len(V) void FarMacroApi::lenFunc() const { - auto Params = parseParams(1, mData); + auto Params = parseParams(1); PassValue(Params[0].toString().size()); } void FarMacroApi::ucaseFunc() const { - auto Params = parseParams(1, mData); + auto Params = parseParams(1); auto& Val = Params[0]; Val = upper(Val.toString()); PassValue(Val); @@ -4479,7 +4477,7 @@ void FarMacroApi::ucaseFunc() const void FarMacroApi::lcaseFunc() const { - auto Params = parseParams(1, mData); + auto Params = parseParams(1); auto& Val = Params[0]; Val = lower(Val.toString()); PassValue(Val); @@ -4487,7 +4485,7 @@ void FarMacroApi::lcaseFunc() const void FarMacroApi::stringFunc() const { - auto Params = parseParams(1, mData); + auto Params = parseParams(1); auto& Val = Params[0]; Val.toString(); PassValue(Val); @@ -4496,7 +4494,7 @@ void FarMacroApi::stringFunc() const // S=StrPad(Src,Cnt[,Fill[,Op]]) void FarMacroApi::strpadFunc() const { - auto Params = parseParams(4, mData); + auto Params = parseParams(4); auto& Src = Params[0]; if (Src.isUnknown()) { @@ -4558,7 +4556,7 @@ void FarMacroApi::strpadFunc() const // S=StrWrap(Text,Width[,Break[,Flags]]) void FarMacroApi::strwrapFunc() const { - auto Params = parseParams(3, mData); + auto Params = parseParams(3); auto& Break = Params[2]; const size_t Width = Params[1].asInteger(); const auto& Text = Params[0]; @@ -4571,21 +4569,21 @@ void FarMacroApi::strwrapFunc() const void FarMacroApi::intFunc() const { - const auto Params = parseParams(1, mData); + const auto Params = parseParams(1); const auto& Val = Params[0]; PassValue(Val.asInteger()); } void FarMacroApi::floatFunc() const { - const auto Params = parseParams(1, mData); + const auto Params = parseParams(1); const auto& Val = Params[0]; PassValue(Val.asDouble()); } void FarMacroApi::absFunc() const { - const auto Params = parseParams(1, mData); + const auto Params = parseParams(1); TVar Result; @@ -4618,7 +4616,7 @@ void FarMacroApi::absFunc() const void FarMacroApi::ascFunc() const { - const auto Params = parseParams(1, mData); + const auto Params = parseParams(1); const auto& tmpVar = Params[0]; if (tmpVar.isString() && !tmpVar.asString().empty()) @@ -4629,7 +4627,7 @@ void FarMacroApi::ascFunc() const void FarMacroApi::chrFunc() const { - const auto Params = parseParams(1, mData); + const auto Params = parseParams(1); auto tmpVar = Params[0]; if (tmpVar.isNumber()) @@ -4644,7 +4642,7 @@ void FarMacroApi::chrFunc() const // N=FMatch(S,Mask) void FarMacroApi::fmatchFunc() const { - auto Params = parseParams(2, mData); + auto Params = parseParams(2); auto& Mask = Params[1]; auto& S = Params[0]; filemasks FileMask; @@ -4686,7 +4684,7 @@ void FarMacroApi::editorselFunc() const Opt: ignore return 1 */ - auto Params = parseParams(2, mData); + auto Params = parseParams(2); TVar Ret(0ll); const auto& Opts = Params[1]; auto& Action = Params[0]; @@ -4716,7 +4714,7 @@ void FarMacroApi::editorundoFunc() const if (!CurrentEditor || !CurrentEditor->IsVisible()) return PassValue(0); - auto Params = parseParams(1, mData); + auto Params = parseParams(1); auto& Action = Params[0]; EditorUndoRedo eur{ sizeof(eur) }; @@ -4734,7 +4732,7 @@ void FarMacroApi::editorsettitleFunc() const if (!CurrentEditor || !CurrentEditor->IsVisible()) return PassValue(0); - auto Params = parseParams(1, mData); + auto Params = parseParams(1); auto& Title = Params[0]; if (Title.isInteger() && !Title.asInteger()) @@ -4753,7 +4751,7 @@ void FarMacroApi::editordellineFunc() const if (!CurrentEditor || !CurrentEditor->IsVisible()) return PassValue(0); - const auto Params = parseParams(1, mData); + const auto Params = parseParams(1); const auto& Line = Params[0]; if (!Line.isNumber()) @@ -4772,7 +4770,7 @@ void FarMacroApi::editorinsstrFunc() const if (!CurrentEditor || !CurrentEditor->IsVisible()) return PassValue(0); - auto Params = parseParams(2, mData); + auto Params = parseParams(2); auto& S = Params[0]; const auto& Line = Params[1]; @@ -4795,7 +4793,7 @@ void FarMacroApi::editorsetstrFunc() const if (!CurrentEditor || !CurrentEditor->IsVisible()) return PassValue(0); - auto Params = parseParams(2, mData); + auto Params = parseParams(2); auto& S = Params[0]; const auto& Line = Params[1]; @@ -4821,7 +4819,7 @@ void FarMacroApi::pluginexistFunc() const // N=Plugin.Load(DllPath[,ForceLoad]) void FarMacroApi::pluginloadFunc() const { - const auto Params = parseParams(2, mData); + const auto Params = parseParams(2); const auto& ForceLoad = Params[1]; const auto& DllPath = Params[0].asString(); const TVar Ret(pluginapi::apiPluginsControl(nullptr, !ForceLoad.asInteger()?PCTL_LOADPLUGIN:PCTL_FORCEDLOADPLUGIN, 0, UNSAFE_CSTR(DllPath))); @@ -4854,7 +4852,7 @@ TSTFLD_ERROR (-2) - ошибка (кривые параметры или н */ void FarMacroApi::testfolderFunc() const { - const auto Params = parseParams(1, mData); + const auto Params = parseParams(1); const auto& tmpVar = Params[0]; long long Ret=TSTFLD_ERROR; diff --git a/far/vbuild.m4 b/far/vbuild.m4 index 162f3d67c33..25802702b0f 100644 --- a/far/vbuild.m4 +++ b/far/vbuild.m4 @@ -1 +1 @@ -6210 +6211 From eda2217a2e9fa2a0e76b5fb6cc6fc08fec0c816c Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Mon, 13 Nov 2023 19:18:02 +0000 Subject: [PATCH 14/16] Add llvm clang build action --- .github/workflows/build.yml | 48 ++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0bafc75f5a3..c24ed485b30 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v4 @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-dotnet@v3 with: @@ -66,7 +66,7 @@ jobs: steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Initialize CodeQL if: matrix.build == 'msbuild_cl_x64_debug' @@ -124,7 +124,7 @@ jobs: steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Initialize CodeQL if: matrix.build == 'nmake_cl_x64_debug' @@ -179,18 +179,22 @@ jobs: mingw_gcc_x64_debug, mingw_gcc_x64_release, mingw_clang_x64_debug, - mingw_clang_x64_release + mingw_clang_x64_release, + mingw_llvm_x64_debug, + mingw_llvm_x64_release ] include: - { build: mingw_gcc_x64_debug, compiler: mingw_gcc, arch: amd64, build_config: Debug } - { build: mingw_gcc_x64_release, compiler: mingw_gcc, arch: amd64, build_config: Release } - - { build: mingw_clang_x64_Debug, compiler: mingw_clang, arch: amd64, build_config: Debug } - - { build: mingw_clang_x64_Release, compiler: mingw_clang, arch: amd64, build_config: Release } + - { build: mingw_clang_x64_debug, compiler: mingw_clang, arch: amd64, build_config: Debug } + - { build: mingw_clang_x64_release, compiler: mingw_clang, arch: amd64, build_config: Release } + - { build: mingw_llvm_x64_debug, compiler: mingw_llvm, arch: amd64, build_config: Debug } + - { build: mingw_llvm_x64_release, compiler: mingw_llvm, arch: amd64, build_config: Release } steps: - name: Checkout source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Initialize CodeQL if: matrix.build == 'mingw_gcc_x64_debug' @@ -250,6 +254,34 @@ jobs: clang --version make -j4 CLANG=1 -f makefile_all_gcc + - name: Install llvm x64 + id: install_llvm_x64 + if: matrix.compiler == 'mingw_llvm' + uses: robinraju/release-downloader@v1.8 + with: + repository: "mstorsjo/llvm-mingw" + latest: true + fileName: "llvm-mingw-*-msvcrt-x86_64.zip" + extract: true + + - name: Build Far (llvm) + if: matrix.compiler == 'mingw_llvm' + working-directory: far + shell: cmd + run: | + set path=${{github.workspace}}\llvm-mingw-${{steps.install_llvm_x64.outputs.tag_name}}-msvcrt-x86_64\bin;%path% + clang --version + make -j4 CLANG=1 -f makefile_gcc + + - name: Build plugins (llvm) + if: matrix.compiler == 'mingw_llvm' + working-directory: plugins + shell: cmd + run: | + set path=${{github.workspace}}\llvm-mingw-${{steps.install_llvm_x64.outputs.tag_name}}-msvcrt-x86_64\bin;%path% + clang --version + make -j4 CLANG=1 -f makefile_all_gcc + - name: Perform CodeQL Analysis if: matrix.build == 'mingw_gcc_x64_debug' uses: github/codeql-action/analyze@v2 From ab239ac2b58d1ad6379e7ef8d401ef0ab4bd52ea Mon Sep 17 00:00:00 2001 From: Shmuel Zeigerman Date: Tue, 14 Nov 2023 23:07:29 +0200 Subject: [PATCH 15/16] Fix Macro Settings dialog --- far/changelog | 5 ++ far/macro.cpp | 126 +++++++++++++++++++++++--------------------------- far/vbuild.m4 | 2 +- 3 files changed, 64 insertions(+), 69 deletions(-) diff --git a/far/changelog b/far/changelog index 822feb8d926..e3ef924e225 100644 --- a/far/changelog +++ b/far/changelog @@ -1,3 +1,8 @@ +-------------------------------------------------------------------------------- +shmuel 2023-11-14 23:04:38+02:00 - build 6212 + +1. Fix Macro Settings dialog. + -------------------------------------------------------------------------------- shmuel 2023-11-13 20:19:31+02:00 - build 6211 diff --git a/far/macro.cpp b/far/macro.cpp index 3111fb30c17..d8cb6ee2082 100644 --- a/far/macro.cpp +++ b/far/macro.cpp @@ -1111,6 +1111,11 @@ static int Set3State(DWORD Flags,DWORD Chk1,DWORD Chk2) return b1==b2 ? 2 : b1 ? 1 : 0; } +static DWORD Get3State(int Selected,DWORD Chk1,DWORD Chk2) +{ + return Selected==2 ? 0 : Selected==0 ? Chk1 : Chk2; +} + enum MACROSETTINGSDLG { MS_DOUBLEBOX, @@ -1216,13 +1221,13 @@ bool KeyMacro::GetMacroSettings(int Key, unsigned long long& Flags, string_view { DI_CHECKBOX, {{5, 8 }, {0, 8 }}, DIF_NONE, msg(lng::MMacroSettingsRunAfterStart), }, { DI_TEXT, {{-1, 9 }, {0, 9 }}, DIF_SEPARATOR, }, { DI_CHECKBOX, {{5, 10}, {0, 10}}, DIF_NONE, msg(lng::MMacroSettingsActivePanel), }, - { DI_CHECKBOX, {{7, 11}, {0, 11}}, DIF_3STATE | DIF_DISABLE, msg(lng::MMacroSettingsPluginPanel), }, - { DI_CHECKBOX, {{7, 12}, {0, 12}}, DIF_3STATE | DIF_DISABLE, msg(lng::MMacroSettingsFolders), }, - { DI_CHECKBOX, {{7, 13}, {0, 13}}, DIF_3STATE | DIF_DISABLE, msg(lng::MMacroSettingsSelectionPresent), }, + { DI_CHECKBOX, {{7, 11}, {0, 11}}, DIF_3STATE, msg(lng::MMacroSettingsPluginPanel), }, + { DI_CHECKBOX, {{7, 12}, {0, 12}}, DIF_3STATE, msg(lng::MMacroSettingsFolders), }, + { DI_CHECKBOX, {{7, 13}, {0, 13}}, DIF_3STATE, msg(lng::MMacroSettingsSelectionPresent), }, { DI_CHECKBOX, {{37, 10}, {0, 10}}, DIF_NONE, msg(lng::MMacroSettingsPassivePanel), }, - { DI_CHECKBOX, {{39, 11}, {0, 11}}, DIF_3STATE | DIF_DISABLE, msg(lng::MMacroSettingsPluginPanel), }, - { DI_CHECKBOX, {{39, 12}, {0, 12}}, DIF_3STATE | DIF_DISABLE, msg(lng::MMacroSettingsFolders), }, - { DI_CHECKBOX, {{39, 13}, {0, 13}}, DIF_3STATE | DIF_DISABLE, msg(lng::MMacroSettingsSelectionPresent), }, + { DI_CHECKBOX, {{39, 11}, {0, 11}}, DIF_3STATE, msg(lng::MMacroSettingsPluginPanel), }, + { DI_CHECKBOX, {{39, 12}, {0, 12}}, DIF_3STATE, msg(lng::MMacroSettingsFolders), }, + { DI_CHECKBOX, {{39, 13}, {0, 13}}, DIF_3STATE, msg(lng::MMacroSettingsSelectionPresent), }, { DI_TEXT, {{-1, 14}, {0, 14}}, DIF_SEPARATOR, }, { DI_CHECKBOX, {{5, 15}, {0, 15}}, DIF_3STATE, msg(lng::MMacroSettingsCommandLine), }, { DI_CHECKBOX, {{5, 16}, {0, 16}}, DIF_3STATE, msg(lng::MMacroSettingsSelectionBlockPresent), }, @@ -1234,28 +1239,40 @@ bool KeyMacro::GetMacroSettings(int Key, unsigned long long& Flags, string_view MacroSettingsDlg[MS_EDIT_SEQUENCE].strHistory = L"MacroSequence"sv; MacroSettingsDlg[MS_EDIT_DESCR].strHistory = L"MacroDescription"sv; - MacroSettingsDlg[MS_CHECKBOX_A_PLUGINPANEL].Selected = 2; - MacroSettingsDlg[MS_CHECKBOX_A_FOLDERS].Selected = 2; - MacroSettingsDlg[MS_CHECKBOX_A_SELECTION].Selected = 2; - - MacroSettingsDlg[MS_CHECKBOX_P_PLUGINPANEL].Selected = 2; - MacroSettingsDlg[MS_CHECKBOX_P_FOLDERS].Selected = 2; - MacroSettingsDlg[MS_CHECKBOX_P_SELECTION].Selected = 2; - - MacroSettingsDlg[MS_CHECKBOX_CMDLINE].Selected = 2; - MacroSettingsDlg[MS_CHECKBOX_SELBLOCK].Selected = 2; - MacroSettingsDlg[MS_DOUBLEBOX].strData = far::vformat(msg(lng::MMacroSettingsTitle), KeyToText(Key)); //if(!(Key&0x7F000000)) //MacroSettingsDlg[3].Flags|=DIF_DISABLE; MacroSettingsDlg[MS_CHECKBOX_OUTPUT].Selected=Flags&MFLAGS_ENABLEOUTPUT?1:0; MacroSettingsDlg[MS_CHECKBOX_START].Selected=Flags&MFLAGS_RUNAFTERFARSTART?1:0; - MacroSettingsDlg[MS_CHECKBOX_A_PLUGINPANEL].Selected=Set3State(Flags,MFLAGS_NOFILEPANELS,MFLAGS_NOPLUGINPANELS); - MacroSettingsDlg[MS_CHECKBOX_A_FOLDERS].Selected=Set3State(Flags,MFLAGS_NOFILES,MFLAGS_NOFOLDERS); - MacroSettingsDlg[MS_CHECKBOX_A_SELECTION].Selected=Set3State(Flags,MFLAGS_SELECTION,MFLAGS_NOSELECTION); - MacroSettingsDlg[MS_CHECKBOX_P_PLUGINPANEL].Selected=Set3State(Flags,MFLAGS_PNOFILEPANELS,MFLAGS_PNOPLUGINPANELS); - MacroSettingsDlg[MS_CHECKBOX_P_FOLDERS].Selected=Set3State(Flags,MFLAGS_PNOFILES,MFLAGS_PNOFOLDERS); - MacroSettingsDlg[MS_CHECKBOX_P_SELECTION].Selected=Set3State(Flags,MFLAGS_PSELECTION,MFLAGS_PNOSELECTION); + + int a = Set3State(Flags,MFLAGS_NOFILEPANELS,MFLAGS_NOPLUGINPANELS); + int b = Set3State(Flags,MFLAGS_NOFILES,MFLAGS_NOFOLDERS); + int c = Set3State(Flags,MFLAGS_SELECTION,MFLAGS_NOSELECTION); + MacroSettingsDlg[MS_CHECKBOX_A_PLUGINPANEL].Selected = a; + MacroSettingsDlg[MS_CHECKBOX_A_FOLDERS].Selected = b; + MacroSettingsDlg[MS_CHECKBOX_A_SELECTION].Selected = c; + MacroSettingsDlg[MS_CHECKBOX_A_PANEL].Selected = (a!=2 || b!=2 || c!= 2) ? 1 : 0; + if (0 == MacroSettingsDlg[MS_CHECKBOX_A_PANEL].Selected) + { + MacroSettingsDlg[MS_CHECKBOX_A_PLUGINPANEL].Flags |= DIF_DISABLE; + MacroSettingsDlg[MS_CHECKBOX_A_FOLDERS].Flags |= DIF_DISABLE; + MacroSettingsDlg[MS_CHECKBOX_A_SELECTION].Flags |= DIF_DISABLE; + } + + a = Set3State(Flags,MFLAGS_PNOFILEPANELS,MFLAGS_PNOPLUGINPANELS); + b = Set3State(Flags,MFLAGS_PNOFILES,MFLAGS_PNOFOLDERS); + c = Set3State(Flags,MFLAGS_PSELECTION,MFLAGS_PNOSELECTION); + MacroSettingsDlg[MS_CHECKBOX_P_PLUGINPANEL].Selected = a; + MacroSettingsDlg[MS_CHECKBOX_P_FOLDERS].Selected = b; + MacroSettingsDlg[MS_CHECKBOX_P_SELECTION].Selected = c; + MacroSettingsDlg[MS_CHECKBOX_P_PANEL].Selected = (a!=2 || b!=2 || c!= 2) ? 1 : 0; + if (0 == MacroSettingsDlg[MS_CHECKBOX_P_PANEL].Selected) + { + MacroSettingsDlg[MS_CHECKBOX_P_PLUGINPANEL].Flags |= DIF_DISABLE; + MacroSettingsDlg[MS_CHECKBOX_P_FOLDERS].Flags |= DIF_DISABLE; + MacroSettingsDlg[MS_CHECKBOX_P_SELECTION].Flags |= DIF_DISABLE; + } + MacroSettingsDlg[MS_CHECKBOX_CMDLINE].Selected=Set3State(Flags,MFLAGS_EMPTYCOMMANDLINE,MFLAGS_NOTEMPTYCOMMANDLINE); MacroSettingsDlg[MS_CHECKBOX_SELBLOCK].Selected=Set3State(Flags,MFLAGS_EDITSELECTION,MFLAGS_EDITNOSELECTION); MacroSettingsDlg[MS_EDIT_SEQUENCE].strData = Src.empty()? m_RecCode : Src; @@ -1270,60 +1287,33 @@ bool KeyMacro::GetMacroSettings(int Key, unsigned long long& Flags, string_view if (Dlg->GetExitCode()!=MS_BUTTON_OK) return false; - enum key_id - { - key_output, - key_start, - key_pluginpanel, - key_folders, - key_selection, - key_cmdline, - key_selblock, - - key_count - }; - - static const MACROFLAGS_MFLAGS Mapping[][3] = - { - // [ ] [x] [?] - { MFLAGS_NONE, MFLAGS_ENABLEOUTPUT, MFLAGS_NONE }, - { MFLAGS_NONE, MFLAGS_RUNAFTERFARSTART, MFLAGS_NONE }, - { MFLAGS_NOPLUGINPANELS, MFLAGS_NOFILEPANELS, MFLAGS_NONE }, - { MFLAGS_NOFOLDERS, MFLAGS_NOFILES, MFLAGS_NONE }, - { MFLAGS_NOSELECTION, MFLAGS_SELECTION, MFLAGS_NONE }, - { MFLAGS_NOTEMPTYCOMMANDLINE, MFLAGS_EMPTYCOMMANDLINE, MFLAGS_NONE }, - { MFLAGS_EDITNOSELECTION, MFLAGS_EDITSELECTION, MFLAGS_NONE }, - }; - - static_assert(key_count == std::size(Mapping)); - - const auto get_flag = [&](MACROSETTINGSDLG ControlId, key_id KeyId) - { - return Mapping[KeyId][MacroSettingsDlg[ControlId].Selected]; - }; - - Flags = - get_flag(MS_CHECKBOX_OUTPUT, key_output) | - get_flag(MS_CHECKBOX_START, key_start) | - get_flag(MS_CHECKBOX_CMDLINE, key_cmdline) | - get_flag(MS_CHECKBOX_SELBLOCK, key_selblock); + Flags=MacroSettingsDlg[MS_CHECKBOX_OUTPUT].Selected?MFLAGS_ENABLEOUTPUT:MFLAGS_NONE; + Flags|=MacroSettingsDlg[MS_CHECKBOX_START].Selected?MFLAGS_RUNAFTERFARSTART:MFLAGS_NONE; if (MacroSettingsDlg[MS_CHECKBOX_A_PANEL].Selected) { - Flags |= - get_flag(MS_CHECKBOX_A_PLUGINPANEL, key_pluginpanel) | - get_flag(MS_CHECKBOX_A_FOLDERS, key_folders) | - get_flag(MS_CHECKBOX_A_SELECTION, key_selection); + Flags |= Get3State(MacroSettingsDlg[MS_CHECKBOX_A_PLUGINPANEL].Selected, + MFLAGS_NOPLUGINPANELS, MFLAGS_NOFILEPANELS); + Flags |= Get3State(MacroSettingsDlg[MS_CHECKBOX_A_FOLDERS].Selected, + MFLAGS_NOFOLDERS, MFLAGS_NOFILES); + Flags |= Get3State(MacroSettingsDlg[MS_CHECKBOX_A_SELECTION].Selected, + MFLAGS_NOSELECTION, MFLAGS_SELECTION); } if (MacroSettingsDlg[MS_CHECKBOX_P_PANEL].Selected) { - Flags |= - get_flag(MS_CHECKBOX_P_PLUGINPANEL, key_pluginpanel) | - get_flag(MS_CHECKBOX_P_FOLDERS, key_folders) | - get_flag(MS_CHECKBOX_P_SELECTION, key_selection); + Flags |= Get3State(MacroSettingsDlg[MS_CHECKBOX_P_PLUGINPANEL].Selected, + MFLAGS_PNOPLUGINPANELS, MFLAGS_PNOFILEPANELS); + Flags |= Get3State(MacroSettingsDlg[MS_CHECKBOX_P_FOLDERS].Selected, + MFLAGS_PNOFOLDERS, MFLAGS_PNOFILES); + Flags |= Get3State(MacroSettingsDlg[MS_CHECKBOX_P_SELECTION].Selected, + MFLAGS_PNOSELECTION, MFLAGS_PSELECTION); } + Flags |= Get3State(MacroSettingsDlg[MS_CHECKBOX_CMDLINE].Selected, + MFLAGS_NOTEMPTYCOMMANDLINE, MFLAGS_EMPTYCOMMANDLINE); + Flags |= Get3State(MacroSettingsDlg[MS_CHECKBOX_SELBLOCK].Selected, + MFLAGS_EDITNOSELECTION, MFLAGS_EDITSELECTION); return true; } diff --git a/far/vbuild.m4 b/far/vbuild.m4 index 25802702b0f..613e68ae63b 100644 --- a/far/vbuild.m4 +++ b/far/vbuild.m4 @@ -1 +1 @@ -6211 +6212 From 25dc22f0f2a36076843eaa05d9dfeee36186d8a2 Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Tue, 14 Nov 2023 23:23:17 +0000 Subject: [PATCH 16/16] Add Python version of lng.generator --- misc/lng/lng.generator.py | 204 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 misc/lng/lng.generator.py diff --git a/misc/lng/lng.generator.py b/misc/lng/lng.generator.py new file mode 100644 index 00000000000..c37345bd397 --- /dev/null +++ b/misc/lng/lng.generator.py @@ -0,0 +1,204 @@ +import argparse +import configparser +import os +import shutil +import sys +import tempfile +import zlib + +class lang: + full_filename = "" + filename = "" + name = "" + desc = "" + out_file = None + crc = 0 + old_crc = 0 + need_update = 0 + + +def unquote(s): + return s[1:-1] if s.startswith('"') and s.endswith('"') else s + + +def crc32(file_name): + with open(file_name, 'rb') as f: + hash = 0 + while True: + s = f.read(65536) + if not s: + break + hash = zlib.crc32(s, hash) + + return hash & 0xFFFFFFFF + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-i", help = "optional ini file with update status") + parser.add_argument("-ol", help = "language files output path", required = True) + parser.add_argument("-oh", help = "header file output path", required = True) + parser.add_argument("-nc", action = "store_true") + parser.add_argument("feed_file") + args = parser.parse_args() + + with open(args.feed_file, "r", encoding="utf-8-sig") as feed_file: + data = feed_file.readlines() + + index = 0 + + def skip(i): + while i != len(data): + s = data[i].strip() + if not len(s) or s.startswith("#"): + i += 1 + continue + return i + + def take(): + nonlocal index + index = skip(index) + s = data[index].strip() + index += 1 + return s + + def take_comment(name): + nonlocal index + ss = None + index = skip(index) + while index != len(data): + s = data[index].strip() + if not s.startswith(name): + return ss + + s = s[len(name):] + index += 1 + + if ss is None: + ss = [s] + else: + ss.append(s) + + + hdr_name = take() + lang_count = int(take()) + + if lang_count == 0: + raise Exception("No languages to process") + + hdr_fullname = os.path.join(args.oh, hdr_name) + + old_crc = 0 + config = configparser.ConfigParser() + + if args.i is not None: + config.read(args.i) + + def get_ini(section): + return int(config.get(section, "CRC32", fallback = 0)) + + def set_ini(section, value): + if not section in config: + config[section] = {} + config[section]["CRC32"] = str(value) + + old_crc = get_ini(hdr_fullname) if os.path.isfile(hdr_fullname) else 0 + + hdr_file = tempfile.NamedTemporaryFile(mode = "w", encoding = "utf-8-sig", delete = False) + + langs = [lang() for i in range(lang_count)] + + for l in langs: + l.filename, l.name, l.desc = [unquote(i) for i in take().split(" ", 2)] + + l.full_filename = os.path.join(args.ol, l.filename) + + if args.i is not None and os.path.isfile(l.full_filename): + l.old_crc = get_ini(l.full_filename) + + l.out_file = tempfile.NamedTemporaryFile(mode = "w", encoding = "utf-8-sig", delete = False) + l.out_file.write(f".Language={l.name},{l.desc}\n\n") + + c_hhead = take_comment("hhead:") + if c_hhead is not None: + hdr_file.write(c_hhead) + + c_htail = take_comment("htail:") + + c_enum = take_comment("enum:") + hdr_file.write(f"enum {c_enum[0]}\n{{\n") + + while index != len(data): + # Unused + c_h = take_comment("h:") + # Unused + c_he = take_comment("he:") + + msg_id = take() + + c_l = take_comment("l:") + # Unused + c_le = take_comment("le:") + + if c_h is not None: + hdr_file.write("{}\n".format("\n".join(c_h))) + + if c_l is not None and msg_id != "MYes": + for i in c_l: + hdr_file.write(f"\t{i}\n" if len(i) else "\n") + + hdr_file.write(f"\t{msg_id},\n") + + if c_he is not None: + hdr_file.write("\n".join(c_he)) + + for l in langs: + msg = take() + + if c_l is not None: + l.out_file.write("{}\n".format("\n".join(c_l))) + + if msg.startswith("upd:"): + msg = msg[4:] + l.out_file.write("// need translation:\n") + l.need_update += 1 + + l.out_file.write(f"//[{msg_id}]\n{msg}\n") + + + hdr_file.write("};\n") + + if c_htail is not None: + hdr_file.write(c_htail) + + def finalize(out_file, full_name, old_crc): + out_file.close() + update = True + + new_crc = -1 + if args.i is not None: + new_crc = crc32(out_file.name) + if new_crc == old_crc: + update = False + else: + set_ini(full_name, new_crc) + + if update: + shutil.move(out_file.name, full_name) + + if os.path.exists(out_file.name): + os.remove(out_file.name) + + + for l in langs: + finalize(l.out_file, l.full_filename, l.crc) + if l.need_update: + print(f"INFO: There are {l.need_update} strings that require review in {l.name} translation") + + finalize(hdr_file, hdr_fullname, old_crc) + + if args.i is not None: + with open(args.i, 'w') as configfile: + config.write(configfile) + +if __name__ == '__main__': + main()