Repository :
https://github.com/FarGroup/FarManager
On branch : master
Link :
https://github.com/FarGroup/FarManager/commit/6083b216216f76e8e06612fb37b8f95d9908b296
>---------------------------------------------------------------
commit 6083b216216f76e8e06612fb37b8f95d9908b296
Author: Michael Z. Kadaner <
MKad...@users.noreply.github.com>
Date: Sat Jun 13 13:50:37 2026 -0400
Do not store `Annotation` in menu item.
Retrieve it from the menu owner on demand.
>---------------------------------------------------------------
6083b216216f76e8e06612fb37b8f95d9908b296
far/editor.cpp | 11 ++++++++++-
far/vmenu.cpp | 32 +++++++++++++++++++-------------
far/vmenu.hpp | 6 +++++-
far/vmenu2.cpp | 1 -
4 files changed, 34 insertions(+), 16 deletions(-)
diff --git a/far/editor.cpp b/far/editor.cpp
index 2b9f6c1a8..eaf27f2cd 100644
--- a/far/editor.cpp
+++ b/far/editor.cpp
@@ -3527,7 +3527,6 @@ namespace
void add_item(FindCoord FoundCoords, string_view ItemText)
{
menu_item_ex Item{ string{ ItemText } };
- Item.Annotation.emplace(FoundCoords.Pos, segment::length_tag{ FoundCoords.SearchLen });
Item.ComplexUserData = FoundCoords;
m_Menu->AddItem(Item);
@@ -3606,6 +3605,16 @@ namespace
return false;
}
);
+ m_Menu->ListBox().RegisterItemAnnotationProvider(
+ [](const menu_item_ex& Item)
+ {
+ if (const auto* Coord{ std::any_cast<FindCoord>(&Item.ComplexUserData) })
+ {
+ return segment{ Coord->Pos, segment::length_tag{ Coord->SearchLen } };
+ }
+ return segment{};
+ }
+ );
}
void toggle_zoom()
diff --git a/far/vmenu.cpp b/far/vmenu.cpp
index 3046de49a..67b3c6bf6 100644
--- a/far/vmenu.cpp
+++ b/far/vmenu.cpp
@@ -527,11 +527,6 @@ namespace
return Item.Name;
}
- int safe_get_item_annotation(menu_item_ex const& Item)
- {
- return Item.Annotation.transform([](const auto Annotation) { return Annotation.start(); }).value_or(0);
- }
-
std::pair<int, int> item_hpos_limits(const int ItemLength, const int TextAreaWidth, const item_hscroll_policy Policy) noexcept
{
using enum item_hscroll_policy;
@@ -949,7 +944,7 @@ int VMenu::AddItem(menu_item_ex&& NewItem,int PosAdd)
const auto ItemLength{ GetItemVisualLength(NewMenuItem) };
UpdateMaxLength(ItemLength);
- m_HorizontalTracker->add_item(NewMenuItem.HorizontalPosition, ItemLength, safe_get_item_annotation(NewMenuItem));
+ m_HorizontalTracker->add_item(NewMenuItem.HorizontalPosition, ItemLength, SafeGetItemAnnotationStart(NewMenuItem));
const auto NewFlags = NewMenuItem.Flags;
NewMenuItem.Flags = 0;
@@ -967,13 +962,12 @@ bool VMenu::UpdateItem(const FarListUpdate *NewItem)
auto& Item = Items[NewItem->Index];
m_HorizontalTracker->remove_item(
- Item.HorizontalPosition, GetItemVisualLength(Item), safe_get_item_annotation(Item));
+ Item.HorizontalPosition, GetItemVisualLength(Item), SafeGetItemAnnotationStart(Item));
// Освободим память... от ранее занятого ;-)
if (NewItem->Item.Flags&LIF_DELETEUSERDATA)
{
Item.ComplexUserData = {};
- Item.Annotation.reset();
}
Item.Name = NullToEmpty(NewItem->Item.Text);
@@ -982,7 +976,7 @@ bool VMenu::UpdateItem(const FarListUpdate *NewItem)
const auto ItemLength{ GetItemVisualLength(Item) };
UpdateMaxLength(ItemLength);
- m_HorizontalTracker->add_item(Item.HorizontalPosition, ItemLength, safe_get_item_annotation(Item));
+ m_HorizontalTracker->add_item(Item.HorizontalPosition, ItemLength, SafeGetItemAnnotationStart(Item));
SetMenuFlags(VMENU_UPDATEREQUIRED | (bFilterEnabled ? VMENU_REFILTERREQUIRED : VMENU_NONE));
@@ -1013,7 +1007,7 @@ int VMenu::DeleteItem(int ID, int Count)
--ItemHiddenCount;
m_HorizontalTracker->remove_item(
- I.HorizontalPosition, GetItemVisualLength(I), safe_get_item_annotation(I));
+ I.HorizontalPosition, GetItemVisualLength(I), SafeGetItemAnnotationStart(I));
}
// а вот теперь перемещения
@@ -2363,7 +2357,7 @@ bool VMenu::SetItemHPos(menu_item_ex& Item, const auto& GetNewHPos)
return GetNewHPos(Item.HorizontalPosition, ItemLength);
}();
- m_HorizontalTracker->update_item_hpos(Item.HorizontalPosition, NewHPos, ItemLength, safe_get_item_annotation(Item));
+ m_HorizontalTracker->update_item_hpos(Item.HorizontalPosition, NewHPos, ItemLength, SafeGetItemAnnotationStart(Item));
if (Item.HorizontalPosition == NewHPos) return false;
Item.HorizontalPosition = NewHPos;
@@ -2457,7 +2451,7 @@ bool VMenu::AlignAnnotations()
return SetAllItemsHPos(
[&](const menu_item_ex& Item)
{
- return AlignPos - static_cast<int>(visual_string_length(get_item_text(Item).substr(0, safe_get_item_annotation(Item))));
+ return AlignPos - static_cast<int>(visual_string_length(get_item_text(Item).substr(0, SafeGetItemAnnotationStart(Item))));
});
}
@@ -2934,7 +2928,7 @@ std::tuple<string, segment> VMenu::GetItemTextWithHighlight(const menu_item_ex&
const auto GetHighlight{
[&]
{
- if (Item.Annotation) return *Item.Annotation;
+ if (m_ItemAnnotationProvider) return m_ItemAnnotationProvider(Item);
if (HotkeyPos != string::npos) return segment{ static_cast<int>(HotkeyPos), segment::length_tag{ 1 } };
if (Item.AutoHotkey) return segment{ static_cast<int>(Item.AutoHotkeyPos), segment::length_tag{ 1 } };
return segment{};
@@ -3427,6 +3421,11 @@ void VMenu::RegisterExtendedDataProvider(extended_item_data_getter&& ExtendedDat
m_ExtendedDataSetter = std::move(ExtendedDataSetter);
}
+void VMenu::RegisterItemAnnotationProvider(item_annotation_provider&& ItemAnnotationProvider)
+{
+ m_ItemAnnotationProvider = std::move(ItemAnnotationProvider);
+}
+
FarListItem *VMenu::MenuItem2FarList(const menu_item_ex *MItem, FarListItem *FItem)
{
if (FItem && MItem)
@@ -3589,6 +3588,13 @@ int VMenu::GetItemVisualLength(const menu_item_ex& Item) const
return static_cast<int>(CheckFlags(VMENU_SHOWAMPERSAND) ? visual_string_length(ItemText) : HiStrlen(ItemText));
}
+int VMenu::SafeGetItemAnnotationStart(const menu_item_ex& Item) const
+{
+ if (!m_ItemAnnotationProvider) return 0;
+ const auto Annotation{ m_ItemAnnotationProvider(Item) };
+ return Annotation.empty() ? 0 : Annotation.start();
+}
+
#ifdef ENABLE_TESTS
#include "testing.hpp"
diff --git a/far/vmenu.hpp b/far/vmenu.hpp
index 56aed92c0..c2bb3e645 100644
--- a/far/vmenu.hpp
+++ b/far/vmenu.hpp
@@ -137,7 +137,6 @@ struct menu_item_ex: menu_item
: menu_item{ std::forward<T>(Name), Flags }
{}
- std::optional<segment> Annotation;
std::any ComplexUserData;
intptr_t SimpleUserData{};
@@ -251,6 +250,9 @@ public:
using extended_item_data_setter = std::function<bool(menu_item_ex&, const extended_item_data&)>;
void RegisterExtendedDataProvider(extended_item_data_getter&& ExtendedDataGetter, extended_item_data_setter&& ExtendedDataSetter);
+ using item_annotation_provider = std::function<segment(const menu_item_ex&)>;
+ void RegisterItemAnnotationProvider(item_annotation_provider&& ItemAnnotationProvider);
+
int GetSelectPos() const { return SelectPos; }
int GetLastSelectPosResult() const { return SelectPosResult; }
int GetSelectPos(FarListPos *ListPos) const;
@@ -324,6 +326,7 @@ private:
[[nodiscard]] int CalculateTextAreaWidth() const;
[[nodiscard]] int GetItemVisualLength(const menu_item_ex& Item) const;
+ [[nodiscard]] int SafeGetItemAnnotationStart(const menu_item_ex& Item) const;
int GetItemPosition(int Position) const;
bool CheckKeyHiOrAcc(DWORD Key, int Type, bool Translate, bool ChangePos, int& NewPos);
@@ -361,6 +364,7 @@ private:
fixed_column_provider m_FixedColumnProvider;
extended_item_data_getter m_ExtendedDataGetter;
extended_item_data_setter m_ExtendedDataSetter;
+ item_annotation_provider m_ItemAnnotationProvider;
window_ptr CurrentWindow;
bool PrevCursorVisible{};
size_t PrevCursorSize{};
diff --git a/far/vmenu2.cpp b/far/vmenu2.cpp
index e8080fe86..8a9738d57 100644
--- a/far/vmenu2.cpp
+++ b/far/vmenu2.cpp
@@ -446,7 +446,6 @@ int VMenu2::AddItem(const menu_item_ex& NewItem, int PosAdd)
auto& Item = at(PosAdd);
Item.AccelKey=NewItem.AccelKey;
- Item.Annotation = NewItem.Annotation;
Resize();
return n;