home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / warptlk3.zip / TOOLKIT / SAMPLES / REXX / API / PMREXX / PMREXX.C next >
C/C++ Source or Header  |  1995-08-24  |  88KB  |  1,490 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.         WinPostMsg( hwndFrame, WM_QUIT, 0L, 0L );
  681.         break;
  682.         
  683.       case  RXHB_MSGBOX : {            /* Put up a message box. The mp1       */
  684.                                        /* parameter has the resource ids for  */
  685.                                        /* the message and the title.          */
  686.           USHORT msgid = SHORT1FROMMP(mp1);
  687.           PUCHAR header = getstring(SHORT2FROMMP(mp1));
  688.           PUCHAR content = getstring(SHORT1FROMMP(mp1));/* If we are          */
  689.                                        /* displaying the ended message, set   */
  690.                                        /* the owner to the desktop so we don't*/
  691.                                        /* steal the focus back from other     */
  692.                                        /* apps.                               */
  693.  
  694.           LONG  rc = WinMessageBox(HWND_DESKTOP,
  695.               (RXHM_PROC_ENDED == msgid?HWND_DESKTOP: hwnd),
  696.               content, header, msgid, SHORT1FROMMP(mp2));
  697.           free(header);
  698.           free(content);
  699.           return  MPFROMSHORT(rc);
  700.         }
  701.         break;
  702.  
  703.       case  WM_CLOSE :
  704.  
  705.          /* Check to see if the window needs to be saved, but only if the     */
  706.          /* user has entered a filename, otherwise just exit.                 */
  707.  
  708.         if ((!strlen(pszFileName)) || ProcessSaveQuit(hwnd)) {
  709.           WinSendMsg(hwndClient, WM_SAVEAPPLICATION, NULL, NULL);
  710.           WinPostMsg( hwndFrame, WM_QUIT, 0L, 0L );
  711.           return (MRESULT)(FALSE);
  712.         }
  713.  
  714.         else {                         /* Don't Close if Cancel on            */
  715.                                        /* ProcessSaveQuit                     */
  716.           return (MRESULT)(TRUE);
  717.         }
  718.         break;
  719.  
  720.       default  :
  721.         break;
  722.     }
  723.     return (*SuperProc)(hwnd, msg, mp1, mp2);
  724. }
  725.  
  726. /************************** START OF SPECIFICATIONS ***************************/
  727. /*                                                                            */
  728. /*   SUBROUTINE NAME: PMRXCmds                                                */
  729. /*                                                                            */
  730. /*   DESCRIPTIVE NAME:                                                        */
  731. /*               Process WM_COMMAND messages for the window procedure.        */
  732. /*                                                                            */
  733. /*   FUNCTION:                                                                */
  734. /*               This routine processes all the WM_COMMAND messages that have */
  735. /*               are handled by the Subclassed window.  Messages handled are: */
  736. /*                                                                            */
  737. /*       PMRXA_RESTART  - This requests that the REXX procedure be re-run.    */
  738. /*                        This command is only valid if the previous instance */
  739. /*                        of the procedure has ended.                         */
  740. /*       PMRXA_EXIT     - This is a request to close the application.         */
  741. /*       PMRXA_SAVEAS   - Save the MLE to the same file as last time.         */
  742. /*       PMRXA_SAVE     - Present the user with a dialog to select a file for */
  743. /*                        saving the MLE.                                     */
  744. /*       PMRXA_ABOUT    - Present the About dialog.                           */
  745. /*                                                                            */
  746. /*   NOTES:                                                                   */
  747. /*                                                                            */
  748. /*   ENTRY POINT:                                                             */
  749. /*      LINKAGE:                                                              */
  750. /*       MRESULT PMRXCmds(HWND hwnd, MPARAM mp1, MPARAM MP2)                  */
  751. /*                                                                            */
  752. /*   INPUT:                                                                   */
  753. /*       hwnd           - The window handle of the window that received the   */
  754. /*                        command.                                            */
  755. /*       mp1            - The first parameter of the WM_COMMAND message.      */
  756. /*       mp2            - The second parameter of the WM_COMMAND message.     */
  757. /*                                                                            */
  758. /*   EXIT-NORMAL:                                                             */
  759. /*       returns TRUE if the file was saved successfully or user response     */
  760. /*       from SAVEAS dialog.                                                  */
  761. /*   EXIT-ERROR:                                                              */
  762. /*       returns FALSE if the file was not saved successfully.                */
  763. /*                                                                            */
  764. /*   EFFECTS:                                                                 */
  765. /*                                                                            */
  766. /*   INTERNAL REFERENCES:                                                     */
  767. /*      ROUTINES:                                                             */
  768. /*       getstring      - Retrieve a string resource                          */
  769. /*       SelectFile     - Interface to the file selection dialog              */
  770. /*       SetCheckMark   - Check/uncheck a menu item                           */
  771. /*       WriteFile      - Write the data from the MLE into a file             */
  772. /*                                                                            */
  773. /*                                                                            */
  774. /*   EXTERNAL REFERENCES:                                                     */
  775. /*      ROUTINES:                                                             */
  776. /*       WinAlarm                       WinPostMessage                        */
  777. /*       WinSendMsg                     WinLoadString                         */
  778. /*       WinDlgBox                      WinWindowFromID                       */
  779. /*                                                                            */
  780. /**************************** END OF SPECIFICATIONS ***************************/
  781.  
  782. MRESULT PMRXCmds(HWND hwnd, MPARAM mp1, MPARAM mp2)
  783. {
  784.     CHAR pszFMask[FNAME_SIZE];         /* buffer to hold mask for wildcard    */
  785.                                        /* searches                            */
  786.     CHAR pszTitle[TITLE_SIZE];         /* text for Save As title bar          */
  787.     CHAR pszFName[FNAME_SIZE];         /* buffer for formatted filename       */
  788.     CHAR Temp = '\0';                  /* temporary character                 */
  789.     ULONG  UserResponse;               /* holds user response from Save As    */
  790.     ULONG  usFileSize;
  791.                                        
  792.  
  793.  
  794.     switch (LOUSHORT(mp1)) {
  795.  
  796.       /************************************************************************/
  797.       /* Flip the trace flag                                                  */
  798.       /************************************************************************/
  799.  
  800.       case  PMRXA_FLAGCHANGE:
  801.         if (mp2 == 0) {
  802.            trace = FALSE;
  803.         } else {
  804.            trace = TRUE;
  805.         } /* endif */
  806.         break;
  807.  
  808.       /************************************************************************/
  809.       /* Flip the result flag                                                 */
  810.       /************************************************************************/
  811.  
  812.       case  PMRXA_RESULTCHANGE:
  813.  
  814.         Results = !Results;
  815.         break;
  816.  
  817.       /************************************************************************/
  818.       /* Rerun the program                                                    */
  819.       /************************************************************************/
  820.  
  821.       case  PMRXA_RESTART :
  822.         if (!Results) {
  823.  
  824.           WinEnableWindowUpdate(hwnd, FALSE);
  825.                                        /* disable updates Get length of the   */
  826.                                        /* output in the MLE                   */
  827.           usFileSize = (ULONG )WinSendMsg(WinWindowFromID(hwnd,
  828.                                           (USHORT)MLE_WNDW),
  829.                                           MLM_QUERYTEXTLENGTH,
  830.                                           (MPARAM)0, (MPARAM)0);
  831.                                        /* Select all of the output in the MLE */
  832.           WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  833.                      MLM_DELETE, (MPARAM)0L, MPFROMSHORT(usFileSize));
  834.           WinInvalidateRect(hwnd, NULL, TRUE);
  835.                                        /* update the window                   */
  836.           WinEnableWindowUpdate(hwnd, TRUE);
  837.                                        /* Make MLE so that it can't be undone */
  838.           WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  839.                      MLM_RESETUNDO, (MPARAM)0, (MPARAM)0);
  840.         } /* endif */
  841.  
  842.         DosCreateThread(&rexx_tid, (PFNTHREAD)CallRexx, (ULONG)0, (ULONG)0,
  843.             STACK_SIZE);
  844.  
  845.         break;
  846.  
  847.       /************************************************************************/
  848.       /* Shutdown and get out                                                 */
  849.       /************************************************************************/
  850.  
  851.       case PMRXA_EXIT:
  852.  
  853.          WinPostMsg( hwnd, WM_CLOSE, 0L, 0L );
  854.          break;
  855.  
  856.       /************************************************************************/
  857.       /* Save the file according to user file specification                   */
  858.       /************************************************************************/
  859.  
  860.       case  PMRXA_SAVE :
  861.  
  862.         WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  863.             MLM_RESETUNDO, (MPARAM)0, (MPARAM)0);
  864.  
  865.         if (!strlen(pszFileName)) {    /* User hasn't added a filename  */
  866.                                        /* yet, so put up the Save As dialog   */
  867.           WinSendMsg(hwnd, WM_COMMAND, MPFROMSHORT(PMRXA_SAVEAS), (MPARAM)0);
  868.         }
  869.  
  870.         else {                         /* We have the filename, so just write */
  871.                                        /* it out.                             */
  872.  
  873.           if (WriteFile(hab, hwnd, pszFileName, procname, FALSE)) {
  874.             WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  875.                        MLM_SETCHANGED, MPFROMSHORT(FALSE), (MPARAM)0);
  876.             return (MRESULT)(TRUE);
  877.           }
  878.  
  879.           else {
  880.             return (MRESULT)(FALSE);
  881.           }
  882.         }
  883.         break;
  884.  
  885.       /************************************************************************/
  886.       /* Bring up the Save As dialog to get the filename                      */
  887.       /************************************************************************/
  888.  
  889.       case  PMRXA_SAVEAS :
  890.         WinLoadString(hab, (HMODULE)NULL, PMRXHB_SAVETITLE,
  891.             sizeof(pszTitle), pszTitle);
  892.         WinLoadString(hab, (HMODULE)NULL, PMRXHB_FILEMASK,
  893.             sizeof(pszFMask), pszFMask);
  894.         *pszFName = '\0';
  895.  
  896.         if (ESCAPE != (UserResponse = SelectFile( pszTitle,
  897.             pszFMask, pszFName))) {
  898.  
  899.           if (WriteFile(hab, hwnd, pszFName, procname, TRUE)) {
  900.             WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  901.                        MLM_SETCHANGED, MPFROMSHORT(FALSE), NULL);
  902.             strcpy(pszFileName, pszFName);
  903.           }
  904.         }
  905.         WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  906.                    MLM_RESETUNDO, (MPARAM)0, (MPARAM)0);
  907.         return (MRESULT)(UserResponse);
  908.         break;
  909.  
  910.       /************************************************************************/
  911.       /* Display the About dialog.                                            */
  912.       /************************************************************************/
  913.  
  914.       case  PMRXA_ABOUT :
  915.  
  916.         WinDlgBox(HWND_DESKTOP, hwndFrame, (PFNWP)CuaLogoDlgProc,
  917.                        (HMODULE)0, PMREXX_CUALOGO, (PVOID)NULL);
  918.         break;
  919.  
  920.  
  921.       /************************************************************************/
  922.       /* Option not handled here, pass on to default win proc                 */
  923.       /************************************************************************/
  924.  
  925.       default  :
  926.         return (*SuperProc)(hwnd, WM_COMMAND, mp1, mp2);
  927.     }
  928. }
  929.  
  930. /************************** START OF SPECIFICATIONS ***************************/
  931. /*                                                                            */
  932. /*   SUBROUTINE NAME: SelectFile                                              */
  933. /*                                                                            */
  934. /*   DESCRIPTIVE NAME: Bring up Select File dialog procedure.                 */
  935. /*                                                                            */
  936. /*   FUNCTION:                                                                */
  937. /*               This routine sets up the file structure before calling the   */
  938. /*               file selection dialog.                                       */
  939. /*                                                                            */
  940. /*   NOTES:                                                                   */
  941. /*                                                                            */
  942. /*   ENTRY POINT:                                                             */
  943. /*      LINKAGE: ULONG  SelectFile                                            */
  944. /*                                                                            */
  945. /*   INPUT:                                                                   */
  946. /*      PSZ pszTitle - current title text                                     */
  947. /*      PSZ pszFileMask - file mask to search for                             */
  948. /*      PSZ pszFName - filename (returned)                                    */
  949. /*                                                                            */
  950. /*   EXIT-NORMAL:                                                             */
  951. /*      Returns ENTER or ESCAPE                                               */
  952. /*                                                                            */
  953. /*   EXIT-ERROR:                                                              */
  954. /*      None.                                                                 */
  955. /*                                                                            */
  956. /*   EFFECTS:                                                                 */
  957. /*                                                                            */
  958. /*   INTERNAL REFERENCES:                                                     */
  959. /*      ROUTINES:                                                             */
  960. /*        getstring                                                           */
  961. /*                                                                            */
  962. /*   EXTERNAL REFERENCES:                                                     */
  963. /*      ROUTINES:                                                             */
  964. /*        WinFileDlg                                                          */
  965. /*                                                                            */
  966. /**************************** END OF SPECIFICATIONS ***************************/
  967.  
  968.   ULONG  SelectFile(PSZ pszTitle, PSZ pszFileMask, PSZ pszFName) {
  969.     BOOL     fSuccess = FALSE;
  970.     HWND     hwndDlg;                  /* file dialog handle                  */
  971.     FILEDLG  fdl;                      /* open/saveas dialog data             */
  972.     PSZ      pszDefaultDrive = NULL ;
  973.     static   PSZ   ppszDefaultDriveList[] = { NULL } ;
  974.     PSZ      pszDefaultEAType = NULL ;
  975.     static   PSZ   ppszDefaultEATypeList[] = { NULL } ;
  976.  
  977.  
  978.   fdl.pfnDlgProc     = NULL;
  979.   fdl.cbSize         = sizeof(FILEDLG);
  980.   fdl.fl             = FDS_HELPBUTTON | FDS_CENTER | FDS_SAVEAS_DIALOG | FDS_ENABLEFILELB ;
  981.   fdl.ulUser         = 0L ;
  982.   fdl.lReturn        = 0L;
  983.   fdl.lSRC           = FDS_SUCCESSFUL ;
  984.   fdl.hMod           = (HMODULE)NULL ;
  985.   fdl.usDlgId        = 0 ;
  986.   fdl.x              = 0 ;
  987.   fdl.y              = 0 ;
  988.   fdl.pszIDrive      = pszDefaultDrive ;
  989.   fdl.papszIDriveList= (PAPSZ) ppszDefaultDriveList ;
  990.   fdl.pszIType       = pszDefaultEAType ;
  991.   fdl.papszITypeList = (PAPSZ) ppszDefaultEATypeList ;
  992.   fdl.pszOKButton    = NULL;
  993.  
  994.   strcpy(fdl.szFullFile, pszFileMask);
  995.   fdl.pszTitle = pszTitle;
  996.  
  997.   /* Call the Standard Open/SaveAs Dialog Procedure. */
  998.  
  999.   hwndDlg = WinFileDlg(HWND_DESKTOP, hwndClient, &fdl);  
  1000.  
  1001.   /* Check which button was selected. */
  1002.  
  1003.   switch ((SHORT)fdl.lReturn) {
  1004.  
  1005.     case DID_OK_PB:
  1006.       strcpy(pszFName, fdl.szFullFile);
  1007.       fSuccess = TRUE;
  1008.       break;
  1009.  
  1010.     case DID_CANCEL_PB:
  1011.       fSuccess = FALSE;
  1012.       break ;
  1013.   }
  1014.  
  1015.   return fSuccess;
  1016. }
  1017.  
  1018. /************************** START OF SPECIFICATIONS ***************************/
  1019. /*                                                                            */
  1020. /*   SUBROUTINE NAME: getstring                                               */
  1021. /*                                                                            */
  1022. /*   DESCRIPTIVE NAME:                                                        */
  1023. /*               Allocate memory for, and obtain a string resource.           */
  1024. /*                                                                            */
  1025. /*   FUNCTION:                                                                */
  1026. /*               This function gets a string resource from the                */
  1027. /*               program file. It accepts as input, the resource ID           */
  1028. /*               of the string to get, and returns a far pointer to           */
  1029. /*               the string in allocated storage. The caller should           */
  1030. /*               free the storage (via free()) when done with the             */
  1031. /*               string.                                                      */
  1032. /*                                                                            */
  1033. /*   NOTES:                                                                   */
  1034. /*                                                                            */
  1035. /*   ENTRY POINT:                                                             */
  1036. /*      LINKAGE:  getstring(ULONG  string_name)                               */
  1037. /*                                                                            */
  1038. /*   INPUT:                                                                   */
  1039. /*      string_name - The resource ID that identifies the string in the       */
  1040. /*                    resource file.                                          */
  1041. /*                                                                            */
  1042. /*   EXIT-NORMAL:                                                             */
  1043. /*      Returns a pointer to the string.                                      */
  1044. /*                                                                            */
  1045. /*   EXIT-ERROR:                                                              */
  1046. /*      Returns a null pointer.  Use WinGetLastError to find the cause.       */
  1047. /*                                                                            */
  1048. /*   EFFECTS:                                                                 */
  1049. /*      Assumptions made include:                                             */
  1050. /*          The maximum width string to be obtained is MAXWIDTH-1 characters. */
  1051. /*          MAXWIDTH is defined in file PMREXX.H.                             */
  1052. /*                                                                            */
  1053. /*   INTERNAL REFERENCES:                                                     */
  1054. /*      ROUTINES:                                                             */
  1055. /*                                                                            */
  1056. /*   EXTERNAL REFERENCES:                                                     */
  1057. /*      ROUTINES:                                                             */
  1058. /*       WinLoadString                                                        */
  1059. /*                                                                            */
  1060. /**************************** END OF SPECIFICATIONS ***************************/
  1061.  
  1062. PUCHAR getstring(ULONG  string_name)
  1063. {
  1064.   UCHAR buffer[MAXWIDTH];
  1065.   ULONG chars;
  1066.  
  1067.   buffer[0] = '\0';
  1068.   /* Get the message into our local buffer, then make a copy to return.      */
  1069.   chars = WinLoadString(hab, (HMODULE)NULL,
  1070.       (ULONG)string_name, MAXWIDTH, buffer);
  1071.   return  strdup((const char *)buffer);
  1072. }
  1073.  
  1074. /************************** START OF SPECIFICATIONS ***************************/
  1075. /*                                                                            */
  1076. /*   SUBROUTINE NAME: init_routine                                            */
  1077. /*                                                                            */
  1078. /*   DESCRIPTIVE NAME:                                                        */
  1079. /*               Process the REXX Initialization exit                         */
  1080. /*                                                                            */
  1081. /*   FUNCTION:                                                                */
  1082. /*               This function has been registered to handle the RXINI exit.  */
  1083. /*               for the REXX procedure. This issues a call to RexxSetTrace   */
  1084. /*               to turn on tracing if it has been requested from the onset.  */
  1085. /*                                                                            */
  1086. /*   NOTES:                                                                   */
  1087. /*                                                                            */
  1088. /*   ENTRY POINT:                                                             */
  1089. /*      LINKAGE:                                                              */
  1090. /*          LONG  init_routine( LONG  exitno, LONG  subfunc, PUCHAR parmblock)*/
  1091. /*                                                                            */
  1092. /*   INPUT:                                                                   */
  1093. /*       The arguments are defined by the REXX interface specifications.      */
  1094. /*                                                                            */
  1095. /*   INTERNAL REFERENCES:                                                     */
  1096. /*      ROUTINES:                                                             */
  1097. /*                                                                            */
  1098. /*   EXTERNAL REFERENCES:                                                     */
  1099. /*      ROUTINES:                                                             */
  1100. /*        RexxSetTrace                                                        */
  1101. /*                                                                            */
  1102. /**************************** END OF SPECIFICATIONS ***************************/
  1103.  
  1104. LONG  init_routine(LONG  exitno, LONG  subfunc, PUCHAR parmblock)
  1105. {
  1106.   if (trace)                           /* tracing at start?                   */
  1107.     RexxSetTrace(proc_id, rexx_tid);   /* turn it on now                      */
  1108.   else 
  1109.     RexxResetTrace(proc_id, rexx_tid);
  1110.   return RXEXIT_HANDLED;               /* return with no errors               */
  1111. }
  1112.  
  1113. /************************** START OF SPECIFICATIONS ***************************/
  1114. /*                                                                            */
  1115. /*   SUBROUTINE NAME: SetOptions                                              */
  1116. /*                                                                            */
  1117. /*   DESCRIPTIVE NAME:                                                        */
  1118. /*               Enable/disable menu items.                                   */
  1119. /*                                                                            */
  1120. /*   FUNCTION:                                                                */
  1121. /*               This function is called to individually enable or disable a  */
  1122. /*               particular item in the menu structure.                       */
  1123. /*                                                                            */
  1124. /*   NOTES:                                                                   */
  1125. /*                                                                            */
  1126. /*   ENTRY POINT:                                                             */
  1127. /*      LINKAGE:                                                              */
  1128. /*          void SetOptions( ULONG  item, BOOL option )                       */
  1129. /*                                                                            */
  1130. /*   INPUT:                                                                   */
  1131. /*       item           - The id of the item to enable/disable                */
  1132. /*       option         - TRUE to enable the option, FALSE to disable.        */
  1133. /*                                                                            */
  1134. /*   EXIT-NORMAL:                                                             */
  1135. /*                                                                            */
  1136. /*   EXIT-ERROR:                                                              */
  1137. /*                                                                            */
  1138. /*   EFFECTS:                                                                 */
  1139. /*                                                                            */
  1140. /*   INTERNAL REFERENCES:                                                     */
  1141. /*      ROUTINES:                                                             */
  1142. /*                                                                            */
  1143. /*   EXTERNAL REFERENCES:                                                     */
  1144. /*      ROUTINES:                                                             */
  1145. /*       DosSleep                                                             */
  1146. /*       WinPostMsg                                                           */
  1147. /*       WinWindowFromID                                                      */
  1148. /*                                                                            */
  1149. /**************************** END OF SPECIFICATIONS ***************************/
  1150.  
  1151. void SetOptions(ULONG item,BOOL option)
  1152. {
  1153.  
  1154.    /* This call may be issued from a non-PM thread. So we have to use Post    */
  1155.    /*   instead of Send. If the Post fails, give the window procedure a       */
  1156.    /*   chance to empty the message queue and try again.                      */
  1157.  
  1158.   while (!WinPostMsg(WinWindowFromID(hwndFrame, (USHORT)FID_MENU),
  1159.       MM_SETITEMATTR, MPFROM2SHORT(item, TRUE),
  1160.       MPFROM2SHORT(MIA_DISABLED, option? ~MIA_DISABLED:MIA_DISABLED))) {
  1161.     DosSleep(0L);                      /* This give the window thread a chance*/
  1162.                                        /* to run                              */
  1163.   }
  1164. }
  1165.  
  1166.  
  1167. /************************** START OF SPECIFICATIONS ***************************/
  1168. /*                                                                            */
  1169. /*   SUBROUTINE NAME: SetCheckMark                                            */
  1170. /*                                                                            */
  1171. /*   DESCRIPTIVE NAME:                                                        */
  1172. /*               Check/Uncheck menu items.                                    */
  1173. /*                                                                            */
  1174. /*   FUNCTION:                                                                */
  1175. /*               This function is called to place a check mark next to, or    */
  1176. /*               remove a check mark from a particular item in the menu       */
  1177. /*               structure.                                                   */
  1178. /*                                                                            */
  1179. /*   NOTES:                                                                   */
  1180. /*                                                                            */
  1181. /*   ENTRY POINT:                                                             */
  1182. /*      LINKAGE:                                                              */
  1183. /*          void SetCheckMark( ULONG item, BOOL option )                      */
  1184. /*                                                                            */
  1185. /*   INPUT:                                                                   */
  1186. /*       item           - The id of the item to check/uncheck.                */
  1187. /*       option         - TRUE to check the item, FALSE to uncheck.           */
  1188. /*                                                                            */
  1189. /*   EXIT-NORMAL:                                                             */
  1190. /*                                                                            */
  1191. /*   EXIT-ERROR:                                                              */
  1192. /*                                                                            */
  1193. /*   EFFECTS:                                                                 */
  1194. /*                                                                            */
  1195. /*   INTERNAL REFERENCES:                                                     */
  1196. /*      ROUTINES:                                                             */
  1197. /*                                                                            */
  1198. /*   EXTERNAL REFERENCES:                                                     */
  1199. /*      ROUTINES:                                                             */
  1200. /*       DosSleep                                                             */
  1201. /*       WinPostMsg                                                           */
  1202. /*       WinWindowFromID                                                      */
  1203. /**************************** END OF SPECIFICATIONS ***************************/
  1204.  
  1205. void SetCheckMark(ULONG item,BOOL option)
  1206. {
  1207.  
  1208.    /* This call may be issued from a non-PM thread. So we have to use Post    */
  1209.    /*   instead of Send. If the Post fails, give the window procedure a       */
  1210.    /*   chance to empty the message queue and try again.                      */
  1211.  
  1212.   while (!WinPostMsg(WinWindowFromID(hwndFrame, (USHORT)FID_MENU),
  1213.       MM_SETITEMATTR, MPFROM2SHORT(item, TRUE), MPFROM2SHORT(MIA_CHECKED,
  1214.       option?MIA_CHECKED:~MIA_CHECKED))) {
  1215.     DosSleep(0L);                      /* This give the window thread a chance*/
  1216.                                        /* to run                              */
  1217.   }
  1218. }
  1219.  
  1220. /************************** START OF SPECIFICATIONS ***************************/
  1221. /*                                                                            */
  1222. /*   SUBROUTINE NAME:  SysErrorBoxM                                           */
  1223. /*                                                                            */
  1224. /*   DESCRIPTIVE NAME: System Error Box with Message                          */
  1225. /*                                                                            */
  1226. /*   FUNCTION:                                                                */
  1227. /*               Pop up a window with the error information for a base        */
  1228. /*               system error, along with an added user control.              */
  1229. /*                                                                            */
  1230. /*   NOTES:                                                                   */
  1231. /*                                                                            */
  1232. /*   ENTRY POINT:                                                             */
  1233. /*      LINKAGE:                                                              */
  1234. /*          ULONG  SysErrorBoxM(HWND hwndOwner, ULONG  errorcd,               */
  1235. /*                              PSZ message, ULONG  fsStyle )                 */
  1236. /*                                                                            */
  1237. /*   INPUT:                                                                   */
  1238. /*       hwndOwner  -  Owners window handle                                   */
  1239. /*       errorcd    -  Error code                                             */
  1240. /*       message    -  User provided message                                  */
  1241. /*       fsStyle    -  Style flags                                            */
  1242. /*                                                                            */
  1243. /*   EXIT-NORMAL:                                                             */
  1244. /*       returns ID of button pushed.                                         */
  1245. /*                                                                            */
  1246. /*   EXIT-ERROR:                                                              */
  1247. /*                                                                            */
  1248. /*   EFFECTS:                                                                 */
  1249. /*                                                                            */
  1250. /*   INTERNAL REFERENCES:                                                     */
  1251. /*      ROUTINES:                                                             */
  1252. /*                                                                            */
  1253. /*   EXTERNAL REFERENCES:                                                     */
  1254. /*      ROUTINES:                                                             */
  1255. /*       WinMessageBox                                                        */
  1256. /*       DosGetMessage                                                        */
  1257. /*                                                                            */
  1258. /**************************** END OF SPECIFICATIONS ***************************/
  1259.  
  1260. ULONG  SysErrorBoxM(HWND hwndOwner,ULONG  errorcd,PSZ message,ULONG  fsStyle)
  1261. {
  1262.   CHAR *szErrMsg;                      /* Buffer to hold message returned     */
  1263.   CHAR szErrTitle[80];                 /* Buffer to hold title for message box*/
  1264.   ULONG  cbMsg = ONE_K-1;              /* Length of message buffer            */
  1265.   ULONG  rc;                           /* return code variable                */
  1266.   CHAR *msgfile;                       /* Holds name of message file          */
  1267.   CHAR *errformat;                     /* Holds format string for title       */
  1268.  
  1269.  
  1270.   if (!(szErrMsg = malloc(ONE_K)))
  1271.     return 0;                          /* If we couldn't get space, just      */
  1272.                                        /* return                              */
  1273.   errformat = getstring(SYS_ERROR_TEXT);/* Get the format string for msg      */
  1274.   msgfile = getstring(MSG_FILE);       /* Get name of system message file     */
  1275.   sprintf(szErrTitle, errformat, errorcd);
  1276.  
  1277.                                        /* retrieve message with DosGetMessage */
  1278.   rc = DosGetMessage(NULL,             /* pointer to table of character       */
  1279.                                        /* pointers                            */
  1280.                      0,                /* number of pointers in table         */
  1281.                      szErrMsg,         /* pointer to buffer for return message*/
  1282.                      cbMsg+1,          /* length of buffer                    */
  1283.                      errorcd,          /* message number to retrieve          */
  1284.                      msgfile,          /* name of file containing message     */
  1285.                      &cbMsg);          /* length of returned message          */
  1286.  
  1287.   free(errformat);                     /* release string memory               */
  1288.   free(msgfile);
  1289.   szErrMsg[cbMsg] = '\0';              /* terminate message with a NULL       */
  1290.  
  1291.    /************************************************************************
  1292.    * Since the message returned may have imbedded carraige returns and/or  *
  1293.    * linefeeds we must remove them.                                        *
  1294.    ************************************************************************/
  1295.   while (--cbMsg) {
  1296.  
  1297.     if (szErrMsg[cbMsg] == '\n'|szErrMsg[cbMsg] == '\r') {
  1298.       szErrMsg[cbMsg] = ' ';
  1299.     }
  1300.   }
  1301.                                        /* add "user" message to system one    */
  1302.   if (message) {
  1303.     strcat(szErrMsg, "\n");
  1304.     strcat(szErrMsg, message);
  1305.   }
  1306.                                        /* Pop up a Message box                */
  1307.   rc = WinMessageBox(HWND_DESKTOP, hwndOwner, szErrMsg, szErrTitle, 0, fsStyle);
  1308.  
  1309.    /* Free the message buffer, and return.                                    */
  1310.  
  1311.   free(szErrMsg);
  1312.   return  rc;
  1313. }
  1314.  
  1315. /************************** START OF SPECIFICATIONS ***************************/
  1316. /*                                                                            */
  1317. /*   SUBROUTINE NAME: CuaLogoDlgProc                                          */
  1318. /*                                                                            */
  1319. /*   DESCRIPTIVE NAME: Logo Dialog Procedure                                  */
  1320. /*                                                                            */
  1321. /*   FUNCTION:                                                                */
  1322. /*               This routine is the dialog procedure for diaply of the       */
  1323. /*               About dialog.                                                */
  1324. /*                                                                            */
  1325. /*   NOTES:                                                                   */
  1326. /*                                                                            */
  1327. /*   ENTRY POINT:                                                             */
  1328. /*      LINKAGE: Standard Dialog procedure interface.                         */
  1329. /*                                                                            */
  1330. /*   INPUT: Standard Dialog procedure interface.                              */
  1331. /*                                                                            */
  1332. /*   EXIT-NORMAL:                                                             */
  1333. /*                                                                            */
  1334. /*   EXIT-ERROR:                                                              */
  1335. /*                                                                            */
  1336. /*   EFFECTS:                                                                 */
  1337. /*                                                                            */
  1338. /*   INTERNAL REFERENCES:                                                     */
  1339. /*      ROUTINES:                                                             */
  1340. /*                                                                            */
  1341. /*   EXTERNAL REFERENCES:                                                     */
  1342. /*      ROUTINES:                                                             */
  1343. /*        WinDefDlgProc                                                       */
  1344. /*        WinDismissDlg                                                       */
  1345. /*                                                                            */
  1346. /**************************** END OF SPECIFICATIONS ***************************/
  1347.  
  1348. MRESULT EXPENTRY CuaLogoDlgProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  1349. {
  1350.     LONG timeout;
  1351.     HINI hini;
  1352.     LONG ldefault = 2000;               /* Default logo to 2 seconds  @D08*/
  1353.     UCHAR buffer[MAXWIDTH];
  1354.  
  1355.     switch(msg)
  1356.     {
  1357.        case WM_INITDLG:
  1358.           if (mp2) {                    /* @C07A */
  1359.              hini = HINI_PROFILE;
  1360.              timeout = PrfQueryProfileInt(hini,(PSZ)"PM_ControlPanel", (PSZ)"LogoDisplayTime", ldefault);
  1361.              if (timeout == 0) 
  1362.              {
  1363.                WinDismissDlg (hwnd,TRUE);
  1364.                break;
  1365.              }
  1366.              else WinStartTimer(hab, hwnd, 0, (ULONG) timeout);
  1367.                                   /* start a time of required duration */
  1368.           } /* endif */
  1369.           return ( (MRESULT) FALSE);
  1370.  
  1371.         case WM_COMMAND:
  1372.             break;
  1373.  
  1374.         case WM_TIMER:               /* @C07A */
  1375.             WinStopTimer(hab, hwnd, 0);
  1376.             WinDismissDlg(hwnd, TRUE);
  1377.             break;
  1378.     }
  1379.     return(WinDefDlgProc(hwnd,msg,mp1,mp2));
  1380. }
  1381. /************************** START OF SPECIFICATIONS ***************************/
  1382. /*                                                                            */
  1383. /*   SUBROUTINE NAME:  SysErrorBox                                            */
  1384. /*                                                                            */
  1385. /*   DESCRIPTIVE NAME: System Error Box                                       */
  1386. /*                                                                            */
  1387. /*   FUNCTION:                                                                */
  1388. /*               Pop up a window with the error information for a base        */
  1389. /*               system error.                                                */
  1390. /*                                                                            */
  1391. /*   NOTES:                                                                   */
  1392. /*                                                                            */
  1393. /*   ENTRY POINT:                                                             */
  1394. /*      LINKAGE:                                                              */
  1395. /*          ULONG  SysErrorBox(HWND hwnd, ULONG  errorcd, PSZ message)        */
  1396. /*                                                                            */
  1397. /*   INPUT:                                                                   */
  1398. /*       hwndOwner  -  Owners window handle                                   */
  1399. /*       errorcd    -  Error code                                             */
  1400. /*       message    -  User provided message                                  */
  1401. /*                                                                            */
  1402. /*   EXIT-NORMAL:                                                             */
  1403. /*                                                                            */
  1404. /*   EXIT-ERROR:                                                              */
  1405. /*                                                                            */
  1406. /*   EFFECTS:                                                                 */
  1407. /*                                                                            */
  1408. /*   INTERNAL REFERENCES:                                                     */
  1409. /*      ROUTINES:                                                             */
  1410. /*                                                                            */
  1411. /*   EXTERNAL REFERENCES:                                                     */
  1412. /*      ROUTINES:                                                             */
  1413. /*       DosSleep                                                             */
  1414. /*       WinPostMsg                                                           */
  1415. /**************************** END OF SPECIFICATIONS ***************************/
  1416.  
  1417. void SysErrorBox(HWND hwnd,ULONG  errorcd,PUCHAR message)
  1418.  
  1419. {
  1420.  
  1421.    /***************************************************************************/
  1422.    /* This call may be issued from a non-PM thread. So we have to use Post    */
  1423.    /*   instead of Send. If the Post fails, give the window procedure a       */
  1424.    /*   chance to empty the message queue and try again.                      */
  1425.    /***************************************************************************/
  1426.  
  1427.   while (!WinPostMsg(hwnd, DOS_ERROR, message,
  1428.        MPFROM2SHORT(errorcd, MB_CANCEL|MB_ICONEXCLAMATION))) {
  1429.     DosSleep(0L);                      /* This give the window thread a chance*/
  1430.                                        /* to run                              */
  1431.   }                                    /* endwhile                            */
  1432. }
  1433.  
  1434. /************************** START OF SPECIFICATIONS ***************************/
  1435. /*                                                                            */
  1436. /*   SUBROUTINE NAME: ProcessSaveQuit                                         */
  1437. /*                                                                            */
  1438. /*   DESCRIPTIVE NAME: Set up call to Save/Quit dialog.                       */
  1439. /*                                                                            */
  1440. /*   FUNCTION:                                                                */
  1441. /*               Checks to see if the output in the MLE has changed since the */
  1442. /*               last save, and if so brings up the Save/Quit dialog.         */
  1443. /*                                                                            */
  1444. /*   NOTES:                                                                   */
  1445. /*                                                                            */
  1446. /*   ENTRY POINT:                                                             */
  1447. /*      LINKAGE: ULONG  ProcessSaveQuit                                       */
  1448. /*                                                                            */
  1449. /*   INPUT:                                                                   */
  1450. /*      HWND hWnd - window handle                                             */
  1451. /*                                                                            */
  1452. /*   EXIT-NORMAL:                                                             */
  1453. /*      Returns TRUE if processed correctly                                   */
  1454. /*                                                                            */
  1455. /*   EXIT-ERROR:                                                              */
  1456. /*      Returns FALSE otherwise                                               */
  1457. /*                                                                            */
  1458. /*   EFFECTS:                                                                 */
  1459. /*                                                                            */
  1460. /*   INTERNAL REFERENCES:                                                     */
  1461. /*      ROUTINES:                                                             */
  1462. /*       SaveQuit - Bring up Save/Quit/Cancel Dialog                          */
  1463. /*                                                                            */
  1464. /*   EXTERNAL REFERENCES:                                                     */
  1465. /*      ROUTINES:                                                             */
  1466. /*       WinDestroyWindow                                                     */
  1467. /*       WinInvalidateRect                                                    */
  1468. /*       WinQueryWindowULong                                                  */
  1469. /*       WinSendMsg                                                           */
  1470. /*       WinWindowFromID                                                      */
  1471. /*                                                                            */
  1472. /**************************** END OF SPECIFICATIONS ***************************/
  1473.  
  1474.   ULONG  ProcessSaveQuit(HWND hwnd)
  1475.   {
  1476.     HWND hEdit;
  1477.     ULONG  usRetVal;
  1478.  
  1479.     hEdit = WinWindowFromID(hwnd, MLE_WNDW);
  1480.  
  1481.     if (WinSendMsg(hEdit, MLM_QUERYCHANGED, NULL, NULL)) {
  1482.       usRetVal = (ULONG )SaveQuit(hab, hwnd, pszFileName);
  1483.     }
  1484.     else {
  1485.       usRetVal = 1;
  1486.     }
  1487.  
  1488.     return (usRetVal);
  1489.   }
  1490.