diff options
author | elfmz <fenix1905@tut.by> | 2021-12-31 00:27:16 +0300 |
---|---|---|
committer | elfmz <fenix1905@tut.by> | 2021-12-31 02:27:02 +0300 |
commit | a14dc1a81c797928d4f1b7d6a6b46ecc63f98308 (patch) | |
tree | c27c61ac33582bc4d469c6608cd042add388f230 /far2l/src/fileedit.cpp | |
parent | d5f1bf245e96834d44390d1723cfef3dfbb1fb02 (diff) |
shuffle a bit far2l sources
Diffstat (limited to 'far2l/src/fileedit.cpp')
-rw-r--r-- | far2l/src/fileedit.cpp | 2905 |
1 files changed, 2905 insertions, 0 deletions
diff --git a/far2l/src/fileedit.cpp b/far2l/src/fileedit.cpp new file mode 100644 index 00000000..dabfcf59 --- /dev/null +++ b/far2l/src/fileedit.cpp @@ -0,0 +1,2905 @@ +/* +fileedit.cpp + +Редактирование файла - надстройка над editor.cpp +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "headers.hpp" + +#include <limits> +#include "fileedit.hpp" +#include "keyboard.hpp" +#include "codepage.hpp" +#include "lang.hpp" +#include "macroopcode.hpp" +#include "keys.hpp" +#include "ctrlobj.hpp" +#include "poscache.hpp" +#include "filepanels.hpp" +#include "panel.hpp" +#include "dialog.hpp" +#include "fileview.hpp" +#include "help.hpp" +#include "ctrlobj.hpp" +#include "manager.hpp" +#include "namelist.hpp" +#include "history.hpp" +#include "cmdline.hpp" +#include "scrbuf.hpp" +#include "savescr.hpp" +#include "chgprior.hpp" +#include "filestr.hpp" +#include "TPreRedrawFunc.hpp" +#include "syslog.hpp" +#include "interf.hpp" +#include "message.hpp" +#include "config.hpp" +#include "delete.hpp" +#include "datetime.hpp" +#include "pathmix.hpp" +#include "dirmix.hpp" +#include "strmix.hpp" +#include "exitcode.hpp" +#include "cache.hpp" +#include "constitle.hpp" +#include "wakeful.hpp" +#include "DlgGuid.hpp" +#include "filelist.hpp" + +enum enumOpenEditor +{ + ID_OE_TITLE, + ID_OE_OPENFILETITLE, + ID_OE_FILENAME, + ID_OE_SEPARATOR1, + ID_OE_CODEPAGETITLE, + ID_OE_CODEPAGE, + ID_OE_SEPARATOR2, + ID_OE_OK, + ID_OE_CANCEL, +}; + +static const wchar_t *EOLName(const wchar_t *eol) +{ + if (wcscmp(eol, L"\n") == 0) + return L"LF"; + + if (wcscmp(eol, L"\r") == 0) + return L"CR"; + + if (wcscmp(eol, L"\r\n") == 0) + return L"CRLF"; + + if (wcscmp(eol, L"\r\r\n") == 0) + return L"CRRLF"; + + return eol;//L"WTF"; +} + +LONG_PTR __stdcall hndOpenEditor( + HANDLE hDlg, + int msg, + int param1, + LONG_PTR param2 +) +{ + if (msg == DN_INITDIALOG) + { + int codepage = *(int*)SendDlgMessage(hDlg, DM_GETDLGDATA, 0, 0); + FillCodePagesList(hDlg, ID_OE_CODEPAGE, codepage, true, false); + } + + if (msg == DN_CLOSE) + { + if (param1 == ID_OE_OK) + { + int *param = (int*)SendDlgMessage(hDlg, DM_GETDLGDATA, 0, 0); + FarListPos pos; + SendDlgMessage(hDlg, DM_LISTGETCURPOS, ID_OE_CODEPAGE, (LONG_PTR)&pos); + *param = (int)SendDlgMessage(hDlg, DM_LISTGETDATA, ID_OE_CODEPAGE, pos.SelectPos); + return TRUE; + } + } + + return DefDlgProc(hDlg, msg, param1, param2); +} + +bool dlgOpenEditor(FARString &strFileName, UINT &codepage) +{ + const wchar_t *HistoryName=L"NewEdit"; + DialogDataEx EditDlgData[]= + { + {DI_DOUBLEBOX,3,1,72,8,{},0,MSG(MEditTitle)}, + {DI_TEXT, 5,2, 0,2,{},0,MSG(MEditOpenCreateLabel)}, + {DI_EDIT, 5,3,70,3,{(DWORD_PTR)HistoryName},DIF_FOCUS|DIF_HISTORY|DIF_EDITEXPAND|DIF_EDITPATH,L""}, + {DI_TEXT, 3,4, 0,4,{},DIF_SEPARATOR,L""}, + {DI_TEXT, 5,5, 0,5,{},0,MSG(MEditCodePage)}, + {DI_COMBOBOX,25,5,70,5,{},DIF_DROPDOWNLIST|DIF_LISTWRAPMODE|DIF_LISTAUTOHIGHLIGHT,L""}, + {DI_TEXT, 3,6, 0,6,{},DIF_SEPARATOR,L""}, + {DI_BUTTON, 0,7, 0,7,{},DIF_DEFAULT|DIF_CENTERGROUP,MSG(MOk)}, + {DI_BUTTON, 0,7, 0,7,{},DIF_CENTERGROUP,MSG(MCancel)} + }; + MakeDialogItemsEx(EditDlgData,EditDlg); + EditDlg[ID_OE_FILENAME].strData = strFileName; + Dialog Dlg(EditDlg, ARRAYSIZE(EditDlg), (FARWINDOWPROC)hndOpenEditor, (LONG_PTR)&codepage); + Dlg.SetPosition(-1,-1,76,10); + Dlg.SetHelp(L"FileOpenCreate"); + Dlg.SetId(FileOpenCreateId); + Dlg.Process(); + + if (Dlg.GetExitCode() == ID_OE_OK) + { + strFileName = EditDlg[ID_OE_FILENAME].strData; + ConvertHomePrefixInPath(strFileName); + return true; + } + + return false; +} + + + + +enum enumSaveFileAs +{ + ID_SF_TITLE, + ID_SF_SAVEASFILETITLE, + ID_SF_FILENAME, + ID_SF_SEPARATOR1, + ID_SF_CODEPAGETITLE, + ID_SF_CODEPAGE, + ID_SF_SIGNATURE, + ID_SF_SEPARATOR2, + ID_SF_SAVEASFORMATTITLE, + ID_SF_DONOTCHANGE, + ID_SF_DOS, + ID_SF_UNIX, + ID_SF_MAC, + ID_SF_SEPARATOR3, + ID_SF_OK, + ID_SF_CANCEL, +}; + +LONG_PTR __stdcall hndSaveFileAs( + HANDLE hDlg, + int msg, + int param1, + LONG_PTR param2 +) +{ + static UINT codepage=0; + + switch (msg) + { + case DN_INITDIALOG: + { + codepage=*(UINT*)SendDlgMessage(hDlg, DM_GETDLGDATA, 0, 0); + FillCodePagesList(hDlg, ID_SF_CODEPAGE, codepage, false, false); + + if (IsUnicodeOrUtfCodePage(codepage)) + { + SendDlgMessage(hDlg,DM_ENABLE,ID_SF_SIGNATURE,TRUE); + } + else + { + SendDlgMessage(hDlg,DM_SETCHECK,ID_SF_SIGNATURE,BSTATE_UNCHECKED); + SendDlgMessage(hDlg,DM_ENABLE,ID_SF_SIGNATURE,FALSE); + } + + break; + } + case DN_CLOSE: + { + if (param1 == ID_SF_OK) + { + UINT *codepage = (UINT*)SendDlgMessage(hDlg, DM_GETDLGDATA, 0, 0); + FarListPos pos; + SendDlgMessage(hDlg, DM_LISTGETCURPOS, ID_SF_CODEPAGE, (LONG_PTR)&pos); + *codepage = (UINT)SendDlgMessage(hDlg, DM_LISTGETDATA, ID_SF_CODEPAGE, pos.SelectPos); + return TRUE; + } + + break; + } + case DN_EDITCHANGE: + { + if (param1==ID_SF_CODEPAGE) + { + FarListPos pos; + SendDlgMessage(hDlg,DM_LISTGETCURPOS,ID_SF_CODEPAGE,(LONG_PTR)&pos); + UINT Cp=static_cast<UINT>(SendDlgMessage(hDlg,DM_LISTGETDATA,ID_SF_CODEPAGE,pos.SelectPos)); + + if (Cp!=codepage) + { + codepage=Cp; + + if (IsUnicodeOrUtfCodePage(codepage)) + { + SendDlgMessage(hDlg,DM_SETCHECK,ID_SF_SIGNATURE,BSTATE_CHECKED); + SendDlgMessage(hDlg,DM_ENABLE,ID_SF_SIGNATURE,TRUE); + } + else + { + SendDlgMessage(hDlg,DM_SETCHECK,ID_SF_SIGNATURE,BSTATE_UNCHECKED); + SendDlgMessage(hDlg,DM_ENABLE,ID_SF_SIGNATURE,FALSE); + } + + return TRUE; + } + } + + break; + } + } + + return DefDlgProc(hDlg, msg, param1, param2); +} + + + +bool dlgSaveFileAs(FARString &strFileName, int &TextFormat, UINT &codepage,bool &AddSignature) +{ + const wchar_t *HistoryName=L"NewEdit"; + DialogDataEx EditDlgData[]= + { + {DI_DOUBLEBOX,3,1,72,15,{},0,MSG(MEditTitle)}, + {DI_TEXT,5,2,0,2,{},0,MSG(MEditSaveAs)}, + {DI_EDIT,5,3,70,3,{(DWORD_PTR)HistoryName},DIF_FOCUS|DIF_HISTORY|DIF_EDITEXPAND|DIF_EDITPATH,L""}, + {DI_TEXT,3,4,0,4,{},DIF_SEPARATOR,L""}, + {DI_TEXT,5,5,0,5,{},0,MSG(MEditCodePage)}, + {DI_COMBOBOX,25,5,70,5,{},DIF_DROPDOWNLIST|DIF_LISTWRAPMODE|DIF_LISTAUTOHIGHLIGHT,L""}, + {DI_CHECKBOX,5,6,0,6,{AddSignature},DIF_DISABLE,MSG(MEditAddSignature)}, + {DI_TEXT,3,7,0,7,{},DIF_SEPARATOR,L""}, + {DI_TEXT,5,8,0,8,{},0,MSG(MEditSaveAsFormatTitle)}, + {DI_RADIOBUTTON,5,9,0,9,{},DIF_GROUP,MSG(MEditSaveOriginal)}, + {DI_RADIOBUTTON,5,10,0,10,{},0,MSG(MEditSaveDOS)}, + {DI_RADIOBUTTON,5,11,0,11,{},0,MSG(MEditSaveUnix)}, + {DI_RADIOBUTTON,5,12,0,12,{},0,MSG(MEditSaveMac)}, + {DI_TEXT,3,13,0,13,{},DIF_SEPARATOR,L""}, + {DI_BUTTON,0,14,0,14,{},DIF_DEFAULT|DIF_CENTERGROUP,MSG(MOk)}, + {DI_BUTTON,0,14,0,14,{},DIF_CENTERGROUP,MSG(MCancel)} + }; + MakeDialogItemsEx(EditDlgData,EditDlg); + EditDlg[ID_SF_FILENAME].strData = (/*Flags.Check(FFILEEDIT_SAVETOSAVEAS)?strFullFileName:strFileName*/strFileName); + { + size_t pos=0; + if (EditDlg[ID_SF_FILENAME].strData.Pos(pos,MSG(MNewFileName))) + EditDlg[ID_SF_FILENAME].strData.Truncate(pos); + } + EditDlg[ID_SF_DONOTCHANGE+TextFormat].Selected = TRUE; + Dialog Dlg(EditDlg, ARRAYSIZE(EditDlg), (FARWINDOWPROC)hndSaveFileAs, (LONG_PTR)&codepage); + Dlg.SetPosition(-1,-1,76,17); + Dlg.SetHelp(L"FileSaveAs"); + Dlg.SetId(FileSaveAsId); + Dlg.Process(); + + if ((Dlg.GetExitCode() == ID_SF_OK) && !EditDlg[ID_SF_FILENAME].strData.IsEmpty()) + { + strFileName = EditDlg[ID_SF_FILENAME].strData; + ConvertHomePrefixInPath(strFileName); + AddSignature=EditDlg[ID_SF_SIGNATURE].Selected!=0; + + if (EditDlg[ID_SF_DONOTCHANGE].Selected) + TextFormat=0; + else if (EditDlg[ID_SF_DOS].Selected) + TextFormat=1; + else if (EditDlg[ID_SF_UNIX].Selected) + TextFormat=2; + else if (EditDlg[ID_SF_MAC].Selected) + TextFormat=3; + + return true; + } + + return false; +} + + +const FileEditor *FileEditor::CurrentEditor = nullptr; + +FileEditor::FileEditor(const wchar_t *Name, UINT codepage, DWORD InitFlags, int StartLine, int StartChar, const wchar_t *PluginData, int OpenModeExstFile): + BadConversion(false), SaveAsTextFormat(0) +{ + ScreenObject::SetPosition(0,0,ScrX,ScrY); + Flags.Set(InitFlags); + Flags.Set(FFILEEDIT_FULLSCREEN); + Init(Name,codepage, nullptr,InitFlags,StartLine,StartChar, PluginData,FALSE,OpenModeExstFile); +} + + +FileEditor::FileEditor( + const wchar_t *Name, + UINT codepage, + DWORD InitFlags, + int StartLine, + int StartChar, + const wchar_t *Title, + int X1, + int Y1, + int X2, + int Y2, + int DeleteOnClose, + int OpenModeExstFile +) : SaveAsTextFormat(0) +{ + Flags.Set(InitFlags); + + if (X1 < 0) + X1=0; + + if (X2 < 0 || X2 > ScrX) + X2=ScrX; + + if (Y1 < 0) + Y1=0; + + if (Y2 < 0 || Y2 > ScrY) + Y2=ScrY; + + if (X1 >= X2) + { + X1=0; + X2=ScrX; + } + + if (Y1 >= Y2) + { + Y1=0; + Y2=ScrY; + } + + ScreenObject::SetPosition(X1,Y1,X2,Y2); + Flags.Change(FFILEEDIT_FULLSCREEN,(!X1 && !Y1 && X2==ScrX && Y2==ScrY)); + Init(Name,codepage, Title,InitFlags,StartLine,StartChar,L"",DeleteOnClose,OpenModeExstFile); +} + +/* $ 07.05.2001 DJ + в деструкторе грохаем EditNamesList, если он был создан, а в SetNamesList() + создаем EditNamesList и копируем туда значения +*/ +/* + Вызов деструкторов идет так: + FileEditor::~FileEditor() + Editor::~Editor() + ... +*/ +FileEditor::~FileEditor() +{ + //AY: флаг оповещающий закрытие редактора. + m_bClosing = true; + + if (m_editor->EdOpt.SavePos && CtrlObject) + SaveToCache(); + + BitFlags FEditFlags=m_editor->Flags; + int FEditEditorID=m_editor->EditorID; + + if (bEE_READ_Sent && CtrlObject) + { + FileEditor *save = CtrlObject->Plugins.CurEditor; + CtrlObject->Plugins.CurEditor=this; + CtrlObject->Plugins.ProcessEditorEvent(EE_CLOSE,&FEditEditorID); + CtrlObject->Plugins.CurEditor = save; + } + + if (!Flags.Check(FFILEEDIT_OPENFAILED)) + { + /* $ 11.10.2001 IS + Удалим файл вместе с каталогом, если это просится и файла с таким же + именем не открыто в других фреймах. + */ + /* $ 14.06.2001 IS + Если установлен FEDITOR_DELETEONLYFILEONCLOSE и сброшен + FEDITOR_DELETEONCLOSE, то удаляем только файл. + */ + if (Flags.Check(FFILEEDIT_DELETEONCLOSE|FFILEEDIT_DELETEONLYFILEONCLOSE) && + !FrameManager->CountFramesWithName(strFullFileName)) + { + if (Flags.Check(FFILEEDIT_DELETEONCLOSE)) + DeleteFileWithFolder(strFullFileName); + else + { + apiMakeWritable(strFullFileName);//apiSetFileAttributes(strFullFileName,FILE_ATTRIBUTE_NORMAL); + apiDeleteFile(strFullFileName); //BUGBUG + } + } + } + + if (m_editor) + delete m_editor; + + m_editor=nullptr; + CurrentEditor=nullptr; + + if (EditNamesList) + delete EditNamesList; +} + +void FileEditor::Init( + const wchar_t *Name, + UINT codepage, + const wchar_t *Title, + DWORD InitFlags, + int StartLine, + int StartChar, + const wchar_t *PluginData, + int DeleteOnClose, + int OpenModeExstFile +) +{ + SudoClientRegion sdc_rgn; + class SmartLock + { + private: + Editor *editor; + public: + SmartLock() {editor=nullptr;} + ~SmartLock() {if (editor) editor->Unlock();} + + void Set(Editor *e) {editor=e; editor->Lock();} + }; + SmartLock __smartlock; + SysErrorCode=0; + int BlankFileName=!StrCmp(Name,MSG(MNewFileName)); + //AY: флаг оповещающий закрытие редактора. + m_bClosing = false; + bEE_READ_Sent = false; + m_AddSignature = FB_NO; + m_editor = new Editor; + __smartlock.Set(m_editor); + + if (!m_editor) + { + ExitCode=XC_OPEN_ERROR; + return; + } + + m_codepage = codepage; + m_editor->SetOwner(this); + m_editor->SetCodePage(m_codepage); + *AttrStr=0; + CurrentEditor=this; + SetTitle(Title); + EditNamesList = nullptr; + KeyBarVisible = Opt.EdOpt.ShowKeyBar; + TitleBarVisible = Opt.EdOpt.ShowTitleBar; + // $ 17.08.2001 KM - Добавлено для поиска по AltF7. При редактировании найденного файла из архива для клавиши F2 сделать вызов ShiftF2. + Flags.Change(FFILEEDIT_SAVETOSAVEAS, (InitFlags&FFILEEDIT_SAVETOSAVEAS) == FFILEEDIT_SAVETOSAVEAS || BlankFileName != 0); + + if (!*Name) + { + ExitCode=XC_OPEN_ERROR; + return; + } + + SetPluginData(PluginData); + m_editor->SetHostFileEditor(this); + SetCanLoseFocus(Flags.Check(FFILEEDIT_ENABLEF6)); + apiGetCurrentDirectory(strStartDir); + + if (!SetFileName(Name)) + { + ExitCode=XC_OPEN_ERROR; + return; + } + + //int FramePos=FrameManager->FindFrameByFile(MODALTYPE_EDITOR,FullFileName); + //if (FramePos!=-1) + if (Flags.Check(FFILEEDIT_ENABLEF6)) + { + //if (Flags.Check(FFILEEDIT_ENABLEF6)) + int FramePos=FrameManager->FindFrameByFile(MODALTYPE_EDITOR, strFullFileName); + + if (FramePos!=-1) + { + int SwitchTo=FALSE; + int MsgCode=0; + + if (!(*FrameManager)[FramePos]->GetCanLoseFocus(TRUE) || + Opt.Confirm.AllowReedit) + { + if (OpenModeExstFile == FEOPMODE_QUERY) + { + SetMessageHelp(L"EditorReload"); + MsgCode=Message(0,3,MSG(MEditTitle), + strFullFileName, + MSG(MAskReload), + MSG(MCurrent),MSG(MNewOpen),MSG(MReload)); + } + else + { + MsgCode=(OpenModeExstFile==FEOPMODE_USEEXISTING)?0: + (OpenModeExstFile==FEOPMODE_NEWIFOPEN?1: + (OpenModeExstFile==FEOPMODE_RELOAD?2:-100) + ); + } + + switch (MsgCode) + { + case 0: // Current + SwitchTo=TRUE; + FrameManager->DeleteFrame(this); //??? + break; + case 1: // NewOpen + SwitchTo=FALSE; + break; + case 2: // Reload + FrameManager->DeleteFrame(FramePos); + SetExitCode(-2); + break; + case -100: + //FrameManager->DeleteFrame(this); //??? + SetExitCode(XC_EXISTS); + return; + default: + FrameManager->DeleteFrame(this); //??? + SetExitCode(MsgCode == -100?XC_EXISTS:XC_QUIT); + return; + } + } + else + { + SwitchTo=TRUE; + } + + if (SwitchTo) + { + FrameManager->ActivateFrame(FramePos); + //FrameManager->PluginCommit(); + SetExitCode((OpenModeExstFile != FEOPMODE_QUERY)?XC_EXISTS:TRUE); + return ; + } + } + } + + /* $ 29.11.2000 SVS + Если файл имеет атрибут ReadOnly или System или Hidden, + И параметр на запрос выставлен, то сначала спросим. + */ + /* $ 03.12.2000 SVS + System или Hidden - задаются отдельно + */ + /* $ 15.12.2000 SVS + - Shift-F4, новый файл. Выдает сообщение :-( + */ + DWORD FAttr=apiGetFileAttributes(Name); + + /* $ 05.06.2001 IS + + посылаем подальше всех, кто пытается отредактировать каталог + */ + if (FAttr!=INVALID_FILE_ATTRIBUTES && FAttr&FILE_ATTRIBUTE_DIRECTORY) + { + Message(MSG_WARNING,1,MSG(MEditTitle),MSG(MEditCanNotEditDirectory),MSG(MOk)); + ExitCode=XC_OPEN_ERROR; + return; + } + + if ((m_editor->EdOpt.ReadOnlyLock&2) && + FAttr != INVALID_FILE_ATTRIBUTES && + (FAttr & + (FILE_ATTRIBUTE_READONLY| + /* Hidden=0x2 System=0x4 - располагаются во 2-м полубайте, + поэтому применяем маску 0110.0000 и + сдвигаем на свое место => 0000.0110 и получаем + те самые нужные атрибуты */ + ((m_editor->EdOpt.ReadOnlyLock&0x60)>>4) + ) + ) + ) + { + if (Message(MSG_WARNING,2,MSG(MEditTitle),Name,MSG(MEditRSH), + MSG(MEditROOpen),MSG(MYes),MSG(MNo))) + { + ExitCode=XC_OPEN_ERROR; + return; + } + } + + m_editor->SetPosition(X1,Y1+(Opt.EdOpt.ShowTitleBar?1:0),X2,Y2-(Opt.EdOpt.ShowKeyBar?1:0)); + m_editor->SetStartPos(StartLine,StartChar); + SetDeleteOnClose(DeleteOnClose); + int UserBreak; + + /* $ 06.07.2001 IS + При создании файла с нуля так же посылаем плагинам событие EE_READ, дабы + не нарушать однообразие. + */ + if (FAttr == INVALID_FILE_ATTRIBUTES) + Flags.Set(FFILEEDIT_NEW); + + if (BlankFileName && Flags.Check(FFILEEDIT_CANNEWFILE)) + Flags.Set(FFILEEDIT_NEW); + + if (Flags.Check(FFILEEDIT_NEW)) + m_AddSignature = FB_MAYBE; + + if (Flags.Check(FFILEEDIT_LOCKED)) + m_editor->Flags.Set(FEDITOR_LOCKMODE); + + if (!LoadFile(strFullFileName,UserBreak)) + { + if (BlankFileName) + { + Flags.Clear(FFILEEDIT_OPENFAILED); //AY: ну так как редактор мы открываем то видимо надо и сбросить ошибку открытия + UserBreak=0; + } + + if (!Flags.Check(FFILEEDIT_NEW) || UserBreak) + { + if (UserBreak!=1) + { + WINPORT(SetLastError)(SysErrorCode); + Message(MSG_WARNING|MSG_ERRORTYPE,1,MSG(MEditTitle),MSG(MEditCannotOpen),strFileName,MSG(MOk)); + ExitCode=XC_OPEN_ERROR; + } + else + { + ExitCode=XC_LOADING_INTERRUPTED; + } + + // Ахтунг. Ниже комментарии оставлены в назидании потомкам (до тех пор, пока не измениться манагер) + //FrameManager->DeleteFrame(this); // BugZ#546 - Editor валит фар! + //CtrlObject->Cp()->Redraw(); //AY: вроде как не надо, делает проблемы с проресовкой если в редакторе из истории попытаться выбрать несуществующий файл + + // если прервали загрузку, то фремы нужно проапдейтить, чтобы предыдущие месаги не оставались на экране + if (!Opt.Confirm.Esc && UserBreak && ExitCode==XC_LOADING_INTERRUPTED && FrameManager) + FrameManager->RefreshFrame(); + + return; + } + + if (m_codepage==CP_AUTODETECT) + m_codepage=Opt.EdOpt.DefaultCodePage; + + m_editor->SetCodePage(m_codepage); + } + + CtrlObject->Plugins.CurEditor=this;//&FEdit; + CtrlObject->Plugins.ProcessEditorEvent(EE_READ,nullptr); + bEE_READ_Sent = true; + ShowConsoleTitle(); + EditKeyBar.SetOwner(this); + EditKeyBar.SetPosition(X1,Y2,X2,Y2); + InitKeyBar(); + + if (!Opt.EdOpt.ShowKeyBar) + EditKeyBar.Hide0(); + + MacroMode=MACRO_EDITOR; + CtrlObject->Macro.SetMode(MACRO_EDITOR); + + F4KeyOnly=true; + + if (Flags.Check(FFILEEDIT_ENABLEF6)) + FrameManager->InsertFrame(this); + else + FrameManager->ExecuteFrame(this); +} + +void FileEditor::InitKeyBar() +{ + EditKeyBar.SetAllGroup(KBL_MAIN, Opt.OnlyEditorViewerUsed?MSingleEditF1:MEditF1, 12); + EditKeyBar.SetAllGroup(KBL_SHIFT, Opt.OnlyEditorViewerUsed?MSingleEditShiftF1:MEditShiftF1, 12); + EditKeyBar.SetAllGroup(KBL_ALT, Opt.OnlyEditorViewerUsed?MSingleEditAltF1:MEditAltF1, 12); + EditKeyBar.SetAllGroup(KBL_CTRL, Opt.OnlyEditorViewerUsed?MSingleEditCtrlF1:MEditCtrlF1, 12); + EditKeyBar.SetAllGroup(KBL_CTRLSHIFT, Opt.OnlyEditorViewerUsed?MSingleEditCtrlShiftF1:MEditCtrlShiftF1, 12); + EditKeyBar.SetAllGroup(KBL_CTRLALT, Opt.OnlyEditorViewerUsed?MSingleEditCtrlAltF1:MEditCtrlAltF1, 12); + EditKeyBar.SetAllGroup(KBL_ALTSHIFT, Opt.OnlyEditorViewerUsed?MSingleEditAltShiftF1:MEditAltShiftF1, 12); + EditKeyBar.SetAllGroup(KBL_CTRLALTSHIFT, Opt.OnlyEditorViewerUsed?MSingleEditCtrlAltShiftF1:MEditCtrlAltShiftF1, 12); + + if (!GetCanLoseFocus()) + EditKeyBar.Change(KBL_SHIFT,L"",4-1); + + if (Flags.Check(FFILEEDIT_SAVETOSAVEAS)) + EditKeyBar.Change(KBL_MAIN,MSG(MEditShiftF2),2-1); + + if (!Flags.Check(FFILEEDIT_ENABLEF6)) + EditKeyBar.Change(KBL_MAIN,L"",6-1); + + if (!GetCanLoseFocus()) + EditKeyBar.Change(KBL_MAIN,L"",12-1); + + if (!GetCanLoseFocus()) + EditKeyBar.Change(KBL_ALT,L"",11-1); + + if (!Opt.UsePrintManager || CtrlObject->Plugins.FindPlugin(SYSID_PRINTMANAGER)) + EditKeyBar.Change(KBL_ALT,L"",5-1); + + if (m_codepage!=WINPORT(GetOEMCP)()) + EditKeyBar.Change(KBL_MAIN,MSG(Opt.OnlyEditorViewerUsed?MSingleEditF8DOS:MEditF8DOS),7); + else + EditKeyBar.Change(KBL_MAIN,MSG(Opt.OnlyEditorViewerUsed?MSingleEditF8:MEditF8),7); + + EditKeyBar.ReadRegGroup(L"Editor",Opt.strLanguage); + EditKeyBar.SetAllRegGroup(); + EditKeyBar.Refresh(true); + m_editor->SetPosition(X1,Y1+(Opt.EdOpt.ShowTitleBar?1:0),X2,Y2-(Opt.EdOpt.ShowKeyBar?1:0)); + SetKeyBar(&EditKeyBar); +} + +void FileEditor::SetNamesList(NamesList *Names) +{ + if (!EditNamesList) + EditNamesList = new NamesList; + + Names->MoveData(*EditNamesList); +} + +void FileEditor::Show() +{ + if (Flags.Check(FFILEEDIT_FULLSCREEN)) + { + if (Opt.EdOpt.ShowKeyBar) + { + EditKeyBar.SetPosition(0,ScrY,ScrX,ScrY); + EditKeyBar.Redraw(); + } + + ScreenObject::SetPosition(0,0,ScrX,ScrY-(Opt.EdOpt.ShowKeyBar?1:0)); + m_editor->SetPosition(0,(Opt.EdOpt.ShowTitleBar?1:0),ScrX,ScrY-(Opt.EdOpt.ShowKeyBar?1:0)); + } + + ScreenObject::Show(); +} + + +void FileEditor::DisplayObject() +{ + if (!m_editor->Locked()) + { + if (m_editor->Flags.Check(FEDITOR_ISRESIZEDCONSOLE)) + { + m_editor->Flags.Clear(FEDITOR_ISRESIZEDCONSOLE); + CtrlObject->Plugins.CurEditor=this; + CtrlObject->Plugins.ProcessEditorEvent(EE_REDRAW,EEREDRAW_CHANGE);//EEREDRAW_ALL); + } + + m_editor->Show(); + } +} + +int64_t FileEditor::VMProcess(int OpCode,void *vParam,int64_t iParam) +{ + if (OpCode == MCODE_V_EDITORSTATE) + { + DWORD MacroEditState=0; + MacroEditState|=Flags.Flags&FFILEEDIT_NEW?0x00000001:0; + MacroEditState|=Flags.Flags&FFILEEDIT_ENABLEF6?0x00000002:0; + MacroEditState|=Flags.Flags&FFILEEDIT_DELETEONCLOSE?0x00000004:0; + MacroEditState|=m_editor->Flags.Flags&FEDITOR_MODIFIED?0x00000008:0; + MacroEditState|=m_editor->BlockStart?0x00000010:0; + MacroEditState|=m_editor->VBlockStart?0x00000020:0; + MacroEditState|=m_editor->Flags.Flags&FEDITOR_WASCHANGED?0x00000040:0; + MacroEditState|=m_editor->Flags.Flags&FEDITOR_OVERTYPE?0x00000080:0; + MacroEditState|=m_editor->Flags.Flags&FEDITOR_CURPOSCHANGEDBYPLUGIN?0x00000100:0; + MacroEditState|=m_editor->Flags.Flags&FEDITOR_LOCKMODE?0x00000200:0; + MacroEditState|=m_editor->EdOpt.PersistentBlocks?0x00000400:0; + MacroEditState|=Opt.OnlyEditorViewerUsed?0x08000000|0x00000800:0; + MacroEditState|=!GetCanLoseFocus()?0x00000800:0; + return (int64_t)MacroEditState; + } + + if (OpCode == MCODE_V_EDITORCURPOS) + return (int64_t)(m_editor->CurLine->GetTabCurPos()+1); + + if (OpCode == MCODE_V_EDITORCURLINE) + return (int64_t)(m_editor->NumLine+1); + + if (OpCode == MCODE_V_ITEMCOUNT || OpCode == MCODE_V_EDITORLINES) + return (int64_t)(m_editor->NumLastLine); + + return m_editor->VMProcess(OpCode,vParam,iParam); +} + + +int FileEditor::ProcessKey(int Key) +{ + return ReProcessKey(Key,FALSE); +} + +int FileEditor::ReProcessKey(int Key,int CalledFromControl) +{ + SudoClientRegion sdc_rgn; + if (Key!=KEY_F4 && Key!=KEY_IDLE) + F4KeyOnly=false; + + DWORD FNAttr; + + if (Flags.Check(FFILEEDIT_REDRAWTITLE) && (((unsigned int)Key & 0x00ffffff) < KEY_END_FKEY || IS_INTERNAL_KEY_REAL((unsigned int)Key & 0x00ffffff))) + ShowConsoleTitle(); + + // BugZ#488 - Shift=enter + if (ShiftPressed && (Key == KEY_ENTER || Key == KEY_NUMENTER) && CtrlObject->Macro.IsExecuting() == MACROMODE_NOMACRO) + { + Key=Key == KEY_ENTER?KEY_SHIFTENTER:KEY_SHIFTNUMENTER; + } + + // Все сотальные необработанные клавиши пустим далее + /* $ 28.04.2001 DJ + не передаем KEY_MACRO* плагину - поскольку ReadRec в этом случае + никак не соответствует обрабатываемой клавише, возникают разномастные + глюки + */ + if (((unsigned int)Key >= KEY_MACRO_BASE && (unsigned int)Key <= KEY_MACRO_ENDBASE) || ((unsigned int)Key>=KEY_OP_BASE && (unsigned int)Key <=KEY_OP_ENDBASE)) // исключаем MACRO + { + ; // + } + + switch (Key) + { + /* $ 27.09.2000 SVS + Печать файла/блока с использованием плагина PrintMan + */ + case KEY_ALTF5: + { + if (Opt.UsePrintManager && CtrlObject->Plugins.FindPlugin(SYSID_PRINTMANAGER)) + { + CtrlObject->Plugins.CallPlugin(SYSID_PRINTMANAGER,OPEN_EDITOR,nullptr); // printman + return TRUE; + } + + break; // отдадим Alt-F5 на растерзание плагинам, если не установлен PrintMan + } + case KEY_F6: + { + if (Flags.Check(FFILEEDIT_ENABLEF6)) + { + int FirstSave=1, NeedQuestion=1; + UINT cp=m_codepage; + + // проверка на "а может это говно удалили уже?" + // возможно здесь она и не нужна! + // хотя, раз уж были изменени, то + if (m_editor->IsFileChanged() && // в текущем сеансе были изменения? + apiGetFileAttributes(strFullFileName) == INVALID_FILE_ATTRIBUTES) // а файл еще существует? + { + switch (Message(MSG_WARNING,2,MSG(MEditTitle), + MSG(MEditSavedChangedNonFile), + MSG(MEditSavedChangedNonFile2), + MSG(MHYes),MSG(MHNo))) + { + case 0: + + if (ProcessKey(KEY_F2)) + { + FirstSave=0; + break; + } + + default: + return FALSE; + } + } + + if (!FirstSave || m_editor->IsFileChanged() || apiGetFileAttributes(strFullFileName)!=INVALID_FILE_ATTRIBUTES) + { + long FilePos=m_editor->GetCurPos(); + + /* $ 01.02.2001 IS + ! Открываем вьюер с указанием длинного имени файла, а не короткого + */ + if (ProcessQuitKey(FirstSave,NeedQuestion)) + { + /* $ 11.10.200 IS + не будем удалять файл, если было включено удаление, но при этом + пользователь переключился во вьюер + */ + SetDeleteOnClose(0); + //объект будет в конце удалён в FrameManager + new FileViewer(strFullFileName, GetCanLoseFocus(), Flags.Check(FFILEEDIT_DISABLEHISTORY), FALSE, + FilePos, nullptr, EditNamesList, Flags.Check(FFILEEDIT_SAVETOSAVEAS), cp); + } + + ShowTime(2); + } + + return TRUE; + } + + break; // отдадим F6 плагинам, если есть запрет на переключение + } + /* $ 10.05.2001 DJ + Alt-F11 - показать view/edit history + */ + case KEY_ALTF11: + { + if (GetCanLoseFocus()) + { + CtrlObject->CmdLine->ShowViewEditHistory(); + return TRUE; + } + + break; // отдадим Alt-F11 на растерзание плагинам, если редактор модальный + } + } + +#if 1 + BOOL ProcessedNext=TRUE; + + _SVS(if (Key=='n' || Key=='m')) + _SVS(SysLog(L"%d Key='%c'",__LINE__,Key)); + + if (!CalledFromControl && (CtrlObject->Macro.IsRecording() == MACROMODE_RECORDING_COMMON || CtrlObject->Macro.IsExecuting() == MACROMODE_EXECUTING_COMMON || CtrlObject->Macro.GetCurRecord(nullptr,nullptr) == MACROMODE_NOMACRO)) + { + + _SVS(if (CtrlObject->Macro.IsRecording() == MACROMODE_RECORDING_COMMON || CtrlObject->Macro.IsExecuting() == MACROMODE_EXECUTING_COMMON)) + _SVS(SysLog(L"%d !!!! CtrlObject->Macro.GetCurRecord(nullptr,nullptr) != MACROMODE_NOMACRO !!!!",__LINE__)); + + ProcessedNext=!ProcessEditorInput(FrameManager->GetLastInputRecord()); + } + + if (ProcessedNext) +#else + if (!CalledFromControl && //CtrlObject->Macro.IsExecuting() || CtrlObject->Macro.IsRecording() || // пусть доходят! + !ProcessEditorInput(FrameManager->GetLastInputRecord())) +#endif + { + + switch (Key) + { + case KEY_F1: + { + Help Hlp(L"Editor"); + return TRUE; + } + /* $ 25.04.2001 IS + ctrl+f - вставить в строку полное имя редактируемого файла + */ + case KEY_CTRLF: + { + if (!m_editor->Flags.Check(FEDITOR_LOCKMODE)) + { + m_editor->Pasting++; + m_editor->TextChanged(1); + BOOL IsBlock=m_editor->VBlockStart || m_editor->BlockStart; + + if (!m_editor->EdOpt.PersistentBlocks && IsBlock) + { + m_editor->Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK); + m_editor->DeleteBlock(); + } + + //AddUndoData(CurLine->EditLine.GetStringAddr(),NumLine, + // CurLine->EditLine.GetCurPos(),UNDO_EDIT); + m_editor->Paste(strFullFileName); //??? + //if (!EdOpt.PersistentBlocks) + m_editor->UnmarkBlock(); + m_editor->Pasting--; + m_editor->Show(); //??? + } + + return (TRUE); + } + /* $ 24.08.2000 SVS + + Добавляем реакцию показа бакграунда на клавишу CtrlAltShift + */ + case KEY_CTRLO: + { + if (!Opt.OnlyEditorViewerUsed) + { + m_editor->Hide(); // $ 27.09.2000 skv - To prevent redraw in macro with Ctrl-O + + if (FrameManager->ShowBackground()) + { + SetCursorType(FALSE,0); + WaitKey(); + } + + Show(); + } + + return TRUE; + } + case KEY_F2: + case KEY_SHIFTF2: + { + BOOL Done=FALSE; + FARString strOldCurDir; + apiGetCurrentDirectory(strOldCurDir); + + while (!Done) // бьемся до упора + { + size_t pos; + + // проверим путь к файлу, может его уже снесли... + if (FindLastSlash(pos,strFullFileName)) + { + wchar_t *lpwszPtr = strFullFileName.GetBuffer(); + wchar_t wChr = lpwszPtr[pos+1]; + lpwszPtr[pos+1]=0; + + // В корне? + if (!IsLocalRootPath(lpwszPtr)) + { + // а дальше? каталог существует? + if ((FNAttr=apiGetFileAttributes(lpwszPtr)) == INVALID_FILE_ATTRIBUTES || + !(FNAttr&FILE_ATTRIBUTE_DIRECTORY) + //|| LocalStricmp(OldCurDir,FullFileName) // <- это видимо лишнее. + ) + Flags.Set(FFILEEDIT_SAVETOSAVEAS); + } + + lpwszPtr[pos+1]=wChr; + //strFullFileName.ReleaseBuffer (); так как ничего не поменялось то это лишнее. + } + + if (Key == KEY_F2 && + (FNAttr=apiGetFileAttributes(strFullFileName)) != INVALID_FILE_ATTRIBUTES && + !(FNAttr&FILE_ATTRIBUTE_DIRECTORY) + ) + { + Flags.Clear(FFILEEDIT_SAVETOSAVEAS); + } + + UINT codepage = m_codepage; + bool SaveAs = Key==KEY_SHIFTF2 || Flags.Check(FFILEEDIT_SAVETOSAVEAS); + int NameChanged=FALSE; + FARString strFullSaveAsName = strFullFileName; + + if (SaveAs) + { + FARString strSaveAsName = Flags.Check(FFILEEDIT_SAVETOSAVEAS)?strFullFileName:strFileName; + + bool AddSignature = DecideAboutSignature(); + if (!dlgSaveFileAs(strSaveAsName, SaveAsTextFormat, codepage, AddSignature)) + return FALSE; + + if (AddSignature) + m_AddSignature = FB_YES; + + apiExpandEnvironmentStrings(strSaveAsName, strSaveAsName); + Unquote(strSaveAsName); + NameChanged=StrCmpI(strSaveAsName, (Flags.Check(FFILEEDIT_SAVETOSAVEAS)?strFullFileName:strFileName)); + + if (!NameChanged) + FarChDir(strStartDir); // ПОЧЕМУ? А нужно ли??? + + if (NameChanged) + { + if (!AskOverwrite(strSaveAsName)) + { + FarChDir(strOldCurDir); + return TRUE; + } + } + + ConvertNameToFull(strSaveAsName, strFullSaveAsName); //BUGBUG, не проверяем имя на правильность + //это не про нас, про нас ниже, все куда страшнее + /*FARString strFileNameTemp = strSaveAsName; + + if(!SetFileName(strFileNameTemp)) + { + WINPORT(SetLastError)(ERROR_INVALID_NAME); + Message(MSG_WARNING|MSG_ERRORTYPE,1,MSG(MEditTitle),strFileNameTemp,MSG(MOk)); + if(!NameChanged) + FarChDir(strOldCurDir); + continue; + //return FALSE; + } */ + + if (!NameChanged) + FarChDir(strOldCurDir); + } + + ShowConsoleTitle(); + FarChDir(strStartDir); //??? + int SaveResult=SaveFile(strFullSaveAsName, 0, SaveAs, SaveAsTextFormat, codepage, DecideAboutSignature()); + + if (SaveResult==SAVEFILE_ERROR) + { + WINPORT(SetLastError)(SysErrorCode); + + if (Message(MSG_WARNING|MSG_ERRORTYPE,2,MSG(MEditTitle),MSG(MEditCannotSave), + strFileName,MSG(MRetry),MSG(MCancel))) + { + Done=TRUE; + break; + } + } + else if (SaveResult==SAVEFILE_SUCCESS) + { + //здесь идет полная жопа, проверка на ошибки вообще пока отсутствует + { + bool bInPlace = /*(!IsUnicodeOrUtfCodePage(m_codepage) && !IsUnicodeOrUtfCodePage(codepage)) || */(m_codepage == codepage); + + if (!bInPlace) + { + m_editor->FreeAllocatedData(); + m_editor->InsertString(nullptr, 0); + } + + SetFileName(strFullSaveAsName); + SetCodePage(codepage); // + + if (!bInPlace) + { + Message(MSG_WARNING, 1, L"WARNING!", L"Editor will be reopened with new file!", MSG(MOk)); + int UserBreak; + LoadFile(strFullSaveAsName, UserBreak); + // TODO: возможно подобный ниже код здесь нужен (copy/paste из FileEditor::Init()). оформить его нужно по иному + //if(!Opt.Confirm.Esc && UserBreak && ExitCode==XC_LOADING_INTERRUPTED && FrameManager) + // FrameManager->RefreshFrame(); + } + + // перерисовывать надо как минимум когда изменилась кодировка или имя файла + ShowConsoleTitle(); + Show();//!!! BUGBUG + } + Done=TRUE; + } + else + { + Done=TRUE; + break; + } + } + + return TRUE; + } + // $ 30.05.2003 SVS - Shift-F4 в редакторе/вьювере позволяет открывать другой редактор/вьювер (пока только редактор) + case KEY_SHIFTF4: + { + if (!Opt.OnlyEditorViewerUsed && GetCanLoseFocus()) + CtrlObject->Cp()->ActivePanel->ProcessKey(Key); + + return TRUE; + } + // $ 21.07.2000 SKV + выход с позиционированием на редактируемом файле по CTRLF10 + case KEY_CTRLF10: + { + if (isTemporary()) + { + return TRUE; + } + + FARString strFullFileNameTemp = strFullFileName; + + if (apiGetFileAttributes(strFullFileName) == INVALID_FILE_ATTRIBUTES) // а сам файл то еще на месте? + { + if (!CheckShortcutFolder(&strFullFileNameTemp,FALSE)) + return FALSE; + + strFullFileNameTemp += L"/."; // для вваливания внутрь :-) + } + + Panel *ActivePanel = CtrlObject->Cp()->ActivePanel; + + if (Flags.Check(FFILEEDIT_NEW) || (ActivePanel && ActivePanel->FindFile(strFileName) == -1)) // Mantis#279 + { + UpdateFileList(); + Flags.Clear(FFILEEDIT_NEW); + } + + { + SaveScreen Sc; + CtrlObject->Cp()->GoToFile(strFullFileNameTemp); + Flags.Set(FFILEEDIT_REDRAWTITLE); + } + + return (TRUE); + } + case KEY_ALTF10: + { + FrameManager->ExitMainLoop(1); + return (TRUE); + } + case KEY_CTRLB: + { + Opt.EdOpt.ShowKeyBar=!Opt.EdOpt.ShowKeyBar; + + if (!Opt.EdOpt.ShowKeyBar) + EditKeyBar.Hide0(); // 0 mean - Don't purge saved screen + + EditKeyBar.Refresh(Opt.EdOpt.ShowKeyBar); + Show(); + KeyBarVisible = Opt.EdOpt.ShowKeyBar; + return (TRUE); + } + case KEY_CTRLSHIFTB: + { + Opt.EdOpt.ShowTitleBar=!Opt.EdOpt.ShowTitleBar; + TitleBarVisible = Opt.EdOpt.ShowTitleBar; + Show(); + return (TRUE); + } + case KEY_SHIFTF10: + + if (!ProcessKey(KEY_F2)) // учтем факт того, что могли отказаться от сохранения + return FALSE; + + case KEY_F4: + if (F4KeyOnly) + return TRUE; + case KEY_ESC: + case KEY_F10: + { + int FirstSave=1, NeedQuestion=1; + + if (Key != KEY_SHIFTF10) // KEY_SHIFTF10 не учитываем! + { + bool FilePlaced=apiGetFileAttributes(strFullFileName) == INVALID_FILE_ATTRIBUTES && !Flags.Check(FFILEEDIT_NEW); + + if (m_editor->IsFileChanged() || // в текущем сеансе были изменения? + FilePlaced) // а сам файл то еще на месте? + { + int Res; + + if (m_editor->IsFileChanged() && FilePlaced) + Res=Message(MSG_WARNING,3,MSG(MEditTitle), + MSG(MEditSavedChangedNonFile), + MSG(MEditSavedChangedNonFile2), + MSG(MHYes),MSG(MHNo),MSG(MHCancel)); + else if (!m_editor->IsFileChanged() && FilePlaced) + Res=Message(MSG_WARNING,3,MSG(MEditTitle), + MSG(MEditSavedChangedNonFile1), + MSG(MEditSavedChangedNonFile2), + MSG(MHYes),MSG(MHNo),MSG(MHCancel)); + else + Res=100; + + switch (Res) + { + case 0: + + if (!ProcessKey(KEY_F2)) // попытка сначала сохранить + NeedQuestion=0; + + FirstSave=0; + break; + case 1: + NeedQuestion=0; + FirstSave=0; + break; + case 100: + FirstSave=NeedQuestion=1; + break; + case 2: + default: + return FALSE; + } + } + else if (!m_editor->Flags.Check(FEDITOR_MODIFIED)) //???? + NeedQuestion=0; + } + + if (!ProcessQuitKey(FirstSave,NeedQuestion)) + return FALSE; + + return TRUE; + } + case KEY_F8: + case KEY_SHIFTF8: + { + UINT codepage; + if (Key==KEY_F8) { + codepage = (m_codepage==WINPORT(GetACP)()?WINPORT(GetOEMCP)():WINPORT(GetACP)()); + } else { + codepage = SelectCodePage(m_codepage, false, true, false, true); + if (codepage == CP_AUTODETECT) { + if (!GetFileFormat2(strFileName,codepage,nullptr,true,true)) { + codepage = (UINT)-1; + } + } + } + if (codepage != (UINT)-1 && codepage != m_codepage) { + const bool need_reload = 0 +// || IsFixedSingleCharCodePage(m_codepage) != IsFixedSingleCharCodePage(codepage) + || IsUTF8(m_codepage) != IsUTF8(codepage) + || IsUTF7(m_codepage) != IsUTF7(codepage) + || IsUTF16(m_codepage) != IsUTF16(codepage) + || IsUTF32(m_codepage) != IsUTF32(codepage); + if (!IsFileModified() || !need_reload) { + SetCodePage(codepage); + Flags.Set(FFILEEDIT_CODEPAGECHANGEDBYUSER); + if (need_reload) { + int UserBreak = 0; + SaveToCache(); + LoadFile(strLoadedFileName, UserBreak); + } + ChangeEditKeyBar(); + } else + Message(0, 1, MSG(MEditTitle), L"Save file before changing this codepage", MSG(MHOk), nullptr); + } + return TRUE; + } + case KEY_ALTSHIFTF9: + { + // Работа с локальной копией EditorOptions + EditorOptions EdOpt; + GetEditorOptions(EdOpt); + EditorConfig(EdOpt,true); // $ 27.11.2001 DJ - Local в EditorConfig + EditKeyBar.Refresh(true); //???? Нужно ли???? + SetEditorOptions(EdOpt); + + EditKeyBar.Refresh(Opt.EdOpt.ShowKeyBar); + + m_editor->Show(); + return TRUE; + } + default: + { + if (Flags.Check(FFILEEDIT_FULLSCREEN) && CtrlObject->Macro.IsExecuting() == MACROMODE_NOMACRO) + EditKeyBar.Refresh(Opt.EdOpt.ShowKeyBar); + + if (!EditKeyBar.ProcessKey(Key)) + return(m_editor->ProcessKey(Key)); + } + } + } + return TRUE; +} + + +int FileEditor::ProcessQuitKey(int FirstSave,BOOL NeedQuestion) +{ + SudoClientRegion sdc_rgn; + FARString strOldCurDir; + apiGetCurrentDirectory(strOldCurDir); + + for (;;) + { + FarChDir(strStartDir); // ПОЧЕМУ? А нужно ли??? + int SaveCode=SAVEFILE_SUCCESS; + + if (NeedQuestion) + { + SaveCode=SaveFile(strFullFileName,FirstSave,0,FALSE); + } + + if (SaveCode==SAVEFILE_CANCEL) + break; + + if (SaveCode==SAVEFILE_SUCCESS) + { + /* $ 09.02.2002 VVM + + Обновить панели, если писали в текущий каталог */ + if (NeedQuestion) + { + if (apiGetFileAttributes(strFullFileName)!=INVALID_FILE_ATTRIBUTES) + { + UpdateFileList(); + } + } + + FrameManager->DeleteFrame(); + SetExitCode(XC_QUIT); + break; + } + + if (!StrCmp(strFileName,MSG(MNewFileName))) + { + if (!ProcessKey(KEY_SHIFTF2)) + { + FarChDir(strOldCurDir); + return FALSE; + } + else + break; + } + + WINPORT(SetLastError)(SysErrorCode); + + if (Message(MSG_WARNING|MSG_ERRORTYPE,2,MSG(MEditTitle),MSG(MEditCannotSave), + strFileName,MSG(MRetry),MSG(MCancel))) + break; + + FirstSave=0; + } + + FarChDir(strOldCurDir); + return (unsigned int)GetExitCode() == XC_QUIT; +} + + +// сюды плавно переносить код из Editor::ReadFile() +int FileEditor::LoadFile(const wchar_t *Name,int &UserBreak) +{ + SudoClientRegion sdc_rgn; + ChangePriority ChPriority(ChangePriority::NORMAL); + TPreRedrawFuncGuard preRedrawFuncGuard(Editor::PR_EditorShowMsg); + wakeful W; + int LastLineCR = 0; + EditorCacheParams cp; + UserBreak = 0; + File EditFile; + DWORD FileAttr = apiGetFileAttributes(Name); + if ((FileAttr!=INVALID_FILE_ATTRIBUTES && (FileAttr&FILE_ATTRIBUTE_DEVICE)!=0) || //avoid stuck + !EditFile.Open(Name, GENERIC_READ, FILE_SHARE_READ|(Opt.EdOpt.EditOpenedForWrite?FILE_SHARE_WRITE:0), nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN)) + { + SysErrorCode=WINPORT(GetLastError)(); + + if ((SysErrorCode != ERROR_FILE_NOT_FOUND) && (SysErrorCode != ERROR_PATH_NOT_FOUND)) + { + UserBreak = -1; + Flags.Set(FFILEEDIT_OPENFAILED); + } + + return FALSE; + } + + /*if (GetFileType(hEdit) != FILE_TYPE_DISK) + { + fclose(EditFile); + WINPORT(SetLastError)(ERROR_INVALID_NAME); + UserBreak=-1; + Flags.Set(FFILEEDIT_OPENFAILED); + return FALSE; + }*/ + + if (Opt.EdOpt.FileSizeLimitLo || Opt.EdOpt.FileSizeLimitHi) + { + UINT64 FileSize=0; + if (EditFile.GetSize(FileSize)) + { + UINT64 MaxSize = Opt.EdOpt.FileSizeLimitHi * 0x100000000ull + Opt.EdOpt.FileSizeLimitLo; + + if (FileSize > MaxSize) + { + FARString strTempStr1, strTempStr2, strTempStr3, strTempStr4; + // Ширина = 8 - это будет... в Kb и выше... + FileSizeToStr(strTempStr1, FileSize, 8); + FileSizeToStr(strTempStr2, MaxSize, 8); + strTempStr3.Format(MSG(MEditFileLong), RemoveExternalSpaces(strTempStr1).CPtr()); + strTempStr4.Format(MSG(MEditFileLong2), RemoveExternalSpaces(strTempStr2).CPtr()); + + if (Message(MSG_WARNING,2,MSG(MEditTitle), Name, strTempStr3, strTempStr4, MSG(MEditROOpen), MSG(MYes),MSG(MNo))) + { + EditFile.Close(); + UserBreak=1; + Flags.Set(FFILEEDIT_OPENFAILED); + errno = EFBIG; + return FALSE; + } + } + } + else + { + ErrnoSaver ErSr; + if (Message(MSG_WARNING|MSG_ERRORTYPE,2,MSG(MEditTitle),Name,MSG(MEditFileGetSizeError),MSG(MEditROOpen),MSG(MYes),MSG(MNo))) + { + EditFile.Close(); + UserBreak=1; + Flags.Set(FFILEEDIT_OPENFAILED); + return FALSE; + } + } + } + + m_editor->FreeAllocatedData(false); + bool bCached = LoadFromCache(&cp); + + DWORD FileAttributes=apiGetFileAttributes(Name); + if((m_editor->EdOpt.ReadOnlyLock&1) && FileAttributes != INVALID_FILE_ATTRIBUTES && (FileAttributes & (FILE_ATTRIBUTE_READONLY|((m_editor->EdOpt.ReadOnlyLock&0x60)>>4)))) + { + m_editor->Flags.Swap(FEDITOR_LOCKMODE); + } + + // Проверяем поддерживается или нет загруженная кодовая страница + if (bCached && cp.CodePage && !IsCodePageSupported(cp.CodePage)) + cp.CodePage = 0; + + GetFileString GetStr(EditFile); + *m_editor->GlobalEOL=0; //BUGBUG??? + wchar_t *Str; + int StrLength,GetCode; + UINT dwCP=0; + bool Detect=false; + + if (m_codepage == CP_AUTODETECT || IsUnicodeOrUtfCodePage(m_codepage)) + { + bool bSignatureDetected = false; + Detect=GetFileFormat(EditFile,dwCP,&bSignatureDetected,Opt.EdOpt.AutoDetectCodePage!=0); + + // Проверяем поддерживается или нет задетектировання кодовая страница + if (Detect) { + Detect = IsCodePageSupported(dwCP); + if (Detect) { + m_AddSignature = (bSignatureDetected ? FB_YES : FB_NO); + } + } + } + + if (m_codepage == CP_AUTODETECT) + { + if (Detect) + { + m_codepage=dwCP; + } + + if (bCached) + { + if (cp.CodePage) + { + m_codepage = cp.CodePage; + Flags.Set(FFILEEDIT_CODEPAGECHANGEDBYUSER); + } + } + + if (m_codepage==CP_AUTODETECT) + m_codepage=Opt.EdOpt.DefaultCodePage; + } + else + { + Flags.Set(FFILEEDIT_CODEPAGECHANGEDBYUSER); + } + + m_editor->SetCodePage(m_codepage); //BUGBUG + + if (!IsUnicodeOrUtfCodePage(m_codepage)) + { + EditFile.SetPointer(0, nullptr, FILE_BEGIN); + } + + UINT64 FileSize=0; + EditFile.GetSize(FileSize); + DWORD StartTime=WINPORT(GetTickCount)(); + + while ((GetCode=GetStr.GetString(&Str, m_codepage, StrLength))) + { + if (GetCode == -1) + { + EditFile.Close(); + return FALSE; + } + + LastLineCR=0; + DWORD CurTime=WINPORT(GetTickCount)(); + + if (CurTime-StartTime>RedrawTimeout) + { + StartTime=CurTime; + + if (CheckForEscSilent()) + { + if (ConfirmAbortOp()) + { + UserBreak = 1; + EditFile.Close(); + return FALSE; + } + } + + SetCursorType(FALSE,0); + INT64 CurPos=0; + EditFile.GetPointer(CurPos); + int Percent=static_cast<int>(CurPos*100/FileSize); + // В случае если во время загрузки файл увеличивается размере, то количество + // процентов может быть больше 100. Обрабатываем эту ситуацию. + if (Percent>100) + { + EditFile.GetSize(FileSize); + Percent=static_cast<int>(CurPos*100/FileSize); + if (Percent>100) + { + Percent=100; + } + } + Editor::EditorShowMsg(MSG(MEditTitle),MSG(MEditReading),Name,Percent); + } + + const wchar_t *CurEOL; + + int Offset = StrLength > 3 ? StrLength - 3 : 0; + + if (!LastLineCR && + ( + (CurEOL = wmemchr(Str+Offset,L'\r',StrLength-Offset)) || + (CurEOL = wmemchr(Str+Offset,L'\n',StrLength-Offset)) + ) + ) + { + far_wcsncpy(m_editor->GlobalEOL,CurEOL,ARRAYSIZE(m_editor->GlobalEOL)); + m_editor->GlobalEOL[ARRAYSIZE(m_editor->GlobalEOL)-1]=0; + LastLineCR=1; + } + + if (!m_editor->InsertString(Str, StrLength)) + { + EditFile.Close(); + return FALSE; + } + } + + BadConversion = !GetStr.IsConversionValid(); + if (BadConversion) + { + Message(MSG_WARNING,1,MSG(MWarning),MSG(MEditorLoadCPWarn1),MSG(MEditorLoadCPWarn2),MSG(MEditorSaveNotRecommended),MSG(MOk)); + } + + if (LastLineCR||!m_editor->NumLastLine) + m_editor->InsertString(L"", 0); + + EditFile.Close(); + //if ( bCached ) + m_editor->SetCacheParams(&cp); + SysErrorCode=WINPORT(GetLastError)(); + apiGetFindDataForExactPathName(Name, FileInfo); + EditorGetFileAttributes(Name); + strLoadedFileName = Name; + return TRUE; +} + +//TextFormat и Codepage используются ТОЛЬКО, если bSaveAs = true! + +int FileEditor::SaveFile(const wchar_t *Name,int Ask, bool bSaveAs, int TextFormat, UINT codepage, bool AddSignature) +{ + SudoClientRegion sdc_rgn; + if (!bSaveAs) + { + TextFormat=0; + codepage=m_editor->GetCodePage(); + } + + wakeful W; + + if (m_editor->Flags.Check(FEDITOR_LOCKMODE) && !m_editor->Flags.Check(FEDITOR_MODIFIED) && !bSaveAs) + return SAVEFILE_SUCCESS; + + if (Ask) + { + if (!m_editor->Flags.Check(FEDITOR_MODIFIED)) + return SAVEFILE_SUCCESS; + + if (Ask) + { + switch (Message(MSG_WARNING,3,MSG(MEditTitle),MSG(MEditAskSave), + MSG(MHYes),MSG(MHNo),MSG(MHCancel))) + { + case -1: + case -2: + case 2: // Continue Edit + return SAVEFILE_CANCEL; + case 0: // Save + break; + case 1: // Not Save + m_editor->TextChanged(0); // 10.08.2000 skv: TextChanged() support; + return SAVEFILE_SUCCESS; + } + } + } + + int NewFile=TRUE; + + FileUnmakeWritable = apiMakeWritable(Name); + if (FileUnmakeWritable.get()) + { + //BUGBUG + int AskOverwrite=Message(MSG_WARNING,2,MSG(MEditTitle),Name,MSG(MEditRO), + MSG(MEditOvr),MSG(MYes),MSG(MNo)); + + if (AskOverwrite) { + FileUnmakeWritable->Unmake(); + FileUnmakeWritable.reset(); + return SAVEFILE_CANCEL; + } + } + + DWORD FileAttributes=EditorGetFileAttributes(Name); + if (FileAttributes!=INVALID_FILE_ATTRIBUTES) + { + // Проверка времени модификации... + if (!Flags.Check(FFILEEDIT_SAVEWQUESTIONS)) + { + FAR_FIND_DATA_EX FInfo; + + if (apiGetFindDataForExactPathName(Name, FInfo) && !FileInfo.strFileName.IsEmpty()) + { + int64_t RetCompare=FileTimeDifference(&FileInfo.ftLastWriteTime,&FInfo.ftLastWriteTime); + + if (RetCompare || !(FInfo.nFileSize == FileInfo.nFileSize)) + { + SetMessageHelp(L"WarnEditorSavedEx"); + + switch (Message(MSG_WARNING,3,MSG(MEditTitle),MSG(MEditAskSaveExt), + MSG(MHYes),MSG(MEditBtnSaveAs),MSG(MHCancel))) + { + case -1: + case -2: + case 2: // Continue Edit + return SAVEFILE_CANCEL; + case 1: // Save as + + if (ProcessKey(KEY_SHIFTF2)) + return SAVEFILE_SUCCESS; + else + return SAVEFILE_CANCEL; + + case 0: // Save + break; + } + } + } + } + + Flags.Clear(FFILEEDIT_SAVEWQUESTIONS); + NewFile=FALSE; + } + else + { + // проверим путь к файлу, может его уже снесли... + FARString strCreatedPath = Name; + const wchar_t *Ptr=LastSlash(strCreatedPath); + + if (Ptr) + { + CutToSlash(strCreatedPath); + DWORD FAttr=0; + + if (apiGetFileAttributes(strCreatedPath) == INVALID_FILE_ATTRIBUTES) + { + // и попробуем создать. + // Раз уж + CreatePath(strCreatedPath); + FAttr=apiGetFileAttributes(strCreatedPath); + } + + if (FAttr == INVALID_FILE_ATTRIBUTES) + return SAVEFILE_ERROR; + } + } + + if (BadConversion) + { + if(Message(MSG_WARNING,2,MSG(MWarning),MSG(MEditDataLostWarn),MSG(MEditorSaveNotRecommended),MSG(MOk),MSG(MCancel))) + { + return SAVEFILE_CANCEL; + } + else + { + BadConversion = false; + } + } + + int RetCode=SAVEFILE_SUCCESS; + + if (TextFormat) + m_editor->Flags.Set(FEDITOR_WASCHANGED); + + switch (TextFormat) + { + case 1: + wcscpy(m_editor->GlobalEOL,DOS_EOL_fmt); + break; + case 2: + wcscpy(m_editor->GlobalEOL,UNIX_EOL_fmt); + break; + case 3: + wcscpy(m_editor->GlobalEOL,MAC_EOL_fmt); + break; + case 4: + wcscpy(m_editor->GlobalEOL,WIN_EOL_fmt); + break; + } + + if (apiGetFileAttributes(Name) == INVALID_FILE_ATTRIBUTES) + Flags.Set(FFILEEDIT_NEW); + + { + //SaveScreen SaveScr; + /* $ 11.10.2001 IS + Если было произведено сохранение с любым результатом, то не удалять файл + */ + Flags.Clear(FFILEEDIT_DELETEONCLOSE|FFILEEDIT_DELETEONLYFILEONCLOSE); + CtrlObject->Plugins.CurEditor=this; +//_D(SysLog(L"%08d EE_SAVE",__LINE__)); + + if (!IsUnicodeOrUtfCodePage(codepage)) + { + int LineNumber=0; + bool BadSaveConfirmed=false; + for (Edit *CurPtr=m_editor->TopList; CurPtr; CurPtr=CurPtr->m_next,LineNumber++) + { + const wchar_t *SaveStr, *EndSeq; + int Length; + CurPtr->GetBinaryString(&SaveStr,&EndSeq,Length); + BOOL UsedDefaultCharStr=FALSE,UsedDefaultCharEOL=FALSE; + WINPORT(WideCharToMultiByte)(codepage,WC_NO_BEST_FIT_CHARS,SaveStr,Length,nullptr,0,nullptr,&UsedDefaultCharStr); + + if (!*EndSeq && CurPtr->m_next) + EndSeq=*m_editor->GlobalEOL?m_editor->GlobalEOL:DOS_EOL_fmt; + + if (TextFormat&&*EndSeq) + EndSeq=m_editor->GlobalEOL; + + WINPORT(WideCharToMultiByte)(codepage,WC_NO_BEST_FIT_CHARS,EndSeq,StrLength(EndSeq),nullptr,0,nullptr,&UsedDefaultCharEOL); + + if (!BadSaveConfirmed && (UsedDefaultCharStr||UsedDefaultCharEOL)) + { + //SetMessageHelp(L"EditorDataLostWarning") + int Result=Message(MSG_WARNING,3,MSG(MWarning),MSG(MEditorSaveCPWarn1),MSG(MEditorSaveCPWarn2),MSG(MEditorSaveNotRecommended),MSG(MOk),MSG(MEditorSaveCPWarnShow),MSG(MCancel)); + if (!Result) + { + BadSaveConfirmed=true; + break; + } + else + { + if(Result==1) + { + m_editor->GoToLine(LineNumber); + if(UsedDefaultCharStr) + { + for(int Pos=0;Pos<Length;Pos++) + { + BOOL UseDefChar=0; + WINPORT(WideCharToMultiByte)(codepage,WC_NO_BEST_FIT_CHARS,SaveStr+Pos,1,nullptr,0,nullptr,&UseDefChar); + if(UseDefChar) + { + CurPtr->SetCurPos(Pos); + break; + } + } + } + else + { + CurPtr->SetCurPos(CurPtr->GetLength()); + } + Show(); + } + return SAVEFILE_CANCEL; + } + } + } + } + + CtrlObject->Plugins.ProcessEditorEvent(EE_SAVE,nullptr); + File EditFile; + DWORD dwWritten=0; + // Don't use CreationDisposition=CREATE_ALWAYS here - it's kills alternate streams + if(!EditFile.Open(Name, GENERIC_WRITE, FILE_SHARE_READ, nullptr, Flags.Check(FFILEEDIT_NEW)?CREATE_NEW:TRUNCATE_EXISTING, FILE_ATTRIBUTE_ARCHIVE|FILE_FLAG_SEQUENTIAL_SCAN)) + { + //_SVS(SysLogLastError();SysLog(L"Name='%ls',FileAttributes=%d",Name,FileAttributes)); + RetCode=SAVEFILE_ERROR; + SysErrorCode=WINPORT(GetLastError)(); + goto end; + } + + m_editor->UndoSavePos=m_editor->UndoPos; + m_editor->Flags.Clear(FEDITOR_UNDOSAVEPOSLOST); +// ConvertNameToFull(Name,FileName, sizeof(FileName)); + /* + if (ConvertNameToFull(Name,m_editor->FileName, sizeof(m_editor->FileName)) >= sizeof(m_editor->FileName)) + { + m_editor->Flags.Set(FEDITOR_OPENFAILED); + RetCode=SAVEFILE_ERROR; + goto end; + } + */ + SetCursorType(FALSE,0); + TPreRedrawFuncGuard preRedrawFuncGuard(Editor::PR_EditorShowMsg); + + DWORD dwSignature = 0; + DWORD SignLength = 0; + switch (codepage) + { + case CP_UTF32LE: + dwSignature = SIGN_UTF32LE; + SignLength = 4; + if (!bSaveAs) AddSignature = (m_AddSignature != FB_NO); + break; + case CP_UTF32BE: + dwSignature = SIGN_UTF32BE; + SignLength = 4; + if (!bSaveAs) AddSignature = (m_AddSignature != FB_NO); + break; + case CP_UTF16LE: + dwSignature = SIGN_UTF16LE; + SignLength = 2; + if (!bSaveAs) AddSignature = (m_AddSignature != FB_NO); + break; + case CP_UTF16BE: + dwSignature = SIGN_UTF16BE; + SignLength = 2; + if (!bSaveAs) AddSignature = (m_AddSignature != FB_NO); + break; + case CP_UTF8: + dwSignature = SIGN_UTF8; + SignLength = 3; + if (!bSaveAs) AddSignature = (m_AddSignature == FB_YES); + break; + } + if (AddSignature) + { + if (!EditFile.Write(&dwSignature,SignLength,&dwWritten,nullptr)||dwWritten!=SignLength) + { + EditFile.Close(); + apiDeleteFile(Name); + RetCode=SAVEFILE_ERROR; + goto end; + } + } + + DWORD StartTime=WINPORT(GetTickCount)(); + size_t LineNumber=0; + CachedWrite Cache(EditFile); + + for (Edit *CurPtr=m_editor->TopList; CurPtr; CurPtr=CurPtr->m_next,LineNumber++) + { + DWORD CurTime=WINPORT(GetTickCount)(); + + if (CurTime-StartTime>RedrawTimeout) + { + StartTime=CurTime; + Editor::EditorShowMsg(MSG(MEditTitle),MSG(MEditSaving),Name,(int)(LineNumber*100/m_editor->NumLastLine)); + } + + const wchar_t *SaveStr, *EndSeq; + + int Length; + + CurPtr->GetBinaryString(&SaveStr,&EndSeq,Length); + + if (!*EndSeq && CurPtr->m_next) + EndSeq=*m_editor->GlobalEOL ? m_editor->GlobalEOL:DOS_EOL_fmt; + + if (TextFormat && *EndSeq) + { + EndSeq=m_editor->GlobalEOL; + CurPtr->SetEOL(EndSeq); + } + + int EndLength=StrLength(EndSeq); + bool bError = false; + + if (codepage == CP_WIDE_LE) + { + if ( + (Length && !Cache.Write(SaveStr,Length*sizeof(wchar_t))) || + (EndLength && !Cache.Write(EndSeq,EndLength*sizeof(wchar_t))) + ) + { + SysErrorCode=WINPORT(GetLastError)(); + bError = true; + } + } + else + { + if (Length) + { + DWORD length = (codepage == CP_WIDE_BE) ? Length * sizeof(wchar_t) : + WINPORT(WideCharToMultiByte)(codepage, 0, SaveStr, Length, nullptr, 0, nullptr, nullptr); + char *SaveStrCopy=(char *)malloc(length); + + if (SaveStrCopy) + { + if (codepage == CP_WIDE_BE) { + WideReverse(SaveStr, (wchar_t *)SaveStrCopy, Length); + } else + WINPORT(WideCharToMultiByte)(codepage, 0, SaveStr, Length, SaveStrCopy, length, nullptr, nullptr); + + if (!Cache.Write(SaveStrCopy,length)) + { + bError = true; + SysErrorCode=WINPORT(GetLastError)(); + } + + free(SaveStrCopy); + } + else + bError = true; + } + + if (!bError) + { + if (EndLength) + { + DWORD endlength = (codepage == CP_WIDE_BE ? EndLength*sizeof(wchar_t) + : WINPORT(WideCharToMultiByte)(codepage, 0, EndSeq, EndLength, nullptr, 0, nullptr, nullptr)); + char *EndSeqCopy=(char *)malloc(endlength); + + if (EndSeqCopy) + { + if (codepage == CP_WIDE_BE) + WideReverse(EndSeq, (wchar_t *)EndSeqCopy, EndLength); + else + WINPORT(WideCharToMultiByte)(codepage, 0, EndSeq, EndLength, EndSeqCopy, endlength, nullptr, nullptr); + + if (!Cache.Write(EndSeqCopy,endlength)) + { + bError = true; + SysErrorCode=WINPORT(GetLastError)(); + } + + free(EndSeqCopy); + } + else + bError = true; + } + } + } + + if (bError) + { + EditFile.Close(); + apiDeleteFile(Name); + RetCode=SAVEFILE_ERROR; + goto end; + } + } + + if(Cache.Flush()) + { + EditFile.SetEnd(); + EditFile.Close(); + } + else + { + SysErrorCode=WINPORT(GetLastError)(); + EditFile.Close(); + apiDeleteFile(Name); + RetCode=SAVEFILE_ERROR; + } + } + + if (SaveObserver && RetCode != SAVEFILE_ERROR) { + SaveObserver->OnEditedFileSaved(Name); + } + +end: + + if (FileUnmakeWritable) + { + FileUnmakeWritable->Unmake(); + FileUnmakeWritable.reset(); +// apiSetFileAttributes(Name,FileAttributes|FILE_ATTRIBUTE_ARCHIVE); + } + + apiGetFindDataForExactPathName(Name, FileInfo); + EditorGetFileAttributes(Name); + + if (m_editor->Flags.Check(FEDITOR_MODIFIED) || NewFile) + m_editor->Flags.Set(FEDITOR_WASCHANGED); + + /* Этот кусок раскомметировать в том случае, если народ решит, что + для если файл был залочен и мы его переписали под други именем... + ...то "лочка" должна быть снята. + */ + +// if(SaveAs) +// Flags.Clear(FEDITOR_LOCKMODE); + /* 28.12.2001 VVM + ! Проверить на успешную запись */ + if (RetCode==SAVEFILE_SUCCESS) + m_editor->TextChanged(0); + + if (GetDynamicallyBorn()) // принудительно сбросим Title // Flags.Check(FFILEEDIT_SAVETOSAVEAS) ???????? + strTitle.Clear(); + + Show(); + // ************************************ + Flags.Clear(FFILEEDIT_NEW); + return RetCode; +} + +int FileEditor::ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent) +{ + F4KeyOnly = false; + if (!EditKeyBar.ProcessMouse(MouseEvent)) + if (!ProcessEditorInput(FrameManager->GetLastInputRecord())) + if (!m_editor->ProcessMouse(MouseEvent)) + return FALSE; + + return TRUE; +} + + +int FileEditor::GetTypeAndName(FARString &strType, FARString &strName) +{ + strType = MSG(MScreensEdit); + strName = strFullFileName; + return(MODALTYPE_EDITOR); +} + + +void FileEditor::ShowConsoleTitle() +{ + FARString strTitle; + strTitle.Format(MSG(MInEditor), PointToName(strFileName)); + ConsoleTitle::SetFarTitle(strTitle); + Flags.Clear(FFILEEDIT_REDRAWTITLE); +} + +void FileEditor::SetScreenPosition() +{ + if (Flags.Check(FFILEEDIT_FULLSCREEN)) + { + SetPosition(0,0,ScrX,ScrY); + } +} + +/* $ 10.05.2001 DJ + добавление в view/edit history +*/ + +void FileEditor::OnDestroy() +{ + _OT(SysLog(L"[%p] FileEditor::OnDestroy()",this)); + + if (!Flags.Check(FFILEEDIT_DISABLEHISTORY) && StrCmpI(strFileName,MSG(MNewFileName))) + CtrlObject->ViewHistory->AddToHistory(strFullFileName,(m_editor->Flags.Check(FEDITOR_LOCKMODE)?4:1)); + + if (CtrlObject->Plugins.CurEditor==this)//&this->FEdit) + { + CtrlObject->Plugins.CurEditor=nullptr; + } +} + +int FileEditor::GetCanLoseFocus(int DynamicMode) +{ + if (DynamicMode) + { + if (m_editor->IsFileModified()) + { + return FALSE; + } + } + else + { + return CanLoseFocus; + } + + return TRUE; +} + +void FileEditor::SetLockEditor(BOOL LockMode) +{ + if (LockMode) + m_editor->Flags.Set(FEDITOR_LOCKMODE); + else + m_editor->Flags.Clear(FEDITOR_LOCKMODE); +} + +int FileEditor::FastHide() +{ + return Opt.AllCtrlAltShiftRule & CASR_EDITOR; +} + +BOOL FileEditor::isTemporary() +{ + return (!GetDynamicallyBorn()); +} + +void FileEditor::ResizeConsole() +{ + m_editor->PrepareResizedConsole(); +} + +int FileEditor::ProcessEditorInput(INPUT_RECORD *Rec) +{ + int RetCode; + CtrlObject->Plugins.CurEditor=this; + RetCode=CtrlObject->Plugins.ProcessEditorInput(Rec); + return RetCode; +} + +void FileEditor::SetPluginTitle(const wchar_t *PluginTitle) +{ + if (!PluginTitle) + strPluginTitle.Clear(); + else + strPluginTitle = PluginTitle; +} + +BOOL FileEditor::SetFileName(const wchar_t *NewFileName) +{ + strFileName = NewFileName; + + if (StrCmp(strFileName,MSG(MNewFileName))) + { + ConvertNameToFull(strFileName, strFullFileName); + FARString strFilePath=strFullFileName; + + if (CutToSlash(strFilePath,1)) + { + FARString strCurPath; + + if (apiGetCurrentDirectory(strCurPath)) + { + DeleteEndSlash(strCurPath); + + if (!StrCmpI(strFilePath,strCurPath)) + strFileName=PointToName(strFullFileName); + } + } + + } + else + { + strFullFileName = strStartDir; + AddEndSlash(strFullFileName); + strFullFileName += strFileName; + } + + return TRUE; +} + +void FileEditor::SetTitle(const wchar_t *Title) +{ + strTitle = Title; +} + +void FileEditor::ChangeEditKeyBar() +{ + if (m_codepage!=WINPORT(GetOEMCP)()) + EditKeyBar.Change(MSG(Opt.OnlyEditorViewerUsed?MSingleEditF8DOS:MEditF8DOS),7); + else + EditKeyBar.Change(MSG(Opt.OnlyEditorViewerUsed?MSingleEditF8:MEditF8),7); + + EditKeyBar.Redraw(); +} + +FARString &FileEditor::GetTitle(FARString &strLocalTitle,int SubLen,int TruncSize) +{ + if (!strPluginTitle.IsEmpty()) + strLocalTitle = strPluginTitle; + else + { + if (!strTitle.IsEmpty()) + strLocalTitle = strTitle; + else + strLocalTitle = strFullFileName; + } + + return strLocalTitle; +} + +void FileEditor::ShowStatus() +{ + if (m_editor->Locked() || !Opt.EdOpt.ShowTitleBar) + return; + + SetColor(COL_EDITORSTATUS); + GotoXY(X1,Y1); //?? + FARString strLineStr; + FARString strLocalTitle; + GetTitle(strLocalTitle); + int NameLength = Opt.ViewerEditorClock && Flags.Check(FFILEEDIT_FULLSCREEN) ? 17:23; + + if (X2 > 80) + NameLength += (X2-80); + + if (!strPluginTitle.IsEmpty() || !strTitle.IsEmpty()) + TruncPathStr(strLocalTitle, (ObjWidth<NameLength?ObjWidth:NameLength)); + else + TruncPathStr(strLocalTitle, NameLength); + + //предварительный расчет + strLineStr.Format(L"%d/%d", m_editor->NumLastLine, m_editor->NumLastLine); + int SizeLineStr = (int)strLineStr.GetLength(); + + if (SizeLineStr > 12) + NameLength -= (SizeLineStr-12); + else + SizeLineStr = 12; + + strLineStr.Format(L"%d/%d", m_editor->NumLine+1, m_editor->NumLastLine); + FARString strAttr(AttrStr); + FormatString FString; + FString<<fmt::LeftAlign()<<fmt::Width(NameLength)<<strLocalTitle<<L' '<< + (m_editor->Flags.Check(FEDITOR_MODIFIED) ? L'*':L' ')<< + (m_editor->Flags.Check(FEDITOR_LOCKMODE) ? L'-':L' ')<< + (m_editor->Flags.Check(FEDITOR_PROCESSCTRLQ) ? L'"':L' ')<< + fmt::Width(5)<<EOLName(m_editor->GlobalEOL)<<L' '<< + fmt::Width(5)<<m_codepage<<L' '<<fmt::Width(7)<<MSG(MEditStatusLine)<<L' '<< + fmt::Width(SizeLineStr)<<fmt::Precision(SizeLineStr)<<strLineStr<<L' '<< + fmt::Width(5)<<MSG(MEditStatusCol)<<L' '<< + fmt::LeftAlign()<<fmt::Width(4)<<m_editor->CurLine->GetTabCurPos()+1<<L' '<< + fmt::Width(3)<<strAttr; + int StatusWidth=ObjWidth - (Opt.ViewerEditorClock && Flags.Check(FFILEEDIT_FULLSCREEN)?5:0); + + if (StatusWidth<0) + StatusWidth=0; + + FS<<fmt::LeftAlign()<<fmt::Width(StatusWidth)<<fmt::Precision(StatusWidth)<<FString.strValue(); + { + const wchar_t *Str; + int Length; + m_editor->CurLine->GetBinaryString(&Str,nullptr,Length); + int CurPos=m_editor->CurLine->GetCurPos(); + + if (CurPos<Length) + { + GotoXY(X2-(Opt.ViewerEditorClock && Flags.Check(FFILEEDIT_FULLSCREEN) ? 16:10),Y1); + SetColor(COL_EDITORSTATUS); + /* $ 27.02.2001 SVS + Показываем в зависимости от базы */ + static const wchar_t *FmtWCharCode[]={L"%05o",L"%5d",L"%04Xh"}; + mprintf(FmtWCharCode[m_editor->EdOpt.CharCodeBase%ARRAYSIZE(FmtWCharCode)],Str[CurPos]); + + if (!IsUnicodeOrUtfCodePage(m_codepage)) + { + char C=0; + BOOL UsedDefaultChar=FALSE; + WINPORT(WideCharToMultiByte)(m_codepage,WC_NO_BEST_FIT_CHARS,&Str[CurPos],1,&C,1,0,&UsedDefaultChar); + + if (C && !UsedDefaultChar && static_cast<wchar_t>(C)!=Str[CurPos]) + { + static const wchar_t *FmtCharCode[]={L"%o",L"%d",L"%Xh"}; + Text(L" ("); + mprintf(FmtCharCode[m_editor->EdOpt.CharCodeBase%ARRAYSIZE(FmtCharCode)],C); + Text(L")"); + } + } + } + } + + if (Opt.ViewerEditorClock && Flags.Check(FFILEEDIT_FULLSCREEN)) + ShowTime(FALSE); +} + +/* $ 13.02.2001 + Узнаем атрибуты файла и заодно сформируем готовую строку атрибутов для + статуса. +*/ +DWORD FileEditor::EditorGetFileAttributes(const wchar_t *Name) +{ + SudoClientRegion sdc_rgn; + DWORD FileAttributes=apiGetFileAttributes(Name); + int ind=0; + + if (FileAttributes!=INVALID_FILE_ATTRIBUTES) + { + if (FileAttributes&FILE_ATTRIBUTE_READONLY) AttrStr[ind++]=L'R'; + + if (FileAttributes&FILE_ATTRIBUTE_SYSTEM) AttrStr[ind++]=L'S'; + + if (FileAttributes&FILE_ATTRIBUTE_HIDDEN) AttrStr[ind++]=L'H'; + } + AttrStr[ind]=0; + return FileAttributes; +} + +/* Return TRUE - панель обовили +*/ +BOOL FileEditor::UpdateFileList() +{ + Panel *ActivePanel = CtrlObject->Cp()->ActivePanel; + const wchar_t *FileName = PointToName(strFullFileName); + FARString strFilePath, strPanelPath; + strFilePath = strFullFileName; + strFilePath.Truncate(FileName - strFullFileName.CPtr()); + ActivePanel->GetCurDir(strPanelPath); + AddEndSlash(strPanelPath); + AddEndSlash(strFilePath); + + if (!StrCmp(strPanelPath, strFilePath)) + { + ActivePanel->Update(UPDATE_KEEP_SELECTION|UPDATE_DRAW_MESSAGE); + return TRUE; + } + + return FALSE; +} + +void FileEditor::SetPluginData(const wchar_t *PluginData) +{ + FileEditor::strPluginData = PluginData; +} + +/* $ 14.06.2002 IS + DeleteOnClose стал int: + 0 - не удалять ничего + 1 - удалять файл и каталог + 2 - удалять только файл +*/ +void FileEditor::SetDeleteOnClose(int NewMode) +{ + Flags.Clear(FFILEEDIT_DELETEONCLOSE|FFILEEDIT_DELETEONLYFILEONCLOSE); + + if (NewMode==1) + Flags.Set(FFILEEDIT_DELETEONCLOSE); + else if (NewMode==2) + Flags.Set(FFILEEDIT_DELETEONLYFILEONCLOSE); +} + +void FileEditor::GetEditorOptions(EditorOptions& EdOpt) +{ + EdOpt = m_editor->EdOpt; +} + +void FileEditor::SetEditorOptions(EditorOptions& EdOpt) +{ + m_editor->SetTabSize(EdOpt.TabSize); + m_editor->SetConvertTabs(EdOpt.ExpandTabs); + m_editor->SetPersistentBlocks(EdOpt.PersistentBlocks); + m_editor->SetDelRemovesBlocks(EdOpt.DelRemovesBlocks); + m_editor->SetAutoIndent(EdOpt.AutoIndent); + m_editor->SetAutoDetectCodePage(EdOpt.AutoDetectCodePage); + m_editor->SetCursorBeyondEOL(EdOpt.CursorBeyondEOL); + m_editor->SetCharCodeBase(EdOpt.CharCodeBase); + m_editor->SetSavePosMode(EdOpt.SavePos, EdOpt.SaveShortPos); + m_editor->SetReadOnlyLock(EdOpt.ReadOnlyLock); + m_editor->SetShowScrollBar(EdOpt.ShowScrollBar); + m_editor->SetShowWhiteSpace(EdOpt.ShowWhiteSpace); + m_editor->SetSearchPickUpWord(EdOpt.SearchPickUpWord); + //m_editor->SetBSLikeDel(EdOpt.BSLikeDel); +} + +void FileEditor::OnChangeFocus(int focus) +{ + Frame::OnChangeFocus(focus); + CtrlObject->Plugins.CurEditor=this; + int FEditEditorID=m_editor->EditorID; + CtrlObject->Plugins.ProcessEditorEvent(focus?EE_GOTFOCUS:EE_KILLFOCUS,&FEditEditorID); +} + + +int FileEditor::EditorControl(int Command, void *Param) +{ +#if defined(SYSLOG_KEYMACRO) + _KEYMACRO(CleverSysLog SL(L"FileEditor::EditorControl()")); + + if (Command == ECTL_READINPUT || Command == ECTL_PROCESSINPUT) + { + _KEYMACRO(SysLog(L"(Command=%ls, Param=[%d/0x%08X]) Macro.IsExecuting()=%d",_ECTL_ToName(Command),(int)((DWORD_PTR)Param),(int)((DWORD_PTR)Param),CtrlObject->Macro.IsExecuting())); + } + +#else + _ECTLLOG(CleverSysLog SL(L"FileEditor::EditorControl()")); + _ECTLLOG(SysLog(L"(Command=%ls, Param=[%d/0x%08X])",_ECTL_ToName(Command),(int)Param,Param)); +#endif + + if (m_bClosing && (Command != ECTL_GETINFO) && (Command != ECTL_GETBOOKMARKS) && (Command!=ECTL_GETFILENAME)) + return FALSE; + + switch (Command) + { + case ECTL_GETFILENAME: + { + if (Param) + { + wcscpy(reinterpret_cast<LPWSTR>(Param),strFullFileName); + } + + return static_cast<int>(strFullFileName.GetLength()+1); + } + case ECTL_GETBOOKMARKS: + { + if (!Flags.Check(FFILEEDIT_OPENFAILED) && Param) + { + EditorBookMarks *ebm = reinterpret_cast<EditorBookMarks*>(Param); + for(size_t i = 0; i < POSCACHE_BOOKMARK_COUNT; i++) + { + if (ebm->Line) + { + ebm->Line[i] = static_cast<long>(m_editor->SavePos.Line[i]); + } + if (ebm->Cursor) + { + ebm->Cursor[i] = static_cast<long>(m_editor->SavePos.Cursor[i]); + } + if (ebm->ScreenLine) + { + ebm->ScreenLine[i] = static_cast<long>(m_editor->SavePos.ScreenLine[i]); + } + if (ebm->LeftPos) + { + ebm->LeftPos[i] = static_cast<long>(m_editor->SavePos.LeftPos[i]); + } + } + return TRUE; + } + + return FALSE; + } + case ECTL_ADDSTACKBOOKMARK: + { + return m_editor->AddStackBookmark(); + } + case ECTL_PREVSTACKBOOKMARK: + { + return m_editor->PrevStackBookmark(); + } + case ECTL_NEXTSTACKBOOKMARK: + { + return m_editor->NextStackBookmark(); + } + case ECTL_CLEARSTACKBOOKMARKS: + { + return m_editor->ClearStackBookmarks(); + } + case ECTL_DELETESTACKBOOKMARK: + { + return m_editor->DeleteStackBookmark(m_editor->PointerToStackBookmark((int)(INT_PTR)Param)); + } + case ECTL_GETSTACKBOOKMARKS: + { + return m_editor->GetStackBookmarks((EditorBookMarks *)Param); + } + case ECTL_SETTITLE: + { + strPluginTitle = (const wchar_t*)Param; + ShowStatus(); + ScrBuf.Flush(); //??? + return TRUE; + } + case ECTL_REDRAW: + { + FileEditor::DisplayObject(); + ScrBuf.Flush(); + return TRUE; + } + /* + Функция установки Keybar Labels + Param = nullptr - восстановить, пред. значение + Param = -1 - обновить полосу (перерисовать) + Param = KeyBarTitles + */ + case ECTL_SETKEYBAR: + { + KeyBarTitles *Kbt = (KeyBarTitles*)Param; + + if (!Kbt) //восстановить изначальное + InitKeyBar(); + else + { + if ((LONG_PTR)Param != (LONG_PTR)-1) // не только перерисовать? + { + for (int I = 0; I < 12; ++I) + { + if (Kbt->Titles[I]) + EditKeyBar.Change(KBL_MAIN,Kbt->Titles[I],I); + + if (Kbt->CtrlTitles[I]) + EditKeyBar.Change(KBL_CTRL,Kbt->CtrlTitles[I],I); + + if (Kbt->AltTitles[I]) + EditKeyBar.Change(KBL_ALT,Kbt->AltTitles[I],I); + + if (Kbt->ShiftTitles[I]) + EditKeyBar.Change(KBL_SHIFT,Kbt->ShiftTitles[I],I); + + if (Kbt->CtrlShiftTitles[I]) + EditKeyBar.Change(KBL_CTRLSHIFT,Kbt->CtrlShiftTitles[I],I); + + if (Kbt->AltShiftTitles[I]) + EditKeyBar.Change(KBL_ALTSHIFT,Kbt->AltShiftTitles[I],I); + + if (Kbt->CtrlAltTitles[I]) + EditKeyBar.Change(KBL_CTRLALT,Kbt->CtrlAltTitles[I],I); + } + } + + EditKeyBar.Refresh(Opt.EdOpt.ShowKeyBar); + } + + return TRUE; + } + case ECTL_SAVEFILE: + { + FARString strName = strFullFileName; + int EOL=0; + UINT codepage=m_codepage; + + if (Param) + { + EditorSaveFile *esf=(EditorSaveFile *)Param; + + if (*esf->FileName) strName=esf->FileName; + + if (esf->FileEOL) + { + if (!StrCmp(esf->FileEOL,DOS_EOL_fmt)) + EOL=1; + else if (!StrCmp(esf->FileEOL,UNIX_EOL_fmt)) + EOL=2; + else if (!StrCmp(esf->FileEOL,MAC_EOL_fmt)) + EOL=3; + else if (!StrCmp(esf->FileEOL,WIN_EOL_fmt)) + EOL=4; + } + + codepage=esf->CodePage; + } + + { + FARString strOldFullFileName = strFullFileName; + + if (SetFileName(strName)) + { + if (StrCmpI(strFullFileName,strOldFullFileName)) + { + if (!AskOverwrite(strName)) + { + SetFileName(strOldFullFileName); + return FALSE; + } + } + + Flags.Set(FFILEEDIT_SAVEWQUESTIONS); + //всегда записываем в режиме save as - иначе не сменить кодировку и концы линий. + return SaveFile(strName, FALSE, true, EOL, codepage, DecideAboutSignature()); + } + } + + return FALSE; + } + case ECTL_QUIT: + { + FrameManager->DeleteFrame(this); + SetExitCode(SAVEFILE_ERROR); // что-то меня терзают смутные сомнения ...??? + return TRUE; + } + case ECTL_READINPUT: + { + if (CtrlObject->Macro.IsRecording() == MACROMODE_RECORDING || CtrlObject->Macro.IsExecuting() == MACROMODE_EXECUTING) + { +// return FALSE; + } + + if (Param) + { + INPUT_RECORD *rec=(INPUT_RECORD *)Param; + DWORD Key; + + for (;;) + { + Key=GetInputRecord(rec); + + if ((!rec->EventType || rec->EventType == KEY_EVENT || rec->EventType == FARMACRO_KEY_EVENT) && + ((Key >= KEY_MACRO_BASE && Key <= KEY_MACRO_ENDBASE) || (Key>=KEY_OP_BASE && Key <=KEY_OP_ENDBASE))) // исключаем MACRO + ReProcessKey(Key); + else + break; + } + + //if(Key==KEY_CONSOLE_BUFFER_RESIZE) //???? + // Show(); //???? +#if defined(SYSLOG_KEYMACRO) + + if (rec->EventType == KEY_EVENT) + { + SysLog(L"ECTL_READINPUT={%ls,{%d,%d,Vk=0x%04X,0x%08X}}", + (rec->EventType == FARMACRO_KEY_EVENT?"FARMACRO_KEY_EVENT":"KEY_EVENT"), + rec->Event.KeyEvent.bKeyDown, + rec->Event.KeyEvent.wRepeatCount, + rec->Event.KeyEvent.wVirtualKeyCode, + rec->Event.KeyEvent.dwControlKeyState); + } + +#endif + return TRUE; + } + + return FALSE; + } + case ECTL_PROCESSINPUT: + { + if (Param) + { + INPUT_RECORD *rec=(INPUT_RECORD *)Param; + + if (ProcessEditorInput(rec)) + return TRUE; + + if (rec->EventType==MOUSE_EVENT) + ProcessMouse(&rec->Event.MouseEvent); + else + { +#if defined(SYSLOG_KEYMACRO) + + if (!rec->EventType || rec->EventType == KEY_EVENT || rec->EventType == FARMACRO_KEY_EVENT) + { + SysLog(L"ECTL_PROCESSINPUT={%ls,{%d,%d,Vk=0x%04X,0x%08X}}", + (rec->EventType == FARMACRO_KEY_EVENT?"FARMACRO_KEY_EVENT":"KEY_EVENT"), + rec->Event.KeyEvent.bKeyDown, + rec->Event.KeyEvent.wRepeatCount, + rec->Event.KeyEvent.wVirtualKeyCode, + rec->Event.KeyEvent.dwControlKeyState); + } + +#endif + int Key=CalcKeyCode(rec,FALSE); + ReProcessKey(Key); + } + + return TRUE; + } + + return FALSE; + } + case ECTL_PROCESSKEY: + { + ReProcessKey((int)(INT_PTR)Param); + return TRUE; + } + case ECTL_SETPARAM: + { + if (Param) + { + EditorSetParameter *espar=(EditorSetParameter *)Param; + if (ESPT_SETBOM==espar->Type) + { + if (IsUnicodeOrUtfCodePage(m_codepage)) + { + m_AddSignature = espar->Param.iParam ? FB_YES : FB_NO; + return TRUE; + } + return FALSE; + } + } + break; + } + } + + int result=m_editor->EditorControl(Command,Param); + if (result&&Param&&ECTL_GETINFO==Command) + { + EditorInfo *Info=(EditorInfo *)Param; + if (DecideAboutSignature()) + Info->Options|= EOPT_BOM; + } + return result; +} + +bool FileEditor::DecideAboutSignature() +{ + return (m_AddSignature==FB_YES || (m_AddSignature==FB_MAYBE && IsUnicodeOrUtfCodePage(m_codepage) && m_codepage!=CP_UTF8)); +} + +bool FileEditor::LoadFromCache(EditorCacheParams *pp) +{ + memset(pp, 0, sizeof(EditorCacheParams)); + memset(&pp->SavePos,0xff,sizeof(InternalEditorBookMark)); + + FARString strCacheName; + + if (*GetPluginData()) + { + strCacheName=GetPluginData(); + strCacheName+=PointToName(strFullFileName); + } + else + { + strCacheName+=strFullFileName; + } + + PosCache PosCache{}; + + if (Opt.EdOpt.SaveShortPos) + { + PosCache.Position[0] = pp->SavePos.Line; + PosCache.Position[1] = pp->SavePos.Cursor; + PosCache.Position[2] = pp->SavePos.ScreenLine; + PosCache.Position[3] = pp->SavePos.LeftPos; + } + + if (CtrlObject->EditorPosCache->GetPosition( + strCacheName, + PosCache + )) + { + pp->Line=static_cast<int>(PosCache.Param[0]); + pp->ScreenLine=static_cast<int>(PosCache.Param[1]); + pp->LinePos=static_cast<int>(PosCache.Param[2]); + pp->LeftPos=static_cast<int>(PosCache.Param[3]); + pp->CodePage=static_cast<UINT>(PosCache.Param[4]); + + if (pp->Line < 0) pp->Line=0; + + if (pp->ScreenLine < 0) pp->ScreenLine=0; + + if (pp->LinePos < 0) pp->LinePos=0; + + if (pp->LeftPos < 0) pp->LeftPos=0; + + if ((int)pp->CodePage < 0) pp->CodePage=0; + + return true; + } + + return false; +} + +void FileEditor::SaveToCache() +{ + EditorCacheParams cp; + m_editor->GetCacheParams(&cp); + FARString strCacheName=strPluginData.IsEmpty()?strFullFileName:strPluginData+PointToName(strFullFileName); + + if (!Flags.Check(FFILEEDIT_OPENFAILED)) //???? + { + PosCache poscache{}; + poscache.Param[0] = cp.Line; + poscache.Param[1] = cp.ScreenLine; + poscache.Param[2] = cp.LinePos; + poscache.Param[3] = cp.LeftPos; + poscache.Param[4] = Flags.Check(FFILEEDIT_CODEPAGECHANGEDBYUSER)?m_codepage:0; + + if (Opt.EdOpt.SaveShortPos) + { + //if no position saved these are nulls + poscache.Position[0] = cp.SavePos.Line; + poscache.Position[1] = cp.SavePos.Cursor; + poscache.Position[2] = cp.SavePos.ScreenLine; + poscache.Position[3] = cp.SavePos.LeftPos; + } + + CtrlObject->EditorPosCache->AddPosition(strCacheName, poscache); + } +} + +void FileEditor::SetCodePage(UINT codepage) +{ + if (codepage != m_codepage) + { + m_codepage = codepage; + + if (m_editor) + { + if (!m_editor->SetCodePage(m_codepage)) + { + Message(MSG_WARNING,1,MSG(MWarning),MSG(MEditorSwitchCPWarn1),MSG(MEditorSwitchCPWarn2),MSG(MEditorSaveNotRecommended),MSG(MOk)); + BadConversion = true; + } + + ChangeEditKeyBar(); //??? + } + } +} + +bool FileEditor::AskOverwrite(const FARString& FileName) +{ + bool result=true; + DWORD FNAttr=apiGetFileAttributes(FileName); + + if (FNAttr!=INVALID_FILE_ATTRIBUTES) + { + if (Message(MSG_WARNING,2,MSG(MEditTitle),FileName,MSG(MEditExists),MSG(MEditOvr),MSG(MYes),MSG(MNo))) + { + result=false; + } + else + { + Flags.Set(FFILEEDIT_SAVEWQUESTIONS); + } + } + + return result; +} + +void ModalEditConsoleHistory(bool scroll_to_end) +{ + const std::string &histfile = CtrlObject->CmdLine->GetConsoleLog(false); + if (histfile.empty()) + return; + + FileEditor *ShellEditor=new(std::nothrow) FileEditor(StrMB2Wide(histfile).c_str(), + CP_UTF8, FFILEEDIT_DISABLEHISTORY | FFILEEDIT_NEW | FFILEEDIT_SAVETOSAVEAS, + scroll_to_end ? std::numeric_limits<int>::max() : 0 ); + unlink(histfile.c_str()); + if (ShellEditor) { + DWORD editorExitCode = ShellEditor->GetExitCode(); + if (editorExitCode != XC_LOADING_INTERRUPTED && editorExitCode != XC_OPEN_ERROR) { + FrameManager->ExecuteModal(); + } else + delete ShellEditor; + } +} |