Merge pull request #2212 from unxed/ctrl_yo
[far2l.git] / far2l / src / dialog.hpp
blob42fca7f7608c1409999361d157f1d45b3d605c25
1 #pragma once
3 /*
4 dialog.hpp
6 Класс диалога Dialog.
8 Предназначен для отображения модальных диалогов.
9 Является производным от класса Frame.
12 Copyright (c) 1996 Eugene Roshal
13 Copyright (c) 2000 Far Group
14 All rights reserved.
16 Redistribution and use in source and binary forms, with or without
17 modification, are permitted provided that the following conditions
18 are met:
19 1. Redistributions of source code must retain the above copyright
20 notice, this list of conditions and the following disclaimer.
21 2. Redistributions in binary form must reproduce the above copyright
22 notice, this list of conditions and the following disclaimer in the
23 documentation and/or other materials provided with the distribution.
24 3. The name of the authors may not be used to endorse or promote products
25 derived from this software without specific prior written permission.
27 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include "frame.hpp"
40 #include <farplug-wide.h>
41 #include <memory>
42 #include "vmenu.hpp"
43 #include "chgmmode.hpp"
44 #include "bitflags.hpp"
45 #include "CriticalSections.hpp"
47 class History;
49 // Флаги текущего режима диалога
50 enum DIALOG_MODES
52 DMODE_INITOBJECTS = 0x00000001, // элементы инициализарованы?
53 DMODE_CREATEOBJECTS = 0x00000002, // объекты (Edit,...) созданы?
54 DMODE_WARNINGSTYLE = 0x00000004, // Warning Dialog Style?
55 DMODE_DRAGGED = 0x00000008, // диалог двигается?
56 DMODE_ISCANMOVE = 0x00000010, // можно ли двигать диалог?
57 DMODE_ALTDRAGGED = 0x00000020, // диалог двигается по Alt-Стрелка?
58 DMODE_SMALLDIALOG = 0x00000040, // "короткий диалог"
59 DMODE_DRAWING = 0x00001000, // диалог рисуется?
60 DMODE_KEY = 0x00002000, // Идет посылка клавиш?
61 DMODE_SHOW = 0x00004000, // Диалог виден?
62 DMODE_MOUSEEVENT = 0x00008000, // Нужно посылать MouseMove в обработчик?
63 DMODE_RESIZED = 0x00010000, //
64 DMODE_ENDLOOP = 0x00020000, // Конец цикла обработки диалога?
65 DMODE_BEGINLOOP = 0x00040000, // Начало цикла обработки диалога?
66 // DMODE_OWNSITEMS =0x00080000, // если TRUE, Dialog освобождает список Item в деструкторе
67 DMODE_NODRAWSHADOW = 0x00100000, // не рисовать тень?
68 DMODE_NODRAWPANEL = 0x00200000, // не рисовать подложку?
69 DMODE_FULLSHADOW = 0x00400000,
70 DMODE_NOPLUGINS = 0x00800000,
71 DMODE_KEEPCONSOLETITLE = 0x10000000, // не изменять заголовок консоли
72 DMODE_CLICKOUTSIDE = 0x20000000, // было нажатие мыши вне диалога?
73 DMODE_MSGINTERNAL = 0x40000000, // Внутренняя Message?
74 DMODE_OLDSTYLE = 0x80000000, // Диалог в старом (до 1.70) стиле
77 // #define DIMODE_REDRAW 0x00000001 // требуется принудительная прорисовка итема?
79 #define MakeDialogItemsEx(Data, Item) \
80 DialogItemEx Item[ARRAYSIZE(Data)]; \
81 DataToItemEx(Data, Item, ARRAYSIZE(Data));
83 // Структура, описывающая автоматизацию для DIF_AUTOMATION
84 // на первом этапе - примитивная - выставление флагов у элементов для CheckBox
85 struct DialogItemAutomation
87 WORD ID; // Для этого элемента...
88 DWORD Flags[3][2]; // ...выставить вот эти флаги
89 // [0] - Unchecked, [1] - Checked, [2] - 3Checked
90 // [][0] - Set, [][1] - Skip
93 class DlgUserControl
95 public:
96 COORD CursorPos;
97 bool CursorVisible;
98 DWORD CursorSize;
100 public:
101 DlgUserControl()
103 CursorVisible(false), CursorSize(static_cast<DWORD>(-1))
105 CursorPos.X = CursorPos.Y = -1;
107 ~DlgUserControl(){};
111 Описывает один элемент диалога - внутренне представление.
112 Для плагинов это FarDialogItem (за исключением ObjPtr)
114 struct DialogItemEx
116 int Type;
117 int X1, Y1, X2, Y2;
118 int Focus;
119 union
121 DWORD_PTR Reserved;
122 int Selected;
123 FarList *ListItems;
124 int ListPos;
125 CHAR_INFO *VBuf;
127 FARString strHistory;
128 FARString strMask;
129 std::unique_ptr<DialogItemTrueColors> TrueColors;
130 DWORD Flags;
131 int DefaultButton;
133 FARString strData;
134 size_t nMaxLength;
136 WORD ID;
137 BitFlags IFlags;
138 unsigned AutoCount; // Автоматизация
139 DialogItemAutomation *AutoPtr;
140 DWORD_PTR UserData; // ассоциированные данные
142 // прочее
143 void *ObjPtr;
144 VMenu *ListPtr;
145 DlgUserControl *UCData;
147 int SelStart;
148 int SelEnd;
150 void Clear()
152 TrueColors.reset();
153 Type = 0;
154 X1 = 0;
155 Y1 = 0;
156 X2 = 0;
157 Y2 = 0;
158 Focus = 0;
159 Reserved = 0;
160 strHistory.Clear();
161 strMask.Clear();
162 Flags = 0;
163 DefaultButton = 0;
164 strData.Clear();
165 nMaxLength = 0;
166 ID = 0;
167 IFlags.ClearAll();
168 AutoCount = 0;
169 AutoPtr = nullptr;
170 UserData = 0;
171 ObjPtr = nullptr;
172 ListPtr = nullptr;
173 UCData = nullptr;
174 SelStart = 0;
175 SelEnd = 0;
178 const DialogItemEx &operator=(const DialogItemEx &Other)
180 Type = Other.Type;
181 X1 = Other.X1;
182 X2 = Other.X2;
183 Y1 = Other.Y1;
184 Y2 = Other.Y2;
185 Focus = Other.Focus;
186 Reserved = Other.Reserved;
187 Flags = Other.Flags;
188 DefaultButton = Other.DefaultButton;
189 strData = Other.strData;
190 nMaxLength = Other.nMaxLength;
191 ID = Other.ID;
192 IFlags = Other.IFlags;
193 AutoCount = Other.AutoCount;
194 AutoPtr = Other.AutoPtr;
195 UserData = Other.UserData;
196 ObjPtr = Other.ObjPtr;
197 ListPtr = Other.ListPtr;
198 UCData = Other.UCData;
199 SelStart = Other.SelStart;
200 SelEnd = Other.SelEnd;
201 return *this;
204 void Indent(int Delta)
206 X1+= Delta;
207 X2+= Delta;
210 bool AddAutomation(int id, FarDialogItemFlags UncheckedSet, FarDialogItemFlags UncheckedSkip,
211 FarDialogItemFlags CheckedSet, FarDialogItemFlags CheckedSkip, FarDialogItemFlags Checked3Set,
212 FarDialogItemFlags Checked3Skip)
214 DialogItemAutomation *Auto;
216 if ((Auto = (DialogItemAutomation *)realloc(AutoPtr,
217 sizeof(DialogItemAutomation) * (AutoCount + 1)))) {
218 AutoPtr = Auto;
219 Auto = AutoPtr + AutoCount;
220 Auto->ID = id;
221 Auto->Flags[0][0] = UncheckedSet;
222 Auto->Flags[0][1] = UncheckedSkip;
223 Auto->Flags[1][0] = CheckedSet;
224 Auto->Flags[1][1] = CheckedSkip;
225 Auto->Flags[2][0] = Checked3Set;
226 Auto->Flags[2][1] = Checked3Skip;
227 AutoCount++;
228 return true;
230 return false;
235 Описывает один элемент диалога - для сокращения объемов
236 Структура аналогичена структуре InitDialogItem (см. "Far PlugRinG
237 Russian Help Encyclopedia of Developer")
240 struct DialogDataEx
242 WORD Type;
243 short X1, Y1, X2, Y2;
244 union
246 DWORD_PTR Reserved;
247 unsigned int Selected;
248 const wchar_t *History;
249 const wchar_t *Mask;
250 FarList *ListItems;
251 int ListPos;
252 CHAR_INFO *VBuf;
254 DWORD Flags;
255 const wchar_t *Data;
258 class DlgEdit;
259 class ConsoleTitle;
261 class Dialog : public Frame
263 friend class DlgEdit;
264 friend LONG_PTR SendDlgMessageSynched(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2);
265 friend LONG_PTR WINAPI DefDlgProc(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2);
267 private:
268 ChangeMacroMode CMM;
269 INT_PTR PluginNumber; // Номер плагина, для формирования HelpTopic
270 unsigned FocusPos; // всегда известно какой элемент в фокусе
271 unsigned PrevFocusPos; // всегда известно какой элемент был в фокусе
272 int IsEnableRedraw; // Разрешена перерисовка диалога? ( 0 - разрешена)
273 int InCtlColorDlgItem;
274 BitFlags DialogMode; // Флаги текущего режима диалога
276 LONG_PTR DataDialog; // Данные, специфические для конкретного экземпляра диалога
277 // (первоначально здесь параметр, переданный в конструктор)
279 DialogItemEx **Item; // массив элементов диалога
280 DialogItemEx *pSaveItemEx; // пользовательский массив элементов диалога
282 unsigned ItemCount; // количество элементов диалога
284 ConsoleTitle *OldTitle; // предыдущий заголовок
286 FARWINDOWPROC RealDlgProc; // функция обработки диалога
288 // переменные для перемещения диалога
289 int OldX1, OldX2, OldY1, OldY2;
291 wchar_t *HelpTopic;
293 volatile int DropDownOpened; // Содержит статус комбобокса и хистори: TRUE - открыт, FALSE - закрыт.
295 CriticalSection CS;
297 int RealWidth, RealHeight;
299 GUID Id;
300 bool IdExist;
302 private:
303 void Init(FARWINDOWPROC DlgProc, LONG_PTR InitParam);
304 virtual void DisplayObject();
305 void DeleteDialogObjects();
306 int LenStrItem(int ID, const wchar_t *lpwszStr = nullptr);
308 void ShowDialog(unsigned ID = (unsigned)-1); // ID=-1 - отрисовать весь диалог
310 DWORD CtlColorDlgItem(int ItemPos, const DialogItemEx *CurItem);
312 $ 28.07.2000 SVS
313 + Изменяет фокус ввода между двумя элементами.
314 Вынесен отдельно для того, чтобы обработать DMSG_KILLFOCUS & DMSG_SETFOCUS
316 void ChangeFocus2(unsigned SetFocusPos);
318 unsigned ChangeFocus(unsigned FocusPos, int Step, int SkipGroup);
319 BOOL SelectFromEditHistory(DialogItemEx *CurItem, DlgEdit *EditLine, const wchar_t *HistoryName,
320 FARString &strStr);
321 int SelectFromComboBox(DialogItemEx *CurItem, DlgEdit *EditLine, VMenu *List);
322 int AddToEditHistory(const wchar_t *AddStr, const wchar_t *HistoryName);
324 void ProcessLastHistory(DialogItemEx *CurItem, int MsgIndex); // обработка DIF_USELASTHISTORY
326 int ProcessHighlighting(FarKey Key, unsigned FocusPos, int Translate);
327 int CheckHighlights(WORD Chr, int StartPos = 0);
329 void SelectOnEntry(unsigned Pos, BOOL Selected);
331 void CheckDialogCoord();
332 BOOL GetItemRect(unsigned I, SMALL_RECT &Rect);
333 bool ItemHasDropDownArrow(const DialogItemEx *Item);
335 // возвращает заголовок диалога (текст первого текста или фрейма)
336 const wchar_t *GetDialogTitle();
338 BOOL SetItemRect(unsigned ID, SMALL_RECT *Rect);
341 $ 23.06.2001 KM
342 + Функции программного открытия/закрытия комбобокса и хистори
343 и получения статуса открытости/закрытости комбобокса и хистори.
345 void SetDropDownOpened(int Status) { DropDownOpened = Status; }
346 int GetDropDownOpened() { return DropDownOpened; }
348 void ProcessCenterGroup();
349 unsigned ProcessRadioButton(unsigned);
351 unsigned InitDialogObjects(unsigned ID = (unsigned)-1);
353 int ProcessOpenComboBox(int Type, DialogItemEx *CurItem, unsigned CurFocusPos);
354 int ProcessMoveDialog(DWORD Key);
356 int Do_ProcessTab(int Next);
357 int Do_ProcessNextCtrl(int Next, BOOL IsRedraw = TRUE);
358 int Do_ProcessFirstCtrl();
359 int Do_ProcessSpace();
360 void SetComboBoxPos(DialogItemEx *Item = nullptr);
362 LONG_PTR CallDlgProc(int nMsg, int nParam1, LONG_PTR nParam2);
364 void ProcessKey(FarKey Key, unsigned ItemPos);
366 public:
367 Dialog(DialogItemEx *SrcItem, unsigned SrcItemCount, FARWINDOWPROC DlgProc = nullptr,
368 LONG_PTR InitParam = 0);
369 Dialog(FarDialogItem *SrcItem, unsigned SrcItemCount, FARWINDOWPROC DlgProc = nullptr,
370 LONG_PTR InitParam = 0);
371 virtual ~Dialog();
373 public:
374 virtual int ProcessKey(FarKey Key);
375 virtual int ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent);
376 virtual int64_t VMProcess(MacroOpcode OpCode, void *vParam = nullptr, int64_t iParam = 0);
377 virtual void Show();
378 virtual void Hide();
379 void FastShow() { ShowDialog(); }
381 void GetDialogObjectsData();
383 void SetDialogMode(DWORD Flags) { DialogMode.Set(Flags); }
384 bool CheckDialogMode(DWORD Flags) { return DialogMode.Check(Flags) != FALSE; }
386 // метод для перемещения диалога
387 void AdjustEditPos(int dx, int dy);
389 int IsMoving() { return DialogMode.Check(DMODE_DRAGGED); }
390 void SetModeMoving(int IsMoving) { DialogMode.Change(DMODE_ISCANMOVE, IsMoving); }
391 int GetModeMoving() { return DialogMode.Check(DMODE_ISCANMOVE); }
392 void SetDialogData(LONG_PTR NewDataDialog);
393 LONG_PTR GetDialogData() { return DataDialog; };
395 void InitDialog();
396 void Process();
397 void SetPluginNumber(INT_PTR NewPluginNumber) { PluginNumber = NewPluginNumber; }
399 void SetHelp(const wchar_t *Topic);
400 void ShowHelp();
401 int Done() { return DialogMode.Check(DMODE_ENDLOOP); }
402 void ClearDone();
403 virtual void SetExitCode(int Code);
405 void CloseDialog();
407 virtual int GetTypeAndName(FARString &strType, FARString &strName);
408 virtual int GetType() { return MODALTYPE_DIALOG; }
409 virtual const wchar_t *GetTypeName() { return L"[Dialog]"; };
411 virtual int GetMacroMode();
413 /* $ Введена для нужд CtrlAltShift OT */
414 virtual int FastHide();
415 virtual void ResizeConsole();
416 // virtual void OnDestroy();
418 // For MACRO
419 const DialogItemEx **GetAllItem() { return (const DialogItemEx **)Item; };
420 unsigned GetAllItemCount() { return ItemCount; }; // количество элементов диалога
421 unsigned GetDlgFocusPos() { return FocusPos; };
423 int SetAutomation(WORD IDParent, WORD id, FarDialogItemFlags UncheckedSet,
424 FarDialogItemFlags UncheckedSkip, FarDialogItemFlags CheckedSet, FarDialogItemFlags CheckedSkip,
425 FarDialogItemFlags Checked3Set = DIF_NONE, FarDialogItemFlags Checked3Skip = DIF_NONE);
427 LONG_PTR WINAPI DlgProc(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2);
429 virtual void SetPosition(int X1, int Y1, int X2, int Y2);
431 BOOL IsInited();
432 bool ProcessEvents();
434 void SetId(const GUID &Id);
436 friend class History;
439 typedef LONG_PTR(WINAPI *SENDDLGMESSAGE)(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2);
441 LONG_PTR WINAPI SendDlgMessage(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2);
443 LONG_PTR WINAPI DefDlgProc(HANDLE hDlg, int Msg, int Param1, LONG_PTR Param2);
445 bool IsKeyHighlighted(const wchar_t *Str, FarKey Key, int Translate, int AmpPos = -1);
447 void DataToItemEx(const DialogDataEx *Data, DialogItemEx *Item, int Count);
449 extern const wchar_t *fmtSavedDialogHistory;