ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cmdinput.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.