2 * CMDINPUT.C - handles command input (tab completion, history, etc.).
7 * 01/14/95 (Tim Norman)
10 * 08/08/95 (Matt Rains)
11 * i have cleaned up the source code. changes now bring this source
12 * into guidelines for recommended programming practice.
13 * i have added some constants to help making changes easier.
15 * 12/12/95 (Tim Norman)
16 * added findxy() function to get max x/y coordinates to display
17 * correctly on larger screens
19 * 12/14/95 (Tim Norman)
20 * fixed the Tab completion code that Matt Rains broke by moving local
21 * variables to a more global scope and forgetting to initialize them
25 * fixed a bug in tab completion that caused filenames at the beginning
26 * of the command-line to have their first letter truncated
29 * fixed a silly bug using printf instead of fputs, where typing "%i"
32 * 6/14/97 (Steffan Kaiser)
35 * 6/7/97 (Marc Desrochers)
36 * recoded everything! now properly adjusts when text font is changed.
37 * removed findxy(), reposition(), and reprint(), as these functions
38 * were inefficient. added goxy() function as gotoxy() was buggy when
39 * the screen font was changed. the printf() problem with %i on the
40 * command line was fixed by doing printf("%s",str) instead of
41 * printf(str). Don't ask how I find em just be glad I do :)
43 * 7/12/97 (Tim Norman)
44 * Note: above changes pre-empted Steffan's ctrl-break checking.
46 * 7/7/97 (Marc Desrochers)
47 * rewrote a new findxy() because the new dir() used it. This
48 * findxy() simply returns the values of *maxx *maxy. In the
49 * future, please use the pointers, they will always be correct
50 * since they point to BIOS values.
52 * 7/8/97 (Marc Desrochers)
53 * once again removed findxy(), moved the *maxx, *maxy pointers
54 * global and included them as externs in command.h. Also added
55 * insert/overstrike capability
57 * 7/13/97 (Tim Norman)
58 * added different cursor appearance for insert/overstrike mode
60 * 7/13/97 (Tim Norman)
61 * changed my code to use _setcursortype until I can figure out why
62 * my code is crashing on some machines. It doesn't crash on mine :)
64 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
65 * added config.h include
67 * 28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
68 * put ifdef's around filename completion code.
70 * 30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
71 * moved filename completion code to filecomp.c
72 * made second TAB display list of filename matches
74 * 31-Jul-1998 (John P Price <linux-guru@gcfl.net>)
75 * Fixed bug where if you typed something, then hit HOME, then tried
76 * to type something else in insert mode, it crashed.
78 * 07-Aug-1998 (John P Price <linux-guru@gcfl.net>)
79 * Fixed carrage return output to better match MSDOS with echo
80 * on or off.(marked with "JPP 19980708")
82 * 13-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
83 * Added insert/overwrite cursor.
85 * 25-Jan-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
86 * Replaced CRT io functions by Win32 console io functions.
87 * This can handle <Shift>-<Tab> for 4NT filename completion.
88 * Unicode and redirection safe!
90 * 04-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
91 * Fixed input bug. A "line feed" character remained in the keyboard
92 * input queue when you pressed <RETURN>. This sometimes caused
93 * some very strange effects.
94 * Fixed some command line editing annoyances.
111 * global command line insert/overwrite flag
113 static BOOL bInsert
= TRUE
;
117 ClearCommandLine (LPTSTR str
, INT maxlen
, SHORT orgx
, SHORT orgy
)
121 SetCursorXY (orgx
, orgy
);
122 for (count
= 0; count
< (INT
)_tcslen (str
); count
++)
123 ConOutChar (_T(' '));
124 _tcsnset (str
, _T('\0'), maxlen
);
125 SetCursorXY (orgx
, orgy
);
129 /* read in a command line */
130 VOID
ReadCommand (LPTSTR str
, INT maxlen
)
132 SHORT orgx
; /* origin x/y */
134 SHORT curx
; /*current x/y cursor position*/
136 INT count
; /*used in some for loops*/
137 INT current
= 0; /*the position of the cursor in the string (str)*/
138 INT charcount
= 0;/*chars in the string (str)*/
142 BOOL bContinue
=FALSE
;/*is TRUE the second case will not be executed*/
144 /* get screen size */
145 GetScreenSize (&maxx
, &maxy
);
147 /* JPP 19980807 - if echo off, don't print prompt */
151 GetCursorXY (&orgx
, &orgy
);
153 memset (str
, 0, maxlen
* sizeof (TCHAR
));
155 SetCursorType (bInsert
, TRUE
);
161 if (ir
.Event
.KeyEvent
.dwControlKeyState
&
162 (RIGHT_ALT_PRESSED
|RIGHT_ALT_PRESSED
|
163 RIGHT_CTRL_PRESSED
|LEFT_CTRL_PRESSED
) )
166 switch (ir
.Event
.KeyEvent
.wVirtualKeyCode
)
169 #ifdef FEATURE_HISTORY
172 /*add the current command line to the history*/
173 if (ir
.Event
.KeyEvent
.dwControlKeyState
&
174 (LEFT_CTRL_PRESSED
|RIGHT_CTRL_PRESSED
))
180 ClearCommandLine (str
, maxlen
, orgx
, orgy
);
181 current
= charcount
= 0;
187 /*delete current history entry*/
188 if (ir
.Event
.KeyEvent
.dwControlKeyState
&
189 (LEFT_CTRL_PRESSED
|RIGHT_CTRL_PRESSED
))
191 ClearCommandLine (str
, maxlen
, orgx
, orgy
);
192 History_del_current_entry(str
);
193 current
= charcount
= _tcslen (str
);
194 ConOutPrintf (_T("%s"), str
);
199 #endif/*FEATURE_HISTORY*/
212 switch (ir
.Event
.KeyEvent
.wVirtualKeyCode
)
215 /* <BACKSPACE> - delete character to left of cursor */
216 if (current
> 0 && charcount
> 0)
218 if (current
== charcount
)
220 /* if at end of line */
221 str
[current
- 1] = _T('\0');
222 if (GetCursorX () != 0)
224 ConOutPrintf (_T("\b \b"));
228 SetCursorXY ((SHORT
)(maxx
- 1), (SHORT
)(GetCursorY () - 1));
229 ConOutChar (_T(' '));
230 SetCursorXY ((SHORT
)(maxx
- 1), (SHORT
)(GetCursorY () - 1));
235 for (count
= current
- 1; count
< charcount
; count
++)
236 str
[count
] = str
[count
+ 1];
237 if (GetCursorX () != 0)
238 SetCursorXY ((SHORT
)(GetCursorX () - 1), GetCursorY ());
240 SetCursorXY ((SHORT
)(maxx
- 1), (SHORT
)(GetCursorY () - 1));
241 GetCursorXY (&curx
, &cury
);
242 ConOutPrintf (_T("%s "), &str
[current
- 1]);
243 SetCursorXY (curx
, cury
);
251 /* toggle insert/overstrike mode */
253 SetCursorType (bInsert
, TRUE
);
257 /* delete character under cursor */
258 if (current
!= charcount
&& charcount
> 0)
260 for (count
= current
; count
< charcount
; count
++)
261 str
[count
] = str
[count
+ 1];
263 GetCursorXY (&curx
, &cury
);
264 ConOutPrintf (_T("%s "), &str
[current
]);
265 SetCursorXY (curx
, cury
);
270 /* goto beginning of string */
273 SetCursorXY (orgx
, orgy
);
279 /* goto end of string */
280 if (current
!= charcount
)
282 SetCursorXY (orgx
, orgy
);
283 ConOutPrintf (_T("%s"), str
);
289 #ifdef FEATURE_UNIX_FILENAME_COMPLETION
290 /* expand current file name */
291 if ((current
== charcount
) ||
292 (current
== charcount
- 1 &&
293 str
[current
] == _T('"'))) /* only works at end of line*/
295 if (wLastKey
!= VK_TAB
)
297 /* if first TAB, complete filename*/
298 CompleteFilename (str
, charcount
);
299 charcount
= _tcslen (str
);
303 str
[current
-1] == _T('"'))
306 SetCursorXY (orgx
, orgy
);
307 ConOutPrintf (_T("%s"), str
);
308 if ((charcount
> (USHORT
)(maxx
- orgx
)) && (orgy
== maxy
+ 1))
311 /* set cursor position */
312 SetCursorXY ((orgx
+ current
) % maxx
,
313 orgy
+ (orgx
+ current
) / maxx
);
317 /*if second TAB, list matches*/
318 if (ShowCompletionMatches (str
, charcount
))
321 GetCursorXY (&orgx
, &orgy
);
322 ConOutPrintf (_T("%s"), str
);
324 /* set cursor position */
325 SetCursorXY ((orgx
+ current
) % maxx
,
326 orgy
+ (orgx
+ current
) / maxx
);
340 #ifdef FEATURE_4NT_FILENAME_COMPLETION
341 /* this is not implemented yet */
342 if (ir
.Event
.KeyEvent
.dwControlKeyState
& SHIFT_PRESSED
)
344 /* get previous match */
356 /* end input, return to main */
357 #ifdef FEATURE_HISTORY
358 /* add to the history */
363 ConOutChar (_T('\n'));
367 /* clear str Make this callable! */
368 ClearCommandLine (str
, maxlen
, orgx
, orgy
);
369 current
= charcount
= 0;
372 #ifdef FEATURE_HISTORY
374 History_move_to_bottom();
377 #ifdef FEATURE_HISTORY
378 /* get previous command from buffer */
379 ClearCommandLine (str
, maxlen
, orgx
, orgy
);
381 current
= charcount
= _tcslen (str
);
382 ConOutPrintf (_T("%s"), str
);
387 #ifdef FEATURE_HISTORY
388 /* get next command from buffer */
389 ClearCommandLine (str
, maxlen
, orgx
, orgy
);
391 current
= charcount
= _tcslen (str
);
392 ConOutPrintf (_T("%s"), str
);
397 /* move cursor left */
401 if (GetCursorX () == 0)
402 SetCursorXY ((SHORT
)(maxx
- 1), (SHORT
)(GetCursorY () - 1));
404 SetCursorXY ((SHORT
)(GetCursorX () - 1), GetCursorY ());
417 /* move cursor right */
418 if (current
!= charcount
)
421 if (GetCursorX () == maxx
- 1)
422 SetCursorXY (0, (SHORT
)(GetCursorY () + 1));
424 SetCursorXY ((SHORT
)(GetCursorX () + 1), GetCursorY ());
430 #ifdef FEATURE_HISTORY
434 /*this will only work as long as the two if statement
435 evaluates the same expression and a break is included
436 in each if statement.
437 This can be used for any combination using CTRL.
438 For other combinations is needed another system*/
441 /*add the current command line to the history*/
442 if (ir
.Event
.KeyEvent
.dwControlKeyState
&
443 (LEFT_CTRL_PRESSED
|RIGHT_CTRL_PRESSED
))
449 ClearCommandLine (str
, maxlen
, orgx
, orgy
);
450 current
= charcount
= 0;
455 if (ir
.Event
.KeyEvent
.dwControlKeyState
&
456 (LEFT_CTRL_PRESSED
|RIGHT_CTRL_PRESSED
))
458 ClearCommandLine (str
, maxlen
, orgx
, orgy
);
459 History_del_current_entry(str
);
460 current
= charcount
= _tcslen (str
);
461 ConOutPrintf (_T("%s"), str
);
465 #endif/*FEATURE_HISTORY*/
470 ch
= ir
.Event
.KeyEvent
.uChar
.UnicodeChar
;
471 if ((ch
>= 32 && ch
<= 255) && (charcount
!= (maxlen
- 2)))
473 ch
= ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
474 if ((UCHAR
)ch
>= 32 && (charcount
!= (maxlen
- 2)))
475 #endif /* _UNICODE */
477 /* insert character into string... */
478 if (bInsert
&& current
!= charcount
)
480 for (count
= charcount
; count
> current
; count
--)
481 str
[count
] = str
[count
- 1];
483 if (GetCursorX () == maxx
- 1)
486 cury
= GetCursorY () + 1;
490 GetCursorXY (&curx
, &cury
);
493 ConOutPrintf (_T("%s"), &str
[current
- 1]);
494 if ((_tcslen (str
) > (USHORT
)(maxx
- orgx
)) && (orgy
== maxy
+ 1))
496 SetCursorXY (curx
, cury
);
501 if (current
== charcount
)
506 if ((_tcslen (str
) > (USHORT
)(maxx
- orgx
)) && (orgy
== maxy
+ 1))
522 wLastKey
= ir
.Event
.KeyEvent
.wVirtualKeyCode
;
524 while (ir
.Event
.KeyEvent
.wVirtualKeyCode
!= VK_RETURN
);
526 SetCursorType (bInsert
, TRUE
);