Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencmdinput.c
Go to the documentation of this file.
00001 /* 00002 * CMDINPUT.C - handles command input (tab completion, history, etc.). 00003 * 00004 * 00005 * History: 00006 * 00007 * 01/14/95 (Tim Norman) 00008 * started. 00009 * 00010 * 08/08/95 (Matt Rains) 00011 * i have cleaned up the source code. changes now bring this source 00012 * into guidelines for recommended programming practice. 00013 * i have added some constants to help making changes easier. 00014 * 00015 * 12/12/95 (Tim Norman) 00016 * added findxy() function to get max x/y coordinates to display 00017 * correctly on larger screens 00018 * 00019 * 12/14/95 (Tim Norman) 00020 * fixed the Tab completion code that Matt Rains broke by moving local 00021 * variables to a more global scope and forgetting to initialize them 00022 * when needed 00023 * 00024 * 8/1/96 (Tim Norman) 00025 * fixed a bug in tab completion that caused filenames at the beginning 00026 * of the command-line to have their first letter truncated 00027 * 00028 * 9/1/96 (Tim Norman) 00029 * fixed a silly bug using printf instead of fputs, where typing "%i" 00030 * confused printf :) 00031 * 00032 * 6/14/97 (Steffan Kaiser) 00033 * ctrl-break checking 00034 * 00035 * 6/7/97 (Marc Desrochers) 00036 * recoded everything! now properly adjusts when text font is changed. 00037 * removed findxy(), reposition(), and reprint(), as these functions 00038 * were inefficient. added goxy() function as gotoxy() was buggy when 00039 * the screen font was changed. the printf() problem with %i on the 00040 * command line was fixed by doing printf("%s",str) instead of 00041 * printf(str). Don't ask how I find em just be glad I do :) 00042 * 00043 * 7/12/97 (Tim Norman) 00044 * Note: above changes pre-empted Steffan's ctrl-break checking. 00045 * 00046 * 7/7/97 (Marc Desrochers) 00047 * rewrote a new findxy() because the new dir() used it. This 00048 * findxy() simply returns the values of *maxx *maxy. In the 00049 * future, please use the pointers, they will always be correct 00050 * since they point to BIOS values. 00051 * 00052 * 7/8/97 (Marc Desrochers) 00053 * once again removed findxy(), moved the *maxx, *maxy pointers 00054 * global and included them as externs in command.h. Also added 00055 * insert/overstrike capability 00056 * 00057 * 7/13/97 (Tim Norman) 00058 * added different cursor appearance for insert/overstrike mode 00059 * 00060 * 7/13/97 (Tim Norman) 00061 * changed my code to use _setcursortype until I can figure out why 00062 * my code is crashing on some machines. It doesn't crash on mine :) 00063 * 00064 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>) 00065 * added config.h include 00066 * 00067 * 28-Jul-1998 (John P Price <linux-guru@gcfl.net>) 00068 * put ifdef's around filename completion code. 00069 * 00070 * 30-Jul-1998 (John P Price <linux-guru@gcfl.net>) 00071 * moved filename completion code to filecomp.c 00072 * made second TAB display list of filename matches 00073 * 00074 * 31-Jul-1998 (John P Price <linux-guru@gcfl.net>) 00075 * Fixed bug where if you typed something, then hit HOME, then tried 00076 * to type something else in insert mode, it crashed. 00077 * 00078 * 07-Aug-1998 (John P Price <linux-guru@gcfl.net>) 00079 * Fixed carrage return output to better match MSDOS with echo 00080 * on or off.(marked with "JPP 19980708") 00081 * 00082 * 13-Dec-1998 (Eric Kohl) 00083 * Added insert/overwrite cursor. 00084 * 00085 * 25-Jan-1998 (Eric Kohl) 00086 * Replaced CRT io functions by Win32 console io functions. 00087 * This can handle <Shift>-<Tab> for 4NT filename completion. 00088 * Unicode and redirection safe! 00089 * 00090 * 04-Feb-1999 (Eric Kohl) 00091 * Fixed input bug. A "line feed" character remained in the keyboard 00092 * input queue when you pressed <RETURN>. This sometimes caused 00093 * some very strange effects. 00094 * Fixed some command line editing annoyances. 00095 * 00096 * 30-Apr-2004 (Filip Navara <xnavara@volny.cz>) 00097 * Fixed problems when the screen was scrolled away. 00098 * 00099 * 28-September-2007 (Hervé Poussineau) 00100 * Added history possibilities to right key. 00101 */ 00102 00103 #include <precomp.h> 00104 00105 00106 SHORT maxx; 00107 SHORT maxy; 00108 00109 /* 00110 * global command line insert/overwrite flag 00111 */ 00112 static BOOL bInsert = TRUE; 00113 00114 00115 static VOID 00116 ClearCommandLine (LPTSTR str, INT maxlen, SHORT orgx, SHORT orgy) 00117 { 00118 INT count; 00119 00120 SetCursorXY (orgx, orgy); 00121 for (count = 0; count < (INT)_tcslen (str); count++) 00122 ConOutChar (_T(' ')); 00123 _tcsnset (str, _T('\0'), maxlen); 00124 SetCursorXY (orgx, orgy); 00125 } 00126 00127 00128 /* read in a command line */ 00129 BOOL ReadCommand (LPTSTR str, INT maxlen) 00130 { 00131 CONSOLE_SCREEN_BUFFER_INFO csbi; 00132 SHORT orgx; /* origin x/y */ 00133 SHORT orgy; 00134 SHORT curx; /*current x/y cursor position*/ 00135 SHORT cury; 00136 SHORT tempscreen; 00137 INT count; /*used in some for loops*/ 00138 INT current = 0; /*the position of the cursor in the string (str)*/ 00139 INT charcount = 0;/*chars in the string (str)*/ 00140 INPUT_RECORD ir; 00141 #ifdef FEATURE_UNIX_FILENAME_COMPLETION 00142 WORD wLastKey = 0; 00143 #endif 00144 TCHAR ch; 00145 BOOL bReturn = FALSE; 00146 BOOL bCharInput; 00147 #ifdef FEATURE_4NT_FILENAME_COMPLETION 00148 TCHAR szPath[MAX_PATH]; 00149 #endif 00150 #ifdef FEATURE_HISTORY 00151 //BOOL bContinue=FALSE;/*is TRUE the second case will not be executed*/ 00152 TCHAR PreviousChar; 00153 #endif 00154 00155 if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) 00156 { 00157 /* No console */ 00158 HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); 00159 DWORD dwRead; 00160 CHAR chr; 00161 do 00162 { 00163 if (!ReadFile(hStdin, &chr, 1, &dwRead, NULL) || !dwRead) 00164 return FALSE; 00165 #ifdef _UNICODE 00166 MultiByteToWideChar(InputCodePage, 0, &chr, 1, &str[charcount++], 1); 00167 #endif 00168 } while (chr != '\n' && charcount < maxlen); 00169 str[charcount] = _T('\0'); 00170 return TRUE; 00171 } 00172 00173 /* get screen size */ 00174 maxx = csbi.dwSize.X; 00175 maxy = csbi.dwSize.Y; 00176 00177 curx = orgx = csbi.dwCursorPosition.X; 00178 cury = orgy = csbi.dwCursorPosition.Y; 00179 00180 memset (str, 0, maxlen * sizeof (TCHAR)); 00181 00182 SetCursorType (bInsert, TRUE); 00183 00184 do 00185 { 00186 00187 bReturn = FALSE; 00188 00189 ConInKey (&ir); 00190 00191 if (ir.Event.KeyEvent.dwControlKeyState & 00192 (RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED| 00193 RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED) ) 00194 { 00195 00196 switch (ir.Event.KeyEvent.wVirtualKeyCode) 00197 { 00198 00199 #ifdef FEATURE_HISTORY 00200 00201 case 'K': 00202 /*add the current command line to the history*/ 00203 if (ir.Event.KeyEvent.dwControlKeyState & 00204 (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)) 00205 { 00206 00207 if (str[0]) 00208 History(0,str); 00209 00210 ClearCommandLine (str, maxlen, orgx, orgy); 00211 current = charcount = 0; 00212 curx = orgx; 00213 cury = orgy; 00214 //bContinue=TRUE; 00215 break; 00216 } 00217 00218 case 'D': 00219 /*delete current history entry*/ 00220 if (ir.Event.KeyEvent.dwControlKeyState & 00221 (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)) 00222 { 00223 ClearCommandLine (str, maxlen, orgx, orgy); 00224 History_del_current_entry(str); 00225 current = charcount = _tcslen (str); 00226 ConOutPrintf (_T("%s"), str); 00227 GetCursorXY (&curx, &cury); 00228 //bContinue=TRUE; 00229 break; 00230 } 00231 00232 #endif/*FEATURE_HISTORY*/ 00233 } 00234 00235 00236 00237 00238 } 00239 00240 bCharInput = FALSE; 00241 00242 switch (ir.Event.KeyEvent.wVirtualKeyCode) 00243 { 00244 case VK_BACK: 00245 /* <BACKSPACE> - delete character to left of cursor */ 00246 if (current > 0 && charcount > 0) 00247 { 00248 if (current == charcount) 00249 { 00250 /* if at end of line */ 00251 str[current - 1] = _T('\0'); 00252 if (GetCursorX () != 0) 00253 { 00254 ConOutPrintf (_T("\b \b")); 00255 curx--; 00256 } 00257 else 00258 { 00259 SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1)); 00260 ConOutChar (_T(' ')); 00261 SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1)); 00262 cury--; 00263 curx = maxx - 1; 00264 } 00265 } 00266 else 00267 { 00268 for (count = current - 1; count < charcount; count++) 00269 str[count] = str[count + 1]; 00270 if (GetCursorX () != 0) 00271 { 00272 SetCursorXY ((SHORT)(GetCursorX () - 1), GetCursorY ()); 00273 curx--; 00274 } 00275 else 00276 { 00277 SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1)); 00278 cury--; 00279 curx = maxx - 1; 00280 } 00281 GetCursorXY (&curx, &cury); 00282 ConOutPrintf (_T("%s "), &str[current - 1]); 00283 SetCursorXY (curx, cury); 00284 } 00285 charcount--; 00286 current--; 00287 } 00288 break; 00289 00290 case VK_INSERT: 00291 /* toggle insert/overstrike mode */ 00292 bInsert ^= TRUE; 00293 SetCursorType (bInsert, TRUE); 00294 break; 00295 00296 case VK_DELETE: 00297 /* delete character under cursor */ 00298 if (current != charcount && charcount > 0) 00299 { 00300 for (count = current; count < charcount; count++) 00301 str[count] = str[count + 1]; 00302 charcount--; 00303 GetCursorXY (&curx, &cury); 00304 ConOutPrintf (_T("%s "), &str[current]); 00305 SetCursorXY (curx, cury); 00306 } 00307 break; 00308 00309 case VK_HOME: 00310 /* goto beginning of string */ 00311 if (current != 0) 00312 { 00313 SetCursorXY (orgx, orgy); 00314 curx = orgx; 00315 cury = orgy; 00316 current = 0; 00317 } 00318 break; 00319 00320 case VK_END: 00321 /* goto end of string */ 00322 if (current != charcount) 00323 { 00324 SetCursorXY (orgx, orgy); 00325 ConOutPrintf (_T("%s"), str); 00326 GetCursorXY (&curx, &cury); 00327 current = charcount; 00328 } 00329 break; 00330 00331 case VK_TAB: 00332 #ifdef FEATURE_UNIX_FILENAME_COMPLETION 00333 /* expand current file name */ 00334 if ((current == charcount) || 00335 (current == charcount - 1 && 00336 str[current] == _T('"'))) /* only works at end of line*/ 00337 { 00338 if (wLastKey != VK_TAB) 00339 { 00340 /* if first TAB, complete filename*/ 00341 tempscreen = charcount; 00342 CompleteFilename (str, charcount); 00343 charcount = _tcslen (str); 00344 current = charcount; 00345 00346 SetCursorXY (orgx, orgy); 00347 ConOutPrintf (_T("%s"), str); 00348 00349 if (tempscreen > charcount) 00350 { 00351 GetCursorXY (&curx, &cury); 00352 for (count = tempscreen - charcount; count--; ) 00353 ConOutChar (_T(' ')); 00354 SetCursorXY (curx, cury); 00355 } 00356 else 00357 { 00358 if (((charcount + orgx) / maxx) + orgy > maxy - 1) 00359 orgy += maxy - ((charcount + orgx) / maxx + orgy + 1); 00360 } 00361 00362 /* set cursor position */ 00363 SetCursorXY ((orgx + current) % maxx, 00364 orgy + (orgx + current) / maxx); 00365 GetCursorXY (&curx, &cury); 00366 } 00367 else 00368 { 00369 /*if second TAB, list matches*/ 00370 if (ShowCompletionMatches (str, charcount)) 00371 { 00372 PrintPrompt (); 00373 GetCursorXY (&orgx, &orgy); 00374 ConOutPrintf (_T("%s"), str); 00375 00376 /* set cursor position */ 00377 SetCursorXY ((orgx + current) % maxx, 00378 orgy + (orgx + current) / maxx); 00379 GetCursorXY (&curx, &cury); 00380 } 00381 00382 } 00383 } 00384 else 00385 { 00386 MessageBeep (-1); 00387 } 00388 #endif 00389 #ifdef FEATURE_4NT_FILENAME_COMPLETION 00390 00391 /* used to later see if we went down to the next line */ 00392 tempscreen = charcount; 00393 szPath[0]=_T('\0'); 00394 00395 /* str is the whole things that is on the current line 00396 that is and and out. arg 2 is weather it goes back 00397 one file or forward one file */ 00398 CompleteFilename(str, !(ir.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED), szPath, current); 00399 /* Attempt to clear the line */ 00400 ClearCommandLine (str, maxlen, orgx, orgy); 00401 curx = orgx; 00402 cury = orgy; 00403 current = charcount = 0; 00404 00405 /* Everything is deleted, lets add it back in */ 00406 _tcscpy(str,szPath); 00407 00408 /* Figure out where cusor is going to be after we print it */ 00409 charcount = _tcslen (str); 00410 current = charcount; 00411 00412 SetCursorXY (orgx, orgy); 00413 /* Print out what we have now */ 00414 ConOutPrintf (_T("%s"), str); 00415 00416 /* Move cursor accordingly */ 00417 if(tempscreen > charcount) 00418 { 00419 GetCursorXY (&curx, &cury); 00420 for(count = tempscreen - charcount; count--; ) 00421 ConOutChar (_T(' ')); 00422 SetCursorXY (curx, cury); 00423 } 00424 else 00425 { 00426 if(((charcount + orgx) / maxx) + orgy > maxy - 1) 00427 orgy += maxy - ((charcount + orgx) / maxx + orgy + 1); 00428 } 00429 SetCursorXY((short)(((int)orgx + current) % maxx), (short)((int)orgy + ((int)orgx + current) / maxx)); 00430 GetCursorXY(&curx, &cury); 00431 00432 #endif 00433 break; 00434 00435 case _T('M'): 00436 case _T('C'): 00437 /* ^M does the same as return */ 00438 bCharInput = TRUE; 00439 if(!(ir.Event.KeyEvent.dwControlKeyState & 00440 (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED))) 00441 { 00442 break; 00443 } 00444 00445 case VK_RETURN: 00446 /* end input, return to main */ 00447 #ifdef FEATURE_HISTORY 00448 /* add to the history */ 00449 if (str[0]) 00450 History (0, str); 00451 #endif 00452 str[charcount++] = _T('\n'); 00453 str[charcount] = _T('\0'); 00454 ConOutChar (_T('\n')); 00455 bReturn = TRUE; 00456 break; 00457 00458 case VK_ESCAPE: 00459 /* clear str Make this callable! */ 00460 ClearCommandLine (str, maxlen, orgx, orgy); 00461 curx = orgx; 00462 cury = orgy; 00463 current = charcount = 0; 00464 break; 00465 00466 #ifdef FEATURE_HISTORY 00467 case VK_F3: 00468 History_move_to_bottom(); 00469 #endif 00470 case VK_UP: 00471 #ifdef FEATURE_HISTORY 00472 /* get previous command from buffer */ 00473 ClearCommandLine (str, maxlen, orgx, orgy); 00474 History (-1, str); 00475 current = charcount = _tcslen (str); 00476 if (((charcount + orgx) / maxx) + orgy > maxy - 1) 00477 orgy += maxy - ((charcount + orgx) / maxx + orgy + 1); 00478 ConOutPrintf (_T("%s"), str); 00479 GetCursorXY (&curx, &cury); 00480 #endif 00481 break; 00482 00483 case VK_DOWN: 00484 #ifdef FEATURE_HISTORY 00485 /* get next command from buffer */ 00486 ClearCommandLine (str, maxlen, orgx, orgy); 00487 History (1, str); 00488 current = charcount = _tcslen (str); 00489 if (((charcount + orgx) / maxx) + orgy > maxy - 1) 00490 orgy += maxy - ((charcount + orgx) / maxx + orgy + 1); 00491 ConOutPrintf (_T("%s"), str); 00492 GetCursorXY (&curx, &cury); 00493 #endif 00494 break; 00495 00496 case VK_LEFT: 00497 /* move cursor left */ 00498 if (current > 0) 00499 { 00500 current--; 00501 if (GetCursorX () == 0) 00502 { 00503 SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1)); 00504 curx = maxx - 1; 00505 cury--; 00506 } 00507 else 00508 { 00509 SetCursorXY ((SHORT)(GetCursorX () - 1), GetCursorY ()); 00510 curx--; 00511 } 00512 } 00513 else 00514 { 00515 MessageBeep (-1); 00516 } 00517 break; 00518 00519 case VK_RIGHT: 00520 /* move cursor right */ 00521 if (current != charcount) 00522 { 00523 current++; 00524 if (GetCursorX () == maxx - 1) 00525 { 00526 SetCursorXY (0, (SHORT)(GetCursorY () + 1)); 00527 curx = 0; 00528 cury++; 00529 } 00530 else 00531 { 00532 SetCursorXY ((SHORT)(GetCursorX () + 1), GetCursorY ()); 00533 curx++; 00534 } 00535 } 00536 #ifdef FEATURE_HISTORY 00537 else 00538 { 00539 LPCTSTR last = PeekHistory(-1); 00540 if (last && charcount < (INT)_tcslen (last)) 00541 { 00542 PreviousChar = last[current]; 00543 ConOutChar(PreviousChar); 00544 GetCursorXY(&curx, &cury); 00545 str[current++] = PreviousChar; 00546 charcount++; 00547 } 00548 } 00549 #endif 00550 break; 00551 00552 default: 00553 /* This input is just a normal char */ 00554 bCharInput = TRUE; 00555 00556 } 00557 #ifdef _UNICODE 00558 ch = ir.Event.KeyEvent.uChar.UnicodeChar; 00559 if (ch >= 32 && (charcount != (maxlen - 2)) && bCharInput) 00560 #else 00561 ch = ir.Event.KeyEvent.uChar.AsciiChar; 00562 if ((UCHAR)ch >= 32 && (charcount != (maxlen - 2)) && bCharInput) 00563 #endif /* _UNICODE */ 00564 { 00565 /* insert character into string... */ 00566 if (bInsert && current != charcount) 00567 { 00568 /* If this character insertion will cause screen scrolling, 00569 * adjust the saved origin of the command prompt. */ 00570 tempscreen = _tcslen(str + current) + curx; 00571 if ((tempscreen % maxx) == (maxx - 1) && 00572 (tempscreen / maxx) + cury == (maxy - 1)) 00573 { 00574 orgy--; 00575 cury--; 00576 } 00577 00578 for (count = charcount; count > current; count--) 00579 str[count] = str[count - 1]; 00580 str[current++] = ch; 00581 if (curx == maxx - 1) 00582 curx = 0, cury++; 00583 else 00584 curx++; 00585 ConOutPrintf (_T("%s"), &str[current - 1]); 00586 SetCursorXY (curx, cury); 00587 charcount++; 00588 } 00589 else 00590 { 00591 if (current == charcount) 00592 charcount++; 00593 str[current++] = ch; 00594 if (GetCursorX () == maxx - 1 && GetCursorY () == maxy - 1) 00595 orgy--, cury--; 00596 if (GetCursorX () == maxx - 1) 00597 curx = 0, cury++; 00598 else 00599 curx++; 00600 ConOutChar (ch); 00601 } 00602 } 00603 00604 //wLastKey = ir.Event.KeyEvent.wVirtualKeyCode; 00605 } 00606 while (!bReturn); 00607 00608 SetCursorType (bInsert, TRUE); 00609 00610 #ifdef FEATURE_ALIASES 00611 /* expand all aliases */ 00612 ExpandAlias (str, maxlen); 00613 #endif /* FEATURE_ALIAS */ 00614 return TRUE; 00615 } Generated on Thu May 24 2012 04:18:21 for ReactOS by
1.7.6.1
|