[PATCH 1/3] cmd: Add CHOICE builtin with DOS6 to XP commandline parameter [try 2]
Detlef Riekenberg
wine.dev at web.de
Sun Dec 19 16:13:32 CST 2010
This fixes http://bugs.winehq.org/show_bug.cgi?id=21173
The example script in the bug need another patch.
try 2 removed an unneeded loop
--
By by ... Detlef
---
programs/cmd/En.rc | 5 ++
programs/cmd/builtins.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++
programs/cmd/wcmd.h | 4 +-
programs/cmd/wcmdmain.c | 4 +
4 files changed, 181 insertions(+), 1 deletions(-)
diff --git a/programs/cmd/En.rc b/programs/cmd/En.rc
index 2e32c1c..87b0780 100644
--- a/programs/cmd/En.rc
+++ b/programs/cmd/En.rc
@@ -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\
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 8c3f727..dccdbcb 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -160,6 +160,175 @@ 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);
+ }
+ }
+ /* This location is never reached */
+}
+
+/****************************************************************************
* WCMD_copy
*
* Copy a file or wildcarded set.
diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h
index 2fde678..ce4c2da 100644
--- a/programs/cmd/wcmd.h
+++ b/programs/cmd/wcmd.h
@@ -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[];
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c
index 85f78b8..7b7ce8f 100644
--- a/programs/cmd/wcmdmain.c
+++ b/programs/cmd/wcmdmain.c
@@ -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;
--
1.7.1
More information about the wine-patches
mailing list