Crtl-C gives a new line when reading input
[reactos.git] / reactos / subsys / system / cmd / cmdinput.c
index b9a944a..ab7e649 100644 (file)
  *        input queue when you pressed <RETURN>. This sometimes caused
  *        some very strange effects.
  *        Fixed some command line editing annoyances.
+ *
+ *    30-Apr-2004 (Filip Navara <xnavara@volny.cz>)
+ *        Fixed problems when the screen was scrolled away.
  */
 
-#include "config.h"
-
-#include <windows.h>
-#include <tchar.h>
-#include <string.h>
-
-#include "cmd.h"
-#include "batch.h"
+#include <precomp.h>
+#include "resource.h"
 
 
 SHORT maxx;
@@ -133,6 +130,7 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
        SHORT orgy;
        SHORT curx;                     /*current x/y cursor position*/
        SHORT cury;
+       SHORT tempscreen;
        INT   count;            /*used in some for loops*/
        INT   current = 0;      /*the position of the cursor in the string (str)*/
        INT   charcount = 0;/*chars in the string (str)*/
@@ -140,6 +138,8 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
        WORD   wLastKey = 0;
        TCHAR  ch;
        BOOL bContinue=FALSE;/*is TRUE the second case will not be executed*/
+    BOOL bReturn = FALSE;
+       TCHAR szPath[MAX_PATH];
 
        /* get screen size */
        GetScreenSize (&maxx, &maxy);
@@ -149,6 +149,7 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
                PrintPrompt();
 
        GetCursorXY (&orgx, &orgy);
+       GetCursorXY (&curx, &cury);
 
        memset (str, 0, maxlen * sizeof (TCHAR));
 
@@ -156,6 +157,9 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
 
        do
        {
+    
+        bReturn = FALSE;
+        
                ConInKey (&ir);
 
                if (ir.Event.KeyEvent.dwControlKeyState &
@@ -167,18 +171,20 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
                        {
 
 #ifdef FEATURE_HISTORY
-       
+
                                case 'K':
                                        /*add the current command line to the history*/
                                        if (ir.Event.KeyEvent.dwControlKeyState &
                                                (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
                                        {
-                               
+
                                                if (str[0])
                                                        History(0,str);
 
                                                ClearCommandLine (str, maxlen, orgx, orgy);
                                                current = charcount = 0;
+                                               curx = orgx;
+                                               cury = orgy;
                                                bContinue=TRUE;
                                                break;
                                        }
@@ -189,9 +195,10 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
                                                (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
                                        {
                                                ClearCommandLine (str, maxlen, orgx, orgy);
-                                               History_del_current_entry(str);                                 
+                                               History_del_current_entry(str);
                                                current = charcount = _tcslen (str);
                                                ConOutPrintf (_T("%s"), str);
+                                               GetCursorXY (&curx, &cury);
                                                bContinue=TRUE;
                                                break;
                                        }
@@ -200,7 +207,7 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
                        }
 
 
-                       
+
 
                }
 
@@ -221,13 +228,16 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
                                                str[current - 1] = _T('\0');
                                                if (GetCursorX () != 0)
                                                {
-                                                       ConOutPrintf ("\b \b");
+                                                       ConOutPrintf (_T("\b \b"));
+                                                       curx--;
                                                }
                                                else
                                                {
                                                        SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1));
                                                        ConOutChar (_T(' '));
                                                        SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1));
+                                                       cury--;
+                                                       curx = maxx - 1;
                                                }
                                        }
                                        else
@@ -235,9 +245,16 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
                                                for (count = current - 1; count < charcount; count++)
                                                        str[count] = str[count + 1];
                                                if (GetCursorX () != 0)
+                                               {
                                                        SetCursorXY ((SHORT)(GetCursorX () - 1), GetCursorY ());
+                                                       curx--;
+                                               }
                                                else
+                                               {
                                                        SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1));
+                                                       cury--;
+                                                       curx = maxx - 1;
+                                               }
                                                GetCursorXY (&curx, &cury);
                                                ConOutPrintf (_T("%s "), &str[current - 1]);
                                                SetCursorXY (curx, cury);
@@ -271,6 +288,8 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
                                if (current != 0)
                                {
                                        SetCursorXY (orgx, orgy);
+                                       curx = orgx;
+                                       cury = orgy;
                                        current = 0;
                                }
                                break;
@@ -281,6 +300,7 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
                                {
                                        SetCursorXY (orgx, orgy);
                                        ConOutPrintf (_T("%s"), str);
+                                       GetCursorXY (&curx, &cury);
                                        current = charcount;
                                }
                                break;
@@ -288,19 +308,38 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
                        case VK_TAB:
 #ifdef FEATURE_UNIX_FILENAME_COMPLETION
                                /* expand current file name */
-                               if (current == charcount) /* only works at end of line*/
+                               if ((current == charcount) ||
+                                   (current == charcount - 1 &&
+                                    str[current] == _T('"'))) /* only works at end of line*/
                                {
                                        if (wLastKey != VK_TAB)
                                        {
                                                /* if first TAB, complete filename*/
+                                               tempscreen = charcount;
                                                CompleteFilename (str, charcount);
                                                charcount = _tcslen (str);
                                                current = charcount;
 
                                                SetCursorXY (orgx, orgy);
                                                ConOutPrintf (_T("%s"), str);
-                                               if ((_tcslen (str) > (USHORT)(maxx - orgx)) && (orgy == maxy + 1))
-                                                       orgy--;
+
+                                               if (tempscreen > charcount)
+                                               {
+                                                       GetCursorXY (&curx, &cury);
+                                                       for (count = tempscreen - charcount; count--; )
+                                                               ConOutChar (_T(' '));
+                                                       SetCursorXY (curx, cury);
+                                               }
+                                               else
+                                               {
+                                                       if (((charcount + orgx) / maxx) + orgy > maxy - 1)
+                                                               orgy += maxy - ((charcount + orgx) / maxx + orgy + 1);
+                                               }
+
+                                               /* set cursor position */
+                                               SetCursorXY ((orgx + current) % maxx,
+                                                            orgy + (orgx + current) / maxx);
+                                               GetCursorXY (&curx, &cury);
                                        }
                                        else
                                        {
@@ -310,34 +349,76 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
                                                        PrintPrompt ();
                                                        GetCursorXY (&orgx, &orgy);
                                                        ConOutPrintf (_T("%s"), str);
+
+                                                       /* set cursor position */
+                                                       SetCursorXY ((orgx + current) % maxx,
+                                                                    orgy + (orgx + current) / maxx);
+                                                       GetCursorXY (&curx, &cury);
                                                }
-                                               
+
                                        }
                                }
                                else
                                {
-#ifdef __REACTOS__
-                                       Beep (440, 50);
-#else
                                        MessageBeep (-1);
-#endif
                                }
 #endif
 #ifdef FEATURE_4NT_FILENAME_COMPLETION
-                               /* this is not implemented yet */
-                               if (ir.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED)
-                               {
-                                       /* get previous match */
+                               
+                               /* used to later see if we went down to the next line */
+                               tempscreen = charcount;
+                               szPath[0]=_T('\0');
+
+                               /* str is the whole things that is on the current line 
+                                  that is and and out.  arg 2 is weather it goes back
+                                       one file or forward one file */
+                               CompleteFilename(str, !(ir.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED), szPath, current);
+                               /* Attempt to clear the line */
+                               ClearCommandLine (str, maxlen, orgx, orgy);
+                               curx = orgx;
+                               cury = orgy;
+                               current = charcount = 0;                                
+        //str[0]=_T('\0');
+                               
+                               /* Everything is deleted, lets add it back in */
+                               _tcscpy(str,szPath);
+        
+                               /* Figure out where cusor is going to be after we print it */
+                               charcount = _tcslen (str);
+                               current = charcount;
+
+                               SetCursorXY (orgx, orgy);
+                               /* Print out what we have now */
+                               ConOutPrintf (_T("%s"), str);
 
+                               /* Move cursor accordingly */
+                               if(tempscreen > charcount)
+                               {
+                                       GetCursorXY (&curx, &cury);
+                                       for(count = tempscreen - charcount; count--; )
+                                               ConOutChar (_T(' '));
+                                       SetCursorXY (curx, cury);
                                }
                                else
                                {
-                                       /* get next match */
-
+                                       if(((charcount + orgx) / maxx) + orgy > maxy - 1)
+                                               orgy += maxy - ((charcount + orgx) / maxx + orgy + 1);
                                }
+                               SetCursorXY((short)(((int)orgx + current) % maxx), (short)((int)orgy + ((int)orgx + current) / maxx));
+                               GetCursorXY(&curx, &cury);
+
 #endif
                                break;
-
+            
+            case _T('M'):
+            case _T('C'):
+                /* ^M does the same as return */
+                if(!(ir.Event.KeyEvent.dwControlKeyState &
+                   (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)))
+                {
+                    break;
+                }
+                    
                        case VK_RETURN:
                                /* end input, return to main */
 #ifdef FEATURE_HISTORY
@@ -347,11 +428,14 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
 #endif
                                ConInDummy ();
                                ConOutChar (_T('\n'));
+                bReturn = TRUE;
                                break;
 
                        case VK_ESCAPE:
                                /* clear str  Make this callable! */
                                ClearCommandLine (str, maxlen, orgx, orgy);
+                               curx = orgx;
+                               cury = orgy;
                                current = charcount = 0;
                                break;
 
@@ -365,7 +449,10 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
                                ClearCommandLine (str, maxlen, orgx, orgy);
                                History (-1, str);
                                current = charcount = _tcslen (str);
+                               if (((charcount + orgx) / maxx) + orgy > maxy - 1)
+                                       orgy += maxy - ((charcount + orgx) / maxx + orgy + 1);
                                ConOutPrintf (_T("%s"), str);
+                               GetCursorXY (&curx, &cury);
 #endif
                                break;
 
@@ -375,7 +462,10 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
                                ClearCommandLine (str, maxlen, orgx, orgy);
                                History (1, str);
                                current = charcount = _tcslen (str);
+                               if (((charcount + orgx) / maxx) + orgy > maxy - 1)
+                                       orgy += maxy - ((charcount + orgx) / maxx + orgy + 1);
                                ConOutPrintf (_T("%s"), str);
+                               GetCursorXY (&curx, &cury);
 #endif
                                break;
 
@@ -385,17 +475,20 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
                                {
                                        current--;
                                        if (GetCursorX () == 0)
+                                       {
                                                SetCursorXY ((SHORT)(maxx - 1), (SHORT)(GetCursorY () - 1));
+                                               curx = maxx - 1;
+                                               cury--;
+                                       }
                                        else
+                                       {
                                                SetCursorXY ((SHORT)(GetCursorX () - 1), GetCursorY ());
+                                               curx--;
+                                       }
                                }
                                else
                                {
-#ifdef __REACTOS__
-                                       Beep (440, 50);
-#else
                                        MessageBeep (-1);
-#endif
                                }
                                break;
 
@@ -405,109 +498,72 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
                                {
                                        current++;
                                        if (GetCursorX () == maxx - 1)
+                                       {
                                                SetCursorXY (0, (SHORT)(GetCursorY () + 1));
+                                               curx = 0;
+                                               cury++;
+                                       }
                                        else
+                                       {
                                                SetCursorXY ((SHORT)(GetCursorX () + 1), GetCursorY ());
+                                               curx++;
+                                       }
                                }
                                break;
 
-#if 0
-
-#ifdef FEATURE_HISTORY
-                       
-
-                       /*!!!WARNING!!!*/
-                               /*this will only work as long as the two if statement 
-                               evaluates the same expression and a break is included
-                               in each if statement.
-                               This can be used for any combination using CTRL.
-                               For other combinations is needed another system*/
-       
-                       case 'K':
-                               /*add the current command line to the history*/
-                               if (ir.Event.KeyEvent.dwControlKeyState &
-                                       (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
-                               {
-                               
-                                       if (str[0])
-                                               History(0,str);
-
-                                       ClearCommandLine (str, maxlen, orgx, orgy);
-                                       current = charcount = 0;
-                                       break;
-                               }
-
-                       case 'D':
-                               if (ir.Event.KeyEvent.dwControlKeyState &
-                                       (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
-                               {
-                                       ClearCommandLine (str, maxlen, orgx, orgy);
-                                       History_del_current_entry(str);                                 
-                                       current = charcount = _tcslen (str);
-                                       ConOutPrintf (_T("%s"), str);
-                                       break;
-                               }
-
-#endif/*FEATURE_HISTORY*/
-#endif/*0*/
-
-                       default:
+                       }
 #ifdef _UNICODE
-                               ch = ir.Event.KeyEvent.uChar.UnicodeChar;
-                               if ((ch >= 32 && ch <= 255) && (charcount != (maxlen - 2)))
+            ch = ir.Event.KeyEvent.uChar.UnicodeChar;
+            if ((ch >= 32 && ch <= 255) && (charcount != (maxlen - 2)) &&
+                !(ir.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)))
 #else
-                               ch = ir.Event.KeyEvent.uChar.AsciiChar;
-                               if (ch >= 32 && (charcount != (maxlen - 2)))
+            ch = ir.Event.KeyEvent.uChar.AsciiChar;
+            if ((UCHAR)ch >= 32 && (charcount != (maxlen - 2)) && 
+                !(ir.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)))
 #endif /* _UNICODE */
-                               {
-                                       /* insert character into string... */
-                                       if (bInsert && current != charcount)
-                                       {
-                                               for (count = charcount; count > current; count--)
-                                                       str[count] = str[count - 1];
-                                               str[current++] = ch;
-                                               if (GetCursorX () == maxx - 1)
-                                               {
-                                                       curx = 0;
-                                                       cury = GetCursorY () + 1;
-                                               }
-                                               else
-                                               {
-                                                       GetCursorXY (&curx, &cury);
-                                                       curx++;
-                                               }
-                                               ConOutPrintf (_T("%s"), &str[current - 1]);
-                                               if ((_tcslen (str) > (USHORT)(maxx - orgx)) && (orgy == maxy + 1))
-                                                       cury--;
-                                               SetCursorXY (curx, cury);
-                                               charcount++;
-                                       }
-                                       else
-                                       {
-                                               if (current == charcount)
-                                                       charcount++;
-                                               str[current++] = ch;
-                                               ConOutChar (ch);
-                                       }
-                                       if ((_tcslen (str) > (USHORT)(maxx - orgx)) && (orgy == maxy + 1))
-                                               orgy--;
-                               }
-#if 0
-                               else
-                               {
-#ifdef __REACTOS__
-                                       Beep (440, 100);
-#else
-                                       MessageBeep (-1);
-#endif
-                               }
-#endif
-                               break;
-
-               }
+            {
+                /* insert character into string... */
+                if (bInsert && current != charcount)
+                {
+                        /* If this character insertion will cause screen scrolling,
+                                                                 * adjust the saved origin of the command prompt. */
+                        tempscreen = _tcslen(str + current) + curx;
+                    if ((tempscreen % maxx) == (maxx - 1) &&
+                        (tempscreen / maxx) + cury == (maxy - 1))
+                    {
+                        orgy--;
+                        cury--;
+                    }
+
+                    for (count = charcount; count > current; count--)
+                        str[count] = str[count - 1];
+                    str[current++] = ch;
+                    if (curx == maxx - 1)
+                        curx = 0, cury++;
+                    else
+                        curx++;
+                    ConOutPrintf (_T("%s"), &str[current - 1]);
+                    SetCursorXY (curx, cury);
+                    charcount++;
+                }
+                else
+                {
+                    if (current == charcount)
+                        charcount++;
+                    str[current++] = ch;
+                    if (GetCursorX () == maxx - 1 && GetCursorY () == maxy - 1)
+                        orgy--, cury--;
+                    if (GetCursorX () == maxx - 1)
+                        curx = 0, cury++;
+                    else
+                        curx++;
+                    ConOutChar (ch);
+                }
+            }
+               
                wLastKey = ir.Event.KeyEvent.wVirtualKeyCode;
        }
-       while (ir.Event.KeyEvent.wVirtualKeyCode != VK_RETURN);
+       while (!bReturn);
 
        SetCursorType (bInsert, TRUE);
 }