Repository :
https://github.com/FarGroup/FarManager
On branch : master
Link :
https://github.com/FarGroup/FarManager/commit/a1a11021dca520881f0009527839e8466b4db7c2
>---------------------------------------------------------------
commit a1a11021dca520881f0009527839e8466b4db7c2
Author: Michael Z. Kadaner <
MKad...@users.noreply.github.com>
Date: Sun May 11 21:08:40 2025 -0400
New feature: Edit the content of Find All menu in a new Editor.
- `F4` copies all found lines into a new editor and closes the menu.
- `Alt+F4` copies all lines matching the current filter into a new editor and closes the menu.
WARNING: The new Editor's behavior related to `Save` and `SaveAs` may be unexpected in corner cases.
>---------------------------------------------------------------
a1a11021dca520881f0009527839e8466b4db7c2
far/FarCze.hlf.m4 | 6 ++
far/FarEng.hlf.m4 | 6 ++
far/FarGer.hlf.m4 | 6 ++
far/FarHun.hlf.m4 | 6 ++
far/FarPol.hlf.m4 | 6 ++
far/FarRus.hlf.m4 | 6 ++
far/FarSky.hlf.m4 | 6 ++
far/FarUkr.hlf.m4 | 6 ++
far/changelog | 11 ++++
far/editor.cpp | 169 +++++++++++++++++++++++++++++++++++++++------------
far/editor.hpp | 7 +++
far/farlang.templ.m4 | 15 +++++
far/fileedit.cpp | 111 +++++++++++++++++----------------
far/fileedit.hpp | 38 ++++++------
far/vbuild.m4 | 2 +-
far/vmenu.hpp | 10 +++
far/vmenu2.hpp | 2 +-
17 files changed, 302 insertions(+), 111 deletions(-)
diff --git a/far/FarCze.hlf.m4 b/far/FarCze.hlf.m4
index 6d5aa3eae..1058a52c2 100644
--- a/far/FarCze.hlf.m4
+++ b/far/FarCze.hlf.m4
@@ -3468,6 +3468,12 @@ string is changed to that of the found string. For example:
$ #Editor: All matching entries menu#
The following key combinations are available in this menu:
+ #F4#
+ Copy all found lines into a new editor and close this menu.
+
+ #Alt+F4#
+ Copy all lines matching the current filter into a new editor and close this menu.
+
#F5#
Toggle menu size.
diff --git a/far/FarEng.hlf.m4 b/far/FarEng.hlf.m4
index 2dafdbea5..6cbaa166f 100644
--- a/far/FarEng.hlf.m4
+++ b/far/FarEng.hlf.m4
@@ -3434,6 +3434,12 @@ string is changed to that of the found string. For example:
$ #Editor: All matching entries menu#
The following key combinations are available in this menu:
+ #F4#
+ Copy all found lines into a new editor and close this menu.
+
+ #Alt+F4#
+ Copy all lines matching the current filter into a new editor and close this menu.
+
#F5#
Toggle menu size.
diff --git a/far/FarGer.hlf.m4 b/far/FarGer.hlf.m4
index e916eda2c..02664a700 100644
--- a/far/FarGer.hlf.m4
+++ b/far/FarGer.hlf.m4
@@ -3508,6 +3508,12 @@ string is changed to that of the found string. For example:
$ #Editor: All matching entries menu#
The following key combinations are available in this menu:
+ #F4#
+ Copy all found lines into a new editor and close this menu.
+
+ #Alt+F4#
+ Copy all lines matching the current filter into a new editor and close this menu.
+
#F5#
Toggle menu size.
diff --git a/far/FarHun.hlf.m4 b/far/FarHun.hlf.m4
index de958f2ef..e61301769 100644
--- a/far/FarHun.hlf.m4
+++ b/far/FarHun.hlf.m4
@@ -3517,6 +3517,12 @@ string is changed to that of the found string. For example:
$ #Editor: All matching entries menu#
The following key combinations are available in this menu:
+ #F4#
+ Copy all found lines into a new editor and close this menu.
+
+ #Alt+F4#
+ Copy all lines matching the current filter into a new editor and close this menu.
+
#F5#
Toggle menu size.
diff --git a/far/FarPol.hlf.m4 b/far/FarPol.hlf.m4
index 9138088cb..9583226a4 100644
--- a/far/FarPol.hlf.m4
+++ b/far/FarPol.hlf.m4
@@ -3436,6 +3436,12 @@ jest zgodna z odnalezionym ciągiem. Na przykład:
$ #Edytor: menu wszystkich znalezionych wystąpień#
Następujące kombinacje klawiszy są dostępne w tym menu:
+ #F4#
+ Copy all found lines into a new editor and close this menu.
+
+ #Alt+F4#
+ Copy all lines matching the current filter into a new editor and close this menu.
+
#F5#
Przełącza wielkość menu.
diff --git a/far/FarRus.hlf.m4 b/far/FarRus.hlf.m4
index 52d5183ea..351c5bc05 100644
--- a/far/FarRus.hlf.m4
+++ b/far/FarRus.hlf.m4
@@ -3485,6 +3485,12 @@ $ #Редактор: Режим замены - Сохранять стиль#
$ #Редактор: Меню результатов поиска всех вхождений#
В этом меню доступны следующие сочетания клавиш:
+ #F4#
+ Копировать все найденные строки в новый редактор и закрыть меню.
+
+ #Alt+F4#
+ Копировать все удовлетворяющие активному фильтру строки в новый редактор и закрыть меню.
+
#F5#
Переключить размер меню.
diff --git a/far/FarSky.hlf.m4 b/far/FarSky.hlf.m4
index f7e4d76ba..7e03126bf 100644
--- a/far/FarSky.hlf.m4
+++ b/far/FarSky.hlf.m4
@@ -3429,6 +3429,12 @@ string is changed to that of the found string. For example:
$ #Editor: All matching entries menu#
The following key combinations are available in this menu:
+ #F4#
+ Copy all found lines into a new editor and close this menu.
+
+ #Alt+F4#
+ Copy all lines matching the current filter into a new editor and close this menu.
+
#F5#
Toggle menu size.
diff --git a/far/FarUkr.hlf.m4 b/far/FarUkr.hlf.m4
index a5e832a24..9106e9c38 100644
--- a/far/FarUkr.hlf.m4
+++ b/far/FarUkr.hlf.m4
@@ -3492,6 +3492,12 @@ string is changed to that of the found string. For example:
$ #Editor: All matching entries menu#
The following key combinations are available in this menu:
+ #F4#
+ Copy all found lines into a new editor and close this menu.
+
+ #Alt+F4#
+ Copy all lines matching the current filter into a new editor and close this menu.
+
#F5#
Toggle menu size.
diff --git a/far/changelog b/far/changelog
index 5c10e39c1..b1c9b07dc 100644
--- a/far/changelog
+++ b/far/changelog
@@ -1,3 +1,14 @@
+--------------------------------------------------------------------------------
+MZK 2025-06-29 21:48:53-04:00 - build 6504
+
+1. New feature: Edit the content of Find All menu in a new Editor.
+ - #F4# copies all found lines into a new editor and closes the menu.
+ - #Alt+F4# copies all lines matching the current filter into a new editor
+ and closes the menu.
+
+ WARNING: The new Editor's behavior related to #Save# and #SaveAs#
+ may be unexpected in corner cases.
+
--------------------------------------------------------------------------------
yjh 2025-06-30 01:22:59+03:00 - build 6503
diff --git a/far/editor.cpp b/far/editor.cpp
index bc78b0b77..c0b096170 100644
--- a/far/editor.cpp
+++ b/far/editor.cpp
@@ -53,6 +53,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "xlat.hpp"
#include "datetime.hpp"
#include "strmix.hpp"
+#include "pathmix.hpp"
#include "wakeful.hpp"
#include "colormix.hpp"
#include "vmenu.hpp"
@@ -228,6 +229,11 @@ void Editor::DisplayObject()
ShowEditor();
}
+fileeditor_ptr Editor::GetHostFileEditor() const
+{
+ return std::dynamic_pointer_cast<FileEditor>(m_Owner.lock());
+}
+
void Editor::ShowEditor()
{
if (Lines.empty())
@@ -368,7 +374,7 @@ void Editor::ShowEditor()
}
// BUGBUG
- if (const auto HostFileEditor = std::dynamic_pointer_cast<FileEditor>(m_Owner.lock()))
+ if (const auto HostFileEditor = GetHostFileEditor())
{
HostFileEditor->ShowStatus();
HostFileEditor->ShowChildren();
@@ -2334,7 +2340,7 @@ bool Editor::ProcessKeyInternal(unsigned const KeyCode, bool& Refresh, Manager::
m_Flags.Set(FEDITOR_PROCESSCTRLQ);
// BUGBUG
- if (const auto HostFileEditor = std::dynamic_pointer_cast<FileEditor>(m_Owner.lock()))
+ if (const auto HostFileEditor = GetHostFileEditor())
HostFileEditor->ShowStatus();
Pasting++;
@@ -2769,7 +2775,7 @@ bool Editor::ProcessMouse(const MOUSE_EVENT_RECORD *MouseEvent)
if (m_it_CurLine->ProcessMouse(MouseEvent))
{
// BUGBUG
- if (const auto HostFileEditor = std::dynamic_pointer_cast<FileEditor>(m_Owner.lock()))
+ if (const auto HostFileEditor = GetHostFileEditor())
HostFileEditor->ShowStatus();
Show();
@@ -3405,8 +3411,9 @@ namespace
class find_all_list
{
public:
- explicit find_all_list(int MaxLinesCount)
- : m_LineNumColumnMaxWidth{ radix10_formatted_width(MaxLinesCount) }
+ find_all_list(const size_t MaxLinesCount, const bool CanSaveFoundItemsToNewEditor)
+ : m_CanSaveFoundItemsToNewEditor{ CanSaveFoundItemsToNewEditor }
+ , m_LineNumColumnMaxWidth{ radix10_formatted_width(MaxLinesCount) }
{}
void add_item(FindCoord FoundCoords, string_view ItemText)
@@ -3435,7 +3442,10 @@ namespace
m_Menu->SetMenuFlags(VMENU_WRAPMODE | VMENU_SHOWAMPERSAND | VMENU_ENABLEALIGNANNOTATIONS);
m_Menu->SetPosition({ -1, m_MenuY1, 0, m_MenuY2 });
m_Menu->SetTitle(far::vformat(msg(lng::MEditSearchStatistics), m_Menu->size(), m_UniqueLineCount));
- m_Menu->SetBottomTitle(KeysToLocalizedText(KEY_CTRLENTER, KEY_F5, KEY_SHIFTF5, KEY_ADD, KEY_CTRLUP, KEY_CTRLDOWN));
+ if (m_CanSaveFoundItemsToNewEditor)
+ m_Menu->SetBottomTitle(KeysToLocalizedText(KEY_CTRLENTER, KEY_F4, KEY_ALTF4, KEY_F5, KEY_SHIFTF5, KEY_ADD, KEY_CTRLUP, KEY_CTRLDOWN));
+ else
+ m_Menu->SetBottomTitle(KeysToLocalizedText(KEY_CTRLENTER, KEY_F5, KEY_SHIFTF5, KEY_ADD, KEY_CTRLUP, KEY_CTRLDOWN));
m_Menu->SetHelp(L"FindAllMenu"sv);
m_Menu->SetId(EditorFindAllListId);
@@ -3475,6 +3485,7 @@ namespace
}
const vmenu2_ptr m_Menu{ VMenu2::create({}, {}) };
+ const bool m_CanSaveFoundItemsToNewEditor{};
private:
const short m_LineNumColumnMaxWidth{};
@@ -3503,7 +3514,7 @@ void Editor::DoSearchReplace(const SearchReplaceDisposition Disposition)
bool MatchFound{}, UserBreak{};
std::optional<undo_block> UndoBlock;
string QuotedStr;
- auto FindAllList{ FindAll ? std::optional<find_all_list>{ Lines.size() } : std::nullopt };
+ auto FindAllList{ FindAll ? std::optional{ find_all_list{ Lines.size(), CanSaveFoundItemsToNewEditor() } } : std::nullopt };
{
HideCursor();
@@ -3858,6 +3869,8 @@ void Editor::DoSearchReplace(const SearchReplaceDisposition Disposition)
if(FindAllList && MatchFound)
{
FindAllList->make_ready();
+ enum class save_to_new_editor { none, all, matching_filter };
+ auto SaveToNewEditor{ save_to_new_editor::none };
const auto ExitCode = FindAllList->m_Menu->Run([&](const Manager::Key& RawKey)
{
@@ -3883,22 +3896,7 @@ void Editor::DoSearchReplace(const SearchReplaceDisposition Disposition)
if (SelectedPos == -1)
break;
- const auto& coord = *FindAllList->m_Menu->GetComplexUserDataPtr<FindCoord>(SelectedPos);
- GoToLine(coord.Line);
- m_it_CurLine->SetCurPos(coord.Pos);
- if (EdOpt.SearchSelFound)
- {
- Pasting++;
- // if (!EdOpt.PersistentBlocks)
- UnmarkBlock();
- BeginStreamMarking(m_it_CurLine);
- m_it_CurLine->Select(coord.Pos, coord.Pos + coord.SearchLen);
- Pasting--;
- }
- if (EdOpt.SearchCursorAtEnd)
- {
- m_it_CurLine->SetCurPos(coord.Pos + coord.SearchLen);
- }
+ SelectFoundPattern(*FindAllList->m_Menu->GetComplexUserDataPtr<FindCoord>(SelectedPos));
Refresh();
}
break;
@@ -3915,6 +3913,22 @@ void Editor::DoSearchReplace(const SearchReplaceDisposition Disposition)
}
break;
+ case KEY_F4:
+ if (FindAllList->m_CanSaveFoundItemsToNewEditor && !FindAllList->m_Menu->ListBox().empty())
+ {
+ SaveToNewEditor = save_to_new_editor::all;
+ FindAllList->m_Menu->Close();
+ }
+ break;
+
+ case KEY_ALTF4: case KEY_RALTF4:
+ if (FindAllList->m_CanSaveFoundItemsToNewEditor && FindAllList->m_Menu->ListBox().HasVisible())
+ {
+ SaveToNewEditor = save_to_new_editor::matching_filter;
+ FindAllList->m_Menu->Close();
+ }
+ break;
+
case KEY_F5:
FindAllList->toggle_zoom();
break;
@@ -3939,23 +3953,15 @@ void Editor::DoSearchReplace(const SearchReplaceDisposition Disposition)
return KeyProcessed;
});
+ if (SaveToNewEditor != save_to_new_editor::none)
+ {
+ SaveFoundItemsToNewEditor(FindAllList->m_Menu->ListBox(), SaveToNewEditor == save_to_new_editor::matching_filter, ExitCode);
+ return;
+ }
+
if(ExitCode >= 0)
{
- const auto& coord = *FindAllList->m_Menu->GetComplexUserDataPtr<FindCoord>(ExitCode);
- GoToLine(coord.Line);
- m_it_CurLine->SetCurPos(coord.Pos);
- if (EdOpt.SearchSelFound)
- {
- Pasting++;
- UnmarkBlock();
- BeginStreamMarking(m_it_CurLine);
- m_it_CurLine->Select(coord.Pos, coord.Pos + coord.SearchLen);
- Pasting--;
- }
- if (EdOpt.SearchCursorAtEnd)
- {
- m_it_CurLine->SetCurPos(coord.Pos + coord.SearchLen);
- }
+ SelectFoundPattern(*FindAllList->m_Menu->GetComplexUserDataPtr<FindCoord>(ExitCode));
Show();
}
}
@@ -3970,6 +3976,89 @@ void Editor::DoSearchReplace(const SearchReplaceDisposition Disposition)
{ lng::MOk });
}
+bool Editor::CanSaveFoundItemsToNewEditor() const
+{
+ const auto HostFileEditor = GetHostFileEditor();
+ if (!HostFileEditor) return false;
+ return HostFileEditor->GetCanLoseFocus();
+}
+
+void Editor::SelectFoundPattern(FindCoord coord)
+{
+ GoToLine(coord.Line);
+ m_it_CurLine->SetCurPos(coord.Pos);
+ if (EdOpt.SearchSelFound)
+ {
+ Pasting++;
+ // if (!EdOpt.PersistentBlocks)
+ UnmarkBlock();
+ BeginStreamMarking(m_it_CurLine);
+ m_it_CurLine->Select(coord.Pos, coord.Pos + coord.SearchLen);
+ Pasting--;
+ }
+ if (EdOpt.SearchCursorAtEnd)
+ {
+ m_it_CurLine->SetCurPos(coord.Pos + coord.SearchLen);
+ }
+}
+
+void Editor::SaveFoundItemsToNewEditor(const VMenu& ListBox, const bool MatchingFilter, intptr_t const ExitCode)
+{
+ const auto ShellEditor{
+ FileEditor::create(GetSearchAllFileName(), GetCodePage(), FFILEEDIT_CANNEWFILE | FFILEEDIT_ENABLEF6 | FFILEEDIT_EPHEMERAL) };
+ auto& NewEditor{ *ShellEditor->GetEditor() };
+ const auto FilterFlags{ LIF_HIDDEN | (MatchingFilter ? LIF_FILTERED : 0) };
+
+ std::optional<FindCoord> NewEditorFoundCoord;
+
+ int ThisEditorLastLine = -1;
+ for (const auto& [Item, Index] : enumerate(ListBox.GetItems()))
+ {
+ if (Item.Flags & FilterFlags) continue;
+
+ const auto ThisEditorCoord{ std::any_cast<FindCoord>(Item.ComplexUserData) };
+
+ if (ThisEditorCoord.Line != ThisEditorLastLine)
+ {
+ ThisEditorLastLine = ThisEditorCoord.Line;
+
+ const auto CurString{ GetStringByNumber(ThisEditorCoord.Line) };
+ const auto NewEditorLine{ NewEditor.InsertString(CurString->GetString(), NewEditor.LastLine()) };
+ NewEditorLine->SetEOL(CurString->GetEOL());
+ }
+
+ if (Index == ExitCode)
+ {
+ const auto CurrentFoundCoord{ *ListBox.GetComplexUserDataPtr<const FindCoord>(ExitCode) };
+ NewEditorFoundCoord =
+ {
+ .Line = std::prev(NewEditor.LastLine()).Number(),
+ .Pos = CurrentFoundCoord.Pos,
+ .SearchLen = CurrentFoundCoord.SearchLen
+ };
+ }
+ }
+
+ if (NewEditorFoundCoord)
+ NewEditor.SelectFoundPattern(*NewEditorFoundCoord);
+ else
+ NewEditor.SetCurPos(0, 0);
+}
+
+string Editor::GetSearchAllFileName() const
+{
+ auto SearchAllFileName{ msg(lng::MEditSearchAllFileNameAppend) };
+
+ const auto HostFileEditor = GetHostFileEditor();
+ if (!HostFileEditor) return SearchAllFileName;
+
+ string HostType, HostName;
+ HostFileEditor->GetTypeAndName(HostType, HostName);
+
+ const auto NameAndExt{ name_ext(HostName) };
+ return NameAndExt.first + SearchAllFileName + NameAndExt.second;
+}
+
void Editor::PasteFromClipboard()
{
if (m_Flags.Check(FEDITOR_LOCKMODE))
@@ -5792,7 +5881,7 @@ int Editor::EditorControl(int Command, intptr_t Param1, void *Param2)
{
const uintptr_t cp = espar->iParam;
// BUGBUG
- if (const auto HostFileEditor = std::dynamic_pointer_cast<FileEditor>(m_Owner.lock()))
+ if (const auto HostFileEditor = GetHostFileEditor())
{
if (!HostFileEditor->SetCodePageEx(cp))
return false;
@@ -6835,7 +6924,7 @@ bool Editor::SetCodePage(uintptr_t const CurrentCodepage, uintptr_t const NewCod
uintptr_t Editor::GetCodePage() const
{
- if (const auto HostFileEditor = std::dynamic_pointer_cast<FileEditor>(m_Owner.lock()))
+ if (const auto HostFileEditor = GetHostFileEditor())
return HostFileEditor->GetCodePage();
throw far_exception(L"HostFileEditor is nullptr"sv);
diff --git a/far/editor.hpp b/far/editor.hpp
index af4223eb5..02c345404 100644
--- a/far/editor.hpp
+++ b/far/editor.hpp
@@ -55,6 +55,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class FileEditor;
class KeyBar;
class Edit;
+struct FindCoord;
struct ColorItem;
class Editor final: public SimpleScreenObject
@@ -196,6 +197,7 @@ private:
enum class undo_type: char;
void DisplayObject() override;
+ fileeditor_ptr GetHostFileEditor() const;
void ShowEditor();
numbered_iterator DeleteString(numbered_iterator DelPtr, bool DeleteLast);
@@ -287,6 +289,10 @@ private:
void DoSearchReplace(SearchReplaceDisposition Disposition);
int CalculateSearchStartPosition(bool Continue, bool Backward, bool Regex) const;
int CalculateSearchNextPositionInTheLine(bool Backward, bool Regex) const;
+ bool CanSaveFoundItemsToNewEditor() const;
+ void SelectFoundPattern(FindCoord coord);
+ void SaveFoundItemsToNewEditor(const VMenu& ListBox, bool MatchingFilter, intptr_t ExitCode);
+ string GetSearchAllFileName() const;
void UpdateIteratorAndKeepPos(numbered_iterator& Iter, const auto& Func);
@@ -320,6 +326,7 @@ private:
void DeleteColor(numbered_iterator const& It, delete_color_condition Condition);
bool GetColor(numbered_iterator const& It, ColorItem& Item, size_t Index) const;
std::multiset<ColorItem> const* GetColors(Edit* It) const;
+
// Младший байт (маска 0xFF) юзается классом ScreenObject!!!
enum editor_flags
{
diff --git a/far/farlang.templ.m4 b/far/farlang.templ.m4
index 6fc66ce25..f122cb8e0 100644
--- a/far/farlang.templ.m4
+++ b/far/farlang.templ.m4
@@ -7681,6 +7681,21 @@ upd:"Occurrences: {0}, lines: {1}"
upd:"Occurrences: {0}, lines: {1}"
upd:"Occurrences: {0}, lines: {1}"
+MEditSearchAllFileNameAppend
+".Filtered"
+".Filtered"
+upd:".Filtered"
+upd:".Filtered"
+upd:".Filtered"
+upd:".Filtered"
+upd:".Filtered"
+upd:".Filtered"
+upd:".Filtered"
+upd:".Filtered"
+upd:".Filtered"
+upd:".Filtered"
+upd:".Filtered"
+
MEditNotFound
"Строка не найдена"
"Could not find the string"
diff --git a/far/fileedit.cpp b/far/fileedit.cpp
index 75263c7fd..53c62ffd8 100644
--- a/far/fileedit.cpp
+++ b/far/fileedit.cpp
@@ -493,6 +493,7 @@ void FileEditor::Init(
SetFileName(Name);
+ if (!m_Flags.Check(FFILEEDIT_EPHEMERAL))
{
if (auto EditorWindow = Global->WindowManager->FindWindowByFile(windowtype_editor, strFullFileName))
{
@@ -686,13 +687,12 @@ void FileEditor::Init(
m_editor->SetPosition({ m_Where.left, m_Where.top + (IsTitleBarVisible()? 1 : 0), m_Where.right, m_Where.bottom - (IsKeyBarVisible()? 1 : 0) });
m_editor->SetStartPos(StartLine,StartChar);
SetDeleteOnClose(DeleteOnClose);
- int UserBreak = 0;
/* $ 06.07.2001 IS
При создании файла с нуля так же посылаем плагинам событие EE_READ, дабы
не нарушать однообразие.
*/
- if (!os::fs::exists(FileStatus))
+ if (m_Flags.Check(FFILEEDIT_EPHEMERAL) || !os::fs::exists(FileStatus))
m_Flags.Set(FFILEEDIT_NEW);
if (BlankFileName && m_Flags.Check(FFILEEDIT_CANNEWFILE))
@@ -704,45 +704,49 @@ void FileEditor::Init(
if (m_Flags.Check(FFILEEDIT_LOCKED))
m_editor->m_Flags.Set(Editor::FEDITOR_LOCKMODE);
- error_state_ex ErrorState;
- while (BlankFileName || !LoadFile(strFullFileName, UserBreak, ErrorState))
+ if (!m_Flags.Check(FFILEEDIT_EPHEMERAL))
{
- if (!m_Flags.Check(FFILEEDIT_NEW) || UserBreak)
+ int UserBreak = 0;
+ error_state_ex ErrorState;
+ while (BlankFileName || !LoadFile(strFullFileName, UserBreak, ErrorState))
{
- if (UserBreak!=1)
+ if (!m_Flags.Check(FFILEEDIT_NEW) || UserBreak)
{
- if(OperationFailed(ErrorState, strFullFileName, lng::MEditTitle, msg(lng::MEditCannotOpen), false) == operation::retry)
- continue;
+ if (UserBreak != 1)
+ {
+ if (OperationFailed(ErrorState, strFullFileName, lng::MEditTitle, msg(lng::MEditCannotOpen), false) == operation::retry)
+ continue;
+ else
+ SetExitCode(XC_OPEN_ERROR);
+ }
else
- SetExitCode(XC_OPEN_ERROR);
- }
- else
- {
- SetExitCode(XC_LOADING_INTERRUPTED);
- }
+ {
+ SetExitCode(XC_LOADING_INTERRUPTED);
+ }
- // Ахтунг. Ниже комментарии оставлены в назидании потомкам (до тех пор, пока не измениться манагер)
- //WindowManager->DeleteWindow(this); // BugZ#546 - Editor валит фар!
- //Global->CtrlObject->Cp()->Redraw(); //AY: вроде как не надо, делает проблемы с прорисовкой если в редакторе из истории попытаться выбрать несуществующий файл
+ // Ахтунг. Ниже комментарии оставлены в назидании потомкам (до тех пор, пока не измениться манагер)
+ //WindowManager->DeleteWindow(this); // BugZ#546 - Editor валит фар!
+ //Global->CtrlObject->Cp()->Redraw(); //AY: вроде как не надо, делает проблемы с прорисовкой если в редакторе из истории попытаться выбрать несуществующий файл
- // если прервали загрузку, то фреймы нужно проапдейтить, чтобы предыдущие месаги не оставались на экране
- if (!Global->Opt->Confirm.Esc && UserBreak && GetExitCode() == XC_LOADING_INTERRUPTED)
- Global->WindowManager->RefreshWindow();
+ // если прервали загрузку, то фреймы нужно проапдейтить, чтобы предыдущие месаги не оставались на экране
+ if (!Global->Opt->Confirm.Esc && UserBreak && GetExitCode() == XC_LOADING_INTERRUPTED)
+ Global->WindowManager->RefreshWindow();
- return;
- }
+ return;
+ }
- if (m_codepage==CP_DEFAULT || m_codepage == CP_REDETECT)
- m_codepage = GetDefaultCodePage();
+ if (m_codepage == CP_DEFAULT || m_codepage == CP_REDETECT)
+ m_codepage = GetDefaultCodePage();
- break;
- }
+ break;
+ }
- if (GetExitCode() == XC_LOADING_INTERRUPTED || GetExitCode() == XC_OPEN_ERROR)
- return;
+ if (GetExitCode() == XC_LOADING_INTERRUPTED || GetExitCode() == XC_OPEN_ERROR)
+ return;
- if (!m_Flags.Check(FFILEEDIT_DISABLEHISTORY) && !strFileName.empty())
- Global->CtrlObject->ViewHistory->AddToHistory(strFullFileName, m_editor->m_Flags.Check(Editor::FEDITOR_LOCKMODE)? HR_EDITOR_RO : HR_EDITOR);
+ if (!m_Flags.Check(FFILEEDIT_DISABLEHISTORY) && !strFileName.empty())
+ Global->CtrlObject->ViewHistory->AddToHistory(strFullFileName, m_editor->m_Flags.Check(Editor::FEDITOR_LOCKMODE)? HR_EDITOR_RO : HR_EDITOR);
+ }
InitKeyBar();
// Note: bottom - bottom
@@ -803,7 +807,7 @@ void FileEditor::InitKeyBar()
Keybar[KBL_SHIFT][F4].clear();
}
- if (m_Flags.Check(FFILEEDIT_SAVETOSAVEAS))
+ if (m_Flags.Check(FFILEEDIT_SAVETOSAVEAS | FFILEEDIT_EPHEMERAL))
Keybar[KBL_MAIN][F2] = msg(lng::MEditShiftF2);
if (!m_Flags.Check(FFILEEDIT_ENABLEF6))
@@ -949,10 +953,10 @@ bool FileEditor::ReProcessKey(const Manager::Key& Key, bool CalledFromControl)
break; // отдадим F6 плагинам, если есть запрет на переключение
// If the file is "new", there is nothing to view yet, so we have to save it first.
- const auto NeedSave = m_editor->m_Flags.Check(Editor::FEDITOR_MODIFIED) || m_Flags.Check(FFILEEDIT_NEW);
- bool ConfirmSave = !m_Flags.Check(FFILEEDIT_NEW);
+ const auto NeedSave = m_editor->m_Flags.Check(Editor::FEDITOR_MODIFIED) || m_Flags.Check(FFILEEDIT_NEW | FFILEEDIT_EPHEMERAL);
+ bool ConfirmSave = !m_Flags.Check(FFILEEDIT_NEW) || m_Flags.Check(FFILEEDIT_EPHEMERAL);
- if (!m_Flags.Check(FFILEEDIT_NEW) && !os::fs::is_file(strFullFileName))
+ if (!m_Flags.Check(FFILEEDIT_NEW | FFILEEDIT_EPHEMERAL) && !os::fs::is_file(strFullFileName))
{
ConfirmSave = false;
@@ -1102,7 +1106,7 @@ bool FileEditor::ReProcessKey(const Manager::Key& Key, bool CalledFromControl)
case KEY_CTRLF10:
case KEY_RCTRLF10:
{
- if (Global->WindowManager->InModal())
+ if (m_Flags.Check(FFILEEDIT_EPHEMERAL) || Global->WindowManager->InModal())
{
return true;
}
@@ -1150,7 +1154,8 @@ bool FileEditor::ReProcessKey(const Manager::Key& Key, bool CalledFromControl)
case KEY_ESC:
case KEY_F10:
{
- bool ConfirmSave = true, NeedSave = m_editor->m_Flags.Check(Editor::FEDITOR_MODIFIED);
+ bool NeedSave = m_editor->m_Flags.Check(Editor::FEDITOR_MODIFIED);
+ bool ConfirmSave = true;
if (!m_Flags.Check(FFILEEDIT_NEW) && !os::fs::is_file(strFullFileName))
{
@@ -1218,7 +1223,7 @@ bool FileEditor::ReProcessKey(const Manager::Key& Key, bool CalledFromControl)
if (m_editor->ProcessKey(Key))
{
ShowStatus();
- if (!m_Flags.Check(FFILEEDIT_DISABLEHISTORY))
+ if (!m_Flags.Check(FFILEEDIT_DISABLEHISTORY | FFILEEDIT_EPHEMERAL))
Global->CtrlObject->ViewHistory->AddToHistory(strFullFileName, m_editor->m_Flags.Check(Editor::FEDITOR_LOCKMODE)? HR_EDITOR_RO : HR_EDITOR);
}
}
@@ -1666,7 +1671,7 @@ bool FileEditor::ReloadFile(uintptr_t codepage)
}
}
-//TextFormat и codepage используются ТОЛЬКО, если bSaveAs = true!
+// Eol and Codepage are used ONLY if bSaveAs = true!
int FileEditor::SaveFile(const string_view Name, bool bSaveAs, error_state_ex& ErrorState, eol Eol, uintptr_t Codepage, bool AddSignature)
{
if (!bSaveAs)
@@ -1774,10 +1779,10 @@ int FileEditor::SaveFile(const string_view Name, bool bSaveAs, error_state_ex& E
m_Flags.Set(FFILEEDIT_NEW);
//SaveScreen SaveScr;
- /* $ 11.10.2001 IS
- Если было произведено сохранение с любым результатом, то не удалять файл
- */
- m_Flags.Clear(FFILEEDIT_DELETEONCLOSE|FFILEEDIT_DELETEONLYFILEONCLOSE);
+
+ // $ 11.10.2001 IS Если было произведено сохранение с любым результатом, то не удалять файл
+ // 2025-05-31 MZK And the file is not ephemeral anymore
+ m_Flags.Clear(FFILEEDIT_DELETEONCLOSE | FFILEEDIT_DELETEONLYFILEONCLOSE | FFILEEDIT_EPHEMERAL);
if (!IsUtfCodePage(Codepage))
{
@@ -1913,7 +1918,7 @@ bool FileEditor::SaveAction(bool const SaveAsIntention)
const auto SaveAs =
SaveAsIntention ||
- m_Flags.Check(FFILEEDIT_SAVETOSAVEAS) ||
+ m_Flags.Check(FFILEEDIT_SAVETOSAVEAS | FFILEEDIT_EPHEMERAL) ||
!os::fs::is_directory(ParentDirectory);
for (;;)
@@ -1938,10 +1943,8 @@ bool FileEditor::SaveAction(bool const SaveAsIntention)
strSaveAsName = unquote(os::env::expand(strSaveAsName));
strFullSaveAsName = ConvertNameToFull(strSaveAsName);
- if (!equal_icase(strFullSaveAsName, strFullFileName) && os::fs::exists(strFullSaveAsName) && !AskOverwrite(strSaveAsName))
- {
+ if (DoNotOverwrite(strFullSaveAsName, strSaveAsName))
return false;
- }
}
error_state_ex ErrorState;
@@ -2017,7 +2020,7 @@ void FileEditor::SetScreenPosition()
void FileEditor::OnDestroy()
{
- if (Global->CtrlObject && !m_Flags.Check(FFILEEDIT_DISABLEHISTORY) && !strFileName.empty())
+ if (Global->CtrlObject && !m_Flags.Check(FFILEEDIT_DISABLEHISTORY | FFILEEDIT_EPHEMERAL) && !strFileName.empty())
Global->CtrlObject->ViewHistory->AddToHistory(strFullFileName, m_editor->m_Flags.Check(Editor::FEDITOR_LOCKMODE)? HR_EDITOR_RO : HR_EDITOR);
//AY: флаг оповещающий закрытие редактора.
@@ -2489,7 +2492,7 @@ intptr_t FileEditor::EditorControl(int Command, intptr_t Param1, void *Param2)
Codepage = esf->CodePage;
}
- if (!equal_icase(strName, strFullFileName) && os::fs::exists(strName) && !AskOverwrite(PointToName(strName)))
+ if (DoNotOverwrite(strName, PointToName(strName)))
return FALSE;
//всегда записываем в режиме save as - иначе не сменить кодировку и концы линий.
@@ -2677,17 +2680,23 @@ bool FileEditor::SetCodePage(uintptr_t codepage)
return true;
}
-bool FileEditor::AskOverwrite(const string_view FileName)
+bool FileEditor::DoNotOverwrite(const string_view FullSaveAsName, const string_view SaveAsName)
{
+ if (!m_Flags.Check(FFILEEDIT_EPHEMERAL) && equal_icase(FullSaveAsName, strFullFileName))
+ return false;
+
+ if (!os::fs::exists(FullSaveAsName))
+ return false;
+
return Message(MSG_WARNING,
msg(lng::MEditTitle),
{
- string(FileName),
+ string(SaveAsName),
msg(lng::MEditExists),
msg(lng::MEditOvr)
},
{ lng::MYes, lng::MNo },
- {}, &EditorAskOverwriteId) == message_result::first_button;
+ {}, &EditorAskOverwriteId) != message_result::first_button;
}
uintptr_t FileEditor::GetDefaultCodePage()
diff --git a/far/fileedit.hpp b/far/fileedit.hpp
index d2e11a6b8..10254ab7b 100644
--- a/far/fileedit.hpp
+++ b/far/fileedit.hpp
@@ -63,22 +63,24 @@ enum
enum FFILEEDIT_FLAGS
{
- FFILEEDIT_NEW = 16_bit, // Этот файл СОВЕРШЕННО! новый или его успели стереть! Нету такого и все тут.
- FFILEEDIT_REDRAWTITLE = 17_bit, // Нужно редравить заголовок?
- FFILEEDIT_FULLSCREEN = 18_bit, // Полноэкранный режим?
- FFILEEDIT_DISABLEHISTORY = 19_bit, // Запретить запись в историю?
- FFILEEDIT_ENABLEF6 = 20_bit, // Переключаться во вьювер можно?
- FFILEEDIT_SAVETOSAVEAS = 21_bit, // $ 17.08.2001 KM Добавлено для поиска по AltF7.
- FFILEEDIT_WAS_SAVED = 22_bit, // The file was saved by the user at least once. Sometimes we need to know, e.g. if it's from a plugin panel.
- // При редактировании найденного файла из архива для
- // клавиши F2 сделать вызов ShiftF2.
- FFILEEDIT_LOCKED = 23_bit, // заблокировать?
- FFILEEDIT_OPENFAILED = 24_bit, // файл открыть не удалось
- FFILEEDIT_DELETEONCLOSE = 25_bit, // удалить в деструкторе файл вместе с каталогом (если тот пуст)
- FFILEEDIT_DELETEONLYFILEONCLOSE = 26_bit, // удалить в деструкторе только файл
- FFILEEDIT_DISABLESAVEPOS = 27_bit, // не сохранять позицию для файла
- FFILEEDIT_CANNEWFILE = 28_bit, // допускается новый файл?
- FFILEEDIT_SERVICEREGION = 29_bit, // используется сервисная область
+ FFILEEDIT_NEW = 16_bit, // Этот файл СОВЕРШЕННО! новый или его успели стереть! Нету такого и все тут.
+ FFILEEDIT_REDRAWTITLE = 17_bit, // Нужно редравить заголовок?
+ FFILEEDIT_FULLSCREEN = 18_bit, // Полноэкранный режим?
+ FFILEEDIT_DISABLEHISTORY = 19_bit, // Запретить запись в историю?
+ FFILEEDIT_ENABLEF6 = 20_bit, // Переключаться во вьювер можно?
+ FFILEEDIT_SAVETOSAVEAS = 21_bit, // $ 17.08.2001 KM Добавлено для поиска по AltF7.
+ // При редактировании найденного файла из архива для клавиши F2 сделать вызов ShiftF2.
+ FFILEEDIT_WAS_SAVED = 22_bit, // The file was saved by the user at least once. Sometimes we need to know, e.g. if it's from a plugin panel.
+ FFILEEDIT_LOCKED = 23_bit, // заблокировать?
+ FFILEEDIT_OPENFAILED = 24_bit, // файл открыть не удалось
+ FFILEEDIT_DELETEONCLOSE = 25_bit, // удалить в деструкторе файл вместе с каталогом (если тот пуст)
+ FFILEEDIT_DELETEONLYFILEONCLOSE = 26_bit, // удалить в деструкторе только файл
+ FFILEEDIT_DISABLESAVEPOS = 27_bit, // не сохранять позицию для файла
+ FFILEEDIT_CANNEWFILE = 28_bit, // допускается новый файл?
+ FFILEEDIT_SERVICEREGION = 29_bit, // используется сервисная область
+ FFILEEDIT_EPHEMERAL = 30_bit, // Even if the file exists, do not read it.
+ // Until the file saved for the first time: (i) Save works as SaveAs and (ii) History is disabled.
+ // After the file is saved, the mode is dropped and FileEditor behaves as usual.
};
class FileEditor final: public window,public EditorContainer
@@ -92,6 +94,7 @@ public:
explicit FileEditor(private_tag);
~FileEditor() override;
+ bool GetCanLoseFocus(bool DynamicMode = false) const override;
bool IsFileModified() const override { return m_editor->IsModified(); }
int GetTypeAndName(string &strType, string &strName) override;
long long VMProcess(int OpCode, void* vParam = nullptr, long long iParam = 0) override;
@@ -128,7 +131,6 @@ private:
void SetScreenPosition() override;
int GetType() const override { return windowtype_editor; }
void OnDestroy() override;
- bool GetCanLoseFocus(bool DynamicMode = false) const override;
bool CanFastHide() const override; // для нужд CtrlAltShift
string GetTitle() const override;
bool IsKeyBarVisible() const override;
@@ -141,7 +143,7 @@ private:
*/
void SetDeleteOnClose(int NewMode);
bool ReProcessKey(const Manager::Key& Key, bool CalledFromControl = true);
- bool AskOverwrite(string_view FileName);
+ bool DoNotOverwrite(string_view FullSaveAsName, string_view SaveAsName);
void Init(string_view Name, uintptr_t codepage, const string* Title, int StartLine, int StartChar, const string* PluginData, int DeleteOnClose, const window_ptr& Update, EDITOR_FLAGS OpenModeExstFile);
bool LoadFile(string_view Name, int &UserBreak, error_state_ex& ErrorState);
bool ReloadFile(uintptr_t codepage);
diff --git a/far/vbuild.m4 b/far/vbuild.m4
index 1e5f294b6..401510f15 100644
--- a/far/vbuild.m4
+++ b/far/vbuild.m4
@@ -1 +1 @@
-6503
+6504
diff --git a/far/vmenu.hpp b/far/vmenu.hpp
index d125bda9d..bae0734a4 100644
--- a/far/vmenu.hpp
+++ b/far/vmenu.hpp
@@ -226,17 +226,27 @@ public:
// SelectPos == -1 & non-empty Items - everything is filtered
bool HasVisible() const { return SelectPos > -1 && !Items.empty(); }
int GetShowItemCount() const { return static_cast<int>(Items.size() - ItemHiddenCount); }
+ std::span<MenuItemEx const> GetItems() const noexcept { return Items; }
int GetVisualPos(int Pos) const;
int VisualPosToReal(int VPos) const;
intptr_t GetSimpleUserData(int Position = -1) const;
std::any* GetComplexUserData(int Position = -1);
+ const std::any* GetComplexUserData(int Position = -1) const
+ {
+ return const_cast<VMenu*>(this)->GetComplexUserData();
+ }
template<class T>
T* GetComplexUserDataPtr(int Position = -1)
{
return std::any_cast<T>(GetComplexUserData(Position));
}
+ template<class T>
+ const T* GetComplexUserDataPtr(int Position = -1) const
+ {
+ return std::any_cast<T>(GetComplexUserData(Position));
+ }
void SetComplexUserData(const std::any& Data, int Position = -1);
int GetSelectPos() const { return SelectPos; }
diff --git a/far/vmenu2.hpp b/far/vmenu2.hpp
index 3995628f7..386f35692 100644
--- a/far/vmenu2.hpp
+++ b/far/vmenu2.hpp
@@ -128,13 +128,13 @@ public:
MenuItemEx& at(size_t n);
MenuItemEx& current();
int GetShowItemCount() const;
+ VMenu& ListBox() const { return *GetAllItem()[0].ListPtr; }
private:
intptr_t VMenu2DlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2);
int Call(int Msg, void *param);
LISTITEMFLAGS GetItemFlags(int Position = -1);
string GetMenuTitle(bool bottom = false);
- VMenu& ListBox() const { return *GetAllItem()[0].ListPtr; }
enum class box_type
{