cmd: Add CHOICE builtin with DOS6 to XP commandline parameter.

This commit is contained in:
Detlef Riekenberg 2010-12-19 23:13:32 +01:00 committed by Alexandre Julliard
parent 2f30e3e464
commit 7045e478a8
4 changed files with 180 additions and 1 deletions

View File

@ -211,6 +211,10 @@ PUSHD.\n"
WCMD_MORE, "MORE displays output of files or piped input in pages.\n"
WCMD_CHOICE, "CHOICE displays a text and waits, until the User\n\
press an allowed Key from a selectable list.\n\
CHOICE is mainly used to build a menu selection in a batch file.\n"
WCMD_EXIT,
"EXIT terminates the current command session and returns\n\
to the operating system or shell from which you invoked cmd.\n"
@ -219,6 +223,7 @@ to the operating system or shell from which you invoked cmd.\n"
ATTRIB\t\tShow or change DOS file attributes\n\
CALL\t\tInvoke a batch file from inside another\n\
CD (CHDIR)\tChange current default directory\n\
CHOICE\t\tWait for an keypress from a selectable list\n\
CLS\t\tClear the console screen\n\
COPY\t\tCopy file\n\
CTTY\t\tChange input/output device\n\

View File

@ -159,6 +159,174 @@ void WCMD_change_tty (void) {
}
/****************************************************************************
* WCMD_choice
*
*/
void WCMD_choice (WCHAR * command) {
static const WCHAR bellW[] = {7,0};
static const WCHAR commaW[] = {',',0};
static const WCHAR bracket_open[] = {'[',0};
static const WCHAR bracket_close[] = {']','?',0};
WCHAR answer[16];
WCHAR buffer[16];
WCHAR *ptr = NULL;
WCHAR *opt_c = NULL;
WCHAR *my_command = NULL;
WCHAR opt_default = 0;
DWORD opt_timeout = 0;
DWORD count;
DWORD oldmode;
DWORD have_console;
BOOL opt_n = FALSE;
BOOL opt_s = FALSE;
have_console = GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &oldmode);
errorlevel = 0;
my_command = WCMD_strdupW(WCMD_strtrim_leading_spaces(command));
if (!my_command)
return;
ptr = WCMD_strtrim_leading_spaces(my_command);
while (*ptr == '/') {
switch (toupperW(ptr[1])) {
case 'C':
ptr += 2;
/* the colon is optional */
if (*ptr == ':')
ptr++;
if (!*ptr || isspaceW(*ptr)) {
WINE_FIXME("bad parameter %s for /C\n", wine_dbgstr_w(ptr));
HeapFree(GetProcessHeap(), 0, my_command);
return;
}
/* remember the allowed keys (overwrite previous /C option) */
opt_c = ptr;
while (*ptr && (!isspaceW(*ptr)))
ptr++;
if (*ptr) {
/* terminate allowed chars */
*ptr = 0;
ptr = WCMD_strtrim_leading_spaces(&ptr[1]);
}
WINE_TRACE("answer-list: %s\n", wine_dbgstr_w(opt_c));
break;
case 'N':
opt_n = TRUE;
ptr = WCMD_strtrim_leading_spaces(&ptr[2]);
break;
case 'S':
opt_s = TRUE;
ptr = WCMD_strtrim_leading_spaces(&ptr[2]);
break;
case 'T':
ptr = &ptr[2];
/* the colon is optional */
if (*ptr == ':')
ptr++;
opt_default = *ptr++;
if (!opt_default || (*ptr != ',')) {
WINE_FIXME("bad option %s for /T\n", opt_default ? wine_dbgstr_w(ptr) : "");
HeapFree(GetProcessHeap(), 0, my_command);
return;
}
ptr++;
count = 0;
while (((answer[count] = *ptr)) && isdigitW(*ptr) && (count < 15)) {
count++;
ptr++;
}
answer[count] = 0;
opt_timeout = atoiW(answer);
ptr = WCMD_strtrim_leading_spaces(ptr);
break;
default:
WINE_FIXME("bad parameter: %s\n", wine_dbgstr_w(ptr));
HeapFree(GetProcessHeap(), 0, my_command);
return;
}
}
if (opt_timeout)
WINE_FIXME("timeout not supported: %c,%d\n", opt_default, opt_timeout);
if (have_console)
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), 0);
/* use default keys, when needed: localized versions of "Y"es and "No" */
if (!opt_c) {
LoadStringW(hinst, WCMD_YES, buffer, sizeof(buffer)/sizeof(WCHAR));
LoadStringW(hinst, WCMD_NO, buffer + 1, sizeof(buffer)/sizeof(WCHAR) - 1);
opt_c = buffer;
buffer[2] = 0;
}
/* print the question, when needed */
if (*ptr)
WCMD_output_asis(ptr);
if (!opt_s) {
struprW(opt_c);
WINE_TRACE("case insensitive answer-list: %s\n", wine_dbgstr_w(opt_c));
}
if (!opt_n) {
/* print a list of all allowed answers inside brackets */
WCMD_output_asis(bracket_open);
ptr = opt_c;
answer[1] = 0;
while ((answer[0] = *ptr++)) {
WCMD_output_asis(answer);
if (*ptr)
WCMD_output_asis(commaW);
}
WCMD_output_asis(bracket_close);
}
while (TRUE) {
/* FIXME: Add support for option /T */
WCMD_ReadFile(GetStdHandle(STD_INPUT_HANDLE), answer, 1, &count, NULL);
if (!opt_s)
answer[0] = toupperW(answer[0]);
ptr = strchrW(opt_c, answer[0]);
if (ptr) {
WCMD_output_asis(answer);
WCMD_output(newline);
if (have_console)
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), oldmode);
errorlevel = (ptr - opt_c) + 1;
WINE_TRACE("answer: %d\n", errorlevel);
HeapFree(GetProcessHeap(), 0, my_command);
return;
}
else
{
/* key not allowed: play the bell */
WINE_TRACE("key not allowed: %s\n", wine_dbgstr_w(answer));
WCMD_output_asis(bellW);
}
}
}
/****************************************************************************
* WCMD_copy
*

View File

@ -52,6 +52,7 @@ void WCMD_assoc (WCHAR *, BOOL);
void WCMD_batch (WCHAR *, WCHAR *, int, WCHAR *, HANDLE);
void WCMD_call (WCHAR *command);
void WCMD_change_tty (void);
void WCMD_choice (WCHAR *);
void WCMD_clear_screen (void);
void WCMD_color (void);
void WCMD_copy (void);
@ -202,9 +203,10 @@ typedef struct _DIRECTORY_STACK
#define WCMD_COLOR 41
#define WCMD_FTYPE 42
#define WCMD_MORE 43
#define WCMD_CHOICE 44
/* Must be last in list */
#define WCMD_EXIT 44
#define WCMD_EXIT 45
/* Some standard messages */
extern const WCHAR newline[];

View File

@ -76,6 +76,7 @@ const WCHAR inbuilt[][10] = {
{'C','O','L','O','R','\0'},
{'F','T','Y','P','E','\0'},
{'M','O','R','E','\0'},
{'C','H','O','I','C','E','\0'},
{'E','X','I','T','\0'}
};
@ -1543,6 +1544,9 @@ void WCMD_execute (WCHAR *command, WCHAR *redirects,
case WCMD_MORE:
WCMD_more(p);
break;
case WCMD_CHOICE:
WCMD_choice(p);
break;
case WCMD_EXIT:
WCMD_exit (cmdList);
break;