home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD 45 / SuperCD45.iso / talleres / vayuda / helpscrn / script / SCRIPT.C < prev    next >
C/C++ Source or Header  |  2000-01-20  |  60KB  |  1,591 lines

  1. /****************************************************************************
  2.  
  3.   This offer void where prohibited, batteries not included, this product is sold as is
  4. without warranty either express or implied, no claims of merchantabilty have been made
  5. with regard to this product, end user assumes all liability with regard to the use of
  6. this product and no claims of injury, either fiduciary or personal, may be issued against
  7. the manufacturer.  Use at your own risk, caveat emptor.  The programmer has been certified
  8. virus free.
  9.  
  10.   This software is hereby released to the public domain; you break it, you fix it.  Bug fixes,
  11. patches and feature recommendations gladly accepted (responses tempered to the attitude
  12. of the corespondent).  Send intelligent discourse to grumble@compuserve.com, drivel to /dev/null.
  13.  
  14.  
  15.     PROGRAM: script.c
  16.  
  17.     PURPOSE: Windows program control
  18.  
  19.     FUNCTIONS:
  20.  
  21.     WinMain() - calls initialization function, processes message loop
  22.     InitApplication() - initializes window data and registers window
  23.     InitInstance() - saves instance handle and creates main window
  24.     MainWndProc() - processes messages
  25.  
  26.     HISTORY:
  27.     1.0     Initial release                         12/17/97
  28.     1.1     Added command struct                    01/08/98
  29.     1.2     Fixed small memory leak when            01/15/98
  30.             last line doesn't end with CR
  31.             Changed onexist to use FindFirstFile
  32.     1.3     Added wildcard matches to the           01/19/98
  33.             while, send, and wait functions
  34.             Fixed control character translation
  35.             Added .script file extension
  36.             Added additional error checking
  37.             Fixed wait bug related to uninitialize
  38.             waitcount
  39.             Fixed string compare bug
  40.             Fixed file size > 1024 bug
  41.     2.0     Structural rewrite                      01/29/98
  42.             Create malloc'd structures containing
  43.             functions and command strings.  Create
  44.             malloc'd structure containing labels and
  45.             pointers.
  46.             Use SW_SHOWMINNOACTIVE to start
  47.             minimized windows so they don't
  48.             interfere with open windows
  49.             Save and restore top window
  50.             Save and restore caps lock mode
  51.     2.1     Added shift function to special chars   04/15/98
  52.             Added return code to msgbox
  53.             Added start directory to start command
  54.             Fixed kbd arrow direction screwup
  55.             Added escaped space (for leading blanks)
  56.     2.1.1    Fixed arg count for start and while        06/03/98
  57.     2.1.2    Added norm to start options                8/18/98
  58.             Added activate command
  59.             Added escape to list of characters
  60.             Changed return to VK_RETURN
  61.             Added space to list of characters
  62.     2.1.3    Added home,end,pageup, pagedown            9/9/98
  63.             Reduced timer to .1 sec increments
  64.     2.1.4    Fixed string compare routine to            10/8/98
  65.             allow a match if the second string
  66.             terminates in * wildcard.
  67.     2.1.5    Changed memory allocation to Windows    2/24/99
  68.             functions GlobalAlloc, GlobalLock
  69.     2.1.6    Added delete character                    3/22/99
  70.     2.1.7    Added file create/delete and variables    12/7/99
  71.     2.1.8    Fixed while bug with waitcount            01/20/00
  72.             thanks to Maurice van der Pot <griffn26@yahoo.com>
  73. ****************************************************************************/
  74.  
  75. #include <stdio.h>
  76. #include <dos.h>
  77. #include <ctype.h>
  78. #include <string.h>
  79. #include <windows.h>
  80. #include <windowsx.h>
  81. #include <time.h>
  82. #include <conio.h>
  83. #include <errno.h>
  84. #include "script.h"
  85.  
  86. HANDLE hInst;
  87. MSG msg;
  88. HWND hWnd;
  89. UCHAR szAppName[20], szClassName[20];
  90. UCHAR cmdbuf[_MAX_PATH + _MAX_FNAME + _MAX_EXT];
  91. UCHAR errbuf[160];
  92.  
  93. struct cl {
  94.     char command[10];
  95.     int nargs;
  96.     int function;
  97.     int attr;
  98. } cl[] = {
  99.     { "send", NARG2, IDM_SEND, TRUE },
  100.     { "goto", NARG1, IDM_GOTO, FALSE },
  101.     { "wait", NARG1 | NARG2, IDM_WAIT, FALSE },
  102.     { "while", NARG1 | NARG2, IDM_WHILE, FALSE },
  103.     { "start", NARG1 | NARG2 | NARG3, IDM_START, FALSE },
  104.     { "msgbox", NARG1 | NARG2, IDM_MSGBOX, FALSE },
  105.     { "delay", NARG1, IDM_DELAY, FALSE },
  106.     { "onerror", NARG1, IDM_ONERR, FALSE },
  107.     { "onexist", NARG2, IDM_EXIST, FALSE },
  108.     { "onmsgrtn", NARG2, IDM_ONMSG, FALSE },
  109.     { "activate", NARG1, IDM_ACTIVATE, FALSE },
  110.     { "set", NARG2, IDM_SETVAR, FALSE },
  111.     { "dec", NARG1, IDM_DECVAR, FALSE },
  112.     { "onzero", NARG2, IDM_VARZERO, FALSE },
  113.     { "create", NARG1, IDM_CREATE, FALSE },
  114.     { "delete", NARG1, IDM_DELETE, FALSE },
  115.     { "", 0, 0 }
  116. };
  117.  
  118. CMD *cmdstart;
  119. LABEL *labelstart;
  120. VAR *varstart;
  121.  
  122. #define BLOCKSIZE 1024
  123.  
  124. /*
  125. *       This routine does a string compare of s1 to s
  126. *       it differs from the standard library lookup
  127. *       in that it supports wildcard characters (?, *)
  128. *       and it returns a boolean result, not a magnitude.
  129. *       ? is a single character wildcard and will match
  130. *       any character in the same position.
  131. *       * is a 0-n character wildcard
  132. */
  133. BOOL gstrscn(unsigned char *s, unsigned char *s1, WORD *s2, int first)
  134. {
  135.  
  136.     while (*s && (*s1 != 0xff || *s1))
  137.     {
  138.         if (*s1 == MUWC && *s2 == KSPECIAL)
  139.         {
  140.             s1++;
  141.             s2++;
  142.             if (*s1)
  143.                 return gstrscn(s, s1, s2, TRUE);
  144.             else
  145.                 return TRUE;
  146.         }
  147.         else
  148.             if (first)
  149.             {
  150.                 if (*s == *s1 || (*s1 == SIWC && *s2 == KSPECIAL))
  151.                 {
  152.                     first = FALSE;
  153.                     s1++;
  154.                     s2++;
  155.                 }
  156.             }
  157.             else
  158.                 if (*s != *s1 && (*s1 != SIWC && *s2 != KSPECIAL))
  159.                     return FALSE;
  160.                 else
  161.                 {
  162.                     s1++;
  163.                     s2++;
  164.                 }
  165.         s++;
  166.     }
  167.     if (!*s && *s1 == MUWC && *s2 == KSPECIAL)
  168.         return TRUE;
  169.     if (*s || (*s1 != 0xff && *s1))
  170.         return FALSE;
  171.     return TRUE;
  172. }
  173.  
  174. /*
  175. *   Routine to convert hex character to int
  176. */
  177. int HexToInt(char i)
  178. {
  179.     i -= '0';
  180.     if (i > 0x30)
  181.         i -= 0x27;
  182.     else
  183.         if (i > 0x10)
  184.             i -= 0x7;
  185.     return (int)(i);
  186. }
  187.  
  188. /****************************************************************************
  189.  
  190.     FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  191.  
  192.     PURPOSE: calls initialization function, processes message loop
  193.  
  194. ****************************************************************************/
  195.  
  196. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdline, int nCmdShow)
  197. {
  198.     WIN32_FIND_DATA wf;
  199.     HANDLE fh;
  200.  
  201.     lstrcpy(szAppName, "Script");
  202.     lstrcpy(szClassName, "ScriptClass");
  203.     strcpy(cmdbuf, cmdline);
  204.     if (strstr(cmdbuf, ".") == NULL)                                // no extension supplied, try it as .scr first
  205.         strcat(cmdbuf, ".scr");
  206.     if ((fh = FindFirstFile(cmdbuf, &wf)) == INVALID_HANDLE_VALUE)
  207.     {
  208.         strcat(cmdbuf, "ipt");                                      // not found, try it as .script
  209.         if ((fh = FindFirstFile(cmdbuf, &wf)) == INVALID_HANDLE_VALUE)
  210.             strcpy(cmdbuf, cmdline);                                // not found, no extension
  211.     }
  212.     if (fh != INVALID_HANDLE_VALUE)
  213.         FindClose(fh);
  214.  
  215.     if (!InitApplication(hInstance))
  216.         return (FALSE);
  217.  
  218.     varstart = NULL;
  219.  
  220.     if ((fh = OpenScriptFile(cmdbuf)) == NULL)
  221.         return (FALSE);
  222.  
  223.     if (!FileProc(fh))
  224.     {
  225.         FreeCMD(cmdstart);
  226.         FreeLabel(labelstart);
  227.         FreeVar(varstart);
  228.         CloseHandle(fh);
  229.         return (FALSE);
  230.     }
  231.     CloseHandle(fh);
  232.  
  233.     if (!InitInstance(hInstance, nCmdShow))
  234.         return (FALSE);
  235.  
  236.     SetTimer(hWnd, 1, 100, NULL);        // set timer to .1 seconds
  237.  
  238.     while (GetMessage(&msg, 0, 0, 0))
  239.     {
  240.         TranslateMessage(&msg);
  241.         DispatchMessage(&msg);
  242.     }
  243.     return (msg.wParam);
  244. }
  245.  
  246.  
  247. /****************************************************************************
  248.  
  249.     FUNCTION: InitApplication(HANDLE)
  250.  
  251.     PURPOSE: Initializes window data and registers window class
  252.  
  253. ****************************************************************************/
  254.  
  255. BOOL InitApplication(hInstance)
  256. HANDLE hInstance;
  257. {
  258.     WNDCLASS  wc;
  259.     HBRUSH hbr;
  260.  
  261.     hbr = CreateSolidBrush(RGB(192, 192, 192));
  262.     wc.style = CS_HREDRAW | CS_VREDRAW;
  263.     wc.lpfnWndProc = MainWndProc;
  264.     wc.cbClsExtra = 0;
  265.     wc.cbWndExtra = 0;
  266.     wc.hInstance = hInstance;
  267.     wc.hIcon = NULL;
  268.     wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
  269.     wc.hbrBackground = hbr;
  270.     wc.lpszMenuName = NULL;
  271.     wc.lpszClassName = szClassName;
  272.  
  273.     return (RegisterClass(&wc));
  274. }
  275.  
  276.  
  277. /****************************************************************************
  278.  
  279.     FUNCTION:  InitInstance(HANDLE, int)
  280.  
  281.     PURPOSE:  Saves instance handle and creates main window
  282.  
  283. ****************************************************************************/
  284.  
  285. BOOL InitInstance(HANDLE hInstance, int nCmdShow)
  286. {
  287.     HDC hDC;
  288.  
  289.     hInst = hInstance;
  290.  
  291.     hWnd = CreateWindow(
  292.                         szClassName,
  293.                         szAppName,
  294.                         WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZE,
  295.                         0,
  296.                         0,
  297.                         0,
  298.                         0,
  299.                         HWND_DESKTOP,
  300.                         0,
  301.                         hInstance,
  302.                         NULL
  303.                        );
  304.  
  305.     if (!hWnd)
  306.         return (FALSE);
  307.  
  308.     hDC = GetDC(hWnd);
  309.     if (!hDC)
  310.         return (FALSE);
  311.  
  312.     ReleaseDC(hWnd,hDC);
  313.     return (TRUE);
  314.  
  315. }
  316.  
  317. /****************************************************************************
  318.  
  319.     FUNCTION:  OpenScriptFile(char *filename)
  320.  
  321.     PURPOSE:  Reads file into buffer
  322.  
  323. ****************************************************************************/
  324. HANDLE OpenScriptFile(char *filename)
  325. {
  326.     OPENFILENAME ofn;
  327.     HANDLE fh;
  328.  
  329.     if (!strlen(filename))
  330.     {
  331.         ofn.lStructSize = sizeof(OPENFILENAME);
  332.         ofn.hwndOwner = hWnd;
  333.         ofn.hInstance = NULL;
  334.         ofn.lpstrCustomFilter = NULL;
  335.         ofn.nMaxCustFilter = 0;
  336.         ofn.lpstrFilter = "Script files\0*.scr\0*.script\0";
  337.         ofn.nFilterIndex = 1;
  338.         ofn.lpstrFile = (LPSTR)filename;
  339.         ofn.nMaxFile = _MAX_PATH + _MAX_FNAME + _MAX_EXT;
  340.         ofn.lpstrFileTitle = NULL;
  341.         ofn.nMaxFileTitle = 0;
  342.         ofn.lpstrTitle = NULL;
  343.         ofn.lpstrInitialDir = NULL;
  344.         ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT;
  345.         ofn.nFileOffset = 0;
  346.         ofn.nFileExtension = 0;
  347.         ofn.lCustData = 0L;
  348.         ofn.lpfnHook = NULL;
  349.         ofn.lpTemplateName = NULL;
  350.         ofn.lpstrDefExt = "scr";
  351.         if (!GetOpenFileName((OPENFILENAME FAR *)&ofn))
  352.             return NULL;
  353.     }
  354.     if ((fh = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 
  355.                          FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
  356.     {
  357.          sprintf(errbuf, "Unable to open %s for input", cmdbuf);
  358.          MessageBox(hWnd, errbuf, "File error", MB_ICONSTOP | MB_SYSTEMMODAL);
  359.          return NULL;
  360.     }
  361.     return fh;
  362.  
  363. }
  364.  
  365. /****************************************************************************
  366.  
  367.     FUNCTION:  ReadBlock(HANDLE FileHandle, unsigned char *buf)
  368.  
  369.     PURPOSE:  Reads file into buffer
  370.  
  371. ****************************************************************************/
  372. int ReadBlock(HANDLE fh, unsigned char *buf, DWORD *rc)
  373. {
  374.     if (!ReadFile(fh, buf, BLOCKSIZE, rc, NULL))
  375.     {
  376.         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
  377.                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  378.                       errbuf, sizeof(errbuf), NULL);
  379.         MessageBox(hWnd, errbuf, "Read Error", MB_OK | MB_SYSTEMMODAL);
  380.         return (FALSE);
  381.     }
  382.     if (!*rc)
  383.         CloseHandle(fh);
  384.     return TRUE;
  385. }
  386.  
  387. /****************************************************************************
  388.  
  389.     FUNCTION:  FileProc(HANDLE fh)
  390.  
  391.     PURPOSE:  Reads file into buffer and processes contents
  392.  
  393. ****************************************************************************/
  394.  
  395. BOOL FileProc(HANDLE fh)
  396. {
  397.     UCHAR seqchar;
  398.     int comma = 0;
  399.     int brseq;
  400.     DWORD rc;
  401.     unsigned char *p;
  402.     int badesc;
  403.     int badfunc;
  404.     UCHAR buf[BLOCKSIZE];
  405.     UCHAR cbuf[256];
  406.     UCHAR *cmd;
  407.     WORD attrbuf[256];
  408.     UCHAR *cmdptr;
  409.     WORD *atrptr;
  410.     int atrflag;
  411.     int func;
  412.     int i;
  413.     UCHAR *s;
  414.     LABEL *curlabel, *tmplabel;
  415.     CMD *curcmd, *tmpcmd;
  416.     int firstlabel = TRUE;
  417.     int firstcmd = TRUE;
  418.     int newlabel = FALSE;
  419.     int curmessage;
  420.     HGLOBAL mAlloc;
  421.  
  422.     cmdptr = cbuf;
  423.     atrflag = FALSE;
  424.     atrptr = attrbuf;
  425.     *atrptr = 0;
  426.     brseq = 0;
  427.     badesc = FALSE;
  428.     badfunc = FALSE;
  429.     curcmd = cmdstart;
  430.     curlabel = labelstart;
  431.     if (!ReadBlock(fh, buf, &rc))
  432.         return (FALSE);
  433.     p = buf;
  434.     for (;;)
  435.     {
  436.         if ((p - buf) == sizeof(buf))
  437.         {
  438.             if (!ReadBlock(fh, buf, &rc))
  439.                 return (FALSE);
  440.             p = buf;
  441.             atrflag = FALSE;
  442.         }
  443.  
  444.         if ((DWORD)(p - buf) >= rc)                    // end of file (I think)
  445.             return (TRUE);
  446.  
  447.         while (*p != 0xd && *p != 0xa && ((DWORD)(p - buf) < rc))
  448.         {
  449.             if (!brseq && (*p == '\\' || *p == '$' || *p == '#'))    // handle multiple sequences
  450.             {
  451.                 seqchar = *p;
  452.                 p++;
  453.                 if (seqchar == '$' || seqchar == '#')
  454.                      brseq = 2;
  455.                 else
  456.                      brseq = 1;
  457.             }
  458.             else
  459.             {
  460.                 if (brseq)
  461.                 {
  462.                     brseq--;
  463.                     switch (seqchar) {
  464.  
  465.                         case '\\':
  466.                             switch (*p) {
  467.  
  468.                                 case 'n':
  469.                                     *(cmdptr++) = RETURN;
  470. //                                    *(cmdptr++) = 0x0d;
  471. //                                    atrptr++;
  472.                                     *(atrptr++) |= KSPECIAL;
  473.                                     *atrptr = 0;
  474. //                                    atrflag = TRUE;
  475.                                     break;
  476.  
  477.                                 case ',':
  478.                                     *(cmdptr++) = ',';
  479.                                     atrptr++;
  480.                                     *atrptr = 0;
  481.                                     break;
  482.  
  483.                                 case 't':
  484.                                     *(cmdptr++) = (UCHAR)KTAB;       // escaped tabs are special
  485.                                     *(atrptr++) |= KSPECIAL;
  486.                                     *atrptr = 0;
  487.                                     break;
  488.  
  489.                                 case '>':
  490.                                     *(cmdptr++) = (UCHAR)RTAR;       // escaped arrows are special
  491.                                     *(atrptr++) |= KSPECIAL;
  492.                                     *atrptr = 0;
  493.                                     atrflag = TRUE;
  494.                                     break;
  495.  
  496.                                 case '<':
  497.                                     *(cmdptr++) = (UCHAR)LFAR;       // escaped arrows are special
  498.                                     *(atrptr++) |= KSPECIAL;
  499.                                     *atrptr = 0;
  500.                                     atrflag = TRUE;
  501.                                     break;
  502.  
  503.                                 case '^':
  504.                                     *(cmdptr++) = (UCHAR)UPAR;       // escaped arrows are special
  505.                                     *(atrptr++) |= KSPECIAL;
  506.                                     *atrptr = 0;
  507.                                     atrflag = TRUE;
  508.                                     break;
  509.  
  510.                                 case 'v':
  511.                                     *(cmdptr++) = (UCHAR)DNAR;       // escaped arrows are special
  512.                                     *(atrptr++) |= KSPECIAL;
  513.                                     *atrptr = 0;
  514.                                     atrflag = TRUE;
  515.                                     break;
  516.  
  517.                                 case 'u':
  518.                                     *(cmdptr++) = (UCHAR)PGUP;       // escaped arrows are special
  519.                                     *(atrptr++) |= KSPECIAL;
  520.                                     *atrptr = 0;
  521.                                     atrflag = TRUE;
  522.                                     break;
  523.  
  524.                                 case 'd':
  525.                                     *(cmdptr++) = (UCHAR)PGDN;       // escaped arrows are special
  526.                                     *(atrptr++) |= KSPECIAL;
  527.                                     *atrptr = 0;
  528.                                     atrflag = TRUE;
  529.                                     break;
  530.  
  531.                                 case 'h':
  532.                                     *(cmdptr++) = (UCHAR)HOME;       // escaped arrows are special
  533.                                     *(atrptr++) |= KSPECIAL;
  534.                                     *atrptr = 0;
  535.                                     atrflag = TRUE;
  536.                                     break;
  537.  
  538.                                 case 'o':
  539.                                     *(cmdptr++) = (UCHAR)LEND;       // escaped arrows are special
  540.                                     *(atrptr++) |= KSPECIAL;
  541.                                     *atrptr = 0;
  542.                                     atrflag = TRUE;
  543.                                     break;
  544.  
  545.                                 case 'e':
  546.                                     *(cmdptr++) = (UCHAR)ESCAPE;     // escaped E are special
  547.                                     *(atrptr++) |= KSPECIAL;
  548.                                     *atrptr = 0;
  549.                                     break;
  550.  
  551.                                 case 's':
  552.                                     *(cmdptr++) = (UCHAR)SPACE;      // escaped S are special
  553.                                     *(atrptr++) |= KSPECIAL;
  554.                                     *atrptr = 0;
  555.                                     break;
  556.  
  557.                                 case '\\':
  558.                                     *(cmdptr++) = '\\';             // escaped \ are special
  559.                                     atrptr++;
  560.                                     *atrptr = 0;
  561.                                     break;
  562.  
  563.                                 case '?':
  564.                                     *(cmdptr++) = '?';               // escaped ? are special
  565.                                     atrptr++;
  566.                                     *atrptr = 0;
  567.                                     break;
  568.  
  569.                                 case '*':
  570.                                     *(cmdptr++) = '*';               // escaped * are special
  571.                                     atrptr++;
  572.                                     *atrptr = 0;
  573.                                     break;
  574.  
  575.                                 case '$':
  576.                                     *(cmdptr++) = '$';               // escaped $ are special
  577.                                     atrptr++;
  578.                                     *atrptr = 0;
  579.                                     break;
  580.  
  581.                                 case '#':
  582.                                     *(cmdptr++) = '#';               // escaped # are special
  583.                                     atrptr++;
  584.                                     *atrptr = 0;
  585.                                     break;
  586.  
  587.                                 case '!':
  588.                                     *(cmdptr++) = '!';               // escaped ! are special
  589.                                     atrptr++;
  590.                                     *atrptr = 0;
  591.                                     break;
  592.  
  593.                                 case ' ':
  594.                                     *(cmdptr++) = ' ';                // escaped spaces are special
  595.                                     atrptr++;
  596.                                     *atrptr = 0;
  597.                                     break;
  598.  
  599.                                 case 'x':
  600.                                     *(cmdptr++) = KDELETE;            // escaped x are special
  601.                                     *(atrptr++) |= KSPECIAL;
  602.                                     *atrptr = 0;
  603.                                     break;
  604.  
  605.                                 default:
  606.                                     *(cmdptr++) = '\\';             // bad sequence
  607.                                     *(cmdptr++) = *p;
  608.                                     atrptr++;
  609.                                     *atrptr = 0;
  610.                                     badesc = TRUE;
  611.                             }
  612.                             break;
  613.  
  614.                         case '$':               // function keys
  615.                             if (*p >= '0' && *p <= '9')
  616.                             {
  617.                                 if (brseq)
  618.                                     func = (*p - '0') * 10;
  619.                                 else
  620.                                 {
  621.                                     func += (*p - '0');
  622.                                     *(cmdptr++) = F0 - func;
  623.                                     *(atrptr++) |= KSPECIAL;
  624.                                     *atrptr = 0;
  625.                                     atrflag = TRUE;
  626.                                 }
  627.                             }
  628.                             else
  629.                                 badfunc = TRUE;
  630.                             break;
  631.  
  632.                         case '#':                       // hex character sequences
  633.                             if ((*p >= '0' && *p <= '9') || (*p >= 'A' && *p <= 'F') || (*p >= 'a' && *p <= 'f'))
  634.                             {
  635.                                 if (brseq)
  636.                                     func = HexToInt(*p) << 4;
  637.                                 else
  638.                                 {
  639.                                     func += HexToInt(*p);
  640.                                     *(cmdptr++) = func;
  641.                                     atrptr++;
  642.                                     *atrptr = 0;
  643.                                     atrflag = TRUE;
  644.                                 }
  645.                             }
  646.                             else
  647.                                 badfunc = TRUE;
  648.                             break;
  649.                     }
  650.                 }
  651.                 else
  652.                     switch (*p) {
  653.  
  654.                         case ',':                  // convert nonescaped commas to separator characters
  655.                             *(cmdptr++) = (UCHAR)SEP;
  656.                             comma++;                    // inc comma count
  657.                             atrptr++;
  658.                             *atrptr = 0;
  659.                             break;
  660.  
  661.                         case '?':
  662.                             *(cmdptr++) = (UCHAR)SIWC;
  663.                             *atrptr |= KSPECIAL;
  664.                             atrptr++;
  665.                             *atrptr = 0;
  666.                             break;
  667.  
  668.                         case '*':
  669.                             *(cmdptr++) = (UCHAR)MUWC;
  670.                             *atrptr |= KSPECIAL;
  671.                             atrptr++;
  672.                             *atrptr = 0;
  673.                             break;
  674.  
  675.                         case '%':
  676.                             *atrptr |= KALT;
  677.                             atrflag = TRUE;
  678.                             break;
  679.  
  680.                         case '^':
  681.                             *atrptr |= KCONTROL;
  682.                             atrflag = TRUE;
  683.                             break;
  684.  
  685.                         case '!':
  686.                             *atrptr |= KSHIFT;
  687.                             atrflag = TRUE;
  688.                             break;
  689.  
  690.                         default:
  691.                             *(cmdptr++) = *p;
  692.                             atrptr++;
  693.                             *atrptr = 0;
  694.                     }
  695.                 p++;
  696.             }
  697.             if ((p - buf) == sizeof(buf))
  698.             {
  699.                 if (!ReadBlock(fh, buf, &rc))
  700.                     return (FALSE);
  701.                 p = buf;
  702.             }
  703.         }
  704.         *cmdptr = 0;
  705.         p++;
  706.         if (badfunc)
  707.         {
  708.             for (i = 0;  cbuf[i];  i++)
  709.                 if (cbuf[i] == SEP)
  710.                     cbuf[i] = ',';
  711.             sprintf(errbuf, "Invalid function key\n%s", cbuf);
  712.             MessageBox(hWnd, errbuf, "Command Error", MB_ICONSTOP | MB_SYSTEMMODAL);
  713.             return (FALSE);
  714.         }
  715.         if (badesc)                 // exit expand case
  716.         {
  717.             for (i = 0;  cbuf[i];  i++)
  718.                 if (cbuf[i] == SEP)
  719.                      cbuf[i] = ',';
  720.             sprintf(errbuf, "Invalid escape sequence\n%s", cbuf);
  721.             MessageBox(hWnd, errbuf, "Command Error", MB_ICONSTOP | MB_SYSTEMMODAL);
  722.             return (FALSE);
  723.         }
  724.  
  725.         // expand the string, figure out if a token or comment or blank
  726.         // save the string and start processing (curmessage)
  727.         // anything not recognized is assumed to be a syntax error
  728.  
  729.         if (strlen(cbuf))
  730.         {
  731.             s = cbuf;
  732.             while (*s == 0x20 || *s == 0x9)
  733.                 s++;                    // skip whitespace
  734.             if (*s != ';')              // line is a comment
  735.             {
  736.                 if (*s == ':')          // handle label
  737.                 {
  738.                     s++;
  739.                     if ((mAlloc = GlobalAlloc(GMEM_MOVEABLE, sizeof(struct label))) == NULL)
  740.                     {
  741.                         sprintf(errbuf, "Insufficient memory for allocation\n%s,%s", s, cmd);
  742.                         MessageBox(hWnd, errbuf, "Memory Error", MB_ICONSTOP | MB_SYSTEMMODAL);
  743.                         return (FALSE);
  744.                     }
  745.                     tmplabel = (LABEL *)GlobalLock(mAlloc);
  746.                     GlobalUnlock(mAlloc);
  747.                     if (firstlabel)
  748.                     {
  749.                         firstlabel = FALSE;
  750.                         labelstart = tmplabel;
  751.                     }
  752.                     else
  753.                         curlabel->next = tmplabel;
  754.                     curlabel = tmplabel;
  755.                     if ((mAlloc = GlobalAlloc(GMEM_MOVEABLE, strlen(s) + 1)) == NULL)
  756.                     {
  757.                         sprintf(errbuf, "Insufficient memory for allocation\n%s,%s", s, cmd);
  758.                         MessageBox(hWnd, errbuf, "Memory Error", MB_ICONSTOP | MB_SYSTEMMODAL);
  759.                         return (FALSE);
  760.                     }
  761.                     curlabel->labeltext = (char *)GlobalLock(mAlloc);
  762.                     strcpy(curlabel->labeltext, s);
  763.                     curlabel->next = NULL;
  764.                     curlabel->line = NULL;
  765.                     newlabel = TRUE;
  766.                     GlobalUnlock(mAlloc);
  767.                 }
  768.                 else
  769.                     if ((cmd = strstr(cbuf, "\377")) != NULL)
  770.                     {
  771.                         *(cmd++) = 0;
  772.                         while (*cmd == 0x20 || *cmd == 0x9)        // strip out whitespace
  773.                             cmd++;
  774.                         i = 0;
  775.                         curmessage = 0;
  776.                         while (strlen(cl[i].command))
  777.                         {
  778.                             if (!stricmp(s, cl[i].command))
  779.                             {
  780.                                 if (atrflag && !cl[i].attr)
  781.                                     curmessage = BADSPEC;
  782.                                 else
  783.                                     if ((1 << comma) & cl[i].nargs)
  784.                                     {
  785.                                         if ((mAlloc = GlobalAlloc(GMEM_MOVEABLE, sizeof(struct cmd))) == NULL)
  786.                                         {
  787.                                             sprintf(errbuf, "Insufficient memory for allocation\n%s,%s", s, cmd);
  788.                                             MessageBox(hWnd, errbuf, "Memory Error", MB_ICONSTOP | MB_SYSTEMMODAL);
  789.                                             return (FALSE);
  790.                                         }
  791.                                         tmpcmd = (CMD *)GlobalLock(mAlloc);
  792.                                         GlobalUnlock(mAlloc);
  793.                                         if (firstcmd)
  794.                                         {
  795.                                             firstcmd = FALSE;
  796.                                             cmdstart = tmpcmd;
  797.                                         }
  798.                                         else
  799.                                             curcmd->next = tmpcmd;
  800.                                         curcmd = tmpcmd;
  801.                                         curcmd->function = cl[i].function;
  802.                                         if ((mAlloc = GlobalAlloc(GMEM_MOVEABLE, strlen(cmd) + 1)) == NULL)
  803.                                         {
  804.                                             sprintf(errbuf, "Insufficient memory for allocation\n%s,%s", s, cmd);
  805.                                             MessageBox(hWnd, errbuf, "Memory Error", MB_ICONSTOP | MB_SYSTEMMODAL);
  806.                                             return (FALSE);
  807.                                         }
  808.                                         curcmd->cmdstring = (char *)GlobalLock(mAlloc);
  809.                                         strcpy(curcmd->cmdstring, cmd);
  810.                                         GlobalUnlock(mAlloc);
  811.                                         if ((mAlloc = GlobalAlloc(GMEM_MOVEABLE, strlen(cmd) * sizeof(WORD))) == NULL)
  812.                                         {
  813.                                             sprintf(errbuf, "Insufficient memory for allocation\n%s,%s", s, cmd);
  814.                                             MessageBox(hWnd, errbuf, "Memory Error", MB_ICONSTOP | MB_SYSTEMMODAL);
  815.                                             return (FALSE);
  816.                                         }
  817.                                         curcmd->attrbuf = (WORD *)GlobalLock(mAlloc);
  818.                                         memcpy(curcmd->attrbuf, &attrbuf[cmd - cbuf], strlen(cmd) * sizeof(WORD));
  819.                                         curcmd->next = NULL;
  820.                                         if (newlabel)
  821.                                         {
  822.                                             curlabel->line = curcmd;
  823.                                             newlabel = FALSE;
  824.                                         }
  825.                                         curmessage = GOODCMD;
  826.                                     }
  827.                                     else
  828.                                         curmessage = PARMS;
  829.                                     GlobalUnlock(mAlloc);
  830.                                     break;
  831.                             }
  832.                             i++;
  833.                         }
  834.                         if (!curmessage)
  835.                             curmessage = SYNTAX;
  836.                     }
  837.                     else
  838.                     {
  839.                         curmessage = SYNTAX;
  840.                         cmd = "";
  841.                     }
  842.                 if (curmessage < 0)
  843.                 {
  844.                     if (curmessage == BADSPEC)
  845.                         sprintf(errbuf, "Control or Alt sequence not allowed with this command\n%s,%s", s, cmd);
  846.                     if (curmessage == PARMS)
  847.                     {
  848.                         for (i = 0;  cmd[i];  i++)
  849.                             if (cmd[i] == SEP)
  850.                                 cmd[i] = ',';
  851.                         sprintf(errbuf, "Invalid number of command parameters\n%s,%s", s, cmd);
  852.                     }
  853.                     if (curmessage == SYNTAX)
  854.                         sprintf(errbuf, "Syntax error\n%s,%s", s, cmd);
  855.                     MessageBox(hWnd, errbuf, "Command Error", MB_ICONSTOP | MB_SYSTEMMODAL);
  856.                     return (FALSE);
  857.                 }
  858.             }
  859.         }
  860.         cmdptr = cbuf;
  861.         atrflag = FALSE;
  862.         atrptr = attrbuf;
  863.         *atrptr = 0;
  864.         comma = 0;
  865.     }
  866. }
  867.  
  868. /****************************************************************************
  869.  
  870.     FUNCTION:  FindLabel(char *)
  871.  
  872.     PURPOSE:  Reads file into buffer and processes contents
  873.  
  874. ****************************************************************************/
  875. CMD *FindLabel(char *label)
  876. {
  877.     LABEL *curlabel;
  878.  
  879.     curlabel = labelstart;
  880.     while (curlabel != NULL)
  881.         if (!strcmp(label, curlabel->labeltext))
  882.             return (curlabel->line);
  883.         else
  884.             curlabel = curlabel->next;
  885.     return ((CMD *)-1);
  886. }
  887.  
  888. /****************************************************************************
  889.  
  890.     FUNCTION:  FreeLabel(label *)
  891.  
  892.     PURPOSE:  Free up memory used by label structures
  893.  
  894. ****************************************************************************/
  895. void FreeLabel(LABEL *label)
  896. {
  897.     HGLOBAL mAlloc;
  898.  
  899.     if (label == NULL)
  900.         return;
  901.     FreeLabel(label->next);
  902.     mAlloc = GlobalHandle(label->labeltext);
  903.     GlobalFree(mAlloc);
  904. //    free(label->labeltext);
  905.     mAlloc = GlobalHandle(label);
  906.     GlobalFree(mAlloc);
  907. //    free(label);
  908. }
  909.  
  910. /****************************************************************************
  911.  
  912.     FUNCTION:  FreeCMD(CMD *)
  913.  
  914.     PURPOSE:  Free up memory used by command structures
  915.  
  916. ****************************************************************************/
  917. void FreeCMD(CMD *command)
  918. {
  919.     HGLOBAL mAlloc;
  920.  
  921.     if (command == NULL)
  922.         return;
  923.     FreeCMD(command->next);
  924.     mAlloc = GlobalHandle(command->cmdstring);
  925.     GlobalFree(mAlloc);
  926. //    free(command->cmdstring);
  927.     mAlloc = GlobalHandle(command->attrbuf);
  928.     GlobalFree(mAlloc);
  929. //    free(command->attrbuf);
  930.     mAlloc = GlobalHandle(command);
  931.     GlobalFree(mAlloc);
  932. //    free(command);
  933. }
  934.  
  935. /****************************************************************************
  936.  
  937.     FUNCTION:  FreeVar(VAR *)
  938.  
  939.     PURPOSE:  Free up memory used by variables
  940.  
  941. ****************************************************************************/
  942. void FreeVar(VAR *curvar)
  943. {
  944.     if (!curvar)
  945.         return;
  946.     FreeVar(curvar->next);
  947.     free(curvar->varname);
  948.     free(curvar);
  949. }
  950.  
  951. /****************************************************************************
  952.  
  953.     FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM)
  954.  
  955.     PURPOSE:  Processes messages
  956.  
  957.     MESSAGES:
  958.  
  959.     WM_COMMAND    - application menu (About dialog box)
  960.     WM_CREATE     - create window and objects
  961.     WM_PAINT      - update window, draw objects
  962.     WM_DESTROY    - destroy window
  963.  
  964.     COMMENTS:
  965.  
  966.     Handles to the objects you will use are obtained when the WM_CREATE
  967.     message is received, and deleted when the WM_DESTROY message is
  968.     received.  The actual drawing is done whenever a WM_PAINT message is
  969.     received.
  970.  
  971. ****************************************************************************/
  972.  
  973. long FAR PASCAL MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  974. {
  975.     PAINTSTRUCT     ps;
  976.     UCHAR module[128];
  977.     STARTUPINFO si;
  978.     PROCESS_INFORMATION pi;
  979.     int j, flags, ks;
  980.     UCHAR *s, *p;
  981.     WORD *s1;
  982.     HWND GlobalhWnd, tmphWnd;
  983.     HANDLE ftmp;
  984.     WIN32_FIND_DATA fdata;
  985.     UCHAR cmd[256];
  986.     time_t t;
  987.     FILE *fh;
  988.     VAR *curvar;
  989.     static delay = 0;
  990.     static int errlevel = 0;
  991.     static int mboxrtn = 0;
  992.     static int waitcount = 0;
  993.     static UCHAR labelqry[80];
  994.     static CMD *curcmd;
  995.     static CMD *nextcmd;
  996.     static int stop = FALSE;
  997.  
  998.     switch (message) {
  999.         case WM_COMMAND:
  1000.  
  1001.             switch (wParam) {
  1002.  
  1003.                 /* wait for a program to exit */
  1004.  
  1005.                 case IDM_WHILE:
  1006.                     errlevel = 0;
  1007.                     if ((s = strstr(curcmd->cmdstring, "\377")) != NULL)      // find separator character
  1008.                     {
  1009.                         if (!waitcount)
  1010.                         {
  1011.                             s++;
  1012.                             while (*s == 0x20 || *s == 0x9)
  1013.                                 s++;
  1014.                             sscanf(s, "%d", &waitcount);
  1015.                         }
  1016.                     }
  1017.                     else
  1018.                         waitcount = -1;
  1019.                     if ((GlobalhWnd = GetTopWindow(NULL)) != NULL)
  1020.                     {
  1021.                         do {
  1022.                             if (GetWindowText(GlobalhWnd, module, sizeof(module)))
  1023.                                 if (gstrscn(module, curcmd->cmdstring, curcmd->attrbuf, FALSE))
  1024.                                 {
  1025.                                     if (waitcount)
  1026.                                     {
  1027.                                         waitcount--;
  1028.                                         if (!waitcount)
  1029.                                         {
  1030.                                             errlevel = TRUE;
  1031.                                             break;
  1032.                                         }
  1033.                                         nextcmd = curcmd;       // branch back here
  1034.                                     }
  1035.                                     break;
  1036.                                 }
  1037.                         } while ((GlobalhWnd = GetNextWindow(GlobalhWnd, GW_HWNDNEXT)) != NULL);
  1038.                         waitcount = 0;                            // window not found, clear waitcount
  1039.                     }
  1040.                     break;
  1041.  
  1042.                 /* wait for specified delay (in 1/1000's of a second ) */
  1043.  
  1044.                 case IDM_DELAY:
  1045.                     if (delay == 0)
  1046.                     {
  1047.                         sscanf(curcmd->cmdstring, "%d", &delay);
  1048.                         nextcmd = curcmd;
  1049.                     }
  1050.                     else
  1051.                     {
  1052.                         delay--;
  1053.                         if (delay != 0)
  1054.                            nextcmd = curcmd;
  1055.                     }
  1056.                     break;
  1057.  
  1058.  
  1059.                 /* activate a dormant window */
  1060.  
  1061.                 case IDM_ACTIVATE:
  1062.                     if ((GlobalhWnd = GetTopWindow(NULL)) != NULL)
  1063.                         do {
  1064.                             if (GetWindowText(GlobalhWnd, module, sizeof(module)))
  1065.                                 if (gstrscn(module, curcmd->cmdstring, curcmd->attrbuf, FALSE))
  1066.                                     SetForegroundWindow(GlobalhWnd);
  1067.                         } while ((GlobalhWnd = GetNextWindow(GlobalhWnd, GW_HWNDNEXT)) != NULL);
  1068.                     break;
  1069.  
  1070.  
  1071.                 /* send keys to window */
  1072.  
  1073.                 case IDM_SEND:
  1074.                     stop = TRUE;
  1075.                     if ((s = strstr(curcmd->cmdstring, "\377")) != NULL)      // find separator character
  1076.                     {
  1077.                         s++;
  1078.                         s1 = &curcmd->attrbuf[s - curcmd->cmdstring];
  1079.                         while ((*s == 0x20 || *s == 0x9) && !*s1)
  1080.                         {
  1081.                             s++;
  1082.                             s1++;
  1083.                         }
  1084.                         if ((GlobalhWnd = GetTopWindow(NULL)) != NULL)
  1085.                             do {
  1086.                                 if (GetWindowText(GlobalhWnd, module, sizeof(module)))
  1087.                                     if (gstrscn(module, curcmd->cmdstring, curcmd->attrbuf, FALSE))
  1088.                                     {
  1089.                                         tmphWnd = GetForegroundWindow();
  1090.                                         if ((ks = GetKeyState(VK_CAPITAL)))        // toggle caps lock if on
  1091.                                         {
  1092.                                             keybd_event(VK_CAPITAL, 0, 0L, 0x10001L);
  1093.                                             keybd_event(VK_CAPITAL, 0, KEYEVENTF_KEYUP, 0xc0000001L);
  1094.                                         }
  1095.                                         while (*s)      // send keystrokes
  1096.                                         {
  1097.                                             SetForegroundWindow(GlobalhWnd);
  1098.                                             if (!(*s1 & KSPECIAL))
  1099.                                                 j = VkKeyScan(*s) | *s1;
  1100.                                             else
  1101.                                             {
  1102.                                                 switch (*s) {
  1103.                                                     case RTAR:          // right arrow
  1104.                                                         j = VK_RIGHT;
  1105.                                                         break;
  1106.  
  1107.                                                     case LFAR:          // left arrow
  1108.                                                         j = VK_LEFT;
  1109.                                                         break;
  1110.  
  1111.                                                     case UPAR:          // up arrow
  1112.                                                         j = VK_UP;
  1113.                                                         break;
  1114.  
  1115.                                                     case DNAR:          // down arrow
  1116.                                                         j = VK_DOWN;
  1117.                                                         break;
  1118.  
  1119.                                                     case KTAB:
  1120.                                                         j = VkKeyScan(0x9);
  1121.                                                         break;
  1122.  
  1123.                                                     case F1:
  1124.                                                         j = VK_F1;
  1125.                                                         break;
  1126.  
  1127.                                                     case F2:
  1128.                                                         j = VK_F2;
  1129.                                                         break;
  1130.  
  1131.                                                     case F3:
  1132.                                                         j = VK_F3;
  1133.                                                         break;
  1134.  
  1135.                                                     case F4:
  1136.                                                         j = VK_F4;
  1137.                                                         break;
  1138.  
  1139.                                                     case F5:
  1140.                                                         j = VK_F5;
  1141.                                                         break;
  1142.  
  1143.                                                     case F6:
  1144.                                                         j = VK_F6;
  1145.                                                         break;
  1146.  
  1147.                                                     case F7:
  1148.                                                         j = VK_F7;
  1149.                                                         break;
  1150.  
  1151.                                                     case F8:
  1152.                                                         j = VK_F8;
  1153.                                                         break;
  1154.  
  1155.                                                     case F9:
  1156.                                                         j = VK_F9;
  1157.                                                         break;
  1158.  
  1159.                                                     case F10:
  1160.                                                         j = VK_F10;
  1161.                                                         break;
  1162.  
  1163.                                                     case F11:
  1164.                                                         j = VK_F11;
  1165.                                                         break;
  1166.  
  1167.                                                     case F12:
  1168.                                                         j = VK_F12;
  1169.                                                         break;
  1170.  
  1171.                                                     case ESCAPE:
  1172.                                                         j = VK_ESCAPE;
  1173.                                                         break;
  1174.  
  1175.                                                     case RETURN:
  1176.                                                         j = VK_RETURN;
  1177.                                                         break;
  1178.  
  1179.                                                     case SPACE:
  1180.                                                         j = VK_SPACE;
  1181.                                                         break;
  1182.  
  1183.                                                     case PGDN:
  1184.                                                         j = VK_NEXT;
  1185.                                                         break;
  1186.  
  1187.                                                     case PGUP:
  1188.                                                         j = VK_PRIOR;
  1189.                                                         break;
  1190.  
  1191.                                                     case HOME:
  1192.                                                         j = VK_HOME;
  1193.                                                         break;
  1194.  
  1195.                                                     case LEND:
  1196.                                                         j = VK_END;
  1197.                                                         break;
  1198.  
  1199.                                                     case KDELETE:
  1200.                                                         j = VK_DELETE;
  1201.                                                         break;
  1202.  
  1203.                                                 }
  1204.                                                 j |= *s1;
  1205.                                             }
  1206.                                             if (j & KALT)
  1207.                                                 keybd_event(VK_MENU, 0, 0L, 0x10001L);
  1208.                                             if (j & KCONTROL)
  1209.                                                 keybd_event(VK_CONTROL, 0, 0L, 1L);
  1210.                                             if (j & KSHIFT)
  1211.                                                 keybd_event(VK_SHIFT, 0, 0L, 1L);
  1212.                                             keybd_event((char)(j & 0xff), 0, 0L, 1L);
  1213.                                             keybd_event((char)(j & 0xff), 0, KEYEVENTF_KEYUP, 0xc0000001L);
  1214.                                             if (j & KSHIFT)
  1215.                                                 keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0xc0000001L);
  1216.                                             if (j & KCONTROL)
  1217.                                                 keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0xc0000001L);
  1218.                                             if (j & KALT)
  1219.                                                 keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0xc0000001L);
  1220.                                             s++;
  1221.                                             s1++;
  1222.                                         }
  1223.                                         SetForegroundWindow(tmphWnd);
  1224.                                         if (ks)        // toggle caps lock if on
  1225.                                         {
  1226.                                             keybd_event(VK_CAPITAL, 0, 0L, 0x10001L);
  1227.                                             keybd_event(VK_CAPITAL, 0, KEYEVENTF_KEYUP, 0xc0000001L);
  1228.                                         }
  1229.                                         break;
  1230.                                     }
  1231.                             } while ((GlobalhWnd = GetNextWindow(GlobalhWnd, GW_HWNDNEXT)) != NULL);
  1232.                     }
  1233.                     else
  1234.                     {
  1235.                         stop = TRUE;
  1236.                         sprintf(errbuf, "Send error: Missing text in line");
  1237.                         MessageBox(hWnd, errbuf, "Command Error", MB_ICONSTOP | MB_SYSTEMMODAL);
  1238.                         PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L);
  1239.                     }
  1240.                     stop = FALSE;
  1241.                     break;
  1242.  
  1243.  
  1244.                 /* start program in file after start token */
  1245.  
  1246.                 case IDM_START:
  1247.                     strcpy(cmd, curcmd->cmdstring);
  1248.                     p = NULL;
  1249.                     si.wShowWindow = SW_SHOWNORMAL;
  1250.                     if ((s = strstr(cmd, "\377")) != NULL)
  1251.                     {
  1252.                         *(s++) = 0;
  1253.                         if ((p = strstr(s, "\377")) != NULL)        // check for startup directory
  1254.                             *(p++) = 0;
  1255.                         if (!stricmp(s, "min"))
  1256. //                            si.wShowWindow = SW_SHOWMINIMIZED;
  1257.                             si.wShowWindow = SW_SHOWMINNOACTIVE;
  1258.                         else
  1259.                             if (!stricmp(s, "max"))
  1260.                                 si.wShowWindow = SW_SHOWMAXIMIZED;
  1261.                             else
  1262.                                 if (stricmp(s, "norm"))
  1263.                                 {
  1264.                                     stop = TRUE;
  1265.                                     sprintf(errbuf, "Syntax error\nstart,%s,%s", cmd, s);
  1266.                                     MessageBox(hWnd, errbuf, "Command Error", MB_ICONSTOP | MB_SYSTEMMODAL);
  1267.                                     PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L);
  1268.                                     break;
  1269.                                 }
  1270.                     }
  1271.                     si.cb = sizeof(STARTUPINFO);
  1272.                     si.lpReserved = NULL;
  1273.                     si.lpDesktop = NULL;
  1274.                     si.lpTitle = NULL;
  1275.                     si.dwFlags = STARTF_USESHOWWINDOW;
  1276.                     si.cbReserved2 = 0;
  1277.                     si.lpReserved2 = NULL;
  1278.                     errlevel = 0;
  1279.                     if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, p, &si, &pi))
  1280.                         errlevel = GetLastError();
  1281.                     break;
  1282.  
  1283.                 /* wait for a window with the appropriate text to appear */
  1284.  
  1285.                 case IDM_WAIT:
  1286.                     errlevel = 0;
  1287.                     if ((s = strstr(curcmd->cmdstring, "\377")) != NULL)      // find separator character
  1288.                     {
  1289.                         if (!waitcount)
  1290.                         {
  1291.                             s++;
  1292.                             while (*s == 0x20 || *s == 0x9)
  1293.                                 s++;
  1294.                             sscanf(s, "%d", &waitcount);
  1295.                         }
  1296.                     }
  1297.                     else
  1298.                         waitcount = -1;
  1299.                     if ((GlobalhWnd = GetTopWindow(NULL)) != NULL)
  1300.                         do {
  1301.                             if (GetWindowText(GlobalhWnd, module, sizeof(module)))
  1302.                                 if (gstrscn(module, curcmd->cmdstring, curcmd->attrbuf, FALSE))
  1303.                                 {
  1304.                                     waitcount = 0;
  1305.                                     break;
  1306.                                 }
  1307.                         } while ((GlobalhWnd = GetNextWindow(GlobalhWnd, GW_HWNDNEXT)) != NULL);
  1308.                     if (waitcount)
  1309.                     {
  1310.                         waitcount--;
  1311.                         if (!waitcount)
  1312.                         {
  1313.                             errlevel = TRUE;
  1314.                             break;
  1315.                         }
  1316.                         nextcmd = curcmd;       // branch back here
  1317.                     }
  1318.                     break;
  1319.  
  1320.                 /* check for file existence, branch if true */
  1321.  
  1322.                 case IDM_EXIST:
  1323.                     strcpy(cmd, curcmd->cmdstring);
  1324.                     s = strstr(cmd, "\377");
  1325.                     *(s++) = 0;
  1326.                     if ((ftmp = FindFirstFile(cmd, &fdata)) == INVALID_HANDLE_VALUE)
  1327.                         break;
  1328.                     FindClose(ftmp);
  1329.                     if ((nextcmd = FindLabel(s)) == (CMD *)-1)
  1330.                     {
  1331.                         stop = TRUE;
  1332.                         sprintf(errbuf, "Label \"%s\" not found", s);
  1333.                         MessageBox(hWnd, errbuf, "Command Error", MB_OK | MB_SYSTEMMODAL);
  1334.                         PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L);
  1335.                     }
  1336.                     break;
  1337.  
  1338.                 case IDM_CREATE:
  1339.                     if ((fh = fopen(curcmd->cmdstring, "w")) == NULL)
  1340.                     {
  1341.                         stop = TRUE;
  1342.                         sprintf(errbuf, "Unable to create file \"%s\"", curcmd->cmdstring);
  1343.                         MessageBox(hWnd, errbuf, "Command Error", MB_OK | MB_SYSTEMMODAL);
  1344.                         PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L);
  1345.                     }
  1346.                     time(&t);
  1347.                     fprintf(fh, "%s", asctime(localtime(&t)));
  1348.                     fclose(fh);
  1349.                     break;
  1350.                     
  1351.                 case IDM_DELETE:
  1352.                     unlink(curcmd->cmdstring);
  1353.                     break;
  1354.  
  1355.                 /* branch on the msgbox return value */
  1356.  
  1357.                 case IDM_ONMSG:
  1358.                     strcpy(cmd, curcmd->cmdstring);
  1359.                     s = strstr(cmd, "\377");
  1360.                     *(s++) = 0;
  1361.                     if (!stricmp(cmd, "ABORT"))
  1362.                     {
  1363.                         if (mboxrtn != IDABORT)
  1364.                             break;
  1365.                     }
  1366.                     else
  1367.                         if (!stricmp(cmd, "CANCEL"))
  1368.                         {
  1369.                             if (mboxrtn != IDCANCEL)
  1370.                                 break;
  1371.                         }
  1372.                         else
  1373.                             if (!stricmp(cmd, "IGNORE"))
  1374.                             {
  1375.                                 if (mboxrtn != IDIGNORE)
  1376.                                     break;
  1377.                             }
  1378.                             else
  1379.                                 if (!stricmp(cmd, "NO"))
  1380.                                 {
  1381.                                     if (mboxrtn != IDNO)
  1382.                                         break;
  1383.                                 }
  1384.                                 else
  1385.                                     if (!stricmp(cmd, "OK"))
  1386.                                     {
  1387.                                         if (mboxrtn != IDOK)
  1388.                                             break;
  1389.                                     }
  1390.                                     else
  1391.                                         if (!stricmp(cmd, "RETRY"))
  1392.                                         {
  1393.                                             if (mboxrtn != IDRETRY)
  1394.                                                 break;
  1395.                                         }
  1396.                                         else
  1397.                                             if (!stricmp(cmd, "YES"))
  1398.                                             {
  1399.                                                 if (mboxrtn != IDYES)
  1400.                                                     break;
  1401.                                             }
  1402.                                             else
  1403.                                             {
  1404.                                                 stop = TRUE;
  1405.                                                 sprintf(errbuf, "Syntax error\nonmsgrtn,%s,%s", cmd, s);
  1406.                                                 MessageBox(hWnd, errbuf, "Command Error", MB_ICONSTOP | MB_SYSTEMMODAL);
  1407.                                                 PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L);
  1408.                                                 break;
  1409.                                             }
  1410.                     if ((nextcmd = FindLabel(s)) == (CMD *)-1)
  1411.                     {
  1412.                         stop = TRUE;
  1413.                         sprintf(errbuf, "Label \"%s\" not found", s);
  1414.                         MessageBox(hWnd, errbuf, "Command Error", MB_OK | MB_SYSTEMMODAL);
  1415.                         PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L);
  1416.                     }
  1417.                     break;
  1418.  
  1419.                 /* onerror processing, if errlevel is false skip, else find label */
  1420.  
  1421.                 case IDM_ONERR:
  1422.                     if (!errlevel)
  1423.                         break;
  1424.  
  1425.                 /* goto processing, branch to label */
  1426.  
  1427.                 case IDM_GOTO:
  1428.                     if ((nextcmd = FindLabel(curcmd->cmdstring)) == (CMD *)-1)
  1429.                     {
  1430.                         stop = TRUE;
  1431.                         MessageBox(hWnd, "Label not found", "Command Error", MB_OK | MB_SYSTEMMODAL);
  1432.                         PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L);
  1433.                     }
  1434.                     break;
  1435.  
  1436.                 /* generate a message box containing the given text */
  1437.  
  1438.                 case IDM_MSGBOX:
  1439.                     stop = TRUE;
  1440.                     strcpy(cmd, curcmd->cmdstring);
  1441.                     if ((s = strstr(cmd, "\377")) != NULL)
  1442.                     {
  1443.                         *(s++) = 0;
  1444.                         sscanf(s, "%d", &flags);
  1445.                     }
  1446.                     else
  1447.                         flags = MB_OK | MB_SYSTEMMODAL;
  1448.                     if (!strcmp(cmd, "$syserr"))
  1449.                     {
  1450.                         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errlevel,
  1451.                                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  1452.                                       errbuf, sizeof(errbuf), NULL);
  1453.                         mboxrtn = MessageBox(hWnd, errbuf, "Error", MB_OK | MB_SYSTEMMODAL);
  1454.                     }
  1455.                     else
  1456.                         mboxrtn = MessageBox(hWnd, cmd, "Script message", flags);
  1457.                     stop = FALSE;
  1458.                     break;
  1459.  
  1460.  
  1461.                 // initialize a variable, create it if it doesn't exist
  1462.  
  1463.                 case IDM_SETVAR:
  1464.                     strcpy(cmd, curcmd->cmdstring);
  1465.                     s = strstr(cmd, "\377");
  1466.                     *(s++) = 0;
  1467.                     if (!varstart)  // no variables have been defined, create it
  1468.                     {
  1469.                         varstart = (VAR *)malloc(sizeof(struct var));
  1470.                         varstart->next = NULL;
  1471.                         varstart->varname = (char *)malloc(strlen(cmd) + 1);
  1472.                         strcpy(varstart->varname, cmd);
  1473.                         sscanf(s, "%d", &varstart->rhs);
  1474.                     }
  1475.                     else            // first search existing variable list
  1476.                     {
  1477.                         curvar = varstart;
  1478.                         while (curvar)
  1479.                         {
  1480.                             if (!stricmp(cmd, curvar->varname))
  1481.                                 break;
  1482.                             curvar = curvar->next;
  1483.                         }
  1484.                         if (curvar)            // var was found
  1485.                             sscanf(s, "%d", &curvar->rhs);
  1486.                         else
  1487.                         {
  1488.                             // malloc space for new curvar, then copy data
  1489.                             curvar = (VAR *)malloc(sizeof(struct var));
  1490.                             curvar->next = NULL;
  1491.                             curvar->varname = (char *)malloc(strlen(cmd) + 1);
  1492.                             strcpy(curvar->varname, cmd);
  1493.                             sscanf(s, "%d", &curvar->rhs);
  1494.                         }
  1495.                     }
  1496.                     break;
  1497.  
  1498.                 // decrement a variable, error if it doesn't exist
  1499.  
  1500.                 case IDM_DECVAR:
  1501.                     curvar = varstart;
  1502.                     while (curvar)
  1503.                     {
  1504.                         if (!stricmp(curcmd->cmdstring, curvar->varname))
  1505.                             break;
  1506.                         curvar = curvar->next;
  1507.                     }
  1508.                     if (!curvar)
  1509.                     {
  1510.                         stop = TRUE;
  1511.                         sprintf(errbuf, "Variable \"%s\" not found", curcmd->cmdstring);
  1512.                         MessageBox(hWnd, errbuf, "Command Error", MB_OK | MB_SYSTEMMODAL);
  1513.                         PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L);
  1514.                     }
  1515.                     else
  1516.                         curvar->rhs--;
  1517.                     break;
  1518.  
  1519.                 /* branch on variable = 0 processing, branch to label, error if it doesn't exist */
  1520.  
  1521.                 case IDM_VARZERO:
  1522.                     strcpy(cmd, curcmd->cmdstring);
  1523.                     s = strstr(cmd, "\377");
  1524.                     *(s++) = 0;
  1525.                     curvar = varstart;
  1526.                     while (curvar)
  1527.                     {
  1528.                         if (!stricmp(cmd, curvar->varname))
  1529.                             break;
  1530.                         curvar = curvar->next;
  1531.                     }
  1532.                     if (!curvar)
  1533.                     {
  1534.                         stop = TRUE;
  1535.                         sprintf(errbuf, "Variable \"%s\" not found", cmd);
  1536.                         MessageBox(hWnd, errbuf, "Command Error", MB_OK | MB_SYSTEMMODAL);
  1537.                         PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L);
  1538.                     }
  1539.                     else
  1540.                         if (!curvar->rhs)
  1541.                             if ((nextcmd = FindLabel(s)) == (CMD *)-1)
  1542.                             {
  1543.                                 stop = TRUE;
  1544.                                 MessageBox(hWnd, "Label not found", "Command Error", MB_OK | MB_SYSTEMMODAL);
  1545.                                 PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L);
  1546.                             }
  1547.                     break;
  1548.  
  1549.                 case IDM_QUIT:
  1550.                     PostMessage(hWnd, WM_DESTROY, 0, 0L);
  1551.                     break;
  1552.             }
  1553.  
  1554.             break;
  1555.  
  1556.         case WM_DESTROY:
  1557.             KillTimer(hWnd, 1);
  1558.             FreeCMD(cmdstart);
  1559.             FreeLabel(labelstart);
  1560.             FreeVar(varstart);
  1561.             PostQuitMessage(0);
  1562.             break;
  1563.  
  1564.         case WM_PAINT:
  1565.             BeginPaint (hWnd, &ps);
  1566.             EndPaint (hWnd,  &ps);
  1567.             break;
  1568.  
  1569.         case WM_CREATE:
  1570.             nextcmd = cmdstart;
  1571.             break;
  1572.  
  1573.         case WM_TIMER:
  1574.             if (stop)
  1575.                 break;
  1576.             curcmd = nextcmd;
  1577.             if (curcmd != NULL)
  1578.             {
  1579.                 nextcmd = curcmd->next;
  1580.                 PostMessage(hWnd, WM_COMMAND, (WPARAM)curcmd->function, 0L);
  1581.             }
  1582.             else
  1583.                 PostMessage(hWnd, WM_COMMAND, (WPARAM)IDM_QUIT, 0L);
  1584.             break;
  1585.  
  1586.         default:
  1587.             return (DefWindowProc(hWnd, message, wParam, lParam));
  1588.    }
  1589.    return ((long)NULL);
  1590. }
  1591.