home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tolkit45.zip / os2tk45 / samples / rexx / api / pmrexx / pmrexx.c next >
Encoding:
C/C++ Source or Header  |  1999-05-11  |  86.0 KB  |  1,492 lines

  1. /* static char *SCCSID = "@(#)pmrexx.c  6.4 92/01/10";                        */
  2. /*********************  START OF SPECIFICATIONS  ******************************/
  3. /*                                                                            */
  4. /*   SOURCE FILE NAME:  pmrexx.c                                              */
  5. /*                                                                            */
  6. /*   DESCRIPTIVE NAME:  PM host environment for REXX command files.           */
  7. /*                                                                            */
  8. /*      Provide a means to execute REXX command files from within a           */
  9. /*      PM environment, allowing the REXX/DM bindings to be used.             */
  10. /*                                                                            */
  11. /*   COPYRIGHT:         IBM Corporation 1991                                  */
  12. /*                                                                            */
  13. /*   STATUS:            Version 2.00                                          */
  14. /*                                                                            */
  15. /*   FUNCTION:                                                                */
  16. /*           This program provides a Presentation Manager Shell for           */
  17. /*      REXX programs.                                                        */
  18. /*                                                                            */
  19. /*                                                                            */
  20. /*   NOTES:                                                                   */
  21. /*      DEPENDENCIES:                                                         */
  22. /*          This function has dependencies on the following                   */
  23. /*      files for compilation.                                                */
  24. /*          pmrexx.h   - Definitions necessary for the resource               */
  25. /*                       file compilation.                                    */
  26. /*          pmrexxio.h - typedefs and prototypes necessary for use of         */
  27. /*                       the REXX I/O shell dll.                              */
  28. /*          The C runtime multi-threaded header files                         */
  29. /*          See README.C in \TOOLKT12\C for a list and description of the     */
  30. /*          system files that are needed.                                     */
  31. /*                                                                            */
  32. /*  EXECUTION INSTRUCTIONS:                                                   */
  33. /*          The PMREXX program is executed by specifying the                  */
  34. /*      PMREXX program with arguments corresponding to the name               */
  35. /*      of the REXX procedure file, followed by any arguments to              */
  36. /*      the REXX procedure. For example, from a command line:                 */
  37. /*          PMREXX REXXTRY say 'Hi'                                           */
  38. /*      would call PMREXX to execute the REXX procedure file                  */
  39. /*      "REXXTRY.CMD" with arguments of "say 'Hi'" being passed to            */
  40. /*      the procedure. For the same effect from the start programs            */
  41. /*      list, add PMREXX.EXE as the program (specify a path if it             */
  42. /*      is not in the system path) and "REXXTRY say 'Hi'" as the              */
  43. /*      parameters to be passed.                                              */
  44. /*                                                                            */
  45. /*  EXPECTED OUTPUT:                                                          */
  46. /*          The REXX procedure file will be executed with all                 */
  47. /*      output directed into PM windows.                                      */
  48. /*                                                                            */
  49. /*  PROCEDURES:                                                               */
  50. /*    main:           Main entry point                                        */
  51. /*    CallRexx:       Interface to the Rexx interpreter                       */
  52. /*    CheckRexxFile:  Validate program as a Rexx file                         */
  53. /*    PMRexxSubProc:  Subclass winproc of Rexx I/O window                     */
  54. /*    PMRXCmds:       Routine to process subclassed WM_COMMAND messages       */
  55. /*    SelectFile:     Put up a file selection dialog                          */
  56. /*    getstring:      Retrieve a module resource string                       */
  57. /*    init_routine:   Rexx initialization exit                                */
  58. /*    SetOption:      Enable/Disable a menu option                            */
  59. /*    SetCheckMark:   Check/Uncheck a menu option                             */
  60. /*    SysErrorBoxM:   Display message box with a system error message         */
  61. /*    CuaLogoDlgProc: Display About help                                      */
  62. /*    SysErrorBox:    Display message in a message box                        */
  63. /*                                                                            */
  64. /***********************  END OF SPECIFICATIONS  ******************************/
  65. #include <malloc.h>
  66. #include <process.h>
  67. #include <stddef.h>
  68. #include <stdio.h>
  69. #include <stdlib.h>
  70. #include <string.h>
  71.  
  72. /* Define the sections of the OS/2 header files that we need.                 */
  73.  
  74. #define  INCL_RXSYSEXIT                /* REXX system exits                   */
  75. #define  INCL_RXARI                    /* REXX Asynchronous Request Interface */
  76. #define  INCL_DOSERRORS                /* OS/2 errors                         */
  77. #define  INCL_DOSMODULEMGR             /* OS/2 module support                 */
  78. #define  INCL_DOSPROCESS               /* Process and thread support          */
  79. #define  INCL_DOSSEMAPHORES            /* Semaphores                          */
  80. #define  INCL_DOSQUEUES                /* Queues                              */
  81. #define  INCL_DOSMISC                  /* Miscellaneous doscalls              */
  82. #define  INCL_DOSNLS                   /* NLS (code page) support             */
  83. #define  INCL_GPILCIDS                 /* Physical and logical fonts with     */
  84.                                        /* lcids                               */
  85. #define  INCL_GPIPRIMITIVES            /* Drawing primitives and primitive    */
  86.                                        /* attributes                          */
  87. #define  INCL_WINCOUNTRY               /* Code page support                   */
  88. #define  INCL_WINDIALOGS               /* Dialog boxes                        */
  89. #define  INCL_WINENTRYFIELDS           /* Entry fields                        */
  90. #define  INCL_WINFRAMEMGR              /* Frame manager                       */
  91. #define  INCL_WINHELP                  /* Help manager definitions            */
  92. #define  INCL_WININPUT                 /* Mouse and keyboard input            */
  93. #define  INCL_WINMESSAGEMGR            /* Message management                  */
  94. #define  INCL_WINSHELLDATA             /* Profile calls                       */
  95. #define  INCL_WINSWITCHLIST            /* Task list calls                     */
  96. #define  INCL_WINTIMER                 /* Timer routines                      */
  97. #define  INCL_WINWINDOWMGR             /* General window management           */
  98. #define  INCL_WINMENUS                 /* Menu controls                       */
  99. #define  INCL_WINMLE                   /* Multiple line edit fields           */
  100. #define  INCL_WINPOINTERS              /* Mouse pointers                      */
  101. #define  INCL_WINSTDFILE               /* Standard File dialog                */
  102. #define  INCL_WINACCELERATORS          /* Accelerator APIs                    */
  103. #include <os2.h>
  104. #include <rexxsaa.h>                   /* Include the REXX header file        */
  105. #include "pmrexxio.h"
  106. #include "pmrexx.h"
  107.  
  108. /******************************************************************************/
  109. /*               G L O B A L    V A R I A B L E   S E C T I O N               */
  110. /******************************************************************************/
  111.  
  112. HAB     hab;                           /* Anchor block handle                 */
  113. PFNWP   SuperProc;                     /* Superclass window proc              */
  114. HWND    hwndClient;                    /* Client Window handle                */
  115. HWND    hwndFrame;                     /* Frame Window handle                 */
  116. ULONG   rexx_tid;                      /* ThreadIDs of the REXX thread        */
  117. PID     proc_id;                       /* process ID for PMREXX               */
  118. CHAR    pgmtitle[TITLE_SIZE+FNAME_SIZE+10];/* Holds title for title bar       */
  119. CHAR    procname[FNAME_SIZE];          /* Name of procedure to run            */
  120. RXSTRING rxargv;                       /* Structure to pass parameters to REXX*/
  121. BOOL    trace = FALSE;                 /* Flag to indicate if user gave a /T  */
  122. BOOL    Qflag = FALSE;                 /* Flag to indicate if user gave a /Q  */
  123. BOOL    Results = TRUE;                /* Flag to append or overwrite results */
  124. INT     ProcRC;                        /* process return code                 */
  125. CHAR    pszFileName[FNAME_SIZE];       /* buffer to hold filename             */
  126.  
  127. /* exit_list is a list of the system exits PMREXX register's with REXX        */
  128.  
  129. static RXSYSEXIT exit_list[] =  {
  130.     { PMRXIO_EXIT,   RXSIO },
  131.     { "PMREXXINIT",  RXINI },
  132.     { NULL,          RXENDLST }};
  133.  
  134. /************************** START OF SPECIFICATIONS ***************************/
  135. /*                                                                            */
  136. /*   SUBROUTINE NAME: main                                                    */
  137. /*                                                                            */
  138. /*   DESCRIPTIVE NAME:                                                        */
  139. /*               Execute the PMREXX program.                                  */
  140. /*                                                                            */
  141. /*   FUNCTION:                                                                */
  142. /*               This is the main entry point to the program. It sets up      */
  143. /*               the window, executes the message loop, and cleans up         */
  144. /*               on termination (exit from the message loop).                 */
  145. /*                                                                            */
  146. /*   NOTES:                                                                   */
  147. /*                                                                            */
  148. /*   ENTRY POINT:                                                             */
  149. /*      LINKAGE:  main(LONG  argc, CHAR *argv[])                              */
  150. /*                                                                            */
  151. /*   INPUT:                                                                   */
  152. /*      argc and argv are the standard C argument structures passed           */
  153. /*      in to a program.                                                      */
  154. /*                                                                            */
  155. /*   EXIT-NORMAL:                                                             */
  156. /*       Exit with return code 0.                                             */
  157. /*                                                                            */
  158. /*   EXIT-ERROR:                                                              */
  159. /*       If unable to register the window class, exit rc=1.                   */
  160. /*       If no procedure name was specified, exit with rc=3.                  */
  161. /*       If window was not displayed, exit with return code from the REXX     */
  162. /*         procedure.                                                         */
  163. /*       Otherwise: exit rc=0.                                                */
  164. /*                                                                            */
  165. /*   EFFECTS:                                                                 */
  166. /*       Executes the REXX procedure specified as the first argument with the */
  167. /*       input and output coming from/going to a PM window.                   */
  168. /*                                                                            */
  169. /*   INTERNAL REFERENCES:                                                     */
  170. /*      ROUTINES:                                                             */
  171. /*       CheckRexxFile  - See if the file starts with a comment line          */
  172. /*       getstring      - To obtain the title bar name and window name.       */
  173. /*                                                                            */
  174. /*   EXTERNAL REFERENCES:                                                     */
  175. /*      ROUTINES:                                                             */
  176. /*       DosExit                     WinInitialize                            */
  177. /*       DosGetInfoBlocks            WinMessageBox                            */
  178. /*       DosGetCp                    WinPostMessage                           */
  179. /*       WinAddSwitchEntry           WinQueryWindowProcess                    */
  180. /*       WinAlarm                    WinRemoveSwitchEntry                     */
  181. /*       WinCreateMsgQueue           WinSetCp                                 */
  182. /*       WinSubclassWindow           WinSetWindowText                         */
  183. /*       WinDestroyMsgQueue          WinTerminate                             */
  184. /*       WinSendMsg                  WinUpdateWindow                          */
  185. /*       WinDispatchMsg              WinWindowFromID                          */
  186. /*       WinGetMessage                                                        */
  187. /*                                                                            */
  188. /**************************** END OF SPECIFICATIONS ***************************/
  189.  
  190. void main(LONG argc, CHAR *argv[])
  191. {
  192.   HMQ      hmq;                        /* Message Queue handle                */
  193.   QMSG     qmsg;                       /* Message structure                   */
  194.   LONG     argnum = 1;                 /* Counter for looking at arguments    */
  195.   PUCHAR   trueargs;                   /* Pointer for actual argument string  */
  196.   HSWITCH  hswPMRexx = NULLHANDLE;     /* Handle to task list entry           */
  197.   SWCNTRL  swlEntry;                   /* Structure for task list entry       */
  198.   ULONG    idThread;                   /* Holds id of this thread             */
  199.   ULONG    CpSize;                     /* Size of returned code page info     */
  200.   PTIB     tib;                        /* thread block pointer                */
  201.   PPIB     pib;                        /* process block pointer               */
  202.   ULONG    CodePage;                   /* Code page we are running in         */
  203.    /* We set the creation flags to be the standard window frame flags         */
  204.    /*    but without scroll bars and without a task list entry.               */
  205.   ULONG    flCreate = FCF_STANDARD&~(FCF_VERTSCROLL|FCF_HORZSCROLL);
  206.  
  207.    /* We want the original arguments to pass to REXX, not the mangled         */
  208.    /*    version we get from C.                                               */
  209.  
  210.   DosGetInfoBlocks(&tib, &pib);
  211.   proc_id = pib->pib_ulpid;            /* save process id                     */
  212.   trueargs = pib->pib_pchenv;          /* point to true argument string       */
  213.  
  214.   pszFileName[0] = '\0';               /* set initial file name               */
  215.  
  216.    /* Set up the PM environment                                               */
  217.   hab = WinInitialize(0);
  218.   hmq = WinCreateMsgQueue(hab, 50);
  219.  
  220.                                        /* Create application msg queue        */
  221.                                        /* Get NLS Info                        */
  222.   DosGetCp(sizeof(CodePage), &CodePage, &CpSize);
  223.   WinSetCp(hmq, (USHORT)CodePage);     /* And set for PM                      */
  224.                                        /* Create Rexx I/O window              */
  225.   hwndFrame = RexxCreateIOWindow(HWND_DESKTOP, &hwndClient);
  226.   SuperProc = WinSubclassWindow(hwndClient, (PFNWP)PMRexxSubProc);
  227.                                        /* now add additional menu items       */
  228.  
  229.                                        /* now load the accelerator table      */
  230.   WinSetAccelTable(hab, WinLoadAccelTable(hab,
  231.       (HMODULE)NULL, RXHOST_WIN), hwndFrame);
  232.  
  233.       /* See if the trace bit is supposed to be turned on                     */
  234.   if (argc > argnum && !stricmp("/t", argv[argnum])) {
  235.  
  236.     trace = TRUE;                      /* Set the trace flag                  */
  237.     argnum++;                          /* If it was, that's an extra arg to   */
  238.                                        /* skip                                */
  239.   }
  240.  
  241.   /* See if the qflag option was specified to suppress pmrexx msg box*/
  242.   if (argc > argnum && !strcmpi("/q", argv[argnum])) {
  243.  
  244.      /* Turn on  qflag */
  245.      Qflag = TRUE;
  246.  
  247.      argnum++;               /* If it was, that's an extra arg to skip */
  248.  
  249.   } /* endif */
  250.  
  251.   if (argc <= argnum) {                /* There must at least have been a     */
  252.                                        /* procedure name specified If not,    */
  253.                                        /* alert the user and exit.            */
  254.     WinAlarm(HWND_DESKTOP, WA_ERROR);
  255.     WinMessageBox(HWND_DESKTOP,
  256.                   NULLHANDLE,
  257.                   getstring(BAD_NUM_PARMS),
  258.                   getstring(RXHA_MSGBOXHDR),
  259.                   1,
  260.                   MB_CANCEL|MB_CUACRITICAL|MB_MOVEABLE);
  261.     WinSetFocus(HWND_DESKTOP, hwndFrame);
  262.     WinPostMsg(hwndFrame, WM_QUIT, (MPARAM)0, (MPARAM)0);
  263.     ProcRC = BAD_NUM_PARMS;
  264.   }
  265.  
  266.   else {                               /* procedure name was specified        */
  267.     PUCHAR format = getstring(RXH_TITLE);
  268.     PUCHAR pgmname = getstring(PROGRAM_NAME);/* Create the window/program     */
  269.                                        /* title                               */
  270.  
  271.     strcpy(procname, argv[argnum]);
  272.     sprintf(pgmtitle, (const char *)format, pgmname, procname);
  273.  
  274.          /* Check to see if the file starts with a comment or not             */
  275.  
  276.     if (!CheckRexxFile(procname)) {    /* It doesn't start with a comment     */
  277.                                        /* line, so put up a message box saying*/
  278.                                        /* that the procedure file could not be*/
  279.                                        /* found.                              */
  280.       *procname = '\0';
  281.       WinMessageBox(HWND_DESKTOP,
  282.                     NULLHANDLE, getstring(RXHM_PROC_NOT_FOUND),
  283.                     getstring(RXHA_MSGBOXHDR), 1,
  284.                     MB_CANCEL|MB_CUACRITICAL|MB_MOVEABLE);
  285.       WinSetFocus(HWND_DESKTOP, hwndFrame);
  286.       WinPostMsg(hwndFrame, WM_QUIT, (MPARAM)0, (MPARAM)0);
  287.       ProcRC = PROC_NOT_FOUND;
  288.     }
  289.  
  290.          /* Update the title bar to the newly created name                    */
  291.     WinSetWindowText(WinWindowFromID(hwndFrame,(USHORT)FID_TITLEBAR),
  292.                      pgmtitle);
  293.     free(format);
  294.     free(pgmname);
  295.     argnum++;
  296.  
  297.     if (argnum < argc) {               /* In this section, we obtain the      */
  298.                                        /* arguments to pass to the REXX       */
  299.                                        /* procedure from the original         */
  300.                                        /* arguments as stored in the          */
  301.                                        /* environment segment. We cannot      */
  302.                                        /* accept the *argv[] version, because */
  303.                                        /* the C runtime library will have     */
  304.                                        /* changed things like spacing,        */
  305.                                        /* quotation marks, etc.               */
  306.  
  307.       while (*trueargs++)
  308.         ;                              /* Skip the first argument (the        */
  309.                                        /* command/program name)               */
  310.  
  311.       while (--argnum) {               /* Skip the procedure name and the "/t"*/
  312.                                        /* option, if there                    */
  313.  
  314.         while (' ' == *trueargs) {     /* Skip leading white space            */
  315.           trueargs++;
  316.         }
  317.  
  318.         do {                           /* Then skip the argument              */
  319.  
  320.           if ('"' == *trueargs) {      /* If quote delimited                  */
  321.             trueargs++;                /* skip to matching quote              */
  322.  
  323.             while (*trueargs && '"' != *trueargs++)
  324.               ;
  325.           }
  326.  
  327.           else
  328.             trueargs++;
  329.         }
  330.  
  331.  
  332.         while (' ' != *trueargs);
  333.  
  334.       }
  335.       trueargs++;                      /* Skip next space Set up the remaining*/
  336.                                        /* argument string for passing to the  */
  337.                                        /* REXX procedure.                     */
  338.       rxargv.strptr = (PCHAR)strdup((const char *)trueargs);
  339.       rxargv.strlength = strlen(rxargv.strptr);
  340.  
  341.     }
  342.  
  343.     else {                             /* no additional arguments             */
  344.       rxargv.strlength = 0;
  345.       rxargv.strptr = NULL;
  346.     }
  347.  
  348.                                        /* register I/O handler                */
  349.     RexxRegisterExitExe("PMREXXINIT", (PFN)init_routine, NULL);
  350.     DosCreateThread(&rexx_tid, (PFNTHREAD)CallRexx, (ULONG)0, (ULONG)0,
  351.         STACK_SIZE);
  352.   }
  353.  
  354.   WinUpdateWindow(hwndFrame);
  355.  
  356.    /* Get the switch list handle                                              */
  357.  
  358.   WinQueryWindowProcess(hwndFrame, &swlEntry.idProcess, &idThread);
  359.  
  360.   hswPMRexx = WinQuerySwitchHandle(hwndFrame, swlEntry.idProcess);
  361.  
  362.   if (!WinQuerySwitchEntry(hswPMRexx, &swlEntry)) {
  363.  
  364.     strcpy(swlEntry.szSwtitle, pgmtitle);
  365.     WinChangeSwitchEntry(hswPMRexx, &swlEntry);
  366.   }
  367.  
  368.    /* Main message processing loop - get and dispatch messages until          */
  369.    /* WM_QUIT received                                                        */
  370.  
  371.   while (WinGetMsg(hab, &qmsg, (HWND)NULL, 0, 0))
  372.     WinDispatchMsg(hab, &qmsg);
  373.  
  374.                                        /* Delete subclassing                  */
  375.   WinSubclassWindow(hwndClient, (PFNWP)SuperProc);
  376.                                        /* Destroy Rexx I/O window             */
  377.   RexxDestroyIOWindow(hwndFrame);
  378.                                        /* drop exit handlers                  */
  379.   RexxDeregisterExit("PMREXXINIT", NULL);
  380.   WinDestroyMsgQueue(hmq);
  381.   WinTerminate(hab);
  382.  
  383.    /* Exit the process and return the return code specified by ProcRC         */
  384.  
  385.   DosExit(EXIT_PROCESS, ProcRC);
  386. }
  387.  
  388.  
  389. /************************** START OF SPECIFICATIONS ***************************/
  390. /*                                                                            */
  391. /*   SUBROUTINE NAME: CallRexx                                                */
  392. /*                                                                            */
  393. /*   DESCRIPTIVE NAME:                                                        */
  394. /*               Execute the REXX procedure file via the RexxStart interface. */
  395. /*                                                                            */
  396. /*   FUNCTION:                                                                */
  397. /*               This function is the thread that executes the REXX           */
  398. /*               procedure. It disables the RESTART option and calls the      */
  399. /*               Rexx interpreter.  On return, it reenables the RESTART       */
  400. /*               options, outputs a message box indicating the procedure has  */
  401. /*               ended, and terminates the thread.                            */
  402. /*                                                                            */
  403. /*   NOTES:                                                                   */
  404. /*                                                                            */
  405. /*   ENTRY POINT:                                                             */
  406. /*      LINKAGE:                                                              */
  407. /*          void _stdcall CallRexx(void                                       */
  408. /*                                                                            */
  409. /*   INPUT:                                                                   */
  410. /*       The arguments for the procedure have already been placed in the      */
  411. /*       global variable 'rxargv'.                                            */
  412. /*                                                                            */
  413. /*   EXIT-NORMAL:                                                             */
  414. /*                                                                            */
  415. /*   EXIT-ERROR:                                                              */
  416. /*                                                                            */
  417. /*   EFFECTS:                                                                 */
  418. /*                                                                            */
  419. /*   INTERNAL REFERENCES:                                                     */
  420. /*      ROUTINES:                                                             */
  421. /*       SetCheckMark   - Check/uncheck a menu item                           */
  422. /*       SetOptions     - Enable/disable menu items.                          */
  423. /*                                                                            */
  424. /*   EXTERNAL REFERENCES:                                                     */
  425. /*      ROUTINES:                                                             */
  426. /*                                                                            */
  427. /**************************** END OF SPECIFICATIONS ***************************/
  428.  
  429. void CallRexx(void)
  430. {
  431.   RXSTRING retval;                     /* return value from call to REXXSAA   */
  432.   SHORT    rc;                         /* return code                         */
  433.  
  434.   SetOptions(PMRXA_RESTART, FALSE);    /* Don't allow restart while active    */
  435.   SetOptions(RXIOA_HALT, TRUE);        /* Enable HALT option                  */
  436.                                        /* enable I/O system                   */
  437.   while (!WinPostMsg(hwndClient, REXX_STARTPROC,
  438.       MPFROMLONG(rexx_tid), (MPARAM)0));
  439.     DosSleep(0L);
  440.  
  441.    MAKERXSTRING(retval, NULL, 0);      /* null out RXSTRING                   */
  442.    /* Now start the REXX procedure. Check for a not-found error.           */
  443.    if (PROC_NOT_FOUND == RexxStart((!rxargv.strlength) ? 0 : 1,
  444.                                    (!rxargv.strlength)? NULL : &rxargv,
  445.                                   procname,
  446.                                   NULL,
  447.                                   NULL,
  448.                                   RXCOMMAND,
  449.                                   exit_list,
  450.                                   &rc,
  451.                                   &retval )) {
  452.  
  453.       /* If the procedure was not found, let the window procedure put up   */
  454.       /*   a message box indicating the problem. Set the return code to    */
  455.       /*   exit with.                                                      */
  456.       while (!WinPostMsg(hwndClient, REXX_PROC_NF, NULL, NULL))
  457.          DosSleep(0L);
  458.       ProcRC = PROC_NOT_FOUND;
  459.  
  460.    }
  461.    else {
  462.      DosSleep((ULONG)TIMER_DELAY);
  463.      ProcRC = rc;
  464.   }
  465.                                        /* disable I/O system                  */
  466.   while (!WinPostMsg(hwndClient, REXX_ENDPROC, (MPARAM)0, (MPARAM)0))
  467.     DosSleep(0L);
  468.  
  469.   SetOptions(PMRXA_RESTART, TRUE);     /* Re-enable the re-start option       */
  470.   SetCheckMark(RXIOA_HALT, FALSE);
  471.   SetOptions(RXIOA_HALT, FALSE);       /* Don't allow halt if not active      */
  472.                                        /* display message to user             */
  473.   while (!WinPostMsg(hwndClient, REXX_PROC_ENDED, (MPARAM)0, (MPARAM)0))
  474.     DosSleep(0L);
  475.   DosExit(EXIT_THREAD, 0);             /* end the thread                      */
  476. }
  477.  
  478.  
  479. /************************** START OF SPECIFICATIONS ***************************/
  480. /*                                                                            */
  481. /*   SUBROUTINE NAME:  CheckRexxFile                                          */
  482. /*                                                                            */
  483. /*   DESCRIPTIVE NAME:                                                        */
  484. /*              Verify that this is a REXX procedure file.                    */
  485. /*                                                                            */
  486. /*   FUNCTION:  This function will check that the file starts with a comment  */
  487. /*              line to verify that it is a REXX procedure file.              */
  488. /*                                                                            */
  489. /*   NOTES:                                                                   */
  490. /*                                                                            */
  491. /*   ENTRY POINT:                                                             */
  492. /*      LINKAGE:                                                              */
  493. /*            ULONG  CheckRexxFile(PUCHAR procname)                           */
  494. /*                                                                            */
  495. /*   INPUT:                                                                   */
  496. /*       procname - ptr to an asciiz string containing the filename to run    */
  497. /*                                                                            */
  498. /*   EXIT-NORMAL:                                                             */
  499. /*       returns TRUE if the file starts with a comment line                  */
  500. /*                                                                            */
  501. /*   EXIT-ERROR:                                                              */
  502. /*       returns FALSE otherwise                                              */
  503. /*                                                                            */
  504. /*   EFFECTS:                                                                 */
  505. /*                                                                            */
  506. /*   INTERNAL REFERENCES:                                                     */
  507. /*      ROUTINES:                                                             */
  508. /*                                                                            */
  509. /*   EXTERNAL REFERENCES:                                                     */
  510. /*      ROUTINES:                                                             */
  511. /*        DosSearchPath                                                       */
  512. /**************************** END OF SPECIFICATIONS ***************************/
  513.  
  514. ULONG  CheckRexxFile(PUCHAR procname)
  515. {
  516.   CHAR fullname[FNAME_SIZE];           /* buffer for fully qualified path     */
  517.   CHAR tempname[FNAME_SIZE];           /* holds name to search for            */
  518.   FILE *fptr = NULL;                   /* ptr to file                         */
  519.   CHAR *pathchar,*colon;               /* ptr to '\' and ':'                  */
  520.   CHAR buff[10];                       /* holds input line from file          */
  521.   ULONG  i;                            /* counter variable                    */
  522.  
  523.   strcpy(tempname, (const char *)procname);          /* copy name to temp holder            */
  524.  
  525.   for (i = 0; i < 2 && !fptr; i++) {   /* loop through twice                  */
  526.  
  527.     if (!(fptr = fopen(tempname, "r"))) {/* couldn't open the file            */
  528.       pathchar = getstring(BACKPATH_DELIMETER);/* load in '\' and             */
  529.       colon = getstring(DRIVE_DELIMETER);/* ':'                               */
  530.  
  531.          /* Check to see it they entered a path                               */
  532.  
  533.       if (!strchr((const char *)procname, *pathchar) && !strchr((const char *)procname, *colon)) {
  534.                                        /* They only entered a filename, so    */
  535.                                        /* search the DPATH for it             */
  536.  
  537.         if (!DosSearchPath(SEARCH_CUR_DIRECTORY|SEARCH_ENVIRONMENT|
  538.             SEARCH_IGNORENETERRS, "PATH", tempname, fullname, sizeof(fullname)
  539.             )) {
  540.           fptr = fopen(fullname, "r"); /* Try and open the file               */
  541.         }
  542.       }
  543.     }
  544.  
  545.       /* If we still haven't found it stick on a .CMD, and try again          */
  546.  
  547.     if (!fptr) {
  548.       strcat(tempname, ".cmd");
  549.     }
  550.   }
  551.  
  552.   if (fptr) {                          /* We found it                         */
  553.     fgets(buff, 10, fptr);             /* read in the first line              */
  554.  
  555.       /* Check if the first two characters are a comment                      */
  556.  
  557.     if (*buff == '/' && *(buff+1) == '*') {
  558.  
  559.          /* It's OK, so copy whatever name we found to procname               */
  560.  
  561.       strcpy(procname, tempname);
  562.       fclose(fptr);                    /* Close the file                      */
  563.       return  TRUE;                    /* Indicate success                    */
  564.     }
  565.  
  566.     fclose(fptr);                      /* Close the file                      */
  567.   }
  568.   return  FALSE;                       /* Indicate failure                    */
  569. }
  570.  
  571. /************************** START OF SPECIFICATIONS ***************************/
  572. /*                                                                            */
  573. /*   SUBROUTINE NAME: PMRexxSubProc                                           */
  574. /*                                                                            */
  575. /*   DESCRIPTIVE NAME:                                                        */
  576. /*               Subclass handler for PMREXX I/O window.                      */
  577. /*                                                                            */
  578. /*   FUNCTION:                                                                */
  579. /*               This procedure handles all messages over and above the       */
  580. /*               ones handled by the main PMREXX window.                      */
  581. /*               are:                                                         */
  582. /*       REXX_PROC_NF   - Puts up a message box indicating that the REXX      */
  583. /*                        procedure was not found.                            */
  584. /*       REXX_PROC_ENDED- Puts up a message box indicating to the user that   */
  585. /*                        the REXX procedure has terminated.                  */
  586. /*       RXHB_MSGBOX    - Puts up a message box with the requested message.   */
  587. /*       WM_SAVEAPPLICATION - Save the current font and window information    */
  588. /*                                                                            */
  589. /*   NOTES:                                                                   */
  590. /*                                                                            */
  591. /*   ENTRY POINT:                                                             */
  592. /*      LINKAGE:                                                              */
  593. /*               Standard window procedure linkage is followed.               */
  594. /*                                                                            */
  595. /*   INPUT:                                                                   */
  596. /*               Standard window procedure inputs are passed in.              */
  597. /*                                                                            */
  598. /*   INTERNAL REFERENCES:                                                     */
  599. /*      ROUTINES:                                                             */
  600. /*       getstring      - Retrieve a string resource                          */
  601. /*       PMRXCmds       - This routine processes the various WM_COMMAND       */
  602. /*                        messages.                                           */
  603. /*       SetCheckMark   - Check/uncheck a menu item                           */
  604. /*       SysErrorBoxM   - SysErrorBox with added user control                 */
  605. /*       ProcessSaveQuit - Interface to the Save/Quit dialog                  */
  606. /*                                                                            */
  607. /*                                                                            */
  608. /*   EXTERNAL REFERENCES:                                                     */
  609. /*      ROUTINES:                                                             */
  610. /*       DosReleaseMutexSem                WinMessageBox                      */
  611. /*       DosRequestMutexSem                WinPostMsg                         */
  612. /*       WinSendMsg                        WinQueryWindow                     */
  613. /*       WinSetFocus                       WinQueryWindowPos                  */
  614. /*       WinWindowFromID                                                      */
  615. /*                                                                            */
  616. /**************************** END OF SPECIFICATIONS ***************************/
  617.  
  618. MRESULT EXPENTRY PMRexxSubProc(HWND hwnd, ULONG msg, MPARAM mp1,
  619.                               MPARAM mp2)
  620. {
  621.  
  622.     switch (msg) {
  623.  
  624.       case  WM_COMMAND :
  625.                                        /* All WM_COMMAND processed in PMRXCmds*/
  626.         return (PMRXCmds(hwnd, mp1, mp2));
  627.         break;
  628.  
  629.       case  WM_CHAR :
  630.  
  631.          /* Check for a valid (complete) key message.                         */
  632.  
  633.         if (!(SHORT1FROMMP(mp1)&KC_KEYUP) &&
  634.             (SHORT1FROMMP(mp1)&KC_VIRTUALKEY) ) {
  635.  
  636.           switch (SHORT2FROMMP(mp2)) {
  637.             case  VK_BREAK :           /* For a break key, set the halt       */
  638.                                        /* procedure indicator.                */
  639.               WinSendMsg(hwnd, WM_COMMAND, MPFROMSHORT(RXIOA_HALT), (MPARAM)0);
  640.               break;
  641.  
  642.             case  VK_ENTER :           /* For a break key, set the halt       */
  643.               WinSendMsg(hwnd, WM_CHAR, MPFROM2SHORT(KC_VIRTUALKEY, NULL),
  644.                          MPFROM2SHORT(NULL, VK_NEWLINE));
  645.         break;
  646.             default  :
  647.               break;
  648.           }                            /* endswitch                           */
  649.         }
  650.         break;
  651.  
  652.       case  DOS_ERROR :
  653.  
  654.          /* Place the information on the base system error into a message     */
  655.          /*   box.                                                            */
  656.  
  657.         SysErrorBoxM(hwnd, SHORT1FROMMP(mp1), mp2, SHORT2FROMMP(mp1));
  658.         break;
  659.  
  660.       case  REXX_PROC_NF :
  661.  
  662.          /* Tell the user that REXX could not find the procedure, and then    */
  663.          /*    exit.                                                          */
  664.  
  665.         WinAlarm(HWND_DESKTOP, WA_ERROR);
  666.         WinSendMsg(hwndClient, RXHB_MSGBOX,
  667.             MPFROM2SHORT(RXHM_PROC_NOT_FOUND, RXHA_MSGBOXHDR),
  668.             MPFROMLONG(MB_CANCEL|MB_CUACRITICAL|MB_MOVEABLE));
  669.         WinPostMsg(hwndClient, WM_CLOSE, (MPARAM)0, (MPARAM)0);
  670.         break;
  671.  
  672.       case  REXX_PROC_ENDED :
  673.  
  674.          /* Tell the user that the procedure has completed processing.        */
  675.         if (!Qflag) {
  676.           WinSendMsg(hwndClient, RXHB_MSGBOX,
  677.               MPFROM2SHORT(RXHM_PROC_ENDED, PROGRAM_NAME),
  678.               MPFROMLONG(MB_OK|MB_INFORMATION|MB_MOVEABLE));
  679.           WinSetFocus(HWND_DESKTOP, hwndFrame);
  680.         }
  681.         else {
  682.           /* quit immediately if QUIET flag was selected                      */
  683.           WinPostMsg( hwndFrame, WM_QUIT, 0L, 0L );
  684.         }
  685.         break;
  686.  
  687.       case  RXHB_MSGBOX : {            /* Put up a message box. The mp1       */
  688.                                        /* parameter has the resource ids for  */
  689.                                        /* the message and the title.          */
  690.           USHORT msgid = SHORT1FROMMP(mp1);
  691.           PUCHAR header = getstring(SHORT2FROMMP(mp1));
  692.           PUCHAR content = getstring(SHORT1FROMMP(mp1));/* If we are          */
  693.                                        /* displaying the ended message, set   */
  694.                                        /* the owner to the desktop so we don't*/
  695.                                        /* steal the focus back from other     */
  696.                                        /* apps.                               */
  697.  
  698.           LONG  rc = WinMessageBox(HWND_DESKTOP,
  699.               (RXHM_PROC_ENDED == msgid?HWND_DESKTOP: hwnd),
  700.               content, header, msgid, SHORT1FROMMP(mp2));
  701.           free(header);
  702.           free(content);
  703.           return  MPFROMSHORT(rc);
  704.         }
  705.         break;
  706.  
  707.       case  WM_CLOSE :
  708.  
  709.          /* Check to see if the window needs to be saved, but only if the     */
  710.          /* user has entered a filename, otherwise just exit.                 */
  711.  
  712.         if ((!strlen(pszFileName)) || ProcessSaveQuit(hwnd)) {
  713.           WinSendMsg(hwndClient, WM_SAVEAPPLICATION, NULL, NULL);
  714.           WinPostMsg( hwndFrame, WM_QUIT, 0L, 0L );
  715.           return (MRESULT)(FALSE);
  716.         }
  717.  
  718.         else {                         /* Don't Close if Cancel on            */
  719.                                        /* ProcessSaveQuit                     */
  720.           return (MRESULT)(TRUE);
  721.         }
  722.         break;
  723.  
  724.       default  :
  725.         break;
  726.     }
  727.     return (*SuperProc)(hwnd, msg, mp1, mp2);
  728. }
  729.  
  730. /************************** START OF SPECIFICATIONS ***************************/
  731. /*                                                                            */
  732. /*   SUBROUTINE NAME: PMRXCmds                                                */
  733. /*                                                                            */
  734. /*   DESCRIPTIVE NAME:                                                        */
  735. /*               Process WM_COMMAND messages for the window procedure.        */
  736. /*                                                                            */
  737. /*   FUNCTION:                                                                */
  738. /*               This routine processes all the WM_COMMAND messages that have */
  739. /*               are handled by the Subclassed window.  Messages handled are: */
  740. /*                                                                            */
  741. /*       PMRXA_RESTART  - This requests that the REXX procedure be re-run.    */
  742. /*                        This command is only valid if the previous instance */
  743. /*                        of the procedure has ended.                         */
  744. /*       PMRXA_EXIT     - This is a request to close the application.         */
  745. /*       PMRXA_SAVEAS   - Save the MLE to the same file as last time.         */
  746. /*       PMRXA_SAVE     - Present the user with a dialog to select a file for */
  747. /*                        saving the MLE.                                     */
  748. /*       PMRXA_ABOUT    - Present the About dialog.                           */
  749. /*                                                                            */
  750. /*   NOTES:                                                                   */
  751. /*                                                                            */
  752. /*   ENTRY POINT:                                                             */
  753. /*      LINKAGE:                                                              */
  754. /*       MRESULT PMRXCmds(HWND hwnd, MPARAM mp1, MPARAM MP2)                  */
  755. /*                                                                            */
  756. /*   INPUT:                                                                   */
  757. /*       hwnd           - The window handle of the window that received the   */
  758. /*                        command.                                            */
  759. /*       mp1            - The first parameter of the WM_COMMAND message.      */
  760. /*       mp2            - The second parameter of the WM_COMMAND message.     */
  761. /*                                                                            */
  762. /*   EXIT-NORMAL:                                                             */
  763. /*       returns TRUE if the file was saved successfully or user response     */
  764. /*       from SAVEAS dialog.                                                  */
  765. /*   EXIT-ERROR:                                                              */
  766. /*       returns FALSE if the file was not saved successfully.                */
  767. /*                                                                            */
  768. /*   EFFECTS:                                                                 */
  769. /*                                                                            */
  770. /*   INTERNAL REFERENCES:                                                     */
  771. /*      ROUTINES:                                                             */
  772. /*       getstring      - Retrieve a string resource                          */
  773. /*       SelectFile     - Interface to the file selection dialog              */
  774. /*       SetCheckMark   - Check/uncheck a menu item                           */
  775. /*       WriteFile      - Write the data from the MLE into a file             */
  776. /*                                                                            */
  777. /*                                                                            */
  778. /*   EXTERNAL REFERENCES:                                                     */
  779. /*      ROUTINES:                                                             */
  780. /*       WinAlarm                       WinPostMessage                        */
  781. /*       WinSendMsg                     WinLoadString                         */
  782. /*       WinDlgBox                      WinWindowFromID                       */
  783. /*                                                                            */
  784. /**************************** END OF SPECIFICATIONS ***************************/
  785.  
  786. MRESULT PMRXCmds(HWND hwnd, MPARAM mp1, MPARAM mp2)
  787. {
  788.     CHAR pszFMask[FNAME_SIZE];         /* buffer to hold mask for wildcard    */
  789.                                        /* searches                            */
  790.     CHAR pszTitle[TITLE_SIZE];         /* text for Save As title bar          */
  791.     CHAR pszFName[FNAME_SIZE];         /* buffer for formatted filename       */
  792.     CHAR Temp = '\0';                  /* temporary character                 */
  793.     ULONG  UserResponse;               /* holds user response from Save As    */
  794.     ULONG  usFileSize;
  795.  
  796.  
  797.  
  798.     switch (LOUSHORT(mp1)) {
  799.  
  800.       /************************************************************************/
  801.       /* Flip the trace flag                                                  */
  802.       /************************************************************************/
  803.  
  804.       case  PMRXA_FLAGCHANGE:
  805.         if (mp2 == 0) {
  806.            trace = FALSE;
  807.         } else {
  808.            trace = TRUE;
  809.         } /* endif */
  810.         break;
  811.  
  812.       /************************************************************************/
  813.       /* Flip the result flag                                                 */
  814.       /************************************************************************/
  815.  
  816.       case  PMRXA_RESULTCHANGE:
  817.  
  818.         Results = !Results;
  819.         break;
  820.  
  821.       /************************************************************************/
  822.       /* Rerun the program                                                    */
  823.       /************************************************************************/
  824.  
  825.       case  PMRXA_RESTART :
  826.         if (!Results) {
  827.  
  828.           WinEnableWindowUpdate(hwnd, FALSE);
  829.                                        /* disable updates Get length of the   */
  830.                                        /* output in the MLE                   */
  831.           usFileSize = (ULONG )WinSendMsg(WinWindowFromID(hwnd,
  832.                                           (USHORT)MLE_WNDW),
  833.                                           MLM_QUERYTEXTLENGTH,
  834.                                           (MPARAM)0, (MPARAM)0);
  835.                                        /* Select all of the output in the MLE */
  836.           WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  837.                      MLM_DELETE, (MPARAM)0L, MPFROMSHORT(usFileSize));
  838.           WinInvalidateRect(hwnd, NULL, TRUE);
  839.                                        /* update the window                   */
  840.           WinEnableWindowUpdate(hwnd, TRUE);
  841.                                        /* Make MLE so that it can't be undone */
  842.           WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  843.                      MLM_RESETUNDO, (MPARAM)0, (MPARAM)0);
  844.         } /* endif */
  845.  
  846.         DosCreateThread(&rexx_tid, (PFNTHREAD)CallRexx, (ULONG)0, (ULONG)0,
  847.             STACK_SIZE);
  848.  
  849.         break;
  850.  
  851.       /************************************************************************/
  852.       /* Shutdown and get out                                                 */
  853.       /************************************************************************/
  854.  
  855.       case PMRXA_EXIT:
  856.  
  857.          WinPostMsg( hwnd, WM_CLOSE, 0L, 0L );
  858.          break;
  859.  
  860.       /************************************************************************/
  861.       /* Save the file according to user file specification                   */
  862.       /************************************************************************/
  863.  
  864.       case  PMRXA_SAVE :
  865.  
  866.         WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  867.             MLM_RESETUNDO, (MPARAM)0, (MPARAM)0);
  868.  
  869.         if (!strlen(pszFileName)) {    /* User hasn't added a filename  */
  870.                                        /* yet, so put up the Save As dialog   */
  871.           WinSendMsg(hwnd, WM_COMMAND, MPFROMSHORT(PMRXA_SAVEAS), (MPARAM)0);
  872.         }
  873.  
  874.         else {                         /* We have the filename, so just write */
  875.                                        /* it out.                             */
  876.  
  877.           if (WriteFile(hab, hwnd, pszFileName, procname, FALSE)) {
  878.             WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  879.                        MLM_SETCHANGED, MPFROMSHORT(FALSE), (MPARAM)0);
  880.             return (MRESULT)(TRUE);
  881.           }
  882.  
  883.           else {
  884.             return (MRESULT)(FALSE);
  885.           }
  886.         }
  887.         break;
  888.  
  889.       /************************************************************************/
  890.       /* Bring up the Save As dialog to get the filename                      */
  891.       /************************************************************************/
  892.  
  893.       case  PMRXA_SAVEAS :
  894.         WinLoadString(hab, (HMODULE)NULL, PMRXHB_SAVETITLE,
  895.             sizeof(pszTitle), pszTitle);
  896.         WinLoadString(hab, (HMODULE)NULL, PMRXHB_FILEMASK,
  897.             sizeof(pszFMask), pszFMask);
  898.         *pszFName = '\0';
  899.  
  900.         if (ESCAPE != (UserResponse = SelectFile( pszTitle,
  901.             pszFMask, pszFName))) {
  902.  
  903.           if (WriteFile(hab, hwnd, pszFName, procname, TRUE)) {
  904.             WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  905.                        MLM_SETCHANGED, MPFROMSHORT(FALSE), NULL);
  906.             strcpy(pszFileName, pszFName);
  907.           }
  908.         }
  909.         WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  910.                    MLM_RESETUNDO, (MPARAM)0, (MPARAM)0);
  911.         return (MRESULT)(UserResponse);
  912.         break;
  913.  
  914.       /************************************************************************/
  915.       /* Display the About dialog.                                            */
  916.       /************************************************************************/
  917.  
  918.       case  PMRXA_ABOUT :
  919.  
  920.         WinDlgBox(HWND_DESKTOP, hwndFrame, (PFNWP)CuaLogoDlgProc,
  921.                        (HMODULE)0, PMREXX_CUALOGO, (PVOID)NULL);
  922.         break;
  923.  
  924.  
  925.       /************************************************************************/
  926.       /* Option not handled here, pass on to default win proc                 */
  927.       /************************************************************************/
  928.  
  929.       default  :
  930.         return (*SuperProc)(hwnd, WM_COMMAND, mp1, mp2);
  931.     }
  932. }
  933.  
  934. /************************** START OF SPECIFICATIONS ***************************/
  935. /*                                                                            */
  936. /*   SUBROUTINE NAME: SelectFile                                              */
  937. /*                                                                            */
  938. /*   DESCRIPTIVE NAME: Bring up Select File dialog procedure.                 */
  939. /*                                                                            */
  940. /*   FUNCTION:                                                                */
  941. /*               This routine sets up the file structure before calling the   */
  942. /*               file selection dialog.                                       */
  943. /*                                                                            */
  944. /*   NOTES:                                                                   */
  945. /*                                                                            */
  946. /*   ENTRY POINT:                                                             */
  947. /*      LINKAGE: ULONG  SelectFile                                            */
  948. /*                                                                            */
  949. /*   INPUT:                                                                   */
  950. /*      PSZ pszTitle - current title text                                     */
  951. /*      PSZ pszFileMask - file mask to search for                             */
  952. /*      PSZ pszFName - filename (returned)                                    */
  953. /*                                                                            */
  954. /*   EXIT-NORMAL:                                                             */
  955. /*      Returns ENTER or ESCAPE                                               */
  956. /*                                                                            */
  957. /*   EXIT-ERROR:                                                              */
  958. /*      None.                                                                 */
  959. /*                                                                            */
  960. /*   EFFECTS:                                                                 */
  961. /*                                                                            */
  962. /*   INTERNAL REFERENCES:                                                     */
  963. /*      ROUTINES:                                                             */
  964. /*        getstring                                                           */
  965. /*                                                                            */
  966. /*   EXTERNAL REFERENCES:                                                     */
  967. /*      ROUTINES:                                                             */
  968. /*        WinFileDlg                                                          */
  969. /*                                                                            */
  970. /**************************** END OF SPECIFICATIONS ***************************/
  971.  
  972.   ULONG  SelectFile(PSZ pszTitle, PSZ pszFileMask, PSZ pszFName) {
  973.     BOOL     fSuccess = FALSE;
  974.     HWND     hwndDlg;                  /* file dialog handle                  */
  975.     FILEDLG  fdl;                      /* open/saveas dialog data             */
  976.     PSZ      pszDefaultDrive = NULL ;
  977.     static   PSZ   ppszDefaultDriveList[] = { NULL } ;
  978.     PSZ      pszDefaultEAType = NULL ;
  979.     static   PSZ   ppszDefaultEATypeList[] = { NULL } ;
  980.  
  981.  
  982.   fdl.pfnDlgProc     = NULL;
  983.   fdl.cbSize         = sizeof(FILEDLG);
  984.   fdl.fl             = FDS_HELPBUTTON | FDS_CENTER | FDS_SAVEAS_DIALOG | FDS_ENABLEFILELB ;
  985.   fdl.ulUser         = 0L ;
  986.   fdl.lReturn        = 0L;
  987.   fdl.lSRC           = FDS_SUCCESSFUL ;
  988.   fdl.hMod           = (HMODULE)NULL ;
  989.   fdl.usDlgId        = 0 ;
  990.   fdl.x              = 0 ;
  991.   fdl.y              = 0 ;
  992.   fdl.pszIDrive      = pszDefaultDrive ;
  993.   fdl.papszIDriveList= (PAPSZ) ppszDefaultDriveList ;
  994.   fdl.pszIType       = pszDefaultEAType ;
  995.   fdl.papszITypeList = (PAPSZ) ppszDefaultEATypeList ;
  996.   fdl.pszOKButton    = NULL;
  997.  
  998.   strcpy(fdl.szFullFile, pszFileMask);
  999.   fdl.pszTitle = pszTitle;
  1000.  
  1001.   /* Call the Standard Open/SaveAs Dialog Procedure. */
  1002.  
  1003.   hwndDlg = WinFileDlg(HWND_DESKTOP, hwndClient, &fdl);
  1004.  
  1005.   /* Check which button was selected. */
  1006.  
  1007.   switch ((SHORT)fdl.lReturn) {
  1008.  
  1009.     case DID_OK_PB:
  1010.       strcpy(pszFName, fdl.szFullFile);
  1011.       fSuccess = TRUE;
  1012.       break;
  1013.  
  1014.     case DID_CANCEL_PB:
  1015.       fSuccess = FALSE;
  1016.       break ;
  1017.   }
  1018.  
  1019.   return fSuccess;
  1020. }
  1021.  
  1022. /************************** START OF SPECIFICATIONS ***************************/
  1023. /*                                                                            */
  1024. /*   SUBROUTINE NAME: getstring                                               */
  1025. /*                                                                            */
  1026. /*   DESCRIPTIVE NAME:                                                        */
  1027. /*               Allocate memory for, and obtain a string resource.           */
  1028. /*                                                                            */
  1029. /*   FUNCTION:                                                                */
  1030. /*               This function gets a string resource from the                */
  1031. /*               program file. It accepts as input, the resource ID           */
  1032. /*               of the string to get, and returns a far pointer to           */
  1033. /*               the string in allocated storage. The caller should           */
  1034. /*               free the storage (via free()) when done with the             */
  1035. /*               string.                                                      */
  1036. /*                                                                            */
  1037. /*   NOTES:                                                                   */
  1038. /*                                                                            */
  1039. /*   ENTRY POINT:                                                             */
  1040. /*      LINKAGE:  getstring(ULONG  string_name)                               */
  1041. /*                                                                            */
  1042. /*   INPUT:                                                                   */
  1043. /*      string_name - The resource ID that identifies the string in the       */
  1044. /*                    resource file.                                          */
  1045. /*                                                                            */
  1046. /*   EXIT-NORMAL:                                                             */
  1047. /*      Returns a pointer to the string.                                      */
  1048. /*                                                                            */
  1049. /*   EXIT-ERROR:                                                              */
  1050. /*      Returns a null pointer.  Use WinGetLastError to find the cause.       */
  1051. /*                                                                            */
  1052. /*   EFFECTS:                                                                 */
  1053. /*      Assumptions made include:                                             */
  1054. /*          The maximum width string to be obtained is MAXWIDTH-1 characters. */
  1055. /*          MAXWIDTH is defined in file PMREXX.H.                             */
  1056. /*                                                                            */
  1057. /*   INTERNAL REFERENCES:                                                     */
  1058. /*      ROUTINES:                                                             */
  1059. /*                                                                            */
  1060. /*   EXTERNAL REFERENCES:                                                     */
  1061. /*      ROUTINES:                                                             */
  1062. /*       WinLoadString                                                        */
  1063. /*                                                                            */
  1064. /**************************** END OF SPECIFICATIONS ***************************/
  1065.  
  1066. PUCHAR getstring(ULONG  string_name)
  1067. {
  1068.   UCHAR buffer[MAXWIDTH];
  1069.   ULONG chars;
  1070.  
  1071.   buffer[0] = '\0';
  1072.   /* Get the message into our local buffer, then make a copy to return.      */
  1073.   chars = WinLoadString(hab, (HMODULE)NULL,
  1074.       (ULONG)string_name, MAXWIDTH, buffer);
  1075.   return  strdup((const char *)buffer);
  1076. }
  1077.  
  1078. /************************** START OF SPECIFICATIONS ***************************/
  1079. /*                                                                            */
  1080. /*   SUBROUTINE NAME: init_routine                                            */
  1081. /*                                                                            */
  1082. /*   DESCRIPTIVE NAME:                                                        */
  1083. /*               Process the REXX Initialization exit                         */
  1084. /*                                                                            */
  1085. /*   FUNCTION:                                                                */
  1086. /*               This function has been registered to handle the RXINI exit.  */
  1087. /*               for the REXX procedure. This issues a call to RexxSetTrace   */
  1088. /*               to turn on tracing if it has been requested from the onset.  */
  1089. /*                                                                            */
  1090. /*   NOTES:                                                                   */
  1091. /*                                                                            */
  1092. /*   ENTRY POINT:                                                             */
  1093. /*      LINKAGE:                                                              */
  1094. /*          LONG  init_routine( LONG  exitno, LONG  subfunc, PUCHAR parmblock)*/
  1095. /*                                                                            */
  1096. /*   INPUT:                                                                   */
  1097. /*       The arguments are defined by the REXX interface specifications.      */
  1098. /*                                                                            */
  1099. /*   INTERNAL REFERENCES:                                                     */
  1100. /*      ROUTINES:                                                             */
  1101. /*                                                                            */
  1102. /*   EXTERNAL REFERENCES:                                                     */
  1103. /*      ROUTINES:                                                             */
  1104. /*        RexxSetTrace                                                        */
  1105. /*                                                                            */
  1106. /**************************** END OF SPECIFICATIONS ***************************/
  1107.  
  1108. LONG  init_routine(LONG  exitno, LONG  subfunc, PUCHAR parmblock)
  1109. {
  1110.   if (trace)                           /* tracing at start?                   */
  1111.     RexxSetTrace(proc_id, rexx_tid);   /* turn it on now                      */
  1112.   return RXEXIT_HANDLED;               /* return with no errors               */
  1113. }
  1114.  
  1115. /************************** START OF SPECIFICATIONS ***************************/
  1116. /*                                                                            */
  1117. /*   SUBROUTINE NAME: SetOptions                                              */
  1118. /*                                                                            */
  1119. /*   DESCRIPTIVE NAME:                                                        */
  1120. /*               Enable/disable menu items.                                   */
  1121. /*                                                                            */
  1122. /*   FUNCTION:                                                                */
  1123. /*               This function is called to individually enable or disable a  */
  1124. /*               particular item in the menu structure.                       */
  1125. /*                                                                            */
  1126. /*   NOTES:                                                                   */
  1127. /*                                                                            */
  1128. /*   ENTRY POINT:                                                             */
  1129. /*      LINKAGE:                                                              */
  1130. /*          void SetOptions( ULONG  item, BOOL option )                       */
  1131. /*                                                                            */
  1132. /*   INPUT:                                                                   */
  1133. /*       item           - The id of the item to enable/disable                */
  1134. /*       option         - TRUE to enable the option, FALSE to disable.        */
  1135. /*                                                                            */
  1136. /*   EXIT-NORMAL:                                                             */
  1137. /*                                                                            */
  1138. /*   EXIT-ERROR:                                                              */
  1139. /*                                                                            */
  1140. /*   EFFECTS:                                                                 */
  1141. /*                                                                            */
  1142. /*   INTERNAL REFERENCES:                                                     */
  1143. /*      ROUTINES:                                                             */
  1144. /*                                                                            */
  1145. /*   EXTERNAL REFERENCES:                                                     */
  1146. /*      ROUTINES:                                                             */
  1147. /*       DosSleep                                                             */
  1148. /*       WinPostMsg                                                           */
  1149. /*       WinWindowFromID                                                      */
  1150. /*                                                                            */
  1151. /**************************** END OF SPECIFICATIONS ***************************/
  1152.  
  1153. void SetOptions(ULONG item,BOOL option)
  1154. {
  1155.  
  1156.    /* This call may be issued from a non-PM thread. So we have to use Post    */
  1157.    /*   instead of Send. If the Post fails, give the window procedure a       */
  1158.    /*   chance to empty the message queue and try again.                      */
  1159.  
  1160.   while (!WinPostMsg(WinWindowFromID(hwndFrame, (USHORT)FID_MENU),
  1161.       MM_SETITEMATTR, MPFROM2SHORT(item, TRUE),
  1162.       MPFROM2SHORT(MIA_DISABLED, option? ~MIA_DISABLED:MIA_DISABLED))) {
  1163.     DosSleep(0L);                      /* This give the window thread a chance*/
  1164.                                        /* to run                              */
  1165.   }
  1166. }
  1167.  
  1168.  
  1169. /************************** START OF SPECIFICATIONS ***************************/
  1170. /*                                                                            */
  1171. /*   SUBROUTINE NAME: SetCheckMark                                            */
  1172. /*                                                                            */
  1173. /*   DESCRIPTIVE NAME:                                                        */
  1174. /*               Check/Uncheck menu items.                                    */
  1175. /*                                                                            */
  1176. /*   FUNCTION:                                                                */
  1177. /*               This function is called to place a check mark next to, or    */
  1178. /*               remove a check mark from a particular item in the menu       */
  1179. /*               structure.                                                   */
  1180. /*                                                                            */
  1181. /*   NOTES:                                                                   */
  1182. /*                                                                            */
  1183. /*   ENTRY POINT:                                                             */
  1184. /*      LINKAGE:                                                              */
  1185. /*          void SetCheckMark( ULONG item, BOOL option )                      */
  1186. /*                                                                            */
  1187. /*   INPUT:                                                                   */
  1188. /*       item           - The id of the item to check/uncheck.                */
  1189. /*       option         - TRUE to check the item, FALSE to uncheck.           */
  1190. /*                                                                            */
  1191. /*   EXIT-NORMAL:                                                             */
  1192. /*                                                                            */
  1193. /*   EXIT-ERROR:                                                              */
  1194. /*                                                                            */
  1195. /*   EFFECTS:                                                                 */
  1196. /*                                                                            */
  1197. /*   INTERNAL REFERENCES:                                                     */
  1198. /*      ROUTINES:                                                             */
  1199. /*                                                                            */
  1200. /*   EXTERNAL REFERENCES:                                                     */
  1201. /*      ROUTINES:                                                             */
  1202. /*       DosSleep                                                             */
  1203. /*       WinPostMsg                                                           */
  1204. /*       WinWindowFromID                                                      */
  1205. /**************************** END OF SPECIFICATIONS ***************************/
  1206.  
  1207. void SetCheckMark(ULONG item,BOOL option)
  1208. {
  1209.  
  1210.    /* This call may be issued from a non-PM thread. So we have to use Post    */
  1211.    /*   instead of Send. If the Post fails, give the window procedure a       */
  1212.    /*   chance to empty the message queue and try again.                      */
  1213.  
  1214.   while (!WinPostMsg(WinWindowFromID(hwndFrame, (USHORT)FID_MENU),
  1215.       MM_SETITEMATTR, MPFROM2SHORT(item, TRUE), MPFROM2SHORT(MIA_CHECKED,
  1216.       option?MIA_CHECKED:~MIA_CHECKED))) {
  1217.     DosSleep(0L);                      /* This give the window thread a chance*/
  1218.                                        /* to run                              */
  1219.   }
  1220. }
  1221.  
  1222. /************************** START OF SPECIFICATIONS ***************************/
  1223. /*                                                                            */
  1224. /*   SUBROUTINE NAME:  SysErrorBoxM                                           */
  1225. /*                                                                            */
  1226. /*   DESCRIPTIVE NAME: System Error Box with Message                          */
  1227. /*                                                                            */
  1228. /*   FUNCTION:                                                                */
  1229. /*               Pop up a window with the error information for a base        */
  1230. /*               system error, along with an added user control.              */
  1231. /*                                                                            */
  1232. /*   NOTES:                                                                   */
  1233. /*                                                                            */
  1234. /*   ENTRY POINT:                                                             */
  1235. /*      LINKAGE:                                                              */
  1236. /*          ULONG  SysErrorBoxM(HWND hwndOwner, ULONG  errorcd,               */
  1237. /*                              PSZ message, ULONG  fsStyle )                 */
  1238. /*                                                                            */
  1239. /*   INPUT:                                                                   */
  1240. /*       hwndOwner  -  Owners window handle                                   */
  1241. /*       errorcd    -  Error code                                             */
  1242. /*       message    -  User provided message                                  */
  1243. /*       fsStyle    -  Style flags                                            */
  1244. /*                                                                            */
  1245. /*   EXIT-NORMAL:                                                             */
  1246. /*       returns ID of button pushed.                                         */
  1247. /*                                                                            */
  1248. /*   EXIT-ERROR:                                                              */
  1249. /*                                                                            */
  1250. /*   EFFECTS:                                                                 */
  1251. /*                                                                            */
  1252. /*   INTERNAL REFERENCES:                                                     */
  1253. /*      ROUTINES:                                                             */
  1254. /*                                                                            */
  1255. /*   EXTERNAL REFERENCES:                                                     */
  1256. /*      ROUTINES:                                                             */
  1257. /*       WinMessageBox                                                        */
  1258. /*       DosGetMessage                                                        */
  1259. /*                                                                            */
  1260. /**************************** END OF SPECIFICATIONS ***************************/
  1261.  
  1262. ULONG  SysErrorBoxM(HWND hwndOwner,ULONG  errorcd,PSZ message,ULONG  fsStyle)
  1263. {
  1264.   CHAR *szErrMsg;                      /* Buffer to hold message returned     */
  1265.   CHAR szErrTitle[80];                 /* Buffer to hold title for message box*/
  1266.   ULONG  cbMsg = ONE_K-1;              /* Length of message buffer            */
  1267.   ULONG  rc;                           /* return code variable                */
  1268.   CHAR *msgfile;                       /* Holds name of message file          */
  1269.   CHAR *errformat;                     /* Holds format string for title       */
  1270.  
  1271.  
  1272.   if (!(szErrMsg = malloc(ONE_K)))
  1273.     return 0;                          /* If we couldn't get space, just      */
  1274.                                        /* return                              */
  1275.   errformat = getstring(SYS_ERROR_TEXT);/* Get the format string for msg      */
  1276.   msgfile = getstring(MSG_FILE);       /* Get name of system message file     */
  1277.   sprintf(szErrTitle, errformat, errorcd);
  1278.  
  1279.                                        /* retrieve message with DosGetMessage */
  1280.   rc = DosGetMessage(NULL,             /* pointer to table of character       */
  1281.                                        /* pointers                            */
  1282.                      0,                /* number of pointers in table         */
  1283.                      szErrMsg,         /* pointer to buffer for return message*/
  1284.                      cbMsg+1,          /* length of buffer                    */
  1285.                      errorcd,          /* message number to retrieve          */
  1286.                      msgfile,          /* name of file containing message     */
  1287.                      &cbMsg);          /* length of returned message          */
  1288.  
  1289.   free(errformat);                     /* release string memory               */
  1290.   free(msgfile);
  1291.   szErrMsg[cbMsg] = '\0';              /* terminate message with a NULL       */
  1292.  
  1293.    /************************************************************************
  1294.    * Since the message returned may have imbedded carraige returns and/or  *
  1295.    * linefeeds we must remove them.                                        *
  1296.    ************************************************************************/
  1297.   while (--cbMsg) {
  1298.  
  1299.     if (szErrMsg[cbMsg] == '\n'|szErrMsg[cbMsg] == '\r') {
  1300.       szErrMsg[cbMsg] = ' ';
  1301.     }
  1302.   }
  1303.                                        /* add "user" message to system one    */
  1304.   if (message) {
  1305.     strcat(szErrMsg, "\n");
  1306.     strcat(szErrMsg, message);
  1307.   }
  1308.                                        /* Pop up a Message box                */
  1309.   rc = WinMessageBox(HWND_DESKTOP, hwndOwner, szErrMsg, szErrTitle, 0, fsStyle);
  1310.  
  1311.    /* Free the message buffer, and return.                                    */
  1312.  
  1313.   free(szErrMsg);
  1314.   return  rc;
  1315. }
  1316.  
  1317. /************************** START OF SPECIFICATIONS ***************************/
  1318. /*                                                                            */
  1319. /*   SUBROUTINE NAME: CuaLogoDlgProc                                          */
  1320. /*                                                                            */
  1321. /*   DESCRIPTIVE NAME: Logo Dialog Procedure                                  */
  1322. /*                                                                            */
  1323. /*   FUNCTION:                                                                */
  1324. /*               This routine is the dialog procedure for diaply of the       */
  1325. /*               About dialog.                                                */
  1326. /*                                                                            */
  1327. /*   NOTES:                                                                   */
  1328. /*                                                                            */
  1329. /*   ENTRY POINT:                                                             */
  1330. /*      LINKAGE: Standard Dialog procedure interface.                         */
  1331. /*                                                                            */
  1332. /*   INPUT: Standard Dialog procedure interface.                              */
  1333. /*                                                                            */
  1334. /*   EXIT-NORMAL:                                                             */
  1335. /*                                                                            */
  1336. /*   EXIT-ERROR:                                                              */
  1337. /*                                                                            */
  1338. /*   EFFECTS:                                                                 */
  1339. /*                                                                            */
  1340. /*   INTERNAL REFERENCES:                                                     */
  1341. /*      ROUTINES:                                                             */
  1342. /*                                                                            */
  1343. /*   EXTERNAL REFERENCES:                                                     */
  1344. /*      ROUTINES:                                                             */
  1345. /*        WinDefDlgProc                                                       */
  1346. /*        WinDismissDlg                                                       */
  1347. /*                                                                            */
  1348. /**************************** END OF SPECIFICATIONS ***************************/
  1349.  
  1350. MRESULT EXPENTRY CuaLogoDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  1351. {
  1352.     LONG timeout;
  1353.     HINI hini;
  1354.     LONG ldefault = 2000;               /* Default logo to 2 seconds  @D08*/
  1355.     UCHAR buffer[MAXWIDTH];
  1356.  
  1357.     switch(msg)
  1358.     {
  1359.        case WM_INITDLG:
  1360.           if (mp2) {                    /* @C07A */
  1361.              hini = HINI_PROFILE;
  1362.              timeout = PrfQueryProfileInt(hini,(PSZ)"PM_ControlPanel", (PSZ)"LogoDisplayTime", ldefault);
  1363.              if (timeout == 0)
  1364.              {
  1365.                WinDismissDlg (hwnd,TRUE);
  1366.                break;
  1367.              }
  1368.              else WinStartTimer(hab, hwnd, 0, (ULONG) timeout);
  1369.                                   /* start a time of required duration */
  1370.           } /* endif */
  1371.           return ( (MRESULT) FALSE);
  1372.  
  1373.         case WM_COMMAND:
  1374.             break;
  1375.  
  1376.         case WM_TIMER:               /* @C07A */
  1377.             WinStopTimer(hab, hwnd, 0);
  1378.             WinDismissDlg(hwnd, TRUE);
  1379.             break;
  1380.     }
  1381.     return(WinDefDlgProc(hwnd,msg,mp1,mp2));
  1382. }
  1383. /************************** START OF SPECIFICATIONS ***************************/
  1384. /*                                                                            */
  1385. /*   SUBROUTINE NAME:  SysErrorBox                                            */
  1386. /*                                                                            */
  1387. /*   DESCRIPTIVE NAME: System Error Box                                       */
  1388. /*                                                                            */
  1389. /*   FUNCTION:                                                                */
  1390. /*               Pop up a window with the error information for a base        */
  1391. /*               system error.                                                */
  1392. /*                                                                            */
  1393. /*   NOTES:                                                                   */
  1394. /*                                                                            */
  1395. /*   ENTRY POINT:                                                             */
  1396. /*      LINKAGE:                                                              */
  1397. /*          ULONG  SysErrorBox(HWND hwnd, ULONG  errorcd, PSZ message)        */
  1398. /*                                                                            */
  1399. /*   INPUT:                                                                   */
  1400. /*       hwndOwner  -  Owners window handle                                   */
  1401. /*       errorcd    -  Error code                                             */
  1402. /*       message    -  User provided message                                  */
  1403. /*                                                                            */
  1404. /*   EXIT-NORMAL:                                                             */
  1405. /*                                                                            */
  1406. /*   EXIT-ERROR:                                                              */
  1407. /*                                                                            */
  1408. /*   EFFECTS:                                                                 */
  1409. /*                                                                            */
  1410. /*   INTERNAL REFERENCES:                                                     */
  1411. /*      ROUTINES:                                                             */
  1412. /*                                                                            */
  1413. /*   EXTERNAL REFERENCES:                                                     */
  1414. /*      ROUTINES:                                                             */
  1415. /*       DosSleep                                                             */
  1416. /*       WinPostMsg                                                           */
  1417. /**************************** END OF SPECIFICATIONS ***************************/
  1418.  
  1419. void SysErrorBox(HWND hwnd,ULONG  errorcd,PUCHAR message)
  1420.  
  1421. {
  1422.  
  1423.    /***************************************************************************/
  1424.    /* This call may be issued from a non-PM thread. So we have to use Post    */
  1425.    /*   instead of Send. If the Post fails, give the window procedure a       */
  1426.    /*   chance to empty the message queue and try again.                      */
  1427.    /***************************************************************************/
  1428.  
  1429.   while (!WinPostMsg(hwnd, DOS_ERROR, message,
  1430.        MPFROM2SHORT(errorcd, MB_CANCEL|MB_ICONEXCLAMATION))) {
  1431.     DosSleep(0L);                      /* This give the window thread a chance*/
  1432.                                        /* to run                              */
  1433.   }                                    /* endwhile                            */
  1434. }
  1435.  
  1436. /************************** START OF SPECIFICATIONS ***************************/
  1437. /*                                                                            */
  1438. /*   SUBROUTINE NAME: ProcessSaveQuit                                         */
  1439. /*                                                                            */
  1440. /*   DESCRIPTIVE NAME: Set up call to Save/Quit dialog.                       */
  1441. /*                                                                            */
  1442. /*   FUNCTION:                                                                */
  1443. /*               Checks to see if the output in the MLE has changed since the */
  1444. /*               last save, and if so brings up the Save/Quit dialog.         */
  1445. /*                                                                            */
  1446. /*   NOTES:                                                                   */
  1447. /*                                                                            */
  1448. /*   ENTRY POINT:                                                             */
  1449. /*      LINKAGE: ULONG  ProcessSaveQuit                                       */
  1450. /*                                                                            */
  1451. /*   INPUT:                                                                   */
  1452. /*      HWND hWnd - window handle                                             */
  1453. /*                                                                            */
  1454. /*   EXIT-NORMAL:                                                             */
  1455. /*      Returns TRUE if processed correctly                                   */
  1456. /*                                                                            */
  1457. /*   EXIT-ERROR:                                                              */
  1458. /*      Returns FALSE otherwise                                               */
  1459. /*                                                                            */
  1460. /*   EFFECTS:                                                                 */
  1461. /*                                                                            */
  1462. /*   INTERNAL REFERENCES:                                                     */
  1463. /*      ROUTINES:                                                             */
  1464. /*       SaveQuit - Bring up Save/Quit/Cancel Dialog                          */
  1465. /*                                                                            */
  1466. /*   EXTERNAL REFERENCES:                                                     */
  1467. /*      ROUTINES:                                                             */
  1468. /*       WinDestroyWindow                                                     */
  1469. /*       WinInvalidateRect                                                    */
  1470. /*       WinQueryWindowULong                                                  */
  1471. /*       WinSendMsg                                                           */
  1472. /*       WinWindowFromID                                                      */
  1473. /*                                                                            */
  1474. /**************************** END OF SPECIFICATIONS ***************************/
  1475.  
  1476.   ULONG  ProcessSaveQuit(HWND hwnd)
  1477.   {
  1478.     HWND hEdit;
  1479.     ULONG  usRetVal;
  1480.  
  1481.     hEdit = WinWindowFromID(hwnd, MLE_WNDW);
  1482.  
  1483.     if (WinSendMsg(hEdit, MLM_QUERYCHANGED, NULL, NULL)) {
  1484.       usRetVal = (ULONG )SaveQuit(hab, hwnd, pszFileName);
  1485.     }
  1486.     else {
  1487.       usRetVal = 1;
  1488.     }
  1489.  
  1490.     return (usRetVal);
  1491.   }
  1492.