4 Реализация одиночной строки редактирования
7 Copyright (c) 1996 Eugene Roshal
8 Copyright (c) 2000 Far Group
11 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions
14 1. Redistributions of source code must retain the above copyright
15 notice, this list of conditions and the following disclaimer.
16 2. Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in the
18 documentation and/or other materials provided with the distribution.
19 3. The name of the authors may not be used to endorse or promote products
20 derived from this software without specific prior written permission.
22 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "headers.hpp"
38 #include "keyboard.hpp"
39 #include "macroopcode.hpp"
43 #include "ctrlobj.hpp"
44 #include "filepanels.hpp"
45 #include "filelist.hpp"
49 #include "palette.hpp"
50 #include "clipboard.hpp"
52 #include "datetime.hpp"
53 #include "Bookmarks.hpp"
54 #include "pathmix.hpp"
56 #include "panelmix.hpp"
58 #include "history.hpp"
60 #include "chgmmode.hpp"
65 enum {EOL_NONE
,EOL_CR
,EOL_LF
,EOL_CRLF
,EOL_CRCRLF
};
66 static const wchar_t *EOL_TYPE_CHARS
[]={L
"",L
"\r",L
"\n",L
"\r\n",L
"\r\r\n"};
68 #define EDMASK_ANY L'X' // позволяет вводить в строку ввода любой символ;
69 #define EDMASK_DSS L'#' // позволяет вводить в строку ввода цифры, пробел и знак минуса;
70 #define EDMASK_DIGIT L'9' // позволяет вводить в строку ввода только цифры;
71 #define EDMASK_DIGITS L'N' // позволяет вводить в строку ввода только цифры и пробелы;
72 #define EDMASK_ALPHA L'A' // позволяет вводить в строку ввода только буквы.
73 #define EDMASK_HEX L'H' // позволяет вводить в строку ввода шестнадцатиричные символы.
80 DisableCallback(bool &State
){OldState
=State
;CurState
=&State
;State
=false;}
81 void Restore(){*CurState
=OldState
;}
82 ~DisableCallback(){Restore();}
85 Edit::Edit(ScreenObject
*pOwner
, Callback
* aCallback
, bool bAllocateData
):
88 Str(bAllocateData
? reinterpret_cast<wchar_t*>(malloc(sizeof(wchar_t))) : nullptr),
101 m_Callback
.Active
=true;
102 m_Callback
.m_Callback
=nullptr;
103 m_Callback
.m_Param
=nullptr;
105 if (aCallback
) m_Callback
=*aCallback
;
108 SetWordDiv(Opt
.strWordDiv
);
113 Flags
.Set(FEDITLINE_EDITBEYONDEND
);
114 Color
=F_LIGHTGRAY
|B_BLACK
;
115 SelColor
=F_WHITE
|B_BLACK
;
116 ColorUnChanged
=COL_DIALOGEDITUNCHANGED
;
120 TabSize
=Opt
.EdOpt
.TabSize
;
121 TabExpandMode
= EXPAND_NOTABS
;
122 Flags
.Change(FEDITLINE_DELREMOVESBLOCKS
,Opt
.EdOpt
.DelRemovesBlocks
);
123 Flags
.Change(FEDITLINE_PERSISTENTBLOCKS
,Opt
.EdOpt
.PersistentBlocks
);
124 Flags
.Change(FEDITLINE_SHOWWHITESPACE
,Opt
.EdOpt
.ShowWhiteSpace
);
125 m_codepage
= 0; //BUGBUG
141 DWORD
Edit::SetCodePage(UINT codepage
)
143 DWORD Ret
=SETCP_NOERROR
;
144 DWORD wc2mbFlags
=WC_NO_BEST_FIT_CHARS
;
145 BOOL UsedDefaultChar
=FALSE
;
146 LPBOOL lpUsedDefaultChar
=&UsedDefaultChar
;
148 if (m_codepage
==CP_UTF7
|| m_codepage
==CP_UTF8
|| m_codepage
==CP_UTF16LE
|| m_codepage
==CP_UTF16BE
) // BUGBUG: CP_SYMBOL, 50xxx, 57xxx too
151 lpUsedDefaultChar
=nullptr;
154 DWORD mb2wcFlags
=MB_ERR_INVALID_CHARS
;
156 if (codepage
==CP_UTF7
) // BUGBUG: CP_SYMBOL, 50xxx, 57xxx too
161 if (codepage
!= m_codepage
)
165 //m_codepage = codepage;
166 int length
= WINPORT(WideCharToMultiByte
)(m_codepage
, wc2mbFlags
, Str
, StrSize
, nullptr, 0, nullptr, lpUsedDefaultChar
);
169 Ret
|=SETCP_WC2MBERROR
;
171 char *decoded
= (char*)malloc(length
);
175 Ret
|=SETCP_OTHERERROR
;
179 WINPORT(WideCharToMultiByte
)(m_codepage
, 0, Str
, StrSize
, decoded
, length
, nullptr, nullptr);
180 int length2
= WINPORT(MultiByteToWideChar
)(codepage
, mb2wcFlags
, decoded
, length
, nullptr, 0);
182 if (!length2
&& WINPORT(GetLastError
)()==ERROR_NO_UNICODE_TRANSLATION
)
184 Ret
|=SETCP_MB2WCERROR
;
185 length2
= WINPORT(MultiByteToWideChar
)(codepage
, 0, decoded
, length
, nullptr, 0);
188 wchar_t *encoded
= (wchar_t*)malloc((length2
+1)*sizeof(wchar_t));
193 Ret
|=SETCP_OTHERERROR
;
197 length2
= WINPORT(MultiByteToWideChar
)(codepage
, 0, decoded
, length
, encoded
, length2
);
198 encoded
[length2
] = L
'\0';
205 m_codepage
= codepage
;
212 UINT
Edit::GetCodePage()
218 void Edit::DisplayObject()
220 if (Flags
.Check(FEDITLINE_DROPDOWNBOX
))
222 Flags
.Clear(FEDITLINE_CLEARFLAG
); // при дроп-даун нам не нужно никакого unchanged text
224 SelEnd
=StrSize
; // а также считаем что все выделено -
225 // надо же отличаться от обычных Edit
228 // Вычисление нового положения курсора в строке с учётом Mask.
229 int Value
=(PrevCurPos
>CurPos
)?-1:1;
230 CurPos
=GetNextCursorPos(CurPos
,Value
);
234 при DropDownBox курсор выключаем
235 не знаю даже - попробовал но не очень красиво вышло */
236 if (Flags
.Check(FEDITLINE_DROPDOWNBOX
))
237 ::SetCursorType(0,10);
240 if (Flags
.Check(FEDITLINE_OVERTYPE
))
242 int NewCursorSize
=IsFullscreen()?
243 (Opt
.CursorSize
[3]?Opt
.CursorSize
[3]:99):
244 (Opt
.CursorSize
[2]?Opt
.CursorSize
[2]:99);
245 ::SetCursorType(1,CursorSize
==-1?NewCursorSize
:CursorSize
);
249 int NewCursorSize
=IsFullscreen()?
250 (Opt
.CursorSize
[1]?Opt
.CursorSize
[1]:10):
251 (Opt
.CursorSize
[0]?Opt
.CursorSize
[0]:10);
252 ::SetCursorType(1,CursorSize
==-1?NewCursorSize
:CursorSize
);
256 MoveCursor(X1
+CursorPos
-LeftPos
,Y1
);
260 void Edit::SetCursorType(bool Visible
, DWORD Size
)
262 Flags
.Change(FEDITLINE_CURSORVISIBLE
,Visible
);
264 ::SetCursorType(Visible
,Size
);
267 void Edit::GetCursorType(bool& Visible
, DWORD
& Size
)
269 Visible
=Flags
.Check(FEDITLINE_CURSORVISIBLE
)!=FALSE
;
273 // Вычисление нового положения курсора в строке с учётом Mask.
274 int Edit::GetNextCursorPos(int Position
,int Where
)
278 if (Mask
&& *Mask
&& (Where
==-1 || Where
==1))
280 int PosChanged
=FALSE
;
281 int MaskLen
=StrLength(Mask
);
283 for (int i
=Position
; i
<MaskLen
&& i
>=0; i
+=Where
)
285 if (CheckCharMask(Mask
[i
]))
295 for (int i
=Position
; i
>=0; i
--)
297 if (CheckCharMask(Mask
[i
]))
308 for (int i
=Position
; i
<MaskLen
; i
++)
310 if (CheckCharMask(Mask
[i
]))
322 void Edit::FastShow()
324 int EditLength
=ObjWidth
;
326 if (!Flags
.Check(FEDITLINE_EDITBEYONDEND
) && CurPos
>StrSize
&& StrSize
>=0)
331 if (StrSize
>MaxLength
)
337 if (CurPos
>MaxLength
-1)
338 CurPos
=MaxLength
>0 ? (MaxLength
-1):0;
341 int CellCurPos
=GetCellCurPos();
344 ! Для комбобокса сделаем отображение строки
347 int RealLeftPos
= -1;
348 if (!Flags
.Check(FEDITLINE_DROPDOWNBOX
))
350 if (CellCurPos
- LeftPos
> EditLength
- 1)
352 // tricky left pos shifting to
353 // - avoid LeftPos pointing into middle of full-width char cells pair
354 // - ensure RealLeftPos really shifted in case string starts by some long character
355 for (int ShiftBy
= 1; ShiftBy
<= std::max(TabSize
, 2); ++ShiftBy
)
357 RealLeftPos
= CellPosToReal(CellCurPos
- EditLength
+ ShiftBy
);
358 int NewLeftPos
= RealPosToCell(RealLeftPos
);
359 if (LeftPos
!= NewLeftPos
)
361 LeftPos
= NewLeftPos
;
367 if (CellCurPos
< LeftPos
)
368 LeftPos
= CellCurPos
;
371 if (RealLeftPos
== -1)
372 RealLeftPos
= CellPosToReal(LeftPos
);
375 int CellSelStart
=(SelStart
==-1) ? -1:RealPosToCell(SelStart
);
376 int CellSelEnd
=(SelEnd
<0) ? -1:RealPosToCell(SelEnd
);
379 Если есть маска, сделаем подготовку строки, то есть
380 все "постоянные" символы в маске, не являющиеся шаблонными
381 должны постоянно присутствовать в Str
386 CursorPos
= CellCurPos
;
389 size_t OutStrCells
= 0;
390 for (int i
= RealLeftPos
; i
< StrSize
&& int(OutStrCells
) < EditLength
; ++i
)
393 if (wc
== L
' ' && Flags
.Check(FEDITLINE_SHOWWHITESPACE
) && Flags
.Check(FEDITLINE_EDITORMODE
))
400 for (int j
= 0, S
= TabSize
- ((LeftPos
+ OutStrCells
) % TabSize
);
401 j
< S
&& int(OutStrCells
) < EditLength
;
405 (Flags
.Check(FEDITLINE_SHOWWHITESPACE
) && Flags
.Check(FEDITLINE_EDITORMODE
) && !j
)
411 if (IsCharFullWidth(wc
))
413 if (int(OutStrCells
+ 2) > EditLength
)
415 OutStr
.emplace_back(L
' ');
421 else if (!IsCharXxxfix(wc
) || i
== RealLeftPos
)
424 OutStr
.emplace_back(wc
? wc
: L
' ');
428 if (Flags
.Check(FEDITLINE_PASSWORDMODE
))
430 OutStr
.resize(OutStrCells
);
431 std::fill(OutStr
.begin(), OutStr
.end(), L
'*');
434 OutStr
.emplace_back(0);
437 if (CellSelStart
==-1)
439 if (Flags
.Check(FEDITLINE_CLEARFLAG
))
441 SetColor(ColorUnChanged
);
445 RemoveTrailingSpaces(OutStr
.data());
446 OutStr
.resize(wcslen(OutStr
.data()));
447 OutStrCells
= StrCellsCount(OutStr
.data(), OutStr
.size());
448 OutStr
.emplace_back(0);
451 FS
<< fmt::Cells() << fmt::LeftAlign() << OutStr
.data();
453 int BlankLength
= EditLength
- (int)OutStrCells
;
457 FS
<< fmt::Cells() << fmt::Expand(BlankLength
) << L
"";
462 FS
<< fmt::LeftAlign() << fmt::Cells() << fmt::Size(EditLength
) << OutStr
.data();
467 if ((CellSelStart
-=LeftPos
)<0)
470 int AllString
= (CellSelEnd
==-1);
473 CellSelEnd
= EditLength
;
474 else if ((CellSelEnd
-=LeftPos
)<0)
477 for (;int(OutStrCells
) < EditLength
; ++OutStrCells
)
479 OutStr
.emplace(OutStr
.begin() + OutStr
.size() - 1, L
' ');
483 ! У DropDowList`а выделение по полной программе - на всю видимую длину
484 ДАЖЕ ЕСЛИ ПУСТАЯ СТРОКА
486 if (CellSelStart
>=EditLength
/*|| !AllString && CellSelStart>=StrSize*/ ||
487 CellSelEnd
<CellSelStart
)
489 if (Flags
.Check(FEDITLINE_DROPDOWNBOX
))
492 FS
<< fmt::Cells() << fmt::Expand(X2
- X1
+ 1) << OutStr
.data();
499 FS
<< fmt::Cells() << fmt::Truncate(CellSelStart
) << OutStr
.data();
502 if (!Flags
.Check(FEDITLINE_DROPDOWNBOX
))
504 FS
<< fmt::Cells() << fmt::Skip(CellSelStart
) << fmt::Truncate(CellSelEnd
- CellSelStart
) << OutStr
.data();
506 if (CellSelEnd
< EditLength
)
508 //SetColor(Flags.Check(FEDITLINE_CLEARFLAG) ? SelColor:Color);
510 FS
<< fmt::Cells() << fmt::Skip(CellSelEnd
) << OutStr
.data();
515 FS
<< fmt::Cells() << fmt::Expand(X2
- X1
+ 1) << OutStr
.data();
521 при дроп-даун цвета нам не нужны */
522 if (!Flags
.Check(FEDITLINE_DROPDOWNBOX
))
527 int Edit::RecurseProcessKey(int Key
)
530 int RetCode
=ProcessKey(Key
);
536 // Функция вставки всякой хреновени - от шорткатов до имен файлов
537 int Edit::ProcessInsPath(int Key
,int PrevSelStart
,int PrevSelEnd
)
540 FARString strPathName
;
542 if (Key
>=KEY_RCTRL0
&& Key
<=KEY_RCTRL9
) // шорткаты?
544 FARString strPluginModule
, strPluginFile
, strPluginData
;
546 if (Bookmarks().Get(Key
-KEY_RCTRL0
,&strPathName
,&strPluginModule
,&strPluginFile
,&strPluginData
))
551 RetCode
=_MakePath1(Key
,strPathName
,L
"");
554 // Если что-нить получилось, именно его и вставим (PathName)
557 if (Flags
.Check(FEDITLINE_CLEARFLAG
))
563 if (PrevSelStart
!=-1)
565 SelStart
=PrevSelStart
;
569 if (!Flags
.Check(FEDITLINE_PERSISTENTBLOCKS
))
572 InsertString(strPathName
);
573 Flags
.Clear(FEDITLINE_CLEARFLAG
);
580 int64_t Edit::VMProcess(int OpCode
,void *vParam
,int64_t iParam
)
585 return (int64_t)!GetLength();
586 case MCODE_C_SELECTED
:
587 return (int64_t)(SelStart
!= -1 && SelStart
< SelEnd
);
589 return (int64_t)(CurPos
>= StrSize
);
591 return (int64_t)!CurPos
;
592 case MCODE_V_ITEMCOUNT
:
593 return (int64_t)StrSize
;
595 return (int64_t)(CursorPos
+1);
596 case MCODE_F_EDITOR_SEL
:
598 int Action
=(int)((INT_PTR
)vParam
);
606 case 0: // return FirstLine
607 case 2: // return LastLine
608 return IsSelection()?1:0;
609 case 1: // return FirstPos
610 return IsSelection()?SelStart
+1:0;
611 case 3: // return LastPos
612 return IsSelection()?SelEnd
:0;
613 case 4: // return block type (0=nothing 1=stream, 2=column)
614 return IsSelection()?1:0;
625 case 0: // begin block (FirstLine & FirstPos)
626 case 1: // end block (LastLine & LastPos)
628 SetCellCurPos(iParam
?SelEnd
:SelStart
);
637 case 2: // Set Stream Selection Edge
638 case 3: // Set Column Selection Edge
642 case 0: // selection start
644 MSelStart
=GetCurPos();
647 case 1: // selection finish
651 if (MSelStart
!= GetCurPos())
652 Select(MSelStart
,GetCurPos());
667 case 4: // UnMark sel block
683 int Edit::CalcRTrimmedStrSize() const
685 int TrimmedStrSize
= StrSize
;
686 while (TrimmedStrSize
> 0 && (IsSpace(Str
[TrimmedStrSize
- 1]) || IsEol(Str
[TrimmedStrSize
- 1])))
690 return TrimmedStrSize
;
693 int Edit::CalcPosFwdTo(int Pos
, int LimitPos
) const
697 if (Pos
< LimitPos
) do
700 } while (Pos
< LimitPos
&& Pos
< StrSize
&& IsCharXxxfix(Str
[Pos
]));
705 } while (Pos
< StrSize
&& IsCharXxxfix(Str
[Pos
]));
710 int Edit::CalcPosBwdTo(int Pos
) const
718 } while (Pos
> 0 && IsCharXxxfix(Str
[Pos
]));
723 int Edit::ProcessKey(int Key
)
753 int PrevSelStart
=-1,PrevSelEnd
=0;
755 if (!Flags
.Check(FEDITLINE_DROPDOWNBOX
) && Key
==KEY_CTRLL
)
757 Flags
.Swap(FEDITLINE_READONLY
);
762 В строках ввода при выделенном блоке нажимаем BS и вместо
763 ожидаемого удаления блока (как в редакторе) получаем:
764 - символ перед курсором удален
765 - выделение блока снято
767 if ((((Key
==KEY_BS
|| Key
==KEY_DEL
|| Key
==KEY_NUMDEL
) && Flags
.Check(FEDITLINE_DELREMOVESBLOCKS
)) || Key
==KEY_CTRLD
) &&
768 !Flags
.Check(FEDITLINE_EDITORMODE
) && SelStart
!=-1 && SelStart
<SelEnd
)
775 int _Macro_IsExecuting
=CtrlObject
->Macro
.IsExecuting();
777 // $ 04.07.2000 IG - добавлена проврерка на запуск макроса (00025.edit.cpp.txt)
778 if (!ShiftPressed
&& (!_Macro_IsExecuting
|| (IsNavKey(Key
) && _Macro_IsExecuting
)) &&
779 !IsShiftKey(Key
) && !Recurse
&&
780 Key
!=KEY_SHIFT
&& Key
!=KEY_CTRL
&& Key
!=KEY_ALT
&&
781 Key
!=KEY_RCTRL
&& Key
!=KEY_RALT
&& Key
!=KEY_NONE
&&
783 Key
!=KEY_KILLFOCUS
&& Key
!= KEY_GOTFOCUS
&&
784 ((Key
&(~KEY_CTRLMASK
)) != KEY_LWIN
&& (Key
&(~KEY_CTRLMASK
)) != KEY_RWIN
&& (Key
&(~KEY_CTRLMASK
)) != KEY_APPS
)
787 Flags
.Clear(FEDITLINE_MARKINGBLOCK
); // хмм... а это здесь должно быть?
789 if (!Flags
.Check(FEDITLINE_PERSISTENTBLOCKS
) && !(Key
==KEY_CTRLINS
|| Key
==KEY_CTRLNUMPAD0
) &&
790 !(Key
==KEY_SHIFTDEL
||Key
==KEY_SHIFTNUMDEL
||Key
==KEY_SHIFTDECIMAL
) && !Flags
.Check(FEDITLINE_EDITORMODE
) && Key
!= KEY_CTRLQ
&&
791 !(Key
== KEY_SHIFTINS
|| Key
== KEY_SHIFTNUMPAD0
)) //Key != KEY_SHIFTINS) //??
794 зачем рисоваться, если ничего не изменилось?
796 if (SelStart
!= -1 || SelEnd
)
798 PrevSelStart
=SelStart
;
807 если Opt.DlgEULBsClear = 1, то BS в диалогах для UnChanged строки
808 удаляет такую строку также, как и Del
810 if (((Opt
.Dialogs
.EULBsClear
&& Key
==KEY_BS
) || Key
==KEY_DEL
|| Key
==KEY_NUMDEL
) &&
811 Flags
.Check(FEDITLINE_CLEARFLAG
) && CurPos
>=StrSize
)
815 Bug - Выделяем кусочек строки -> Shift-Del удяляет всю строку
816 Так должно быть только для UnChanged состояния
818 if ((Key
== KEY_SHIFTDEL
|| Key
== KEY_SHIFTNUMDEL
|| Key
== KEY_SHIFTDECIMAL
) && Flags
.Check(FEDITLINE_CLEARFLAG
) && CurPos
>=StrSize
&& SelStart
==-1)
824 if (Flags
.Check(FEDITLINE_CLEARFLAG
) && ((Key
<= 0xFFFF && Key
!=KEY_BS
) || Key
==KEY_CTRLBRACKET
||
825 Key
==KEY_CTRLBACKBRACKET
|| Key
==KEY_CTRLSHIFTBRACKET
||
826 Key
==KEY_CTRLSHIFTBACKBRACKET
|| Key
==KEY_SHIFTENTER
|| Key
==KEY_SHIFTNUMENTER
))
833 // Здесь - вызов функции вставки путей/файлов
834 if (ProcessInsPath(Key
,PrevSelStart
,PrevSelEnd
))
840 if (Key
!=KEY_NONE
&& Key
!=KEY_IDLE
&& Key
!=KEY_SHIFTINS
&& Key
!=KEY_SHIFTNUMPAD0
&& Key
!=KEY_CTRLINS
&&
841 ((unsigned int)Key
<KEY_F1
|| (unsigned int)Key
>KEY_F12
) && Key
!=KEY_ALT
&& Key
!=KEY_SHIFT
&&
842 Key
!=KEY_CTRL
&& Key
!=KEY_RALT
&& Key
!=KEY_RCTRL
&&
843 (Key
<KEY_ALT_BASE
|| Key
> KEY_ALT_BASE
+0xFFFF) && // ???? 256 ???
844 !(((unsigned int)Key
>=KEY_MACRO_BASE
&& (unsigned int)Key
<=KEY_MACRO_ENDBASE
) || ((unsigned int)Key
>=KEY_OP_BASE
&& (unsigned int)Key
<=KEY_OP_ENDBASE
)) && Key
!=KEY_CTRLQ
)
846 Flags
.Clear(FEDITLINE_CLEARFLAG
);
852 case KEY_SHIFTLEFT
: case KEY_SHIFTNUMPAD4
:
856 RecurseProcessKey(KEY_LEFT
);
858 if (!Flags
.Check(FEDITLINE_MARKINGBLOCK
))
861 Flags
.Set(FEDITLINE_MARKINGBLOCK
);
864 if (SelStart
!=-1 && SelStart
<=CurPos
)
865 Select(SelStart
,CurPos
);
868 int EndPos
= CalcPosFwd((Mask
&& *Mask
) ? CalcRTrimmedStrSize() : -1);
869 int NewStartPos
=CurPos
;
874 if (NewStartPos
>StrSize
)
877 AddSelect(NewStartPos
,EndPos
);
885 case KEY_SHIFTRIGHT
: case KEY_SHIFTNUMPAD6
:
887 if (!Flags
.Check(FEDITLINE_MARKINGBLOCK
))
890 Flags
.Set(FEDITLINE_MARKINGBLOCK
);
893 if ((SelStart
!=-1 && SelEnd
==-1) || SelEnd
>CurPos
)
895 if (CalcPosFwd() == SelEnd
)
898 Select(CalcPosFwd(), SelEnd
);
901 AddSelect(CurPos
, CalcPosFwd());
903 RecurseProcessKey(KEY_RIGHT
);
906 case KEY_CTRLSHIFTLEFT
: case KEY_CTRLSHIFTNUMPAD4
:
915 RecurseProcessKey(KEY_SHIFTLEFT
);
917 while (CurPos
>0 && !(!IsWordDiv(WordDiv(), Str
[CurPos
]) &&
918 IsWordDiv(WordDiv(),Str
[CurPos
-1]) && !IsSpace(Str
[CurPos
])))
920 if (!IsSpace(Str
[CurPos
]) && (IsSpace(Str
[CurPos
-1]) ||
921 IsWordDiv(WordDiv(), Str
[CurPos
-1])))
924 RecurseProcessKey(KEY_SHIFTLEFT
);
930 case KEY_CTRLSHIFTRIGHT
: case KEY_CTRLSHIFTNUMPAD6
:
935 RecurseProcessKey(KEY_SHIFTRIGHT
);
937 while (CurPos
<StrSize
&& !(IsWordDiv(WordDiv(), Str
[CurPos
]) &&
938 !IsWordDiv(WordDiv(), Str
[CurPos
-1])))
940 if (!IsSpace(Str
[CurPos
]) && (IsSpace(Str
[CurPos
-1]) || IsWordDiv(WordDiv(), Str
[CurPos
-1])))
943 RecurseProcessKey(KEY_SHIFTRIGHT
);
945 if (MaxLength
!=-1 && CurPos
==MaxLength
-1)
952 case KEY_SHIFTHOME
: case KEY_SHIFTNUMPAD7
:
957 RecurseProcessKey(KEY_SHIFTLEFT
);
963 case KEY_SHIFTEND
: case KEY_SHIFTNUMPAD1
:
966 int Len
= (Mask
&& *Mask
) ? CalcRTrimmedStrSize() : StrSize
;
968 int LastCurPos
=CurPos
;
970 while (CurPos
<Len
/*StrSize*/)
972 RecurseProcessKey(KEY_SHIFTRIGHT
);
974 if (LastCurPos
==CurPos
)break;
989 CurPos
= CalcPosBwd();
991 while (LeftPos
> 0 && RealPosToCell(CurPos
) <= LeftPos
)
995 LeftPos
= RealPosToCell(CellPosToReal(LeftPos
));
1000 if (!RecurseProcessKey(KEY_DEL
))
1005 case KEY_CTRLSHIFTBS
:
1007 DisableCallback
DC(m_Callback
.Active
);
1010 for (int i
=CurPos
; i
>=0; i
--)
1012 RecurseProcessKey(KEY_BS
);
1029 DisableCallback
DC(m_Callback
.Active
);
1034 int StopDelete
=FALSE
;
1036 if (CurPos
>1 && IsSpace(Str
[CurPos
-1])!=IsSpace(Str
[CurPos
-2]))
1039 RecurseProcessKey(KEY_BS
);
1041 if (!CurPos
|| StopDelete
)
1044 if (IsWordDiv(WordDiv(),Str
[CurPos
-1]))
1058 if (!Flags
.Check(FEDITLINE_PERSISTENTBLOCKS
) && (SelStart
!= -1 || Flags
.Check(FEDITLINE_CLEARFLAG
)))
1059 RecurseProcessKey(KEY_DEL
);
1066 case KEY_OP_SELWORD
:
1068 int OldCurPos
=CurPos
;
1069 PrevSelStart
=SelStart
;
1071 #if defined(MOUSEKEY)
1073 if (CurPos
>= SelStart
&& CurPos
<= SelEnd
)
1074 { // выделяем ВСЮ строку при повторном двойном клике
1082 if (CalcWordFromString(Str
,CurPos
,&SStart
,&SEnd
,WordDiv()))
1083 Select(SStart
,SEnd
+(SEnd
< StrSize
?1:0));
1086 CurPos
=OldCurPos
; // возвращаем обратно
1090 case KEY_OP_PLAINTEXT
:
1092 if (!Flags
.Check(FEDITLINE_PERSISTENTBLOCKS
))
1094 if (SelStart
!= -1 || Flags
.Check(FEDITLINE_CLEARFLAG
)) // BugZ#1053 - Неточности в $Text
1095 RecurseProcessKey(KEY_DEL
);
1098 const wchar_t *S
= eStackAsString();
1100 ProcessInsPlainText(S
);
1107 case KEY_CTRLNUMDEL
:
1108 case KEY_CTRLDECIMAL
:
1110 if (CurPos
>=StrSize
)
1114 DisableCallback
DC(m_Callback
.Active
);
1117 int MaskLen
=StrLength(Mask
);
1124 if (!CheckCharMask(Mask
[ptr
]) ||
1125 (IsSpace(Str
[ptr
]) && !IsSpace(Str
[ptr
+1])) ||
1126 (IsWordDiv(WordDiv(), Str
[ptr
])))
1131 for (int i
=0; i
<ptr
-CurPos
; i
++)
1132 RecurseProcessKey(KEY_DEL
);
1138 int StopDelete
=FALSE
;
1140 if (CurPos
<StrSize
-1 && IsSpace(Str
[CurPos
]) && !IsSpace(Str
[CurPos
+1]))
1143 RecurseProcessKey(KEY_DEL
);
1145 if (CurPos
>=StrSize
|| StopDelete
)
1148 if (IsWordDiv(WordDiv(), Str
[CurPos
]))
1161 if (Flags
.Check(FEDITLINE_READONLY
|FEDITLINE_DROPDOWNBOX
))
1168 Str
=(wchar_t *)realloc(Str
,1*sizeof(wchar_t));
1176 if (Flags
.Check(FEDITLINE_READONLY
|FEDITLINE_DROPDOWNBOX
))
1179 if (CurPos
>=StrSize
)
1182 if (!Flags
.Check(FEDITLINE_EDITBEYONDEND
))
1187 if (SelEnd
<SelStart
&& SelEnd
!=-1)
1196 Str
=(wchar_t *)realloc(Str
,(StrSize
+1)*sizeof(wchar_t));
1201 case KEY_HOME
: case KEY_NUMPAD7
:
1202 case KEY_CTRLHOME
: case KEY_CTRLNUMPAD7
:
1209 case KEY_END
: case KEY_NUMPAD1
:
1210 case KEY_CTRLEND
: case KEY_CTRLNUMPAD1
:
1211 case KEY_CTRLSHIFTEND
: case KEY_CTRLSHIFTNUMPAD1
:
1213 PrevCurPos
= CurPos
;
1214 CurPos
= (Mask
&& *Mask
) ? CalcRTrimmedStrSize() : StrSize
;
1218 case KEY_LEFT
: case KEY_NUMPAD4
: case KEY_MSWHEEL_LEFT
:
1223 PrevCurPos
= CurPos
;
1224 CurPos
= CalcPosBwd();
1230 case KEY_RIGHT
: case KEY_NUMPAD6
: case KEY_MSWHEEL_RIGHT
:
1233 PrevCurPos
= CurPos
;
1234 CurPos
= CalcPosFwd((Mask
&& *Mask
) ? CalcRTrimmedStrSize() : -1);
1238 case KEY_INS
: case KEY_NUMPAD0
:
1240 Flags
.Swap(FEDITLINE_OVERTYPE
);
1247 if (Flags
.Check(FEDITLINE_READONLY
|FEDITLINE_DROPDOWNBOX
))
1250 if (CurPos
>=StrSize
)
1255 if (SelEnd
!=-1 && CurPos
<SelEnd
)
1258 if (CurPos
<SelStart
)
1261 if (SelEnd
!=-1 && SelEnd
<=SelStart
)
1274 auto NextPos
= CalcPosFwd();
1275 if (NextPos
> CurPos
) {
1276 wmemmove(Str
+ CurPos
, Str
+ NextPos
, (StrSize
- NextPos
) + 1);
1277 StrSize
-= (NextPos
- CurPos
);
1278 wchar_t *NewStr
= (wchar_t *)realloc(Str
, (StrSize
+ 1) * sizeof(wchar_t));
1289 case KEY_CTRLLEFT
: case KEY_CTRLNUMPAD4
:
1296 CurPos
= CalcPosBwd();
1298 while (CurPos
>0 && !(!IsWordDiv(WordDiv(), Str
[CurPos
]) &&
1299 IsWordDiv(WordDiv(), Str
[CurPos
-1]) && !IsSpace(Str
[CurPos
])))
1301 if (!IsSpace(Str
[CurPos
]) && IsSpace(Str
[CurPos
-1]))
1310 case KEY_CTRLRIGHT
: case KEY_CTRLNUMPAD6
:
1312 if (CurPos
>=StrSize
)
1320 Len
= CalcRTrimmedStrSize();
1321 CurPos
= CalcPosFwd(Len
);
1326 CurPos
= CalcPosFwd();
1329 while (CurPos
<Len
/*StrSize*/ && !(IsWordDiv(WordDiv(),Str
[CurPos
]) &&
1330 !IsWordDiv(WordDiv(), Str
[CurPos
-1])))
1332 if (!IsSpace(Str
[CurPos
]) && IsSpace(Str
[CurPos
-1]))
1341 case KEY_SHIFTNUMDEL
:
1342 case KEY_SHIFTDECIMAL
:
1345 if (SelStart
==-1 || SelStart
>=SelEnd
)
1348 RecurseProcessKey(KEY_CTRLINS
);
1353 case KEY_CTRLINS
: case KEY_CTRLNUMPAD0
:
1355 if (!Flags
.Check(FEDITLINE_PASSWORDMODE
))
1357 if (SelStart
==-1 || SelStart
>=SelEnd
)
1361 std::wstring
TrimmedStr(Str
, CalcRTrimmedStrSize());
1362 CopyToClipboard(TrimmedStr
.c_str());
1366 CopyToClipboard(Str
);
1369 else if (SelEnd
<=StrSize
) // TODO: если в начало условия добавить "StrSize &&", то пропадет баг "Ctrl-Ins в пустой строке очищает клипборд"
1373 CopyToClipboard(Str
+SelStart
);
1380 case KEY_SHIFTINS
: case KEY_SHIFTNUMPAD0
:
1382 wchar_t *ClipText
=PasteFromClipboardEx(MaxLength
);
1387 if (!Flags
.Check(FEDITLINE_PERSISTENTBLOCKS
))
1389 DisableCallback
DC(m_Callback
.Active
);
1393 for (int i
=StrLength(Str
)-1; i
>=0 && IsEol(Str
[i
]); i
--)
1396 for (int i
=0; ClipText
[i
]; i
++)
1398 if (IsEol(ClipText
[i
]))
1400 if (IsEol(ClipText
[i
+1]))
1401 wmemmove(&ClipText
[i
],&ClipText
[i
+1],StrLength(&ClipText
[i
+1])+1);
1410 if (Flags
.Check(FEDITLINE_CLEARFLAG
))
1413 Flags
.Clear(FEDITLINE_CLEARFLAG
);
1414 SetString(ClipText
);
1418 InsertString(ClipText
);
1430 CursorPos
-=(CursorPos
-1) % TabSize
+1;
1432 if (CursorPos
<0) CursorPos
=0; //CursorPos=0,TabSize=1 case
1434 SetCellCurPos(CursorPos
);
1438 case KEY_SHIFTSPACE
:
1442 // _D(SysLog(L"Key=0x%08X",Key));
1443 if (Key
==KEY_ENTER
|| Key
>=EXTENDED_KEY_BASE
) // KEY_NUMENTER,KEY_IDLE,KEY_NONE covered by >=EXTENDED_KEY_BASE
1446 if (!Flags
.Check(FEDITLINE_PERSISTENTBLOCKS
))
1448 if (PrevSelStart
!=-1)
1450 SelStart
=PrevSelStart
;
1453 DisableCallback
DC(m_Callback
.Active
);
1468 int Edit::ProcessCtrlQ()
1475 Key
=GetInputRecord(&rec
);
1477 if (Key
!=KEY_NONE
&& Key
!=KEY_IDLE
&& rec
.Event
.KeyEvent
.uChar
.AsciiChar
)
1480 if (Key
==KEY_CONSOLE_BUFFER_RESIZE
)
1482 // int Dis=EditOutDisabled;
1483 // EditOutDisabled=0;
1485 // EditOutDisabled=Dis;
1491 if (!Flags.Check(FEDITLINE_PERSISTENTBLOCKS))
1496 Flags.Clear(FEDITLINE_CLEARFLAG);
1499 return InsertKey(rec
.Event
.KeyEvent
.uChar
.AsciiChar
);
1502 int Edit::ProcessInsPlainText(const wchar_t *str
)
1513 int Edit::InsertKey(int Key
)
1518 if (Flags
.Check(FEDITLINE_READONLY
|FEDITLINE_DROPDOWNBOX
))
1521 if (Key
==KEY_TAB
&& Flags
.Check(FEDITLINE_OVERTYPE
))
1524 CursorPos
+=TabSize
- (CursorPos
% TabSize
);
1525 SetCellCurPos(CursorPos
);
1531 int MaskLen
=StrLength(Mask
);
1535 if (KeyMatchedMask(Key
))
1537 if (!Flags
.Check(FEDITLINE_OVERTYPE
))
1541 while (!CheckCharMask(Mask
[i
]) && i
>CurPos
)
1544 for (int j
=i
; i
>CurPos
; i
--)
1546 if (CheckCharMask(Mask
[i
]))
1548 while (!CheckCharMask(Mask
[j
-1]))
1568 // Здесь вариант для "ввели символ из маски", например для SetAttr - ввесли '.'
1569 ;// char *Ptr=strchr(Mask+CurPos,Key);
1572 else if (CurPos
<StrSize
)
1581 if (MaxLength
== -1 || StrSize
< MaxLength
)
1583 if (CurPos
>=StrSize
)
1585 if (!(NewStr
=(wchar_t *)realloc(Str
,(CurPos
+2)*sizeof(wchar_t))))
1589 swprintf(&Str
[StrSize
],CurPos
+2,L
"%*ls",CurPos
-StrSize
,L
"");
1590 //memset(Str+StrSize,' ',CurPos-StrSize);Str[CurPos+1]=0;
1593 else if (!Flags
.Check(FEDITLINE_OVERTYPE
))
1596 if (Key
==KEY_TAB
&& (TabExpandMode
==EXPAND_NEWTABS
|| TabExpandMode
==EXPAND_ALLTABS
))
1603 if (!(NewStr
=(wchar_t *)realloc(Str
,(StrSize
+1)*sizeof(wchar_t))))
1608 if (!Flags
.Check(FEDITLINE_OVERTYPE
))
1610 wmemmove(Str
+CurPos
+1,Str
+CurPos
,StrSize
-CurPos
);
1614 if (SelEnd
!=-1 && CurPos
<SelEnd
)
1617 if (CurPos
<SelStart
)
1626 else if (Flags
.Check(FEDITLINE_OVERTYPE
))
1628 if (CurPos
< StrSize
)
1636 MessageBeep(MB_ICONHAND);*/
1641 if (changed
) Changed();
1646 void Edit::SetObjectColor(int Color
,int SelColor
,int ColorUnChanged
)
1649 this->SelColor
=SelColor
;
1650 this->ColorUnChanged
=ColorUnChanged
;
1654 void Edit::GetString(wchar_t *Str
,int MaxSize
)
1656 //far_wcsncpy(Str, this->Str,MaxSize);
1657 wmemmove(Str
,this->Str
,Min(StrSize
,MaxSize
-1));
1658 Str
[Min(StrSize
,MaxSize
-1)]=0;
1662 void Edit::GetString(FARString
&strStr
)
1668 const wchar_t* Edit::GetStringAddr()
1675 void Edit::SetHiString(const wchar_t *Str
)
1677 if (Flags
.Check(FEDITLINE_READONLY
))
1681 HiText2Str(NewStr
, Str
);
1683 SetBinaryString(NewStr
,StrLength(NewStr
));
1686 void Edit::SetString(const wchar_t *Str
, int Length
)
1688 if (Flags
.Check(FEDITLINE_READONLY
))
1692 SetBinaryString(Str
,Length
==-1?(int)StrLength(Str
):Length
);
1695 void Edit::SetEOL(const wchar_t *EOL
)
1704 else if (EOL
[1]==L
'\r' && EOL
[2]==L
'\n')
1708 else if (EOL
[0]==L
'\n')
1713 const wchar_t *Edit::GetEOL()
1715 return EOL_TYPE_CHARS
[EndType
];
1718 /* $ 25.07.2000 tran
1720 в этом методе DropDownBox не обрабатывается
1721 ибо он вызывается только из SetString и из класса Editor
1722 в Dialog он нигде не вызывается */
1723 void Edit::SetBinaryString(const wchar_t *Str
,int Length
)
1725 if (Flags
.Check(FEDITLINE_READONLY
))
1728 // коррекция вставляемого размера, если определен MaxLength
1729 if (MaxLength
!= -1 && Length
> MaxLength
)
1731 Length
=MaxLength
; // ??
1734 if (Length
>0 && !Flags
.Check(FEDITLINE_PARENT_SINGLELINE
))
1736 if (Str
[Length
-1]==L
'\r')
1743 if (Str
[Length
-1]==L
'\n')
1747 if (Length
> 0 && Str
[Length
-1]==L
'\r')
1751 if (Length
> 0 && Str
[Length
-1]==L
'\r')
1771 RefreshStrByMask(TRUE
);
1772 int maskLen
=StrLength(Mask
);
1774 for (int i
=0,j
=0; j
<maskLen
&& j
<Length
;)
1776 if (CheckCharMask(Mask
[i
]))
1780 if (KeyMatchedMask(Str
[j
]))
1787 if (goLoop
) continue;
1798 /* Здесь необходимо условие (!*Str), т.к. для очистки строки
1799 обычно вводится нечто вроде SetBinaryString("",0)
1800 Т.е. таким образом мы добиваемся "инициализации" строки с маской
1802 RefreshStrByMask(!*Str
);
1806 wchar_t *NewStr
=(wchar_t *)malloc((Length
+1)*sizeof(wchar_t));
1815 wmemcpy(this->Str
,Str
,Length
);
1816 this->Str
[Length
]=0;
1818 if (TabExpandMode
== EXPAND_ALLTABS
)
1828 void Edit::GetBinaryString(const wchar_t **Str
,const wchar_t **EOL
,int &Length
)
1833 *EOL
=EOL_TYPE_CHARS
[EndType
];
1835 Length
=StrSize
; //???
1838 int Edit::GetSelString(wchar_t *Str
, int MaxSize
)
1840 if (SelStart
==-1 || (SelEnd
!=-1 && SelEnd
<=SelStart
) ||
1852 CopyLength
=Min(MaxSize
,SelEnd
-SelStart
+1);
1854 far_wcsncpy(Str
,this->Str
+SelStart
,CopyLength
);
1858 int Edit::GetSelString(FARString
&strStr
)
1860 if (SelStart
==-1 || (SelEnd
!=-1 && SelEnd
<=SelStart
) ||
1868 CopyLength
=SelEnd
-SelStart
+1;
1869 wchar_t *lpwszStr
= strStr
.GetBuffer(CopyLength
+1);
1870 far_wcsncpy(lpwszStr
,this->Str
+SelStart
,CopyLength
);
1871 strStr
.ReleaseBuffer();
1877 void Edit::InsertString(const wchar_t *Str
)
1879 if (Flags
.Check(FEDITLINE_READONLY
|FEDITLINE_DROPDOWNBOX
))
1882 if (!Flags
.Check(FEDITLINE_PERSISTENTBLOCKS
))
1885 InsertBinaryString(Str
,StrLength(Str
));
1889 void Edit::InsertBinaryString(const wchar_t *Str
,int Length
)
1893 if (Flags
.Check(FEDITLINE_READONLY
|FEDITLINE_DROPDOWNBOX
))
1896 Flags
.Clear(FEDITLINE_CLEARFLAG
);
1901 int MaskLen
=StrLength(Mask
);
1905 //_SVS(SysLog(L"InsertBinaryString ==> Str='%ls' (Length=%d) Mask='%ls'",Str,Length,Mask+Pos));
1906 int StrLen
=(MaskLen
-Pos
>Length
)?Length
:MaskLen
-Pos
;
1909 Внесены исправления для правильной работы PasteFromClipboard
1912 for (int i
=Pos
,j
=0; j
<StrLen
+Pos
;)
1914 if (CheckCharMask(Mask
[i
]))
1918 if (j
< Length
&& KeyMatchedMask(Str
[j
]))
1921 //_SVS(SysLog(L"InsertBinaryString ==> InsertKey(Str[%d]='%c');",j,Str[j]));
1928 if (goLoop
) continue;
1932 if(Mask
[j
] == Str
[j
])
1945 //_SVS(SysLog(L"InsertBinaryString ==> this->Str='%ls'",this->Str));
1949 if (MaxLength
!= -1 && StrSize
+Length
> MaxLength
)
1951 // коррекция вставляемого размера, если определен MaxLength
1952 if (StrSize
< MaxLength
)
1954 Length
=MaxLength
-StrSize
;
1958 if (MaxLength
== -1 || StrSize
+Length
<= MaxLength
)
1962 if (!(NewStr
=(wchar_t *)realloc(this->Str
,(CurPos
+1)*sizeof(wchar_t))))
1966 swprintf(&this->Str
[StrSize
],CurPos
+1,L
"%*ls",CurPos
-StrSize
,L
"");
1967 //memset(this->Str+StrSize,' ',CurPos-StrSize);this->Str[CurPos+1]=0;
1971 int TmpSize
=StrSize
-CurPos
;
1972 wchar_t *TmpStr
=new(std::nothrow
) wchar_t[TmpSize
+16];
1977 wmemcpy(TmpStr
,&this->Str
[CurPos
],TmpSize
);
1980 if (!(NewStr
=(wchar_t *)realloc(this->Str
,(StrSize
+1)*sizeof(wchar_t))))
1987 wmemcpy(&this->Str
[CurPos
],Str
,Length
);
1990 wmemcpy(this->Str
+CurPos
,TmpStr
,TmpSize
);
1991 this->Str
[StrSize
]=0;
1994 if (TabExpandMode
== EXPAND_ALLTABS
)
2000 MessageBeep(MB_ICONHAND);*/
2005 int Edit::GetLength()
2011 // Функция установки маски ввода в объект Edit
2012 void Edit::SetInputMask(const wchar_t *InputMask
)
2017 if (InputMask
&& *InputMask
)
2019 if (!(Mask
=wcsdup(InputMask
)))
2022 RefreshStrByMask(TRUE
);
2029 // Функция обновления состояния строки ввода по содержимому Mask
2030 void Edit::RefreshStrByMask(int InitMode
)
2034 int MaskLen
=StrLength(Mask
);
2036 if (StrSize
!=MaskLen
)
2038 wchar_t *NewStr
=(wchar_t *)realloc(Str
,(MaskLen
+1)*sizeof(wchar_t));
2045 for (int i
=StrSize
; i
<MaskLen
; i
++)
2048 StrSize
=MaxLength
=MaskLen
;
2052 for (int i
=0; i
<MaskLen
; i
++)
2057 if (!CheckCharMask(Mask
[i
]))
2064 int Edit::ProcessMouse(MOUSE_EVENT_RECORD
*MouseEvent
)
2066 if (!(MouseEvent
->dwButtonState
& 3))
2069 if (MouseEvent
->dwMousePosition
.X
<X1
|| MouseEvent
->dwMousePosition
.X
>X2
||
2070 MouseEvent
->dwMousePosition
.Y
!=Y1
)
2073 //SetClearFlag(0); // пусть едитор сам заботится о снятии клеар-текста?
2074 SetCellCurPos(MouseEvent
->dwMousePosition
.X
- X1
+ LeftPos
);
2076 if (!Flags
.Check(FEDITLINE_PERSISTENTBLOCKS
))
2079 if (MouseEvent
->dwButtonState
&FROM_LEFT_1ST_BUTTON_PRESSED
)
2081 static int PrevDoubleClick
=0;
2082 static COORD PrevPosition
={0,0};
2084 if (WINPORT(GetTickCount
)()-PrevDoubleClick
<=WINPORT(GetDoubleClickTime
)() && MouseEvent
->dwEventFlags
!=MOUSE_MOVED
&&
2085 PrevPosition
.X
== MouseEvent
->dwMousePosition
.X
&& PrevPosition
.Y
== MouseEvent
->dwMousePosition
.Y
)
2093 if (MouseEvent
->dwEventFlags
==DOUBLE_CLICK
)
2095 ProcessKey(KEY_OP_SELWORD
);
2096 PrevDoubleClick
=WINPORT(GetTickCount
)();
2097 PrevPosition
=MouseEvent
->dwMousePosition
;
2113 Немного изменён алгоритм из-за необходимости
2114 добавления поиска целых слов.
2116 int Edit::Search(const FARString
& Str
,FARString
& ReplaceStr
,int Position
,int Case
,int WholeWords
,int Reverse
,int Regexp
, int *SearchLength
)
2118 return SearchString(this->Str
,this->StrSize
,Str
,ReplaceStr
,CurPos
,Position
,Case
,WholeWords
,Reverse
,Regexp
,SearchLength
,WordDiv());
2121 void Edit::InsertTab()
2126 if (Flags
.Check(FEDITLINE_READONLY
))
2130 S
=TabSize
-(Pos
% TabSize
);
2136 SelStart
+=S
-(Pos
==SelStart
?0:1);
2139 if (SelEnd
!=-1 && Pos
<SelEnd
)
2145 int PrevStrSize
=StrSize
;
2148 Str
=(wchar_t *)realloc(Str
,(StrSize
+1)*sizeof(wchar_t));
2150 wmemmove(TabPtr
+S
,TabPtr
,PrevStrSize
-Pos
);
2151 wmemset(TabPtr
,L
' ',S
);
2157 void Edit::ExpandTabs()
2162 if (Flags
.Check(FEDITLINE_READONLY
))
2167 while ((TabPtr
=(wchar_t *)wmemchr(Str
+Pos
,L
'\t',StrSize
-Pos
)))
2170 Pos
=(int)(TabPtr
-Str
);
2171 S
=TabSize
-((int)(TabPtr
-Str
) % TabSize
);
2177 SelStart
+=S
-(Pos
==SelStart
?0:1);
2180 if (SelEnd
!=-1 && Pos
<SelEnd
)
2186 int PrevStrSize
=StrSize
;
2192 Str
=(wchar_t *)realloc(Str
,(StrSize
+1)*sizeof(wchar_t));
2194 wmemmove(TabPtr
+S
,TabPtr
+1,PrevStrSize
-Pos
);
2195 wmemset(TabPtr
,L
' ',S
);
2199 if (changed
) Changed();
2203 int Edit::GetCellCurPos()
2205 return(RealPosToCell(CurPos
));
2209 void Edit::SetCellCurPos(int NewPos
)
2213 int NewPosLimit
= CalcRTrimmedStrSize();
2214 if (NewPos
> NewPosLimit
)
2215 NewPos
= NewPosLimit
;
2218 CurPos
= CellPosToReal(NewPos
);
2222 int Edit::RealPosToCell(int Pos
)
2224 return RealPosToCell(0, 0, Pos
, nullptr);
2228 int Edit::RealPosToCell(int PrevLength
, int PrevPos
, int Pos
, int* CorrectPos
)
2230 // Корректировка табов
2231 bool bCorrectPos
= CorrectPos
&& *CorrectPos
;
2236 // Инциализируем результирующую длину предыдущим значением
2237 int TabPos
= PrevLength
;
2239 // Если предыдущая позиция за концом строки, то табов там точно нет и
2240 // вычислять особо ничего не надо, иначе производим вычисление
2241 if (PrevPos
>= StrSize
)
2242 TabPos
+= Pos
-PrevPos
;
2245 // Начинаем вычисление с предыдущей позиции
2246 int Index
= PrevPos
;
2248 // Проходим по всем символам до позиции поиска, если она ещё в пределах строки,
2249 // либо до конца строки, если позиция поиска за пределами строки
2250 for (; Index
< Min(Pos
, StrSize
); Index
++)
2252 // Обрабатываем табы
2253 if (Str
[Index
] == L
'\t' && TabExpandMode
!= EXPAND_ALLTABS
)
2255 // Если есть необходимость делать корректировку табов и эта коректировка
2256 // ещё не проводилась, то увеличиваем длину обрабатываемой строки на еденицу
2261 bCorrectPos
= false;
2264 // Расчитываем длину таба с учётом настроек и текущей позиции в строке
2265 TabPos
+= TabSize
-(TabPos
%TabSize
);
2267 // Обрабатываем все остальные символы
2268 else if (IsCharFullWidth(Str
[Index
]))
2272 else if (!IsCharXxxfix(Str
[Index
]))
2277 // Если позиция находится за пределами строки, то там точно нет табов и всё просто
2279 TabPos
+= Pos
-Index
;
2286 int Edit::CellPosToReal(int Pos
)
2289 for (int CellPos
= 0; CellPos
< Pos
; Index
++)
2291 if (Index
>= StrSize
)
2293 Index
+= Pos
-CellPos
;
2297 if (Str
[Index
] == L
'\t' && TabExpandMode
!= EXPAND_ALLTABS
)
2299 int NewCellPos
= CellPos
+ TabSize
- (CellPos
%TabSize
);
2301 if (NewCellPos
> Pos
)
2304 CellPos
= NewCellPos
;
2308 CellPos
+= IsCharFullWidth(Str
[Index
]) ? 2 : 1;
2309 while (Index
+ 1 < StrSize
&& IsCharXxxfix(Str
[Index
+ 1]))
2319 void Edit::SanitizeSelectionRange()
2321 if (SelEnd
>= SelStart
&& SelStart
>= 0)
2323 while (SelStart
> 0 && IsCharXxxfix(Str
[SelStart
]))
2326 while (SelEnd
< StrSize
&& IsCharXxxfix(Str
[SelEnd
]))
2331 Если начало выделения за концом строки, надо выделение снять.
2332 17.09.2002 возвращаю обратно. Глюкодром.
2334 if (SelEnd
< SelStart
&& SelEnd
!= -1)
2340 if (SelStart
== -1 && SelEnd
== -1)
2347 void Edit::Select(int Start
,int End
)
2352 SanitizeSelectionRange();
2355 void Edit::AddSelect(int Start
,int End
)
2357 if (Start
< SelStart
|| SelStart
== -1)
2360 if (End
== -1 || (End
> SelEnd
&& SelEnd
!= -1))
2363 if (SelEnd
> StrSize
)
2366 SanitizeSelectionRange();
2370 void Edit::GetSelection(int &Start
,int &End
)
2373 Мало того, что это нарушение правил OO design'а,
2374 так это еще и источние багов.
2376 /* if (SelEnd>StrSize+1)
2378 if (SelStart>StrSize+1)
2379 SelStart=StrSize+1;*/
2392 void Edit::GetRealSelection(int &Start
,int &End
)
2399 void Edit::DeleteBlock()
2401 if (Flags
.Check(FEDITLINE_READONLY
|FEDITLINE_DROPDOWNBOX
))
2404 if (SelStart
==-1 || SelStart
>=SelEnd
)
2411 for (int i
=SelStart
; i
<SelEnd
; i
++)
2413 if (CheckCharMask(Mask
[i
]))
2421 int From
=SelStart
,To
=SelEnd
;
2423 if (From
>StrSize
)From
=StrSize
;
2425 if (To
>StrSize
)To
=StrSize
;
2427 wmemmove(Str
+From
,Str
+To
,StrSize
-To
+1);
2438 Str
=(wchar_t *)realloc(Str
,(StrSize
+1)*sizeof(wchar_t));
2443 Flags
.Clear(FEDITLINE_MARKINGBLOCK
);
2445 // OT: Проверка на корректность поведени строки при удалении и вставки
2446 if (Flags
.Check((FEDITLINE_PARENT_SINGLELINE
|FEDITLINE_PARENT_MULTILINE
)))
2456 void Edit::AddColor(ColorItem
*col
)
2458 if (!(ColorCount
& 15))
2459 ColorList
=(ColorItem
*)realloc(ColorList
,(ColorCount
+16)*sizeof(*ColorList
));
2461 ColorList
[ColorCount
++]=*col
;
2465 int Edit::DeleteColor(int ColorPos
)
2474 for (Src
=0; Src
<ColorCount
; Src
++)
2475 if (ColorPos
!=-1 && ColorList
[Src
].StartPos
!=ColorPos
)
2478 ColorList
[Dest
]=ColorList
[Src
];
2483 int DelCount
=ColorCount
-Dest
;
2496 int Edit::GetColor(ColorItem
*col
,int Item
)
2498 if (Item
>= ColorCount
)
2501 *col
=ColorList
[Item
];
2506 void Edit::ApplyColor()
2508 // Для оптимизации сохраняем вычисленные позиции между итерациями цикла
2509 int Pos
= INT_MIN
, TabPos
= INT_MIN
, TabEditorPos
= INT_MIN
;
2511 // Обрабатываем элементы ракраски
2512 for (int Col
= 0; Col
< ColorCount
; Col
++)
2514 ColorItem
*CurItem
= ColorList
+Col
;
2516 // Пропускаем элементы у которых начало больше конца
2517 if (CurItem
->StartPos
> CurItem
->EndPos
)
2520 // Отсекаем элементы заведомо не попадающие на экран
2521 if (CurItem
->StartPos
-LeftPos
> X2
&& CurItem
->EndPos
-LeftPos
< X1
)
2524 int Attr
= CurItem
->Color
;
2525 int Length
= CurItem
->EndPos
-CurItem
->StartPos
+1;
2527 if (CurItem
->StartPos
+Length
>= StrSize
)
2528 Length
= StrSize
-CurItem
->StartPos
;
2530 // Получаем начальную позицию
2531 int RealStart
, Start
;
2533 // Если предыдущая позиция равна текущей, то ничего не вычисляем
2534 // и сразу берём ранее вычисленное значение
2535 if (Pos
== CurItem
->StartPos
)
2538 Start
= TabEditorPos
;
2540 // Если вычисление идёт первый раз или предыдущая позиция больше текущей,
2541 // то производим вычисление с начала строки
2542 else if (Pos
== INT_MIN
|| CurItem
->StartPos
< Pos
)
2544 RealStart
= RealPosToCell(CurItem
->StartPos
);
2545 Start
= RealStart
-LeftPos
;
2547 // Для отптимизации делаем вычисление относительно предыдущей позиции
2550 RealStart
= RealPosToCell(TabPos
, Pos
, CurItem
->StartPos
, nullptr);
2551 Start
= RealStart
-LeftPos
;
2554 // Запоминаем вычисленные значения для их дальнейшего повторного использования
2555 Pos
= CurItem
->StartPos
;
2557 TabEditorPos
= Start
;
2559 // Пропускаем элементы раскраски у которых начальная позиция за экраном
2563 // Корректировка относительно табов (отключается, если присутвует флаг ECF_TAB1)
2564 int CorrectPos
= Attr
& ECF_TAB1
? 0 : 1;
2569 // Получаем конечную позицию
2570 int EndPos
= CurItem
->EndPos
;
2573 // Обрабатываем случай, когда предыдущая позиция равна текущей, то есть
2574 // длина раскрашиваемой строкии равна 1
2577 // Если необходимо делать корректироку относительно табов и единственный
2578 // символ строки -- это таб, то делаем расчёт с учтом корректировки,
2579 // иначе ничего не вычисялем и берём старые значения
2580 if (CorrectPos
&& EndPos
< StrSize
&& Str
[EndPos
] == L
'\t')
2582 RealEnd
= RealPosToCell(TabPos
, Pos
, ++EndPos
, nullptr);
2583 End
= RealEnd
-LeftPos
;
2592 // Если предыдущая позиция больше текущей, то производим вычисление
2593 // с начала строки (с учётом корректировки относительно табов)
2594 else if (EndPos
< Pos
)
2596 RealEnd
= RealPosToCell(0, 0, EndPos
, &CorrectPos
);
2597 EndPos
+= CorrectPos
;
2598 End
= RealEnd
-LeftPos
;
2600 // Для отптимизации делаем вычисление относительно предыдущей позиции (с учётом
2601 // корректировки относительно табов)
2604 RealEnd
= RealPosToCell(TabPos
, Pos
, EndPos
, &CorrectPos
);
2605 EndPos
+= CorrectPos
;
2606 End
= RealEnd
-LeftPos
;
2609 // Запоминаем вычисленные значения для их дальнейшего повторного использования
2614 // Пропускаем элементы раскраски у которых конечная позиция меньше левой границы экрана
2618 // Обрезаем раскраску элемента по экрану
2625 // Устанавливаем длину раскрашиваемого элемента
2626 Length
= End
-Start
+1;
2629 Length
-= CorrectPos
;
2631 // Раскрашиваем элемент, если есть что раскрашивать
2640 // Не раскрашиваем выделение
2641 SelColor
>= COL_FIRSTPALETTECOLOR
? Palette
[SelColor
-COL_FIRSTPALETTECOLOR
] : SelColor
2647 /* $ 24.09.2000 SVS $
2648 Функция Xlat - перекодировка по принципу QWERTY <-> ЙЦУКЕН
2650 void Edit::Xlat(bool All
)
2652 // Для CmdLine - если нет выделения, преобразуем всю строку
2653 if (All
&& SelStart
== -1 && !SelEnd
)
2655 ::Xlat(Str
,0,StrLength(Str
),Opt
.XLat
.Flags
);
2661 if (SelStart
!= -1 && SelStart
!= SelEnd
)
2664 SelEnd
=StrLength(Str
);
2666 ::Xlat(Str
,SelStart
,SelEnd
,Opt
.XLat
.Flags
);
2671 Если нет выделения, то обработаем текущее слово. Слово определяется на
2672 основе специальной группы разделителей.
2677 Обрабатываем только то слово, на котором стоит курсор, или то слово, что
2678 находится левее позиции курсора на 1 символ
2680 int start
=CurPos
, end
, StrSize
=StrLength(Str
);
2683 if (IsWordDiv(Opt
.XLat
.strWordDivForXlat
,Str
[start
]))
2687 DoXlat
=(!IsWordDiv(Opt
.XLat
.strWordDivForXlat
,Str
[start
]));
2692 while (start
>=0 && !IsWordDiv(Opt
.XLat
.strWordDivForXlat
,Str
[start
]))
2698 while (end
<StrSize
&& !IsWordDiv(Opt
.XLat
.strWordDivForXlat
,Str
[end
]))
2701 ::Xlat(Str
,start
,end
,Opt
.XLat
.Flags
);
2710 Проверяет: попадает ли символ в разрешённый
2711 диапазон символов, пропускаемых маской
2713 int Edit::KeyMatchedMask(int Key
)
2717 if (Mask
[CurPos
]==EDMASK_ANY
)
2719 else if (Mask
[CurPos
] == EDMASK_DSS
&& (std::iswdigit(Key
) || Key
== L
' ' || Key
== L
'-'))
2721 else if (Mask
[CurPos
] == EDMASK_DIGITS
&& (std::iswdigit(Key
) || Key
== L
' '))
2723 else if (Mask
[CurPos
] == EDMASK_DIGIT
&& (std::iswdigit(Key
)))
2725 else if (Mask
[CurPos
] == EDMASK_ALPHA
&& IsAlpha(Key
))
2727 else if (Mask
[CurPos
] == EDMASK_HEX
&& std::iswxdigit(Key
))
2733 int Edit::CheckCharMask(wchar_t Chr
)
2735 return (Chr
==EDMASK_ANY
|| Chr
==EDMASK_DIGIT
|| Chr
==EDMASK_DIGITS
|| Chr
==EDMASK_DSS
|| Chr
==EDMASK_ALPHA
|| Chr
==EDMASK_HEX
)?TRUE
:FALSE
;
2738 void Edit::SetDialogParent(DWORD Sets
)
2740 if ((Sets
&(FEDITLINE_PARENT_SINGLELINE
|FEDITLINE_PARENT_MULTILINE
)) == (FEDITLINE_PARENT_SINGLELINE
|FEDITLINE_PARENT_MULTILINE
) ||
2741 !(Sets
&(FEDITLINE_PARENT_SINGLELINE
|FEDITLINE_PARENT_MULTILINE
)))
2742 Flags
.Clear(FEDITLINE_PARENT_SINGLELINE
|FEDITLINE_PARENT_MULTILINE
);
2743 else if (Sets
&FEDITLINE_PARENT_SINGLELINE
)
2745 Flags
.Clear(FEDITLINE_PARENT_MULTILINE
);
2746 Flags
.Set(FEDITLINE_PARENT_SINGLELINE
);
2748 else if (Sets
&FEDITLINE_PARENT_MULTILINE
)
2750 Flags
.Clear(FEDITLINE_PARENT_SINGLELINE
);
2751 Flags
.Set(FEDITLINE_PARENT_MULTILINE
);
2755 void Edit::Changed(bool DelBlock
)
2757 if(m_Callback
.Active
&& m_Callback
.m_Callback
)
2759 m_Callback
.m_Callback(m_Callback
.m_Param
);
2764 SystemCPEncoder::SystemCPEncoder(int nCodePage)
2766 m_nCodePage = nCodePage;
2768 m_strName.Format(L"codepage - %d", m_nCodePage);
2771 SystemCPEncoder::~SystemCPEncoder()
2775 int __stdcall SystemCPEncoder::AddRef()
2777 return ++m_nRefCount;
2780 int __stdcall SystemCPEncoder::Release()
2782 if (!(--m_nRefCount))
2791 const wchar_t* __stdcall SystemCPEncoder::GetName()
2793 return (const wchar_t*)m_strName;
2796 int __stdcall SystemCPEncoder::Encode(
2797 const char *lpString,
2799 wchar_t *lpwszResult,
2803 int length = MultiByteToWideChar(m_nCodePage, 0, lpString, nLength, nullptr, 0);
2806 length = MultiByteToWideChar(m_nCodePage, 0, lpString, nLength, lpwszResult, nResultLength);
2811 int __stdcall SystemCPEncoder::Decode(
2812 const wchar_t *lpwszString,
2818 int length = WideCharToMultiByte(m_nCodePage, 0, lpwszString, nLength, nullptr, 0, nullptr, nullptr);
2821 length = WideCharToMultiByte(m_nCodePage, 0, lpwszString, nLength, lpResult, nResultLength, nullptr, nullptr);
2826 int __stdcall SystemCPEncoder::Transcode(
2827 const wchar_t *lpwszString,
2830 wchar_t *lpwszResult,
2834 int length = pFrom->Decode(lpwszString, nLength, nullptr, 0);
2835 char *lpDecoded = (char *)malloc(length);
2839 pFrom->Decode(lpwszString, nLength, lpDecoded, length);
2840 length = Encode(lpDecoded, length, nullptr, 0);
2843 length = Encode(lpDecoded, length, lpwszResult, nResultLength);
2853 EditControl::EditControl(ScreenObject
*pOwner
,Callback
* aCallback
,bool bAllocateData
,History
* iHistory
,FarList
* iList
,DWORD iFlags
)
2854 : Edit(pOwner
,aCallback
,bAllocateData
),
2855 pCustomCompletionList(nullptr), pHistory(iHistory
), pList(iList
),
2856 Selection(false), SelectionStart(-1), ECFlags(iFlags
)
2859 ACState
=ECFlags
.Check(EC_ENABLEAUTOCOMPLETE
)!=FALSE
;
2862 void EditControl::Show()
2871 void EditControl::Changed(bool DelBlock
)
2873 if(m_Callback
.Active
)
2876 AutoComplete(false,DelBlock
);
2880 void EditControl::SetMenuPos(VMenu
& menu
)
2882 if(ScrY
-Y1
<Min(Opt
.Dialogs
.CBoxMaxHeight
,menu
.GetItemCount())+2 && Y1
>ScrY
/2)
2884 menu
.SetPosition(X1
,Max(0,Y1
-1-Min(Opt
.Dialogs
.CBoxMaxHeight
,menu
.GetItemCount())-1),Min(ScrX
-2,X2
),Y1
-1);
2888 menu
.SetPosition(X1
,Y1
+1,X2
,0);
2893 static void FilteredAddToMenu(VMenu
&menu
, const FARString
&filter
, const FARString
&text
)
2895 if (!StrCmpNI(text
, filter
, static_cast<int>(filter
.GetLength())) && StrCmp(text
, filter
)) {
2900 void EditControl::PopulateCompletionMenu(VMenu
&ComplMenu
, const FARString
&strFilter
)
2902 SudoSilentQueryRegion ssqr
;
2903 if (pCustomCompletionList
)
2905 for (const auto &possibility
: *pCustomCompletionList
)
2906 FilteredAddToMenu(ComplMenu
, strFilter
, FARString(possibility
));
2908 if (ComplMenu
.GetItemCount() < 10)
2909 ComplMenu
.AssignHighlights(0);
2915 pHistory
->GetAllSimilar(ComplMenu
, strFilter
);
2919 for(int i
=0;i
<pList
->ItemsNumber
;i
++)
2920 FilteredAddToMenu(ComplMenu
, strFilter
, pList
->Items
[i
].Text
);
2922 if(ECFlags
.Check(EC_ENABLEFNCOMPLETE
))
2925 m_pSuggestor
.reset(new MenuFilesSuggestor
);
2927 m_pSuggestor
->Suggest(strFilter
, ComplMenu
);
2932 void EditControl::RemoveSelectedCompletionMenuItem(VMenu
&ComplMenu
)
2934 int CurPos
= ComplMenu
.GetSelectPos();
2935 if (CurPos
>= 0 && !pCustomCompletionList
&& pHistory
)
2937 FARString strName
= ComplMenu
.GetItemPtr(CurPos
)->strName
;
2938 if (pHistory
->DeleteMatching(strName
))
2940 ComplMenu
.DeleteItem(CurPos
, 1);
2941 ComplMenu
.FastShow();
2946 void EditControl::AutoCompleteProcMenu(int &Result
,bool Manual
,bool DelBlock
,int& BackKey
)
2948 VMenu
ComplMenu(nullptr,nullptr,0,0);
2949 FARString strTemp
= Str
;
2950 PopulateCompletionMenu(ComplMenu
, strTemp
);
2951 ComplMenu
.SetBottomTitle(((!pCustomCompletionList
&& pHistory
)
2952 ? Msg::EditControlHistoryFooter
: Msg::EditControlHistoryFooterNoDel
));
2954 if(ComplMenu
.GetItemCount()>1 || (ComplMenu
.GetItemCount()==1 && StrCmpI(strTemp
,ComplMenu
.GetItemPtr(0)->strName
)))
2956 ComplMenu
.SetFlags(VMENU_WRAPMODE
|VMENU_NOTCENTER
|VMENU_SHOWAMPERSAND
);
2958 if(!DelBlock
&& Opt
.AutoComplete
.AppendCompletion
&& (!Flags
.Check(FEDITLINE_PERSISTENTBLOCKS
) || Opt
.AutoComplete
.ShowList
))
2960 int SelStart
=GetLength();
2963 if(IsSlash(Str
[SelStart
-1]) && Str
[SelStart
-2] == L
'"' && IsSlash(ComplMenu
.GetItemPtr(0)->strName
.At(SelStart
-2)))
2965 Str
[SelStart
-2] = Str
[SelStart
-1];
2971 InsertString(ComplMenu
.GetItemPtr(0)->strName
.SubStr(SelStart
));
2972 Select(SelStart
, GetLength());
2975 if(Opt
.AutoComplete
.ShowList
)
2977 ChangeMacroMode
MacroMode(MACRO_AUTOCOMPLETION
);
2978 MenuItemEx EmptyItem
;
2979 ComplMenu
.AddItem(&EmptyItem
,0);
2980 SetMenuPos(ComplMenu
);
2981 ComplMenu
.SetSelectPos(0,0);
2982 ComplMenu
.SetBoxType(SHORT_SINGLE_BOX
);
2983 ComplMenu
.ClearDone();
2988 while (!ComplMenu
.Done())
2991 ComplMenu
.ReadInput(&ir
);
2992 if(!Opt
.AutoComplete
.ModalList
)
2994 int CurPos
=ComplMenu
.GetSelectPos();
2995 if(CurPos
>=0 && PrevPos
!=CurPos
)
2998 SetString(CurPos
?ComplMenu
.GetItemPtr(CurPos
)->strName
:strTemp
);
3002 if(ir
.EventType
==WINDOW_BUFFER_SIZE_EVENT
)
3004 SetMenuPos(ComplMenu
);
3007 else if(ir
.EventType
==KEY_EVENT
|| ir
.EventType
==FARMACRO_KEY_EVENT
)
3009 int MenuKey
=InputRecordToKey(&ir
);
3012 if((MenuKey
>=int(L
' ') && MenuKey
<=MAX_VKEY_CODE
) || MenuKey
==KEY_BS
|| MenuKey
==KEY_DEL
|| MenuKey
==KEY_NUMDEL
)
3017 ProcessKey(MenuKey
);
3019 if(StrCmp(strPrev
,strTemp
))
3021 ComplMenu
.DeleteItems();
3023 if(!strTemp
.IsEmpty())
3025 PopulateCompletionMenu(ComplMenu
, strTemp
);
3027 if(ComplMenu
.GetItemCount()>1 || (ComplMenu
.GetItemCount()==1 && StrCmpI(strTemp
,ComplMenu
.GetItemPtr(0)->strName
)))
3029 if(MenuKey
!=KEY_BS
&& MenuKey
!=KEY_DEL
&& MenuKey
!=KEY_NUMDEL
&& Opt
.AutoComplete
.AppendCompletion
)
3031 int SelStart
=GetLength();
3034 if(IsSlash(Str
[SelStart
-1]) && Str
[SelStart
-2] == L
'"' && IsSlash(ComplMenu
.GetItemPtr(0)->strName
.At(SelStart
-2)))
3036 Str
[SelStart
-2] = Str
[SelStart
-1];
3042 DisableCallback
DC(m_Callback
.Active
);
3043 InsertString(ComplMenu
.GetItemPtr(0)->strName
.SubStr(SelStart
));
3044 if(X2
-X1
>GetLength())
3046 Select(SelStart
, GetLength());
3048 ComplMenu
.AddItem(&EmptyItem
,0);
3049 SetMenuPos(ComplMenu
);
3050 ComplMenu
.SetSelectPos(0,0);
3055 ComplMenu
.SetExitCode(-1);
3064 // "классический" перебор
3067 ComplMenu
.ProcessKey(KEY_DOWN
);
3071 // навигация по строке ввода
3082 if(MenuKey
== KEY_LEFT
|| MenuKey
== KEY_NUMPAD4
)
3084 MenuKey
= KEY_CTRLS
;
3086 else if(MenuKey
== KEY_RIGHT
|| MenuKey
== KEY_NUMPAD6
)
3088 MenuKey
= KEY_CTRLD
;
3090 pOwner
->ProcessKey(MenuKey
);
3094 // навигация по списку
3116 case KEY_MSWHEEL_UP
:
3117 case KEY_MSWHEEL_DOWN
:
3118 case KEY_MSWHEEL_LEFT
:
3119 case KEY_MSWHEEL_RIGHT
:
3121 ComplMenu
.ProcessInput();
3125 case KEY_SHIFTNUMDEL
:
3128 RemoveSelectedCompletionMenuItem(ComplMenu
);
3135 if(Opt
.AutoComplete
.ModalList
)
3137 ComplMenu
.ProcessInput();
3142 // всё остальное закрывает список и идёт владельцу
3146 ComplMenu
.SetExitCode(-1);
3155 ComplMenu
.ProcessInput();
3158 if(Opt
.AutoComplete
.ModalList
)
3160 int ExitCode
=ComplMenu
.GetExitCode();
3163 SetString(ComplMenu
.GetItemPtr(ExitCode
)->strName
);
3170 int EditControl::AutoCompleteProc(bool Manual
,bool DelBlock
,int& BackKey
)
3173 static int Reenter
=0;
3175 if(ECFlags
.Check(EC_ENABLEAUTOCOMPLETE
) && *Str
&& !Reenter
&& (CtrlObject
->Macro
.GetCurRecord(nullptr,nullptr) == MACROMODE_NOMACRO
|| Manual
))
3178 AutoCompleteProcMenu(Result
,Manual
,DelBlock
,BackKey
);
3184 void EditControl::AutoComplete(bool Manual
,bool DelBlock
)
3187 if(AutoCompleteProc(Manual
,DelBlock
,Key
))
3190 int Wait
=WaitInMainLoop
;
3192 if(!CtrlObject
->Macro
.ProcessKey(Key
))
3193 pOwner
->ProcessKey(Key
);
3194 WaitInMainLoop
=Wait
;
3199 int EditControl::ProcessMouse(MOUSE_EVENT_RECORD
*MouseEvent
)
3201 if(Edit::ProcessMouse(MouseEvent
))
3203 while(IsMouseButtonPressed()==FROM_LEFT_1ST_BUTTON_PRESSED
)
3205 Flags
.Clear(FEDITLINE_CLEARFLAG
);
3206 SetCellCurPos(MouseX
- X1
+ LeftPos
);
3207 if(MouseEventFlags
&MOUSE_MOVED
)
3213 Select(SelectionStart
,0);
3217 if(SelectionStart
==-1)
3219 SelectionStart
=CurPos
;
3221 Select(Min(SelectionStart
,CurPos
),Min(StrSize
,Max(SelectionStart
,CurPos
)));
3232 void EditControl::EnableAC(bool Permanent
)
3234 ACState
=Permanent
?true:ECFlags
.Check(EC_ENABLEAUTOCOMPLETE
)!=FALSE
;
3235 ECFlags
.Set(EC_ENABLEAUTOCOMPLETE
);
3238 void EditControl::DisableAC(bool Permanent
)
3240 ACState
=Permanent
?false:ECFlags
.Check(EC_ENABLEAUTOCOMPLETE
)!=FALSE
;
3241 ECFlags
.Clear(EC_ENABLEAUTOCOMPLETE
);
3244 void EditControl::ShowCustomCompletionList(const std::vector
<std::string
> &list
)
3246 pCustomCompletionList
= &list
;
3247 AutoComplete(true, false);
3248 pCustomCompletionList
= nullptr;