Added Wine command-line interpreter.
diff --git a/configure b/configure
index c54b15b..d4688cf 100755
--- a/configure
+++ b/configure
@@ -5300,6 +5300,7 @@
programs/regtest/Makefile
programs/regapi/Makefile
programs/view/Makefile
+programs/wcmd/Makefile
programs/winhelp/Makefile
programs/winver/Makefile
rc/Makefile
@@ -5469,6 +5470,7 @@
programs/regtest/Makefile
programs/regapi/Makefile
programs/view/Makefile
+programs/wcmd/Makefile
programs/winhelp/Makefile
programs/winver/Makefile
rc/Makefile
diff --git a/configure.in b/configure.in
index 0d99cca..bdc9bed 100644
--- a/configure.in
+++ b/configure.in
@@ -802,6 +802,7 @@
programs/regtest/Makefile
programs/regapi/Makefile
programs/view/Makefile
+programs/wcmd/Makefile
programs/winhelp/Makefile
programs/winver/Makefile
rc/Makefile
diff --git a/programs/Makefile.in b/programs/Makefile.in
index a6b80b6..5b6fe2b 100644
--- a/programs/Makefile.in
+++ b/programs/Makefile.in
@@ -8,6 +8,7 @@
regapi \
regtest \
view \
+ wcmd \
winhelp \
winver
diff --git a/programs/wcmd/.cvsignore b/programs/wcmd/.cvsignore
new file mode 100644
index 0000000..c134ce3
--- /dev/null
+++ b/programs/wcmd/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+wcmd
+wcmdrc.s
diff --git a/programs/wcmd/ChangeLog b/programs/wcmd/ChangeLog
new file mode 100644
index 0000000..5777341
--- /dev/null
+++ b/programs/wcmd/ChangeLog
@@ -0,0 +1,46 @@
+
+v0.10 - 2 June 1999
+Additional help text and error codes.
+
+v0.09 - 5 May 1999
+Directory byte counts and disk free space are reported with commas and in 64-bit.
+File sizes have commas but are computed in 32 bits.
+Handling of DIR /S on non-current path corrected.
+DEL with wildcard or directory name works correctly.
+
+v0.08 - 21 Mar 1999
+Invoke an AUTOEXEC.BAT file if it exists in the root directory of the startup drive.
+
+v0.07 - 8 Mar 1999
+Can now be compiled as a WineLib app (conditional code added).
+Additional help text.
+Icon added to resources (the Wine-glass).
+
+v0.06 - 23 Feb 1999
+Help text moved into resource file to allow localisation.
+Simple batch files (without parameters) can be executed.
+
+v0.05 - 17 Feb 1999
+Fixed problem with DIR command & long, complex relative paths.
+DIR /S and /P implemented.
+Date and time in PROMPT localised.
+More work on batch files (they are echoed to screen but not executed).
+
+v0.04 - 7 Feb 1999
+Command-line qualifiers /c /q /k implemented (as NT's CMD.EXE).
+ECHO command implemented, though echo mode is not honoured.
+Environment variables in commands (eg %envvar%) expanded.
+REN and COPY added, but no wildcard support or relative paths.
+Filenames in quotes now handled.
+PAUSE command.
+Preliminary coding for batch files.
+
+v0.03 - 5 Feb 1999
+Added relative path and alternate drive support to DIR, also free disk space
+(32-bit only!).
+
+v0.02 - 27 Jan 1999
+Added change-drive code.
+
+v0.01 - 25 Jan 1999
+Initial version.
diff --git a/programs/wcmd/Makefile.in b/programs/wcmd/Makefile.in
new file mode 100644
index 0000000..9479299
--- /dev/null
+++ b/programs/wcmd/Makefile.in
@@ -0,0 +1,43 @@
+DEFS = -DWINELIB
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR = @srcdir@
+VPATH = @srcdir@
+MODULE = none
+PROGRAMS = wcmd
+ALL_LIBS = $(WINELIB) $(X_LIBS) $(XLIB) $(LIBS)
+RCFLAGS = -w32 -h
+WRCEXTRA = -A -t -p $*
+
+C_SRCS = \
+ batch.c \
+ builtins.c \
+ directory.c \
+ wcmdmain.c
+
+RC_SRCS = \
+ wcmdrc.rc
+
+all: check_wrc $(PROGRAMS)
+
+depend:: $(RC_SRCS:.rc=.h)
+
+@MAKE_RULES@
+
+#this line is needed to prevent winestub.o being linked
+WINESTUB =
+
+wcmd: $(OBJS)
+ $(CC) -o wcmd $(OBJS) $(LDOPTIONS) $(ALL_LIBS)
+
+install: dummy
+ $(INSTALL_PROGRAM) wcmd $(bindir)/wcmd
+
+uninstall: dummy
+ $(RM) $(bindir)/wcmd
+
+$(RC_SRCS:.rc=.s): $(WRC)
+
+dummy:
+
+### Dependencies:
diff --git a/programs/wcmd/README b/programs/wcmd/README
new file mode 100644
index 0000000..7141f26
--- /dev/null
+++ b/programs/wcmd/README
@@ -0,0 +1,50 @@
+WCMD - A Command-Line Interface for WINE
+Copyright (C) 1999 D Pickles (davep@nugate.demon.co.uk)
+Open Source software published under the Wine Licence and Warranty.
+
+This is an Alpha version and is very much "work in progress".
+
+WHAT'S INCLUDED
+- Sources
+- A Makefile for compiling with LibWine. Build Wine with "-enable-dll" first.
+- A Makefile for Borland C++ (needs editing for directories).
+
+WHAT'S MISSING
+- Redirection, shell parameters and pipes
+- Command-line qualifiers for most builtin commands
+- MOVE command (plus the batch-only ones)
+- Wildcards and relative paths in COPY and RENAME
+- Set functionality in DATE, TIME, ATTRIB, SET, LABEL
+- Full internationalisation of the text (and commands?).
+
+WHAT DOESN'T WORK
+- At present it is not possible to launch Windows GDI programs from the command
+line. This is result of the way the CreateProcess() API call is implemented in
+Wine, and will be fixed in a later Wine release.
+- The ATTRIB command reports all files having their Archive flag set, and the
+READONLY setting depends on the Unix file permissions. All other flags are
+always clear. The Wine attributes API calls map to the Unix stat() function
+which cannot handle the other attributes available in DOS.
+- Date/timestamps of files in the DIR listing are shown using the current
+locale. As there is AFAIK no way to set the locale, they will always appear in
+US format.
+- Line editing and command recall doesn't work due to missing functionality in
+Wine.
+- File sizes in the DIR function are all given in 32 bits, though totals and
+free space are computed to 64 bits.
+- DIR/S fails if there is no matching file in the starting directory, ie
+"DIR C:\TEMP\*.c /S" doesn't work if there is no file matching *.c in C:\TEMP
+but one does exist in a lower directory.
+- Copy, rename, move, need the source and destination to be specified fully
+with an absolute or relative path but no wildcards or partial filenames.
+- Simple batch files work, ie a list of commands as they would be typed. However
+invoking a batch file from within another invokes the CALL function, control
+returns to the calling batch file when the subfile exits.
+
+WINE OR WIN32 BINARY?
+Wcmd can be built as a Wine binary, or (using a Win32 compiler) as a Win32 .EXE
+image. The Wine binary is simpler to invoke from the U**x command line or from
+a GUI such as KDE, however it is not possible to invoke a second shell using the
+"WCMD /C filename" syntax. Conversely a Win32 application can be invoked from a
+Win32 GUI such as Program Manager but that needs starting under Wine first.
+
diff --git a/programs/wcmd/batch.c b/programs/wcmd/batch.c
new file mode 100644
index 0000000..cba1c3e
--- /dev/null
+++ b/programs/wcmd/batch.c
@@ -0,0 +1,179 @@
+/*
+ * WCMD - Wine-compatible command line interface - batch interface.
+ *
+ * (C) 1999 D A Pickles
+ *
+ */
+
+
+#include "wcmd.h"
+
+void WCMD_batch_command (HANDLE h, char *command);
+char *WCMD_parameter (char *s, int n);
+BOOL WCMD_go_to (HANDLE h, char *label);
+
+extern HANDLE STDin, STDout;
+extern char nyi[];
+extern char newline[];
+extern char version_string[];
+extern int echo_mode;
+extern char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
+
+
+
+/****************************************************************************
+ * WCMD_batch
+ *
+ * Open and execute a batch file.
+ * On entry *command includes the complete command line beginning with the name
+ * of the batch file (if a CALL command was entered the CALL has been removed).
+ * *file is the name of the file, which might not exist and may not have the
+ * .BAT suffix on.
+ *
+ * We need to handle recursion correctly, since one batch program might call another.
+ */
+
+void WCMD_batch (char *file, char *command) {
+
+HANDLE h;
+char string[MAX_PATH];
+int n;
+
+ strcpy (string, file);
+ CharLower (string);
+ if (strstr (string, ".bat") == NULL) strcat (string, ".bat");
+ h = CreateFile (string, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (h == INVALID_HANDLE_VALUE) {
+ WCMD_output ("File %s not found\n", string);
+ return;
+ }
+
+/*
+ * Work through the file line by line. Specific batch commands are processed here,
+ * the rest are handled by the main command processor.
+ */
+
+ while (WCMD_fgets (string, sizeof(string), h)) {
+ n = strlen (string);
+ if (string[n-1] == '\n') string[n-1] = '\0';
+ if (string[n-2] == '\r') string[n-2] = '\0'; /* Under Windoze we get CRLF! */
+ WCMD_batch_command (h, string);
+ }
+ CloseHandle (h);
+}
+
+/****************************************************************************
+ * WCMD_batch_command
+ *
+ * Execute one line from a batch file.
+ */
+
+void WCMD_batch_command (HANDLE h, char *command) {
+
+DWORD status;
+char cmd[1024];
+
+ if (echo_mode && (command[0] != '@')) WCMD_output ("%s", command);
+ status = ExpandEnvironmentStrings (command, cmd, sizeof(cmd));
+ if (!status) {
+ WCMD_print_error ();
+ return;
+ }
+ WCMD_process_command (cmd);
+}
+
+/****************************************************************************
+ * WCMD_go_to
+ *
+ * Batch file jump instruction. Not the most efficient algorithm ;-)
+ * Returns FALSE if the specified label cannot be found - the file pointer is
+ * then at EOF.
+ */
+
+BOOL WCMD_go_to (HANDLE h, char *label) {
+
+char string[MAX_PATH];
+
+ SetFilePointer (h, 0, NULL, FILE_BEGIN);
+ while (WCMD_fgets (string, sizeof(string), h)) {
+ if ((string[0] == ':') && (strcmp (&string[1], label) == 0)) return TRUE;
+ }
+ return FALSE;
+}
+
+/*******************************************************************
+ * WCMD_parameter - extract a parameter from a command line.
+ *
+ * Returns the 'n'th space-delimited parameter on the command line.
+ * Parameter is in static storage overwritten on the next call.
+ * Parameters in quotes are handled.
+ */
+
+char *WCMD_parameter (char *s, int n) {
+
+int i = -1;
+static char param[MAX_PATH];
+char *p;
+
+ p = param;
+ while (TRUE) {
+ switch (*s) {
+ case ' ':
+ s++;
+ break;
+ case '"':
+ s++;
+ while ((*s != '\0') && (*s != '"')) {
+ *p++ = *s++;
+ }
+ if (i == n) {
+ *p = '\0';
+ return param;
+ }
+ else {
+ param[0] = '\0';
+ i++;
+ }
+ if (*s == '"') s++;
+ break;
+ case '\0':
+ return param;
+ default:
+ while ((*s != '\0') && (*s != ' ')) {
+ *p++ = *s++;
+ }
+ if (i == n) {
+ *p = '\0';
+ return param;
+ }
+ else {
+ param[0] = '\0';
+ i++;
+ }
+ }
+ }
+}
+
+/****************************************************************************
+ * WCMD_fgets
+ *
+ * Get one line from a batch file. We can't use the native f* functions because
+ * of the filename syntax differences between DOS and Unix.
+ */
+
+char *WCMD_fgets (char *s, int n, HANDLE h) {
+
+DWORD bytes;
+BOOL status;
+char *p;
+
+ p = s;
+ do {
+ status = ReadFile (h, s, 1, &bytes, NULL);
+ if ((status == 0) || (bytes == 0)) return NULL;
+ if (*s == '\n') bytes = 0;
+ *++s = '\0';
+ n--;
+ } while ((bytes == 1) && (n > 1));
+ return p;
+}
diff --git a/programs/wcmd/builtins.c b/programs/wcmd/builtins.c
new file mode 100644
index 0000000..ad62eaa
--- /dev/null
+++ b/programs/wcmd/builtins.c
@@ -0,0 +1,645 @@
+/*
+ * WCMD - Wine-compatible command line interface - built-in functions.
+ *
+ * (C) 1999 D A Pickles
+ *
+ * On entry to each function, global variables quals, param1, param2 contain
+ * the qualifiers (uppercased and concatenated) and parameters entered, with
+ * environment-variable and batch parameter substitution already done.
+ */
+
+/*
+ * FIXME:
+ * - No support for redirection, pipes, batch files, shell parameters
+ * - 32-bit limit on file sizes in DIR command
+ * - Lots of functionality missing from builtins
+ * - Messages etc need international support
+ */
+
+#include "wcmd.h"
+
+extern HANDLE STDin, STDout;
+extern HINSTANCE hinst;
+extern char *inbuilt[];
+extern char nyi[];
+extern char newline[];
+extern char version_string[];
+extern char anykey[];
+extern int echo_mode;
+extern char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
+
+
+/****************************************************************************
+ * WCMD_call
+ *
+ * Call another batch file.
+ */
+
+void WCMD_call () {
+
+ WCMD_output (nyi);
+
+}
+
+/****************************************************************************
+ * WCMD_clear_screen
+ *
+ * Clear the terminal screen.
+ */
+
+void WCMD_clear_screen () {
+
+ WCMD_output (nyi);
+
+}
+
+/****************************************************************************
+ * WCMD_change_tty
+ *
+ * Change the default i/o device (ie redirect STDin/STDout).
+ */
+
+void WCMD_change_tty () {
+
+ WCMD_output (nyi);
+
+}
+
+/****************************************************************************
+ * WCMD_copy
+ *
+ * Copy a file or wildcarded set.
+ * FIXME: No wildcard support
+ * FIXME: Needs output file to be fully specified (can't just enter directory)
+ */
+
+void WCMD_copy () {
+
+DWORD count;
+WIN32_FIND_DATA fd;
+HANDLE hff;
+BOOL force, status;
+static char *overwrite = "Overwrite file (Y/N)?";
+char string[8], outpath[MAX_PATH];
+
+ if ((strchr(param1,'*') != NULL) && (strchr(param1,'%') != NULL)) {
+ WCMD_output ("Wildcards not yet supported\n");
+ return;
+ }
+ GetFullPathName (param2, sizeof(outpath), outpath, NULL);
+ force = (strstr (quals, "/Y") != NULL);
+ if (!force) {
+ hff = FindFirstFile (outpath, &fd);
+ if (hff != INVALID_HANDLE_VALUE) {
+ FindClose (hff);
+ WCMD_output (overwrite);
+ ReadFile (STDin, string, sizeof(string), &count, NULL);
+ if (toupper(string[0]) == 'Y') force = TRUE;
+ }
+ else force = TRUE;
+ }
+ if (force) {
+ status = CopyFile (param1, outpath, FALSE);
+ if (!status) WCMD_print_error ();
+ }
+}
+
+/****************************************************************************
+ * WCMD_create_dir
+ *
+ * Create a directory.
+ */
+
+void WCMD_create_dir () {
+
+ if (!CreateDirectory (param1, NULL)) WCMD_print_error ();
+}
+
+/****************************************************************************
+ * WCMD_delete
+ *
+ * Delete a file or wildcarded set.
+ *
+ */
+
+void WCMD_delete (int recurse) {
+
+WIN32_FIND_DATA fd;
+HANDLE hff;
+char fpath[MAX_PATH];
+char *p;
+
+ hff = FindFirstFile (param1, &fd);
+ if (hff == INVALID_HANDLE_VALUE) {
+ WCMD_output ("File Not Found\n");
+ return;
+ }
+ if ((strchr(param1,'*') == NULL) && (strchr(param1,'?') == NULL)
+ && (!recurse) && (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ strcat (param1, "\\*");
+ WCMD_delete (1);
+ return;
+ }
+ if ((strchr(param1,'*') != NULL) || (strchr(param1,'?') != NULL)) {
+ strcpy (fpath, param1);
+ do {
+ p = strrchr (fpath, '\\');
+ if (p != NULL) {
+ *++p = '\0';
+ strcat (fpath, fd.cFileName);
+ }
+ else strcpy (fpath, fd.cFileName);
+ if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (!DeleteFile (fpath)) WCMD_print_error ();
+ }
+ } while (FindNextFile(hff, &fd) != 0);
+ FindClose (hff);
+ }
+ else {
+ if (!DeleteFile (param1)) WCMD_print_error ();
+ }
+}
+
+/****************************************************************************
+ * WCMD_echo
+ *
+ * Echo input to the screen (or not). We don't try to emulate the bugs
+ * in DOS (try typing "ECHO ON AGAIN" for an example).
+ */
+
+void WCMD_echo (char *command) {
+
+static char *eon = "Echo is ON\n", *eoff = "Echo is OFF\n";
+int count;
+
+ count = strlen(command);
+ if (count == 0) {
+ if (echo_mode) WCMD_output (eon);
+ else WCMD_output (eoff);
+ return;
+ }
+ if ((count == 1) && (command[0] == '.')) {
+ WCMD_output (newline);
+ return;
+ }
+ if (lstrcmpi(command, "ON") == 0) {
+ echo_mode = 1;
+ return;
+ }
+ if (lstrcmpi(command, "OFF") == 0) {
+ echo_mode = 0;
+ return;
+ }
+ WCMD_output (command);
+ WCMD_output (newline);
+
+}
+
+/****************************************************************************
+ * WCMD_for
+ *
+ * Batch file loop processing.
+ */
+
+void WCMD_for () {
+
+ WCMD_output (nyi);
+
+}
+
+/**************************************************************************
+ * WCMD_give_help
+ *
+ * Simple on-line help. Help text is stored in the resource file.
+ */
+
+void WCMD_give_help (char *command) {
+
+int i;
+char buffer[2048];
+
+ command = WCMD_strtrim_leading_spaces(command);
+ if (lstrlen(command) == 0) {
+ LoadString (hinst, 1000, buffer, sizeof(buffer));
+ WCMD_output (buffer);
+ }
+ else {
+ for (i=0; i<=WCMD_EXIT; i++) {
+ if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
+ param1, -1, inbuilt[i], -1) == 2) {
+ LoadString (hinst, i, buffer, sizeof(buffer));
+ WCMD_output (buffer);
+ return;
+ }
+ }
+ WCMD_output ("No help available for %s\n", param1);
+ }
+ return;
+}
+
+/****************************************************************************
+ * WCMD_if
+ *
+ * Batch file conditional.
+ */
+
+void WCMD_if () {
+
+ WCMD_output (nyi);
+
+}
+
+/****************************************************************************
+ * WCMD_move
+ *
+ * Move a file, directory tree or wildcarded set of files.
+ */
+
+void WCMD_move () {
+
+ WCMD_output (nyi);
+}
+
+/****************************************************************************
+ * WCMD_pause
+ *
+ * Wait for keyboard input.
+ */
+
+void WCMD_pause () {
+
+DWORD count;
+char string[32];
+
+ WCMD_output (anykey);
+ ReadFile (STDin, string, sizeof(string), &count, NULL);
+}
+
+/****************************************************************************
+ * WCMD_remove_dir
+ *
+ * Delete a directory.
+ */
+
+void WCMD_remove_dir () {
+
+ if (!RemoveDirectory (param1)) WCMD_print_error ();
+}
+
+/****************************************************************************
+ * WCMD_rename
+ *
+ * Rename a file.
+ * FIXME: Needs input and output files to be fully specified.
+ */
+
+void WCMD_rename () {
+
+int status;
+static char *dirmsg = "Input file is a directory. Use the MOVE command\n\n";
+
+ if ((strchr(param1,'*') != NULL) || (strchr(param1,'%') != NULL)) {
+ WCMD_output ("Wildcards not yet supported\n");
+ return;
+ }
+ status = GetFileAttributes (param1);
+ if ((status != -1) && (status & FILE_ATTRIBUTE_DIRECTORY)) {
+ WCMD_output (dirmsg);
+ return;
+ }
+ status = MoveFile (param1, param2);
+ if (!status) WCMD_print_error ();
+}
+
+/*****************************************************************************
+ * WCMD_setshow_attrib
+ *
+ * Display and optionally sets DOS attributes on a file or directory
+ *
+ * FIXME: Wine currently uses the Unix stat() function to get file attributes.
+ * As a result only the Readonly flag is correctly reported, the Archive bit
+ * is always set and the rest are not implemented. We do the Right Thing anyway.
+ *
+ */
+
+void WCMD_setshow_attrib () {
+
+DWORD count;
+HANDLE hff;
+WIN32_FIND_DATA fd;
+char flags[9] = {" "};
+
+ if (lstrlen(param1) == 0) {
+ GetCurrentDirectory (sizeof(param1), param1);
+ strcat (param1, "\\*");
+ }
+
+ hff = FindFirstFile (param1, &fd);
+ if (hff == INVALID_HANDLE_VALUE) {
+ WCMD_output ("File Not Found\n");
+ }
+ else {
+ do {
+ if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
+ flags[0] = 'H';
+ }
+ if (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {
+ flags[1] = 'S';
+ }
+ if (fd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
+ flags[2] = 'A';
+ }
+ if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
+ flags[3] = 'R';
+ }
+ if (fd.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) {
+ flags[4] = 'T';
+ }
+ if (fd.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) {
+ flags[5] = 'C';
+ }
+ WCMD_output ("%s %s\n", flags, fd.cFileName);
+ for (count=0; count < 8; count++) flags[count] = ' ';
+ }
+ } while (FindNextFile(hff, &fd) != 0);
+ }
+ FindClose (hff);
+}
+
+/*****************************************************************************
+ * WCMD_setshow_default
+ *
+ * Set/Show the current default directory
+ */
+
+void WCMD_setshow_default () {
+
+BOOL status;
+char string[1024];
+
+ if (strlen(param1) == 0) {
+ GetCurrentDirectory (sizeof(string), string);
+ strcat (string, "\n");
+ WCMD_output (string);
+ }
+ else {
+ status = SetCurrentDirectory (param1);
+ if (!status) {
+ WCMD_print_error ();
+ return;
+ }
+ }
+ return;
+}
+
+/****************************************************************************
+ * WCMD_setshow_date
+ *
+ * Set/Show the system date
+ * FIXME: Can't change date yet
+ */
+
+void WCMD_setshow_date () {
+
+char curdate[64], buffer[64];
+DWORD count;
+
+ if (lstrlen(param1) == 0) {
+ if (GetDateFormat (LOCALE_USER_DEFAULT, 0, NULL, NULL,
+ curdate, sizeof(curdate))) {
+ WCMD_output ("Current Date is %s\nEnter new date: ", curdate);
+ ReadFile (STDin, buffer, sizeof(buffer), &count, NULL);
+ if (count > 2) {
+ WCMD_output (nyi);
+ }
+ }
+ else WCMD_print_error ();
+ }
+ else {
+ WCMD_output (nyi);
+ }
+}
+
+/****************************************************************************
+ * WCMD_setshow_env
+ *
+ * Set/Show the environment variables
+ *
+ * FIXME: need to sort variables into order for display?
+ */
+
+void WCMD_setshow_env (char *s) {
+
+LPVOID env;
+char *p;
+int status;
+
+ if (strlen(param1) == 0) {
+ env = GetEnvironmentStrings ();
+ p = (char *) env;
+ while (*p) {
+ WCMD_output ("%s\n", p);
+ p += lstrlen(p) + 1;
+ }
+ }
+ else {
+ p = strchr (s, '=');
+ if (p == NULL) {
+ WCMD_output ("Command Syntax: SET variable=value\n");
+ return;
+ }
+ *p++ = '\0';
+ status = SetEnvironmentVariable (s, p);
+ if (!status) WCMD_print_error();
+ }
+ WCMD_output (newline);
+}
+
+/****************************************************************************
+ * WCMD_setshow_path
+ *
+ * Set/Show the path environment variable
+ */
+
+void WCMD_setshow_path () {
+
+char string[1024];
+DWORD status;
+
+ if (strlen(param1) == 0) {
+ status = GetEnvironmentVariable ("PATH", string, sizeof(string));
+ if (status != 0) {
+ WCMD_output ("PATH=%s\n", string);
+ }
+ else {
+ WCMD_output ("PATH not found\n");
+ }
+ }
+ else {
+ status = SetEnvironmentVariable ("PATH", param1);
+ if (!status) WCMD_print_error();
+ }
+}
+
+/****************************************************************************
+ * WCMD_setshow_prompt
+ *
+ * Set or show the command prompt.
+ */
+
+void WCMD_setshow_prompt () {
+
+char *s;
+
+ if (strlen(param1) == 0) {
+ SetEnvironmentVariable ("PROMPT", NULL);
+ }
+ else {
+ s = param1;
+ while ((*s == '=') || (*s == ' ')) s++;
+ if (strlen(s) == 0) {
+ SetEnvironmentVariable ("PROMPT", NULL);
+ }
+ else SetEnvironmentVariable ("PROMPT", s);
+ }
+}
+
+/****************************************************************************
+ * WCMD_setshow_time
+ *
+ * Set/Show the system time
+ * FIXME: Can't change time yet
+ */
+
+void WCMD_setshow_time () {
+
+char curtime[64], buffer[64];
+DWORD count;
+
+ if (strlen(param1) == 0) {
+ if (GetTimeFormat (LOCALE_USER_DEFAULT, 0, NULL, NULL,
+ curtime, sizeof(curtime))) {
+ WCMD_output ("Current Time is %s\nEnter new time: ", curtime);
+ ReadFile (STDin, buffer, sizeof(buffer), &count, NULL);
+ if (count > 2) {
+ WCMD_output (nyi);
+ }
+ }
+ else WCMD_print_error ();
+ }
+ else {
+ WCMD_output (nyi);
+ }
+}
+
+/****************************************************************************
+ * WCMD_shift
+ *
+ * Shift batch parameters.
+ */
+
+void WCMD_shift () {
+
+ WCMD_output (nyi);
+
+}
+
+/****************************************************************************
+ * WCMD_type
+ *
+ * Copy a file to standard output.
+ */
+
+void WCMD_type () {
+
+HANDLE h;
+char buffer[512];
+DWORD count;
+
+ h = CreateFile (param1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, 0);
+ if (h == INVALID_HANDLE_VALUE) {
+ WCMD_print_error ();
+ return;
+ }
+ while (ReadFile (h, buffer, sizeof(buffer), &count, NULL)) {
+ if (count == 0) break; /* ReadFile reports success on EOF! */
+ WriteFile (STDout, buffer, count, &count, NULL);
+ }
+ CloseHandle (h);
+}
+
+/****************************************************************************
+ * WCMD_verify
+ *
+ * Display verify flag.
+ */
+
+void WCMD_verify () {
+
+ WCMD_output (nyi);
+
+}
+
+/****************************************************************************
+ * WCMD_version
+ *
+ * Display version info.
+ */
+
+void WCMD_version () {
+
+ WCMD_output (version_string);
+
+}
+
+/****************************************************************************
+ * WCMD_volume
+ *
+ * Display volume info and/or set volume label. Returns 0 if error.
+ */
+
+int WCMD_volume (int mode, char *path) {
+
+DWORD count, serial;
+char string[MAX_PATH], label[MAX_PATH], curdir[MAX_PATH];
+BOOL status;
+static char syntax[] = "Syntax Error\n\n";
+
+ if (lstrlen(path) == 0) {
+ status = GetCurrentDirectory (sizeof(curdir), curdir);
+ if (!status) {
+ WCMD_print_error ();
+ return 0;
+ }
+ status = GetVolumeInformation (NULL, label, sizeof(label), &serial, NULL,
+ NULL, NULL, 0);
+ }
+ else {
+ if ((path[1] != ':') || (lstrlen(path) != 2)) {
+ WriteFile (STDout, syntax, strlen(syntax), &count, NULL);
+ return 0;
+ }
+ wsprintf (curdir, "%s\\", path);
+ status = GetVolumeInformation (curdir, label, sizeof(label), &serial, NULL,
+ NULL, NULL, 0);
+ }
+ if (!status) {
+ WCMD_print_error ();
+ return 0;
+ }
+ WCMD_output ("Volume in drive %c is %s\nVolume Serial Number is %04x-%04x\n\n",
+ curdir[0], label, HIWORD(serial), LOWORD(serial));
+ if (mode) {
+ WCMD_output ("Volume label (11 characters, ENTER for none)?");
+ ReadFile (STDin, string, sizeof(string), &count, NULL);
+ if (lstrlen(path) != 0) {
+ if (!SetVolumeLabel (curdir, string)) WCMD_print_error ();
+ }
+ else {
+ if (!SetVolumeLabel (NULL, string)) WCMD_print_error ();
+ }
+ }
+ return 1;
+}
diff --git a/programs/wcmd/directory.c b/programs/wcmd/directory.c
new file mode 100644
index 0000000..62d0620
--- /dev/null
+++ b/programs/wcmd/directory.c
@@ -0,0 +1,301 @@
+/*
+ * WCMD - Wine-compatible command line interface - Directory functions.
+ *
+ * (C) 1999 D A Pickles
+ *
+ * On entry, global variables quals, param1, param2 contain
+ * the qualifiers (uppercased and concatenated) and parameters entered, with
+ * environment-variable and batch parameter substitution already done.
+ */
+
+/*
+ * FIXME:
+ * - 32-bit limit on individual file sizes (directories and free space are 64-bit)
+ * - DIR /S fails if the starting directory is not the current default.
+ */
+
+#include "wcmd.h"
+
+int WCMD_dir_sort (const void *a, const void *b);
+void WCMD_list_directory (char *path, int level);
+char * WCMD_filesize64 (__int64 n);
+char * WCMD_filesize32 (int n);
+char * WCMD_strrev (char *buff);
+
+
+extern HANDLE STDin, STDout;
+extern char nyi[];
+extern char newline[];
+extern char version_string[];
+extern char anykey[];
+extern int echo_mode;
+extern char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
+
+int file_total, dir_total, line_count, page_mode, recurse;
+__int64 byte_total;
+
+/*****************************************************************************
+ * WCMD_directory
+ *
+ * List a file directory.
+ * FIXME: /S switch only works for the current directory
+ *
+ */
+
+void WCMD_directory () {
+
+char path[MAX_PATH], drive[8];
+int status;
+__int64 free_space;
+DWORD spc, bps, fc, capacity;
+
+ line_count = 5;
+ page_mode = (strstr(quals, "/P") != NULL);
+ recurse = (strstr(quals, "/S") != NULL);
+ if (param1[0] == '\0') strcpy (param1, ".");
+ GetFullPathName (param1, sizeof(path), path, NULL);
+ lstrcpyn (drive, path, 3);
+ status = WCMD_volume (0, drive);
+ if (!status) {
+ return;
+ }
+ WCMD_list_directory (path, 0);
+ lstrcpyn (drive, path, 4);
+ GetDiskFreeSpace (drive, &spc, &bps, &fc, &capacity);
+ free_space = bps * spc * fc;
+ WCMD_output (" %18s bytes free\n\n", WCMD_filesize64 (free_space));
+ if (recurse) {
+ WCMD_output ("Total files listed:\n%8d files%25s bytes\n%8d directories\n\n",
+ file_total, WCMD_filesize64 (byte_total), dir_total);
+ }
+}
+
+/*****************************************************************************
+ * WCMD_list_directory
+ *
+ * List a single file directory. This function (and those below it) can be called
+ * recursively when the /S switch is used.
+ *
+ * FIXME: Assumes individual files are less than 2**32 bytes.
+ * FIXME: Entries sorted by name only. Should we support DIRCMD??
+ * FIXME: Assumes 24-line display for the /P qualifier.
+ * FIXME: Other command qualifiers not supported.
+ * FIXME: DIR /S FILENAME fails if at least one matching file is not found in the top level.
+ */
+
+void WCMD_list_directory (char *search_path, int level) {
+
+char string[1024], datestring[32], timestring[32];
+char mem_err[] = "Memory Allocation Error";
+char *p;
+DWORD count;
+WIN32_FIND_DATA *fd;
+FILETIME ft;
+SYSTEMTIME st;
+HANDLE hff;
+int status, dir_count, file_count, entry_count, i;
+__int64 byte_count;
+
+ dir_count = 0;
+ file_count = 0;
+ entry_count = 0;
+ byte_count = 0;
+
+/*
+ * If the path supplied does not include a wildcard, and the endpoint of the
+ * path references a directory, we need to list the *contents* of that
+ * directory not the directory file itself.
+ */
+
+ if ((strchr(search_path, '*') == NULL) && (strchr(search_path, '%') == NULL)) {
+ status = GetFileAttributes (search_path);
+ if ((status != -1) && (status & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (search_path[strlen(search_path)-1] == '\\') {
+ strcat (search_path, "*");
+ }
+ else {
+ strcat (search_path, "\\*");
+ }
+ }
+ }
+
+ fd = malloc (sizeof(WIN32_FIND_DATA));
+ hff = FindFirstFile (search_path, fd);
+ if (hff == INVALID_HANDLE_VALUE) {
+ WCMD_output ("File Not Found\n");
+ free (fd);
+ return;
+ }
+ do {
+ entry_count++;
+ fd = realloc (fd, (entry_count+1)*sizeof(WIN32_FIND_DATA));
+ if (fd == NULL) {
+ FindClose (hff);
+ WCMD_output (mem_err);
+ return;
+ }
+ } while (FindNextFile(hff, (fd+entry_count)) != 0);
+ FindClose (hff);
+ qsort (fd, entry_count, sizeof(WIN32_FIND_DATA), WCMD_dir_sort);
+ if (level != 0) WCMD_output ("\n\n");
+ WCMD_output ("Directory of %s\n\n", search_path);
+ if (page_mode) {
+ line_count += 2;
+ if (line_count > 23) {
+ line_count = 0;
+ WCMD_output (anykey);
+ ReadFile (STDin, string, sizeof(string), &count, NULL);
+ }
+ }
+ for (i=0; i<entry_count; i++) {
+ FileTimeToLocalFileTime (&(fd+i)->ftLastWriteTime, &ft);
+ FileTimeToSystemTime (&ft, &st);
+ GetDateFormat (0, DATE_SHORTDATE, &st, NULL, datestring,
+ sizeof(datestring));
+ GetTimeFormat (0, TIME_NOSECONDS, &st,
+ NULL, timestring, sizeof(timestring));
+ if ((fd+i)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ dir_count++;
+ WCMD_output ("%8s %8s <DIR> %s\n",
+ datestring, timestring, (fd+i)->cFileName);
+ }
+ else {
+ file_count++;
+ byte_count += (fd+i)->nFileSizeLow;
+ WCMD_output ("%8s %8s %10s %s\n",
+ datestring, timestring,
+ WCMD_filesize32((fd+i)->nFileSizeLow), (fd+i)->cFileName);
+ }
+ if (page_mode) {
+ if (++line_count > 23) {
+ line_count = 0;
+ WCMD_output (anykey);
+ ReadFile (STDin, string, sizeof(string), &count, NULL);
+ }
+ }
+ }
+ if (file_count == 1) {
+ WCMD_output (" 1 file %25s bytes\n", WCMD_filesize64 (byte_count));
+ }
+ else {
+ WCMD_output ("%8d files %24s bytes\n", file_count, WCMD_filesize64 (byte_count));
+ }
+ if (page_mode) {
+ if (++line_count > 23) {
+ line_count = 0;
+ WCMD_output (anykey);
+ ReadFile (STDin, string, sizeof(string), &count, NULL);
+ }
+ }
+ byte_total = byte_total + byte_count;
+ file_total = file_total + file_count;
+ dir_total = dir_total + dir_count;
+ if (dir_count == 1) WCMD_output ("1 directory ");
+ else WCMD_output ("%8d directories", dir_count);
+ if (page_mode) {
+ if (++line_count > 23) {
+ line_count = 0;
+ WCMD_output (anykey);
+ ReadFile (STDin, string, sizeof(string), &count, NULL);
+ }
+ }
+ for (i=0; i<entry_count; i++) {
+ if ((recurse) &&
+ ((fd+i)->cFileName[0] != '.') &&
+ ((fd+i)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+// GetFullPathName ((fd+i)->cFileName, sizeof(string), string, NULL);
+ p = strrchr (search_path, '\\');
+ lstrcpyn (string, search_path, (p-search_path+2));
+ lstrcat (string, (fd+i)->cFileName);
+ lstrcat (string, p);
+ WCMD_list_directory (string, 1);
+ }
+ }
+ free (fd);
+ return;
+}
+
+/*****************************************************************************
+ * WCMD_filesize64
+ *
+ * Convert a 64-bit number into a character string, with commas every three digits.
+ * Result is returned in a static string overwritten with each call.
+ * FIXME: There must be a better algorithm!
+ */
+
+char * WCMD_filesize64 (__int64 n) {
+
+__int64 q;
+int r, i;
+char *p;
+static char buff[32];
+
+ p = buff;
+ i = -3;
+ do {
+ if ((++i)%3 == 1) *p++ = ',';
+ q = n / 10;
+ r = n - (q * 10);
+ *p++ = r + '0';
+ *p = '\0';
+ n = q;
+ } while (n != 0);
+ WCMD_strrev (buff);
+ return buff;
+}
+
+/*****************************************************************************
+ * WCMD_filesize32
+ *
+ * Convert a 32-bit number into a character string, with commas every three digits.
+ * Result is returned in a static string overwritten with each call.
+ * FIXME: There must be a better algorithm!
+ */
+
+char * WCMD_filesize32 (int n) {
+
+int r, i;
+char *p, *q;
+static char buff1[16], buff2[16];
+
+ wsprintf (buff1, "%i", n);
+ r = lstrlen (buff1);
+ WCMD_strrev (buff1);
+ p = buff1;
+ q = buff2;
+ for (i=0; i<r; i++) {
+ if ((i-2)%3 == 1) *q++ = ',';
+ *q++ = *p++;
+ }
+ *q = '\0';
+ WCMD_strrev (buff2);
+ return buff2;
+}
+
+/*****************************************************************************
+ * WCMD_strrev
+ *
+ * Reverse a character string in-place (strrev() is not available under unixen :-( ).
+ */
+
+char * WCMD_strrev (char *buff) {
+
+int r, i;
+char b;
+
+ r = lstrlen (buff);
+ for (i=0; i<r/2; i++) {
+ b = buff[i];
+ buff[i] = buff[r-i-1];
+ buff[r-i-1] = b;
+ }
+ return (buff);
+}
+
+
+int WCMD_dir_sort (const void *a, const void *b) {
+
+ return (lstrcmpi(((WIN32_FIND_DATA *)a)->cFileName,
+ ((WIN32_FIND_DATA *)b)->cFileName));
+}
+
diff --git a/programs/wcmd/makefile.bcc b/programs/wcmd/makefile.bcc
new file mode 100644
index 0000000..910e9c1
--- /dev/null
+++ b/programs/wcmd/makefile.bcc
@@ -0,0 +1,47 @@
+#-----------------------------------------------------------------------------
+VERSION = BCB.01
+#-----------------------------------------------------------------------------
+!ifndef BCB
+BCB = $(MAKEDIR)\..
+!endif
+PROJECT = wcmd.exe
+OBJFILES = builtins.obj wcmdmain.obj directory.obj batch.obj
+RESFILES = wcmdrc.rc
+RESDEPEN = $(RESFILES)
+LIBFILES =
+DEFFILE =
+#-----------------------------------------------------------------------------
+CFLAG1 = -c
+CFLAG2 = -H=C:\BC\PROJECTS\CMD.CSM -nC:\BC\PROJECTS\CMD \
+ -IC:\BC\INCLUDE;C:\BC\PROJECTS\CMD
+PFLAGS = -U$(BCB)\lib\obj -jph -m
+RFLAGS = -I$(BCB)\include;C:\BC\INCLUDE;C:\BC\PROJECTS\CMD
+LFLAGS = -ap -Tpe -c -x -L$(BCB)\lib;$(BCB)\lib\obj;C:\BC\LIB
+IFLAGS = -i
+LINKER = tlink32
+#-----------------------------------------------------------------------------
+ALLOBJ = c0x32.obj $(OBJFILES)
+ALLRES = $(RESFILES)
+ALLLIB = $(LIBFILES) noeh32.lib import32.lib cw32mt.lib
+# ---------------------------------------------------------------------------
+.autodepend
+
+$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE)
+ $(BCB)\BIN\$(LINKER) @&&!
+ $(LFLAGS) +
+ $(ALLOBJ), +
+ $(PROJECT),, +
+ $(ALLLIB), +
+ $(DEFFILE), +
+ $(ALLRES)
+!
+
+.cpp.obj:
+ $(BCB)\BIN\bcc32 $(CFLAG1) $(CFLAG2) -o$* $*
+
+.c.obj:
+ $(BCB)\BIN\bcc32 $(CFLAG1) $(CFLAG2) -o$* $**
+
+.rc.res:
+ $(BCB)\BIN\brcc32 $(RFLAGS) $<
+#-----------------------------------------------------------------------------
diff --git a/programs/wcmd/wcmd.h b/programs/wcmd/wcmd.h
new file mode 100644
index 0000000..f12104c
--- /dev/null
+++ b/programs/wcmd/wcmd.h
@@ -0,0 +1,108 @@
+/*
+ * WCMD - Wine-compatible command line interface.
+ *
+ * (C) 1999 D A Pickles
+ */
+
+
+#define IDI_ICON1 1
+#include <windows.h>
+#ifndef RC_INVOKED
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef WINELIB
+#include <winbase.h>
+#include <wincon.h>
+#endif /* !WINELIB */
+
+void WCMD_batch (char *, char *);
+void WCMD_call (void);
+void WCMD_change_tty (void);
+void WCMD_clear_screen (void);
+void WCMD_copy (void);
+void WCMD_create_dir (void);
+void WCMD_delete (int recurse);
+void WCMD_directory (void);
+void WCMD_echo (char *);
+void WCMD_for (void);
+void WCMD_give_help (char *command);
+void WCMD_if (void);
+void WCMD_move (void);
+void WCMD_output (char *format, ...);
+void WCMD_parse (char *s, char *q, char *p1, char *p2);
+void WCMD_pause (void);
+void WCMD_print_error (void);
+void WCMD_process_command (char *command);
+void WCMD_remove_dir (void);
+void WCMD_rename (void);
+void WCMD_run_program (char *command);
+void WCMD_setshow_attrib (void);
+void WCMD_setshow_date (void);
+void WCMD_setshow_default (void);
+void WCMD_setshow_env (char *command);
+void WCMD_setshow_path (void);
+void WCMD_setshow_prompt (void);
+void WCMD_setshow_time (void);
+void WCMD_shift (void);
+void WCMD_show_prompt (void);
+void WCMD_type (void);
+void WCMD_verify (void);
+void WCMD_version (void);
+int WCMD_volume (int mode, char *command);
+
+char *WCMD_fgets (char *s, int n, HANDLE stream);
+char *WCMD_strtrim_leading_spaces (char *string);
+void WCMD_strtrim_trailing_spaces (char *string);
+#endif /* !RC_INVOKED */
+
+/*
+ * Serial nos of builtin commands. These constants must be in step with
+ * the list of strings defined in WCMD.C, and WCMD_EXIT *must* always be
+ * the last one.
+ *
+ * Yes it *would* be nice to use an enumeration here, but the Resource
+ * Compiler won't accept resource IDs from enumerations :-(
+ */
+
+#define WCMD_ATTRIB 0
+#define WCMD_CALL 1
+#define WCMD_CD 2
+#define WCMD_CHDIR 3
+#define WCMD_CLS 4
+#define WCMD_COPY 5
+#define WCMD_CTTY 6
+#define WCMD_DATE 7
+#define WCMD_DEL 8
+#define WCMD_DIR 9
+#define WCMD_ECHO 10
+#define WCMD_ERASE 11
+#define WCMD_FOR 12
+#define WCMD_GOTO 13
+#define WCMD_HELP 14
+#define WCMD_IF 15
+#define WCMD_LABEL 16
+#define WCMD_MD 17
+#define WCMD_MKDIR 18
+#define WCMD_MOVE 19
+#define WCMD_PATH 20
+#define WCMD_PAUSE 21
+#define WCMD_PROMPT 22
+#define WCMD_REM 23
+#define WCMD_REN 24
+#define WCMD_RENAME 25
+#define WCMD_RD 26
+#define WCMD_RMDIR 27
+#define WCMD_SET 28
+#define WCMD_SHIFT 29
+#define WCMD_TIME 30
+#define WCMD_TYPE 31
+#define WCMD_VERIFY 32
+#define WCMD_VER 33
+#define WCMD_VOL 34
+#define WCMD_EXIT 35
+
+
diff --git a/programs/wcmd/wcmdmain.c b/programs/wcmd/wcmdmain.c
new file mode 100644
index 0000000..4fc0d72
--- /dev/null
+++ b/programs/wcmd/wcmdmain.c
@@ -0,0 +1,556 @@
+/*
+ * WCMD - Wine-compatible command line interface.
+ *
+ * (C) 1999 D A Pickles
+ */
+
+/*
+ * FIXME:
+ * - No support for redirection, pipes, batch commands
+ * - 32-bit limit on file sizes in DIR command
+ * - Cannot handle parameters in quotes
+ * - Lots of functionality missing from builtins
+ */
+
+#include "wcmd.h"
+
+#ifdef WINELIB
+/* external declaration here because we don't want to depend on Wine headers */
+#ifdef __cplusplus
+extern "C" HINSTANCE MAIN_WinelibInit( int *argc, char *argv[] );
+#else
+extern HINSTANCE MAIN_WinelibInit( int *argc, char *argv[] );
+#endif
+#endif /* WINELIB */
+
+char *inbuilt[] = {"ATTRIB", "CALL", "CD", "CHDIR", "CLS", "COPY", "CTTY",
+ "DATE", "DEL", "DIR", "ECHO", "ERASE", "FOR", "GOTO",
+ "HELP", "IF", "LABEL", "MD", "MKDIR", "MOVE", "PATH", "PAUSE",
+ "PROMPT", "REM", "REN", "RENAME", "RD", "RMDIR", "SET", "SHIFT",
+ "TIME", "TYPE", "VERIFY", "VER", "VOL", "EXIT"};
+
+HANDLE STDin, STDout;
+HINSTANCE hinst;
+int echo_mode = 1;
+char nyi[] = "Not Yet Implemented\n\n";
+char newline[] = "\n";
+char version_string[] = "WCMD Version 0.10\n\n";
+char anykey[] = "Press any key to continue: ";
+char quals[MAX_PATH], param1[MAX_PATH], param2[MAX_PATH];
+
+/*****************************************************************************
+ * Main entry point. This is a console application so we have a main() not a
+ * winmain().
+ */
+
+
+int main (int argc, char *argv[]) {
+
+char string[1024], args[MAX_PATH], param[MAX_PATH];
+int status, i;
+DWORD count;
+HANDLE h;
+
+#ifdef WINELIB
+ if (!(hinst = MAIN_WinelibInit( &argc, argv ))) return 0;
+#else
+ hinst = 0;
+#endif
+
+ args[0] = param[0] = '\0';
+ if (argc > 1) {
+ for (i=1; i<argc; i++) {
+ if (argv[i][0] == '/') {
+ strcat (args, argv[i]);
+ }
+ else {
+ strcat (param, argv[i]);
+ strcat (param, " ");
+ }
+ }
+ }
+
+/*
+ * Allocate a console and set it up.
+ */
+
+ status = FreeConsole ();
+ if (!status) WCMD_print_error();
+ status = AllocConsole();
+ if (!status) WCMD_print_error();
+ STDout = GetStdHandle (STD_OUTPUT_HANDLE);
+ STDin = GetStdHandle (STD_INPUT_HANDLE);
+ SetConsoleMode (STDin, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT |
+ ENABLE_PROCESSED_INPUT);
+
+/*
+ * Execute any command-line options.
+ */
+
+ if (strstr(args, "/q") != NULL) {
+ WCMD_echo ("OFF");
+ }
+
+ if (strstr(args, "/c") != NULL) {
+ WCMD_process_command (param);
+ return 0;
+ }
+
+ if (strstr(args, "/k") != NULL) {
+ WCMD_process_command (param);
+ }
+
+/*
+ * If there is an AUTOEXEC.BAT file, try to execute it.
+ */
+
+ GetFullPathName ("\\autoexec.bat", sizeof(string), string, NULL);
+ h = CreateFile (string, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (h != INVALID_HANDLE_VALUE) {
+ CloseHandle (h);
+// WCMD_batch (string, " ");
+ }
+
+/*
+ * Loop forever getting commands and executing them.
+ */
+
+ WCMD_version ();
+ while (TRUE) {
+ WCMD_show_prompt ();
+ ReadFile (STDin, string, sizeof(string), &count, NULL);
+ if (count > 1) {
+ string[count-1] = '\0'; /* ReadFile output is not null-terminated! */
+ if (string[count-2] == '\r') string[count-2] = '\0'; /* Under Windoze we get CRLF! */
+ if (lstrlen (string) != 0) {
+ WCMD_process_command (string);
+ }
+ }
+ }
+}
+
+
+/*****************************************************************************
+ * Process one command. If the command is EXIT this routine does not return.
+ * We will recurse through here executing batch files.
+ */
+
+
+void WCMD_process_command (char *command) {
+
+char cmd[1024];
+char *p;
+int status, i;
+DWORD count;
+
+/*
+ * Throw away constructs we don't support yet
+ */
+
+ if ((strchr(command,'<') != NULL) || (strchr(command,'>') != NULL)) {
+ WCMD_output ("Redirection not yet implemented\n");
+ return;
+ }
+ if (strchr(command,'|') != NULL) {
+ WCMD_output ("Pipes not yet implemented\n");
+ return;
+ }
+
+/*
+ * Expand up environment variables.
+ */
+
+ status = ExpandEnvironmentStrings (command, cmd, sizeof(cmd));
+ if (!status) {
+ WCMD_print_error ();
+ return;
+ }
+
+/*
+ * Changing default drive has to be handled as a special case.
+ */
+
+ if ((cmd[1] == ':') && IsCharAlpha (cmd[0]) && (strlen(cmd) == 2)) {
+ status = SetCurrentDirectory (cmd);
+ if (!status) WCMD_print_error ();
+ return;
+ }
+ WCMD_output (newline);
+
+/*
+ * Check if the command entered is internal. If it is, pass the rest of the
+ * line down to the command. If not try to run a program.
+ */
+
+ count = 0;
+ while (IsCharAlphaNumeric(cmd[count])) {
+ count++;
+ }
+ for (i=0; i<=WCMD_EXIT; i++) {
+ if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
+ cmd, count, inbuilt[i], -1) == 2) break;
+ }
+ p = WCMD_strtrim_leading_spaces (&cmd[count]);
+ WCMD_parse (p, quals, param1, param2);
+ switch (i) {
+
+ case WCMD_ATTRIB:
+ WCMD_setshow_attrib ();
+ break;
+ case WCMD_CALL:
+ WCMD_batch (param1, p);
+ break;
+ case WCMD_CD:
+ case WCMD_CHDIR:
+ WCMD_setshow_default ();
+ break;
+ case WCMD_CLS:
+ WCMD_clear_screen ();
+ break;
+ case WCMD_COPY:
+ WCMD_copy ();
+ break;
+ case WCMD_CTTY:
+ WCMD_change_tty ();
+ break;
+ case WCMD_DATE:
+ WCMD_setshow_date ();
+ break;
+ case WCMD_DEL:
+ case WCMD_ERASE:
+ WCMD_delete (0);
+ break;
+ case WCMD_DIR:
+ WCMD_directory ();
+ break;
+ case WCMD_ECHO:
+ WCMD_echo (p);
+ break;
+ case WCMD_FOR:
+ WCMD_for ();
+ break;
+ case WCMD_GOTO:
+ break;
+ case WCMD_HELP:
+ WCMD_give_help (p);
+ break;
+ case WCMD_IF:
+ WCMD_if ();
+ break;
+ case WCMD_LABEL:
+ WCMD_volume (1, p);
+ break;
+ case WCMD_MD:
+ case WCMD_MKDIR:
+ WCMD_create_dir ();
+ break;
+ case WCMD_MOVE:
+ WCMD_move ();
+ break;
+ case WCMD_PATH:
+ WCMD_setshow_path ();
+ break;
+ case WCMD_PAUSE:
+ WCMD_pause ();
+ break;
+ case WCMD_PROMPT:
+ WCMD_setshow_prompt ();
+ break;
+ case WCMD_REM:
+ break;
+ case WCMD_REN:
+ case WCMD_RENAME:
+ WCMD_rename ();
+ break;
+ case WCMD_RD:
+ case WCMD_RMDIR:
+ WCMD_remove_dir ();
+ break;
+ case WCMD_SET:
+ WCMD_setshow_env (p);
+ break;
+ case WCMD_SHIFT:
+ WCMD_shift ();
+ break;
+ case WCMD_TIME:
+ WCMD_setshow_time ();
+ break;
+ case WCMD_TYPE:
+ WCMD_type ();
+ break;
+ case WCMD_VER:
+ WCMD_version ();
+ break;
+ case WCMD_VERIFY:
+ WCMD_verify ();
+ break;
+ case WCMD_VOL:
+ WCMD_volume (0, p);
+ break;
+ case WCMD_EXIT:
+ ExitProcess (0);
+ default:
+ WCMD_run_program (cmd);
+ };
+ }
+
+/******************************************************************************
+ * WCMD_run_program
+ *
+ * Execute a command line as an external program. If no extension given then
+ * precedence is given to .BAT files. Must allow recursion.
+ *
+ * FIXME: Case sensitivity in suffixes!
+ */
+
+void WCMD_run_program (char *command) {
+
+STARTUPINFO st;
+PROCESS_INFORMATION pe;
+BOOL status;
+HANDLE h;
+char filetorun[MAX_PATH];
+
+ WCMD_parse (command, quals, param1, param2); /* Quick way to get the filename */
+ if (strpbrk (param1, "\\:") == NULL) { /* No explicit path given */
+ if ((strchr (param1, '.') == NULL) || (strstr (param1, ".bat") != NULL)) {
+ if (SearchPath (NULL, param1, ".bat", sizeof(filetorun), filetorun, NULL)) {
+ WCMD_batch (filetorun, command);
+ return;
+ }
+ }
+ }
+ else { /* Explicit path given */
+ if (strstr (param1, ".bat") != NULL) {
+ WCMD_batch (param1, command);
+ return;
+ }
+ if (strchr (param1, '.') == NULL) {
+ strcpy (filetorun, param1);
+ strcat (filetorun, ".bat");
+ h = CreateFile (filetorun, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (h != INVALID_HANDLE_VALUE) {
+ CloseHandle (h);
+ WCMD_batch (param1, command);
+ return;
+ }
+ }
+ }
+
+ /* No batch file found, assume executable */
+
+ ZeroMemory (&st, sizeof(STARTUPINFO));
+ st.cb = sizeof(STARTUPINFO);
+ status = CreateProcess (NULL, command, NULL, NULL, FALSE,
+ 0, NULL, NULL, &st, &pe);
+ if (!status) {
+ WCMD_print_error ();
+ }
+}
+
+/******************************************************************************
+ * WCMD_show_prompt
+ *
+ * Display the prompt on STDout
+ *
+ */
+
+void WCMD_show_prompt () {
+
+int status;
+char out_string[MAX_PATH], curdir[MAX_PATH], prompt_string[MAX_PATH];
+char *p, *q;
+
+ status = GetEnvironmentVariable ("PROMPT", prompt_string, sizeof(prompt_string));
+ if ((status == 0) || (status > sizeof(prompt_string))) {
+ lstrcpy (prompt_string, "$N$G");
+ }
+ p = prompt_string;
+ q = out_string;
+ *q = '\0';
+ while (*p != '\0') {
+ if (*p != '$') {
+ *q++ = *p++;
+ *q = '\0';
+ }
+ else {
+ p++;
+ switch (toupper(*p)) {
+ case '$':
+ *q++ = '$';
+ break;
+ case 'B':
+ *q++ = '|';
+ break;
+ case 'D':
+ GetDateFormat (LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, q, MAX_PATH);
+ while (*q) q++;
+ break;
+ case 'E':
+ *q++ = '\E';
+ break;
+ case 'G':
+ *q++ = '>';
+ break;
+ case 'L':
+ *q++ = '<';
+ break;
+ case 'N':
+ status = GetCurrentDirectory (sizeof(curdir), curdir);
+ if (status) {
+ *q++ = curdir[0];
+ }
+ break;
+ case 'P':
+ status = GetCurrentDirectory (sizeof(curdir), curdir);
+ if (status) {
+ lstrcat (q, curdir);
+ while (*q) q++;
+ }
+ break;
+ case 'Q':
+ *q++ = '=';
+ break;
+ case 'T':
+ GetTimeFormat (LOCALE_USER_DEFAULT, 0, NULL, NULL, q, MAX_PATH);
+ while (*q) q++;
+ break;
+ case '_':
+ *q++ = '\n';
+ break;
+ }
+ p++;
+ *q = '\0';
+ }
+ }
+ WCMD_output (out_string);
+}
+
+/****************************************************************************
+ * WCMD_print_error
+ *
+ * Print the message for GetLastError - not much use yet as Wine doesn't have
+ * the messages available, so we show meaningful messages for the most likely.
+ */
+
+void WCMD_print_error () {
+LPVOID lpMsgBuf;
+DWORD error_code;
+
+ error_code = GetLastError ();
+ switch (error_code) {
+ case ERROR_FILE_NOT_FOUND:
+ WCMD_output ("File Not Found\n");
+ break;
+ case ERROR_PATH_NOT_FOUND:
+ WCMD_output ("Path Not Found\n");
+ break;
+ default:
+ FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, error_code,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf, 0, NULL);
+ WCMD_output (lpMsgBuf);
+ LocalFree ((HLOCAL)lpMsgBuf);
+ }
+ return;
+}
+
+/*******************************************************************
+ * WCMD_parse - parse a command into parameters and qualifiers.
+ *
+ * On exit, all qualifiers are concatenated into q, the first string
+ * not beginning with "/" is in p1 and the
+ * second in p2. Any subsequent non-qualifier strings are lost.
+ * Parameters in quotes are handled.
+ */
+
+void WCMD_parse (char *s, char *q, char *p1, char *p2) {
+
+int p = 0;
+
+ *q = *p1 = *p2 = '\0';
+ while (TRUE) {
+ switch (*s) {
+ case '/':
+ *q++ = *s++;
+ while ((*s != '\0') && (*s != ' ') && *s != '/') {
+ *q++ = toupper (*s++);
+ }
+ *q = '\0';
+ break;
+ case ' ':
+ s++;
+ break;
+ case '"':
+ s++;
+ while ((*s != '\0') && (*s != '"')) {
+ if (p == 0) *p1++ = *s++;
+ else if (p == 1) *p2++ = *s++;
+ else s++;
+ }
+ if (p == 0) *p1 = '\0';
+ if (p == 1) *p2 = '\0';
+ p++;
+ if (*s == '"') s++;
+ break;
+ case '\0':
+ return;
+ default:
+ while ((*s != '\0') && (*s != ' ') && (*s != '/')) {
+ if (p == 0) *p1++ = *s++;
+ else if (p == 1) *p2++ = *s++;
+ else s++;
+ }
+ if (p == 0) *p1 = '\0';
+ if (p == 1) *p2 = '\0';
+ p++;
+ }
+ }
+}
+
+/*******************************************************************
+ * WCMD_output - send output to current standard output device.
+ *
+ */
+
+void WCMD_output (char *format, ...) {
+
+va_list ap;
+char string[1024];
+DWORD count;
+
+ va_start(ap,format);
+ vsprintf (string, format, ap);
+ WriteFile (STDout, string, lstrlen(string), &count, NULL);
+ va_end(ap);
+}
+
+
+/* Remove leading spaces from a string. Return a pointer to the first
+ * non-space character. Does not modify the input string
+ */
+
+char *WCMD_strtrim_leading_spaces (char *string) {
+
+char *ptr;
+
+ ptr = string;
+ while (*ptr == ' ') ptr++;
+ return ptr;
+}
+
+/* Remove trailing spaces from a string. This routine modifies the input
+ * string by placing a null after the last non-space character
+ */
+
+void WCMD_strtrim_trailing_spaces (char *string) {
+
+char *ptr;
+
+ ptr = string + lstrlen (string) - 1;
+ while ((*ptr == ' ') && (ptr >= string)) {
+ *ptr = '\0';
+ ptr--;
+ }
+}
diff --git a/programs/wcmd/wcmdrc.rc b/programs/wcmd/wcmdrc.rc
new file mode 100644
index 0000000..1c8eaaf
--- /dev/null
+++ b/programs/wcmd/wcmdrc.rc
@@ -0,0 +1,294 @@
+
+#include "wcmd.h"
+
+STRINGTABLE
+{
+ WCMD_ATTRIB, "Help about ATTRIB\n"
+ WCMD_CALL, "Help about CALL\n"
+ WCMD_CD, "Help about CD\n"
+ WCMD_CHDIR, "Help about CHDIR\n"
+
+ WCMD_CLS,
+"CLS clears the console screen\n"
+
+ WCMD_COPY, "Help about COPY\n"
+ WCMD_CTTY, "Help about CTTY\n"
+ WCMD_DATE, "Help about DATE\n"
+ WCMD_DEL, "Help about DEL\n"
+ WCMD_DIR, "Help about DIR\n"
+
+ WCMD_ECHO,
+"ECHO <string> displays <string> on the current terminal device.\
+ \
+ECHO ON causes all subsequent commands in a batch file to be displayed\
+on the terminal device before they are executed.\
+ \
+ECHO OFF reverses the effect of a previous ECHO ON (ECHO is OFF by\
+default). The ECHO OFF command can be prevented from displaying by\
+preceding it with an @ sign.\n"
+
+ WCMD_ERASE, "Help about ERASE\n"
+ WCMD_FOR, "Help about FOR\n"
+ WCMD_GOTO, "Help about GOTO\n"
+ WCMD_HELP, "Help about HELP\n"
+ WCMD_IF, "Help about IF\n"
+ WCMD_LABEL, "Help about LABEL\n"
+ WCMD_MD, "Help about MD\n"
+ WCMD_MKDIR, "Help about MKDIR\n"
+ WCMD_MOVE, "Help about MOVE\n"
+ WCMD_PATH,
+"PATH displays or changes the wcmd search path. \
+ \
+Entering PATH will display the current PATH setting (initially this is \
+the value given in your wine.conf file). To change the setting follow the \
+PATH command with the new value. \
+ \
+It is also possible to modify the PATH by using the PATH environment \
+variable, for example: \
+ PATH %PATH%;c:\\temp \n"
+
+ WCMD_PAUSE,
+"PAUSE displays a message on the screen 'Press Return key to continue'\
+and waits for the user to press the Return key. It is mainly useful in\
+batch files to allow the user to read the output of a previous command\
+before it scrolls off the screen.\n"
+
+ WCMD_PROMPT,
+"PROMPT sets the command-line prompt.\
+ \
+The string following the PROMPT command (and the space immediately after)\
+appears at the beginning of the line when wcmd is waiting for input.\
+ \
+The following character strings have the special meaning shown:\
+ \
+$$ Dollar sign $_ Linefeed $b Pipe sign (|)\
+$d Current date $e Escape $g > sign\
+$l > sign $n Current drive $p Current path\
+$q Equal sign $t Current time $v wcmd version\
+ \
+Note that entering the PROMPT command without a prompt-string resets the\
+prompt to the default, which is the current drive letter followed by a\
+greater-than (>) sign.\
+ \
+The prompt can also be changed by altering the PROMPT environment variable,\
+so the command 'SET PROMPT=text' has the same effect as 'PROMPT text'\n"
+
+ WCMD_REM,
+"A command line beginning REM (followed by a space) performs no\
+action, and can therefore be used as a comment in a batch file.\n"
+
+ WCMD_REN, "Help about REN\n"
+ WCMD_RENAME, "Help about RENAME\n"
+ WCMD_RD, "Help about RD\n"
+ WCMD_RMDIR, "Help about RMDIR\n"
+
+ WCMD_SET,
+"SET displays or changes the wcmd environment variables.\
+ \
+SET without parameters shows all of the current environment.\
+ \
+To create or modify an environment variable the syntax is:\
+ \
+ SET <variable>=<value>\
+ \
+where <variable> and <value> are character strings. There must be no\
+spaces either side of the equals sign, nor can the variable or value\
+have embedded spaces.\
+ \
+Under Wine, the environment of the underlying operating system is\
+included into the Win32 environment, there will generally therefore be\
+many more values than in a native Win32 implementation. Note that it is\
+not possible to affect the operating system environment from within wcmd.\n"
+
+ WCMD_SHIFT, "Help about SHIFT\n"
+ WCMD_TIME, "Help about TIME\n"
+
+ WCMD_TYPE,
+"TYPE <filename> copies <filename> to the console device (or elsewhere\
+if redirected). No check is made that the file is readable text.\n"
+
+ WCMD_VERIFY, "Help about VERIFY\n"
+
+ WCMD_VER,
+"VER displays the version of wcmd you are running\n"
+
+ WCMD_VOL, "Help about VOL\n"
+
+ WCMD_EXIT,
+"EXIT terminates the current command session and returns\
+to the operating system or shell from which you invoked wcmd.\n"
+
+ 1000, "WCMD built-in commands are:\
+ATTRIB\t\tShow or change DOS file attributes\
+CALL\t\tInvoke a batch file from inside another\
+CD (CHDIR)\tChange current default directory\
+CLS\t\tClear the console screen\
+COPY\t\tCopy file\
+CTTY\t\tChange input/output device\
+DATE\t\tShow or change the system date\
+DEL (ERASE)\tDelete a file or set of files\
+DIR\t\tList the contents of a directory\
+ECHO\t\tCopy text directly to the console output\
+HELP\t\tShow brief help details on a topic\
+MD (MKDIR)\tCreate a subdirectory\
+MOVE\t\tMove a file, set of files or directory tree\
+PATH\t\tSet or show the search path\
+PROMPT\t\tChange the command prompt\
+REN (RENAME)\tRename a file\
+RD (RMDIR)\tDelete a subdirectory\
+SET\t\tSet or show environment variables\
+TIME\t\tSet or show the current system time\
+TYPE\t\tType the contents of a text file\
+VER\t\tShow the current version of WCMD\
+VOL\t\tShow the volume label of a disk device\
+EXIT\t\tClose down WCMD\n\
+Enter HELP <command> for further information on any of the above commands\n"
+}
+LANGUAGE LANG_NEUTRAL,SUBLANG_NEUTRAL
+
+
+IDI_ICON1 ICON
+{
+ '00 00 01 00 01 00 20 20 00 01 00 00 00 00 A8 08'
+ '00 00 16 00 00 00 28 00 00 00 20 00 00 00 40 00'
+ '00 00 01 00 08 00 00 00 00 00 80 04 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 40 00 00 00 80 00 00 00 FF 00 00 00 00 20'
+ '00 00 40 20 00 00 80 20 00 00 FF 20 00 00 00 40'
+ '00 00 40 40 00 00 80 40 00 00 FF 40 00 00 00 60'
+ '00 00 40 60 00 00 80 60 00 00 FF 60 00 00 00 80'
+ '00 00 40 80 00 00 80 80 00 00 FF 80 00 00 00 A0'
+ '00 00 40 A0 00 00 80 A0 00 00 FF A0 00 00 00 C0'
+ '00 00 40 C0 00 00 80 C0 00 00 FF C0 00 00 00 FF'
+ '00 00 40 FF 00 00 80 FF 00 00 FF FF 00 00 00 00'
+ '20 00 40 00 20 00 80 00 20 00 FF 00 20 00 00 20'
+ '20 00 40 20 20 00 80 20 20 00 FF 20 20 00 00 40'
+ '20 00 40 40 20 00 80 40 20 00 FF 40 20 00 00 60'
+ '20 00 40 60 20 00 80 60 20 00 FF 60 20 00 00 80'
+ '20 00 40 80 20 00 80 80 20 00 FF 80 20 00 00 A0'
+ '20 00 40 A0 20 00 80 A0 20 00 FF A0 20 00 00 C0'
+ '20 00 40 C0 20 00 80 C0 20 00 FF C0 20 00 00 FF'
+ '20 00 40 FF 20 00 80 FF 20 00 FF FF 20 00 00 00'
+ '40 00 40 00 40 00 80 00 40 00 FF 00 40 00 00 20'
+ '40 00 40 20 40 00 80 20 40 00 FF 20 40 00 00 40'
+ '40 00 40 40 40 00 80 40 40 00 FF 40 40 00 00 60'
+ '40 00 40 60 40 00 80 60 40 00 FF 60 40 00 00 80'
+ '40 00 40 80 40 00 80 80 40 00 FF 80 40 00 00 A0'
+ '40 00 40 A0 40 00 80 A0 40 00 FF A0 40 00 00 C0'
+ '40 00 40 C0 40 00 80 C0 40 00 FF C0 40 00 00 FF'
+ '40 00 40 FF 40 00 80 FF 40 00 FF FF 40 00 00 00'
+ '60 00 40 00 60 00 80 00 60 00 FF 00 60 00 00 20'
+ '60 00 40 20 60 00 80 20 60 00 FF 20 60 00 00 40'
+ '60 00 40 40 60 00 80 40 60 00 FF 40 60 00 00 60'
+ '60 00 40 60 60 00 80 60 60 00 FF 60 60 00 00 80'
+ '60 00 40 80 60 00 80 80 60 00 FF 80 60 00 00 A0'
+ '60 00 40 A0 60 00 80 A0 60 00 FF A0 60 00 00 C0'
+ '60 00 40 C0 60 00 80 C0 60 00 FF C0 60 00 00 FF'
+ '60 00 40 FF 60 00 80 FF 60 00 FF FF 60 00 00 00'
+ '80 00 40 00 80 00 80 00 80 00 FF 00 80 00 00 20'
+ '80 00 40 20 80 00 80 20 80 00 FF 20 80 00 00 40'
+ '80 00 40 40 80 00 80 40 80 00 FF 40 80 00 00 60'
+ '80 00 40 60 80 00 80 60 80 00 FF 60 80 00 00 80'
+ '80 00 40 80 80 00 80 80 80 00 FF 80 80 00 00 A0'
+ '80 00 40 A0 80 00 80 A0 80 00 FF A0 80 00 00 C0'
+ '80 00 40 C0 80 00 80 C0 80 00 FF C0 80 00 00 FF'
+ '80 00 40 FF 80 00 80 FF 80 00 FF FF 80 00 00 00'
+ 'A0 00 40 00 A0 00 80 00 A0 00 FF 00 A0 00 00 20'
+ 'A0 00 40 20 A0 00 80 20 A0 00 FF 20 A0 00 00 40'
+ 'A0 00 40 40 A0 00 80 40 A0 00 FF 40 A0 00 00 60'
+ 'A0 00 40 60 A0 00 80 60 A0 00 FF 60 A0 00 00 80'
+ 'A0 00 40 80 A0 00 80 80 A0 00 FF 80 A0 00 00 A0'
+ 'A0 00 40 A0 A0 00 80 A0 A0 00 FF A0 A0 00 00 C0'
+ 'A0 00 40 C0 A0 00 80 C0 A0 00 FF C0 A0 00 00 FF'
+ 'A0 00 40 FF A0 00 80 FF A0 00 FF FF A0 00 00 00'
+ 'C0 00 40 00 C0 00 80 00 C0 00 FF 00 C0 00 00 20'
+ 'C0 00 40 20 C0 00 80 20 C0 00 FF 20 C0 00 00 40'
+ 'C0 00 40 40 C0 00 80 40 C0 00 FF 40 C0 00 00 60'
+ 'C0 00 40 60 C0 00 80 60 C0 00 FF 60 C0 00 00 80'
+ 'C0 00 40 80 C0 00 80 80 C0 00 FF 80 C0 00 00 A0'
+ 'C0 00 40 A0 C0 00 80 A0 C0 00 FF A0 C0 00 00 C0'
+ 'C0 00 40 C0 C0 00 80 C0 C0 00 FF C0 C0 00 00 FF'
+ 'C0 00 40 FF C0 00 80 FF C0 00 FF FF C0 00 00 00'
+ 'FF 00 40 00 FF 00 80 00 FF 00 FF 00 FF 00 00 20'
+ 'FF 00 40 20 FF 00 80 20 FF 00 FF 20 FF 00 00 40'
+ 'FF 00 40 40 FF 00 80 40 FF 00 FF 40 FF 00 00 60'
+ 'FF 00 40 60 FF 00 80 60 FF 00 FF 60 FF 00 00 80'
+ 'FF 00 40 80 FF 00 80 80 FF 00 FF 80 FF 00 00 A0'
+ 'FF 00 40 A0 FF 00 80 A0 FF 00 FF A0 FF 00 00 C0'
+ 'FF 00 40 C0 FF 00 80 C0 FF 00 FF C0 FF 00 00 FF'
+ 'FF 00 40 FF FF 00 80 FF FF 00 FF FF FF 00 FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF B6 24 FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF 6D 24 FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF B6 00 B6 FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF 92 00 FF FF 24 FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF 24 FF FF FF FF 92 FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF 24 FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF 92 FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF 6D FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF B6 FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF 6D FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF 92 FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF 6D FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF 6D FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF 24 FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 24'
+ 'FF B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 24'
+ '80 81 60 6C FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF 24 81'
+ 'C1 81 80 81 20 FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF C0 C1'
+ '80 80 C1 81 C1 20 FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF 81 81'
+ '81 80 81 80 80 80 24 FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF 6D 80 81'
+ '81 80 81 C1 C0 80 80 92 FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF B6 FF FF'
+ 'FF FF FF 81 C0 80 80 20 FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF 92 FF FF'
+ 'FF FF FF FF C5 C0 80 81 6D FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FB 81 81 24 FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 FF'
+ 'FF FF FF FF FF FF FF FF 24 FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF 6D FF'
+ 'FF FF FF FF FF FF FF FF 6D FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92'
+ 'FF FF FF FF FF FF FF 24 24 FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ '92 FF FF FF FF 24 6D FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ '92 FF FF 00 92 FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
+ 'FF 24 B6 FF FF FF FF FF FF FF FF FF FF FF 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+}
+
+