mirror of
https://github.com/reactos/reactos.git
synced 2024-12-26 17:14:41 +00:00
3ade7829d0
* Only expand arguments actually containing wildcard characters (to prevent expanding directory names to all files within that directory) svn path=/trunk/; revision=4018
331 lines
6.2 KiB
C
331 lines
6.2 KiB
C
/*
|
|
* CHOICE.C - internal command.
|
|
*
|
|
*
|
|
* History:
|
|
*
|
|
* 12 Aug 1999 (Eric Kohl)
|
|
* started.
|
|
*
|
|
* 01 Sep 1999 (Eric Kohl)
|
|
* Fixed help text.
|
|
*
|
|
* 26 Sep 1999 (Paolo Pantaleo)
|
|
* Fixed timeout.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#ifdef INCLUDE_CMD_CHOICE
|
|
|
|
#include <windows.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <tchar.h>
|
|
|
|
#include "cmd.h"
|
|
#include "batch.h"
|
|
|
|
|
|
#define GC_TIMEOUT -1
|
|
#define GC_NOKEY 0 //an event occurred but it wasn't a key pressed
|
|
#define GC_KEYREAD 1 //a key has been read
|
|
|
|
|
|
static INT
|
|
GetCharacterTimeout (LPTCH ch, DWORD dwMilliseconds)
|
|
{
|
|
//--------------------------------------------
|
|
// Get a character from standard input but with a timeout.
|
|
// The function will wait a limited amount
|
|
// of time, then the function returns GC_TIMEOUT.
|
|
//
|
|
// dwMilliseconds is the timeout value, that can
|
|
// be set to INFINITE, so the function works like
|
|
// stdio.h's getchar()
|
|
|
|
HANDLE hInput;
|
|
DWORD dwRead;
|
|
|
|
INPUT_RECORD lpBuffer;
|
|
|
|
hInput = GetStdHandle (STD_INPUT_HANDLE);
|
|
|
|
//if the timeout experied return GC_TIMEOUT
|
|
if (WaitForSingleObject (hInput, dwMilliseconds) == WAIT_TIMEOUT)
|
|
return GC_TIMEOUT;
|
|
|
|
//otherwise get the event
|
|
ReadConsoleInput (hInput, &lpBuffer, 1, &dwRead);
|
|
|
|
//if the event is a key pressed
|
|
if ((lpBuffer.EventType == KEY_EVENT) &&
|
|
(lpBuffer.Event.KeyEvent.bKeyDown == TRUE))
|
|
{
|
|
//read the key
|
|
#ifdef _UNICODE
|
|
*ch = lpBuffer.Event.KeyEvent.uChar.UnicodeChar;
|
|
#else
|
|
*ch = lpBuffer.Event.KeyEvent.uChar.AsciiChar;
|
|
#endif
|
|
return GC_KEYREAD;
|
|
}
|
|
|
|
//else return no key
|
|
return GC_NOKEY;
|
|
}
|
|
|
|
static INT
|
|
IsKeyInString (LPTSTR lpString, TCHAR cKey, BOOL bCaseSensitive)
|
|
{
|
|
LPTCH p = lpString;
|
|
INT val = 0;
|
|
|
|
while (*p)
|
|
{
|
|
if (bCaseSensitive)
|
|
{
|
|
if (*p == cKey)
|
|
return val;
|
|
}
|
|
else
|
|
{
|
|
if (_totlower (*p) == _totlower (cKey))
|
|
return val;
|
|
}
|
|
|
|
val++;
|
|
p++;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
INT
|
|
CommandChoice (LPTSTR cmd, LPTSTR param)
|
|
{
|
|
LPTSTR lpOptions = "YN";
|
|
LPTSTR lpText = NULL;
|
|
BOOL bNoPrompt = FALSE;
|
|
BOOL bCaseSensitive = FALSE;
|
|
BOOL bTimeout = FALSE;
|
|
INT nTimeout = 0;
|
|
TCHAR cDefault = _T('\0');
|
|
INPUT_RECORD ir;
|
|
LPTSTR p, np;
|
|
LPTSTR *arg;
|
|
INT argc;
|
|
INT i;
|
|
INT val;
|
|
|
|
INT GCret;
|
|
TCHAR Ch;
|
|
DWORD amount,clk;
|
|
|
|
if (_tcsncmp (param, _T("/?"), 2) == 0)
|
|
{
|
|
ConOutPuts (_T("Waits for the user to choose one of a set of choices.\n"
|
|
"\n"
|
|
"CHOICE [/C[:]choices][/N][/S][/T[:]c,nn][text]\n"
|
|
"\n"
|
|
" /C[:]choices Specifies allowable keys. Default is YN.\n"
|
|
" /N Do not display choices and ? at the end of the prompt string.\n"
|
|
" /S Treat choice keys as case sensitive.\n"
|
|
" /T[:]c,nn Default choice to c after nn seconds.\n"
|
|
" text Prompt string to display.\n"
|
|
"\n"
|
|
"ERRORLEVEL is set to offset of key user presses in choices."));
|
|
return 0;
|
|
}
|
|
|
|
/* retrieve text */
|
|
p = param;
|
|
|
|
while (TRUE)
|
|
{
|
|
if (*p == _T('\0'))
|
|
break;
|
|
|
|
if (*p != _T('/'))
|
|
{
|
|
lpText = p;
|
|
break;
|
|
}
|
|
np = _tcschr (p, _T(' '));
|
|
if (!np)
|
|
break;
|
|
p = np + 1;
|
|
}
|
|
|
|
/* build parameter array */
|
|
arg = split (param, &argc, FALSE);
|
|
|
|
/* evaluate arguments */
|
|
if (argc > 0)
|
|
{
|
|
for (i = 0; i < argc; i++)
|
|
{
|
|
if (_tcsnicmp (arg[i], _T("/c"), 2) == 0)
|
|
{
|
|
if (arg[i][2] == _T(':'))
|
|
lpOptions = &arg[i][3];
|
|
else
|
|
lpOptions = &arg[i][2];
|
|
|
|
if (_tcslen (lpOptions) == 0)
|
|
{
|
|
ConErrPuts (_T("Invalid option. Expected format: /C[:]options"));
|
|
freep (arg);
|
|
return 1;
|
|
}
|
|
}
|
|
else if (_tcsnicmp (arg[i], _T("/n"), 2) == 0)
|
|
{
|
|
bNoPrompt = TRUE;
|
|
}
|
|
else if (_tcsnicmp (arg[i], _T("/s"), 2) == 0)
|
|
{
|
|
bCaseSensitive = TRUE;
|
|
}
|
|
else if (_tcsnicmp (arg[i], _T("/t"), 2) == 0)
|
|
{
|
|
LPTSTR s;
|
|
|
|
if (arg[i][2] == _T(':'))
|
|
{
|
|
cDefault = arg[i][3];
|
|
s = &arg[i][4];
|
|
}
|
|
else
|
|
{
|
|
cDefault = arg[i][2];
|
|
s = &arg[i][3];
|
|
}
|
|
|
|
if (*s != _T(','))
|
|
{
|
|
ConErrPuts (_T("Invalid option. Expected format: /T[:]c,nn"));
|
|
freep (arg);
|
|
return 1;
|
|
}
|
|
|
|
s++;
|
|
nTimeout = _ttoi(s);
|
|
bTimeout = TRUE;
|
|
}
|
|
else if (arg[i][0] == _T('/'))
|
|
{
|
|
ConErrPrintf (_T("Illegal Option: %s"), arg[i]);
|
|
freep (arg);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* print text */
|
|
if (lpText)
|
|
ConOutPrintf (_T("%s"), lpText);
|
|
|
|
/* print options */
|
|
if (bNoPrompt == FALSE)
|
|
{
|
|
ConOutPrintf (_T("[%c"), lpOptions[0]);
|
|
|
|
for (i = 1; (unsigned)i < _tcslen (lpOptions); i++)
|
|
ConOutPrintf (_T(",%c"), lpOptions[i]);
|
|
|
|
ConOutPrintf (_T("]?"));
|
|
}
|
|
|
|
ConInFlush ();
|
|
|
|
if(!bTimeout)
|
|
{
|
|
while (TRUE)
|
|
{
|
|
ConInKey (&ir);
|
|
|
|
val = IsKeyInString (lpOptions,
|
|
#ifdef _UNICODE
|
|
ir.Event.KeyEvent.uChar.UnicodeChar,
|
|
#else
|
|
ir.Event.KeyEvent.uChar.AsciiChar,
|
|
#endif /* _UNICODE */
|
|
bCaseSensitive);
|
|
|
|
if (val >= 0)
|
|
{
|
|
ConOutPrintf (_T("%c\n"), lpOptions[val]);
|
|
|
|
nErrorLevel = val + 1;
|
|
|
|
break;
|
|
}
|
|
|
|
Beep (440, 50);
|
|
}
|
|
|
|
freep (arg);
|
|
return 0;
|
|
}
|
|
|
|
clk = GetTickCount ();
|
|
amount = nTimeout*1000;
|
|
|
|
loop:
|
|
GCret = GetCharacterTimeout (&Ch, amount - (GetTickCount () - clk));
|
|
|
|
switch (GCret)
|
|
{
|
|
case GC_TIMEOUT:
|
|
#ifdef _DEBUG
|
|
DebugPrintf (_T("GC_TIMEOUT\n"));
|
|
DebugPrintf (_T("elapsed %d msecs\n"), GetTickCount () - clk);
|
|
#endif /* _DEBUG */
|
|
break;
|
|
|
|
case GC_NOKEY:
|
|
#ifdef _DEBUG
|
|
DebugPrintf(_T("GC_NOKEY\n"));
|
|
DebugPrintf(_T("elapsed %d msecs\n"), GetTickCount () - clk);
|
|
#endif /* _DEBUG */
|
|
goto loop;
|
|
|
|
case GC_KEYREAD:
|
|
#ifdef _DEBUG
|
|
DebugPrintf(_T("GC_KEYREAD\n"));
|
|
DebugPrintf(_T("elapsed %d msecs\n"), GetTickCount () - clk);
|
|
DebugPrintf(_T("read %c"), Ch);
|
|
#endif /* _DEBUG */
|
|
if ((val=IsKeyInString(lpOptions,Ch,bCaseSensitive))==-1)
|
|
{
|
|
Beep (440, 50);
|
|
goto loop;
|
|
}
|
|
cDefault=Ch;
|
|
break;
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
DebugPrintf(_T("exiting wait loop after %d msecs\n"),
|
|
GetTickCount () - clk);
|
|
#endif /* _DEBUG */
|
|
|
|
val = IsKeyInString (lpOptions, cDefault, bCaseSensitive);
|
|
ConOutPrintf (_T("%c\n"), lpOptions[val]);
|
|
|
|
nErrorLevel = val + 1;
|
|
|
|
freep (arg);
|
|
|
|
#ifdef _DEBUG
|
|
DebugPrintf (_T("ErrorLevel: %d\n"), nErrorLevel);
|
|
#endif /* _DEBUG */
|
|
|
|
return 0;
|
|
}
|
|
#endif /* INCLUDE_CMD_CHOICE */
|
|
|
|
/* EOF */
|