Merge pull request #2212 from unxed/ctrl_yo
[far2l.git] / incsrch / control.c
blob6279dd4bdef42a0c0ad8b7a35616afc841ba5875
1 /*
2 FAR manager incremental search plugin, search as you type in editor.
3 Copyright (C) 1999-2019, Stanislav V. Mekhanoshin
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
18 #include "incsrch.h"
20 static void PutEvent(int Cmd)
22 register int cnt = Event.Event.KeyEvent.wRepeatCount;
23 if (!cnt)
24 cnt++;
25 do {
26 aEvents[nEvents].Flags = (unsigned char)Cmd;
27 aEvents[nEvents].AsciiChar = Event.Event.KeyEvent.uChar.AsciiChar;
28 if (++nEvents == PREVIEW_EVENTS) {
29 #if defined(WINPORT_DIRECT)
30 putwchar('\007');
31 #else
32 MessageBeep((UINT)-1);
33 #endif
34 break;
36 Cmd|= KC_FAILKILL;
37 } while (--cnt);
40 BOOL CollectEvents(void)
42 Loop:
43 while (!bTermEvent && nEvents != PREVIEW_EVENTS && WaitInput(FALSE)
44 && apiEditorControl(ECTL_READINPUT, &Event)) {
45 switch (Event.EventType) {
46 case 0: // Internal FAR (bug?)
47 case NOOP_EVENT:
48 case FOCUS_EVENT:
49 case MENU_EVENT:
50 case WINDOW_BUFFER_SIZE_EVENT:
51 case 0x8001: // KEY_EVENT&0x8000
52 continue;
53 case MOUSE_EVENT:
54 if (Event.Event.MouseEvent.dwButtonState)
55 goto Quit;
56 continue;
57 case KEY_EVENT:
58 if (!Event.Event.KeyEvent.bKeyDown)
59 continue;
60 else if (Event.Event.KeyEvent.wVirtualKeyCode == VK_MENU) {
61 aEvents[nEvents++].Flags = KC_CLEARMSG;
62 continue;
63 } else if (Event.Event.KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
64 goto Quit;
65 } else
66 switch (Event.Event.KeyEvent.wVirtualKeyCode) {
67 case VK_F1:
68 aEvents[nEvents++].Flags = KC_HELP;
69 case VK_CONTROL:
70 case VK_SHIFT:
71 case VK_NUMLOCK:
72 case VK_CAPITAL:
73 case VK_SCROLL:
74 continue;
75 case VK_ESCAPE:
76 bTermEvent = TRUE;
77 bEscape = TRUE;
78 return TRUE;
79 case VK_BACK:
80 PutEvent(KC_BACK);
81 continue;
82 case VK_RETURN:
83 if (Event.Event.KeyEvent.dwControlKeyState
84 & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
85 PutEvent((Event.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED)
86 ? KC_PREV
87 : KC_NEXT);
88 continue;
90 goto Quit;
91 case VK_INSERT:
92 if (Event.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) {
93 Paste:
94 PasteSearchText();
95 continue;
97 goto Quit;
98 case 'V':
99 case 'v':
100 if (Event.Event.KeyEvent.dwControlKeyState
101 & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
102 goto Paste;
103 default:
104 if ((Event.Event.KeyEvent.dwControlKeyState
105 & (ENHANCED_KEY | LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED
106 | RIGHT_ALT_PRESSED | RIGHT_CTRL_PRESSED))
107 || ((unsigned)Event.Event.KeyEvent.uChar.AsciiChar < 32
108 && Event.Event.KeyEvent.uChar.AsciiChar != '\t'))
109 goto Quit;
110 PutEvent(KC_CHAR);
112 continue;
113 default:
114 goto Quit;
117 if (bTermEvent) {
118 Quit:
119 bTermEvent = TRUE;
120 if (bStopOnFound) {
121 bTermEvent = FALSE;
122 goto Loop;
125 return nEvents || bTermEvent;
128 void ShowTitle(int OpenFrom)
130 int nRest;
131 TCHAR Title[TITLE_LEN + 2];
133 #if defined(UNICODE)
134 _tstrcpy(Title, TITLE_PREFIX_STR);
135 #else
136 *(DWORD *)Title = TITLE_PREFIX_STR_DWORD;
137 #endif
139 if (!bStopOnFound) {
140 nRest = ((nLen >= TITLE_LEN - TITLE_PREFIX_LEN - 1) ? TITLE_LEN - TITLE_PREFIX_LEN - 1 : nLen);
141 memcpy(&Title[TITLE_PREFIX_LEN], &sStr[nLen - nRest], nRest * sizeof(sStr[0]));
142 if (OpenFrom == OPEN_EDITOR) {
143 Title[nRest + TITLE_PREFIX_LEN] = '\0';
144 apiEditorControl(ECTL_SETTITLE, Title);
146 #ifdef VIEWVER_SUPPORT
147 else {
148 /* blank the next chars... */
149 setmem(&Title[nRest + TITLE_PREFIX_LEN], ' ',
150 sizeof(Title) / sizeof(Title[0]) - nRest - TITLE_PREFIX_LEN - 1);
151 Title[sizeof(Title) / sizeof(Title[0])] = '\0';
152 apiText(0, 0, iViewerStatusColor, Title);
153 apiText(0, 0, iViewerStatusColor, NULL);
155 #endif
157 if (bNotFound) {
158 StatusMessage(MNotFound);
159 if (bBeepOnMismatch)
160 #if defined(WINPORT_DIRECT)
161 putwchar('\007');
162 #else
163 MessageBeep((UINT)-1);
164 #endif
165 bNotFound = FALSE;
169 #ifdef __SW_ET
170 void __etRedraw(void)
172 apiEditorControl(ECTL_REDRAW, NULL);
175 void __etSelect(struct EditorSelect *pSi)
177 apiEditorControl(ECTL_SELECT, pSi);
179 #endif
181 void SelectFound(BOOL bRedraw)
183 struct EditorSelect si;
185 si.BlockType = (nLen ? BTYPE_STREAM : BTYPE_NONE);
186 si.BlockStartLine = ei.CurLine;
187 si.BlockStartPos = ei.CurPos - nLen;
188 si.BlockWidth = nLen;
189 si.BlockHeight = 1;
190 #ifdef __SW_ET
191 __etSelect(&si);
192 #else
193 apiEditorControl(ECTL_SELECT, &si);
194 #endif
195 if (bRedraw)
196 #ifdef __SW_ET
197 __etRedraw();
198 #else
199 apiEditorControl(ECTL_REDRAW, NULL);
200 #endif
203 void SetPosition(int nLine, int nPos, int nLeftPos)
205 esp.CurLine = nLine;
206 esp.CurPos = nPos;
207 esp.LeftPos = nLeftPos;
208 apiEditorControl(ECTL_SETPOSITION, &esp);
211 void PositionToView(int nLine, int nStartPos)
213 int pos = nStartPos + nLen;
215 SetPosition(nLine, pos,
216 (ei.LeftPos > nStartPos) ? (ei.WindowSizeX > pos) ? 0 : nStartPos
217 : (ei.LeftPos + ei.WindowSizeX <= pos)
218 ? (pos - ei.WindowSizeX + 1)
219 : ei.LeftPos);
221 apiEditorControl(ECTL_GETINFO, &ei);
224 void StatusMessage(int Index)
226 apiText(28, 0, 0x0E, GetMsg(Index));
227 apiText(28, 0, 0x0E, NULL);
228 if (bStopOnFound)
229 CollectEvents(); // to force FAR redraw title
232 int DialogFromTemplate(const TCHAR *sTitle, const DialogTemplateItem *aTplItems,
233 struct FarDialogItem *aDialogItems, int nItemsNumber, TCHAR *sHelpTopic, int nFocus,
234 int nDefaultButton)
236 int i;
237 int nDialogWidth = 0;
239 zeromem(aDialogItems, sizeof(struct FarDialogItem) * nItemsNumber);
240 aDialogItems[0].Type = DI_DOUBLEBOX;
241 for (i = 1; i < nItemsNumber; i++) {
242 aDialogItems[i].Type = aTplItems[i - 1].Type;
243 aDialogItems[i].X1 = aTplItems[i - 1].X1;
244 aDialogItems[i].Y1 = aTplItems[i - 1].Y1;
245 aDialogItems[i].Selected = aTplItems[i - 1].Selected;
246 aDialogItems[i].Flags = aTplItems[i - 1].Flags & ~DIFT_MSGNUM;
247 if (aTplItems[i - 1].Flags & DIFT_MSGNUM)
248 #if defined(WINPORT_DIRECT)
249 aDialogItems[i].PtrData = GetMsg(aTplItems[i - 1].Data);
250 #else
251 _tstrcpy((TCHAR *)aDialogItems[i].Data, GetMsg(aTplItems[i - 1].Data));
252 #endif
253 else if (aTplItems[i - 1].Data)
254 #if defined(WINPORT_DIRECT)
255 aDialogItems[i].PtrData = (TCHAR *)(aTplItems[i - 1].Data);
256 #else
257 _tstrcpy((TCHAR *)aDialogItems[i].Data, (TCHAR *)(aTplItems[i - 1].Data));
258 #endif
260 aDialogItems[nFocus].Focus = TRUE;
261 aDialogItems[nDefaultButton].DefaultButton = TRUE;
263 if (sTitle)
264 #if defined(WINPORT_DIRECT)
265 aDialogItems[0].PtrData = sTitle;
266 #else
267 _tstrcpy((TCHAR *)aDialogItems[0].Data, sTitle);
268 #endif
269 aDialogItems[0].X1 = 3;
270 aDialogItems[0].Y1 = 1;
271 aDialogItems[0].Y2 = aDialogItems[nItemsNumber - 1].Y1 + 1;
273 for (i = 1; i < nItemsNumber; i++) {
274 #if defined(WINPORT_DIRECT)
275 if (!aDialogItems[i].PtrData)
276 continue;
277 int w = _tstrlen((TCHAR *)aDialogItems[i].PtrData);
278 #else
279 int w = _tstrlen((TCHAR *)aDialogItems[i].Data);
280 #endif
281 if (nDialogWidth < w)
282 nDialogWidth = w;
285 nDialogWidth+= 16;
286 aDialogItems[0].X2 = nDialogWidth - 4;
288 #if defined(WINPORT_DIRECT)
289 HANDLE hDlg = apiDialogInit(ModuleNumber, -1, -1, nDialogWidth, aDialogItems[nItemsNumber - 1].Y1 + 3,
290 sHelpTopic, aDialogItems, nItemsNumber, 0, 0, NULL, 0);
291 if (hDlg == INVALID_HANDLE_VALUE)
292 return 0;
294 int Ret = apiDialogRun(hDlg);
296 for (i = 1; i < nItemsNumber; i++)
297 aDialogItems[i].Selected = apiSendDlgMessage(hDlg, DM_GETCHECK, i, 0) == BSTATE_CHECKED;
299 apiDialogFree(hDlg);
301 return Ret;
302 #else
303 return apiDialog(ModuleNumber, -1, -1, nDialogWidth, aDialogItems[0].Y2 + 2, sHelpTopic, aDialogItems,
304 nItemsNumber);
305 #endif