Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/elfmz/far2l.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelfmz <fenix1905@tut.by>2021-12-31 00:27:16 +0300
committerelfmz <fenix1905@tut.by>2021-12-31 02:27:02 +0300
commita14dc1a81c797928d4f1b7d6a6b46ecc63f98308 (patch)
treec27c61ac33582bc4d469c6608cd042add388f230 /far2l/src/editor.cpp
parentd5f1bf245e96834d44390d1723cfef3dfbb1fb02 (diff)
shuffle a bit far2l sources
Diffstat (limited to 'far2l/src/editor.cpp')
-rw-r--r--far2l/src/editor.cpp6995
1 files changed, 6995 insertions, 0 deletions
diff --git a/far2l/src/editor.cpp b/far2l/src/editor.cpp
new file mode 100644
index 00000000..1644acac
--- /dev/null
+++ b/far2l/src/editor.cpp
@@ -0,0 +1,6995 @@
+/*
+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 "editor.hpp"
+#include "edit.hpp"
+#include "keyboard.hpp"
+#include "lang.hpp"
+#include "macroopcode.hpp"
+#include "keys.hpp"
+#include "ctrlobj.hpp"
+#include "chgprior.hpp"
+#include "filestr.hpp"
+#include "dialog.hpp"
+#include "fileedit.hpp"
+#include "savescr.hpp"
+#include "scrbuf.hpp"
+#include "TPreRedrawFunc.hpp"
+#include "syslog.hpp"
+#include "interf.hpp"
+#include "message.hpp"
+#include "clipboard.hpp"
+#include "xlat.hpp"
+#include "datetime.hpp"
+#include "stddlg.hpp"
+#include "strmix.hpp"
+#include "palette.hpp"
+#include "FarDlgBuilder.hpp"
+#include "wakeful.hpp"
+
+static int ReplaceMode,ReplaceAll;
+
+static int EditorID=0;
+
+// EditorUndoData
+enum {UNDO_EDIT=1,UNDO_INSSTR,UNDO_DELSTR,UNDO_BEGIN,UNDO_END};
+
+Editor::Editor(ScreenObject *pOwner,bool DialogUsed):
+ UndoPos(nullptr),
+ UndoSavePos(nullptr),
+ UndoSkipLevel(0),
+ LastChangeStrPos(0),
+ NumLastLine(0),
+ NumLine(0),
+ Pasting(0),
+ BlockStart(nullptr),
+ BlockStartLine(0),
+ VBlockStart(nullptr),
+ MaxRightPos(0),
+ LastSearchCase(GlobalSearchCase),
+ LastSearchWholeWords(GlobalSearchWholeWords),
+ LastSearchReverse(GlobalSearchReverse),
+ LastSearchSelFound(Opt.EdOpt.SearchSelFound),
+ LastSearchRegexp(Opt.EdOpt.SearchRegexp),
+ m_codepage(CP_OEMCP),
+ StartLine(-1),
+ StartChar(-1),
+ StackPos(0),
+ NewStackPos(FALSE),
+ EditorID(::EditorID++),
+ HostFileEditor(nullptr),
+ TopList(nullptr),
+ EndList(nullptr),
+ TopScreen(nullptr),
+ CurLine(nullptr),
+ LastGetLine(nullptr),
+ LastGetLineNumber(0)
+{
+ _KEYMACRO(SysLog(L"Editor::Editor()"));
+ _KEYMACRO(SysLog(1));
+ EdOpt = Opt.EdOpt;
+ SetOwner(pOwner);
+
+ if (DialogUsed)
+ Flags.Set(FEDITOR_DIALOGMEMOEDIT);
+
+ /* $ 26.10.2003 KM
+ Если установлен глобальный режим поиска 16-ричных кодов, тогда
+ сконвертируем GlobalSearchString в строку, ибо она содержит строку в
+ 16-ричном представлении.
+ */
+ if (GlobalSearchHex)
+ Transform(strLastSearchStr,strGlobalSearchString,L'S');
+ else
+ strLastSearchStr = strGlobalSearchString;
+
+ UnmarkMacroBlock();
+ /* $ 12.01.2002 IS
+ По умолчанию конец строки так или иначе равен \r\n, поэтому нечего
+ пудрить мозги, пропишем его явно.
+ */
+ wcscpy(GlobalEOL, NATIVE_EOLW);
+ memset(&SavePos,0xff,sizeof(SavePos));
+ InsertString(nullptr, 0);
+}
+
+
+Editor::~Editor()
+{
+ //_SVS(SysLog(L"[%p] Editor::~Editor()",this));
+ FreeAllocatedData();
+ KeepInitParameters();
+ _KEYMACRO(SysLog(-1));
+ _KEYMACRO(SysLog(L"Editor::~Editor()"));
+}
+
+void Editor::FreeAllocatedData(bool FreeUndo)
+{
+ while (EndList)
+ {
+ Edit *Prev=EndList->m_prev;
+ delete EndList;
+ EndList=Prev;
+ }
+
+ UndoData.Clear();
+ UndoSavePos=nullptr;
+ UndoPos=nullptr;
+ UndoSkipLevel=0;
+ ClearStackBookmarks();
+ TopList=EndList=CurLine=nullptr;
+ NumLastLine = 0;
+}
+
+void Editor::KeepInitParameters()
+{
+ // Установлен глобальный режим поиска 16-ричных данных?
+ if (GlobalSearchHex)
+ Transform(strGlobalSearchString,strLastSearchStr,L'X');
+ else
+ strGlobalSearchString = strLastSearchStr;
+
+ GlobalSearchCase=LastSearchCase;
+ GlobalSearchWholeWords=LastSearchWholeWords;
+ GlobalSearchReverse=LastSearchReverse;
+ Opt.EdOpt.SearchSelFound=LastSearchSelFound;
+ Opt.EdOpt.SearchRegexp=LastSearchRegexp;
+}
+
+/*
+ преобразование из буфера в список
+*/
+int Editor::SetRawData(const wchar_t *SrcBuf,int SizeSrcBuf,int TextFormat)
+{
+#if defined(PROJECT_DI_MEMOEDIT)
+ //InsertString(const wchar_t *lpwszStr, int nLength, Edit *pAfter)
+ TextChanged(1);
+
+#endif
+ return TRUE;
+}
+
+/*
+ Editor::Edit2Str - преобразование из списка в буфер с учетом EOL
+
+ DestBuf - куда сохраняем (выделяется динамически!)
+ SizeDestBuf - размер сохранения
+ TextFormat - тип концовки строк
+*/
+int Editor::GetRawData(wchar_t **DestBuf,int& SizeDestBuf,int TextFormat)
+{
+#if defined(PROJECT_DI_MEMOEDIT)
+ wchar_t* PDest=nullptr;
+ SizeDestBuf=0; // общий размер = 0
+
+ const wchar_t *SaveStr, *EndSeq;
+
+ int Length;
+
+ // посчитаем количество строк и общий размер памяти (чтобы не дергать realloc)
+ Edit *CurPtr=TopList;
+
+ DWORD AllLength=0;
+
+ while (CurPtr)
+ {
+ CurPtr->GetBinaryString(&SaveStr,&EndSeq,Length);
+ AllLength+=Length+StrLength(!TextFormat?EndSeq:GlobalEOL)+1;
+ }
+
+ wchar_t * MemEditStr=reinterpret_cast<wchar_t*>(malloc((AllLength+8)*sizeof(wchar_t)));
+
+ if (MemEditStr)
+ {
+ *MemEditStr=0;
+ PDest=MemEditStr;
+
+ // прйдемся по списку строк
+ CurPtr=TopList;
+
+ AllLength=0;
+
+ while (CurPtr)
+ {
+ CurPtr->GetBinaryString(&SaveStr,&EndSeq,Length);
+ wmemcpy(PDest,SaveStr,Length);
+ PDest+=Length;
+
+ size_t LenEndSeq;
+ if (!TextFormat)
+ {
+ LenEndSeq=StrLength(EndSeq);
+ wmemcpy(PDest,EndSeq,LenEndSeq);
+ }
+ else
+ {
+ LenEndSeq=StrLength(GlobalEOL);
+ wmemcpy(PDest,GlobalEOL,LenEndSeq);
+ }
+
+ PDest+=LenEndSeq;
+
+ AllLength+=LenEndSeq+Length;
+
+ CurPtr=CurPtr->m_next;
+ }
+
+ *PDest=0;
+
+ SizeDestBuf=AllLength;
+ DestBuf=&MemEditStr;
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+#else
+ return TRUE;
+#endif
+}
+
+
+void Editor::DisplayObject()
+{
+ ShowEditor(FALSE);
+}
+
+
+void Editor::ShowEditor(int CurLineOnly)
+{
+ if (Locked() || !TopList)
+ return;
+
+ Edit *CurPtr;
+ int LeftPos,CurPos,Y;
+
+//_SVS(SysLog(L"Enter to ShowEditor, CurLineOnly=%i",CurLineOnly));
+ /*$ 10.08.2000 skv
+ To make sure that CurEditor is set to required value.
+ */
+ if (!Flags.Check(FEDITOR_DIALOGMEMOEDIT))
+ CtrlObject->Plugins.CurEditor=HostFileEditor; // this;
+
+ XX2=X2-(EdOpt.ShowScrollBar?1:0);
+ /* 17.04.2002 skv
+ Что б курсор не бегал при Alt-F9 в конце длинного файла.
+ Если на экране есть свободное место, и есть текст сверху,
+ перепозиционируем.
+ */
+
+ if (!EdOpt.AllowEmptySpaceAfterEof)
+ {
+ while (CalcDistance(TopScreen,nullptr,Y2-Y1)<Y2-Y1)
+ {
+ if (TopScreen->m_prev)
+ TopScreen=TopScreen->m_prev;
+ else
+ break;
+ }
+ }
+
+ /*
+ если курсор удруг оказался "за экраном",
+ подвинем экран под курсор, а не
+ курсор загоним в экран.
+ */
+
+ while (CalcDistance(TopScreen,CurLine,-1)>=Y2-Y1+1)
+ {
+ TopScreen=TopScreen->m_next;
+ //DisableOut=TRUE;
+ //ProcessKey(KEY_UP);
+ //DisableOut=FALSE;
+ }
+
+ CurPos=CurLine->GetTabCurPos();
+
+ if (!EdOpt.CursorBeyondEOL)
+ {
+ MaxRightPos=CurPos;
+ int RealCurPos=CurLine->GetCurPos();
+ int Length=CurLine->GetLength();
+
+ if (RealCurPos>Length)
+ {
+ CurLine->SetCurPos(Length);
+ CurLine->SetLeftPos(0);
+ CurPos=CurLine->GetTabCurPos();
+ }
+ }
+
+ if (!Pasting)
+ {
+ /*$ 10.08.2000 skv
+ Don't send EE_REDRAW while macro is being executed.
+ Send EE_REDRAW with param=2 if text was just modified.
+
+ */
+ _SYS_EE_REDRAW(CleverSysLog Clev(L"Editor::ShowEditor()"));
+
+ if (!ScrBuf.GetLockCount())
+ {
+ /*$ 13.09.2000 skv
+ EE_REDRAW 1 and 2 replaced.
+ */
+ if (Flags.Check(FEDITOR_JUSTMODIFIED))
+ {
+ Flags.Clear(FEDITOR_JUSTMODIFIED);
+
+ if (!Flags.Check(FEDITOR_DIALOGMEMOEDIT))
+ {
+ _SYS_EE_REDRAW(SysLog(L"Call ProcessEditorEvent(EE_REDRAW,EEREDRAW_CHANGE)"));
+ CtrlObject->Plugins.ProcessEditorEvent(EE_REDRAW,EEREDRAW_CHANGE);
+ }
+ }
+ else
+ {
+ if (!Flags.Check(FEDITOR_DIALOGMEMOEDIT))
+ {
+ _SYS_EE_REDRAW(SysLog(L"Call ProcessEditorEvent(EE_REDRAW,%ls)",(CurLineOnly?"EEREDRAW_LINE":"EEREDRAW_ALL")));
+ CtrlObject->Plugins.ProcessEditorEvent(EE_REDRAW,CurLineOnly?EEREDRAW_LINE:EEREDRAW_ALL);
+ }
+ }
+ }
+ _SYS_EE_REDRAW(else SysLog(L"ScrBuf Locked !!!"));
+ }
+
+ DrawScrollbar();
+
+ if (!CurLineOnly)
+ {
+ LeftPos=CurLine->GetLeftPos();
+#if 0
+
+ // крайне эксперементальный кусок!
+ if (CurPos+LeftPos < XX2)
+ LeftPos=0;
+ else if (CurLine->X2 < XX2)
+ LeftPos=CurLine->GetLength()-CurPos;
+
+ if (LeftPos < 0)
+ LeftPos=0;
+
+#endif
+
+ for (CurPtr=TopScreen,Y=Y1; Y<=Y2; Y++)
+ if (CurPtr)
+ {
+ CurPtr->SetEditBeyondEnd(TRUE);
+ CurPtr->SetPosition(X1,Y,XX2,Y);
+ //CurPtr->SetTables(UseDecodeTable ? &TableSet:nullptr);
+ //_D(SysLog(L"Setleftpos 3 to %i",LeftPos));
+ CurPtr->SetLeftPos(LeftPos);
+ CurPtr->SetTabCurPos(CurPos);
+ CurPtr->FastShow();
+ CurPtr->SetEditBeyondEnd(EdOpt.CursorBeyondEOL);
+ CurPtr=CurPtr->m_next;
+ }
+ else
+ {
+ SetScreen(X1,Y,XX2,Y,L' ',COL_EDITORTEXT); //Пустые строки после конца текста
+ }
+ }
+
+ CurLine->SetOvertypeMode(Flags.Check(FEDITOR_OVERTYPE));
+ CurLine->Show();
+
+ if (VBlockStart && VBlockSizeX>0 && VBlockSizeY>0)
+ {
+ int CurScreenLine=NumLine-CalcDistance(TopScreen,CurLine,-1);
+ LeftPos=CurLine->GetLeftPos();
+
+ for (CurPtr=TopScreen,Y=Y1; Y<=Y2; Y++)
+ {
+ if (CurPtr)
+ {
+ if (CurScreenLine>=VBlockY && CurScreenLine<VBlockY+VBlockSizeY)
+ {
+ int BlockX1=VBlockX-LeftPos+X1;
+ int BlockX2=VBlockX+VBlockSizeX-1-LeftPos+X1;
+
+ if (BlockX1<X1)
+ BlockX1=X1;
+
+ if (BlockX2>XX2)
+ BlockX2=XX2;
+
+ if (BlockX1<=XX2 && BlockX2>=X1)
+ ChangeBlockColor(BlockX1,Y,BlockX2,Y,COL_EDITORSELECTEDTEXT);
+ }
+
+ CurPtr=CurPtr->m_next;
+ CurScreenLine++;
+ }
+ }
+ }
+
+ if (HostFileEditor) HostFileEditor->ShowStatus();
+
+//_SVS(SysLog(L"Exit from ShowEditor"));
+}
+
+
+/*$ 10.08.2000 skv
+ Wrapper for Modified.
+ Set JustModified every call to 1
+ to track any text state change.
+ Even if state==0, this can be
+ last UNDO.
+*/
+void Editor::TextChanged(int State)
+{
+ Flags.Change(FEDITOR_MODIFIED,State);
+ Flags.Set(FEDITOR_JUSTMODIFIED);
+}
+
+
+bool Editor::CheckLine(Edit* line)
+{
+ if (line)
+ {
+ Edit* eLine;
+
+ for (eLine=TopList; eLine; eLine=eLine->m_next)
+ {
+ if (eLine == line)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+int Editor::BlockStart2NumLine(int *Pos)
+{
+ if (BlockStart || VBlockStart)
+ {
+ Edit *eBlock=VBlockStart?VBlockStart:BlockStart;
+
+ if (Pos)
+ {
+ if (VBlockStart)
+ *Pos=eBlock->RealPosToTab(eBlock->TabPosToReal(VBlockX));
+ else
+ *Pos=eBlock->RealPosToTab(eBlock->SelStart);
+ }
+
+ return CalcDistance(TopList,eBlock,-1);
+ }
+
+ return -1;
+}
+
+int Editor::BlockEnd2NumLine(int *Pos)
+{
+ int iLine=-1, iPos=-1;
+ Edit *eBlock=VBlockStart?VBlockStart:BlockStart;
+
+ if (eBlock)
+ {
+ int StartSel, EndSel;
+ Edit *eLine=eBlock;
+ iLine=BlockStart2NumLine(nullptr); // получили строку начала блока
+
+ if (VBlockStart)
+ {
+ for (int Line=VBlockSizeY; eLine && Line > 0; Line--, eLine=eLine->m_next)
+ {
+ iPos=eLine->RealPosToTab(eLine->TabPosToReal(VBlockX+VBlockSizeX));
+ iLine++;
+ }
+
+ iLine--;
+ }
+ else
+ {
+ while (eLine) // поиск строки, содержащую конец блока
+ {
+ eLine->GetSelection(StartSel,EndSel);
+
+ if (EndSel == -1) // это значит, что конец блока "за строкой"
+ eLine->GetRealSelection(StartSel,EndSel);
+
+ if (StartSel == -1)
+ {
+ // Если в текущей строки нет выделения, это еще не значит что мы в конце. Это может быть только начало :)
+ if (eLine->m_next)
+ {
+ eLine->m_next->GetSelection(StartSel,EndSel);
+
+ if (EndSel == -1) // это значит, что конец блока "за строкой"
+ eLine->m_next->GetRealSelection(StartSel,EndSel);
+
+ if (StartSel==-1)
+ {
+ break;
+ }
+ }
+ else
+ break;
+ }
+ else
+ {
+ iPos=eLine->RealPosToTab(EndSel);
+ iLine++;
+ }
+
+ eLine=eLine->m_next;
+ }
+
+ iLine--;
+ }
+ }
+
+ if (Pos)
+ *Pos=iPos;
+
+ return iLine;
+}
+
+
+int64_t Editor::VMProcess(int OpCode,void *vParam,int64_t iParam)
+{
+ int CurPos=CurLine->GetCurPos();
+
+ switch (OpCode)
+ {
+ case MCODE_C_EMPTY:
+ return (int64_t)(!CurLine->m_next && !CurLine->m_prev); //??
+ case MCODE_C_EOF:
+ return (int64_t)(!CurLine->m_next && CurPos>=CurLine->GetLength());
+ case MCODE_C_BOF:
+ return (int64_t)(!CurLine->m_prev && !CurPos);
+ case MCODE_C_SELECTED:
+ return (int64_t)(BlockStart || VBlockStart?TRUE:FALSE);
+ case MCODE_V_EDITORCURPOS:
+ return (int64_t)(CurLine->GetTabCurPos()+1);
+ case MCODE_V_EDITORREALPOS:
+ return (int64_t)(CurLine->GetCurPos()+1);
+ case MCODE_V_EDITORCURLINE:
+ return (int64_t)(NumLine+1);
+ case MCODE_V_ITEMCOUNT:
+ case MCODE_V_EDITORLINES:
+ return (int64_t)NumLastLine;
+ // работа со стековыми закладками
+ case MCODE_F_BM_ADD:
+ return AddStackBookmark();
+ case MCODE_F_BM_CLEAR:
+ return ClearStackBookmarks();
+ case MCODE_F_BM_NEXT:
+ return NextStackBookmark();
+ case MCODE_F_BM_PREV:
+ return PrevStackBookmark();
+ case MCODE_F_BM_BACK:
+ return BackStackBookmark();
+ case MCODE_F_BM_STAT:
+ {
+ switch (iParam)
+ {
+ case 0: // BM.Stat(0) возвращает количество
+ return GetStackBookmarks(nullptr);
+ case 1: // индекс текущей закладки (0 если закладок нет)
+ return CurrentStackBookmarkIdx()+1;
+ }
+ return 0;
+ }
+ case MCODE_F_BM_PUSH: // N=BM.push() - сохранить текущую позицию в виде закладки в конце стека
+ return PushStackBookMark();
+ case MCODE_F_BM_POP: // N=BM.pop() - восстановить текущую позицию из закладки в конце стека и удалить закладку
+ return PopStackBookMark();
+ case MCODE_F_BM_GOTO: // N=BM.goto([n]) - переход на закладку с указанным индексом (0 --> текущую)
+ return GotoStackBookmark((int)iParam-1);
+ case MCODE_F_BM_GET: // N=BM.Get(Idx,M) - возвращает координаты строки (M==0) или колонки (M==1) закладки с индексом (Idx=1...)
+ {
+ int64_t Ret=-1;
+ long Val[1];
+ EditorBookMarks ebm={0};
+ int iMode=(int)((LONG_PTR)vParam);
+
+ switch (iMode)
+ {
+ case 0: ebm.Line=Val; break;
+ case 1: ebm.Cursor=Val; break;
+ case 2: ebm.LeftPos=Val; break;
+ case 3: ebm.ScreenLine=Val; break;
+ default: iMode=-1; break;
+ }
+
+ if (iMode >= 0 && GetStackBookmark((int)iParam-1,&ebm))
+ Ret=(int64_t)((DWORD)Val[0]+1);
+
+ return Ret;
+ }
+ case MCODE_F_BM_DEL: // N=BM.Del(Idx) - удаляет закладку с указанным индексом (x=1...), 0 - удаляет текущую закладку
+ return DeleteStackBookmark(PointerToStackBookmark((int)iParam-1));
+
+ case MCODE_F_EDITOR_SEL:
+ {
+ int iLine;
+ int iPos;
+ int Action=(int)((INT_PTR)vParam);
+
+ switch (Action)
+ {
+ case 0: // Get Param
+ {
+ switch (iParam)
+ {
+ case 0: // return FirstLine
+ {
+ return BlockStart2NumLine(nullptr)+1;
+ }
+ case 1: // return FirstPos
+ {
+ if (BlockStart2NumLine(&iPos) != -1)
+ return iPos+1;
+
+ return 0;
+ }
+ case 2: // return LastLine
+ {
+ return BlockEnd2NumLine(nullptr)+1;
+ }
+ case 3: // return LastPos
+ {
+ if (BlockEnd2NumLine(&iPos) != -1)
+ return iPos;
+
+ return 0;
+ }
+ case 4: // return block type (0=nothing 1=stream, 2=column)
+ {
+ return VBlockStart?2:(BlockStart?1:0);
+ }
+ }
+
+ break;
+ }
+ case 1: // Set Pos
+ {
+ switch (iParam)
+ {
+ case 0: // begin block (FirstLine & FirstPos)
+ case 1: // end block (LastLine & LastPos)
+ {
+ if (!iParam)
+ iLine=BlockStart2NumLine(&iPos);
+ else
+ iLine=BlockEnd2NumLine(&iPos);
+
+ if (iLine > -1 && iPos > -1)
+ {
+ GoToLine(iLine);
+ CurLine->SetCurPos(CurLine->TabPosToReal(iPos));
+ return 1;
+ }
+
+ return 0;
+ }
+ }
+
+ break;
+ }
+ case 2: // Set Stream Selection Edge
+ case 3: // Set Column Selection Edge
+ {
+ switch (iParam)
+ {
+ case 0: // selection start
+ {
+ MBlockStart=CurLine;
+ MBlockStartX=CurLine->GetCurPos();
+ return 1;
+ }
+ case 1: // selection finish
+ {
+ int Ret=0;
+
+ if (CheckLine(MBlockStart))
+ {
+ EditorSelect eSel;
+ eSel.BlockType=(Action == 2)?BTYPE_STREAM:BTYPE_COLUMN;
+ eSel.BlockStartPos=MBlockStartX;
+ eSel.BlockWidth=CurLine->GetCurPos()-MBlockStartX;
+
+ if (eSel.BlockWidth || (Action == 2 && MBlockStart != CurLine))
+ {
+ int bl=CalcDistance(TopList,MBlockStart,-1);
+ int el=CalcDistance(TopList,CurLine,-1);
+
+ if (bl > el)
+ {
+ eSel.BlockStartLine=el;
+ eSel.BlockHeight=CalcDistance(CurLine,MBlockStart,-1)+1;
+ }
+ else
+ {
+ eSel.BlockStartLine=bl;
+ eSel.BlockHeight=CalcDistance(MBlockStart,CurLine,-1)+1;
+ }
+
+ if (bl > el || (bl == el && eSel.BlockWidth<0))
+ {
+ eSel.BlockWidth*=-1;
+ eSel.BlockStartPos=CurLine->GetCurPos();
+ }
+
+ Ret=EditorControl(ECTL_SELECT,&eSel);
+ }
+ else if (!eSel.BlockWidth && MBlockStart == CurLine)
+ {
+ UnmarkBlock();
+ }
+ }
+
+ UnmarkMacroBlock();
+ Show();
+ return (int64_t)Ret;
+ }
+ }
+
+ break;
+ }
+ case 4: // UnMark sel block
+ {
+ bool NeedRedraw=BlockStart || VBlockStart;
+ UnmarkBlock();
+ UnmarkMacroBlock();
+
+ if (NeedRedraw)
+ Show();
+
+ return 1;
+ }
+ }
+
+ break;
+ }
+ case MCODE_V_EDITORSELVALUE: // Editor.SelValue
+ {
+ FARString strText;
+ wchar_t *Text;
+
+ if (VBlockStart)
+ Text = VBlock2Text(nullptr);
+ else
+ Text = Block2Text(nullptr);
+
+ if (Text)
+ {
+ strText = Text;
+ free(Text);
+ }
+
+ *(FARString *)vParam=strText;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void Editor::ProcessPasteEvent()
+{
+ if (Flags.Check(FEDITOR_LOCKMODE))
+ return;
+
+ Pasting++;
+ if (!EdOpt.PersistentBlocks && !VBlockStart)
+ DeleteBlock();
+
+ Paste();
+ // MarkingBlock=!VBlockStart;
+ Flags.Change(FEDITOR_MARKINGBLOCK,!VBlockStart);
+ Flags.Clear(FEDITOR_MARKINGVBLOCK);
+
+ if (!EdOpt.PersistentBlocks)
+ UnmarkBlock();
+
+ Pasting--;
+ Show();
+}
+
+int Editor::ProcessKey(int Key)
+{
+ if (Key==KEY_IDLE)
+ {
+ if (Opt.ViewerEditorClock && HostFileEditor && HostFileEditor->IsFullScreen() && Opt.EdOpt.ShowTitleBar)
+ ShowTime(FALSE);
+
+ return TRUE;
+ }
+
+ if (Key==KEY_NONE)
+ return TRUE;
+
+ _KEYMACRO(CleverSysLog SL(L"Editor::ProcessKey()"));
+ _KEYMACRO(SysLog(L"Key=%ls",_FARKEY_ToName(Key)));
+ int CurPos,CurVisPos,I;
+ CurPos=CurLine->GetCurPos();
+ CurVisPos=GetLineCurPos();
+ int isk=IsShiftKey(Key);
+ _SVS(SysLog(L"[%d] isk=%d",__LINE__,isk));
+
+ //if ((!isk || CtrlObject->Macro.IsExecuting()) && !isk && !Pasting)
+ if (!isk && !Pasting && !(((unsigned int)Key >= KEY_MACRO_BASE && (unsigned int)Key <= KEY_MACRO_ENDBASE) || ((unsigned int)Key>=KEY_OP_BASE && (unsigned int)Key <=KEY_OP_ENDBASE)))
+ {
+ _SVS(SysLog(L"[%d] BlockStart=(%d,%d)",__LINE__,BlockStart,VBlockStart));
+
+ if (BlockStart || VBlockStart)
+ {
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+ }
+
+ if ((BlockStart || VBlockStart) && !EdOpt.PersistentBlocks)
+// if (BlockStart || VBlockStart && !EdOpt.PersistentBlocks)
+ {
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+
+ if (!EdOpt.PersistentBlocks)
+ {
+ static int UnmarkKeys[]=
+ {
+ KEY_LEFT, KEY_NUMPAD4,
+ KEY_RIGHT, KEY_NUMPAD6,
+ KEY_HOME, KEY_NUMPAD7,
+ KEY_END, KEY_NUMPAD1,
+ KEY_UP, KEY_NUMPAD8,
+ KEY_DOWN, KEY_NUMPAD2,
+ KEY_PGUP, KEY_NUMPAD9,
+ KEY_PGDN, KEY_NUMPAD3,
+ KEY_CTRLHOME, KEY_CTRLNUMPAD7,
+ KEY_CTRLPGUP, KEY_CTRLNUMPAD9,
+ KEY_CTRLEND, KEY_CTRLNUMPAD1,
+ KEY_CTRLPGDN, KEY_CTRLNUMPAD3,
+ KEY_CTRLLEFT, KEY_CTRLNUMPAD4,
+ KEY_CTRLRIGHT, KEY_CTRLNUMPAD7,
+ KEY_CTRLUP, KEY_CTRLNUMPAD8,
+ KEY_CTRLDOWN, KEY_CTRLNUMPAD2,
+ KEY_CTRLN,
+ KEY_CTRLE,
+ KEY_CTRLS,
+ };
+
+ for (size_t I=0; I<ARRAYSIZE(UnmarkKeys); I++)
+ if (Key==UnmarkKeys[I])
+ {
+ UnmarkBlock();
+ break;
+ }
+ }
+ else
+ {
+ int StartSel,EndSel;
+// Edit *BStart=!BlockStart?VBlockStart:BlockStart;
+// BStart->GetRealSelection(StartSel,EndSel);
+ BlockStart->GetRealSelection(StartSel,EndSel);
+ _SVS(SysLog(L"[%d] PersistentBlocks! StartSel=%d, EndSel=%d",__LINE__,StartSel,EndSel));
+
+ if (StartSel==-1 || StartSel==EndSel)
+ UnmarkBlock();
+ }
+ }
+ }
+
+ if (Key==KEY_ALTD)
+ Key=KEY_CTRLK;
+
+ // работа с закладками
+ if (Key>=KEY_CTRL0 && Key<=KEY_CTRL9)
+ return GotoBookmark(Key-KEY_CTRL0);
+
+ if (Key>=KEY_CTRLSHIFT0 && Key<=KEY_CTRLSHIFT9)
+ Key=Key-KEY_CTRLSHIFT0+KEY_RCTRL0;
+
+ if (Key>=KEY_RCTRL0 && Key<=KEY_RCTRL9)
+ return SetBookmark(Key-KEY_RCTRL0);
+
+ int SelStart=0,SelEnd=0;
+ int SelFirst=FALSE;
+ int SelAtBeginning=FALSE;
+ EditorBlockGuard _bg(*this,&Editor::UnmarkEmptyBlock);
+
+ switch (Key)
+ {
+ case KEY_SHIFTLEFT: case KEY_SHIFTRIGHT:
+ case KEY_SHIFTUP: case KEY_SHIFTDOWN:
+ case KEY_SHIFTHOME: case KEY_SHIFTEND:
+ case KEY_SHIFTNUMPAD4: case KEY_SHIFTNUMPAD6:
+ case KEY_SHIFTNUMPAD8: case KEY_SHIFTNUMPAD2:
+ case KEY_SHIFTNUMPAD7: case KEY_SHIFTNUMPAD1:
+ case KEY_CTRLSHIFTLEFT: case KEY_CTRLSHIFTNUMPAD4: /* 12.11.2002 DJ */
+ {
+ _KEYMACRO(CleverSysLog SL(L"Editor::ProcessKey(KEY_SHIFT*)"));
+ _SVS(SysLog(L"[%d] SelStart=%d, SelEnd=%d",__LINE__,SelStart,SelEnd));
+ UnmarkEmptyBlock(); // уберем выделение, если его размер равен 0
+ _bg.SetNeedCheckUnmark(true);
+ CurLine->GetRealSelection(SelStart,SelEnd);
+
+ if (Flags.Check(FEDITOR_CURPOSCHANGEDBYPLUGIN))
+ {
+ if (SelStart!=-1 && (CurPos<SelStart || // если курсор до выделения
+ (SelEnd!=-1 && (CurPos>SelEnd || // ... после выделения
+ (CurPos>SelStart && CurPos<SelEnd)))) &&
+ CurPos<CurLine->GetLength()) // ... внутри выдления
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+
+ Flags.Clear(FEDITOR_CURPOSCHANGEDBYPLUGIN);
+ }
+
+ _SVS(SysLog(L"[%d] SelStart=%d, SelEnd=%d",__LINE__,SelStart,SelEnd));
+
+ if (!Flags.Check(FEDITOR_MARKINGBLOCK))
+ {
+ UnmarkBlock();
+ Flags.Set(FEDITOR_MARKINGBLOCK);
+ BlockStart=CurLine;
+ BlockStartLine=NumLine;
+ SelFirst=TRUE;
+ SelStart=SelEnd=CurPos;
+ }
+ else
+ {
+ SelAtBeginning=CurLine==BlockStart && CurPos==SelStart;
+
+ if (SelStart==-1)
+ {
+ SelStart=SelEnd=CurPos;
+ }
+ }
+
+ _SVS(SysLog(L"[%d] SelStart=%d, SelEnd=%d",__LINE__,SelStart,SelEnd));
+ }
+ }
+
+ switch (Key)
+ {
+ case KEY_CTRLSHIFTPGUP: case KEY_CTRLSHIFTNUMPAD9:
+ case KEY_CTRLSHIFTHOME: case KEY_CTRLSHIFTNUMPAD7:
+ {
+ Lock();
+ Pasting++;
+
+ while (CurLine!=TopList)
+ {
+ ProcessKey(KEY_SHIFTPGUP);
+ }
+
+ if (Key == KEY_CTRLSHIFTHOME || Key == KEY_CTRLSHIFTNUMPAD7)
+ ProcessKey(KEY_SHIFTHOME);
+
+ Pasting--;
+ Unlock();
+ Show();
+ return TRUE;
+ }
+ case KEY_CTRLSHIFTPGDN: case KEY_CTRLSHIFTNUMPAD3:
+ case KEY_CTRLSHIFTEND: case KEY_CTRLSHIFTNUMPAD1:
+ {
+ Lock();
+ Pasting++;
+
+ while (CurLine!=EndList)
+ {
+ ProcessKey(KEY_SHIFTPGDN);
+ }
+
+ /* $ 06.02.2002 IS
+ Принудительно сбросим флаг того, что позиция изменена плагином.
+ Для чего:
+ при выполнении "ProcessKey(KEY_SHIFTPGDN)" (см. чуть выше)
+ позиция плагины (в моем случае - колорер) могут дергать
+ ECTL_SETPOSITION, в результате чего выставляется флаг
+ FEDITOR_CURPOSCHANGEDBYPLUGIN. А при обработке KEY_SHIFTEND
+ выделение в подобном случае начинается с нуля, что сводит на нет
+ предыдущее выполнение KEY_SHIFTPGDN.
+ */
+ Flags.Clear(FEDITOR_CURPOSCHANGEDBYPLUGIN);
+
+ if (Key == KEY_CTRLSHIFTEND || Key == KEY_CTRLSHIFTNUMPAD1)
+ ProcessKey(KEY_SHIFTEND);
+
+ Pasting--;
+ Unlock();
+ Show();
+ return TRUE;
+ }
+ case KEY_SHIFTPGUP: case KEY_SHIFTNUMPAD9:
+ {
+ Pasting++;
+ Lock();
+
+ for (I=Y1; I<Y2; I++)
+ {
+ ProcessKey(KEY_SHIFTUP);
+
+ if (!EdOpt.CursorBeyondEOL)
+ {
+ if (CurLine->GetCurPos()>CurLine->GetLength())
+ {
+ CurLine->SetCurPos(CurLine->GetLength());
+ }
+ }
+ }
+
+ Pasting--;
+ Unlock();
+ Show();
+ return TRUE;
+ }
+ case KEY_SHIFTPGDN: case KEY_SHIFTNUMPAD3:
+ {
+ Pasting++;
+ Lock();
+
+ for (I=Y1; I<Y2; I++)
+ {
+ ProcessKey(KEY_SHIFTDOWN);
+
+ if (!EdOpt.CursorBeyondEOL)
+ {
+ if (CurLine->GetCurPos()>CurLine->GetLength())
+ {
+ CurLine->SetCurPos(CurLine->GetLength());
+ }
+ }
+ }
+
+ Pasting--;
+ Unlock();
+ Show();
+ return TRUE;
+ }
+ case KEY_SHIFTHOME: case KEY_SHIFTNUMPAD7:
+ {
+ Pasting++;
+ Lock();
+
+ if (SelAtBeginning)
+ {
+ CurLine->Select(0,SelEnd);
+ }
+ else
+ {
+ if (!SelStart)
+ {
+ CurLine->Select(-1,0);
+ }
+ else
+ {
+ CurLine->Select(0,SelStart);
+ }
+ }
+
+ ProcessKey(KEY_HOME);
+ Pasting--;
+ Unlock();
+ Show();
+ return TRUE;
+ }
+ case KEY_SHIFTEND:
+ case KEY_SHIFTNUMPAD1:
+ {
+ {
+ int LeftPos=CurLine->GetLeftPos();
+ Pasting++;
+ Lock();
+ int CurLength=CurLine->GetLength();
+
+ if (!SelAtBeginning || SelFirst)
+ {
+ CurLine->Select(SelStart,CurLength);
+ }
+ else
+ {
+ if (SelEnd!=-1)
+ CurLine->Select(SelEnd,CurLength);
+ else
+ CurLine->Select(CurLength,-1);
+ }
+
+ CurLine->ObjWidth=XX2-X1;
+ ProcessKey(KEY_END);
+ Pasting--;
+ Unlock();
+
+ if (EdOpt.PersistentBlocks)
+ Show();
+ else
+ {
+ CurLine->FastShow();
+ ShowEditor(LeftPos==CurLine->GetLeftPos());
+ }
+ }
+ return TRUE;
+ }
+ case KEY_SHIFTLEFT: case KEY_SHIFTNUMPAD4:
+ {
+ _SVS(CleverSysLog SL(L"case KEY_SHIFTLEFT"));
+
+ if (!CurPos && !CurLine->m_prev)return TRUE;
+
+ if (!CurPos) //курсор в начале строки
+ {
+ if (SelAtBeginning) //курсор в начале блока
+ {
+ BlockStart=CurLine->m_prev;
+ CurLine->m_prev->Select(CurLine->m_prev->GetLength(),-1);
+ }
+ else // курсор в конце блока
+ {
+ CurLine->Select(-1,0);
+ CurLine->m_prev->GetRealSelection(SelStart,SelEnd);
+ CurLine->m_prev->Select(SelStart,CurLine->m_prev->GetLength());
+ }
+ }
+ else
+ {
+ if (SelAtBeginning || SelFirst)
+ {
+ CurLine->Select(SelStart-1,SelEnd);
+ }
+ else
+ {
+ CurLine->Select(SelStart,SelEnd-1);
+ }
+ }
+
+ int LeftPos=CurLine->GetLeftPos();
+ Edit *OldCur=CurLine;
+ int _OldNumLine=NumLine;
+ Pasting++;
+ ProcessKey(KEY_LEFT);
+ Pasting--;
+
+ if (_OldNumLine!=NumLine)
+ {
+ BlockStartLine=NumLine;
+ }
+
+ ShowEditor(OldCur==CurLine && LeftPos==CurLine->GetLeftPos());
+ return TRUE;
+ }
+ case KEY_SHIFTRIGHT: case KEY_SHIFTNUMPAD6:
+ {
+ _SVS(CleverSysLog SL(L"case KEY_SHIFTRIGHT"));
+
+ if (!CurLine->m_next && CurPos==CurLine->GetLength() && !EdOpt.CursorBeyondEOL)
+ {
+ return TRUE;
+ }
+
+ if (SelAtBeginning)
+ {
+ CurLine->Select(SelStart+1,SelEnd);
+ }
+ else
+ {
+ CurLine->Select(SelStart,SelEnd+1);
+ }
+
+ Edit *OldCur=CurLine;
+ int OldLeft=CurLine->GetLeftPos();
+ Pasting++;
+ ProcessKey(KEY_RIGHT);
+ Pasting--;
+
+ if (OldCur!=CurLine)
+ {
+ if (SelAtBeginning)
+ {
+ OldCur->Select(-1,0);
+ BlockStart=CurLine;
+ BlockStartLine=NumLine;
+ }
+ else
+ {
+ OldCur->Select(SelStart,-1);
+ }
+ }
+
+ ShowEditor(OldCur==CurLine && OldLeft==CurLine->GetLeftPos());
+ return TRUE;
+ }
+ case KEY_CTRLSHIFTLEFT: case KEY_CTRLSHIFTNUMPAD4:
+ {
+ _SVS(CleverSysLog SL(L"case KEY_CTRLSHIFTLEFT"));
+ _SVS(SysLog(L"[%d] Pasting=%d, SelEnd=%d",__LINE__,Pasting,SelEnd));
+ {
+ int SkipSpace=TRUE;
+ Pasting++;
+ Lock();
+ int CurPos;
+
+ for (;;)
+ {
+ const wchar_t *Str;
+ int Length;
+ CurLine->GetBinaryString(&Str,nullptr,Length);
+ /* $ 12.11.2002 DJ
+ обеспечим корректную работу Ctrl-Shift-Left за концом строки
+ */
+ CurPos=CurLine->GetCurPos();
+
+ if (CurPos>Length)
+ {
+ int SelStartPos = CurPos;
+ CurLine->ProcessKey(KEY_END);
+ CurPos=CurLine->GetCurPos();
+
+ if (CurLine->SelStart >= 0)
+ {
+ if (!SelAtBeginning)
+ CurLine->Select(CurLine->SelStart, CurPos);
+ else
+ CurLine->Select(CurPos, CurLine->SelEnd);
+ }
+ else
+ CurLine->Select(CurPos, SelStartPos);
+ }
+
+ if (!CurPos)
+ break;
+
+ if (IsSpace(Str[CurPos-1]) || IsWordDiv(EdOpt.strWordDiv,Str[CurPos-1]))
+ {
+ if (SkipSpace)
+ {
+ ProcessKey(KEY_SHIFTLEFT);
+ continue;
+ }
+ else
+ break;
+ }
+
+ SkipSpace=FALSE;
+ ProcessKey(KEY_SHIFTLEFT);
+ }
+
+ Pasting--;
+ Unlock();
+ Show();
+ }
+ return TRUE;
+ }
+ case KEY_CTRLSHIFTRIGHT: case KEY_CTRLSHIFTNUMPAD6:
+ {
+ _SVS(CleverSysLog SL(L"case KEY_CTRLSHIFTRIGHT"));
+ _SVS(SysLog(L"[%d] Pasting=%d, SelEnd=%d",__LINE__,Pasting,SelEnd));
+ {
+ int SkipSpace=TRUE;
+ Pasting++;
+ Lock();
+ int CurPos;
+
+ for (;;)
+ {
+ const wchar_t *Str;
+ int Length;
+ CurLine->GetBinaryString(&Str,nullptr,Length);
+ CurPos=CurLine->GetCurPos();
+
+ if (CurPos>=Length)
+ break;
+
+ if (IsSpace(Str[CurPos]) || IsWordDiv(EdOpt.strWordDiv,Str[CurPos]))
+ {
+ if (SkipSpace)
+ {
+ ProcessKey(KEY_SHIFTRIGHT);
+ continue;
+ }
+ else
+ break;
+ }
+
+ SkipSpace=FALSE;
+ ProcessKey(KEY_SHIFTRIGHT);
+ }
+
+ Pasting--;
+ Unlock();
+ Show();
+ }
+ return TRUE;
+ }
+ case KEY_SHIFTDOWN: case KEY_SHIFTNUMPAD2:
+ {
+ if (!CurLine->m_next)return TRUE;
+
+ CurPos=CurLine->RealPosToTab(CurPos);
+
+ if (SelAtBeginning)//Снимаем выделение
+ {
+ if (SelEnd==-1)
+ {
+ CurLine->Select(-1,0);
+ BlockStart=CurLine->m_next;
+ BlockStartLine=NumLine+1;
+ }
+ else
+ {
+ CurLine->Select(SelEnd,-1);
+ }
+
+ CurLine->m_next->GetRealSelection(SelStart,SelEnd);
+
+ if (SelStart!=-1)SelStart=CurLine->m_next->RealPosToTab(SelStart);
+
+ if (SelEnd!=-1)SelEnd=CurLine->m_next->RealPosToTab(SelEnd);
+
+ if (SelStart==-1)
+ {
+ SelStart=0;
+ SelEnd=CurPos;
+ }
+ else
+ {
+ if (SelEnd!=-1 && SelEnd<CurPos)
+ {
+ SelStart=SelEnd;
+ SelEnd=CurPos;
+ }
+ else
+ {
+ SelStart=CurPos;
+ }
+ }
+
+ if (SelStart!=-1)SelStart=CurLine->m_next->TabPosToReal(SelStart);
+
+ if (SelEnd!=-1)SelEnd=CurLine->m_next->TabPosToReal(SelEnd);
+
+ /*if(!EdOpt.CursorBeyondEOL && SelEnd>CurLine->m_next->GetLength())
+ {
+ SelEnd=CurLine->m_next->GetLength();
+ }
+ if(!EdOpt.CursorBeyondEOL && SelStart>CurLine->m_next->GetLength())
+ {
+ SelStart=CurLine->m_next->GetLength();
+ }*/
+ }
+ else //расширяем выделение
+ {
+ CurLine->Select(SelStart,-1);
+ SelStart=CurLine->m_next->TabPosToReal(0);
+ SelEnd=CurLine->m_next->TabPosToReal(CurPos);
+ }
+
+ if (!EdOpt.CursorBeyondEOL && SelEnd > CurLine->m_next->GetLength())
+ {
+ SelEnd=CurLine->m_next->GetLength();
+ }
+
+ if (!EdOpt.CursorBeyondEOL && SelStart > CurLine->m_next->GetLength())
+ {
+ SelStart=CurLine->m_next->GetLength();
+ }
+
+// if(!SelStart && !SelEnd)
+// CurLine->m_next->Select(-1,0);
+// else
+ CurLine->m_next->Select(SelStart,SelEnd);
+ Down();
+ Show();
+ return TRUE;
+ }
+ case KEY_SHIFTUP: case KEY_SHIFTNUMPAD8:
+ {
+ if (!CurLine->m_prev) return 0;
+
+ if (SelAtBeginning || SelFirst) // расширяем выделение
+ {
+ CurLine->Select(0,SelEnd);
+ SelStart=CurLine->RealPosToTab(CurPos);
+
+ if (!EdOpt.CursorBeyondEOL &&
+ CurLine->m_prev->TabPosToReal(SelStart)>CurLine->m_prev->GetLength())
+ {
+ SelStart=CurLine->m_prev->RealPosToTab(CurLine->m_prev->GetLength());
+ }
+
+ SelStart=CurLine->m_prev->TabPosToReal(SelStart);
+ CurLine->m_prev->Select(SelStart,-1);
+ BlockStart=CurLine->m_prev;
+ BlockStartLine=NumLine-1;
+ }
+ else // снимаем выделение
+ {
+ CurPos=CurLine->RealPosToTab(CurPos);
+
+ if (!SelStart)
+ {
+ CurLine->Select(-1,0);
+ }
+ else
+ {
+ CurLine->Select(0,SelStart);
+ }
+
+ CurLine->m_prev->GetRealSelection(SelStart,SelEnd);
+
+ if (SelStart!=-1)SelStart=CurLine->m_prev->RealPosToTab(SelStart);
+
+ if (SelStart!=-1)SelEnd=CurLine->m_prev->RealPosToTab(SelEnd);
+
+ if (SelStart==-1)
+ {
+ BlockStart=CurLine->m_prev;
+ BlockStartLine=NumLine-1;
+ SelStart=CurLine->m_prev->TabPosToReal(CurPos);
+ SelEnd=-1;
+ }
+ else
+ {
+ if (CurPos<SelStart)
+ {
+ SelEnd=SelStart;
+ SelStart=CurPos;
+ }
+ else
+ {
+ SelEnd=CurPos;
+ }
+
+ SelStart=CurLine->m_prev->TabPosToReal(SelStart);
+ SelEnd=CurLine->m_prev->TabPosToReal(SelEnd);
+
+ if (!EdOpt.CursorBeyondEOL && SelEnd>CurLine->m_prev->GetLength())
+ {
+ SelEnd=CurLine->m_prev->GetLength();
+ }
+
+ if (!EdOpt.CursorBeyondEOL && SelStart>CurLine->m_prev->GetLength())
+ {
+ SelStart=CurLine->m_prev->GetLength();
+ }
+ }
+
+ CurLine->m_prev->Select(SelStart,SelEnd);
+ }
+
+ Up();
+ Show();
+ return TRUE;
+ }
+ case KEY_CTRLADD:
+ {
+ Copy(TRUE);
+ return TRUE;
+ }
+ case KEY_CTRLA:
+ {
+ UnmarkBlock();
+ SelectAll();
+ return TRUE;
+ }
+ case KEY_CTRLU:
+ {
+ UnmarkMacroBlock();
+ UnmarkBlock();
+ return TRUE;
+ }
+ case KEY_CTRLC:
+ case KEY_CTRLINS: case KEY_CTRLNUMPAD0:
+ {
+ if (/*!EdOpt.PersistentBlocks && */!BlockStart && !VBlockStart)
+ {
+ BlockStart=CurLine;
+ BlockStartLine=NumLine;
+ CurLine->AddSelect(0,-1);
+ Show();
+ }
+
+ Copy(FALSE);
+ return TRUE;
+ }
+ case KEY_CTRLP:
+ case KEY_CTRLM:
+ {
+ if (Flags.Check(FEDITOR_LOCKMODE))
+ return TRUE;
+
+ if (BlockStart || VBlockStart)
+ {
+ int SelStart,SelEnd;
+ CurLine->GetSelection(SelStart,SelEnd);
+ Pasting++;
+ bool OldUseInternalClipboard=Clipboard::SetUseInternalClipboardState(true);
+ ProcessKey(Key==KEY_CTRLP ? KEY_CTRLINS:KEY_SHIFTDEL);
+
+ /* $ 10.04.2001 SVS
+ ^P/^M - некорректно работали: уловие для CurPos должно быть ">=",
+ а не "меньше".
+ */
+ if (Key==KEY_CTRLM && SelStart!=-1 && SelEnd!=-1)
+ {
+ if (CurPos>=SelEnd)
+ CurLine->SetCurPos(CurPos-(SelEnd-SelStart));
+ else
+ CurLine->SetCurPos(CurPos);
+ }
+
+ ProcessKey(KEY_SHIFTINS);
+ Pasting--;
+ EmptyInternalClipboard();
+ Clipboard::SetUseInternalClipboardState(OldUseInternalClipboard);
+ /*$ 08.02.2001 SKV
+ всё делалось с pasting'ом, поэтому redraw плагинам не ушел.
+ сделаем его.
+ */
+ Show();
+ }
+
+ return TRUE;
+ }
+ case KEY_CTRLX:
+ case KEY_SHIFTDEL:
+ case KEY_SHIFTNUMDEL:
+ case KEY_SHIFTDECIMAL:
+ {
+ Copy(FALSE);
+ }
+ case KEY_CTRLD:
+ {
+ if (Flags.Check(FEDITOR_LOCKMODE))
+ return TRUE;
+
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+ DeleteBlock();
+ Show();
+ return TRUE;
+ }
+ case KEY_CTRLV:
+ case KEY_SHIFTINS: case KEY_SHIFTNUMPAD0:
+ {
+ ProcessPasteEvent();
+ return TRUE;
+ }
+ case KEY_LEFT: case KEY_NUMPAD4:
+ {
+ Flags.Set(FEDITOR_NEWUNDO);
+
+ if (!CurPos && CurLine->m_prev)
+ {
+ Up();
+ Show();
+ CurLine->ProcessKey(KEY_END);
+ Show();
+ }
+ else
+ {
+ int LeftPos=CurLine->GetLeftPos();
+ CurLine->ProcessKey(KEY_LEFT);
+ ShowEditor(LeftPos==CurLine->GetLeftPos());
+ }
+
+ return TRUE;
+ }
+ case KEY_INS: case KEY_NUMPAD0:
+ {
+ Flags.Swap(FEDITOR_OVERTYPE);
+ Show();
+ return TRUE;
+ }
+ case KEY_NUMDEL:
+ case KEY_DEL:
+ {
+ if (!Flags.Check(FEDITOR_LOCKMODE))
+ {
+ // Del в самой последней позиции ничего не удаляет, поэтому не модифицируем...
+ if (!CurLine->m_next && CurPos>=CurLine->GetLength() && !BlockStart && !VBlockStart)
+ return TRUE;
+
+ /* $ 07.03.2002 IS
+ Снимем выделение, если блок все равно пустой
+ */
+ if (!Pasting)
+ UnmarkEmptyBlock();
+
+ if (!Pasting && EdOpt.DelRemovesBlocks && (BlockStart || VBlockStart))
+ DeleteBlock();
+ else
+ {
+ if (CurPos>=CurLine->GetLength())
+ {
+ AddUndoData(UNDO_BEGIN);
+ AddUndoData(UNDO_EDIT,CurLine->GetStringAddr(),CurLine->GetEOL(),NumLine,CurLine->GetCurPos(),CurLine->GetLength());
+
+ if (!CurLine->m_next)
+ CurLine->SetEOL(L"");
+ else
+ {
+ int SelStart,SelEnd,NextSelStart,NextSelEnd;
+ int Length=CurLine->GetLength();
+ CurLine->GetSelection(SelStart,SelEnd);
+ CurLine->m_next->GetSelection(NextSelStart,NextSelEnd);
+ const wchar_t *Str;
+ int NextLength;
+ CurLine->m_next->GetBinaryString(&Str,nullptr,NextLength);
+ CurLine->InsertBinaryString(Str,NextLength);
+ CurLine->SetEOL(CurLine->m_next->GetEOL());
+ CurLine->SetCurPos(CurPos);
+ DeleteString(CurLine->m_next,NumLine+1,TRUE,NumLine+1);
+
+ if (!NextLength)
+ CurLine->SetEOL(L"");
+
+ if (NextSelStart!=-1)
+ {
+ if (SelStart==-1)
+ {
+ CurLine->Select(Length+NextSelStart,NextSelEnd==-1 ? -1:Length+NextSelEnd);
+ BlockStart=CurLine;
+ BlockStartLine=NumLine;
+ }
+ else
+ CurLine->Select(SelStart,NextSelEnd==-1 ? -1:Length+NextSelEnd);
+ }
+ }
+
+ AddUndoData(UNDO_END);
+ }
+ else
+ {
+ AddUndoData(UNDO_EDIT,CurLine->GetStringAddr(),CurLine->GetEOL(),NumLine,CurLine->GetCurPos(),CurLine->GetLength());
+ CurLine->ProcessKey(KEY_DEL);
+ }
+
+ TextChanged(1);
+ }
+
+ Show();
+ }
+
+ return TRUE;
+ }
+ case KEY_BS:
+ {
+ if (!Flags.Check(FEDITOR_LOCKMODE))
+ {
+ // Bs в самом начале нихрена ничего не удаляет, посему не будем выставлять
+ if (!CurLine->m_prev && !CurPos && !BlockStart && !VBlockStart)
+ return TRUE;
+
+ TextChanged(1);
+ int IsDelBlock=FALSE;
+
+ if (EdOpt.BSLikeDel)
+ {
+ if (!Pasting && EdOpt.DelRemovesBlocks && (BlockStart || (VBlockStart && /* #279 */ VBlockSizeX > 0 && VBlockSizeY > 0)) )
+ IsDelBlock=TRUE;
+ }
+ else
+ {
+ if (!Pasting && !EdOpt.PersistentBlocks && BlockStart)
+ IsDelBlock=TRUE;
+ }
+
+ if (IsDelBlock)
+ DeleteBlock();
+ else if (!CurPos && CurLine->m_prev)
+ {
+ Pasting++;
+ Up();
+ CurLine->ProcessKey(KEY_CTRLEND);
+ ProcessKey(KEY_DEL);
+ Pasting--;
+ }
+ else
+ {
+ AddUndoData(UNDO_EDIT,CurLine->GetStringAddr(),CurLine->GetEOL(),NumLine,CurLine->GetCurPos(),CurLine->GetLength());
+ CurLine->ProcessKey(KEY_BS);
+ }
+
+ Show();
+ }
+
+ return TRUE;
+ }
+ case KEY_CTRLBS:
+ {
+ if (!Flags.Check(FEDITOR_LOCKMODE))
+ {
+ TextChanged(1);
+
+ if (!Pasting && !EdOpt.PersistentBlocks && BlockStart)
+ DeleteBlock();
+ else if (!CurPos && CurLine->m_prev)
+ ProcessKey(KEY_BS);
+ else
+ {
+ AddUndoData(UNDO_EDIT,CurLine->GetStringAddr(),CurLine->GetEOL(),NumLine,CurLine->GetCurPos(),CurLine->GetLength());
+ CurLine->ProcessKey(KEY_CTRLBS);
+ }
+
+ Show();
+ }
+
+ return TRUE;
+ }
+ case KEY_UP: case KEY_NUMPAD8:
+ {
+ {
+ Flags.Set(FEDITOR_NEWUNDO);
+ int PrevMaxPos=MaxRightPos;
+ Edit *LastTopScreen=TopScreen;
+ Up();
+
+ if (TopScreen==LastTopScreen)
+ ShowEditor(TRUE);
+ else
+ Show();
+
+ if (PrevMaxPos>CurLine->GetTabCurPos())
+ {
+ CurLine->SetTabCurPos(PrevMaxPos);
+ CurLine->FastShow();
+ CurLine->SetTabCurPos(PrevMaxPos);
+ Show();
+ }
+ }
+ return TRUE;
+ }
+ case KEY_DOWN: case KEY_NUMPAD2:
+ {
+ {
+ Flags.Set(FEDITOR_NEWUNDO);
+ int PrevMaxPos=MaxRightPos;
+ Edit *LastTopScreen=TopScreen;
+ Down();
+
+ if (TopScreen==LastTopScreen)
+ ShowEditor(TRUE);
+ else
+ Show();
+
+ if (PrevMaxPos>CurLine->GetTabCurPos())
+ {
+ CurLine->SetTabCurPos(PrevMaxPos);
+ CurLine->FastShow();
+ CurLine->SetTabCurPos(PrevMaxPos);
+ Show();
+ }
+ }
+ return TRUE;
+ }
+ case KEY_MSWHEEL_UP:
+ case(KEY_MSWHEEL_UP | KEY_ALT):
+ {
+ int Roll = Key & KEY_ALT?1:Opt.MsWheelDeltaEdit;
+
+ for (int i=0; i<Roll; i++)
+ ProcessKey(KEY_CTRLUP);
+
+ return TRUE;
+ }
+ case KEY_MSWHEEL_DOWN:
+ case(KEY_MSWHEEL_DOWN | KEY_ALT):
+ {
+ int Roll = Key & KEY_ALT?1:Opt.MsWheelDeltaEdit;
+
+ for (int i=0; i<Roll; i++)
+ ProcessKey(KEY_CTRLDOWN);
+
+ return TRUE;
+ }
+ case KEY_MSWHEEL_LEFT:
+ case(KEY_MSWHEEL_LEFT | KEY_ALT):
+ {
+ int Roll = Key & KEY_ALT?1:Opt.MsHWheelDeltaEdit;
+
+ for (int i=0; i<Roll; i++)
+ ProcessKey(KEY_LEFT);
+
+ return TRUE;
+ }
+ case KEY_MSWHEEL_RIGHT:
+ case(KEY_MSWHEEL_RIGHT | KEY_ALT):
+ {
+ int Roll = Key & KEY_ALT?1:Opt.MsHWheelDeltaEdit;
+
+ for (int i=0; i<Roll; i++)
+ ProcessKey(KEY_RIGHT);
+
+ return TRUE;
+ }
+ case KEY_CTRLUP: case KEY_CTRLNUMPAD8:
+ {
+ Flags.Set(FEDITOR_NEWUNDO);
+ ScrollUp();
+ Show();
+ return TRUE;
+ }
+ case KEY_CTRLDOWN: case KEY_CTRLNUMPAD2:
+ {
+ Flags.Set(FEDITOR_NEWUNDO);
+ ScrollDown();
+ Show();
+ return TRUE;
+ }
+ case KEY_PGUP: case KEY_NUMPAD9:
+ {
+ Flags.Set(FEDITOR_NEWUNDO);
+
+ for (I=Y1; I<Y2; I++)
+ ScrollUp();
+
+ Show();
+ return TRUE;
+ }
+ case KEY_PGDN: case KEY_NUMPAD3:
+ {
+ Flags.Set(FEDITOR_NEWUNDO);
+
+ for (I=Y1; I<Y2; I++)
+ ScrollDown();
+
+ Show();
+ return TRUE;
+ }
+ case KEY_CTRLHOME: case KEY_CTRLNUMPAD7:
+ case KEY_CTRLPGUP: case KEY_CTRLNUMPAD9:
+ {
+ {
+ Flags.Set(FEDITOR_NEWUNDO);
+ int StartPos=CurLine->GetTabCurPos();
+ NumLine=0;
+ TopScreen=CurLine=TopList;
+
+ if (Key == KEY_CTRLHOME || Key == KEY_CTRLNUMPAD7)
+ CurLine->SetCurPos(0);
+ else
+ CurLine->SetTabCurPos(StartPos);
+
+ Show();
+ }
+ return TRUE;
+ }
+ case KEY_CTRLEND: case KEY_CTRLNUMPAD1:
+ case KEY_CTRLPGDN: case KEY_CTRLNUMPAD3:
+ {
+ {
+ Flags.Set(FEDITOR_NEWUNDO);
+ int StartPos=CurLine->GetTabCurPos();
+ NumLine=NumLastLine-1;
+ CurLine=EndList;
+
+ for (TopScreen=CurLine,I=Y1; I<Y2 && TopScreen->m_prev; I++)
+ {
+ TopScreen->SetPosition(X1,I,XX2,I);
+ TopScreen=TopScreen->m_prev;
+ }
+
+ CurLine->SetLeftPos(0);
+
+ if (Key == KEY_CTRLEND || Key == KEY_CTRLNUMPAD1)
+ {
+ CurLine->SetCurPos(CurLine->GetLength());
+ CurLine->FastShow();
+ }
+ else
+ CurLine->SetTabCurPos(StartPos);
+
+ Show();
+ }
+ return TRUE;
+ }
+ case KEY_NUMENTER:
+ case KEY_ENTER:
+ {
+ if (Pasting || !ShiftPressed || CtrlObject->Macro.IsExecuting())
+ {
+ if (!Pasting && !EdOpt.PersistentBlocks && BlockStart)
+ DeleteBlock();
+
+ Flags.Set(FEDITOR_NEWUNDO);
+ InsertString();
+ CurLine->FastShow();
+ Show();
+ }
+
+ return TRUE;
+ }
+ case KEY_CTRLN:
+ {
+ Flags.Set(FEDITOR_NEWUNDO);
+
+ while (CurLine!=TopScreen)
+ {
+ CurLine=CurLine->m_prev;
+ NumLine--;
+ }
+
+ CurLine->SetCurPos(CurPos);
+ Show();
+ return TRUE;
+ }
+ case KEY_CTRLE:
+ {
+ {
+ Flags.Set(FEDITOR_NEWUNDO);
+ Edit *CurPtr=TopScreen;
+ int CurLineFound=FALSE;
+
+ for (I=Y1; I<Y2; I++)
+ {
+ if (!CurPtr->m_next)
+ break;
+
+ if (CurPtr==CurLine)
+ CurLineFound=TRUE;
+
+ if (CurLineFound)
+ NumLine++;
+
+ CurPtr=CurPtr->m_next;
+ }
+
+ CurLine=CurPtr;
+ CurLine->SetCurPos(CurPos);
+ Show();
+ }
+ return TRUE;
+ }
+ case KEY_CTRLL:
+ {
+ Flags.Swap(FEDITOR_LOCKMODE);
+
+ if (HostFileEditor) HostFileEditor->ShowStatus();
+
+ return TRUE;
+ }
+ case KEY_CTRLY:
+ {
+ DeleteString(CurLine,NumLine,FALSE,NumLine);
+ Show();
+ return TRUE;
+ }
+ case KEY_F7:
+ {
+ int ReplaceMode0=ReplaceMode;
+ int ReplaceAll0=ReplaceAll;
+ ReplaceMode=ReplaceAll=FALSE;
+
+ if (!Search(FALSE))
+ {
+ ReplaceMode=ReplaceMode0;
+ ReplaceAll=ReplaceAll0;
+ }
+
+ return TRUE;
+ }
+ case KEY_CTRLF7:
+ {
+ if (!Flags.Check(FEDITOR_LOCKMODE))
+ {
+ int ReplaceMode0=ReplaceMode;
+ int ReplaceAll0=ReplaceAll;
+ ReplaceMode=TRUE;
+ ReplaceAll=FALSE;
+
+ if (!Search(FALSE))
+ {
+ ReplaceMode=ReplaceMode0;
+ ReplaceAll=ReplaceAll0;
+ }
+ }
+
+ return TRUE;
+ }
+ case KEY_SHIFTF7:
+ {
+ /* $ 20.09.2000 SVS
+ При All после нажатия Shift-F7 надобно снова спросить...
+ */
+ //ReplaceAll=FALSE;
+ /* $ 07.05.2001 IS
+ Сказано в хелпе "Shift-F7 Продолжить _поиск_"
+ */
+ //ReplaceMode=FALSE;
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+ Search(TRUE);
+ return TRUE;
+ }
+ case KEY_ALTF7:
+ {
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+ int LastSearchReversePrev = LastSearchReverse;
+ LastSearchReverse = !LastSearchReverse;
+ Search(TRUE);
+ LastSearchReverse = LastSearchReversePrev;
+ return TRUE;
+ }
+ /*case KEY_F8:
+ {
+ Flags.Set(FEDITOR_TABLECHANGEDBYUSER);
+ if ((AnsiText=!AnsiText))
+ {
+ int UseUnicode=FALSE;
+ GetTable(&TableSet,TRUE,TableNum,UseUnicode);
+ }
+ TableNum=0;
+ UseDecodeTable=AnsiText;
+ SetStringsTable();
+ if (HostFileEditor) HostFileEditor->ChangeEditKeyBar();
+ Show();
+ return TRUE;
+ } */ //BUGBUGBUG
+ /*case KEY_SHIFTF8:
+ {
+ {
+ int UseUnicode=FALSE;
+ int GetTableCode=GetTable(&TableSet,FALSE,TableNum,UseUnicode);
+ if (GetTableCode!=-1)
+ {
+ Flags.Set(FEDITOR_TABLECHANGEDBYUSER);
+ UseDecodeTable=GetTableCode;
+ AnsiText=FALSE;
+ SetStringsTable();
+ if (HostFileEditor) HostFileEditor->ChangeEditKeyBar();
+ Show();
+ }
+ }
+ return TRUE; //BUGBUGBUG
+ } */
+ case KEY_F11:
+ {
+ /*
+ if(!Flags.Check(FEDITOR_DIALOGMEMOEDIT))
+ {
+ CtrlObject->Plugins.CurEditor=HostFileEditor; // this;
+ if (CtrlObject->Plugins.CommandsMenu(MODALTYPE_EDITOR,0,"Editor"))
+ *PluginTitle=0;
+ Show();
+ }
+ */
+ return TRUE;
+ }
+ case KEY_CTRLSHIFTZ:
+ case KEY_ALTBS:
+ case KEY_CTRLZ:
+ {
+ if (!Flags.Check(FEDITOR_LOCKMODE))
+ {
+ Lock();
+ Undo(Key==KEY_CTRLSHIFTZ);
+ Unlock();
+ Show();
+ }
+
+ return TRUE;
+ }
+ case KEY_ALTF8:
+ {
+ {
+ GoToPosition();
+
+ // <GOTO_UNMARK:1>
+ if (!EdOpt.PersistentBlocks)
+ UnmarkBlock();
+
+ // </GOTO_UNMARK>
+ Show();
+ }
+ return TRUE;
+ }
+ case KEY_ALTU:
+ {
+ if (!Flags.Check(FEDITOR_LOCKMODE))
+ {
+ BlockLeft();
+ Show();
+ }
+
+ return TRUE;
+ }
+ case KEY_ALTI:
+ {
+ if (!Flags.Check(FEDITOR_LOCKMODE))
+ {
+ BlockRight();
+ Show();
+ }
+
+ return TRUE;
+ }
+ case KEY_ALTSHIFTLEFT: case KEY_ALTSHIFTNUMPAD4:
+ case KEY_ALTLEFT:
+ {
+ if (!CurPos)
+ return TRUE;
+
+ if (!Flags.Check(FEDITOR_MARKINGVBLOCK))
+ BeginVBlockMarking();
+
+ Pasting++;
+ {
+ int Delta=CurLine->GetTabCurPos()-CurLine->RealPosToTab(CurPos-1);
+
+ if (CurLine->GetTabCurPos()>VBlockX)
+ VBlockSizeX-=Delta;
+ else
+ {
+ VBlockX-=Delta;
+ VBlockSizeX+=Delta;
+ }
+
+ /* $ 25.07.2000 tran
+ остатки бага 22 - подправка при перебега за границу блока */
+ if (VBlockSizeX<0)
+ {
+ VBlockSizeX=-VBlockSizeX;
+ VBlockX-=VBlockSizeX;
+ }
+
+ ProcessKey(KEY_LEFT);
+ }
+ Pasting--;
+ Show();
+ //_D(SysLog(L"VBlockX=%i, VBlockSizeX=%i, GetLineCurPos=%i",VBlockX,VBlockSizeX,GetLineCurPos()));
+ //_D(SysLog(L"~~~~~~~~~~~~~~~~ KEY_ALTLEFT END, VBlockY=%i:%i, VBlockX=%i:%i",VBlockY,VBlockSizeY,VBlockX,VBlockSizeX));
+ return TRUE;
+ }
+ case KEY_ALTSHIFTRIGHT: case KEY_ALTSHIFTNUMPAD6:
+ case KEY_ALTRIGHT:
+ {
+ /* $ 23.10.2000 tran
+ вместо GetTabCurPos надо вызывать GetCurPos -
+ сравнивать реальную позицию с реальной длиной
+ а было сравнение видимой позицией с реальной длиной*/
+ if (!EdOpt.CursorBeyondEOL && CurLine->GetCurPos()>=CurLine->GetLength())
+ return TRUE;
+
+ if (!Flags.Check(FEDITOR_MARKINGVBLOCK))
+ BeginVBlockMarking();
+
+ //_D(SysLog(L"---------------- KEY_ALTRIGHT, getLineCurPos=%i",GetLineCurPos()));
+ Pasting++;
+ {
+ int Delta;
+ /* $ 18.07.2000 tran
+ встань в начало текста, нажми alt-right, alt-pagedown,
+ выделится блок шириной в 1 колонку, нажми еще alt-right
+ выделение сбросится
+ */
+ int VisPos=CurLine->RealPosToTab(CurPos),
+ NextVisPos=CurLine->RealPosToTab(CurPos+1);
+ //_D(SysLog(L"CurPos=%i, VisPos=%i, NextVisPos=%i",
+ // CurPos,VisPos, NextVisPos); //,CurLine->GetTabCurPos()));
+ Delta=NextVisPos-VisPos;
+ //_D(SysLog(L"Delta=%i",Delta));
+
+ if (CurLine->GetTabCurPos()>=VBlockX+VBlockSizeX)
+ VBlockSizeX+=Delta;
+ else
+ {
+ VBlockX+=Delta;
+ VBlockSizeX-=Delta;
+ }
+
+ /* $ 25.07.2000 tran
+ остатки бага 22 - подправка при перебега за границу блока */
+ if (VBlockSizeX<0)
+ {
+ VBlockSizeX=-VBlockSizeX;
+ VBlockX-=VBlockSizeX;
+ }
+
+ ProcessKey(KEY_RIGHT);
+ //_D(SysLog(L"VBlockX=%i, VBlockSizeX=%i, GetLineCurPos=%i",VBlockX,VBlockSizeX,GetLineCurPos()));
+ }
+ Pasting--;
+ Show();
+ //_D(SysLog(L"~~~~~~~~~~~~~~~~ KEY_ALTRIGHT END, VBlockY=%i:%i, VBlockX=%i:%i",VBlockY,VBlockSizeY,VBlockX,VBlockSizeX));
+ return TRUE;
+ }
+ /* $ 29.06.2000 IG
+ + CtrlAltLeft, CtrlAltRight для вертикальный блоков
+ */
+ case KEY_CTRLALTLEFT: case KEY_CTRLALTNUMPAD4:
+ {
+ {
+ int SkipSpace=TRUE;
+ Pasting++;
+ Lock();
+
+ for (;;)
+ {
+ const wchar_t *Str;
+ int Length;
+ CurLine->GetBinaryString(&Str,nullptr,Length);
+ int CurPos=CurLine->GetCurPos();
+
+ if (CurPos>Length)
+ {
+ CurLine->ProcessKey(KEY_END);
+ CurPos=CurLine->GetCurPos();
+ }
+
+ if (!CurPos)
+ break;
+
+ if (IsSpace(Str[CurPos-1]) || IsWordDiv(EdOpt.strWordDiv,Str[CurPos-1]))
+ {
+ if (SkipSpace)
+ {
+ ProcessKey(KEY_ALTSHIFTLEFT);
+ continue;
+ }
+ else
+ break;
+ }
+
+ SkipSpace=FALSE;
+ ProcessKey(KEY_ALTSHIFTLEFT);
+ }
+
+ Pasting--;
+ Unlock();
+ Show();
+ }
+ return TRUE;
+ }
+ case KEY_CTRLALTRIGHT: case KEY_CTRLALTNUMPAD6:
+ {
+ {
+ int SkipSpace=TRUE;
+ Pasting++;
+ Lock();
+
+ for (;;)
+ {
+ const wchar_t *Str;
+ int Length;
+ CurLine->GetBinaryString(&Str,nullptr,Length);
+ int CurPos=CurLine->GetCurPos();
+
+ if (CurPos>=Length)
+ break;
+
+ if (IsSpace(Str[CurPos]) || IsWordDiv(EdOpt.strWordDiv,Str[CurPos]))
+ {
+ if (SkipSpace)
+ {
+ ProcessKey(KEY_ALTSHIFTRIGHT);
+ continue;
+ }
+ else
+ break;
+ }
+
+ SkipSpace=FALSE;
+ ProcessKey(KEY_ALTSHIFTRIGHT);
+ }
+
+ Pasting--;
+ Unlock();
+ Show();
+ }
+ return TRUE;
+ }
+ case KEY_ALTSHIFTUP: case KEY_ALTSHIFTNUMPAD8:
+ case KEY_ALTUP:
+ {
+ if (!CurLine->m_prev)
+ return TRUE;
+
+ if (!Flags.Check(FEDITOR_MARKINGVBLOCK))
+ BeginVBlockMarking();
+
+ if (!EdOpt.CursorBeyondEOL && VBlockX>=CurLine->m_prev->GetLength())
+ return TRUE;
+
+ Pasting++;
+
+ if (NumLine>VBlockY)
+ VBlockSizeY--;
+ else
+ {
+ VBlockY--;
+ VBlockSizeY++;
+ VBlockStart=VBlockStart->m_prev;
+ BlockStartLine--;
+ }
+
+ ProcessKey(KEY_UP);
+ AdjustVBlock(CurVisPos);
+ Pasting--;
+ Show();
+ //_D(SysLog(L"~~~~~~~~ ALT_PGUP, VBlockY=%i:%i, VBlockX=%i:%i",VBlockY,VBlockSizeY,VBlockX,VBlockSizeX));
+ return TRUE;
+ }
+ case KEY_ALTSHIFTDOWN: case KEY_ALTSHIFTNUMPAD2:
+ case KEY_ALTDOWN:
+ {
+ if (!CurLine->m_next)
+ return TRUE;
+
+ if (!Flags.Check(FEDITOR_MARKINGVBLOCK))
+ BeginVBlockMarking();
+
+ if (!EdOpt.CursorBeyondEOL && VBlockX>=CurLine->m_next->GetLength())
+ return TRUE;
+
+ Pasting++;
+
+ if (NumLine>=VBlockY+VBlockSizeY-1)
+ VBlockSizeY++;
+ else
+ {
+ VBlockY++;
+ VBlockSizeY--;
+ VBlockStart=VBlockStart->m_next;
+ BlockStartLine++;
+ }
+
+ ProcessKey(KEY_DOWN);
+ AdjustVBlock(CurVisPos);
+ Pasting--;
+ Show();
+ //_D(SysLog(L"~~~~ Key_AltDOWN: VBlockY=%i:%i, VBlockX=%i:%i",VBlockY,VBlockSizeY,VBlockX,VBlockSizeX));
+ return TRUE;
+ }
+ case KEY_ALTSHIFTHOME: case KEY_ALTSHIFTNUMPAD7:
+ case KEY_ALTHOME:
+ {
+ Pasting++;
+ Lock();
+
+ while (CurLine->GetCurPos()>0)
+ ProcessKey(KEY_ALTSHIFTLEFT);
+
+ Unlock();
+ Pasting--;
+ Show();
+ return TRUE;
+ }
+ case KEY_ALTSHIFTEND: case KEY_ALTSHIFTNUMPAD1:
+ case KEY_ALTEND:
+ {
+ Pasting++;
+ Lock();
+
+ if (CurLine->GetCurPos()<CurLine->GetLength())
+ while (CurLine->GetCurPos()<CurLine->GetLength())
+ ProcessKey(KEY_ALTSHIFTRIGHT);
+
+ if (CurLine->GetCurPos()>CurLine->GetLength())
+ while (CurLine->GetCurPos()>CurLine->GetLength())
+ ProcessKey(KEY_ALTSHIFTLEFT);
+
+ Unlock();
+ Pasting--;
+ Show();
+ return TRUE;
+ }
+ case KEY_ALTSHIFTPGUP: case KEY_ALTSHIFTNUMPAD9:
+ case KEY_ALTPGUP:
+ {
+ Pasting++;
+ Lock();
+
+ for (I=Y1; I<Y2; I++)
+ ProcessKey(KEY_ALTSHIFTUP);
+
+ Unlock();
+ Pasting--;
+ Show();
+ return TRUE;
+ }
+ case KEY_ALTSHIFTPGDN: case KEY_ALTSHIFTNUMPAD3:
+ case KEY_ALTPGDN:
+ {
+ Pasting++;
+ Lock();
+
+ for (I=Y1; I<Y2; I++)
+ ProcessKey(KEY_ALTSHIFTDOWN);
+
+ Unlock();
+ Pasting--;
+ Show();
+ return TRUE;
+ }
+ case KEY_CTRLALTPGUP: case KEY_CTRLALTNUMPAD9:
+ case KEY_CTRLALTHOME: case KEY_CTRLALTNUMPAD7:
+ {
+ Lock();
+ Pasting++;
+
+ while (CurLine!=TopList)
+ {
+ ProcessKey(KEY_ALTUP);
+ }
+
+ Pasting--;
+ Unlock();
+ Show();
+ return TRUE;
+ }
+ case KEY_CTRLALTPGDN: case KEY_CTRLALTNUMPAD3:
+ case KEY_CTRLALTEND: case KEY_CTRLALTNUMPAD1:
+ {
+ Lock();
+ Pasting++;
+
+ while (CurLine!=EndList)
+ {
+ ProcessKey(KEY_ALTDOWN);
+ }
+
+ Pasting--;
+ Unlock();
+ Show();
+ return TRUE;
+ }
+ case KEY_CTRLALTBRACKET: // Вставить сетевое (UNC) путь из левой панели
+ case KEY_CTRLALTBACKBRACKET: // Вставить сетевое (UNC) путь из правой панели
+ case KEY_ALTSHIFTBRACKET: // Вставить сетевое (UNC) путь из активной панели
+ case KEY_ALTSHIFTBACKBRACKET: // Вставить сетевое (UNC) путь из пассивной панели
+ case KEY_CTRLBRACKET: // Вставить путь из левой панели
+ case KEY_CTRLBACKBRACKET: // Вставить путь из правой панели
+ case KEY_CTRLSHIFTBRACKET: // Вставить путь из активной панели
+ case KEY_CTRLSHIFTBACKBRACKET: // Вставить путь из пассивной панели
+ case KEY_CTRLSHIFTNUMENTER:
+ case KEY_SHIFTNUMENTER:
+ case KEY_CTRLSHIFTENTER:
+ case KEY_SHIFTENTER:
+ {
+ if (!Flags.Check(FEDITOR_LOCKMODE))
+ {
+ Pasting++;
+ AddUndoData(UNDO_BEGIN);
+ TextChanged(1);
+
+ if (!EdOpt.PersistentBlocks && BlockStart)
+ {
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+ DeleteBlock();
+ }
+
+ AddUndoData(UNDO_EDIT,CurLine->GetStringAddr(),CurLine->GetEOL(),NumLine,CurLine->GetCurPos(),CurLine->GetLength());
+ CurLine->ProcessKey(Key);
+ Pasting--;
+ AddUndoData(UNDO_END);
+ Show();
+ }
+
+ return TRUE;
+ }
+ case KEY_CTRLQ:
+ {
+ if (!Flags.Check(FEDITOR_LOCKMODE))
+ {
+ Flags.Set(FEDITOR_PROCESSCTRLQ);
+
+ if (HostFileEditor) HostFileEditor->ShowStatus();
+
+ Pasting++;
+ TextChanged(1);
+
+ if (!EdOpt.PersistentBlocks && BlockStart)
+ {
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+ DeleteBlock();
+ }
+
+ AddUndoData(UNDO_EDIT,CurLine->GetStringAddr(),CurLine->GetEOL(),NumLine,CurLine->GetCurPos(),CurLine->GetLength());
+ CurLine->ProcessCtrlQ();
+ Flags.Clear(FEDITOR_PROCESSCTRLQ);
+ Pasting--;
+ Show();
+ }
+
+ return TRUE;
+ }
+ case KEY_OP_SELWORD:
+ {
+ int OldCurPos=CurPos;
+ int SStart, SEnd;
+ Pasting++;
+ Lock();
+ UnmarkBlock();
+
+ // CurLine->TableSet ??? => UseDecodeTable?CurLine->TableSet:nullptr !!!
+ if (CalcWordFromString(CurLine->GetStringAddr(),CurPos,&SStart,&SEnd,EdOpt.strWordDiv))
+ {
+ CurLine->Select(SStart,SEnd+(SEnd < CurLine->StrSize?1:0));
+
+ if (CurLine->IsSelection())
+ {
+ Flags.Set(FEDITOR_MARKINGBLOCK);
+ BlockStart=CurLine;
+ BlockStartLine=NumLine;
+ //SelFirst=TRUE;
+ SelStart=SStart;
+ SelEnd=SEnd;
+ //CurLine->ProcessKey(MCODE_OP_SELWORD);
+ }
+ }
+
+ CurPos=OldCurPos; // возвращаем обратно
+ Pasting--;
+ Unlock();
+ Show();
+ return TRUE;
+ }
+ case KEY_OP_PLAINTEXT:
+ {
+ if (!Flags.Check(FEDITOR_LOCKMODE))
+ {
+ const wchar_t *Fmt = eStackAsString();
+ FARString strTStr;
+
+ strTStr = Fmt;
+
+ wchar_t *Ptr=strTStr.GetBuffer();
+
+ while (*Ptr) // заменим L'\n' на L'\r' по правилам Paset ;-)
+ {
+ if (*Ptr == L'\n')
+ *Ptr=L'\r';
+
+ ++Ptr;
+ }
+
+ strTStr.ReleaseBuffer();
+ Pasting++;
+ //_SVS(SysLogDump(Fmt,0,TStr,strlen(TStr),nullptr));
+ TextChanged(1);
+ BOOL IsBlock=VBlockStart || BlockStart;
+
+ if (!EdOpt.PersistentBlocks && IsBlock)
+ {
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+ DeleteBlock();
+ }
+
+ //AddUndoData(UNDO_EDIT,CurLine->GetStringAddr(),CurLine->GetEOL(),NumLine,CurLine->GetCurPos(),CurLine->GetLength());
+ Paste(strTStr);
+ //if (!EdOpt.PersistentBlocks && IsBlock)
+ UnmarkBlock();
+ Pasting--;
+ Show();
+ }
+
+ return TRUE;
+ }
+ default:
+ {
+ {
+ if ((Key==KEY_CTRLDEL || Key==KEY_CTRLNUMDEL || Key==KEY_CTRLDECIMAL || Key==KEY_CTRLT) && CurPos>=CurLine->GetLength())
+ {
+ /*$ 08.12.2000 skv
+ - CTRL-DEL в начале строки при выделенном блоке и
+ включенном EditorDelRemovesBlocks
+ */
+ int save=EdOpt.DelRemovesBlocks;
+ EdOpt.DelRemovesBlocks=0;
+ int ret=ProcessKey(KEY_DEL);
+ EdOpt.DelRemovesBlocks=save;
+ return ret;
+ }
+
+ if (!Pasting && !EdOpt.PersistentBlocks && BlockStart)
+ if ((Key>=32 && Key<0x10000) || Key==KEY_ADD || Key==KEY_SUBTRACT || // ??? 256 ???
+ Key==KEY_MULTIPLY || Key==KEY_DIVIDE || Key==KEY_TAB)
+ {
+ DeleteBlock();
+ /* $ 19.09.2002 SKV
+ Однако надо.
+ Иначе есди при надичии выделения набирать
+ текст с шифтом флаги не сбросятся и следующий
+ выделенный блок будет глючный.
+ */
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+ Show();
+ }
+
+ int SkipCheckUndo=(Key==KEY_RIGHT || Key==KEY_NUMPAD6 ||
+ Key==KEY_CTRLLEFT || Key==KEY_CTRLNUMPAD4 ||
+ Key==KEY_CTRLRIGHT || Key==KEY_CTRLNUMPAD6 ||
+ Key==KEY_HOME || Key==KEY_NUMPAD7 ||
+ Key==KEY_END || Key==KEY_NUMPAD1 ||
+ Key==KEY_CTRLS);
+
+ if (Flags.Check(FEDITOR_LOCKMODE) && !SkipCheckUndo)
+ return TRUE;
+
+ if ((Key==KEY_CTRLLEFT || Key==KEY_CTRLNUMPAD4) && !CurLine->GetCurPos())
+ {
+ Pasting++;
+ ProcessKey(KEY_LEFT);
+ Pasting--;
+ /* $ 24.9.2001 SKV
+ fix бага с ctrl-left в начале строки
+ в блоке с переопределённым плагином фоном.
+ */
+ ShowEditor(FALSE);
+ //if(!Flags.Check(FEDITOR_DIALOGMEMOEDIT)){
+ //CtrlObject->Plugins.CurEditor=HostFileEditor; // this;
+ //_D(SysLog(L"%08d EE_REDRAW",__LINE__));
+ //CtrlObject->Plugins.ProcessEditorEvent(EE_REDRAW,EEREDRAW_ALL);
+ //}
+ return TRUE;
+ }
+
+ if (((!EdOpt.CursorBeyondEOL && (Key==KEY_RIGHT || Key==KEY_NUMPAD6)) || Key==KEY_CTRLRIGHT || Key==KEY_CTRLNUMPAD6) &&
+ CurLine->GetCurPos()>=CurLine->GetLength() &&
+ CurLine->m_next)
+ {
+ Pasting++;
+ ProcessKey(KEY_HOME);
+ ProcessKey(KEY_DOWN);
+ Pasting--;
+
+ if (!Flags.Check(FEDITOR_DIALOGMEMOEDIT))
+ {
+ CtrlObject->Plugins.CurEditor=HostFileEditor; // this;
+ //_D(SysLog(L"%08d EE_REDRAW",__LINE__));
+ _SYS_EE_REDRAW(SysLog(L"Editor::ProcessKey[%d](!EdOpt.CursorBeyondEOL): EE_REDRAW(EEREDRAW_ALL)",__LINE__));
+ CtrlObject->Plugins.ProcessEditorEvent(EE_REDRAW,EEREDRAW_ALL);
+ }
+
+ /*$ 03.02.2001 SKV
+ А то EEREDRAW_ALL то уходит, а на самом деле
+ только текущая линия перерисовывается.
+ */
+ ShowEditor(0);
+ return TRUE;
+ }
+
+ const wchar_t *Str;
+
+ wchar_t *CmpStr=0;
+
+ int Length,CurPos;
+
+ CurLine->GetBinaryString(&Str,nullptr,Length);
+
+ CurPos=CurLine->GetCurPos();
+
+ if (Key<0x10000 && CurPos>0 && !Length)
+ {
+ Edit *PrevLine=CurLine->m_prev;
+
+ while (PrevLine && !PrevLine->GetLength())
+ PrevLine=PrevLine->m_prev;
+
+ if (PrevLine)
+ {
+ int TabPos=CurLine->GetTabCurPos();
+ CurLine->SetCurPos(0);
+ const wchar_t *PrevStr=nullptr;
+ int PrevLength=0;
+ PrevLine->GetBinaryString(&PrevStr,nullptr,PrevLength);
+
+ for (int I=0; I<PrevLength && IsSpace(PrevStr[I]); I++)
+ {
+ int NewTabPos=CurLine->GetTabCurPos();
+
+ if (NewTabPos==TabPos)
+ break;
+
+ if (NewTabPos>TabPos)
+ {
+ CurLine->ProcessKey(KEY_BS);
+
+ while (CurLine->GetTabCurPos()<TabPos)
+ CurLine->ProcessKey(' ');
+
+ break;
+ }
+
+ if (NewTabPos<TabPos)
+ CurLine->ProcessKey(PrevStr[I]);
+ }
+
+ CurLine->SetTabCurPos(TabPos);
+ }
+ }
+
+ if (!SkipCheckUndo)
+ {
+ CurLine->GetBinaryString(&Str,nullptr,Length);
+ CurPos=CurLine->GetCurPos();
+ CmpStr=new wchar_t[Length+1];
+ wmemcpy(CmpStr,Str,Length);
+ CmpStr[Length]=0;
+ }
+
+ int LeftPos=CurLine->GetLeftPos();
+
+ if (Key == KEY_OP_XLAT)
+ {
+ Xlat();
+ Show();
+ delete[] CmpStr;
+ return TRUE;
+ }
+
+ // <comment> - это требуется для корректной работы логики блоков для Ctrl-K
+ int PreSelStart,PreSelEnd;
+ CurLine->GetSelection(PreSelStart,PreSelEnd);
+ // </comment>
+ //AY: Это что бы при FastShow LeftPos не становился в конец строки.
+ CurLine->ObjWidth=XX2-X1+1;
+
+ if (CurLine->ProcessKey(Key))
+ {
+ int SelStart,SelEnd;
+
+ /* $ 17.09.2002 SKV
+ Если находимся в середине блока,
+ в начале строки, и нажимаем tab, который заменяется
+ на пробелы, выделение съедет. Это фикс.
+ */
+ if (Key==KEY_TAB && CurLine->GetConvertTabs() &&
+ BlockStart && BlockStart!=CurLine)
+ {
+ CurLine->GetSelection(SelStart,SelEnd);
+ CurLine->Select(SelStart==-1?-1:0,SelEnd);
+ }
+
+ if (!SkipCheckUndo)
+ {
+ const wchar_t *NewCmpStr;
+ int NewLength;
+ CurLine->GetBinaryString(&NewCmpStr,nullptr,NewLength);
+
+ if (NewLength!=Length || memcmp(CmpStr,NewCmpStr,Length*sizeof(wchar_t)))
+ {
+ AddUndoData(UNDO_EDIT,CmpStr,CurLine->GetEOL(),NumLine,CurPos,Length); // EOL? - CurLine->GetEOL() GlobalEOL ""
+ TextChanged(1);
+ }
+
+ delete[] CmpStr;
+ }
+
+ // <Bug 794>
+ // обработаем только первую и последнюю строку с блоком
+ if (Key == KEY_CTRLK && EdOpt.PersistentBlocks)
+ {
+ if (CurLine==BlockStart)
+ {
+ if (CurPos)
+ {
+ CurLine->GetSelection(SelStart,SelEnd);
+
+ // 1. блок за концом строки (CurPos был ближе к началу, чем SelStart)
+ if ((SelEnd == -1 && PreSelStart > CurPos) || SelEnd > CurPos)
+ SelStart=SelEnd=-1; // в этом случае снимаем выделение
+
+ // 2. CurPos внутри блока
+ else if (SelEnd == -1 && PreSelEnd > CurPos && SelStart < CurPos)
+ SelEnd=PreSelEnd; // в этом случае усекаем блок
+
+ // 3. блок остался слева от CurPos или выделение нужно снять (см. выше)
+ if (SelEnd >= CurPos || SelStart==-1)
+ CurLine->Select(SelStart,CurPos);
+ }
+ else
+ {
+ CurLine->Select(-1,-1);
+ BlockStart=BlockStart->m_next;
+ }
+ }
+ else // ЗДЕСЬ ЗАСАДА !!! ЕСЛИ ВЫДЕЛЕННЫЙ БЛОК ДОСТАТОЧНО БОЛЬШОЙ (ПО СТРОКАМ), ТО ЦИКЛ ПЕРЕБОРА... МОЖЕТ ЗАТЯНУТЬ...
+ {
+ // найдем эту последнюю строку (и последняя ли она)
+ Edit *CurPtrBlock=BlockStart,*CurPtrBlock2=BlockStart;
+
+ while (CurPtrBlock)
+ {
+ CurPtrBlock->GetRealSelection(SelStart,SelEnd);
+
+ if (SelStart==-1)
+ break;
+
+ CurPtrBlock2=CurPtrBlock;
+ CurPtrBlock=CurPtrBlock->m_next;
+ }
+
+ if (CurLine==CurPtrBlock2)
+ {
+ if (CurPos)
+ {
+ CurLine->GetSelection(SelStart,SelEnd);
+ CurLine->Select(SelStart,CurPos);
+ }
+ else
+ {
+ CurLine->Select(-1,-1);
+ CurPtrBlock2=CurPtrBlock2->m_next;
+ }
+ }
+ }
+ }
+
+ // </Bug 794>
+ ShowEditor(LeftPos==CurLine->GetLeftPos());
+ return TRUE;
+ }
+ else if (!SkipCheckUndo)
+ delete[] CmpStr;
+
+ if (VBlockStart)
+ Show();
+ }
+ return FALSE;
+ }
+ }
+}
+
+
+int Editor::ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent)
+{
+ Edit *NewPtr;
+ int NewDist,Dist;
+
+
+ // Shift + Mouse click -> adhoc quick edit
+ if ( (MouseEvent->dwControlKeyState & SHIFT_PRESSED) != 0
+ && (MouseEvent->dwEventFlags & MOUSE_MOVED) == 0
+ && (MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) != 0 ) {
+ WINPORT(BeginConsoleAdhocQuickEdit)();
+ return TRUE;
+ }
+
+ // $ 28.12.2000 VVM - Щелчок мышкой снимает непостоянный блок всегда
+ if ((MouseEvent->dwButtonState & 3))
+ {
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+
+ if ((!EdOpt.PersistentBlocks) && (BlockStart || VBlockStart))
+ {
+ UnmarkBlock();
+ Show();
+ }
+ }
+
+ if (EdOpt.ShowScrollBar && MouseEvent->dwMousePosition.X==X2 && !(MouseEvent->dwEventFlags & MOUSE_MOVED))
+ {
+ if (MouseEvent->dwMousePosition.Y==Y1)
+ {
+ while (IsMouseButtonPressed())
+ {
+ ProcessKey(KEY_CTRLUP);
+ }
+ }
+ else if (MouseEvent->dwMousePosition.Y==Y2)
+ {
+ while (IsMouseButtonPressed())
+ {
+ ProcessKey(KEY_CTRLDOWN);
+ }
+ }
+ else
+ {
+ while (IsMouseButtonPressed())
+ GoToLine((NumLastLine-1)*(MouseY-Y1)/(Y2-Y1));
+ }
+
+ return TRUE;
+ }
+
+ if (MouseEvent->dwButtonState&FROM_LEFT_1ST_BUTTON_PRESSED)
+ {
+ static int EditorPrevDoubleClick=0;
+ static COORD EditorPrevPosition={0,0};
+
+ if (WINPORT(GetTickCount)()-EditorPrevDoubleClick<=WINPORT(GetDoubleClickTime)() && MouseEvent->dwEventFlags!=MOUSE_MOVED &&
+ EditorPrevPosition.X == MouseEvent->dwMousePosition.X && EditorPrevPosition.Y == MouseEvent->dwMousePosition.Y)
+ {
+ CurLine->Select(0,CurLine->StrSize);
+
+ if (CurLine->IsSelection())
+ {
+ Flags.Set(FEDITOR_MARKINGBLOCK);
+ BlockStart=CurLine;
+ BlockStartLine=NumLine;
+ }
+
+ EditorPrevDoubleClick=0;
+ EditorPrevPosition.X=0;
+ EditorPrevPosition.Y=0;
+ }
+
+ if (MouseEvent->dwEventFlags==DOUBLE_CLICK)
+ {
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+
+ if (BlockStart || VBlockStart)
+ UnmarkBlock();
+
+ ProcessKey(KEY_OP_SELWORD);
+ EditorPrevDoubleClick=WINPORT(GetTickCount)();
+ EditorPrevPosition=MouseEvent->dwMousePosition;
+ }
+ else
+ {
+ EditorPrevDoubleClick=0;
+ EditorPrevPosition.X=0;
+ EditorPrevPosition.Y=0;
+ }
+
+ Show();
+ }
+
+ if (MouseEvent->dwButtonState == FROM_LEFT_2ND_BUTTON_PRESSED
+ && (MouseEvent->dwEventFlags & (DOUBLE_CLICK | MOUSE_MOVED | MOUSE_HWHEELED | MOUSE_WHEELED)) == 0)
+ {
+ ProcessPasteEvent();
+ }
+
+ if (CurLine->ProcessMouse(MouseEvent))
+ {
+ if (HostFileEditor) HostFileEditor->ShowStatus();
+
+ if (VBlockStart)
+ Show();
+ else
+ {
+ if (!Flags.Check(FEDITOR_DIALOGMEMOEDIT))
+ {
+ CtrlObject->Plugins.CurEditor=HostFileEditor; // this;
+ _SYS_EE_REDRAW(SysLog(L"Editor::ProcessMouse[%08d] ProcessEditorEvent(EE_REDRAW,EEREDRAW_LINE)",__LINE__));
+ CtrlObject->Plugins.ProcessEditorEvent(EE_REDRAW,EEREDRAW_LINE);
+ }
+ }
+
+ return TRUE;
+ }
+
+ if (!(MouseEvent->dwButtonState & 3))
+ return FALSE;
+
+ // scroll up
+ if (MouseEvent->dwMousePosition.Y==Y1-1)
+ {
+ while (IsMouseButtonPressed() && MouseY==Y1-1)
+ ProcessKey(KEY_UP);
+
+ return TRUE;
+ }
+
+ // scroll down
+ if (MouseEvent->dwMousePosition.Y==Y2+1)
+ {
+ while (IsMouseButtonPressed() && MouseY==Y2+1)
+ ProcessKey(KEY_DOWN);
+
+ return TRUE;
+ }
+
+ if (MouseEvent->dwMousePosition.X<X1 || MouseEvent->dwMousePosition.X>X2 ||
+ MouseEvent->dwMousePosition.Y<Y1 || MouseEvent->dwMousePosition.Y>Y2)
+ return FALSE;
+
+ NewDist=MouseEvent->dwMousePosition.Y-Y1;
+ NewPtr=TopScreen;
+
+ while (NewDist-- && NewPtr->m_next)
+ NewPtr=NewPtr->m_next;
+
+ Dist=CalcDistance(TopScreen,NewPtr,-1)-CalcDistance(TopScreen,CurLine,-1);
+
+ if (Dist>0)
+ while (Dist--)
+ Down();
+ else
+ while (Dist++)
+ Up();
+
+ CurLine->ProcessMouse(MouseEvent);
+ Show();
+ return TRUE;
+}
+
+
+int Editor::CalcDistance(Edit *From, Edit *To,int MaxDist)
+{
+ int Distance=0;
+
+ while (From!=To && From->m_next && (MaxDist==-1 || MaxDist-- > 0))
+ {
+ Distance++;
+ From=From->m_next;
+ }
+
+ return(Distance);
+}
+
+
+
+void Editor::DeleteString(Edit *DelPtr, int LineNumber, int DeleteLast,int UndoLine)
+{
+ if (Flags.Check(FEDITOR_LOCKMODE))
+ return;
+
+ /* $ 16.12.2000 OT
+ CtrlY на последней строке с выделенным вертикальным блоком не снимал выделение */
+ if (VBlockStart && NumLine<VBlockY+VBlockSizeY)
+ {
+ if (NumLine<VBlockY)
+ {
+ if (VBlockY>0)
+ {
+ VBlockY--;
+ BlockStartLine--;
+ }
+ }
+ else if (--VBlockSizeY<=0)
+ VBlockStart=nullptr;
+ }
+
+ TextChanged(1);
+
+ if (!DelPtr->m_next && (!DeleteLast || !DelPtr->m_prev))
+ {
+ AddUndoData(UNDO_EDIT,DelPtr->GetStringAddr(),DelPtr->GetEOL(),UndoLine,DelPtr->GetCurPos(),DelPtr->GetLength());
+ DelPtr->SetString(L"");
+ return;
+ }
+
+ for (size_t I=0; I<ARRAYSIZE(SavePos.Line); I++)
+ if (SavePos.Line[I]!=POS_NONE && UndoLine<static_cast<int>(SavePos.Line[I]))
+ SavePos.Line[I]--;
+
+ if (StackPos)
+ {
+ InternalEditorStackBookMark *sb_temp = StackPos, *sb_new;
+
+ while (sb_temp->prev)
+ sb_temp=sb_temp->prev;
+
+ while (sb_temp)
+ {
+ sb_new = sb_temp->next;
+
+ if (UndoLine < static_cast<int>(sb_temp->Line))
+ sb_temp->Line--;
+ else
+ {
+ if (UndoLine == static_cast<int>(sb_temp->Line))
+ DeleteStackBookmark(sb_temp);
+ }
+
+ sb_temp = sb_new;
+ }
+ }
+
+ NumLastLine--;
+
+ if(LastGetLine)
+ {
+ if(LineNumber<=LastGetLineNumber)
+ {
+ if(LineNumber==LastGetLineNumber)
+ {
+ LastGetLine=LastGetLine->m_prev;
+ }
+ LastGetLineNumber--;
+ }
+ }
+
+ if (CurLine==DelPtr)
+ {
+ int LeftPos,CurPos;
+ CurPos=DelPtr->GetTabCurPos();
+ LeftPos=DelPtr->GetLeftPos();
+
+ if (DelPtr->m_next)
+ CurLine=DelPtr->m_next;
+ else
+ {
+ CurLine=DelPtr->m_prev;
+ /* $ 04.11.2002 SKV
+ Вроде как если это произошло, номер текущей строки надо изменить.
+ */
+ NumLine--;
+ }
+
+ CurLine->SetLeftPos(LeftPos);
+ CurLine->SetTabCurPos(CurPos);
+ }
+
+ if (DelPtr->m_prev)
+ {
+ DelPtr->m_prev->m_next=DelPtr->m_next;
+
+ if (DelPtr==EndList)
+ EndList=EndList->m_prev;
+ }
+
+ if (DelPtr->m_next)
+ DelPtr->m_next->m_prev=DelPtr->m_prev;
+
+ if (DelPtr==TopScreen)
+ {
+ if (TopScreen->m_next)
+ TopScreen=TopScreen->m_next;
+ else
+ TopScreen=TopScreen->m_prev;
+ }
+
+ if (DelPtr==TopList)
+ TopList=TopList->m_next;
+
+ if (DelPtr==BlockStart)
+ {
+ BlockStart=BlockStart->m_next;
+
+ // Mantis#0000316: Не работает копирование строки
+ if (BlockStart && !BlockStart->IsSelection())
+ BlockStart=nullptr;
+ }
+
+ if (DelPtr==VBlockStart)
+ VBlockStart=VBlockStart->m_next;
+
+ if (UndoLine!=-1)
+ AddUndoData(UNDO_DELSTR,DelPtr->GetStringAddr(),DelPtr->GetEOL(),UndoLine,0,DelPtr->GetLength());
+
+ delete DelPtr;
+}
+
+
+void Editor::InsertString()
+{
+ if (Flags.Check(FEDITOR_LOCKMODE))
+ return;
+
+ /*$ 10.08.2000 skv
+ There is only one return - if new will fail.
+ In this case things are realy bad.
+ Move TextChanged to the end of functions
+ AFTER all modifications are made.
+ */
+// TextChanged(1);
+ Edit *NewString;
+ Edit *SrcIndent=nullptr;
+ int SelStart,SelEnd;
+ int CurPos;
+ int NewLineEmpty=TRUE;
+ NewString = InsertString(nullptr, 0, CurLine, NumLine);
+
+ if (!NewString)
+ return;
+
+ //NewString->SetTables(UseDecodeTable ? &TableSet:nullptr); // ??
+ int Length;
+ const wchar_t *CurLineStr;
+ const wchar_t *EndSeq;
+ CurLine->GetBinaryString(&CurLineStr,&EndSeq,Length);
+
+ /* $ 13.01.2002 IS
+ Если не был определен тип конца строки, то считаем что конец строки
+ у нас равен DOS_EOL_fmt и установим его явно.
+ */
+ if (!*EndSeq)
+ CurLine->SetEOL(*GlobalEOL?GlobalEOL:NATIVE_EOLW);
+
+ CurPos=CurLine->GetCurPos();
+ CurLine->GetSelection(SelStart,SelEnd);
+
+ for (size_t I=0; I<ARRAYSIZE(SavePos.Line); I++)
+ if (SavePos.Line[I]!=POS_NONE &&
+ (NumLine<(int)SavePos.Line[I] || (NumLine==(int)SavePos.Line[I] && !CurPos)))
+ SavePos.Line[I]++;
+
+ if (StackPos)
+ {
+ InternalEditorStackBookMark *sb_temp = StackPos;
+
+ while (sb_temp->prev)
+ sb_temp=sb_temp->prev;
+
+ while (sb_temp)
+ {
+ if (NumLine < static_cast<int>(sb_temp->Line) || (NumLine==static_cast<int>(sb_temp->Line) && !CurPos))
+ sb_temp->Line++;
+
+ sb_temp=sb_temp->next;
+ }
+ }
+
+ int IndentPos=0;
+
+ if (EdOpt.AutoIndent && !Pasting)
+ {
+ Edit *PrevLine=CurLine;
+
+ while (PrevLine)
+ {
+ const wchar_t *Str;
+ int Length,Found=FALSE;
+ PrevLine->GetBinaryString(&Str,nullptr,Length);
+
+ for (int I=0; I<Length; I++)
+ if (!IsSpace(Str[I]))
+ {
+ PrevLine->SetCurPos(I);
+ IndentPos=PrevLine->GetTabCurPos();
+ SrcIndent=PrevLine;
+ Found=TRUE;
+ break;
+ }
+
+ if (Found)
+ break;
+
+ PrevLine=PrevLine->m_prev;
+ }
+ }
+
+ int SpaceOnly=TRUE;
+
+ if (CurPos<Length)
+ {
+ if (IndentPos>0)
+ for (int I=0; I<CurPos; I++)
+ if (!IsSpace(CurLineStr[I]))
+ {
+ SpaceOnly=FALSE;
+ break;
+ }
+
+ NewString->SetBinaryString(&CurLineStr[CurPos],Length-CurPos);
+
+ for (int i0=0; i0<Length-CurPos; i0++)
+ {
+ if (!IsSpace(CurLineStr[i0+CurPos]))
+ {
+ NewLineEmpty=FALSE;
+ break;
+ }
+ }
+
+ AddUndoData(UNDO_BEGIN);
+ AddUndoData(UNDO_EDIT,CurLine->GetStringAddr(),CurLine->GetEOL(),NumLine,
+ CurLine->GetCurPos(),CurLine->GetLength());
+ AddUndoData(UNDO_INSSTR,nullptr,EndList==CurLine?L"":GlobalEOL,NumLine+1,0); // EOL? - CurLine->GetEOL() GlobalEOL ""
+ AddUndoData(UNDO_END);
+ wchar_t *NewCurLineStr = (wchar_t *) malloc((CurPos+1)*sizeof(wchar_t));
+
+ if (!NewCurLineStr)
+ return;
+
+ wmemcpy(NewCurLineStr,CurLineStr,CurPos);
+ NewCurLineStr[CurPos]=0;
+ int StrSize=CurPos;
+
+ if (EdOpt.AutoIndent && NewLineEmpty)
+ {
+ RemoveTrailingSpaces(NewCurLineStr);
+ StrSize=StrLength(NewCurLineStr);
+ }
+
+ CurLine->SetBinaryString(NewCurLineStr,StrSize);
+ CurLine->SetEOL(EndSeq);
+ free(NewCurLineStr);
+ }
+ else
+ {
+ NewString->SetString(L"");
+ AddUndoData(UNDO_INSSTR,nullptr,L"",NumLine+1,0);// EOL? - CurLine->GetEOL() GlobalEOL ""
+ }
+
+ if (VBlockStart && NumLine<VBlockY+VBlockSizeY)
+ {
+ if (NumLine<VBlockY)
+ {
+ VBlockY++;
+ BlockStartLine++;
+ }
+ else
+ VBlockSizeY++;
+ }
+
+ if (SelStart!=-1 && (SelEnd==-1 || CurPos<SelEnd))
+ {
+ if (CurPos>=SelStart)
+ {
+ CurLine->Select(SelStart,-1);
+ NewString->Select(0,SelEnd==-1 ? -1:SelEnd-CurPos);
+ }
+ else
+ {
+ CurLine->Select(-1,0);
+ NewString->Select(SelStart-CurPos,SelEnd==-1 ? -1:SelEnd-CurPos);
+ BlockStart=NewString;
+ BlockStartLine++;
+ }
+ }
+ else if (BlockStart && NumLine<BlockStartLine)
+ BlockStartLine++;
+
+ NewString->SetEOL(EndSeq);
+ CurLine->SetCurPos(0);
+
+ if (CurLine==EndList)
+ EndList=NewString;
+
+ Down();
+
+ if (IndentPos>0)
+ {
+ int OrgIndentPos=IndentPos;
+ ShowEditor(FALSE);
+ CurLine->GetBinaryString(&CurLineStr,nullptr,Length);
+
+ if (SpaceOnly)
+ {
+ int Decrement=0;
+
+ for (int I=0; I<IndentPos && I<Length; I++)
+ {
+ if (!IsSpace(CurLineStr[I]))
+ break;
+
+ if (CurLineStr[I]==L' ')
+ Decrement++;
+ else
+ {
+ int TabPos=CurLine->RealPosToTab(I);
+ Decrement+=EdOpt.TabSize - (TabPos % EdOpt.TabSize);
+ }
+ }
+
+ IndentPos-=Decrement;
+ }
+
+ if (IndentPos>0)
+ {
+ if (CurLine->GetLength() || !EdOpt.CursorBeyondEOL)
+ {
+ CurLine->ProcessKey(KEY_HOME);
+ int SaveOvertypeMode=CurLine->GetOvertypeMode();
+ CurLine->SetOvertypeMode(FALSE);
+ const wchar_t *PrevStr=nullptr;
+ int PrevLength=0;
+
+ if (SrcIndent)
+ {
+ SrcIndent->GetBinaryString(&PrevStr,nullptr,PrevLength);
+ }
+
+ for (int I=0; CurLine->GetTabCurPos()<IndentPos; I++)
+ {
+ if (SrcIndent && I<PrevLength && IsSpace(PrevStr[I]))
+ {
+ CurLine->ProcessKey(PrevStr[I]);
+ }
+ else
+ {
+ CurLine->ProcessKey(KEY_SPACE);
+ }
+ }
+
+ while (CurLine->GetTabCurPos()>IndentPos)
+ CurLine->ProcessKey(KEY_BS);
+
+ CurLine->SetOvertypeMode(SaveOvertypeMode);
+ }
+
+ CurLine->SetTabCurPos(IndentPos);
+ }
+
+ CurLine->GetBinaryString(&CurLineStr,nullptr,Length);
+ CurPos=CurLine->GetCurPos();
+
+ if (SpaceOnly)
+ {
+ int NewPos=0;
+
+ for (int I=0; I<Length; I++)
+ {
+ NewPos=I;
+
+ if (!IsSpace(CurLineStr[I]))
+ break;
+ }
+
+ if (NewPos>OrgIndentPos)
+ NewPos=OrgIndentPos;
+
+ if (NewPos>CurPos)
+ CurLine->SetCurPos(NewPos);
+ }
+ }
+
+ TextChanged(1);
+}
+
+
+
+void Editor::Down()
+{
+ //TODO: "Свертка" - если учесть "!Flags.Check(FSCROBJ_VISIBLE)", то крутить надо до следующей видимой строки
+ Edit *CurPtr;
+ int LeftPos,CurPos,Y;
+
+ if (!CurLine->m_next)
+ return;
+
+ for (Y=0,CurPtr=TopScreen; CurPtr && CurPtr!=CurLine; CurPtr=CurPtr->m_next)
+ Y++;
+
+ if (Y>=Y2-Y1)
+ TopScreen=TopScreen->m_next;
+
+ CurPos=CurLine->GetTabCurPos();
+ LeftPos=CurLine->GetLeftPos();
+ CurLine=CurLine->m_next;
+ NumLine++;
+ CurLine->SetLeftPos(LeftPos);
+ CurLine->SetTabCurPos(CurPos);
+}
+
+
+void Editor::ScrollDown()
+{
+ //TODO: "Свертка" - если учесть "!Flags.Check(FSCROBJ_VISIBLE)", то крутить надо до следующей видимой строки
+ int LeftPos,CurPos;
+
+ if (!CurLine->m_next || !TopScreen->m_next)
+ return;
+
+ if (!EdOpt.AllowEmptySpaceAfterEof && CalcDistance(TopScreen,EndList,Y2-Y1)<Y2-Y1)
+ {
+ Down();
+ return;
+ }
+
+ TopScreen=TopScreen->m_next;
+ CurPos=CurLine->GetTabCurPos();
+ LeftPos=CurLine->GetLeftPos();
+ CurLine=CurLine->m_next;
+ NumLine++;
+ CurLine->SetLeftPos(LeftPos);
+ CurLine->SetTabCurPos(CurPos);
+}
+
+
+void Editor::Up()
+{
+ //TODO: "Свертка" - если учесть "!Flags.Check(FSCROBJ_VISIBLE)", то крутить надо до следующей видимой строки
+ int LeftPos,CurPos;
+
+ if (!CurLine->m_prev)
+ return;
+
+ if (CurLine==TopScreen)
+ TopScreen=TopScreen->m_prev;
+
+ CurPos=CurLine->GetTabCurPos();
+ LeftPos=CurLine->GetLeftPos();
+ CurLine=CurLine->m_prev;
+ NumLine--;
+ CurLine->SetLeftPos(LeftPos);
+ CurLine->SetTabCurPos(CurPos);
+}
+
+
+void Editor::ScrollUp()
+{
+ //TODO: "Свертка" - если учесть "!Flags.Check(FSCROBJ_VISIBLE)", то крутить надо до следующей видимой строки
+ int LeftPos,CurPos;
+
+ if (!CurLine->m_prev)
+ return;
+
+ if (!TopScreen->m_prev)
+ {
+ Up();
+ return;
+ }
+
+ TopScreen=TopScreen->m_prev;
+ CurPos=CurLine->GetTabCurPos();
+ LeftPos=CurLine->GetLeftPos();
+ CurLine=CurLine->m_prev;
+ NumLine--;
+ CurLine->SetLeftPos(LeftPos);
+ CurLine->SetTabCurPos(CurPos);
+}
+
+/* $ 21.01.2001 SVS
+ Диалоги поиска/замены выведен из Editor::Search
+ в отдельную функцию GetSearchReplaceString
+ (файл stddlg.cpp)
+*/
+BOOL Editor::Search(int Next)
+{
+ Edit *CurPtr,*TmpPtr;
+ FARString strSearchStr, strReplaceStr;
+ static FARString strLastReplaceStr;
+ //static int LastSuccessfulReplaceMode=0;
+ FARString strMsgStr;
+ const wchar_t *TextHistoryName=L"SearchText",*ReplaceHistoryName=L"ReplaceText";
+ int CurPos,Case,WholeWords,ReverseSearch,SelectFound,Regexp,Match,NewNumLine,UserBreak;
+
+ if (Next && strLastSearchStr.IsEmpty())
+ return TRUE;
+
+ strSearchStr = strLastSearchStr;
+ strReplaceStr = strLastReplaceStr;
+ Case=LastSearchCase;
+ WholeWords=LastSearchWholeWords;
+ ReverseSearch=LastSearchReverse;
+ SelectFound=LastSearchSelFound;
+ Regexp=LastSearchRegexp;
+
+ if (!Next)
+ {
+ if (EdOpt.SearchPickUpWord)
+ {
+ int StartPickPos=-1,EndPickPos=-1;
+ const wchar_t *Ptr=CalcWordFromString(CurLine->GetStringAddr(),CurLine->GetCurPos(),&StartPickPos,&EndPickPos, GetWordDiv());
+
+ if (Ptr)
+ {
+ FARString strWord(Ptr,(size_t)EndPickPos-StartPickPos+1);
+ strSearchStr=strWord;
+ }
+ }
+
+ if (!GetSearchReplaceString(ReplaceMode,&strSearchStr,
+ &strReplaceStr,
+ TextHistoryName,ReplaceHistoryName,
+ &Case,&WholeWords,&ReverseSearch,&SelectFound,&Regexp,L"EditorSearch"))
+ return FALSE;
+ }
+
+ strLastSearchStr = strSearchStr;
+ strLastReplaceStr = strReplaceStr;
+ LastSearchCase=Case;
+ LastSearchWholeWords=WholeWords;
+ LastSearchReverse=ReverseSearch;
+ LastSearchSelFound=SelectFound;
+ LastSearchRegexp=Regexp;
+
+ if (strSearchStr.IsEmpty())
+ return TRUE;
+
+ //LastSuccessfulReplaceMode=ReplaceMode;
+
+ if (!EdOpt.PersistentBlocks || (SelectFound && !ReplaceMode))
+ UnmarkBlock();
+
+ {
+ //SaveScreen SaveScr;
+ TPreRedrawFuncGuard preRedrawFuncGuard(Editor::PR_EditorShowMsg);
+ strMsgStr=strSearchStr;
+ InsertQuote(strMsgStr);
+ SetCursorType(FALSE,-1);
+ Match=0;
+ UserBreak=0;
+ CurPos=CurLine->GetCurPos();
+ /* $ 16.10.2000 tran
+ CurPos увеличивается при следующем поиске
+ */
+ /* $ 28.11.2000 SVS
+ "О, это не ощибка - это свойство моей программы" :-)
+ Новое поведение стало подконтрольным
+ */
+ /* $ 21.12.2000 SVS
+ - В предыдущем исправлении было задано неверное условие для
+ правила EditorF7Rules
+ */
+ /* $ 10.06.2001 IS
+ - Баг: зачем-то при продолжении _обратного_ поиска прокручивались на шаг
+ _вперед_.
+ */
+
+ /* $ 09.11.2001 IS
+ проклятое место, блин.
+ опять фиксим, т.к. не соответствует заявленному
+ */
+ if (!ReverseSearch && (Next || (EdOpt.F7Rules && !ReplaceMode)))
+ CurPos++;
+
+ NewNumLine=NumLine;
+ CurPtr=CurLine;
+ DWORD StartTime=WINPORT(GetTickCount)();
+ int StartLine=NumLine;
+ wakeful W;
+
+ while (CurPtr)
+ {
+ DWORD CurTime=WINPORT(GetTickCount)();
+
+ if (CurTime-StartTime>RedrawTimeout)
+ {
+ StartTime=CurTime;
+
+ if (CheckForEscSilent())
+ {
+ if (ConfirmAbortOp())
+ {
+ UserBreak=TRUE;
+ break;
+ }
+ }
+
+ strMsgStr=strSearchStr;
+ InsertQuote(strMsgStr);
+ SetCursorType(FALSE,-1);
+ int Total=ReverseSearch?StartLine:NumLastLine-StartLine;
+ int Current=abs(NewNumLine-StartLine);
+ EditorShowMsg(MSG(MEditSearchTitle),MSG(MEditSearchingFor),strMsgStr,Current*100/Total);
+ }
+
+ int SearchLength=0;
+ FARString strReplaceStrCurrent(ReplaceMode?strReplaceStr:L"");
+
+ if (CurPtr->Search(strSearchStr,strReplaceStrCurrent,CurPos,Case,WholeWords,ReverseSearch,Regexp,&SearchLength))
+ {
+ if (SelectFound && !ReplaceMode)
+ {
+ Pasting++;
+ Lock();
+ UnmarkBlock();
+ Flags.Set(FEDITOR_MARKINGBLOCK);
+ int iFoundPos = CurPtr->GetCurPos();
+ CurPtr->Select(iFoundPos, iFoundPos+SearchLength);
+ BlockStart = CurPtr;
+ BlockStartLine = NewNumLine;
+ Unlock();
+ Pasting--;
+ }
+
+ int Skip=FALSE;
+ /* $ 24.01.2003 KM
+ ! По окончании поиска отступим от верха экрана на треть отображаемой высоты.
+ */
+ /* $ 15.04.2003 VVM
+ Отступим на четверть и проверим на перекрытие диалогом замены */
+ int FromTop=(ScrY-2)/4;
+
+ if (FromTop<0 || FromTop>=((ScrY-5)/2-2))
+ FromTop=0;
+
+ TmpPtr=CurLine=CurPtr;
+
+ for (int i=0; i<FromTop; i++)
+ {
+ if (TmpPtr->m_prev)
+ TmpPtr=TmpPtr->m_prev;
+ else
+ break;
+ }
+
+ TopScreen=TmpPtr;
+ NumLine=NewNumLine;
+ int LeftPos=CurPtr->GetLeftPos();
+ int TabCurPos=CurPtr->GetTabCurPos();
+
+ if (ObjWidth>8 && TabCurPos-LeftPos+SearchLength>ObjWidth-8)
+ CurPtr->SetLeftPos(TabCurPos+SearchLength-ObjWidth+8);
+
+ if (ReplaceMode)
+ {
+ int MsgCode=0;
+
+ if (!ReplaceAll)
+ {
+ Show();
+ SHORT CurX,CurY;
+ GetCursorPos(CurX,CurY);
+ ScrBuf.ApplyColor(CurX,CurY,CurPtr->RealPosToTab(CurPtr->TabPosToReal(CurX)+SearchLength)-1,CurY,FarColorToReal(COL_EDITORSELECTEDTEXT));
+ FARString strQSearchStr(CurPtr->GetStringAddr()+CurPtr->GetCurPos(),SearchLength), strQReplaceStr=strReplaceStrCurrent;
+ InsertQuote(strQSearchStr);
+ InsertQuote(strQReplaceStr);
+ PreRedrawItem pitem=PreRedraw.Pop();
+ MsgCode=Message(0,4,MSG(MEditReplaceTitle),MSG(MEditAskReplace),
+ strQSearchStr,MSG(MEditAskReplaceWith),strQReplaceStr,
+ MSG(MEditReplace),MSG(MEditReplaceAll),MSG(MEditSkip),MSG(MEditCancel));
+ PreRedraw.Push(pitem);
+
+ if (MsgCode==1)
+ ReplaceAll=TRUE;
+
+ if (MsgCode==2)
+ Skip=TRUE;
+
+ if (MsgCode<0 || MsgCode==3)
+ {
+ UserBreak=TRUE;
+ break;
+ }
+ }
+
+ if (!MsgCode || MsgCode==1)
+ {
+ Pasting++;
+
+ /*$ 15.08.2000 skv
+ If Replace FARString doesn't contain control symbols (tab and return),
+ processed with fast method, otherwise use improved old one.
+ */
+ if (strReplaceStrCurrent.Contains(L'\t') || strReplaceStrCurrent.Contains(L'\r'))
+ {
+ int SaveOvertypeMode=Flags.Check(FEDITOR_OVERTYPE);
+ Flags.Set(FEDITOR_OVERTYPE);
+ CurLine->SetOvertypeMode(TRUE);
+ //int CurPos=CurLine->GetCurPos();
+
+ int I=0;
+ for (; SearchLength && strReplaceStrCurrent[I]; I++,SearchLength--)
+ {
+ int Ch=strReplaceStrCurrent[I];
+
+ if (Ch==KEY_TAB)
+ {
+ Flags.Clear(FEDITOR_OVERTYPE);
+ CurLine->SetOvertypeMode(FALSE);
+ ProcessKey(KEY_DEL);
+ ProcessKey(KEY_TAB);
+ Flags.Set(FEDITOR_OVERTYPE);
+ CurLine->SetOvertypeMode(TRUE);
+ continue;
+ }
+
+ /* $ 24.05.2002 SKV
+ Если реплэйсим на Enter, то overtype не спасёт.
+ Нужно сначала удалить то, что заменяем.
+ */
+ if (Ch==L'\r')
+ {
+ ProcessKey(KEY_DEL);
+ }
+
+ if (Ch!=KEY_BS && !(Ch==KEY_DEL || Ch==KEY_NUMDEL))
+ ProcessKey(Ch);
+ }
+
+ if (!SearchLength)
+ {
+ Flags.Clear(FEDITOR_OVERTYPE);
+ CurLine->SetOvertypeMode(FALSE);
+
+ for (; strReplaceStrCurrent[I]; I++)
+ {
+ int Ch=strReplaceStrCurrent[I];
+
+ if (Ch!=KEY_BS && !(Ch==KEY_DEL || Ch==KEY_NUMDEL))
+ ProcessKey(Ch);
+ }
+ }
+ else
+ {
+ for (; SearchLength; SearchLength--)
+ {
+ ProcessKey(KEY_DEL);
+ }
+ }
+
+ int Cnt=0;
+ const wchar_t *Tmp=strReplaceStrCurrent;
+
+ while ((Tmp=wcschr(Tmp,L'\r')) )
+ {
+ Cnt++;
+ Tmp++;
+ }
+
+ if (Cnt>0)
+ {
+ CurPtr=CurLine;
+ NewNumLine+=Cnt;
+ }
+
+ Flags.Change(FEDITOR_OVERTYPE,SaveOvertypeMode);
+ }
+ else
+ {
+ /* Fast method */
+ const wchar_t *Str,*Eol;
+ int StrLen,NewStrLen;
+ int SStrLen=SearchLength,
+ RStrLen=(int)strReplaceStrCurrent.GetLength();
+ CurLine->GetBinaryString(&Str,&Eol,StrLen);
+ int EolLen=StrLength(Eol);
+ NewStrLen=StrLen;
+ NewStrLen-=SStrLen;
+ NewStrLen+=RStrLen;
+ NewStrLen+=EolLen;
+ wchar_t *NewStr=new wchar_t[NewStrLen+1];
+ int CurPos=CurLine->GetCurPos();
+ wmemcpy(NewStr,Str,CurPos);
+ wmemcpy(NewStr+CurPos,strReplaceStrCurrent,RStrLen);
+ wmemcpy(NewStr+CurPos+RStrLen,Str+CurPos+SStrLen,StrLen-CurPos-SStrLen);
+ wmemcpy(NewStr+NewStrLen-EolLen,Eol,EolLen);
+ AddUndoData(UNDO_EDIT,CurLine->GetStringAddr(),CurLine->GetEOL(),NumLine,CurLine->GetCurPos(),CurLine->GetLength());
+ CurLine->SetBinaryString(NewStr,NewStrLen);
+ CurLine->SetCurPos(CurPos+RStrLen);
+
+ if (SelectFound && !ReplaceMode)
+ {
+ UnmarkBlock();
+ Flags.Set(FEDITOR_MARKINGBLOCK);
+ CurPtr->Select(CurPos, CurPos+RStrLen);
+ BlockStart = CurPtr;
+ BlockStartLine = NewNumLine;
+ }
+
+ delete [] NewStr;
+ TextChanged(1);
+ }
+
+ /* skv$*/
+ //AY: В этом нет никакой надобности и оно приводит к не правильному
+ //позиционированию при Replace
+ //if (ReverseSearch)
+ //CurLine->SetCurPos(CurPos);
+ Pasting--;
+ }
+ }
+
+ Match=1;
+
+ if (!ReplaceMode)
+ break;
+
+ CurPos=CurLine->GetCurPos();
+
+ if (Skip)
+ if (!ReverseSearch)
+ CurPos++;
+ }
+ else
+ {
+ if (ReverseSearch)
+ {
+ CurPtr=CurPtr->m_prev;
+
+ if (!CurPtr)
+ break;
+
+ CurPos=CurPtr->GetLength();
+ NewNumLine--;
+ }
+ else
+ {
+ CurPos=0;
+ CurPtr=CurPtr->m_next;
+ NewNumLine++;
+ }
+ }
+ }
+ }
+ Show();
+
+ if (!Match && !UserBreak)
+ Message(MSG_WARNING,1,MSG(MEditSearchTitle),MSG(MEditNotFound),
+ strMsgStr,MSG(MOk));
+
+ return TRUE;
+}
+
+void Editor::Paste(const wchar_t *Src)
+{
+ if (Flags.Check(FEDITOR_LOCKMODE))
+ return;
+
+ wchar_t *ClipText=(wchar_t *)Src;
+ BOOL IsDeleteClipText=FALSE;
+
+ if (!ClipText)
+ {
+ Clipboard clip;
+
+ if (!clip.Open())
+ return;
+
+ bool IsVertical = false;
+ ClipText = clip.Paste(IsVertical);
+ if (ClipText && IsVertical)
+ {
+ VPaste(ClipText);
+ clip.Close();
+ return;
+ }
+
+ clip.Close();
+
+ IsDeleteClipText=TRUE;
+ }
+
+ if (ClipText && *ClipText)
+ {
+ AddUndoData(UNDO_BEGIN);
+ Flags.Set(FEDITOR_NEWUNDO);
+ TextChanged(1);
+ int SaveOvertype=Flags.Check(FEDITOR_OVERTYPE);
+ UnmarkBlock();
+ Pasting++;
+ Lock();
+
+ if (Flags.Check(FEDITOR_OVERTYPE))
+ {
+ Flags.Clear(FEDITOR_OVERTYPE);
+ CurLine->SetOvertypeMode(FALSE);
+ }
+
+ BlockStart=CurLine;
+ BlockStartLine=NumLine;
+ /* $ 19.05.2001 IS
+ Решение проблемы непрошеной конвертации табуляции (которая должна быть
+ добавлена в начало строки при автоотступе) в пробелы.
+ */
+ int StartPos=CurLine->GetCurPos();
+ int oldAutoIndent=EdOpt.AutoIndent;
+
+ for (int I=0; ClipText[I];)
+ {
+ if (ClipText[I]==L'\n' || ClipText[I]==L'\r')
+ {
+ CurLine->Select(StartPos,-1);
+ StartPos=0;
+ EdOpt.AutoIndent=FALSE;
+ ProcessKey(KEY_ENTER);
+
+ if (ClipText[I]==L'\r' && ClipText[I+1]==L'\n')
+ I++;
+
+ I++;
+ }
+ else
+ {
+ if (EdOpt.AutoIndent) // первый символ вставим так, чтобы
+ { // сработал автоотступ
+ //ProcessKey(UseDecodeTable?TableSet.DecodeTable[(unsigned)ClipText[I]]:ClipText[I]); //BUGBUG
+ ProcessKey(ClipText[I]); //BUGBUG
+ I++;
+ StartPos=CurLine->GetCurPos();
+
+ if (StartPos) StartPos--;
+ }
+
+ int Pos=I;
+
+ while (ClipText[Pos] && ClipText[Pos]!=L'\n' && ClipText[Pos]!=L'\r')
+ Pos++;
+
+ if (Pos>I)
+ {
+ const wchar_t *Str;
+ int Length,CurPos;
+ CurLine->GetBinaryString(&Str,nullptr,Length);
+ CurPos=CurLine->GetCurPos();
+ AddUndoData(UNDO_EDIT,Str,CurLine->GetEOL(),NumLine,CurPos,Length); // EOL? - CurLine->GetEOL() GlobalEOL ""
+ CurLine->InsertBinaryString(&ClipText[I],Pos-I);
+ }
+
+ I=Pos;
+ }
+ }
+
+ EdOpt.AutoIndent=oldAutoIndent;
+ CurLine->Select(StartPos,CurLine->GetCurPos());
+ /* IS $ */
+
+ if (SaveOvertype)
+ {
+ Flags.Set(FEDITOR_OVERTYPE);
+ CurLine->SetOvertypeMode(TRUE);
+ }
+
+ Pasting--;
+ Unlock();
+ AddUndoData(UNDO_END);
+ }
+
+ if (IsDeleteClipText)
+ free(ClipText);
+}
+
+
+void Editor::Copy(int Append)
+{
+ if (VBlockStart)
+ {
+ VCopy(Append);
+ return;
+ }
+
+ wchar_t *CopyData=nullptr;
+
+ Clipboard clip;
+
+ if (!clip.Open())
+ return;
+
+ if (Append)
+ CopyData=clip.Paste();
+
+ if ((CopyData=Block2Text(CopyData)) )
+ {
+ clip.Copy(CopyData);
+ free(CopyData);
+ }
+
+ clip.Close();
+}
+
+wchar_t *Editor::Block2Text(wchar_t *ptrInitData)
+{
+ size_t DataSize=0;
+
+ if (ptrInitData)
+ DataSize = wcslen(ptrInitData);
+
+ size_t TotalChars = DataSize;
+ int StartSel, EndSel;
+ for (Edit *Ptr = BlockStart; Ptr; Ptr = Ptr->m_next)
+ {
+ Ptr->GetSelection(StartSel, EndSel);
+ if (StartSel == -1)
+ break;
+ if (EndSel == -1)
+ {
+ TotalChars += Ptr->GetLength() - StartSel;
+ TotalChars += wcslen(NATIVE_EOLW); // CRLF
+ }
+ else
+ TotalChars += EndSel - StartSel;
+ }
+ TotalChars++; // '\0'
+
+ wchar_t *CopyData=(wchar_t *)malloc(TotalChars*sizeof(wchar_t));
+
+ if (!CopyData)
+ {
+ if (ptrInitData)
+ free(ptrInitData);
+
+ return nullptr;
+ }
+
+ if (ptrInitData)
+ {
+ wcscpy(CopyData,ptrInitData);
+ free(ptrInitData);
+ }
+ else
+ {
+ *CopyData=0;
+ }
+
+ for (Edit *Ptr = BlockStart; Ptr; Ptr = Ptr->m_next)
+ {
+ Ptr->GetSelection(StartSel, EndSel);
+ if (StartSel==-1)
+ break;
+
+ int Length;
+ if (EndSel == -1)
+ Length = Ptr->GetLength() - StartSel;
+ else
+ Length = EndSel - StartSel;
+
+ Ptr->GetSelString(CopyData + DataSize, Length + 1);
+ DataSize += Length;
+
+ if (EndSel == -1)
+ {
+ wcscpy(CopyData + DataSize, NATIVE_EOLW);
+ DataSize += wcslen(NATIVE_EOLW);
+ }
+ }
+
+ return CopyData;
+}
+
+
+void Editor::DeleteBlock()
+{
+ if (Flags.Check(FEDITOR_LOCKMODE))
+ return;
+
+ if (VBlockStart)
+ {
+ DeleteVBlock();
+ return;
+ }
+
+ Edit *CurPtr=BlockStart;
+ AddUndoData(UNDO_BEGIN);
+
+ for(int i=BlockStartLine;CurPtr;i++)
+ {
+ TextChanged(1);
+ int StartSel,EndSel;
+ /* $ 17.09.2002 SKV
+ меняем на Real что б ловить выделение за концом строки.
+ */
+ CurPtr->GetRealSelection(StartSel,EndSel);
+
+ if (EndSel!=-1 && EndSel>CurPtr->GetLength())
+ EndSel=-1;
+
+ if (StartSel==-1)
+ break;
+
+ if (!StartSel && EndSel==-1)
+ {
+ Edit *NextLine=CurPtr->m_next;
+ DeleteString(CurPtr,i,FALSE,BlockStartLine);
+
+ if (BlockStartLine<NumLine)
+ NumLine--;
+
+ if (NextLine)
+ {
+ CurPtr=NextLine;
+ continue;
+ }
+ else
+ break;
+ }
+
+ int Length=CurPtr->GetLength();
+
+ if (StartSel || EndSel)
+ AddUndoData(UNDO_EDIT,CurPtr->GetStringAddr(),CurPtr->GetEOL(),BlockStartLine,CurPtr->GetCurPos(),CurPtr->GetLength());
+
+ /* $ 17.09.2002 SKV
+ опять про выделение за концом строки.
+ InsertBinaryString добавит trailing space'ов
+ */
+ if (StartSel>Length)
+ {
+ Length=StartSel;
+ CurPtr->SetCurPos(Length);
+ CurPtr->InsertBinaryString(L"",0);
+ }
+
+ const wchar_t *CurStr,*EndSeq;
+
+ CurPtr->GetBinaryString(&CurStr,&EndSeq,Length);
+
+ // дальше будет realloc, поэтому тут malloc.
+ wchar_t *TmpStr=(wchar_t*)malloc((Length+3)*sizeof(wchar_t));
+
+ wmemcpy(TmpStr,CurStr,Length);
+
+ TmpStr[Length]=0;
+
+ int DeleteNext=FALSE;
+
+ if (EndSel==-1)
+ {
+ EndSel=Length;
+
+ if (CurPtr->m_next)
+ DeleteNext=TRUE;
+ }
+
+ // wmemmove(TmpStr+StartSel,TmpStr+EndSel,StrLength(TmpStr+EndSel)+1);
+ wmemmove(TmpStr+StartSel,TmpStr+EndSel,Length-EndSel+1);
+ int CurPos=StartSel;
+ /* if (CurPos>=StartSel)
+ {
+ CurPos-=(EndSel-StartSel);
+ if (CurPos<StartSel)
+ CurPos=StartSel;
+ }
+ */
+ Length-=EndSel-StartSel;
+
+ if (DeleteNext)
+ {
+ const wchar_t *NextStr,*EndSeq;
+ int NextLength,NextStartSel,NextEndSel;
+ CurPtr->m_next->GetSelection(NextStartSel,NextEndSel);
+
+ if (NextStartSel==-1)
+ NextEndSel=0;
+
+ if (NextEndSel==-1)
+ EndSel=-1;
+ else
+ {
+ CurPtr->m_next->GetBinaryString(&NextStr,&EndSeq,NextLength);
+ NextLength-=NextEndSel;
+
+ if (NextLength>0)
+ {
+ TmpStr=(wchar_t *)realloc(TmpStr,(Length+NextLength+3)*sizeof(wchar_t));
+ wmemcpy(TmpStr+Length,NextStr+NextEndSel,NextLength);
+ Length+=NextLength;
+ }
+ }
+
+ if (CurLine==CurPtr->m_next)
+ {
+ CurLine=CurPtr;
+ NumLine--;
+ }
+
+ if (CurLine==CurPtr && CurPtr->m_next && CurPtr->m_next==TopScreen)
+ {
+ TopScreen=CurPtr;
+ }
+
+ DeleteString(CurPtr->m_next,i,FALSE,BlockStartLine+1);
+
+ if (BlockStartLine+1<NumLine)
+ NumLine--;
+ }
+
+ int EndLength=StrLength(EndSeq);
+ wmemcpy(TmpStr+Length,EndSeq,EndLength);
+ Length+=EndLength;
+ CurPtr->SetBinaryString(TmpStr,Length);
+ free(TmpStr);
+ CurPtr->SetCurPos(CurPos);
+
+ if (DeleteNext && EndSel==-1)
+ {
+ CurPtr->Select(CurPtr->GetLength(),-1);
+ }
+ else
+ {
+ CurPtr->Select(-1,0);
+ CurPtr=CurPtr->m_next;
+ BlockStartLine++;
+ }
+ }
+
+ AddUndoData(UNDO_END);
+ BlockStart=nullptr;
+}
+
+
+void Editor::UnmarkBlock()
+{
+ if (!BlockStart && !VBlockStart)
+ return;
+
+ VBlockStart=nullptr;
+ _SVS(SysLog(L"[%d] Editor::UnmarkBlock()",__LINE__));
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+
+ while (BlockStart)
+ {
+ int StartSel,EndSel;
+ BlockStart->GetSelection(StartSel,EndSel);
+
+ if (StartSel==-1)
+ {
+ /* $ 24.06.2002 SKV
+ Если в текущей строки нет выделения,
+ это еще не значит что мы в конце.
+ Это может быть только начало :)
+ */
+ if (BlockStart->m_next)
+ {
+ BlockStart->m_next->GetSelection(StartSel,EndSel);
+
+ if (StartSel==-1)
+ {
+ break;
+ }
+ }
+ else
+ break;
+ }
+
+ BlockStart->Select(-1,0);
+ BlockStart=BlockStart->m_next;
+ }
+
+ BlockStart=nullptr;
+ Show();
+}
+
+/* $ 07.03.2002 IS
+ Удалить выделение, если оно пустое (выделено ноль символов в ширину)
+*/
+void Editor::UnmarkEmptyBlock()
+{
+ _SVS(SysLog(L"[%d] Editor::UnmarkEmptyBlock()",__LINE__));
+
+ if (BlockStart || VBlockStart) // присутствует выделение
+ {
+ int Lines=0,StartSel,EndSel;
+ Edit *Block=BlockStart;
+
+ if (VBlockStart)
+ {
+ if (VBlockSizeX)
+ Lines=VBlockSizeY;
+ }
+ else while (Block) // пробегаем по всем выделенным строкам
+ {
+ Block->GetRealSelection(StartSel,EndSel);
+
+ if (StartSel==-1)
+ break;
+
+ if (StartSel!=EndSel)// выделено сколько-то символов
+ {
+ ++Lines; // увеличим счетчик непустых строк
+ break;
+ }
+
+ Block=Block->m_next;
+ }
+
+ if (!Lines) // если выделено ноль символов в ширину, то
+ UnmarkBlock(); // перестанем морочить голову и снимем выделение
+ }
+}
+
+void Editor::UnmarkMacroBlock()
+{
+ MBlockStart=nullptr;
+ MBlockStartX=-1;
+}
+
+void Editor::GoToLine(int Line)
+{
+ if (Line != NumLine)
+ {
+ bool bReverse = false;
+ int LastNumLine=NumLine;
+ int CurScrLine=CalcDistance(TopScreen,CurLine,-1);
+ int CurPos=CurLine->GetTabCurPos();
+ int LeftPos=CurLine->GetLeftPos();
+
+ if (Line < NumLine)
+ {
+ if (Line > NumLine/2)
+ {
+ bReverse = true;
+ }
+ else
+ {
+ CurLine = TopList;
+ NumLine = 0;
+ }
+ }
+ else
+ {
+ if (Line > (NumLine + (NumLastLine-NumLine)/2))
+ {
+ bReverse = true;
+ CurLine = EndList;
+ NumLine = NumLastLine-1;
+ }
+ }
+
+ if (bReverse)
+ {
+ for (; NumLine>Line && CurLine->m_prev; NumLine--)
+ CurLine=CurLine->m_prev;
+ }
+ else
+ {
+ for (; NumLine<Line && CurLine->m_next; NumLine++)
+ CurLine=CurLine->m_next;
+ }
+
+ CurScrLine+=NumLine-LastNumLine;
+
+ if (CurScrLine<0 || CurScrLine>Y2-Y1)
+ TopScreen=CurLine;
+
+ CurLine->SetLeftPos(LeftPos);
+ CurLine->SetTabCurPos(CurPos);
+ }
+
+// <GOTO_UNMARK:2>
+// if (!EdOpt.PersistentBlocks)
+// UnmarkBlock();
+// </GOTO_UNMARK>
+ Show();
+ return;
+}
+
+void Editor::GoToPosition()
+{
+ DialogBuilder Builder(MEditGoToLine, L"EditorGotoPos");
+ FARString strData;
+ Builder.AddEditField(&strData,28,L"LineNumber",DIF_FOCUS|DIF_HISTORY|DIF_USELASTHISTORY|DIF_NOAUTOCOMPLETE);
+ Builder.AddOKCancel();
+ Builder.ShowDialog();
+ if(!strData.IsEmpty())
+ {
+ int LeftPos=CurLine->GetTabCurPos()+1;
+ int CurPos=CurLine->GetCurPos();
+
+ int NewLine=0, NewCol=0;
+ GetRowCol(strData,&NewLine,&NewCol);
+ GoToLine(NewLine);
+
+ if (NewCol == -1)
+ {
+ CurLine->SetTabCurPos(CurPos);
+ CurLine->SetLeftPos(LeftPos);
+ }
+ else
+ {
+ CurLine->SetTabCurPos(NewCol);
+ }
+ Show();
+ }
+}
+
+void Editor::GetRowCol(const wchar_t *_argv,int *row,int *col)
+{
+ int x=0xffff,y;
+ int l;
+ wchar_t *argvx=0;
+ int LeftPos=CurLine->GetTabCurPos() + 1;
+ FARString strArg = _argv;
+ // что бы не оставить "врагу" выбора - только то, что мы хотим ;-)
+ // "прибьем" все внешние пробелы.
+ RemoveExternalSpaces(strArg);
+ wchar_t *argv = strArg.GetBuffer();
+ // получаем индекс вхождения любого разделителя
+ // в искомой строке
+ l=(int)wcscspn(argv,L",:;. ");
+ // если разделителя нету, то l=strlen(argv)
+
+ if (l < StrLength(argv)) // Варианты: "row,col" или ",col"?
+ {
+ argv[l]=L'\0'; // Вместо разделителя впиндюлим "конец строки" :-)
+ argvx=argv+l+1;
+ x=_wtoi(argvx);
+ }
+
+ y=_wtoi(argv);
+
+ // + переход на проценты
+ if (wcschr(argv,L'%'))
+ y=NumLastLine * y / 100;
+
+ // вычисляем относительность
+ if (argv[0]==L'-' || argv[0]==L'+')
+ y=NumLine+y+1;
+
+ if (argvx)
+ {
+ if (argvx[0]==L'-' || argvx[0]==L'+')
+ {
+ x=LeftPos+x;
+ }
+ }
+
+ strArg.ReleaseBuffer();
+ // теперь загоним результат назад
+ *row=y;
+
+ if (x!=0xffff)
+ *col=x;
+ else
+ *col=LeftPos;
+
+ (*row)--;
+
+ if (*row< 0) // если ввели ",Col"
+ *row=NumLine; // то переходим на текущую строку и колонку
+
+ (*col)--;
+
+ if (*col< -1)
+ *col=-1;
+
+ return ;
+}
+
+void Editor::AddUndoData(int Type,const wchar_t *Str,const wchar_t *Eol,int StrNum,int StrPos,int Length)
+{
+ if (Flags.Check(FEDITOR_DISABLEUNDO))
+ return;
+
+ if (StrNum==-1)
+ StrNum=NumLine;
+
+ for (EditorUndoData *u=UndoData.Next(UndoPos); u;)
+ {
+ if (u==UndoSavePos)
+ {
+ UndoSavePos=nullptr;
+ Flags.Set(FEDITOR_UNDOSAVEPOSLOST);
+ }
+
+ EditorUndoData *nu=UndoData.Next(u);
+ UndoData.Delete(u);
+ u=nu;
+ }
+
+ EditorUndoData *PrevUndo=UndoData.Last();
+
+ if (Type==UNDO_END)
+ {
+ if (PrevUndo && PrevUndo->Type!=UNDO_BEGIN)
+ PrevUndo=UndoData.Prev(PrevUndo);
+
+ if (PrevUndo && PrevUndo->Type==UNDO_BEGIN)
+ {
+ UndoData.Delete(PrevUndo);
+ UndoPos=UndoData.Last();
+
+ if (PrevUndo==UndoSavePos)
+ UndoSavePos=UndoPos;
+
+ return;
+ }
+ }
+
+ if (Type==UNDO_EDIT && !Flags.Check(FEDITOR_NEWUNDO))
+ {
+ if (PrevUndo && PrevUndo->Type==UNDO_EDIT && StrNum==PrevUndo->StrNum &&
+ (abs(StrPos-PrevUndo->StrPos)<=1 || abs(StrPos-LastChangeStrPos)<=1))
+ {
+ LastChangeStrPos=StrPos;
+ return;
+ }
+ }
+
+ Flags.Clear(FEDITOR_NEWUNDO);
+ UndoPos=UndoData.Push();
+ UndoPos->SetData(Type,Str,Eol,StrNum,StrPos,Length);
+
+ if (EdOpt.UndoSize>0)
+ {
+ while (!UndoData.Empty() && (UndoData.Count()>static_cast<size_t>(EdOpt.UndoSize) || UndoSkipLevel>0))
+ {
+ EditorUndoData *u=UndoData.First();
+
+ if (u->Type==UNDO_BEGIN)
+ ++UndoSkipLevel;
+
+ if (u->Type==UNDO_END && UndoSkipLevel>0)
+ --UndoSkipLevel;
+
+ if (!UndoSavePos)
+ Flags.Set(FEDITOR_UNDOSAVEPOSLOST);
+
+ if (u==UndoSavePos)
+ UndoSavePos=nullptr;
+
+ UndoData.Delete(u);
+ }
+
+ UndoPos=UndoData.Last();
+ }
+}
+
+void Editor::Undo(int redo)
+{
+ EditorUndoData *ustart=redo ? UndoData.Next(UndoPos) : UndoPos;
+
+ if (!ustart)
+ return;
+
+ TextChanged(1);
+ Flags.Set(FEDITOR_DISABLEUNDO);
+ int level=0;
+ EditorUndoData *uend;
+
+ for (uend=ustart; uend; uend=redo ? UndoData.Next(uend) : UndoData.Prev(uend))
+ {
+ if (uend->Type==UNDO_BEGIN || uend->Type==UNDO_END)
+ {
+ int l=uend->Type==UNDO_BEGIN ? -1 : 1;
+ level+=redo ? -l : l;
+ }
+
+ if (level<=0)
+ break;
+ }
+
+ if (level)
+ uend=ustart;
+
+ UnmarkBlock();
+ EditorUndoData *ud=ustart;
+
+ for (;;)
+ {
+ if (ud->Type!=UNDO_BEGIN && ud->Type!=UNDO_END)
+ GoToLine(ud->StrNum);
+
+ switch (ud->Type)
+ {
+ case UNDO_INSSTR:
+ ud->SetData(UNDO_DELSTR,CurLine->GetStringAddr(),CurLine->GetEOL(),ud->StrNum,ud->StrPos,CurLine->GetLength());
+ DeleteString(CurLine,NumLine,TRUE,NumLine>0 ? NumLine-1:NumLine);
+ break;
+ case UNDO_DELSTR:
+ ud->Type=UNDO_INSSTR;
+ Pasting++;
+
+ if (NumLine<ud->StrNum)
+ {
+ ProcessKey(KEY_END);
+ ProcessKey(KEY_ENTER);
+ }
+ else
+ {
+ ProcessKey(KEY_HOME);
+ ProcessKey(KEY_ENTER);
+ ProcessKey(KEY_UP);
+ }
+
+ Pasting--;
+
+ if (ud->Str)
+ {
+ CurLine->SetString(ud->Str,ud->Length);
+ CurLine->SetEOL(ud->EOL); // необходимо дополнительно выставлять, т.к. SetString вызывает Edit::SetBinaryString и... дальше по тексту
+ }
+
+ break;
+ case UNDO_EDIT:
+ {
+ EditorUndoData tmp;
+ tmp.SetData(UNDO_EDIT,CurLine->GetStringAddr(),CurLine->GetEOL(),ud->StrNum,ud->StrPos,CurLine->GetLength());
+
+ if (ud->Str)
+ {
+ CurLine->SetString(ud->Str,ud->Length);
+ CurLine->SetEOL(ud->EOL); // необходимо дополнительно выставлять, т.к. SetString вызывает Edit::SetBinaryString и... дальше по тексту
+ }
+
+ CurLine->SetCurPos(ud->StrPos);
+ ud->SetData(tmp.Type,tmp.Str,tmp.EOL,tmp.StrNum,tmp.StrPos,tmp.Length);
+ break;
+ }
+ }
+
+ if (ud==uend)
+ break;
+
+ ud=redo ? UndoData.Next(ud) : UndoData.Prev(ud);
+ }
+
+ UndoPos=redo ? ud : UndoData.Prev(ud);
+
+ if (!Flags.Check(FEDITOR_UNDOSAVEPOSLOST) && UndoPos==UndoSavePos)
+ TextChanged(0);
+
+ Flags.Clear(FEDITOR_DISABLEUNDO);
+}
+
+void Editor::SelectAll()
+{
+ Edit *CurPtr;
+ BlockStart=TopList;
+ BlockStartLine=0;
+
+ for (CurPtr=TopList; CurPtr; CurPtr=CurPtr->m_next)
+ if (CurPtr->m_next)
+ CurPtr->Select(0,-1);
+ else
+ CurPtr->Select(0,CurPtr->GetLength());
+
+ Show();
+}
+
+
+void Editor::SetStartPos(int LineNum,int CharNum)
+{
+ StartLine=LineNum? LineNum:1;
+ StartChar=CharNum? CharNum:1;
+}
+
+
+BOOL Editor::IsFileChanged() const
+{
+ return Flags.Check(FEDITOR_MODIFIED|FEDITOR_WASCHANGED);
+}
+
+
+BOOL Editor::IsFileModified() const
+{
+ return Flags.Check(FEDITOR_MODIFIED);
+}
+
+// используется в FileEditor
+long Editor::GetCurPos()
+{
+ Edit *CurPtr=TopList;
+ long TotalSize=0;
+
+ while (CurPtr!=TopScreen)
+ {
+ const wchar_t *SaveStr,*EndSeq;
+ int Length;
+ CurPtr->GetBinaryString(&SaveStr,&EndSeq,Length);
+ TotalSize+=Length+StrLength(EndSeq);
+ CurPtr=CurPtr->m_next;
+ }
+
+ return(TotalSize);
+}
+
+
+/*
+void Editor::SetStringsTable()
+{
+ Edit *CurPtr=TopList;
+ while (CurPtr)
+ {
+ CurPtr->SetTables(UseDecodeTable ? &TableSet:nullptr);
+ CurPtr=CurPtr->m_next;
+ }
+}
+*/
+
+
+void Editor::BlockLeft()
+{
+ if (VBlockStart)
+ {
+ VBlockShift(TRUE);
+ return;
+ }
+
+ Edit *CurPtr=BlockStart;
+ int LineNum=BlockStartLine;
+ /* $ 14.02.2001 VVM
+ + При отсутствии блока AltU/AltI сдвигают текущую строчку */
+ int MoveLine = 0;
+
+ if (!CurPtr)
+ {
+ MoveLine = 1;
+ CurPtr = CurLine;
+ LineNum = NumLine;
+ }
+
+ AddUndoData(UNDO_BEGIN);
+
+ while (CurPtr)
+ {
+ int StartSel,EndSel;
+ CurPtr->GetSelection(StartSel,EndSel);
+
+ /* $ 14.02.2001 VVM
+ + Блока нет - сделаем его искусственно */
+ if (MoveLine)
+ {
+ StartSel = 0; EndSel = -1;
+ }
+
+ if (StartSel==-1)
+ break;
+
+ int Length=CurPtr->GetLength();
+ wchar_t *TmpStr=new wchar_t[Length+EdOpt.TabSize+5];
+ const wchar_t *CurStr,*EndSeq;
+ CurPtr->GetBinaryString(&CurStr,&EndSeq,Length);
+ Length--;
+
+ if (*CurStr==L' ')
+ wmemcpy(TmpStr,CurStr+1,Length);
+ else if (*CurStr==L'\t')
+ {
+ wmemset(TmpStr, L' ', EdOpt.TabSize-1);
+ wmemcpy(TmpStr+EdOpt.TabSize-1,CurStr+1,Length);
+ Length+=EdOpt.TabSize-1;
+ }
+
+ if ((EndSel==-1 || EndSel>StartSel) && IsSpace(*CurStr))
+ {
+ int EndLength=StrLength(EndSeq);
+ wmemcpy(TmpStr+Length,EndSeq,EndLength);
+ Length+=EndLength;
+ TmpStr[Length]=0;
+ AddUndoData(UNDO_EDIT,CurStr,CurPtr->GetEOL(),LineNum,0,CurPtr->GetLength()); // EOL? - CurLine->GetEOL() GlobalEOL ""
+ int CurPos=CurPtr->GetCurPos();
+ CurPtr->SetBinaryString(TmpStr,Length);
+ CurPtr->SetCurPos(CurPos>0 ? CurPos-1:CurPos);
+
+ if (!MoveLine)
+ CurPtr->Select(StartSel>0 ? StartSel-1:StartSel,EndSel>0 ? EndSel-1:EndSel);
+
+ TextChanged(1);
+ }
+
+ delete[] TmpStr;
+ CurPtr=CurPtr->m_next;
+ LineNum++;
+ MoveLine = 0;
+ }
+
+ AddUndoData(UNDO_END);
+}
+
+
+void Editor::BlockRight()
+{
+ if (VBlockStart)
+ {
+ VBlockShift(FALSE);
+ return;
+ }
+
+ Edit *CurPtr=BlockStart;
+ int LineNum=BlockStartLine;
+ /* $ 14.02.2001 VVM
+ + При отсутствии блока AltU/AltI сдвигают текущую строчку */
+ int MoveLine = 0;
+
+ if (!CurPtr)
+ {
+ MoveLine = 1;
+ CurPtr = CurLine;
+ LineNum = NumLine;
+ }
+
+ AddUndoData(UNDO_BEGIN);
+
+ while (CurPtr)
+ {
+ int StartSel,EndSel;
+ CurPtr->GetSelection(StartSel,EndSel);
+
+ /* $ 14.02.2001 VVM
+ + Блока нет - сделаем его искусственно */
+ if (MoveLine)
+ {
+ StartSel = 0; EndSel = -1;
+ }
+
+ if (StartSel==-1)
+ break;
+
+ int Length=CurPtr->GetLength();
+ wchar_t *TmpStr=new wchar_t[Length+5];
+ const wchar_t *CurStr,*EndSeq;
+ CurPtr->GetBinaryString(&CurStr,&EndSeq,Length);
+ *TmpStr=L' ';
+ wmemcpy(TmpStr+1,CurStr,Length);
+ Length++;
+
+ if (EndSel==-1 || EndSel>StartSel)
+ {
+ int EndLength=StrLength(EndSeq);
+ wmemcpy(TmpStr+Length,EndSeq,EndLength);
+ TmpStr[Length+EndLength]=0;
+ AddUndoData(UNDO_EDIT,CurStr,CurPtr->GetEOL(),LineNum,0,CurPtr->GetLength()); // EOL? - CurLine->GetEOL() GlobalEOL ""
+ int CurPos=CurPtr->GetCurPos();
+
+ if (Length>1)
+ CurPtr->SetBinaryString(TmpStr,Length+EndLength);
+
+ CurPtr->SetCurPos(CurPos+1);
+
+ if (!MoveLine)
+ CurPtr->Select(StartSel>0 ? StartSel+1:StartSel,EndSel>0 ? EndSel+1:EndSel);
+
+ TextChanged(1);
+ }
+
+ delete[] TmpStr;
+ CurPtr=CurPtr->m_next;
+ LineNum++;
+ MoveLine = 0;
+ }
+
+ AddUndoData(UNDO_END);
+}
+
+
+void Editor::DeleteVBlock()
+{
+ if (Flags.Check(FEDITOR_LOCKMODE) || VBlockSizeX<=0 || VBlockSizeY<=0)
+ return;
+
+ AddUndoData(UNDO_BEGIN);
+
+ if (!EdOpt.PersistentBlocks)
+ {
+ Edit *CurPtr=CurLine;
+ Edit *NewTopScreen=TopScreen;
+
+ while (CurPtr)
+ {
+ if (CurPtr==VBlockStart)
+ {
+ TopScreen=NewTopScreen;
+ CurLine=CurPtr;
+ CurPtr->SetTabCurPos(VBlockX);
+ break;
+ }
+
+ NumLine--;
+
+ if (NewTopScreen==CurPtr && CurPtr->m_prev)
+ NewTopScreen=CurPtr->m_prev;
+
+ CurPtr=CurPtr->m_prev;
+ }
+ }
+
+ Edit *CurPtr=VBlockStart;
+
+ for (int Line=0; CurPtr && Line<VBlockSizeY; Line++,CurPtr=CurPtr->m_next)
+ {
+ TextChanged(1);
+ int TBlockX=CurPtr->TabPosToReal(VBlockX);
+ int TBlockSizeX=CurPtr->TabPosToReal(VBlockX+VBlockSizeX)-
+ CurPtr->TabPosToReal(VBlockX);
+ const wchar_t *CurStr,*EndSeq;
+ int Length;
+ CurPtr->GetBinaryString(&CurStr,&EndSeq,Length);
+
+ if (TBlockX>=Length)
+ continue;
+
+ AddUndoData(UNDO_EDIT,CurPtr->GetStringAddr(),CurPtr->GetEOL(),BlockStartLine+Line,CurPtr->GetCurPos(),CurPtr->GetLength());
+ wchar_t *TmpStr=new wchar_t[Length+3];
+ int CurLength=TBlockX;
+ wmemcpy(TmpStr,CurStr,TBlockX);
+
+ if (Length>TBlockX+TBlockSizeX)
+ {
+ int CopySize=Length-(TBlockX+TBlockSizeX);
+ wmemcpy(TmpStr+CurLength,CurStr+TBlockX+TBlockSizeX,CopySize);
+ CurLength+=CopySize;
+ }
+
+ int EndLength=StrLength(EndSeq);
+ wmemcpy(TmpStr+CurLength,EndSeq,EndLength);
+ CurLength+=EndLength;
+ int CurPos=CurPtr->GetCurPos();
+ CurPtr->SetBinaryString(TmpStr,CurLength);
+
+ if (CurPos>TBlockX)
+ {
+ CurPos-=TBlockSizeX;
+
+ if (CurPos<TBlockX)
+ CurPos=TBlockX;
+ }
+
+ CurPtr->SetCurPos(CurPos);
+ delete[] TmpStr;
+ }
+
+ AddUndoData(UNDO_END);
+ VBlockStart=nullptr;
+}
+
+void Editor::VCopy(int Append)
+{
+ wchar_t *CopyData=nullptr;
+
+ Clipboard clip;
+
+ if (!clip.Open())
+ return;
+
+ if (Append)
+ CopyData=clip.Paste();
+
+ if ((CopyData=VBlock2Text(CopyData)) )
+ {
+ clip.Copy(CopyData, true);
+ free(CopyData);
+ }
+
+ clip.Close();
+}
+
+wchar_t *Editor::VBlock2Text(wchar_t *ptrInitData)
+{
+ size_t DataSize=0;
+
+ if (ptrInitData)
+ DataSize = wcslen(ptrInitData);
+
+ //RealPos всегда <= TabPos, поэтому берём максимальный размер буффера
+ size_t TotalChars = DataSize + (VBlockSizeX + wcslen(NATIVE_EOLW)) * VBlockSizeY + 1;
+
+ wchar_t *CopyData=(wchar_t *)malloc(TotalChars*sizeof(wchar_t));
+
+ if (!CopyData)
+ {
+ if (ptrInitData)
+ free(ptrInitData);
+
+ return nullptr;
+ }
+
+ if (ptrInitData)
+ {
+ wcscpy(CopyData,ptrInitData);
+ free(ptrInitData);
+ }
+ else
+ {
+ *CopyData=0;
+ }
+
+ Edit *CurPtr=VBlockStart;
+
+ for (int Line=0; CurPtr && Line<VBlockSizeY; Line++,CurPtr=CurPtr->m_next)
+ {
+ int TBlockX=CurPtr->TabPosToReal(VBlockX);
+ int TBlockSizeX=CurPtr->TabPosToReal(VBlockX+VBlockSizeX)-TBlockX;
+ const wchar_t *CurStr,*EndSeq;
+ int Length;
+ CurPtr->GetBinaryString(&CurStr,&EndSeq,Length);
+
+ if (Length>TBlockX)
+ {
+ int CopySize=Length-TBlockX;
+
+ if (CopySize>TBlockSizeX)
+ CopySize=TBlockSizeX;
+
+ wmemcpy(CopyData+DataSize,CurStr+TBlockX,CopySize);
+
+ if (CopySize<TBlockSizeX)
+ wmemset(CopyData+DataSize+CopySize,L' ',TBlockSizeX-CopySize);
+ }
+ else
+ {
+ wmemset(CopyData+DataSize,L' ',TBlockSizeX);
+ }
+
+ DataSize+=TBlockSizeX;
+ wcscpy(CopyData+DataSize, NATIVE_EOLW);
+ DataSize+= wcslen(NATIVE_EOLW);
+ }
+
+ return CopyData;
+}
+
+
+
+void Editor::VPaste(wchar_t *ClipText)
+{
+ if (Flags.Check(FEDITOR_LOCKMODE))
+ return;
+
+ if (*ClipText)
+ {
+ AddUndoData(UNDO_BEGIN);
+ Flags.Set(FEDITOR_NEWUNDO);
+ TextChanged(1);
+ int SaveOvertype=Flags.Check(FEDITOR_OVERTYPE);
+ UnmarkBlock();
+ Pasting++;
+ Lock();
+
+ if (Flags.Check(FEDITOR_OVERTYPE))
+ {
+ Flags.Clear(FEDITOR_OVERTYPE);
+ CurLine->SetOvertypeMode(FALSE);
+ }
+
+ VBlockStart=CurLine;
+ BlockStartLine=NumLine;
+ int StartPos=CurLine->GetTabCurPos();
+ VBlockX=StartPos;
+ VBlockSizeX=0;
+ VBlockY=NumLine;
+ VBlockSizeY=0;
+ Edit *SavedTopScreen=TopScreen;
+
+ for (int I=0; ClipText[I]; I++)
+ if (ClipText[I] != '\r' && ClipText[I] != '\n')
+ {
+ ProcessKey(ClipText[I]);
+ }
+ else
+ {
+ const size_t EolLength = (ClipText[I] == '\r' || ClipText[I + 1] == '\n') ? 2 : 1;
+
+ int CurWidth=CurLine->GetTabCurPos()-StartPos;
+
+ if (CurWidth>VBlockSizeX)
+ VBlockSizeX=CurWidth;
+
+ VBlockSizeY++;
+
+ if (!CurLine->m_next)
+ {
+ if (ClipText[I + EolLength])
+ {
+ ProcessKey(KEY_END);
+ ProcessKey(KEY_ENTER);
+
+ /* $ 19.05.2001 IS
+ Не вставляем пробелы тогда, когда нас об этом не просят, а
+ именно - при включенном автоотступе ничего вставлять не нужно,
+ оно само вставится и в другом месте.
+ */
+ if (!EdOpt.AutoIndent)
+ for (int I=0; I<StartPos; I++)
+ ProcessKey(L' ');
+ }
+ }
+ else
+ {
+ ProcessKey(KEY_DOWN);
+ CurLine->SetTabCurPos(StartPos);
+ CurLine->SetOvertypeMode(FALSE);
+ }
+
+ I+= EolLength - 1;
+ continue;
+ }
+
+ int CurWidth=CurLine->GetTabCurPos()-StartPos;
+
+ if (CurWidth>VBlockSizeX)
+ VBlockSizeX=CurWidth;
+
+ if (!VBlockSizeY)
+ VBlockSizeY++;
+
+ if (SaveOvertype)
+ {
+ Flags.Set(FEDITOR_OVERTYPE);
+ CurLine->SetOvertypeMode(TRUE);
+ }
+
+ TopScreen=SavedTopScreen;
+ CurLine=VBlockStart;
+ NumLine=BlockStartLine;
+ CurLine->SetTabCurPos(StartPos);
+ Pasting--;
+ Unlock();
+ AddUndoData(UNDO_END);
+ }
+
+ free(ClipText);
+}
+
+
+void Editor::VBlockShift(int Left)
+{
+ if (Flags.Check(FEDITOR_LOCKMODE) || (Left && !VBlockX) || VBlockSizeX<=0 || VBlockSizeY<=0)
+ return;
+
+ Edit *CurPtr=VBlockStart;
+ AddUndoData(UNDO_BEGIN);
+
+ for (int Line=0; CurPtr && Line<VBlockSizeY; Line++,CurPtr=CurPtr->m_next)
+ {
+ TextChanged(1);
+ int TBlockX=CurPtr->TabPosToReal(VBlockX);
+ int TBlockSizeX=CurPtr->TabPosToReal(VBlockX+VBlockSizeX)-
+ CurPtr->TabPosToReal(VBlockX);
+ const wchar_t *CurStr,*EndSeq;
+ int Length;
+ CurPtr->GetBinaryString(&CurStr,&EndSeq,Length);
+
+ if (TBlockX>Length)
+ continue;
+
+ if ((Left && CurStr[TBlockX-1]==L'\t') ||
+ (!Left && TBlockX+TBlockSizeX<Length && CurStr[TBlockX+TBlockSizeX]==L'\t'))
+ {
+ CurPtr->ReplaceTabs();
+ CurPtr->GetBinaryString(&CurStr,&EndSeq,Length);
+ TBlockX=CurPtr->TabPosToReal(VBlockX);
+ TBlockSizeX=CurPtr->TabPosToReal(VBlockX+VBlockSizeX)-
+ CurPtr->TabPosToReal(VBlockX);
+ }
+
+ AddUndoData(UNDO_EDIT,CurPtr->GetStringAddr(),CurPtr->GetEOL(),BlockStartLine+Line,CurPtr->GetCurPos(),CurPtr->GetLength());
+ int StrLen=Max(Length,TBlockX+TBlockSizeX+!Left);
+ wchar_t *TmpStr=new wchar_t[StrLen+3];
+ wmemset(TmpStr,L' ',StrLen);
+ wmemcpy(TmpStr,CurStr,Length);
+
+ if (Left)
+ {
+ WCHAR Ch=TmpStr[TBlockX-1];
+
+ for (int I=TBlockX; I<TBlockX+TBlockSizeX; I++)
+ TmpStr[I-1]=TmpStr[I];
+
+ TmpStr[TBlockX+TBlockSizeX-1]=Ch;
+ }
+ else
+ {
+ int Ch=TmpStr[TBlockX+TBlockSizeX];
+
+ for (int I=TBlockX+TBlockSizeX-1; I>=TBlockX; I--)
+ TmpStr[I+1]=TmpStr[I];
+
+ TmpStr[TBlockX]=Ch;
+ }
+
+ while (StrLen>0 && TmpStr[StrLen-1]==L' ')
+ StrLen--;
+
+ int EndLength=StrLength(EndSeq);
+ wmemcpy(TmpStr+StrLen,EndSeq,EndLength);
+ StrLen+=EndLength;
+ CurPtr->SetBinaryString(TmpStr,StrLen);
+ delete[] TmpStr;
+ }
+
+ VBlockX+=Left ? -1:1;
+ CurLine->SetTabCurPos(Left ? VBlockX:VBlockX+VBlockSizeX);
+ AddUndoData(UNDO_END);
+}
+
+
+int Editor::EditorControl(int Command,void *Param)
+{
+ _ECTLLOG(CleverSysLog SL(L"Editor::EditorControl()"));
+ _ECTLLOG(SysLog(L"Command=%ls Param=[%d/0x%08X]",_ECTL_ToName(Command),Param,Param));
+
+ switch (Command)
+ {
+ case ECTL_GETSTRING:
+ {
+ EditorGetString *GetString=(EditorGetString *)Param;
+
+ if (GetString)
+ {
+ Edit *CurPtr=GetStringByNumber(GetString->StringNumber);
+
+ if (!CurPtr)
+ {
+ _ECTLLOG(SysLog(L"EditorGetString => GetStringByNumber(%d) return nullptr",GetString->StringNumber));
+ return FALSE;
+ }
+
+ CurPtr->GetBinaryString(const_cast<const wchar_t **>(&GetString->StringText),
+ const_cast<const wchar_t **>(&GetString->StringEOL),
+ GetString->StringLength);
+ GetString->SelStart=-1;
+ GetString->SelEnd=0;
+ int DestLine=GetString->StringNumber;
+
+ if (DestLine==-1)
+ DestLine=NumLine;
+
+ if (BlockStart)
+ {
+ CurPtr->GetRealSelection(GetString->SelStart,GetString->SelEnd);
+ }
+ else if (VBlockStart && DestLine>=VBlockY && DestLine<VBlockY+VBlockSizeY)
+ {
+ GetString->SelStart=CurPtr->TabPosToReal(VBlockX);
+ GetString->SelEnd=GetString->SelStart+
+ CurPtr->TabPosToReal(VBlockX+VBlockSizeX)-
+ CurPtr->TabPosToReal(VBlockX);
+ }
+
+ _ECTLLOG(SysLog(L"EditorGetString{"));
+ _ECTLLOG(SysLog(L" StringNumber =%d",GetString->StringNumber));
+ _ECTLLOG(SysLog(L" StringText ='%ls'",GetString->StringText));
+ _ECTLLOG(SysLog(L" StringEOL ='%ls'",GetString->StringEOL?_SysLog_LinearDump((LPBYTE)GetString->StringEOL,StrLength(GetString->StringEOL)):L"(null)"));
+ _ECTLLOG(SysLog(L" StringLength =%d",GetString->StringLength));
+ _ECTLLOG(SysLog(L" SelStart =%d",GetString->SelStart));
+ _ECTLLOG(SysLog(L" SelEnd =%d",GetString->SelEnd));
+ _ECTLLOG(SysLog(L"}"));
+ return TRUE;
+ }
+
+ break;
+ }
+ case ECTL_INSERTSTRING:
+ {
+ if (Flags.Check(FEDITOR_LOCKMODE))
+ {
+ _ECTLLOG(SysLog(L"FEDITOR_LOCKMODE!"));
+ return FALSE;
+ }
+ else
+ {
+ int Indent=Param && *(int *)Param!=FALSE;
+
+ if (!Indent)
+ Pasting++;
+
+ Flags.Set(FEDITOR_NEWUNDO);
+ InsertString();
+ Show();
+
+ if (!Indent)
+ Pasting--;
+ }
+
+ return TRUE;
+ }
+ case ECTL_INSERTTEXT:
+ {
+ if (!Param)
+ return FALSE;
+
+ _ECTLLOG(SysLog(L"(const wchar_t *)Param='%ls'",(const wchar_t *)Param));
+
+ if (Flags.Check(FEDITOR_LOCKMODE))
+ {
+ _ECTLLOG(SysLog(L"FEDITOR_LOCKMODE!"));
+ return FALSE;
+ }
+ else
+ {
+ const wchar_t *Str=(const wchar_t *)Param;
+ Pasting++;
+ Lock();
+
+ while (*Str)
+ ProcessKey(*(Str++));
+
+ Unlock();
+ Pasting--;
+ }
+
+ return TRUE;
+ }
+ case ECTL_SETSTRING:
+ {
+ EditorSetString *SetString=(EditorSetString *)Param;
+
+ if (!SetString)
+ break;
+
+ _ECTLLOG(SysLog(L"EditorSetString{"));
+ _ECTLLOG(SysLog(L" StringNumber =%d",SetString->StringNumber));
+ _ECTLLOG(SysLog(L" StringText ='%ls'",SetString->StringText));
+ _ECTLLOG(SysLog(L" StringEOL ='%ls'",SetString->StringEOL?_SysLog_LinearDump((LPBYTE)SetString->StringEOL,StrLength(SetString->StringEOL)):L"(null)"));
+ _ECTLLOG(SysLog(L" StringLength =%d",SetString->StringLength));
+ _ECTLLOG(SysLog(L"}"));
+
+ if (Flags.Check(FEDITOR_LOCKMODE))
+ {
+ _ECTLLOG(SysLog(L"FEDITOR_LOCKMODE!"));
+ break;
+ }
+ else
+ {
+ /* $ 06.08.2002 IS
+ Проверяем корректность StringLength и вернем FALSE, если оно меньше
+ нуля.
+ */
+ int Length=SetString->StringLength;
+
+ if (Length < 0)
+ {
+ _ECTLLOG(SysLog(L"SetString->StringLength < 0"));
+ return FALSE;
+ }
+
+ Edit *CurPtr=GetStringByNumber(SetString->StringNumber);
+
+ if (!CurPtr)
+ {
+ _ECTLLOG(SysLog(L"GetStringByNumber(%d) return nullptr",SetString->StringNumber));
+ return FALSE;
+ }
+
+ const wchar_t *EOL=SetString->StringEOL ? SetString->StringEOL:GlobalEOL;
+
+ int LengthEOL=StrLength(EOL);
+
+ wchar_t *NewStr=(wchar_t*)malloc((Length+LengthEOL+1)*sizeof(wchar_t));
+
+ if (!NewStr)
+ {
+ _ECTLLOG(SysLog(L"malloc(%d) return nullptr",Length+LengthEOL+1));
+ return FALSE;
+ }
+
+ int DestLine=SetString->StringNumber;
+
+ if (DestLine==-1)
+ DestLine=NumLine;
+
+ wmemcpy(NewStr,SetString->StringText,Length);
+ wmemcpy(NewStr+Length,EOL,LengthEOL);
+ AddUndoData(UNDO_EDIT,CurPtr->GetStringAddr(),CurPtr->GetEOL(),DestLine,CurPtr->GetCurPos(),CurPtr->GetLength());
+ int CurPos=CurPtr->GetCurPos();
+ CurPtr->SetBinaryString(NewStr,Length+LengthEOL);
+ CurPtr->SetCurPos(CurPos);
+ TextChanged(1); // 10.08.2000 skv - Modified->TextChanged
+ free(NewStr);
+ }
+
+ return TRUE;
+ }
+ case ECTL_DELETESTRING:
+ {
+ if (Flags.Check(FEDITOR_LOCKMODE))
+ {
+ _ECTLLOG(SysLog(L"FEDITOR_LOCKMODE!"));
+ return FALSE;
+ }
+
+ DeleteString(CurLine,NumLine,FALSE,NumLine);
+ return TRUE;
+ }
+ case ECTL_DELETECHAR:
+ {
+ if (Flags.Check(FEDITOR_LOCKMODE))
+ {
+ _ECTLLOG(SysLog(L"FEDITOR_LOCKMODE!"));
+ return FALSE;
+ }
+
+ Pasting++;
+ ProcessKey(KEY_DEL);
+ Pasting--;
+ return TRUE;
+ }
+ case ECTL_GETINFO:
+ {
+ EditorInfo *Info=(EditorInfo *)Param;
+
+ if (Info)
+ {
+ Info->EditorID=Editor::EditorID;
+ Info->WindowSizeX=ObjWidth;
+ Info->WindowSizeY=Y2-Y1+1;
+ Info->TotalLines=NumLastLine;
+ Info->CurLine=NumLine;
+ Info->CurPos=CurLine->GetCurPos();
+ Info->CurTabPos=CurLine->GetTabCurPos();
+ Info->TopScreenLine=NumLine-CalcDistance(TopScreen,CurLine,-1);
+ Info->LeftPos=CurLine->GetLeftPos();
+ Info->Overtype=Flags.Check(FEDITOR_OVERTYPE);
+ Info->BlockType=VBlockStart?BTYPE_COLUMN:BlockStart?BTYPE_STREAM:BTYPE_NONE;
+ Info->BlockStartLine=Info->BlockType==BTYPE_NONE ? 0:BlockStartLine;
+ Info->Options=0;
+
+ if (EdOpt.ExpandTabs == EXPAND_ALLTABS)
+ Info->Options|=EOPT_EXPANDALLTABS;
+
+ if (EdOpt.ExpandTabs == EXPAND_NEWTABS)
+ Info->Options|=EOPT_EXPANDONLYNEWTABS;
+
+ if (EdOpt.PersistentBlocks)
+ Info->Options|=EOPT_PERSISTENTBLOCKS;
+
+ if (EdOpt.DelRemovesBlocks)
+ Info->Options|=EOPT_DELREMOVESBLOCKS;
+
+ if (EdOpt.AutoIndent)
+ Info->Options|=EOPT_AUTOINDENT;
+
+ if (EdOpt.SavePos)
+ Info->Options|=EOPT_SAVEFILEPOSITION;
+
+ if (EdOpt.AutoDetectCodePage)
+ Info->Options|=EOPT_AUTODETECTCODEPAGE;
+
+ if (EdOpt.CursorBeyondEOL)
+ Info->Options|=EOPT_CURSORBEYONDEOL;
+
+ if (EdOpt.ShowWhiteSpace)
+ Info->Options|=EOPT_SHOWWHITESPACE;
+
+ Info->TabSize=EdOpt.TabSize;
+ Info->BookMarkCount=POSCACHE_BOOKMARK_COUNT;
+ Info->CurState=Flags.Check(FEDITOR_LOCKMODE)?ECSTATE_LOCKED:0;
+ Info->CurState|=!Flags.Check(FEDITOR_MODIFIED)?ECSTATE_SAVED:0;
+ Info->CurState|=Flags.Check(FEDITOR_MODIFIED|FEDITOR_WASCHANGED)?ECSTATE_MODIFIED:0;
+ Info->CodePage=m_codepage;
+ return TRUE;
+ }
+
+ _ECTLLOG(SysLog(L"Error: !Param"));
+ return FALSE;
+ }
+ case ECTL_SETPOSITION:
+ {
+ // "Вначале было слово..."
+ if (Param)
+ {
+ // ...а вот теперь поработаем с тем, что передалаи
+ EditorSetPosition *Pos=(EditorSetPosition *)Param;
+ _ECTLLOG(SysLog(L"EditorSetPosition{"));
+ _ECTLLOG(SysLog(L" CurLine = %d",Pos->CurLine));
+ _ECTLLOG(SysLog(L" CurPos = %d",Pos->CurPos));
+ _ECTLLOG(SysLog(L" CurTabPos = %d",Pos->CurTabPos));
+ _ECTLLOG(SysLog(L" TopScreenLine = %d",Pos->TopScreenLine));
+ _ECTLLOG(SysLog(L" LeftPos = %d",Pos->LeftPos));
+ _ECTLLOG(SysLog(L" Overtype = %d",Pos->Overtype));
+ _ECTLLOG(SysLog(L"}"));
+ Lock();
+ int CurPos=CurLine->GetCurPos();
+
+ // выставим флаг об изменении поз (если надо)
+ if ((Pos->CurLine >= 0 || Pos->CurPos >= 0)&&
+ (Pos->CurLine!=NumLine || Pos->CurPos!=CurPos))
+ Flags.Set(FEDITOR_CURPOSCHANGEDBYPLUGIN);
+
+ if (Pos->CurLine >= 0) // поменяем строку
+ {
+ if (Pos->CurLine==NumLine-1)
+ Up();
+ else if (Pos->CurLine==NumLine+1)
+ Down();
+ else
+ GoToLine(Pos->CurLine);
+ }
+
+ if (Pos->TopScreenLine >= 0 && Pos->TopScreenLine<=NumLine)
+ {
+ TopScreen=CurLine;
+
+ for (int I=NumLine; I>0 && NumLine-I<Y2-Y1 && I!=Pos->TopScreenLine; I--)
+ TopScreen=TopScreen->m_prev;
+ }
+
+ if (Pos->CurPos >= 0)
+ CurLine->SetCurPos(Pos->CurPos);
+
+ if (Pos->CurTabPos >= 0)
+ CurLine->SetTabCurPos(Pos->CurTabPos);
+
+ if (Pos->LeftPos >= 0)
+ CurLine->SetLeftPos(Pos->LeftPos);
+
+ /* $ 30.08.2001 IS
+ Изменение режима нужно выставлять сразу, в противном случае приходят
+ глюки, т.к. плагинописатель думает, что режим изменен, и ведет себя
+ соответствующе, в результате чего получает неопределенное поведение.
+ */
+ if (Pos->Overtype >= 0)
+ {
+ Flags.Change(FEDITOR_OVERTYPE,Pos->Overtype);
+ CurLine->SetOvertypeMode(Flags.Check(FEDITOR_OVERTYPE));
+ }
+
+ Unlock();
+ return TRUE;
+ }
+
+ _ECTLLOG(SysLog(L"Error: !Param"));
+ break;
+ }
+ case ECTL_SELECT:
+ {
+ if (Param)
+ {
+ EditorSelect *Sel=(EditorSelect *)Param;
+ _ECTLLOG(SysLog(L"EditorSelect{"));
+ _ECTLLOG(SysLog(L" BlockType =%ls (%d)",(Sel->BlockType==BTYPE_NONE?L"BTYPE_NONE":(Sel->BlockType==BTYPE_STREAM?L"":(Sel->BlockType==BTYPE_COLUMN?L"BTYPE_COLUMN":L"BTYPE_?????"))),Sel->BlockType));
+ _ECTLLOG(SysLog(L" BlockStartLine=%d",Sel->BlockStartLine));
+ _ECTLLOG(SysLog(L" BlockStartPos =%d",Sel->BlockStartPos));
+ _ECTLLOG(SysLog(L" BlockWidth =%d",Sel->BlockWidth));
+ _ECTLLOG(SysLog(L" BlockHeight =%d",Sel->BlockHeight));
+ _ECTLLOG(SysLog(L"}"));
+
+ if (Sel->BlockType==BTYPE_NONE || Sel->BlockStartPos==-1)
+ {
+ UnmarkBlock();
+ return TRUE;
+ }
+
+ if (Sel->BlockHeight < 1)
+ {
+ _ECTLLOG(SysLog(L"Error: EditorSelect::BlockHeight < 1"));
+ return FALSE;
+ }
+
+ Edit *CurPtr=GetStringByNumber(Sel->BlockStartLine);
+
+ if (!CurPtr)
+ {
+ _ECTLLOG(SysLog(L"Error: start line BlockStartLine=%d not found, GetStringByNumber(%d) return nullptr",Sel->BlockStartLine,Sel->BlockStartLine));
+ return FALSE;
+ }
+
+ UnmarkBlock();
+
+ if (Sel->BlockType==BTYPE_STREAM)
+ {
+ Flags.Set(FEDITOR_MARKINGBLOCK);
+ BlockStart=CurPtr;
+
+ if ((BlockStartLine=Sel->BlockStartLine) == -1)
+ BlockStartLine=NumLine;
+
+ for (int i=0; i < Sel->BlockHeight; i++)
+ {
+ int SelStart= i? 0:Sel->BlockStartPos;
+ int SelEnd = (i < Sel->BlockHeight-1) ? -1 : Sel->BlockStartPos+Sel->BlockWidth;
+ CurPtr->Select(SelStart,SelEnd);
+ CurPtr=CurPtr->m_next;
+
+ if (!CurPtr)
+ return TRUE; // ранее было FALSE
+ }
+ }
+ else if (Sel->BlockType==BTYPE_COLUMN)
+ {
+ Flags.Set(FEDITOR_MARKINGVBLOCK);
+ VBlockStart=CurPtr;
+
+ if ((BlockStartLine=Sel->BlockStartLine) == -1)
+ BlockStartLine=NumLine;
+
+ VBlockX=Sel->BlockStartPos;
+
+ if ((VBlockY=Sel->BlockStartLine) == -1)
+ VBlockY=NumLine;
+
+ VBlockSizeX=Sel->BlockWidth;
+ VBlockSizeY=Sel->BlockHeight;
+
+ if (VBlockSizeX < 0)
+ {
+ VBlockSizeX=-VBlockSizeX;
+ VBlockX-=VBlockSizeX;
+
+ if (VBlockX < 0)
+ VBlockX=0;
+ }
+ }
+
+ return TRUE;
+ }
+
+ _ECTLLOG(SysLog(L"Error: !Param"));
+ break;
+ }
+ case ECTL_REDRAW:
+ {
+ Show();
+ ScrBuf.Flush();
+ return TRUE;
+ }
+ case ECTL_TABTOREAL:
+ {
+ if (Param)
+ {
+ EditorConvertPos *ecp=(EditorConvertPos *)Param;
+ Edit *CurPtr=GetStringByNumber(ecp->StringNumber);
+
+ if (!CurPtr)
+ {
+ _ECTLLOG(SysLog(L"GetStringByNumber(%d) return nullptr",ecp->StringNumber));
+ return FALSE;
+ }
+
+ ecp->DestPos=CurPtr->TabPosToReal(ecp->SrcPos);
+ _ECTLLOG(SysLog(L"EditorConvertPos{"));
+ _ECTLLOG(SysLog(L" StringNumber =%d",ecp->StringNumber));
+ _ECTLLOG(SysLog(L" SrcPos =%d",ecp->SrcPos));
+ _ECTLLOG(SysLog(L" DestPos =%d",ecp->DestPos));
+ _ECTLLOG(SysLog(L"}"));
+ return TRUE;
+ }
+
+ break;
+ }
+ case ECTL_REALTOTAB:
+ {
+ if (Param)
+ {
+ EditorConvertPos *ecp=(EditorConvertPos *)Param;
+ Edit *CurPtr=GetStringByNumber(ecp->StringNumber);
+
+ if (!CurPtr)
+ {
+ _ECTLLOG(SysLog(L"GetStringByNumber(%d) return nullptr",ecp->StringNumber));
+ return FALSE;
+ }
+
+ ecp->DestPos=CurPtr->RealPosToTab(ecp->SrcPos);
+ _ECTLLOG(SysLog(L"EditorConvertPos{"));
+ _ECTLLOG(SysLog(L" StringNumber =%d",ecp->StringNumber));
+ _ECTLLOG(SysLog(L" SrcPos =%d",ecp->SrcPos));
+ _ECTLLOG(SysLog(L" DestPos =%d",ecp->DestPos));
+ _ECTLLOG(SysLog(L"}"));
+ return TRUE;
+ }
+
+ break;
+ }
+ case ECTL_EXPANDTABS:
+ {
+ if (Flags.Check(FEDITOR_LOCKMODE))
+ {
+ _ECTLLOG(SysLog(L"FEDITOR_LOCKMODE!"));
+ return FALSE;
+ }
+ else
+ {
+ int StringNumber=*(int *)Param;
+ Edit *CurPtr=GetStringByNumber(StringNumber);
+
+ if (!CurPtr)
+ {
+ _ECTLLOG(SysLog(L"GetStringByNumber(%d) return nullptr",StringNumber));
+ return FALSE;
+ }
+
+ AddUndoData(UNDO_EDIT,CurPtr->GetStringAddr(),CurPtr->GetEOL(),StringNumber,CurPtr->GetCurPos(),CurPtr->GetLength());
+ CurPtr->ReplaceTabs();
+ }
+
+ return TRUE;
+ }
+ // TODO: Если DI_MEMOEDIT не будет юзать раскаску, то должно выполняется в FileEditor::EditorControl(), в диалоге - нафиг ненать
+ case ECTL_ADDCOLOR:
+ {
+ if (Param)
+ {
+ EditorColor *col=(EditorColor *)Param;
+ _ECTLLOG(SysLog(L"EditorColor{"));
+ _ECTLLOG(SysLog(L" StringNumber=%d",col->StringNumber));
+ _ECTLLOG(SysLog(L" ColorItem =%d (0x%08X)",col->ColorItem,col->ColorItem));
+ _ECTLLOG(SysLog(L" StartPos =%d",col->StartPos));
+ _ECTLLOG(SysLog(L" EndPos =%d",col->EndPos));
+ _ECTLLOG(SysLog(L" Color =%d (0x%08X)",col->Color,col->Color));
+ _ECTLLOG(SysLog(L"}"));
+ ColorItem newcol;
+ newcol.StartPos=col->StartPos+(col->StartPos!=-1?X1:0);
+ newcol.EndPos=col->EndPos+X1;
+ newcol.Color=col->Color;
+ Edit *CurPtr=GetStringByNumber(col->StringNumber);
+
+ if (!CurPtr)
+ {
+ _ECTLLOG(SysLog(L"GetStringByNumber(%d) return nullptr",col->StringNumber));
+ return FALSE;
+ }
+
+ if (!col->Color)
+ return(CurPtr->DeleteColor(newcol.StartPos));
+
+ CurPtr->AddColor(&newcol);
+ return TRUE;
+ }
+
+ break;
+ }
+ // TODO: Если DI_MEMOEDIT не будет юзать раскаску, то должно выполняется в FileEditor::EditorControl(), в диалоге - нафиг ненать
+ case ECTL_GETCOLOR:
+ {
+ if (Param)
+ {
+ EditorColor *col=(EditorColor *)Param;
+ Edit *CurPtr=GetStringByNumber(col->StringNumber);
+
+ if (!CurPtr)
+ {
+ _ECTLLOG(SysLog(L"GetStringByNumber(%d) return nullptr",col->StringNumber));
+ return FALSE;
+ }
+
+ ColorItem curcol;
+
+ if (!CurPtr->GetColor(&curcol,col->ColorItem))
+ {
+ _ECTLLOG(SysLog(L"GetColor() return nullptr"));
+ return FALSE;
+ }
+
+ col->StartPos=curcol.StartPos-X1;
+ col->EndPos=curcol.EndPos-X1;
+ col->Color=curcol.Color;
+ _ECTLLOG(SysLog(L"EditorColor{"));
+ _ECTLLOG(SysLog(L" StringNumber=%d",col->StringNumber));
+ _ECTLLOG(SysLog(L" ColorItem =%d (0x%08X)",col->ColorItem,col->ColorItem));
+ _ECTLLOG(SysLog(L" StartPos =%d",col->StartPos));
+ _ECTLLOG(SysLog(L" EndPos =%d",col->EndPos));
+ _ECTLLOG(SysLog(L" Color =%d (0x%08X)",col->Color,col->Color));
+ _ECTLLOG(SysLog(L"}"));
+ return TRUE;
+ }
+
+ break;
+ }
+ // должно выполняется в FileEditor::EditorControl()
+ case ECTL_PROCESSKEY:
+ {
+ _ECTLLOG(SysLog(L"Key = %ls",_FARKEY_ToName((DWORD)Param)));
+ ProcessKey((int)(INT_PTR)Param);
+ return TRUE;
+ }
+ /* $ 16.02.2001 IS
+ Изменение некоторых внутренних настроек редактора. Param указывает на
+ структуру EditorSetParameter
+ */
+ case ECTL_SETPARAM:
+ {
+ if (Param)
+ {
+ EditorSetParameter *espar=(EditorSetParameter *)Param;
+ int rc=TRUE;
+ _ECTLLOG(SysLog(L"EditorSetParameter{"));
+ _ECTLLOG(SysLog(L" Type =%ls",_ESPT_ToName(espar->Type)));
+
+ switch (espar->Type)
+ {
+ case ESPT_GETWORDDIV:
+ _ECTLLOG(SysLog(L" wszParam =(%p)",espar->Param.wszParam));
+
+ if (espar->Param.wszParam && espar->Size)
+ far_wcsncpy(espar->Param.wszParam,EdOpt.strWordDiv,espar->Size);
+
+ rc=(int)EdOpt.strWordDiv.GetLength()+1;
+ break;
+ case ESPT_SETWORDDIV:
+ _ECTLLOG(SysLog(L" wszParam =[%ls]",espar->Param.wszParam));
+ SetWordDiv((!espar->Param.wszParam || !*espar->Param.wszParam)?Opt.strWordDiv.CPtr():espar->Param.wszParam);
+ break;
+ case ESPT_TABSIZE:
+ _ECTLLOG(SysLog(L" iParam =%d",espar->Param.iParam));
+ SetTabSize(espar->Param.iParam);
+ break;
+ case ESPT_EXPANDTABS:
+ _ECTLLOG(SysLog(L" iParam =%ls",espar->Param.iParam?L"On":L"Off"));
+ SetConvertTabs(espar->Param.iParam);
+ break;
+ case ESPT_AUTOINDENT:
+ _ECTLLOG(SysLog(L" iParam =%ls",espar->Param.iParam?L"On":L"Off"));
+ SetAutoIndent(espar->Param.iParam);
+ break;
+ case ESPT_CURSORBEYONDEOL:
+ _ECTLLOG(SysLog(L" iParam =%ls",espar->Param.iParam?L"On":L"Off"));
+ SetCursorBeyondEOL(espar->Param.iParam);
+ break;
+ case ESPT_CHARCODEBASE:
+ _ECTLLOG(SysLog(L" iParam =%ls",(!espar->Param.iParam?L"0 (Oct)":(espar->Param.iParam==1?L"1 (Dec)":(espar->Param.iParam==2?L"2 (Hex)":L"?????")))));
+ SetCharCodeBase(espar->Param.iParam);
+ break;
+ /* $ 07.08.2001 IS сменить кодировку из плагина */
+ case ESPT_CODEPAGE:
+ {
+ //BUGBUG
+ if ((UINT)espar->Param.iParam==CP_AUTODETECT)
+ {
+ rc=FALSE;
+ }
+ else
+ {
+ if (HostFileEditor)
+ {
+ HostFileEditor->SetCodePage(espar->Param.iParam);
+ HostFileEditor->CodepageChangedByUser();
+ }
+ else
+ {
+ SetCodePage(espar->Param.iParam);
+ }
+
+ Show();
+ }
+ }
+ break;
+ /* $ 29.10.2001 IS изменение настройки "Сохранять позицию файла" */
+ case ESPT_SAVEFILEPOSITION:
+ _ECTLLOG(SysLog(L" iParam =%ls",espar->Param.iParam?L"On":L"Off"));
+ SetSavePosMode(espar->Param.iParam, -1);
+ break;
+ /* $ 23.03.2002 IS запретить/отменить изменение файла */
+ case ESPT_LOCKMODE:
+ _ECTLLOG(SysLog(L" iParam =%ls",espar->Param.iParam?L"On":L"Off"));
+ Flags.Change(FEDITOR_LOCKMODE, espar->Param.iParam);
+ break;
+ case ESPT_SHOWWHITESPACE:
+ SetShowWhiteSpace(espar->Param.iParam);
+ break;
+ default:
+ _ECTLLOG(SysLog(L"}"));
+ return FALSE;
+ }
+
+ _ECTLLOG(SysLog(L"}"));
+ return rc;
+ }
+
+ return FALSE;
+ }
+ // Убрать флаг редактора "осуществляется выделение блока"
+ case ECTL_TURNOFFMARKINGBLOCK:
+ {
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+ return TRUE;
+ }
+ case ECTL_DELETEBLOCK:
+ {
+ if (Flags.Check(FEDITOR_LOCKMODE) || !(VBlockStart || BlockStart))
+ {
+
+ _ECTLLOG(if (Flags.Check(FEDITOR_LOCKMODE))SysLog(L"FEDITOR_LOCKMODE!"));
+
+ _ECTLLOG(if (!(VBlockStart || BlockStart))SysLog(L"Not selected block!"));
+
+ return FALSE;
+ }
+
+ Flags.Clear(FEDITOR_MARKINGVBLOCK|FEDITOR_MARKINGBLOCK);
+ DeleteBlock();
+ Show();
+ return TRUE;
+ }
+ case ECTL_UNDOREDO:
+ {
+ if (Param)
+ {
+ EditorUndoRedo *eur=(EditorUndoRedo *)Param;
+
+ switch (eur->Command)
+ {
+ case EUR_BEGIN:
+ AddUndoData(UNDO_BEGIN);
+ return TRUE;
+ case EUR_END:
+ AddUndoData(UNDO_END);
+ return TRUE;
+ case EUR_UNDO:
+ case EUR_REDO:
+ Lock();
+ Undo(eur->Command==EUR_REDO);
+ Unlock();
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+int Editor::SetBookmark(DWORD Pos)
+{
+ if (Pos < POSCACHE_BOOKMARK_COUNT)
+ {
+ SavePos.Line[Pos]=NumLine;
+ SavePos.Cursor[Pos]=CurLine->GetCurPos();
+ SavePos.LeftPos[Pos]=CurLine->GetLeftPos();
+ SavePos.ScreenLine[Pos]=CalcDistance(TopScreen,CurLine,-1);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int Editor::GotoBookmark(DWORD Pos)
+{
+ if (Pos < POSCACHE_BOOKMARK_COUNT)
+ {
+ if (SavePos.Line[Pos]!=POS_NONE)
+ {
+ GoToLine(static_cast<int>(SavePos.Line[Pos]));
+ CurLine->SetCurPos(static_cast<int>(SavePos.Cursor[Pos]));
+ CurLine->SetLeftPos(static_cast<int>(SavePos.LeftPos[Pos]));
+ TopScreen=CurLine;
+
+ for (DWORD I=0; I<SavePos.ScreenLine[Pos] && TopScreen->m_prev; I++)
+ TopScreen=TopScreen->m_prev;
+
+ if (!EdOpt.PersistentBlocks)
+ UnmarkBlock();
+
+ Show();
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int Editor::ClearStackBookmarks()
+{
+ NewStackPos = FALSE;
+
+ if (StackPos)
+ {
+ InternalEditorStackBookMark *sb_prev = StackPos->prev, *sb_next;
+
+ while (StackPos)
+ {
+ sb_next = StackPos->next;
+ free(StackPos);
+ StackPos = sb_next;
+ }
+
+ StackPos = sb_prev;
+
+ while (StackPos)
+ {
+ sb_prev = StackPos->prev;
+ free(StackPos);
+ StackPos = sb_prev;
+ }
+ }
+
+ return TRUE;
+}
+
+int Editor::DeleteStackBookmark(InternalEditorStackBookMark *sb_delete)
+{
+ NewStackPos=FALSE;
+
+ if (sb_delete)
+ {
+ if (sb_delete->next)
+ sb_delete->next->prev=sb_delete->prev;
+
+ if (sb_delete->prev)
+ sb_delete->prev->next=sb_delete->next;
+
+ if (StackPos==sb_delete)
+ StackPos=(sb_delete->next)?sb_delete->next:sb_delete->prev;
+
+ free(sb_delete);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int Editor::RestoreStackBookmark()
+{
+ NewStackPos=FALSE;
+
+ if (StackPos && ((int)StackPos->Line!=NumLine || (int)StackPos->Cursor!=CurLine->GetCurPos()))
+ {
+ GoToLine(StackPos->Line);
+ CurLine->SetCurPos(StackPos->Cursor);
+ CurLine->SetLeftPos(StackPos->LeftPos);
+ TopScreen=CurLine;
+
+ for (DWORD I=0; I<StackPos->ScreenLine && TopScreen->m_prev; I++)
+ TopScreen=TopScreen->m_prev;
+
+ if (!EdOpt.PersistentBlocks)
+ UnmarkBlock();
+
+ Show();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int Editor::AddStackBookmark(BOOL blNewPos)
+{
+ InternalEditorStackBookMark *sb_old=StackPos;
+
+ if (StackPos && StackPos->next)
+ {
+ StackPos=StackPos->next;
+ StackPos->prev=0;
+ ClearStackBookmarks();
+ StackPos=sb_old;
+ StackPos->next=0;
+ }
+
+ InternalEditorStackBookMark *sb_new=(InternalEditorStackBookMark*)malloc(sizeof(InternalEditorStackBookMark));
+
+ if (sb_new)
+ {
+ if (StackPos)
+ StackPos->next=sb_new;
+
+ StackPos=sb_new;
+ StackPos->prev=sb_old;
+ StackPos->next=0;
+ StackPos->Line=NumLine;
+ StackPos->Cursor=CurLine->GetCurPos();
+ StackPos->LeftPos=CurLine->GetLeftPos();
+ StackPos->ScreenLine=CalcDistance(TopScreen,CurLine,-1);
+ NewStackPos=blNewPos; // We had to save current position, if we will go to previous bookmark (by default)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+InternalEditorStackBookMark* Editor::PointerToFirstStackBookmark(int *piCount)
+{
+ InternalEditorStackBookMark *sb_temp=StackPos;
+ int iCount=0;
+
+ if (sb_temp)
+ {
+ for (; sb_temp->prev; iCount++)
+ sb_temp=sb_temp->prev;
+ }
+
+ if (piCount)
+ *piCount = iCount;
+
+ return sb_temp;
+}
+
+InternalEditorStackBookMark* Editor::PointerToLastStackBookmark(int *piCount)
+{
+ InternalEditorStackBookMark *sb_temp=StackPos;
+ int iCount=0;
+
+ if (sb_temp)
+ {
+ for (; sb_temp->next; iCount++)
+ sb_temp=sb_temp->next;
+ iCount++;
+ }
+
+ if (piCount)
+ *piCount += iCount;
+
+ return sb_temp;
+}
+
+InternalEditorStackBookMark* Editor::PointerToStackBookmark(int iIdx) // Returns null_ptr if failed!
+{
+ InternalEditorStackBookMark *sb_temp=StackPos;
+
+ if (iIdx!=-1 && sb_temp) // -1 == current
+ {
+ while (sb_temp->prev)
+ sb_temp=sb_temp->prev;
+
+ for (int i=0; i!=iIdx && sb_temp; i++)
+ sb_temp=sb_temp->next;
+ }
+
+ return sb_temp;
+}
+
+int Editor::BackStackBookmark()
+{
+ if (StackPos)
+ {
+ if (NewStackPos) // If we had to save current position ...
+ {
+ NewStackPos=FALSE;
+ // ... if current bookmark is last and current_position != bookmark_position
+ // save current position as new bookmark
+ if (!StackPos->next && ((int)StackPos->Line!=NumLine || (int)StackPos->Cursor!=CurLine->GetCurPos()))
+ AddStackBookmark(FALSE);
+ }
+
+ return PrevStackBookmark();
+ }
+
+ return FALSE;
+}
+
+int Editor::PrevStackBookmark()
+{
+ if (StackPos)
+ {
+ if (StackPos->prev) // If not first bookmark - go
+ {
+ StackPos=StackPos->prev;
+ }
+
+ return RestoreStackBookmark();
+ }
+
+ return FALSE;
+}
+
+int Editor::NextStackBookmark()
+{
+ if (StackPos)
+ {
+ if (StackPos->next) // If not last bookmark - go
+ {
+ StackPos=StackPos->next;
+ }
+
+ return RestoreStackBookmark();
+ }
+
+ return FALSE;
+}
+
+int Editor::LastStackBookmark()
+{
+ if (StackPos)
+ {
+ StackPos=PointerToLastStackBookmark();
+ return RestoreStackBookmark();
+ }
+
+ return FALSE;
+}
+
+int Editor::GotoStackBookmark(int iIdx)
+{
+ if (StackPos)
+ {
+ InternalEditorStackBookMark *sb_temp = PointerToStackBookmark(iIdx);
+ if (sb_temp)
+ {
+ StackPos=sb_temp;
+ return RestoreStackBookmark();
+ }
+ }
+
+ return FALSE;
+}
+
+int Editor::PushStackBookMark()
+{
+ StackPos=PointerToLastStackBookmark();
+ return AddStackBookmark(FALSE);
+}
+
+int Editor::PopStackBookMark()
+{
+ return (LastStackBookmark() && DeleteStackBookmark(StackPos));
+}
+
+int Editor::CurrentStackBookmarkIdx()
+{
+ int iIdx;
+ if (PointerToFirstStackBookmark(&iIdx))
+ return iIdx;
+ return -1;
+}
+
+int Editor::GetStackBookmark(int iIdx,EditorBookMarks *Param)
+{
+ InternalEditorStackBookMark *sb_temp = PointerToStackBookmark(iIdx);
+
+ if (sb_temp && Param)
+ {
+ if (Param->Line) Param->Line[0] =sb_temp->Line;
+ if (Param->Cursor) Param->Cursor[0] =sb_temp->Cursor;
+ if (Param->LeftPos) Param->LeftPos[0] =sb_temp->LeftPos;
+ if (Param->ScreenLine) Param->ScreenLine[0] =sb_temp->ScreenLine;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int Editor::GetStackBookmarks(EditorBookMarks *Param)
+{
+ int iCount=0;
+
+ if (StackPos)
+ {
+ InternalEditorStackBookMark *sb_temp = PointerToFirstStackBookmark(&iCount);
+ PointerToLastStackBookmark(&iCount);
+
+ if (Param)
+ {
+ if (Param->Line || Param->Cursor || Param->LeftPos || Param->ScreenLine)
+ {
+ for (int i=0; i<iCount; i++)
+ {
+ if (Param->Line)
+ Param->Line[i]=sb_temp->Line;
+
+ if (Param->Cursor)
+ Param->Cursor[i]=sb_temp->Cursor;
+
+ if (Param->LeftPos)
+ Param->LeftPos[i]=sb_temp->LeftPos;
+
+ if (Param->ScreenLine)
+ Param->ScreenLine[i]=sb_temp->ScreenLine;
+
+ sb_temp=sb_temp->next;
+ }
+ }
+ else iCount=0;
+ }
+ }
+
+ return iCount;
+}
+
+Edit * Editor::GetStringByNumber(int DestLine)
+{
+ if (DestLine==NumLine || DestLine<0)
+ {
+ LastGetLine = CurLine;
+ LastGetLineNumber = NumLine;
+ return CurLine;
+ }
+
+ if (DestLine>NumLastLine)
+ return nullptr;
+
+ Edit *CurPtr = CurLine;
+ int StartLine = NumLine;
+
+ if(LastGetLine)
+ {
+ CurPtr = LastGetLine;
+ StartLine = LastGetLineNumber;
+ }
+
+ bool Forward = (DestLine>StartLine && DestLine<StartLine+(NumLastLine-StartLine)/2) || (DestLine<StartLine/2);
+
+ if(DestLine>StartLine)
+ {
+ if(!Forward)
+ {
+ StartLine = NumLastLine-1;
+ CurPtr = EndList;
+ }
+ }
+ else
+ {
+ if(Forward)
+ {
+ StartLine = 0;
+ CurPtr = TopList;
+ }
+ }
+
+ for (int Line=StartLine; Line!=DestLine; Forward?Line++:Line--)
+ {
+ CurPtr=(Forward?CurPtr->m_next:CurPtr->m_prev);
+ if (!CurPtr)
+ {
+ LastGetLine = Forward?TopList:EndList;
+ LastGetLineNumber = Forward?0:NumLastLine-1;
+ return nullptr;
+ }
+ }
+ LastGetLine = CurPtr;
+ LastGetLineNumber = DestLine;
+ return CurPtr;
+}
+
+void Editor::SetReplaceMode(int Mode)
+{
+ ::ReplaceMode=Mode;
+}
+
+int Editor::GetLineCurPos()
+{
+ return CurLine->GetTabCurPos();
+}
+
+void Editor::BeginVBlockMarking()
+{
+ UnmarkBlock();
+ VBlockStart=CurLine;
+ VBlockX=CurLine->GetTabCurPos();
+ VBlockSizeX=0;
+ VBlockY=NumLine;
+ VBlockSizeY=1;
+ Flags.Set(FEDITOR_MARKINGVBLOCK);
+ BlockStartLine=NumLine;
+ //_D(SysLog(L"BeginVBlockMarking, set vblock to VBlockY=%i:%i, VBlockX=%i:%i",VBlockY,VBlockSizeY,VBlockX,VBlockSizeX));
+}
+
+void Editor::AdjustVBlock(int PrevX)
+{
+ int x=GetLineCurPos();
+ int c2;
+
+ //_D(SysLog(L"AdjustVBlock, x=%i, vblock is VBlockY=%i:%i, VBlockX=%i:%i, PrevX=%i",x,VBlockY,VBlockSizeY,VBlockX,VBlockSizeX,PrevX));
+ if (x==VBlockX+VBlockSizeX) // ничего не случилось, никаких табуляций нет
+ return;
+
+ if (x>VBlockX) // курсор убежал внутрь блока
+ {
+ VBlockSizeX=x-VBlockX;
+ //_D(SysLog(L"x>VBlockX");
+ }
+ else if (x<VBlockX) // курсор убежал за начало блока
+ {
+ c2=VBlockX;
+
+ if (PrevX>VBlockX) // сдвигались вправо, а пришли влево
+ {
+ VBlockX=x;
+ VBlockSizeX=c2-x; // меняем блок
+ }
+ else // сдвигались влево и пришли еще больше влево
+ {
+ VBlockX=x;
+ VBlockSizeX+=c2-x; // расширяем блок
+ }
+
+ //_D(SysLog(L"x<VBlockX"));
+ }
+ else if (x==VBlockX && x!=PrevX)
+ {
+ VBlockSizeX=0; // ширина в 0, потому прыгнули прям на табуляцию
+ //_D(SysLog(L"x==VBlockX && x!=PrevX"));
+ }
+
+ // примечание
+ // случай x>VBLockX+VBlockSizeX не может быть
+ // потому что курсор прыгает назад на табуляцию, но не вперед
+ //_D(SysLog(L"AdjustVBlock, changed vblock VBlockY=%i:%i, VBlockX=%i:%i",VBlockY,VBlockSizeY,VBlockX,VBlockSizeX));
+}
+
+
+void Editor::Xlat()
+{
+ Edit *CurPtr;
+ int Line;
+ BOOL DoXlat=FALSE;
+ AddUndoData(UNDO_BEGIN);
+
+ if (VBlockStart)
+ {
+ CurPtr=VBlockStart;
+
+ for (Line=0; CurPtr && Line<VBlockSizeY; Line++,CurPtr=CurPtr->m_next)
+ {
+ int TBlockX=CurPtr->TabPosToReal(VBlockX);
+ int TBlockSizeX=CurPtr->TabPosToReal(VBlockX+VBlockSizeX)-
+ CurPtr->TabPosToReal(VBlockX);
+ const wchar_t *CurStr,*EndSeq;
+ int Length;
+ CurPtr->GetBinaryString(&CurStr,&EndSeq,Length);
+ int CopySize=Length-TBlockX;
+
+ if (CopySize>TBlockSizeX)
+ CopySize=TBlockSizeX;
+
+ AddUndoData(UNDO_EDIT,CurPtr->GetStringAddr(),CurPtr->GetEOL(),BlockStartLine+Line,CurLine->GetCurPos(),CurPtr->GetLength());
+ ::Xlat(CurPtr->Str,TBlockX,TBlockX+CopySize,Opt.XLat.Flags);
+ }
+
+ DoXlat=TRUE;
+ }
+ else
+ {
+ Line=0;
+ CurPtr=BlockStart;
+
+ // $ 25.11.2000 IS
+ // Если нет выделения, то обработаем текущее слово. Слово определяется на
+ // основе специальной группы разделителей.
+ if (CurPtr)
+ {
+ while (CurPtr)
+ {
+ int StartSel,EndSel;
+ CurPtr->GetSelection(StartSel,EndSel);
+
+ if (StartSel==-1)
+ break;
+
+ if (EndSel == -1)
+ EndSel=CurPtr->GetLength();//StrLength(CurPtr->Str);
+
+ AddUndoData(UNDO_EDIT,CurPtr->GetStringAddr(),CurPtr->GetEOL(),BlockStartLine+Line,CurLine->GetCurPos(),CurPtr->GetLength());
+ ::Xlat(CurPtr->Str,StartSel,EndSel,Opt.XLat.Flags);
+ Line++;
+ CurPtr=CurPtr->m_next;
+ }
+
+ DoXlat=TRUE;
+ }
+ else
+ {
+ wchar_t *Str=CurLine->Str;
+ int start=CurLine->GetCurPos(), end, StrSize=CurLine->GetLength();//StrLength(Str);
+ // $ 10.12.2000 IS
+ // Обрабатываем только то слово, на котором стоит курсор, или то слово,
+ // что находится левее позиции курсора на 1 символ
+ DoXlat=TRUE;
+
+ if (IsWordDiv(Opt.XLat.strWordDivForXlat,Str[start]))
+ {
+ if (start) start--;
+
+ DoXlat=(!IsWordDiv(Opt.XLat.strWordDivForXlat,Str[start]));
+ }
+
+ if (DoXlat)
+ {
+ while (start>=0 && !IsWordDiv(Opt.XLat.strWordDivForXlat,Str[start]))
+ start--;
+
+ start++;
+ end=start+1;
+
+ while (end<StrSize && !IsWordDiv(Opt.XLat.strWordDivForXlat,Str[end]))
+ end++;
+
+ AddUndoData(UNDO_EDIT,CurLine->GetStringAddr(),CurLine->GetEOL(),NumLine,start,CurLine->GetLength());
+ ::Xlat(Str,start,end,Opt.XLat.Flags);
+ }
+ }
+ }
+
+ AddUndoData(UNDO_END);
+
+ if (DoXlat)
+ TextChanged(1);
+}
+/* SVS $ */
+
+/* $ 15.02.2001 IS
+ Манипуляции с табуляцией на уровне всего загруженного файла.
+ Может быть длительной во времени операцией, но тут уж, imho,
+ ничего не поделать.
+*/
+//Обновим размер табуляции
+void Editor::SetTabSize(int NewSize)
+{
+ if (NewSize<1 || NewSize>512)
+ NewSize=8;
+
+ if (NewSize!=EdOpt.TabSize) /* Меняем размер табуляции только в том случае, если он
+ на самом деле изменился */
+ {
+ EdOpt.TabSize=NewSize;
+ Edit *CurPtr=TopList;
+
+ while (CurPtr)
+ {
+ CurPtr->SetTabSize(NewSize);
+ CurPtr=CurPtr->m_next;
+ }
+ }
+}
+
+// обновим режим пробелы вместо табуляции
+// операция необратима, кстати, т.е. пробелы на табуляцию обратно не изменятся
+void Editor::SetConvertTabs(int NewMode)
+{
+ if (NewMode!=EdOpt.ExpandTabs) /* Меняем режим только в том случае, если он
+ на самом деле изменился */
+ {
+ EdOpt.ExpandTabs=NewMode;
+ Edit *CurPtr=TopList;
+
+ while (CurPtr)
+ {
+ CurPtr->SetConvertTabs(NewMode);
+
+ if (NewMode == EXPAND_ALLTABS)
+ CurPtr->ReplaceTabs();
+
+ CurPtr=CurPtr->m_next;
+ }
+ }
+}
+
+void Editor::SetDelRemovesBlocks(int NewMode)
+{
+ if (NewMode!=EdOpt.DelRemovesBlocks)
+ {
+ EdOpt.DelRemovesBlocks=NewMode;
+ Edit *CurPtr=TopList;
+
+ while (CurPtr)
+ {
+ CurPtr->SetDelRemovesBlocks(NewMode);
+ CurPtr=CurPtr->m_next;
+ }
+ }
+}
+
+void Editor::SetShowWhiteSpace(int NewMode)
+{
+ if (NewMode!=EdOpt.ShowWhiteSpace)
+ {
+ EdOpt.ShowWhiteSpace=NewMode;
+
+ for (Edit *CurPtr=TopList; CurPtr; CurPtr=CurPtr->m_next)
+ {
+ CurPtr->SetShowWhiteSpace(NewMode);
+ }
+ }
+}
+
+void Editor::SetPersistentBlocks(int NewMode)
+{
+ if (NewMode!=EdOpt.PersistentBlocks)
+ {
+ EdOpt.PersistentBlocks=NewMode;
+ Edit *CurPtr=TopList;
+
+ while (CurPtr)
+ {
+ CurPtr->SetPersistentBlocks(NewMode);
+ CurPtr=CurPtr->m_next;
+ }
+ }
+}
+
+// "Курсор за пределами строки"
+void Editor::SetCursorBeyondEOL(int NewMode)
+{
+ if (NewMode!=EdOpt.CursorBeyondEOL)
+ {
+ EdOpt.CursorBeyondEOL=NewMode;
+ Edit *CurPtr=TopList;
+
+ while (CurPtr)
+ {
+ CurPtr->SetEditBeyondEnd(NewMode);
+ CurPtr=CurPtr->m_next;
+ }
+ }
+
+ /* $ 16.10.2001 SKV
+ Если переключились туда сюда этот режим,
+ то из-за этой штуки возникают нехилые глюки
+ при выделении вертикальных блоков.
+ */
+ if (EdOpt.CursorBeyondEOL)
+ {
+ MaxRightPos=0;
+ }
+}
+
+void Editor::GetSavePosMode(int &SavePos, int &SaveShortPos)
+{
+ SavePos=EdOpt.SavePos;
+ SaveShortPos=EdOpt.SaveShortPos;
+}
+
+// передавайте в качестве значения параметра "-1" для параметра,
+// который не нужно менять
+void Editor::SetSavePosMode(int SavePos, int SaveShortPos)
+{
+ if (SavePos!=-1)
+ EdOpt.SavePos=SavePos;
+
+ if (SaveShortPos!=-1)
+ EdOpt.SaveShortPos=SaveShortPos;
+}
+
+void Editor::EditorShowMsg(const wchar_t *Title,const wchar_t *Msg, const wchar_t* Name,int Percent)
+{
+ FARString strProgress;
+
+ if (Percent!=-1)
+ {
+ FormatString strPercent;
+ strPercent<<Percent;
+
+ size_t PercentLength=Max(strPercent.strValue().GetLength(),(size_t)3);
+ size_t Length=Max(Min(static_cast<int>(MAX_WIDTH_MESSAGE-2),StrLength(Name)),40)-PercentLength-2;
+ wchar_t *Progress=strProgress.GetBuffer(Length);
+
+ if (Progress)
+ {
+ size_t CurPos=Min(Percent,100)*Length/100;
+ wmemset(Progress,BoxSymbols[BS_X_DB],CurPos);
+ wmemset(Progress+(CurPos),BoxSymbols[BS_X_B0],Length-CurPos);
+ strProgress.ReleaseBuffer(Length);
+ FormatString strTmp;
+ strTmp<<L" "<<fmt::Width(PercentLength)<<strPercent<<L"%";
+ strProgress+=strTmp;
+ }
+
+ }
+
+ Message(0,0,Title,Msg,Name,strProgress.IsEmpty()?nullptr:strProgress.CPtr());
+ PreRedrawItem preRedrawItem=PreRedraw.Peek();
+ preRedrawItem.Param.Param1=(void *)Title;
+ preRedrawItem.Param.Param2=(void *)Msg;
+ preRedrawItem.Param.Param3=(void *)Name;
+ preRedrawItem.Param.Param4=(void *)(INT_PTR)(Percent);
+ PreRedraw.SetParam(preRedrawItem.Param);
+}
+
+void Editor::PR_EditorShowMsg()
+{
+ PreRedrawItem preRedrawItem=PreRedraw.Peek();
+ Editor::EditorShowMsg((wchar_t*)preRedrawItem.Param.Param1,(wchar_t*)preRedrawItem.Param.Param2,(wchar_t*)preRedrawItem.Param.Param3,(int)(INT_PTR)preRedrawItem.Param.Param4);
+}
+
+
+Edit *Editor::CreateString(const wchar_t *lpwszStr, int nLength)
+{
+ Edit *pEdit = new(std::nothrow) Edit(this, nullptr, lpwszStr ? false : true);
+
+ if (pEdit)
+ {
+ pEdit->m_next = nullptr;
+ pEdit->m_prev = nullptr;
+ pEdit->SetTabSize(EdOpt.TabSize);
+ pEdit->SetPersistentBlocks(EdOpt.PersistentBlocks);
+ pEdit->SetConvertTabs(EdOpt.ExpandTabs);
+ pEdit->SetCodePage(m_codepage);
+
+ if (lpwszStr)
+ pEdit->SetBinaryString(lpwszStr, nLength);
+
+ pEdit->SetCurPos(0);
+ pEdit->SetObjectColor(COL_EDITORTEXT,COL_EDITORSELECTEDTEXT);
+ pEdit->SetEditorMode(TRUE);
+ pEdit->SetWordDiv(EdOpt.strWordDiv);
+ pEdit->SetShowWhiteSpace(EdOpt.ShowWhiteSpace);
+ }
+
+ return pEdit;
+}
+
+/*bool Editor::AddString (const wchar_t *lpwszStr, int nLength)
+{
+ Edit *pNewEdit = CreateString (lpwszStr, nLength);
+
+ if ( !pNewEdit )
+ return false;
+
+ if ( !TopList || !NumLastLine ) //???
+ TopList = EndList = TopScreen = CurLine = pNewEdit;
+ else
+ {
+ Edit *PrevPtr;
+
+ EndList->m_next = pNewEdit;
+
+ PrevPtr = EndList;
+ EndList = EndList->m_next;
+ EndList->m_prev = PrevPtr;
+ EndList->m_next = nullptr;
+ }
+
+ NumLastLine++;
+
+ return true;
+}*/
+
+Edit *Editor::InsertString(const wchar_t *lpwszStr, int nLength, Edit *pAfter, int AfterLineNumber)
+{
+ Edit *pNewEdit = CreateString(lpwszStr, nLength);
+
+ if (pNewEdit)
+ {
+ if (!TopList || !NumLastLine) //???
+ TopList = EndList = TopScreen = CurLine = pNewEdit;
+ else
+ {
+ Edit *pWork = pAfter?pAfter:EndList;
+ Edit *pNext = pWork->m_next;
+ pNewEdit->m_next = pNext;
+ pNewEdit->m_prev = pWork;
+ pWork->m_next = pNewEdit;
+
+ if (pNext)
+ pNext->m_prev = pNewEdit;
+
+ if (!pAfter)
+ {
+ EndList = pNewEdit;
+ AfterLineNumber = NumLastLine-1;
+ }
+ }
+
+ NumLastLine++;
+
+ if(AfterLineNumber<LastGetLineNumber)
+ {
+ LastGetLineNumber++;
+ }
+
+ }
+
+ return pNewEdit;
+}
+
+
+void Editor::SetCacheParams(EditorCacheParams *pp)
+{
+ bool translateTabs=false;
+ SavePos=pp->SavePos;
+ //m_codepage = pp->Table; //BUGBUG!!!, LoadFile do it itself
+
+ if (StartLine == -2) // from Viewer!
+ {
+ Edit *CurPtr=TopList;
+ long TotalSize=0;
+
+ while (CurPtr && CurPtr->m_next)
+ {
+ const wchar_t *SaveStr,*EndSeq;
+ int Length;
+ CurPtr->GetBinaryString(&SaveStr,&EndSeq,Length);
+ TotalSize+=Length+StrLength(EndSeq);
+
+ if (TotalSize > StartChar)
+ break;
+
+ CurPtr=CurPtr->m_next;
+ NumLine++;
+ }
+
+ TopScreen=CurLine=CurPtr;
+
+ if (NumLine == pp->Line - pp->ScreenLine)
+ {
+ Lock();
+
+ for (DWORD I=0; I < (DWORD)pp->ScreenLine; I++)
+ ProcessKey(KEY_DOWN);
+
+ CurLine->SetTabCurPos(pp->LinePos);
+ Unlock();
+ }
+
+ CurLine->SetLeftPos(pp->LeftPos);
+ }
+ else if (StartLine != -1 || EdOpt.SavePos)
+ {
+ if (StartLine!=-1)
+ {
+ pp->Line = StartLine-1;
+ pp->ScreenLine = ObjHeight/2; //ScrY
+
+ if (pp->ScreenLine > pp->Line)
+ pp->ScreenLine = pp->Line;
+
+ pp->LinePos = 0;
+ if (StartChar > 0)
+ {
+ pp->LinePos = StartChar-1;
+ translateTabs = true;
+ }
+ }
+
+ if (pp->ScreenLine > ObjHeight) //ScrY //BUGBUG
+ pp->ScreenLine=ObjHeight;//ScrY;
+
+ if (pp->Line >= pp->ScreenLine)
+ {
+ Lock();
+ GoToLine(pp->Line-pp->ScreenLine);
+ TopScreen = CurLine;
+
+ for (int I=0; I < pp->ScreenLine; I++)
+ ProcessKey(KEY_DOWN);
+
+ if(translateTabs) CurLine->SetCurPos(pp->LinePos);
+ else CurLine->SetTabCurPos(pp->LinePos);
+ CurLine->SetLeftPos(pp->LeftPos);
+ Unlock();
+ }
+ }
+}
+
+void Editor::GetCacheParams(EditorCacheParams *pp)
+{
+ memset(pp, 0, sizeof(EditorCacheParams));
+ memset(&pp->SavePos,0xff,sizeof(InternalEditorBookMark));
+ pp->Line = NumLine;
+ pp->ScreenLine = CalcDistance(TopScreen, CurLine,-1);
+ pp->LinePos = CurLine->GetTabCurPos();
+ pp->LeftPos = CurLine->GetLeftPos();
+ pp->CodePage = m_codepage;
+
+ if (Opt.EdOpt.SaveShortPos)
+ {
+ pp->SavePos=SavePos;
+ }
+}
+
+
+bool Editor::SetCodePage(UINT codepage)
+{
+ if (m_codepage != codepage)
+ {
+ m_codepage = codepage;
+ Edit *current = TopList;
+ DWORD Result=0;
+
+ while (current)
+ {
+ Result|=current->SetCodePage(m_codepage);
+ current = current->m_next;
+ }
+
+ Show();
+ return !Result; // BUGBUG, more details
+ }
+
+ return true;
+}
+
+UINT Editor::GetCodePage()
+{
+ return m_codepage;
+}
+
+
+void Editor::SetDialogParent(DWORD Sets)
+{
+}
+
+void Editor::SetOvertypeMode(int Mode)
+{
+}
+
+int Editor::GetOvertypeMode()
+{
+ return 0;
+}
+
+void Editor::SetEditBeyondEnd(int Mode)
+{
+}
+
+void Editor::SetClearFlag(int Flag)
+{
+}
+
+int Editor::GetClearFlag()
+{
+ return 0;
+}
+
+int Editor::GetCurCol()
+{
+ return CurLine->GetCurPos();
+}
+
+void Editor::SetCurPos(int NewCol, int NewRow)
+{
+ Lock();
+ GoToLine(NewRow);
+ CurLine->SetTabCurPos(NewCol);
+ //CurLine->SetLeftPos(LeftPos); ???
+ Unlock();
+}
+
+void Editor::SetCursorType(bool Visible, DWORD Size)
+{
+ CurLine->SetCursorType(Visible,Size); //???
+}
+
+void Editor::GetCursorType(bool& Visible,DWORD& Size)
+{
+ CurLine->GetCursorType(Visible,Size); //???
+}
+
+void Editor::SetObjectColor(int Color,int SelColor,int ColorUnChanged)
+{
+ for (Edit *CurPtr=TopList; CurPtr; CurPtr=CurPtr->m_next) //???
+ CurPtr->SetObjectColor(Color,SelColor,ColorUnChanged);
+}
+
+void Editor::DrawScrollbar()
+{
+ if (EdOpt.ShowScrollBar)
+ {
+ SetColor(COL_EDITORSCROLLBAR);
+ XX2=X2-(ScrollBarEx(X2,Y1,Y2-Y1+1,NumLine-CalcDistance(TopScreen,CurLine,-1),NumLastLine)?1:0);
+ }
+}