CMD Enhancements:

- Fixed UNICODE build.
- Make the DIR /W behave like in Windows.
- Fixed various problems with command input going mad when the screen contents have scrolled.

svn path=/trunk/; revision=9252
This commit is contained in:
Filip Navara 2004-04-30 16:52:42 +00:00
parent 8352c9c082
commit c7eed44a94
8 changed files with 243 additions and 130 deletions

View file

@ -1,4 +1,4 @@
/* $Id: cmd.c,v 1.11 2004/04/26 20:26:15 gdalsnes Exp $
/* $Id: cmd.c,v 1.12 2004/04/30 16:52:41 navaraf Exp $
*
* CMD.C - command-line interface.
*
@ -119,6 +119,9 @@
*
* 23-Feb-2001 (Carl Nettelblad <cnettel@hem.passagen.se>)
* %envvar% replacement conflicted with for.
*
* 30-Apr-2004 (Filip Navara <xnavara@volny.cz>)
* Make MakeSureDirectoryPathExistsEx unicode safe.
*/
#include "config.h"
@ -178,41 +181,39 @@ WORD wDefColor; /* default color */
*
* FIXME: maybe put this in a header/library where everyone can use it?????
*/
BOOL WINAPI MakeSureDirectoryPathExistsEx(LPCSTR DirPath, BOOL FileAtEnd)
BOOL WINAPI MakeSureDirectoryPathExistsEx(LPCTSTR DirPath, BOOL FileAtEnd)
{
char Path[MAX_PATH];
char *SlashPos = Path;
char Slash;
BOOL bRes;
TCHAR Path[MAX_PATH];
TCHAR *SlashPos = Path;
TCHAR Slash;
BOOL bRes;
strcpy(Path, DirPath);
_tcscpy(Path, DirPath);
while ((SlashPos = _tcspbrk(SlashPos + 1, _T("\\/"))))
{
Slash = *SlashPos;
*SlashPos = 0;
while((SlashPos=strpbrk(SlashPos+1,"\\/")))
{
Slash = *SlashPos;
*SlashPos = 0;
bRes = CreateDirectory(Path, NULL);
if (bRes == FALSE && GetLastError() != ERROR_ALREADY_EXISTS)
{
return FALSE;
}
bRes = CreateDirectoryA(Path, NULL);
if (bRes == FALSE && GetLastError() != ERROR_ALREADY_EXISTS)
{
return FALSE;
}
*SlashPos = Slash;
if (*(SlashPos + 1) == 0) return TRUE;
}
*SlashPos = Slash;
if (!FileAtEnd)
{
bRes = CreateDirectory(Path, NULL);
if (bRes == FALSE && GetLastError() != ERROR_ALREADY_EXISTS)
{
return FALSE;
}
}
if (*(SlashPos+1) == 0) return TRUE;
}
if (!FileAtEnd)
{
bRes = CreateDirectoryA(Path, NULL);
if (bRes == FALSE && GetLastError() != ERROR_ALREADY_EXISTS)
{
return FALSE;
}
}
return TRUE;
return TRUE;
}
@ -564,7 +565,7 @@ VOID ParseCommandLine (LPTSTR cmd)
#ifdef FEATURE_REDIRECTION
/* find the temp path to store temporary files */
GetTempPath (MAX_PATH, szTempPath);
MakeSureDirectoryPathExistsEx(szTempPath, FALSE);
MakeSureDirectoryPathExistsEx(szTempPath, FALSE);
if (szTempPath[_tcslen (szTempPath) - 1] != _T('\\'))
_tcscat (szTempPath, _T("\\"));

View file

@ -92,6 +92,9 @@
* 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"
@ -133,6 +136,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)*/
@ -149,6 +153,7 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
PrintPrompt();
GetCursorXY (&orgx, &orgy);
GetCursorXY (&curx, &cury);
memset (str, 0, maxlen * sizeof (TCHAR));
@ -179,6 +184,8 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
ClearCommandLine (str, maxlen, orgx, orgy);
current = charcount = 0;
curx = orgx;
cury = orgy;
bContinue=TRUE;
break;
}
@ -192,6 +199,7 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
History_del_current_entry(str);
current = charcount = _tcslen (str);
ConOutPrintf (_T("%s"), str);
GetCursorXY (&curx, &cury);
bContinue=TRUE;
break;
}
@ -222,12 +230,15 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
if (GetCursorX () != 0)
{
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 +246,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 +289,8 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
if (current != 0)
{
SetCursorXY (orgx, orgy);
curx = orgx;
cury = orgy;
current = 0;
}
break;
@ -281,6 +301,7 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
{
SetCursorXY (orgx, orgy);
ConOutPrintf (_T("%s"), str);
GetCursorXY (&curx, &cury);
current = charcount;
}
break;
@ -295,6 +316,7 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
if (wLastKey != VK_TAB)
{
/* if first TAB, complete filename*/
tempscreen = charcount;
CompleteFilename (str, charcount);
charcount = _tcslen (str);
current = charcount;
@ -305,12 +327,24 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
SetCursorXY (orgx, orgy);
ConOutPrintf (_T("%s"), str);
if ((charcount > (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
{
@ -324,6 +358,7 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
/* set cursor position */
SetCursorXY ((orgx + current) % maxx,
orgy + (orgx + current) / maxx);
GetCursorXY (&curx, &cury);
}
}
@ -366,6 +401,8 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
case VK_ESCAPE:
/* clear str Make this callable! */
ClearCommandLine (str, maxlen, orgx, orgy);
curx = orgx;
cury = orgy;
current = charcount = 0;
break;
@ -379,7 +416,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;
@ -389,7 +429,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;
@ -399,9 +442,16 @@ 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
{
@ -419,52 +469,19 @@ 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;
@ -477,22 +494,24 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
/* 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 (GetCursorX () == maxx - 1)
{
curx = 0;
cury = GetCursorY () + 1;
}
if (curx == maxx - 1)
curx = 0, cury++;
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++;
}
@ -501,10 +520,14 @@ VOID ReadCommand (LPTSTR str, INT maxlen)
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);
}
if ((_tcslen (str) > (USHORT)(maxx - orgx)) && (orgy == maxy + 1))
orgy--;
}
#if 0
else

View file

@ -1,4 +1,4 @@
/* $Id: console.c,v 1.4 2003/08/13 05:18:40 jimtabor Exp $
/* $Id: console.c,v 1.5 2004/04/30 16:52:41 navaraf Exp $
*
* CONSOLE.C - console input/output functions.
*
@ -106,8 +106,8 @@ VOID ConInString (LPTSTR lpInput, DWORD dwLength)
DWORD i;
PCHAR pBuf;
#ifdef UNICODE
pBuf = (PCHAR)alloca(dwLength);
#ifdef _UNICODE
pBuf = (PCHAR)malloc(dwLength);
#else
pBuf = lpInput;
#endif
@ -132,6 +132,10 @@ VOID ConInString (LPTSTR lpInput, DWORD dwLength)
}
}
#ifdef _UNICODE
free(pBuf);
#endif
SetConsoleMode (hFile, dwOldMode);
}
@ -169,7 +173,7 @@ VOID ConPuts(LPTSTR szText, DWORD nStdHandle)
len = _tcslen(szText);
#ifdef _UNICODE
pBuf = alloca(len + 1);
pBuf = malloc(len + 1);
len = WideCharToMultiByte(CP_ACP, 0, szText, len + 1, pBuf, len + 1, NULL, NULL) - 1;
#else
pBuf = szText;
@ -184,6 +188,9 @@ VOID ConPuts(LPTSTR szText, DWORD nStdHandle)
1,
&dwWritten,
NULL);
#ifdef UNICODE
free(pBuf);
#endif
}
VOID ConOutPuts (LPTSTR szText)
@ -201,7 +208,7 @@ VOID ConPrintf(LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
len = _vstprintf (szOut, szFormat, arg_ptr);
#ifdef _UNICODE
pBuf = alloca(len + 1);
pBuf = malloc(len + 1);
len = WideCharToMultiByte(CP_ACP, 0, szOut, len + 1, pBuf, len + 1, NULL, NULL) - 1;
#else
pBuf = szOut;
@ -211,6 +218,9 @@ VOID ConPrintf(LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
len,
&dwWritten,
NULL);
#ifdef UNICODE
free(pBuf);
#endif
}

View file

@ -1,4 +1,4 @@
/* $Id: dir.c,v 1.8 2004/01/28 17:47:27 gvg Exp $
/* $Id: dir.c,v 1.9 2004/04/30 16:52:41 navaraf Exp $
*
* DIR.C - dir internal command.
*
@ -116,6 +116,9 @@
*
* 28-Jan-2004 (Michael Fritscher <michael@fritscher.net>)
* Fix for /p, so it is working under Windows in GUI-mode, too.
*
* 30-Apr-2004 (Filip Navara <xnavara@volny.cz>)
* Fix /w to print long names.
*/
#include "config.h"
@ -131,10 +134,6 @@
#include "cmd.h"
typedef BOOL STDCALL
(*PGETFREEDISKSPACEEX)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
/* flag definitions */
enum
{
@ -150,6 +149,10 @@ enum
};
typedef BOOL STDCALL
(*PGETFREEDISKSPACEEX)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
/* Globally save the # of dirs, files and bytes,
* probabaly later pass them to functions. Rob Lake */
static ULONG recurse_dir_cnt;
@ -282,19 +285,36 @@ DirReadParam (LPTSTR line, LPTSTR *param, LPDWORD lpFlags)
{
if (*param)
{
error_too_many_parameters (*param);
error_too_many_parameters (line);
return FALSE;
}
*param = line;
/* skip to end of line or next whitespace or next / */
while (*line && !_istspace (*line) && *line != _T('/'))
if (*line != _T('\"'))
{
while (*line && !_istspace (*line) && *line != _T('/'))
line++;
/* if end of line, return */
if (!*line)
return TRUE;
}
else
{
/* skip over the initial quote */
(*param)++;
line++;
/* if end of line, return */
if (!*line)
return TRUE;
while (*line && *line != _T('"'))
line++;
if (*line == _T('"'))
*line = 0;
else
return TRUE;
}
/* if parameter, remember to process it later */
if (*line == _T('/'))
@ -843,6 +863,8 @@ DirList (LPTSTR szPath, LPTSTR szFilespec, LPINT pLine, DWORD dwFlags)
ULONG filecount = 0;
ULONG dircount = 0;
INT count;
USHORT screenwidth;
INT longestfname = 0;
bytecount.QuadPart = 0;
@ -869,6 +891,34 @@ DirList (LPTSTR szPath, LPTSTR szFilespec, LPINT pLine, DWORD dwFlags)
return 0;
}
/* Get the size of longest filename for wide listing. FN */
if (dwFlags & DIR_WIDE && (dwFlags & DIR_BARE) == 0)
{
do
{
if (_tcslen(file.cFileName) > longestfname)
{
longestfname = _tcslen(file.cFileName);
/* Directories get extra brackets around them. */
if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
longestfname += 2;
}
}
while (FindNextFile (hFile, &file));
FindClose (hFile);
hFile = FindFirstFile (szFullPath, &file);
/* Count the highest number of columns */
GetScreenSize(&screenwidth, 0);
/* For counting columns of output */
count = 0;
/* Increase by the number of spaces behind file name */
longestfname += 3;
}
/* moved down here because if we are recursively searching and
* don't find any files, we don't want just to print
* Directory of C:\SOMEDIR
@ -885,9 +935,6 @@ DirList (LPTSTR szPath, LPTSTR szFilespec, LPINT pLine, DWORD dwFlags)
return 1;
}
/* For counting columns of output */
count = 0;
do
{
/* next file, if user doesn't want all files */
@ -907,27 +954,24 @@ DirList (LPTSTR szPath, LPTSTR szFilespec, LPINT pLine, DWORD dwFlags)
if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (file.cAlternateFileName[0] == _T('\0'))
_stprintf (buffer, _T("[%s]"), file.cFileName);
else
_stprintf (buffer, _T("[%s]"), file.cAlternateFileName);
_stprintf (buffer, _T("[%s]"), file.cFileName);
dircount++;
}
else
{
if (file.cAlternateFileName[0] == _T('\0'))
_stprintf (buffer, _T("%s"), file.cFileName);
else
_stprintf (buffer, _T("%s"), file.cAlternateFileName);
_stprintf (buffer, _T("%s"), file.cFileName);
filecount++;
}
ConOutPrintf (_T("%-15s"), buffer);
ConOutPrintf (_T("%*s"), - longestfname, buffer);
count++;
if (count == 5)
/* output as much columns as fits on the screen */
if (count >= (screenwidth / longestfname))
{
/* output 5 columns */
ConOutPrintf (_T("\n"));
/* print the new line only if we aren't on the
* last column, in this case it wraps anyway */
if (count * longestfname != screenwidth)
ConOutPrintf (_T("\n"));
if (IncLine (pLine, dwFlags))
return 1;
count = 0;

View file

@ -1,4 +1,4 @@
/* $Id: echo.c,v 1.2 2003/08/07 09:27:42 hbirr Exp $
/* $Id: echo.c,v 1.3 2004/04/30 16:52:41 navaraf Exp $
*
* ECHO.C - internal echo commands.
*
@ -42,13 +42,13 @@ INT CommandEcho (LPTSTR cmd, LPTSTR param)
if (!_tcsncmp (param, _T("/?"), 2))
{
ConOutPuts ("Displays a message or switches command echoing on or off.\n"
"\n"
" ECHO [ON | OFF]\n"
" ECHO [message]\n"
" ECHO. prints an empty line\n"
"\n"
"Type ECHO without a parameter to display the current ECHO setting.");
ConOutPuts (_T("Displays a message or switches command echoing on or off.\n"
"\n"
" ECHO [ON | OFF]\n"
" ECHO [message]\n"
" ECHO. prints an empty line\n"
"\n"
"Type ECHO without a parameter to display the current ECHO setting."));
return 0;
}

View file

@ -11,6 +11,9 @@
*
* 25-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
* Cleanup. Unicode safe!
*
* 30-Apr-2004 (Filip Navara <xnavara@volny.cz>)
* Make the file listing readable when there is a lot of long names.
*/
#include "config.h"
@ -217,6 +220,8 @@ BOOL ShowCompletionMatches (LPTSTR str, INT charcount)
TCHAR path[MAX_PATH];
TCHAR fname[MAX_PATH];
TCHAR directory[MAX_PATH];
INT longestfname = 0;
SHORT screenwidth;
/* expand current file name */
count = charcount - 1;
@ -283,9 +288,33 @@ BOOL ShowCompletionMatches (LPTSTR str, INT charcount)
hFile = FindFirstFile (path, &file);
if (hFile != INVALID_HANDLE_VALUE)
{
/* Get the size of longest filename first. */
do
{
if (_tcslen(file.cFileName) > longestfname)
{
longestfname = _tcslen(file.cFileName);
/* Directories get extra brackets around them. */
if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
longestfname += 2;
}
}
while (FindNextFile (hFile, &file));
FindClose (hFile);
hFile = FindFirstFile (path, &file);
/* Count the highest number of columns */
GetScreenSize(&screenwidth, 0);
/* For counting columns of output */
count = 0;
/* Increase by the number of spaces behind file name */
longestfname += 3;
/* find anything */
ConOutChar (_T('\n'));
count = 0;
do
{
/* ignore . and .. */
@ -298,10 +327,15 @@ BOOL ShowCompletionMatches (LPTSTR str, INT charcount)
else
_tcscpy (fname, file.cFileName);
ConOutPrintf (_T("%-14s"), fname);
if (++count == 5)
ConOutPrintf (_T("%*s"), - longestfname, fname);
count++;
/* output as much columns as fits on the screen */
if (count >= (screenwidth / longestfname))
{
ConOutChar (_T('\n'));
/* print the new line only if we aren't on the
* last column, in this case it wraps anyway */
if (count * longestfname != screenwidth)
ConOutPrintf (_T("\n"));
count = 0;
}
}

View file

@ -376,7 +376,7 @@ BOOL FileGetString (HANDLE hFile, LPTSTR lpBuffer, INT nBufferLength)
DWORD dwRead;
INT len;
#ifdef _UNICODE
lpString = alloca(nBufferLength);
lpString = malloc(nBufferLength);
#else
lpString = lpBuffer;
#endif
@ -399,6 +399,7 @@ BOOL FileGetString (HANDLE hFile, LPTSTR lpBuffer, INT nBufferLength)
lpString[len++] = '\0';
#ifdef _UNICODE
MultiByteToWideChar(CP_ACP, 0, lpString, len, lpBuffer, len);
free(lpString);
#endif
return TRUE;
}

View file

@ -41,11 +41,11 @@ VOID ShortVersion (VOID)
VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&VersionInfo) && 0 == _tcsnicmp(VersionInfo.szCSDVersion, _T("ReactOS"), 7))
{
ConOutPrintf(_T("%s running on %s"), SHELLVER, VersionInfo.szCSDVersion);
ConOutPrintf(_T("%S running on %s"), SHELLVER, VersionInfo.szCSDVersion);
}
else
{
ConOutPuts(SHELLVER);
ConOutPrintf(_T("%S"), SHELLVER);
}
ConOutPuts (_T("\n"));
}