Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312/* * 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. * * 02 Apr 2005 (Magnus Olsen) * Remove hardcoded strings so that they can be translated. * */
#include "precomp.h"
#ifdef INCLUDE_CMD_CHOICE
#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 INTGetCharacterTimeout (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 expired 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 != FALSE)) { //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 INTIsKeyInString (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;}
INTCommandChoice (LPTSTR param){ LPTSTR lpOptions; TCHAR Options[6]; 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;
LoadString(CMD_ModuleHandle, STRING_CHOICE_OPTION, Options, 4); lpOptions = Options;
if (_tcsncmp (param, _T("/?"), 2) == 0) { ConOutResPaging(TRUE,STRING_CHOICE_HELP); 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, 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) { ConErrResPuts(STRING_CHOICE_ERROR); 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(',')) { ConErrResPuts(STRING_CHOICE_ERROR_TXT); freep (arg); return 1; }
s++; nTimeout = _ttoi(s); bTimeout = TRUE; } else if (arg[i][0] == _T('/')) { ConErrResPrintf(STRING_CHOICE_ERROR_OPTION, 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 bCaseSensitive);
if (val >= 0) { ConOutPrintf (_T("%c\n"), lpOptions[val]);
nErrorLevel = val + 1;
break; }
Beep (440, 50); }
freep (arg); TRACE ("ErrorLevel: %d\n", nErrorLevel); return 0; }
clk = GetTickCount (); amount = nTimeout*1000;
loop: GCret = GetCharacterTimeout (&Ch, amount - (GetTickCount () - clk));
switch (GCret) { case GC_TIMEOUT: TRACE ("GC_TIMEOUT\n"); TRACE ("elapsed %d msecs\n", GetTickCount () - clk); break;
case GC_NOKEY: TRACE ("GC_NOKEY\n"); TRACE ("elapsed %d msecs\n", GetTickCount () - clk); goto loop;
case GC_KEYREAD: TRACE ("GC_KEYREAD\n"); TRACE ("elapsed %d msecs\n", GetTickCount () - clk); TRACE ("read %c\n", Ch); if ((val=IsKeyInString(lpOptions,Ch,bCaseSensitive))==-1) { Beep (440, 50); goto loop; } cDefault=Ch; break; }
TRACE ("exiting wait loop after %d msecs\n", GetTickCount () - clk);
val = IsKeyInString (lpOptions, cDefault, bCaseSensitive); ConOutPrintf(_T("%c\n"), lpOptions[val]);
nErrorLevel = val + 1;
freep (arg);
TRACE ("ErrorLevel: %d\n", nErrorLevel);
return 0;}#endif /* INCLUDE_CMD_CHOICE */
/* EOF */