home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / warptlk3.zip / TOOLKIT / SAMPLES / REXX / API / PMREXX / PMREXXIO.C < prev    next >
C/C++ Source or Header  |  1995-08-24  |  132KB  |  2,321 lines

  1. /* static char *SCCSID = "@(#)pmrexxio.c        6.3 91/12/24";                      */
  2. /*********************  START OF SPECIFICATIONS  ******************************/
  3. /*                                                                            */
  4. /*   SOURCE FILE NAME:  pmrexxio.c                                            */
  5. /*                                                                            */
  6. /*   DESCRIPTIVE NAME:  PM I/O environment for REXX command files.            */
  7. /*                                                                            */
  8. /*      Provide a means for REXX command files to do Pull, Say and            */
  9. /*      Trace interactions when called from a PM application by simulating    */
  10. /*      stdin, stdout and stderr I/O operations.                              */
  11. /*                                                                            */
  12. /*   COPYRIGHT:         IBM Corporation 1991                                  */
  13. /*                                                                            */
  14. /*   STATUS:            Version 2.00                                          */
  15. /*                                                                            */
  16. /*   FUNCTION:                                                                */
  17. /*           This program provides a Presentation Manager Shell for           */
  18. /*      RexxStart programs.                                                   */
  19. /*                                                                            */
  20. /*                                                                            */
  21. /*   NOTES:                                                                   */
  22. /*      DEPENDENCIES:                                                         */
  23. /*          This function has dependencies on the following                   */
  24. /*      files for compilation.                                                */
  25. /*          pmrexxio.h - Definitions for control of the PMREXXIO              */
  26. /*                       dialog.                                              */
  27. /*          pmrxiodt.h - Definitions necessary for the resource               */
  28. /*                       file compilation.                                    */
  29. /*          rhdtatyp.h - Macros, structures, typedefs and defines             */
  30. /*                       local to and necessary for this program.             */
  31. /*          The C runtime multi-threaded header files                         */
  32. /*                                                                            */
  33. /*  EXECUTION INSTRUCTIONS:                                                   */
  34. /*          PMREXXIO is invoked via a call to RexxCreateIOWindow.             */
  35. /*      This call redirects stdin, stdout and stderr to pips which            */
  36. /*      are processed by PMREXXIO.  The calling application enables           */
  37. /*      execution of a Rexx program by posting message REXX_STARTPROC,        */
  38. /*      passing the id of the thread the Rexx program will execute on.        */
  39. /*      On completion of the Rexx program, the message REXX_ENDPROC           */
  40. /*      should be sent to the window.  RexxDestroyIOWindow should be          */
  41. /*      called to perform cleanup of the I/O resources at program             */
  42. /*      termination.                                                          */
  43. /*                                                                            */
  44. /*  EXPECTED OUTPUT:                                                          */
  45. /*          The REXX procedure file will be executed with all                 */
  46. /*      output directed into PM windows.                                      */
  47. /*                                                                            */
  48. /*  PROCEDURES:                                                               */
  49. /*    RexxCreateIOWindow:  Initialize I/O subsystem                           */
  50. /*    RexxDestroyIOWindow:  Terminate I/O subsystem                           */
  51. /*    EntryDlgProc:   Dialog procedure for the input entry field              */
  52. /*    initialize:     Initialize data structures and threads                  */
  53. /*    io_routine:     Process the REXX IO system exit                         */
  54. /*    MainWndProc:    Main window procedure                                   */
  55. /*    SizeWindow:     Size the output window and input window                 */
  56. /*    ClipBoard:      Process MLE clipboard functions                         */
  57. /*    RXIOCmds:       Process WM_COMMAND messages from the main window proc   */
  58. /*    Import:         Add information from import buffer to the MLE           */
  59. /*    SelectFont:     Interface to the font selection dialog                  */
  60. /*    stdinpipe:      Send input to the standard input of a child process     */
  61. /*    stdoutpipe:     Send standard output from child proc to output window   */
  62. /*                                                                            */
  63. /***********************  END OF SPECIFICATIONS  ******************************/
  64. #include <malloc.h>
  65. #include <process.h>
  66. #include <stddef.h>
  67. #include <stdio.h>
  68. #include <stdlib.h>
  69. #include <string.h>
  70.  
  71. /* Define the sections of the OS/2 header files that we need.                 */
  72.  
  73. #define  INCL_RXSYSEXIT                /* REXX system exits                   */
  74. #define  INCL_RXARI                    /* REXX Asynchronous Request Interface */
  75. #define  INCL_DOSSEMAPHORES            /* OS/2 semaphore support              */
  76. #define  INCL_DOSERRORS                /* OS/2 errors                         */
  77. #define  INCL_DOSPROCESS               /* Process and thread support          */
  78. #define  INCL_DOSQUEUES                /* Queues                              */
  79. #define  INCL_DOSMISC                  /* Miscellaneous doscalls              */
  80. #define  INCL_DOSNLS                   /* NLS (code page) support             */
  81. #define  INCL_DOSMODULEMGR             /* OS/2 module support                 */
  82. #define  INCL_GPILCIDS                 /* Physical and logical fonts with     */
  83.                                        /* lcids                               */
  84. #define  INCL_GPIPRIMITIVES            /* Drawing primitives and primitive    */
  85.                                        /* attributes                          */
  86. #define  INCL_WINBUTTONS               /* Buttons controls                    */
  87. #define  INCL_WINCOUNTRY               /* Code page support                   */
  88. #define  INCL_WINDIALOGS               /* Dialog boxes                        */
  89. #define  INCL_WINENTRYFIELDS           /* Entry fields                        */
  90. #define  INCL_WINERRORS                /* Standard Font dialog                */
  91. #define  INCL_WINFRAMEMGR              /* Frame manager                       */
  92. #define  INCL_WINHELP                  /* Help manager definitions            */
  93. #define  INCL_WININPUT                 /* Mouse and keyboard input            */
  94. #define  INCL_WINMENUS                 /* Menu controls                       */
  95. #define  INCL_WINMESSAGEMGR            /* Message management                  */
  96. #define  INCL_WINMLE                   /* Multiple line edit fields           */
  97. #define  INCL_WINPOINTERS              /* Mouse pointers                      */
  98. #define  INCL_WINSTDFONT               /* Standard Font dialog                */
  99. #define  INCL_WINSHELLDATA             /* Profile calls                       */
  100. #define  INCL_WINSWITCHLIST            /* Task list calls                     */
  101. #define  INCL_WINTIMER                 /* Timer routines                      */
  102. #define  INCL_WINWINDOWMGR             /* General window management           */
  103. #include <os2.h>
  104. #include <rexxsaa.h>                   /* Include the REXX header file        */
  105.  
  106. /* Defines, typedefs and function prototypes for pmrexx                       */
  107.  
  108. #include "rhdtatyp.h"
  109. #include "pmrxiodt.h"
  110. #include "pmrexxio.h"
  111.  
  112. /************************** START OF SPECIFICATIONS ***************************/
  113. /*                                                                            */
  114. /*   SUBROUTINE NAME: RexxCreateIOWindow                                      */
  115. /*                                                                            */
  116. /*   DESCRIPTIVE NAME:                                                        */
  117. /*               Initialize a Rexx stdin/stdout/stderr transaction subsystem. */
  118. /*                                                                            */
  119. /*   FUNCTION:                                                                */
  120. /*               Creates Rexx I/O windows and redirects stdin, stdout, and    */
  121. /*               stderr to pipes.                                             */
  122. /*                                                                            */
  123. /*   NOTES:                                                                   */
  124. /*                                                                            */
  125. /*   ENTRY POINT:                                                             */
  126. /*      LINKAGE:  RexxCreateIOWindow(HWND hwndOwner, PHWND phwndClient)       */
  127. /*                                                                            */
  128. /*   INPUT:                                                                   */
  129. /*       phwndClient is the handle of the I/O window client window.           */
  130. /*                                                                            */
  131. /*   EXIT-NORMAL:                                                             */
  132. /*       Exit with handle to I/O frame window.                                */
  133. /*                                                                            */
  134. /*   EXIT-ERROR:                                                              */
  135. /*       If unable to duplicate the write handle for stderr pipe, exit rc=5.  */
  136. /*       If unable to register the window class, exit rc=1.                   */
  137. /*       If no procedure name was specified, exit with rc=3.                  */
  138. /*       If window was not displayed, exit with return code from the REXX     */
  139. /*         procedure.                                                         */
  140. /*       Otherwise: exit with created frame and client handles.               */
  141. /*                                                                            */
  142. /*   EFFECTS:                                                                 */
  143. /*       Initializes the Rexx Presentation Manager I/O subsystem.             */
  144. /*                                                                            */
  145. /*   INTERNAL REFERENCES:                                                     */
  146. /*      ROUTINES:                                                             */
  147. /*       getstring      - To obtain the title bar name and window name.       */
  148. /*       initialize     - Sets up the environment for the program. Starts all */
  149. /*                        necessary threads, sets up the input queues, etc.   */
  150. /*                                                                            */
  151. /*   EXTERNAL REFERENCES:                                                     */
  152. /*      ROUTINES:                                                             */
  153. /*       WinQueryAnchorBlock         WinRegisterClass                         */
  154. /*       WinCreateStdWindow                                                   */
  155. /*                                                                            */
  156. /**************************** END OF SPECIFICATIONS ***************************/
  157.  
  158. HWND RexxCreateIOWindow(
  159.    HWND hwndOwner,                     /* Owner handle                        */
  160.    PHWND phwndClient)                  /* Returned client window              */
  161.  {
  162.  
  163.    /* We set the creation flags to be the standard window frame flags         */
  164.    /*    but without scroll bars and without a task list entry.               */
  165.  
  166.   ULONG flCreate = FCF_STANDARD&~(FCF_VERTSCROLL|FCF_HORZSCROLL|FCF_ACCELTABLE);
  167.   PUCHAR windowtext;                   /* Text for title bar                  */
  168.   ULONG  argnum = 1;                   /* Counter for looking at arguments    */
  169.   HAB    hab;                          /* anchor block                        */
  170.   HMODULE handle;                      /* module handle                       */
  171.   HWND    hwndFrame;                   /* frame handle                        */
  172.  
  173.                                        /* get desktop anchor                  */
  174.   hab = WinQueryAnchorBlock(hwndOwner);
  175.   if (!hab) {                          /* no anchor block?                    */
  176.     return NULLHANDLE;                 /* return with nothing                 */
  177.   }
  178.  
  179.   if (DosQueryModuleHandle(MODULE_NAME, &handle)) {
  180.     return NULLHANDLE;                 /* return with nothing                 */
  181.   }
  182.  
  183.   if (!WinRegisterClass(               /* Register Window Class               */
  184.       hab,                             /* Anchor block handle                 */
  185.       PMREXXCLASSNAME,                 /* Window Class name                   */
  186.       (PFNWP)MainWndProc,              /* Address of Window Procedure         */
  187.       CS_SIZEREDRAW,                   /* Class Style                         */
  188.       sizeof(PUCHAR))) {               /* Extras words for a far ptr.         */
  189.     return  NULLHANDLE;                /* Exit if we couldn't register the    */
  190.   }                                    /* class                               */
  191.  
  192.    /* Get the title bar text                                                  */
  193.  
  194.   windowtext = getstring(hab, handle, WINDOW_TEXT);
  195.  
  196.    /* Create the standard window                                              */
  197.  
  198.   hwndFrame = WinCreateStdWindow(hwndOwner,/* Supplied owner                  */
  199.       0,                               /* Frame Style                         */
  200.       &flCreate,                       /* Control Data                        */
  201.       PMREXXCLASSNAME,                 /* Window Class name                   */
  202.       NULL,                            /* Window Text                         */
  203.       WS_VISIBLE,                      /* Client style                        */
  204.       handle,                          /* Module handle==this module          */
  205.       RXHOST_WIN,                      /* Window ID                           */
  206.       phwndClient);                    /* Client Window handle                */
  207.                                        /* set the window text                 */
  208.   WinSetWindowText(WinWindowFromID(hwndFrame, (USHORT)FID_TITLEBAR),
  209.       windowtext);
  210.   free(windowtext);                    /* release window text                 */
  211.   return hwndFrame;                    /* return created frame handle         */
  212.  }
  213.  
  214. /************************** START OF SPECIFICATIONS ***************************/
  215. /*                                                                            */
  216. /*   SUBROUTINE NAME: RexxDestroyIOWindow                                     */
  217. /*                                                                            */
  218. /*   DESCRIPTIVE NAME:                                                        */
  219. /*               Terminate a Rexx stdin/stdout/stderr transaction subsystem.  */
  220. /*                                                                            */
  221. /*   FUNCTION:                                                                */
  222. /*               Cleans up the Rexx I/O subsystem.                            */
  223. /*                                                                            */
  224. /*   NOTES:                                                                   */
  225. /*                                                                            */
  226. /*   ENTRY POINT:                                                             */
  227. /*      LINKAGE:  RexxDestroyIOWindow(HWND hwndClient)                        */
  228. /*                                                                            */
  229. /*   INPUT:                                                                   */
  230. /*       phwndClient is the handle of the I/O window client window.           */
  231. /*                                                                            */
  232. /*   EXIT-NORMAL:                                                             */
  233. /*                                                                            */
  234. /*   EXIT-ERROR:                                                              */
  235. /*                                                                            */
  236. /*   EFFECTS:                                                                 */
  237. /*       Terminates the Rexx Presntation Manager I/O subsystem.               */
  238. /*                                                                            */
  239. /*   INTERNAL REFERENCES:                                                     */
  240. /*      ROUTINES:                                                             */
  241. /*                                                                            */
  242. /*   EXTERNAL REFERENCES:                                                     */
  243. /*      ROUTINES:                                                             */
  244. /*       WinQueryWindowPtr           WinDestroyHelpInstance                   */
  245. /*       WinAssociateHelpInstance    WinDestroyWindow                         */
  246. /*       DosSuspendThread            RexxDeregisterExit                       */
  247. /*       DosFreeMem                                                           */
  248. /*                                                                            */
  249. /**************************** END OF SPECIFICATIONS ***************************/
  250.  
  251. void RexxDestroyIOWindow(HWND hwnd)
  252. {
  253.   PRHWINDATA pWinData = NULL;          /* pointer to the windata structure    */
  254.  
  255.   pWinData = WinQueryWindowPtr(WinWindowFromID(hwnd, (USHORT)FID_CLIENT),
  256.       (SHORT)0);
  257.    /* And now, clean everything up.                                    */
  258.    if (pWinData->HelpInst) {
  259.       WinDestroyHelpInstance(pWinData->HelpInst);
  260.       WinAssociateHelpInstance(NULLHANDLE, pWinData->frame);
  261.    }
  262.                                        /* cleanup semaphores                  */
  263.    DosCloseMutexSem(pWinData->pipe_in.q_sem);
  264.    DosCloseMutexSem(pWinData->trace_in.q_sem);
  265.    DosCloseEventSem(pWinData->pipe_in.q_data);
  266.    DosCloseEventSem(pWinData->trace_in.q_data);
  267.  
  268.    RexxDeregisterExit(PMRXIO_EXIT, NULL);
  269.    WinDestroyWindow(pWinData->frame);
  270.    DosFreeMem(pWinData);               /* release storage                     */
  271. }
  272.  
  273. /************************** START OF SPECIFICATIONS ***************************/
  274. /*                                                                            */
  275. /*   SUBROUTINE NAME: initialize                                              */
  276. /*                                                                            */
  277. /*   DESCRIPTIVE NAME:                                                        */
  278. /*               Initialize the data structures and threads necessary for the */
  279. /*               program to operate.                                          */
  280. /*                                                                            */
  281. /*   FUNCTION:                                                                */
  282. /*               Initializes the input queues and their semaphores, set up    */
  283. /*               the file handles for redirection of standard input/output and*/
  284. /*               error streams, allocate stacks for and begin the threads.     /
  285. /*               subcommand environments.                                     */
  286. /*                                                                            */
  287. /*   NOTES:                                                                   */
  288. /*                                                                            */
  289. /*   ENTRY POINT:                                                             */
  290. /*      LINKAGE:  initialize                                                  */
  291. /*                                                                            */
  292. /*   INPUT:       none                                                        */
  293. /*                                                                            */
  294. /*   EXIT-NORMAL: returns 0                                                   */
  295. /*                                                                            */
  296. /*   EXIT-ERROR:  returns error code from call causing the error.             */
  297. /*                                                                            */
  298. /*   EFFECTS:                                                                 */
  299. /*                                                                            */
  300. /*   INTERNAL REFERENCES:                                                     */
  301. /*      ROUTINES:                                                             */
  302. /*       makepipe       - Creates a pipe with the read and write handles at   */
  303. /*                        desired positions.                                  */
  304. /*       setinherit     - Sets the inheritance characteristcs of the passed   */
  305. /*                        file handle.                                        */
  306. /*                                                                            */
  307. /*   EXTERNAL REFERENCES:                                                     */
  308. /*      ROUTINES:                                                             */
  309. /*       DosDupHandle                                                         */
  310. /*       DosCreateMutexSem                                                    */
  311. /*       DosCreateEventSem                                                    */
  312. /*       DosGetInfoBlocks                                                     */
  313. /*       RexxRegisterExitExe                                                  */
  314. /*                                                                            */
  315. /**************************** END OF SPECIFICATIONS ***************************/
  316.  
  317.   LONG initialize(PRHWINDATA pWinData)
  318.   {
  319.     LONG         rc;                   /* return code                         */
  320.     PTIB         TI;                   /* Thread info block pointer           */
  321.     PPIB         PI;                   /* Process info block pointer          */
  322.     PRHWINDATA   userdata[2];          /* registered user data                */
  323.  
  324.    /* Initialization Section:                                                 */
  325.    /* First initialize the semaphores for the input queue.                    */
  326.    /* Using a queue and a separate thread ensures that we don't               */
  327.    /*   tie up the window procedure if the pipe backs up.                     */
  328.  
  329.     DosCreateMutexSem(NULL, &pWinData->pipe_in.q_sem, 0, FALSE);
  330.     DosCreateMutexSem(NULL, &pWinData->trace_in.q_sem, 0, FALSE);
  331.     DosCreateEventSem(NULL, &pWinData->pipe_in.q_data, FALSE, FALSE);
  332.     DosCreateEventSem(NULL, &pWinData->trace_in.q_data, FALSE, FALSE);
  333.  
  334.    /* Next, set up the redirection pipes to capture standard                  */
  335.    /*  I/O from subcommand processing.                                        */
  336.    /* First make sure all C handles are closed.                               */
  337.  
  338.     DosClose(STDIN);                   /* close stdin, stdout, stderr         */
  339.     DosClose(STDOUT);
  340.     DosClose(STDERR);
  341.  
  342.    /* Since we closed all open file handles, we are free to use any *
  343.     * handles we want.                                                        */
  344.    /* First, standard input                                                   */
  345.  
  346.     makepipe(&pWinData->stdin_r, STDIN, &pWinData->stdin_w, 4, PIPE_SIZE);
  347.     setinherit(pWinData->stdin_r, TRUE);
  348.     setinherit(pWinData->stdin_w, FALSE);
  349.  
  350.    /* Next, standard output                                                   */
  351.  
  352.     makepipe(&pWinData->stdout_r, 5, &pWinData->stdout_w, STDOUT, PIPE_SIZE);
  353.     setinherit(pWinData->stdout_w, TRUE);
  354.     setinherit(pWinData->stdout_r, FALSE);
  355.  
  356.    /* And, finally, standard error                                            */
  357.    /* Just dup the standard output and handle it once.                        */
  358.  
  359.     pWinData->stderr_w = STDERR;
  360.  
  361.     if (rc = DosDupHandle(pWinData->stdout_w, &pWinData->stderr_w)) {
  362.       return  rc;
  363.     }
  364.  
  365.     DosGetInfoBlocks(&TI, &PI);        /* Get the thread information          */
  366.     pWinData->proc_id = PI->pib_ulpid; /* set the process id                  */
  367.  
  368.     userdata[0] = pWinData;            /* save our anchor                     */
  369.                                        /* register I/O handler                */
  370.     RexxRegisterExitExe(PMRXIO_EXIT, (PFN)io_routine, (PUCHAR)userdata);
  371.  
  372.    /* And, of course, start the various threads!                              */
  373.  
  374.     rc = DosCreateThread(&pWinData->in_tid, (PFNTHREAD)stdinpipe, (ULONG)pWinData,
  375.         (ULONG)0, STACK_SIZE);
  376.     if (!rc) rc = DosCreateThread(&pWinData->out_tid, (PFNTHREAD)stdoutpipe, (ULONG)pWinData,
  377.         (ULONG)0, STACK_SIZE);
  378.     return rc;
  379.   }
  380.  
  381. /************************** START OF SPECIFICATIONS ***************************/
  382. /*                                                                            */
  383. /*   SUBROUTINE NAME: MainWndProc                                             */
  384. /*                                                                            */
  385. /*   DESCRIPTIVE NAME:                                                        */
  386. /*               Main window procedure for the PMREXX program.                */
  387. /*                                                                            */
  388. /*   FUNCTION:                                                                */
  389. /*               This procedure handles all interesting messages for the      */
  390. /*               client area for the PMREXX program. The messages handled     */
  391. /*               are:                                                         */
  392. /*       WM_CREATE      - Allocates and initializes the RHWINDATA structure   */
  393. /*                        (defined in rhdtatyp.h) and places a pointer to it  */
  394. /*                        into the window words.                              */
  395. /*       WM_TIMER       - A 100 millisecond timer is set when output is added */
  396. /*                        to a buffer for later adding to the MLE output      */
  397. /*                        window. Thus if many lines are being added, output  */
  398. /*                        time is improved, and window flashing is reduced.   */
  399. /*                        If the timer pops, then no output has been          */
  400. /*                        added for the 100 milliseconds and it is time to    */
  401. /*                        add the output to the MLE.                          */
  402. /*       WM_ERASEBACKGROUND - Just return TRUE to force a background erase.   */
  403. /*       WM_SIZE        - Calls routine SizeWindow to re-adjust the sizes     */
  404. /*                        of the MLE and input areas.                         */
  405. /*       WM_PAINT       - Paints the header for the input window, and lets    */
  406. /*                        the child controls do the rest.                     */
  407. /*       WM_COMMAND     - All WM_COMMAND messages are processed in routine    */
  408. /*                        RXIOCmds.                                           */
  409. /*       WM_CHAR        - Handles tab and backtab keys to switch the focus    */
  410. /*                        window and the break key as a halt procedure.       */
  411. /*       REXX_MAKE_VISIBLE - Is a user defined message requesting that        */
  412. /*                        the window be made visible. The window is initially */
  413. /*                        created invisible and is not made visible until     */
  414. /*                        something is output, or until some input is         */
  415. /*                        requested. This way, a REXX procedure that does not */
  416. /*                        need this window, will not clutter up the screen    */
  417. /*                        with it (e.g. a DM exec that uses DM for all I/O).  */
  418. /*       REXX_MAKE_INVISIBLE - Is a user defined message requesting that      */
  419. /*                        the window be made invisible.                       */
  420. /*       REXX_ENDPROC   - This signals the end of a Rexx procedure.  The      */
  421. /*                        I/O subsystem is flushed and reinitialized.         */
  422. /*       REXX_STARTPROC - This signals the start of a Rexx procedure.  This   */
  423. /*                        identifies the thread running the procedure.        */
  424. /*       RXIOB_MSGBOX   - Puts up a message box with the requested message.   */
  425. /*       START_TIMER    - Starts a timer. When the timer pops, the buffered   */
  426. /*                        output is added to the MLE. See also, WM_TIMER and  */
  427. /*                        ADD_STDOUTWIN. This message is posted by the thread */
  428. /*                        reading the input pipe.                             */
  429. /*       ADD_STDOUTWIN  - This user defined message is a request to add       */
  430. /*                        output to the output window. To reduce window       */
  431. /*                        flicker and improve performance, data is internally */
  432. /*                        buffered until the buffer is full, or until there   */
  433. /*                        is a lull in output, before being sent on to the    */
  434. /*                        MLE window. See also the WM_TIMER message.          */
  435. /*       WM_SAVEAPPLICATION - Save the current font and window information    */
  436. /*                                                                            */
  437. /*   NOTES:                                                                   */
  438. /*                                                                            */
  439. /*   ENTRY POINT:                                                             */
  440. /*      LINKAGE:                                                              */
  441. /*               Standard window procedure linkage is followed.               */
  442. /*                                                                            */
  443. /*   INPUT:                                                                   */
  444. /*               Standard window procedure inputs are passed in.              */
  445. /*                                                                            */
  446. /*   EXIT-NORMAL:                                                             */
  447. /*                                                                            */
  448. /*   EXIT-ERROR:                                                              */
  449. /*                                                                            */
  450. /*   EFFECTS:                                                                 */
  451. /*                                                                            */
  452. /*   INTERNAL REFERENCES:                                                     */
  453. /*      ROUTINES:                                                             */
  454. /*       getfixedfont    - Get a fixed font for the default display            */
  455. /*       getstring       - Retrieve a string resource                          */
  456. /*       RestoreWindow   - Gets saved window position from user profile        */
  457. /*       RHWinErrorBox   - Display an error message box                        */
  458. /*       SizeWindow      - Sizes all the child windows (MLE & Entry field) to  */
  459. /*                         fit the frame window.                               */
  460. /*       RXIOCmds        - This routine processes the various WM_COMMAND       */
  461. /*                         messages.                                           */
  462. /*       Import          - Sends the data from the internal buffer to the MLE. */
  463. /*                         See the WM_TIMER and ADD_STDOUTWIN messages.        */
  464. /*       SaveWindow      - Saves current window position to user profile       */
  465. /*       SetCheckMark    - Check/uncheck a menu item                           */
  466. /*       ProcessSaveQuit - Interface to the Save/Quit dialog                  */
  467. /*       SearchDlgProc   - Display Search Dialog                                */
  468. /*                                                                            */
  469. /*                                                                            */
  470. /*   EXTERNAL REFERENCES:                                                     */
  471. /*      ROUTINES:                                                             */
  472. /*       DosAllocMem                       WinLoadString                      */
  473. /*       DosCreateMutexSem                 WinMessageBox                      */
  474. /*       DosFreeMem                        WinPostMsg                         */
  475. /*       DosReleaseMutexSem                WinQueryAnchorBlock                */
  476. /*       DosRequestMutexSem                WinQueryWindow                     */
  477. /*       DosSuspendThread                  WinQueryWindowPos                  */
  478. /*       GpiCharStringAt                   WinQueryWindowPtr                  */
  479. /*       GpiQueryCurrentPosition           WinReleasePS                       */
  480. /*       RexxDeregisterExit                WinSendMsg                         */
  481. /*       WinAlarm                          WinSetFocus                        */
  482. /*       WinAssociateHelpInstance          WinSetWindowPtr                    */
  483. /*       WinCreateHelpInstance             WinShowWindow                      */
  484. /*       WinDefWindowProc                  WinStartTimer                      */
  485. /*       WinDestroyHelpInstance            WinStopTimer                       */
  486. /*       WinGetPS                          WinWindowFromID                    */
  487. /*                                                                            */
  488. /**************************** END OF SPECIFICATIONS ***************************/
  489.  
  490.   MRESULT EXPENTRY MainWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  491.   {
  492.     ULONG      rc;                     /* return code                         */
  493.     PRHWINDATA pWinData = NULL;        /* pointer to the windata structure    */
  494.     HPS        hps;                    /* presentation space handle           */
  495.     PIMPORT    im_ptr;                 /* Pointer to buffer for data waiting  */
  496.     ULONG      postcount;              /* number of posted lines              */
  497.     FONTMETRICS fm;                    /* font size information               */
  498.     HWND       hEntry;                 /* entry dialog handle                 */
  499.                                        /* Creation flags for the MLE requests */
  500.                                        /* scroll bars.                        */
  501.     ULONG flCreate = MLS_HSCROLL|MLS_VSCROLL|MLS_BORDER;
  502.  
  503.     pWinData = WinQueryWindowPtr(hwnd, (SHORT)0);
  504.  
  505.     switch (msg) {
  506.  
  507.       case  WM_CREATE :
  508.  
  509.          /* When the window is created, we also create a structure to hold    */
  510.          /*   all the window specific data.                                   */
  511.  
  512.         if (pWinData = malloc(sizeof(*pWinData))) {
  513.           memset(pWinData, '\0', sizeof(*pWinData));
  514.  
  515.           pWinData->hab = WinQueryAnchorBlock(hwnd);
  516.                                        /* and client handle                   */
  517.           pWinData->client = hwnd;
  518.                                        /* save frame handle                   */
  519.           pWinData->frame = WinQueryWindow(hwnd, QW_PARENT);
  520.           if (DosQueryModuleHandle(MODULE_NAME, &pWinData->hResource)) {
  521.             return NULL;               /* return with nothing                 */
  522.           }
  523.           pWinData->imp_ptr = NULL;    /* This is the timer to be used for    */
  524.                                        /* import time-out.                    */
  525.  
  526.           pWinData->timer = (USHORT)WinStartTimer(pWinData->hab, (HWND)0,
  527.                                                  (USHORT)0, (ULONG)0);
  528.                                        /* get code page information           */
  529.           DosQueryCtryInfo(sizeof(COUNTRYINFO), &pWinData->CountryCode,
  530.               &pWinData->CountryInfo, &postcount);
  531.                                        /* Attempt to find a fixed font for the*/
  532.                                        /* display, if we are not successful,  */
  533.                                        /* we will use the system font.        */
  534.           getfixedfont(hwnd, &(pWinData->MleFontAttrs.fAttrs));
  535.                                        /* system font attributes              */
  536.           pWinData->infocus = FALSE;
  537.                                        /* get the input text                  */
  538.                                        /* prompt from the resource file       */
  539.  
  540.           pWinData->RxResult = TRUE;   /* append or overwrite flag            */
  541.  
  542.           pWinData->pszInputText = getstring(pWinData->hab,
  543.           pWinData->hResource, INPUT_TITLE);
  544.  
  545.           WinSetWindowPtr(hwnd, (SHORT)0, pWinData);
  546.                                        /* Now allocate a segment for the      */
  547.                                        /* import buffer for the MLE           */
  548.  
  549.           pWinData->imp_ptr = (PIMPORT)(pWinData->ImportBuffer);
  550.                                        /* initialize the buffer               */
  551.           im_ptr = pWinData->imp_ptr;
  552.           im_ptr->total_size = ALLOCSIZE;
  553.           im_ptr->inuse = HDRSIZE;
  554.           *(PUCHAR)(im_ptr->data) = '\0';
  555.                                        /* create the semaphore                */
  556.           DosCreateMutexSem(NULL, &im_ptr->sem, 0, FALSE);
  557.  
  558.    /* Set up the threads and initialize the data structures                   */
  559.  
  560.           rc = initialize(pWinData);
  561.  
  562.    /* If initialization failed, alert the user and exit                       */
  563.  
  564.           if (rc) {
  565.             WinAlarm(HWND_DESKTOP, WA_ERROR);
  566.             WinMessageBox(HWND_DESKTOP, NULLHANDLE,
  567.                 getstring(pWinData->hab, pWinData->hResource, INIT_FAILED),
  568.                 getstring(pWinData->hab, pWinData->hResource, RXHB_MSGBOXHDR), 1,
  569.                 MB_CANCEL|MB_CUACRITICAL|MB_MOVEABLE);
  570.           }
  571.                                        /* Find out the character              */
  572.                                        /* height for the input entry field    */
  573.           hps = WinGetPS(pWinData->client);
  574.           GpiQueryFontMetrics(hps, (LONG)sizeof fm, &fm);
  575.           pWinData->in_hgt = (ULONG )fm.lMaxBaselineExt+2;
  576.           WinReleasePS(hps);
  577.                                        /* Create the child MLE for            */
  578.                                        /* output                              */
  579.           pWinData->outmle = WinCreateWindow(pWinData->client, WC_MLE, NULL,
  580.               flCreate, 0, 0, 0, 0, pWinData->client, HWND_TOP,
  581.               MLE_WNDW, NULL, NULL);
  582.  
  583.           if (!pWinData->outmle) {     /* If we couldn't do it, tell the user */
  584.                                        /* why.                                */
  585.             RHWinErrorBox(pWinData->hab, hwnd, pWinData->hResource,
  586.                 MLE_CREATE_ERROR, MB_OK|MB_CUAWARNING);
  587.           }                            /* Delay redrawing window until        */
  588.                                        /* we're done updating it              */
  589.           WinEnableWindowUpdate(pWinData->client, FALSE);
  590.                                        /* Set the format for the MLE          */
  591.  
  592.           WinSendMsg(pWinData->outmle, MLM_FORMAT, MLE_TXT_FMT, (MPARAM)0);
  593.                                        /* Make the MLE readonly               */
  594.  
  595.           WinSendMsg(pWinData->outmle, MLM_SETREADONLY, MPFROMLONG(TRUE),
  596.               (MPARAM)0);
  597.                                        /* set the new font                    */
  598.           WinSendMsg(pWinData->outmle, MLM_SETFONT,
  599.               &(pWinData->MleFontAttrs.fAttrs), (MPARAM)0);
  600.                                        /* Update the window                   */
  601.           WinShowWindow(pWinData->outmle, TRUE);
  602.                                        /* set the title width                 */
  603.           pWinData->wtitle = (strlen((const char *)pWinData->pszInputText)+5)*(USHORT)
  604.               fm.lAveCharWidth;
  605.                                        /* Load the dialog box for the input   */
  606.                                        /* window                              */
  607.           hEntry = WinLoadDlg(pWinData->client, pWinData->client,
  608.               (PFNWP)EntryDlgProc, (HMODULE)pWinData->hResource, RH_EF1, NULL);
  609.  
  610.           pWinData->insle = hEntry;    /* save input window handle Set the    */
  611.                                        /* maximum input length to ANSLEN      */
  612.           WinSendMsg(hEntry, EM_SETTEXTLIMIT, MPFROMSHORT(ANSLEN), (MPARAM)0);
  613.                                        /* Set the offset to the first         */
  614.                                        /* character in the input box to 0     */
  615.           WinSendMsg(hEntry, EM_SETFIRSTCHAR, (MPARAM)0, (MPARAM)0);
  616.                                        /* Set the first character to be       */
  617.                                        /* selected as 0                       */
  618.           WinSendMsg(hEntry, EM_SETSEL, (MPARAM)0, (MPARAM)0);
  619.                                        /* Update the windows                  */
  620.           WinShowWindow(hEntry, TRUE);
  621.           WinEnableWindowUpdate(hEntry, TRUE);
  622.           WinEnableWindowUpdate(pWinData->client, TRUE);
  623.           WinSetFocus(HWND_DESKTOP, pWinData->outmle);
  624.         }
  625.         else {                         /* If we couldn't allocate the data    */
  626.                                        /* structure, then we cannot continue, */
  627.                                        /* so alert the user, and exit.        */
  628.           WinSendMsg(WinWindowFromID(hwnd, (USHORT)FID_CLIENT),
  629.               RXIOB_MSGBOX,
  630.               MPFROM2SHORT(RX_ALLOCERR, RXHB_MSGBOXHDR),
  631.               MPFROMLONG(MB_ENTER|MB_CUACRITICAL|MB_MOVEABLE));
  632.           return (MRESULT)TRUE;
  633.         }
  634.         break;
  635.  
  636.       case  WM_TIMER :
  637.  
  638.         if (hwnd) {                    /* We have gone for the designated time*/
  639.                                        /* without adding any new data to the  */
  640.                                        /* output buffer, so it is now time to */
  641.                                        /* import the information to the MLE   */
  642.                                        /* output window.                      */
  643.           WinStopTimer(pWinData->hab, hwnd, pWinData->timer);
  644.                                        /* Get the semaphore so that the       */
  645.                                        /* input pipe thread won't interfere.  */
  646.  
  647.           DosRequestMutexSem(pWinData->imp_ptr->sem, SEM_INDEFINITE_WAIT);
  648.           Import(pWinData);
  649.                                        /* Now clear the                       */
  650.                                        /* thread so that the input pipe can   */
  651.                                        /* continue.                           */
  652.           DosReleaseMutexSem(pWinData->imp_ptr->sem);
  653.         }
  654.  
  655.         break;
  656.  
  657.       case  WM_ERASEBACKGROUND :
  658.  
  659.         return (MRESULT)TRUE;          /* Return TRUE to indicate we want the */
  660.                                        /* background cleared to the system    */
  661.                                        /* default window background color.    */
  662.       case  WM_SIZE :
  663.  
  664.         SizeWindow(hwnd, pWinData);    /* Re-size the client area windows.    */
  665.         break;
  666.  
  667.       case  WM_PAINT :
  668.  
  669.         if (hps = WinGetPS(hwnd)) {    /* The title for the input window needs*/
  670.                                        /* to be re-painted by us. The child   */
  671.                                        /* windows do all the rest of the      */
  672.                                        /* drawing for us.                     */
  673.           POINTL p;
  674.           SWP wp;
  675.           HWND hOwner;
  676.           PUCHAR ptr;                  /* Ensure that we get a proper handle  */
  677.                                        /* to the client area.                 */
  678.  
  679.           hOwner = WinQueryWindow(hwnd, QW_PARENT);
  680.                                        /* Calculate the proper positioning.   */
  681.           WinQueryWindowPos(WinWindowFromID(hOwner, FID_CLIENT), &wp);
  682.  
  683.           p.x = BORDER_MARGIN *2;
  684.           p.y = wp.cy-pWinData->in_hgt-(BORDER_MARGIN *2);
  685.           ptr = pWinData->pszInputText; /* Output the title, and find the      */
  686.                                        /* resulting position for the next     */
  687.                                        /* character. That is where we will    */
  688.                                        /* start the input box.                */
  689.           GpiCharStringAt(hps, &p, (LONG)strlen((const char *)ptr), ptr);
  690.           GpiQueryCurrentPosition(hps, &p);
  691.           pWinData->wtitle = (ULONG )p.x;
  692.           WinReleasePS(hps);
  693.         }
  694.         break;
  695.  
  696.       case  WM_COMMAND :
  697.                                        /* WM_COMMAND processing in RXIOCMDS   */
  698.         return (RXIOCmds(hwnd, mp1, pWinData));
  699.         break;
  700.  
  701.       case  WM_CHAR :
  702.  
  703.          /* Check for a valid (complete) key message.                         */
  704.  
  705.         if (!(SHORT1FROMMP(mp1)&KC_KEYUP) &&
  706.             (SHORT1FROMMP(mp1)&KC_VIRTUALKEY) ) {
  707.  
  708.           switch (SHORT2FROMMP(mp2)) {
  709.             case  VK_TAB :
  710.             case  VK_BACKTAB :         /* For tab and back-tab, switch focus  */
  711.                                        /* windows                             */
  712.               return (MRESULT)WinSetFocus(HWND_DESKTOP,
  713.                   pWinData->infocus?pWinData->outmle: pWinData->insle);
  714.               break;
  715.  
  716.             case VK_NEWLINE:
  717.             case  VK_ENTER :           /* For an enter key, process the command */
  718.               WinSendMsg(pWinData->insle, WM_CHAR, MPFROM2SHORT(KC_VIRTUALKEY, NULL),
  719.                          MPFROM2SHORT(NULL, VK_NEWLINE));
  720.               break;
  721.  
  722.             case  VK_DELETE :           /* For a break key, set the halt       */
  723.                                        /* procedure indicator.                */
  724.               WinSendMsg(hwnd, WM_COMMAND, MPFROMSHORT(RXIOA_DELETE), (MPARAM)0);
  725.               break;
  726.  
  727.             default  :
  728.               break;
  729.           }                            /* endswitch                           */
  730.         }
  731.         break;
  732.  
  733.       case  REXX_STARTPROC :
  734.  
  735.          /* This is the request to start everything up. It is sent by the     */
  736.          /*   main procedure at startup time.                                 */
  737.  
  738.         pWinData->rexx_tid = LONGFROMMP(mp1);
  739.  
  740.         break;
  741.  
  742.       case  REXX_ENDPROC : {
  743.  
  744.         PLIST_ENTRY q_elem;            /* pointer for an element in the input */
  745.                                        /* queue                               */
  746.                                        /* Clear out any entries on input queue*/
  747.         if (!DosRequestMutexSem(pWinData->pipe_in.q_sem, SEM_INDEFINITE_WAIT)) {
  748.           for (q_elem = pWinData->pipe_in.q_1st; q_elem; q_elem = q_elem->next) {
  749.              free(q_elem->ptr);
  750.              free(q_elem);
  751.           }
  752.                                        /* Set the queue to empty              */
  753.           DosResetEventSem(pWinData->pipe_in.q_data, &postcount);
  754.                                        /* Clear the list                      */
  755.           pWinData->pipe_in.q_1st = NULL;
  756.                                        /* We're done with the queue           */
  757.           DosReleaseMutexSem(pWinData->pipe_in.q_sem);
  758.         }
  759.  
  760.         DosReleaseMutexSem(pWinData->imp_ptr->sem);
  761.  
  762.          /* Clear the input pipe, so that any unprocessed data is deleted.    */
  763.          /* The only way to do this is to close the pipe, and then reopen it. */
  764.         DosClose(pWinData->stdin_r);
  765.         DosClose(pWinData->stdin_w);
  766.         makepipe(&pWinData->stdin_r, STDIN, &pWinData->stdin_w, 4, PIPE_SIZE);
  767.         setinherit(pWinData->stdin_r, TRUE);
  768.         setinherit(pWinData->stdin_w, FALSE);
  769.  
  770.         WinSetFocus(HWND_DESKTOP, pWinData->insle);
  771.         break;
  772.       }
  773.  
  774.       case  REXX_MAKE_INVISIBLE :
  775.  
  776.         if (pWinData->visible) {
  777.           pWinData->visible = FALSE;   /* reset flag to invisible             */
  778.             WinShowWindow(pWinData->frame, FALSE);
  779.                                        /* Make it invisible.                  */
  780.         }
  781.         break;
  782.  
  783.       case  REXX_MAKE_VISIBLE :
  784.  
  785.          /* At start-up, the window is left invisible. When output or         */
  786.          /*   trace mode input occurs for the first time, this message is     */
  787.          /*   sent to make the window visible. It is at this time that        */
  788.          /*   the Help Manager gets initialized.                              */
  789.  
  790.         if (!pWinData->visible) {
  791.           HELPINIT hmiData;
  792.  
  793.           pWinData->visible = TRUE;    /* Set so we don't get called          */
  794.                                        /* unnecessarily                       */
  795.           RestoreWindow(hwnd, pWinData);/* From last invocation               */
  796.           WinShowWindow(pWinData->frame, TRUE);
  797.                                        /* Make it visible. Initialize the Help*/
  798.                                        /* Manager data structure              */
  799.           memset(&hmiData, '\0', sizeof hmiData);
  800.           hmiData.cb = sizeof(hmiData);
  801.           hmiData.pszHelpWindowTitle =
  802.               getstring(pWinData->hab, pWinData->hResource, PMREXX_HELP_TITLE);
  803.           hmiData.phtHelpTable = (PHELPTABLE)(PMREXX_HELPTABLE|RESOURCE_FLAG);
  804.           hmiData.pszHelpLibraryName =
  805.               getstring(pWinData->hab, pWinData->hResource, PMREXX_HELPFILENAME);
  806.           hmiData.fShowPanelId = CMIC_HIDE_PANEL_ID;
  807.           hmiData.hmodHelpTableModule = pWinData->hResource;
  808.           hmiData.hmodAccelActionBarModule = pWinData->hResource;
  809.           hmiData.idAccelTable = 0;
  810.           hmiData.idActionBar = 0;
  811.                                        /* Attempt to create help instance     */
  812.  
  813.           if (pWinData->HelpInst = WinCreateHelpInstance(pWinData->hab,
  814.               &hmiData)) {
  815.                                        /* If the create succeeded, then we    */
  816.                                        /* need to associate it with the frame */
  817.                                        /* window.                             */
  818.  
  819.             if (!WinAssociateHelpInstance(pWinData->HelpInst, pWinData->frame)) {
  820.                                        /* If the associate failed, inform the */
  821.                                        /* user and destroy the instance.      */
  822.               RHWinErrorBox(pWinData->hab, hwnd, pWinData->hResource,
  823.                   ERROR_HELPASSOC, MB_OK|MB_CUAWARNING);
  824.               WinDestroyHelpInstance(pWinData->HelpInst);
  825.               pWinData->HelpInst = NULLHANDLE;
  826.             }
  827.           }
  828.  
  829.           else {
  830.                                        /* If the create failed, inform the    */
  831.                                        /* user.                               */
  832.             RHWinErrorBox(pWinData->hab, hwnd, pWinData->hResource,
  833.                 ERROR_HELPCREATE, MB_OK|MB_CUAWARNING);
  834.           }
  835.           WinSetFocus(HWND_DESKTOP, pWinData->insle);
  836.  
  837.         }
  838.         break;
  839.  
  840.       case  RXIOB_MSGBOX : {           /* Put up a message box. The mp1       */
  841.                                        /* parameter has the resource ids for  */
  842.                                        /* the message and the title.          */
  843.           USHORT msgid = SHORT1FROMMP(mp1);
  844.           PUCHAR header = getstring(pWinData->hab, pWinData->hResource,
  845.               SHORT2FROMMP(mp1));
  846.           PUCHAR content = getstring(pWinData->hab, pWinData->hResource,
  847.               SHORT1FROMMP(mp1));
  848.                                        /* If we are                           */
  849.                                        /* displaying the ended message, set   */
  850.                                        /* the owner to the desktop so we don't*/
  851.                                        /* steal the focus back from other     */
  852.                                        /* apps.                               */
  853.  
  854.           LONG  rc = WinMessageBox(HWND_DESKTOP, hwnd, content, header,
  855.                                    msgid, SHORT1FROMMP(mp2));
  856.           free(header);
  857.           free(content);
  858.           return  MPFROMSHORT(rc);
  859.         }
  860.         break;
  861.  
  862.       case  START_TIMER :
  863.  
  864.          /* Start a timer to force output after a period of inactivity.       */
  865.  
  866.         if (!pWinData->visible) {      /* Make the window visible, if not     */
  867.                                        /* already.                            */
  868.           WinSendMsg(WinWindowFromID(hwnd, (USHORT)FID_CLIENT),
  869.                      REXX_MAKE_VISIBLE, (MPARAM)0, (MPARAM)0);
  870.         }
  871.         WinStartTimer(pWinData->hab, hwnd, pWinData->timer, TIMER_DELAY);
  872.         pWinData->imp_queued = FALSE;
  873.         break;
  874.  
  875.       case  ADD_STDOUTWIN :
  876.  
  877.          /* Add an output line to the MLE buffer, and start the timer.        */
  878.  
  879.         if (!pWinData->visible) {      /* Make the window visible, if not     */
  880.                                        /* already.                            */
  881.           WinSendMsg(WinWindowFromID(hwnd, (USHORT)FID_CLIENT),
  882.                      REXX_MAKE_VISIBLE, (MPARAM)0, (MPARAM)0);
  883.         }
  884.         if (pWinData->client == hwnd) {
  885.           HWND    wnd = pWinData->outmle;
  886.           PIMPORT im_ptr = pWinData->imp_ptr;
  887.           PUCHAR  ptr = (PUCHAR)im_ptr->data;
  888.           PUCHAR  tmp1 = (PUCHAR)mp1;  /* Obtain the buffer semaphore to      */
  889.                                        /* prevent interference with the input */
  890.                                        /* pipe thread.                        */
  891.  
  892.           DosRequestMutexSem(im_ptr->sem, SEM_INDEFINITE_WAIT);
  893.                                        /* If the string is too                */
  894.                                        /* large, break it up into pieces and  */
  895.                                        /* add to the window.                  */
  896.           while (strlen((const char *)tmp1) > (ULONG)IMPORTSIZE-HDRSIZE-1) {
  897.                                        /* Save the character we are about to  */
  898.                                        /* null out                            */
  899.             UCHAR tch = *(tmp1+IMPORTSIZE-HDRSIZE-1);
  900.                                        /* Add smaller string to the window    */
  901.             *(tmp1+IMPORTSIZE-HDRSIZE-1) = '\0';
  902.  
  903.             WinSendMsg(hwnd, ADD_STDOUTWIN, tmp1, (MPARAM)mp1);
  904.                                        /* Then bump the pointer and restore   */
  905.                                        /* the character.                      */
  906.             tmp1 += IMPORTSIZE - HDRSIZE - 1;
  907.             *tmp1 = tch;
  908.           }                            /* endwhile See if there is room left  */
  909.                                        /* in the buffer.                      */
  910.  
  911.           while (((im_ptr->total_size)-(im_ptr->inuse)) <= strlen((const char *)tmp1)) {
  912.                                        /* need to import what we have         */
  913.             WinStopTimer(pWinData->hab, hwnd, pWinData->timer);
  914.                                        /* empty the buffer                    */
  915.             Import(pWinData);
  916.           }
  917.  
  918.           strcat(ptr, (const char *)tmp1);           /* Copy the data to the end of the     */
  919.                                        /* buffer                              */
  920.           im_ptr->inuse = HDRSIZE+strlen((const char *)ptr);/* Reset the use count          */
  921.                                        /* and free the semaphore              */
  922.           DosReleaseMutexSem(im_ptr->sem);
  923.           free(mp1);                   /* free the text                       */
  924.                                        /* Start the timer to force output if  */
  925.                                        /* nothing added for the specified     */
  926.                                        /* time.                               */
  927.           WinStartTimer(pWinData->hab, hwnd, pWinData->timer, TIMER_DELAY);
  928.           pWinData->imp_queued = FALSE;
  929.           return (MRESULT)TRUE;
  930.         }
  931.  
  932.         return (MRESULT)FALSE;
  933.         break;
  934.  
  935.       case  HM_QUERY_KEYS_HELP :
  936.  
  937.         return (MRESULT)RX_KEYSHELP;
  938.  
  939.       case  WM_SAVEAPPLICATION :
  940.  
  941.         SaveWindow(pWinData);
  942.         break;
  943.  
  944.       default  :
  945.         break;
  946.     }
  947.     return (WinDefWindowProc(hwnd, msg, mp1, mp2));
  948.  
  949.   }
  950.  
  951. /************************** START OF SPECIFICATIONS ***************************/
  952. /*                                                                            */
  953. /*   SUBROUTINE NAME: RXIOCmds                                                */
  954. /*                                                                            */
  955. /*   DESCRIPTIVE NAME:                                                        */
  956. /*               Process WM_COMMAND messages for the window procedure.        */
  957. /*                                                                            */
  958. /*   FUNCTION:                                                                */
  959. /*               This routine processes all the WM_COMMAND messages that have */
  960. /*               been passed into the MainWndProc. The messages handled are:  */
  961. /*       RXIOA_TRCSTEP  - This requests that the REXX trace be advanced one   */
  962. /*                        step. It is equivalent to an input of a blank line  */
  963. /*                        to a REXX trace read. It is only valid when REXX is */
  964. /*                        waiting for trace input.                            */
  965. /*       RXIOA_TRCLAST  - This requests that the REXX re-trace the last       */
  966. /*                        clause executed. Is is equivalent to an input of an */
  967. /*                        equal sign to a REXX trace read. It is only valid   */
  968. /*                        when REXX is waiting for trace input.               */
  969. /*       RXIOA_TRCOFF   - This requests that the REXX turn off interactive    */
  970. /*                        tracing. Is is equivalent to an input of a "TRACE   */
  971. /*                        OFF" statement to a REXX trace read. It is only     */
  972. /*                        valid when REXX is waiting for trace input.         */
  973. /*       RXIOA_TRACE   - This is a request to turn interactive tracing on    */
  974. /*                        or off. It is only valid when the REXX procedure    */
  975. /*                        has ended and the user has not yet restarted it.    */
  976. /*                        This is because REXX only looks at the trace flag   */
  977. /*                        when it is first called to execute a procedure.     */
  978. /*       RXIOA_HALT     - This requests that the REXX HALT indicator be       */
  979. /*                        raised, requesting the procedure to be interrupted. */
  980. /*       RXIOA_CUT      - This is a request to remove the marked area of the  */
  981. /*                        focus window and place it onto the clipboard.       */
  982. /*       RXIOA_DELETE   - This is a request to delete the marked area of the  */
  983. /*                        focus window.                                       */
  984. /*       RXIOA_PASTE    - Paste from the clipboard into the input window.     */
  985. /*       RXIOA_COPY     - This is a request to copy the marked area of the    */
  986. /*                        focus window into the clipboard.                    */
  987. /*       RXIOA_ALL      - This is a request to mark the entire output area.   */
  988. /*       RXIOA_FONTS    - Present the user with a dialog to select a font for */
  989. /*                        the output window.                                  */
  990. /*                                                                            */
  991. /*   NOTES:                                                                   */
  992. /*                                                                            */
  993. /*   ENTRY POINT:                                                             */
  994. /*      LINKAGE:                                                              */
  995. /*       MRESULT RXIOCmds(HWND hwnd, MPARAM mp1, PRHWINDATA pWinData)         */
  996. /*                                                                            */
  997. /*   INPUT:                                                                   */
  998. /*       hwnd           - The window handle of the window that received the   */
  999. /*                        command.                                            */
  1000. /*       mp1            - The first parameter of the WM_COMMAND message.      */
  1001. /*       pWinData       - A pointer to the RHWINDATA structure of the window. */
  1002. /*                                                                            */
  1003. /*   EXIT-NORMAL:                                                             */
  1004. /*       returns TRUE if the file was saved successfully or user response     */
  1005. /*       from SAVEAS dialog.                                                  */
  1006. /*   EXIT-ERROR:                                                              */
  1007. /*       returns FALSE if the file was not saved successfully.                */
  1008. /*                                                                            */
  1009. /*   EFFECTS:                                                                 */
  1010. /*                                                                            */
  1011. /*   INTERNAL REFERENCES:                                                     */
  1012. /*      ROUTINES:                                                             */
  1013. /*       Add_Q_Element  - Adds an entry to an input queue.                    */
  1014. /*       RHWinErrorBox  - Display an error message box.                       */
  1015. /*       ClipBoard        - Perform clipboard related commands.               */
  1016. /*       SizeWindow     - Resize the child windows within the client area.  */
  1017. /*       SelectFont     - Interface to the font selection dialog              */
  1018. /*       SetCheckMark   - Check/uncheck a menu item                           */
  1019. /*                                                                            */
  1020. /*   EXTERNAL REFERENCES:                                                     */
  1021. /*      ROUTINES:                                                             */
  1022. /*       DosRequestMutexSem             WinInvalidateRect                     */
  1023. /*       DosReleaseMutexSem             WinLoadDlg                            */
  1024. /*       GpiQueryFontMetrics            WinLoadString                         */
  1025. /*       WinAlarm                       WinPostMessage                        */
  1026. /*       WinCreateWindow                WinReleasePS                          */
  1027. /*       WinDlgBox                      WinSendMsg                            */
  1028. /*       WinEnableWindowUpdate          WinShowWindow                         */
  1029. /*       WinGetPS                       WinWindowFromID                       */
  1030. /*                                                                            */
  1031. /*                                                                            */
  1032. /*                                                                            */
  1033. /*                                                                            */
  1034. /*                                                                            */
  1035. /**************************** END OF SPECIFICATIONS ***************************/
  1036.  
  1037. MRESULT RXIOCmds(HWND hwnd, MPARAM mp1, PRHWINDATA pWinData)
  1038. {
  1039.     CHAR Temp = '\0';                  /* temporary character                 */
  1040.                                        /* dialog                              */
  1041.     PLIST_ENTRY q_elem;                /* pointer for an element in the input */
  1042.                                        /* queue                               */
  1043.  
  1044.     switch (LOUSHORT(mp1)) {
  1045.  
  1046.       /************************************************************************/
  1047.       /* Append or overwrite output data it MLE                              */
  1048.       /************************************************************************/
  1049.  
  1050.       case  RXIOA_RESULTS :
  1051.  
  1052.         pWinData->RxResult = !pWinData->RxResult;
  1053.         SetCheckMark(pWinData->frame, RXIOA_RESULTS, pWinData->RxResult);
  1054.         WinSendMsg(pWinData->client, WM_COMMAND,
  1055.            MPFROMSHORT(PMRXA_RESULTCHANGE), (MPARAM)0);
  1056.         break;
  1057.  
  1058.       case  RXIOA_TRCSTEP :
  1059.  
  1060.          /* Trace the next clause. This is accomplished by inputting a        */
  1061.          /*   null line.                                                      */
  1062.  
  1063.         if (q_elem = malloc(sizeof(*q_elem))) {
  1064.           q_elem->ptr = strdup("");
  1065.           q_elem->len = strlen(q_elem->ptr);
  1066.           Add_Q_Element(&pWinData->trace_in, q_elem);
  1067.         }
  1068.         break;
  1069.  
  1070.       case  RXIOA_TRCLAST :
  1071.  
  1072.          /* Re-trace the previous clause. This is accomplished by             */
  1073.          /*   inputting an equal (=) sign alone on a line.                    */
  1074.  
  1075.         if (q_elem = malloc(sizeof(*q_elem))) {
  1076.           q_elem->ptr = strdup("=");
  1077.           q_elem->len = strlen(q_elem->ptr);
  1078.           Add_Q_Element(&pWinData->trace_in, q_elem);
  1079.         }
  1080.         break;
  1081.  
  1082.       case  RXIOA_TRCOFF :
  1083.  
  1084.          /* Turn tracing off by calling RexxResetTrace                        */
  1085.  
  1086.         RexxResetTrace(pWinData->proc_id, pWinData->rexx_tid);
  1087.         pWinData->tracebit = FALSE;
  1088.                                        /* Clear the checkmark                 */
  1089.                                        /* send a null line to end pause       */
  1090.         if (q_elem = malloc(sizeof(*q_elem))) {
  1091.           q_elem->ptr = strdup("trace off");
  1092.           q_elem->len = strlen(q_elem->ptr);
  1093.           Add_Q_Element(&pWinData->trace_in, q_elem);
  1094.         }
  1095.  
  1096.         SetCheckMark(pWinData->frame, RXIOA_TRACE, FALSE);
  1097.         WinSendMsg(pWinData->client, WM_COMMAND,
  1098.            MPFROMSHORT(PMRXA_FLAGCHANGE), (MPARAM)0);
  1099.  
  1100.         break;
  1101.  
  1102.       case  RXIOA_TRACE :
  1103.  
  1104.          /* Change the state of the interactive trace indiciator. This        */
  1105.          /*   will turn tracing on immediately (with the next phrase          */
  1106.          /*   executed).                                                      */
  1107.  
  1108.         if (pWinData->tracebit = (BOOL)(!pWinData->tracebit)) {
  1109.           RexxSetTrace(pWinData->proc_id, pWinData->rexx_tid);
  1110.         }
  1111.         else {
  1112.           RexxResetTrace(pWinData->proc_id, pWinData->rexx_tid);
  1113.         }
  1114.         SetCheckMark(pWinData->frame, RXIOA_TRACE, pWinData->tracebit);
  1115.         WinSendMsg(pWinData->client, WM_COMMAND,
  1116.            MPFROMSHORT(PMRXA_FLAGCHANGE), (MPARAM)1);
  1117.  
  1118.  
  1119.         break;
  1120.  
  1121.       case  RXIOA_HALT :
  1122.  
  1123.          /* Change the Halt Procedure indicator. This will cause REXX to      */
  1124.          /*   terminate execution of the procedure when the next phrase       */
  1125.          /*   is executed.                                                    */
  1126.  
  1127.         RexxSetHalt(pWinData->proc_id, pWinData->rexx_tid);
  1128.         /* If REXX is waiting for input, it won't halt until it gets          */
  1129.         /* some input, so feed it a blank line, just in case                  */
  1130.  
  1131.         if (q_elem = malloc(sizeof(*q_elem))) {
  1132.           q_elem->ptr = strdup("");
  1133.           q_elem->len = 0;
  1134.           if (pWinData->trace_inp) {
  1135.             Add_Q_Element(&pWinData->trace_in, q_elem);
  1136.           } else {
  1137.             Add_Q_Element(&pWinData->pipe_in, q_elem);
  1138.           } /* endif */
  1139.         }
  1140.         if (!pWinData->RxHalt) {
  1141.           pWinData->RxHalt = TRUE;
  1142.           SetCheckMark(pWinData->frame, RXIOA_HALT, pWinData->RxHalt);
  1143.         }
  1144.         break;
  1145.  
  1146.       /************************************************************************/
  1147.       /* These messages relate to clipboard operations                        */
  1148.       /************************************************************************/
  1149.  
  1150.       case  RXIOA_CUT :
  1151.  
  1152.         if (pWinData->infocus) {       /* clear the input window, because it  */
  1153.                                        /* has the focus                       */
  1154.           WinSendMsg(pWinData->insle, EM_CUT, (MPARAM)0, (MPARAM)0);
  1155.         }
  1156.         else {                         /* clear the MLE                       */
  1157.           ClipBoard(hwnd, MLM_CUT, RXIOH_ERR_CUT, pWinData);
  1158.         }
  1159.         break;
  1160.  
  1161.       case  RXIOA_DELETE :
  1162.  
  1163.         if (pWinData->infocus) {       /* clear the input window, because it  */
  1164.                                        /* has the focus                       */
  1165.           WinSendMsg(pWinData->insle, EM_CLEAR, (MPARAM)0, (MPARAM)0);
  1166.         }
  1167.         else {                         /* clear the MLE                       */
  1168.           ClipBoard(hwnd, MLM_CLEAR, RXIOH_ERR_DELETE, pWinData);
  1169.         }
  1170.         break;
  1171.  
  1172.       case  RXIOA_PASTE :
  1173.  
  1174.          /* put the text from the clipboard into the input window             */
  1175.  
  1176.         WinSendMsg(pWinData->insle, EM_PASTE, (MPARAM)0, (MPARAM)0);
  1177.         break;
  1178.  
  1179.       case  RXIOA_COPY :
  1180.  
  1181.         if (pWinData->infocus) {       /* Copy text from input window         */
  1182.           WinSendMsg(pWinData->insle, EM_COPY, (MPARAM)0, (MPARAM)0);
  1183.         }
  1184.         else {                         /* Get the text from the MLE           */
  1185.           ClipBoard(hwnd, MLM_COPY, RXIOH_ERR_COPY, pWinData);
  1186.         }
  1187.         break;
  1188.  
  1189.       /************************************************************************/
  1190.       /* Select all                                                           */
  1191.       /************************************************************************/
  1192.  
  1193.       case  RXIOA_ALL : {
  1194.  
  1195.           ULONG  usFileSize;
  1196.  
  1197.           WinEnableWindowUpdate(hwnd, FALSE);
  1198.                                        /* disable updates Get length of the   */
  1199.                                        /* output in the MLE                   */
  1200.           usFileSize = (ULONG )WinSendMsg(WinWindowFromID(hwnd,
  1201.                                           (USHORT)MLE_WNDW),
  1202.                                           MLM_QUERYTEXTLENGTH,
  1203.                                           (MPARAM)0, (MPARAM)0);
  1204.                                        /* Select all of the output in the MLE */
  1205.           WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  1206.                      MLM_SETSEL, (MPARAM)0L, MPFROMSHORT(usFileSize));
  1207.           WinInvalidateRect(hwnd, NULL, TRUE);
  1208.                                        /* update the window                   */
  1209.           WinEnableWindowUpdate(hwnd, TRUE);
  1210.                                        /* Make MLE so that it can't be undone */
  1211.           WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  1212.                      MLM_RESETUNDO, (MPARAM)0, (MPARAM)0);
  1213.           WinSetFocus(HWND_DESKTOP, pWinData->outmle);
  1214.         }
  1215.         break;
  1216.  
  1217.  
  1218.       /************************************************************************/
  1219.       /* DeSelect all                                                         */
  1220.       /************************************************************************/
  1221.  
  1222.       case  RXIOA_DALL : {
  1223.  
  1224.           ULONG  usFileSize;
  1225.  
  1226.           WinEnableWindowUpdate(hwnd, FALSE);
  1227.                                        /* disable updates Get length of the   */
  1228.                                        /* output in the MLE                   */
  1229.           usFileSize = 0;
  1230.                                      /* DeSelect all of the output in the MLE */
  1231.           WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  1232.                      MLM_SETSEL, (MPARAM)0L, MPFROMSHORT(usFileSize));
  1233.           WinInvalidateRect(hwnd, NULL, TRUE);
  1234.                                        /* update the window                   */
  1235.           WinEnableWindowUpdate(hwnd, TRUE);
  1236.                                        /* Make MLE so that it can't be undone */
  1237.           WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  1238.                      MLM_RESETUNDO, (MPARAM)0, (MPARAM)0);
  1239.           WinSetFocus(HWND_DESKTOP, pWinData->outmle);
  1240.         }
  1241.         break;
  1242.  
  1243.       /************************************************************************/
  1244.       /* Present Font dialog; the dialog will change the PS attribute         */
  1245.       /************************************************************************/
  1246.  
  1247.       case  RXIOA_FONTS :
  1248.         WinSendMsg(WinWindowFromID(hwnd, (USHORT) MLE_WNDW),
  1249.                    MLM_RESETUNDO, (MPARAM)0, (MPARAM)0);
  1250.         SelectFont(pWinData);
  1251.         break;
  1252.  
  1253.  
  1254.       /************************************************************************/
  1255.       /* Display the Search dialog.                                           */
  1256.       /************************************************************************/
  1257.  
  1258.       case  RXIOA_SEARCH :
  1259.         {
  1260.          CHAR           szSearchString[100];
  1261.          MLE_SEARCHDATA mlesrch;
  1262.          USHORT         usResult;
  1263.          SEARCHINFO     searchinfo;
  1264.  
  1265.          searchinfo.size = sizeof(SEARCHINFO);
  1266.          usResult = WinDlgBox(HWND_DESKTOP, hwnd, (PFNWP)SearchDlgProc,
  1267.                              (HMODULE)NULL, PMREXX_SEARCH, &searchinfo);
  1268.          if (usResult == PB_OK) {
  1269.            mlesrch.cb = sizeof(mlesrch);                   /* Structure size           */
  1270.            mlesrch.pchFind = searchinfo.szSearchString;    /* Search string            */
  1271.            mlesrch.pchReplace = NULL;                      /* No replacement string    */
  1272.            mlesrch.cchFind = 0;                            /* Not used                 */
  1273.            mlesrch.cchReplace = 0;                         /* Not used                 */
  1274.            mlesrch.iptStart = -1;                          /* Start at cursor position */
  1275.            mlesrch.iptStop = -1;                           /* Stop at end of file      */
  1276.            mlesrch.cchFound = 0;                            /* See if string was round  */
  1277.            if (searchinfo.caseSensitive) {
  1278.              WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  1279.                         MLM_SEARCH, MPFROMLONG(MLFSEARCH_CASESENSITIVE | MLFSEARCH_SELECTMATCH),
  1280.                         MPFROMP(&mlesrch));
  1281.            } else {
  1282.              WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  1283.                         MLM_SEARCH, MPFROMLONG(MLFSEARCH_SELECTMATCH),
  1284.                         MPFROMP(&mlesrch));
  1285.            } /* endif */
  1286.            if (mlesrch.cchFound < 1) {
  1287.              WinMessageBox(HWND_DESKTOP, NULLHANDLE,
  1288.                  getstring(pWinData->hab, pWinData->hResource, SEARCH_ERROR),
  1289.                  getstring(pWinData->hab, pWinData->hResource, SEARCH_TITLE), 1,
  1290.                  MB_OK|MB_INFORMATION|MB_MOVEABLE);
  1291.            } else {
  1292.              if (pWinData->infocus) {
  1293.                pWinData->infocus = FALSE;
  1294.                WinSetFocus(HWND_DESKTOP, pWinData->outmle);
  1295.              } /* endif */
  1296.            } /* endif */
  1297.          } /* endif */
  1298.         }
  1299.         break;
  1300.       /************************************************************************/
  1301.       /* Display Help for help panel                                          */
  1302.       /************************************************************************/
  1303.  
  1304.       case  RXIOM_HELPHELP :
  1305.  
  1306.         if (pWinData->HelpInst != NULLHANDLE) {
  1307.           WinSendMsg(pWinData->HelpInst, HM_DISPLAY_HELP, (MPARAM)0, (MPARAM)0);
  1308.         }
  1309.         else {
  1310.           WinSendMsg(pWinData->client,
  1311.                      RXIOB_MSGBOX,
  1312.                      MPFROM2SHORT(NO_HELP_MGR, HELP_ERR),
  1313.                      MPFROMLONG(MB_ENTER|MB_CUACRITICAL|MB_MOVEABLE));
  1314.         }
  1315.         break;
  1316.  
  1317.       /************************************************************************/
  1318.       /* Display Extended help panel                                          */
  1319.       /************************************************************************/
  1320.  
  1321.       case  RXIOM_EXTHELP :
  1322.  
  1323.         if (pWinData->HelpInst != NULLHANDLE) {
  1324.           WinSendMsg(pWinData->HelpInst, HM_EXT_HELP, (MPARAM)0, (MPARAM)0);
  1325.         }
  1326.         else {
  1327.           WinSendMsg(pWinData->client,
  1328.                      RXIOB_MSGBOX,
  1329.                      MPFROM2SHORT(NO_HELP_MGR, HELP_ERR),
  1330.                      MPFROMLONG(MB_ENTER|MB_CUACRITICAL|MB_MOVEABLE));
  1331.         }
  1332.         break;
  1333.  
  1334.       /************************************************************************/
  1335.       /* Display keys help panel                                              */
  1336.       /************************************************************************/
  1337.  
  1338.       case  RXIOM_KEYSHELP :
  1339.  
  1340.         if (pWinData->HelpInst != NULLHANDLE) {
  1341.           WinSendMsg(pWinData->HelpInst, HM_KEYS_HELP, (MPARAM)0, (MPARAM)0);
  1342.         }
  1343.         else {
  1344.           WinSendMsg(pWinData->client, RXIOB_MSGBOX,
  1345.                      MPFROM2SHORT(NO_HELP_MGR, HELP_ERR),
  1346.                      MPFROMLONG(MB_ENTER|MB_CUACRITICAL|MB_MOVEABLE));
  1347.         }
  1348.         break;
  1349.  
  1350.       /************************************************************************/
  1351.       /* Display help index                                                   */
  1352.       /************************************************************************/
  1353.  
  1354.       case  RXIOM_INDEXHELP :
  1355.  
  1356.         if (pWinData->HelpInst != NULLHANDLE) {
  1357.           WinSendMsg(pWinData->HelpInst, HM_HELP_INDEX, (MPARAM)0, (MPARAM)0);
  1358.         }
  1359.         else {
  1360.           WinSendMsg(pWinData->client, RXIOB_MSGBOX,
  1361.                      MPFROM2SHORT(NO_HELP_MGR, HELP_ERR),
  1362.                      MPFROMLONG(MB_ENTER|MB_CUACRITICAL|MB_MOVEABLE));
  1363.         }
  1364.         break;
  1365.  
  1366.       /************************************************************************/
  1367.       /* Option not implemented: Warn the user                                */
  1368.       /************************************************************************/
  1369.  
  1370.       default  :
  1371.         WinAlarm(HWND_DESKTOP, WA_ERROR);
  1372.     }                                  /* endswitch                           */
  1373.     return (MRESULT)FALSE;
  1374. }
  1375.  
  1376. /************************** START OF SPECIFICATIONS ***************************/
  1377. /*                                                                            */
  1378. /*   SUBROUTINE NAME: ClipBoard                                               */
  1379. /*                                                                            */
  1380. /*   DESCRIPTIVE NAME:                                                        */
  1381. /*               Process the MLE clipboard functions by passing the message   */
  1382. /*               on to the MLE window.                                        */
  1383. /*                                                                            */
  1384. /*   FUNCTION:                                                                */
  1385. /*               All of the clipboard related functions are handled very      */
  1386. /*               simliarly and so are just passed directly on to the MLE      */
  1387. /*               window for processing. In case of a failure, a message       */
  1388. /*               box is popped up to notify the user.                         */
  1389. /*                                                                            */
  1390. /*   NOTES:                                                                   */
  1391. /*                                                                            */
  1392. /*   ENTRY POINT:                                                             */
  1393. /*      LINKAGE:                                                              */
  1394. /*          CipBoard(hWnd, MLECMsg, ErrMsg, pWinData)                         */
  1395. /*                                                                            */
  1396. /*   INPUT:                                                                   */
  1397. /*       hWnd           - The handle of the window that received the message  */
  1398. /*       MLECMsg        - The message to be processed.                        */
  1399. /*       ErrMsg         - The resource ID of the error message to use in      */
  1400. /*                        case of an error.                                   */
  1401. /*                                                                            */
  1402. /*   EXIT-NORMAL:                                                             */
  1403. /*                                                                            */
  1404. /*   EXIT-ERROR:                                                              */
  1405. /*                                                                            */
  1406. /*   EFFECTS:                                                                 */
  1407. /*                                                                            */
  1408. /*   INTERNAL REFERENCES:                                                     */
  1409. /*      ROUTINES:                                                             */
  1410. /*                                                                            */
  1411. /*   EXTERNAL REFERENCES:                                                     */
  1412. /*      ROUTINES:                                                             */
  1413. /*       WinSendMsg                                                           */
  1414. /*       WinWindowFromID                                                      */
  1415. /*                                                                            */
  1416. /**************************** END OF SPECIFICATIONS ***************************/
  1417.  
  1418.   void ClipBoard(HWND hwnd, USHORT MLECMsg, ULONG ErrMsg,
  1419.       PRHWINDATA pWinData) {
  1420.  
  1421.    /* If an error occurs, put up a message box                                */
  1422.  
  1423.     if (!((MRESULT)WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
  1424.         MLECMsg, (MPARAM)0, (MPARAM)0)))
  1425.  
  1426.       WinSendMsg(pWinData->client, RXIOB_MSGBOX,
  1427.                  MPFROM2SHORT(ErrMsg, RXIOH_ERR_CLIPBRD),
  1428.                  MPFROMLONG(MB_ENTER|MB_CUACRITICAL|MB_MOVEABLE));
  1429.   }
  1430.  
  1431. /************************** START OF SPECIFICATIONS ***************************/
  1432. /*                                                                            */
  1433. /*   SUBROUTINE NAME: Import                                                  */
  1434. /*                                                                            */
  1435. /*   DESCRIPTIVE NAME:                                                        */
  1436. /*               Add the information collected into the import buffer into    */
  1437. /*               the MLE window.                                              */
  1438. /*                                                                            */
  1439. /*   FUNCTION:                                                                */
  1440. /*               Adding information to the MLE involves considerable          */
  1441. /*               overhead. To do so on each individual line would be          */
  1442. /*               unacceptably slow for any considerable amount of output.     */
  1443. /*               Therefore, output is collected into a buffer and output      */
  1444. /*               to the MLE when the buffer is full, or there has been no     */
  1445. /*               output added for some period of time. This is the routine    */
  1446. /*               to take the information collected in the buffer area and     */
  1447. /*               add it to the output window.                                 */
  1448. /*                                                                            */
  1449. /*   NOTES:                                                                   */
  1450. /*                                                                            */
  1451. /*   ENTRY POINT:                                                             */
  1452. /*      LINKAGE:                                                              */
  1453. /*          void Import(PRHWINDATA pWinData)                                  */
  1454. /*                                                                            */
  1455. /*   INPUT:                                                                   */
  1456. /*       pWinData       - Pointer to global control block.                    */
  1457. /*                                                                            */
  1458. /*   EXIT-NORMAL:                                                             */
  1459. /*                                                                            */
  1460. /*   EXIT-ERROR:                                                              */
  1461. /*                                                                            */
  1462. /*   EFFECTS:                                                                 */
  1463. /*                                                                            */
  1464. /*   INTERNAL REFERENCES:                                                     */
  1465. /*      ROUTINES:                                                             */
  1466. /*       RHWinErrorBox  - Display an error message box.                       */
  1467. /*                                                                            */
  1468. /*   EXTERNAL REFERENCES:                                                     */
  1469. /*      ROUTINES:                                                             */
  1470. /*       WinPostMsg                                                           */
  1471. /*       WinQueryWindow                                                       */
  1472. /*       WinSendMsg                                                           */
  1473. /*                                                                            */
  1474. /**************************** END OF SPECIFICATIONS ***************************/
  1475.  
  1476.   void Import(PRHWINDATA pWinData) {
  1477.     IPT ipt = (IPT)NULL;               /* Integer pointer type for MLE        */
  1478.  
  1479.  
  1480.     if (pWinData->imp_ptr->inuse > HDRSIZE) {
  1481.  
  1482.       /* Get the number of characters currently in the MLE                    */
  1483.  
  1484.       ipt = (IPT)WinSendMsg(pWinData->outmle, MLM_QUERYTEXTLENGTH,
  1485.           (MPARAM)0, (MPARAM)0);
  1486.  
  1487.       /* If we had an error setting up the transfer buffer, display a message */
  1488.  
  1489.       if (!WinSendMsg(pWinData->outmle, MLM_SETIMPORTEXPORT,
  1490.           pWinData->imp_ptr->data,
  1491.           MPFROMLONG(pWinData->imp_ptr->total_size-HDRSIZE))) {
  1492.         RHWinErrorBox(pWinData->hab, pWinData->outmle, pWinData->hResource,
  1493.             MLE_IMEXPORT_ERROR, MB_OK|MB_CUACRITICAL);
  1494.         WinPostMsg(WinQueryWindow(pWinData->outmle, QW_PARENT),
  1495.                    WM_CLOSE, (MPARAM)0, (MPARAM)0);
  1496.         return ;
  1497.       }
  1498.       WinEnableWindowUpdate(pWinData->outmle, FALSE);
  1499.  
  1500.       /* Set the MLE to not translate the input                               */
  1501.       WinSendMsg(pWinData->outmle, MLM_FORMAT, MPFROMSHORT(MLFIE_NOTRANS),
  1502.           (MPARAM)0);
  1503.  
  1504.       /* Set the MLE so we can add data to it                                 */
  1505.       WinSendMsg(pWinData->outmle, MLM_SETREADONLY, FALSE, (MPARAM)0);
  1506.  
  1507.       /* Add the data to the MLE, if we get an error, display a message       */
  1508.                                        /* upon return, point to end of data   */
  1509.       if (!WinSendMsg(pWinData->outmle, MLM_IMPORT, &ipt,
  1510.           MPFROMLONG(pWinData->imp_ptr->inuse-HDRSIZE))) {
  1511.  
  1512.         RHWinErrorBox(pWinData->hab, pWinData->outmle, pWinData->hResource,
  1513.             MLE_IMPORT_ERROR, MB_OK|MB_CUACRITICAL);
  1514.  
  1515.          /* It probably failed because the line is too long, so append a      */
  1516.          /* new line and try again.                                           */
  1517.         WinSendMsg(pWinData->outmle, MLM_SETSEL, MPFROMLONG(ipt),
  1518.             MPFROMLONG(ipt));
  1519.         WinSendMsg(pWinData->outmle, MLM_INSERT, "\r", (MPARAM)0);
  1520.  
  1521.          /* Move the selection to the end of the input                        */
  1522.         ipt = (IPT)WinSendMsg(pWinData->outmle, MLM_QUERYTEXTLENGTH, (MPARAM)0,
  1523.             (MPARAM)0);
  1524.  
  1525.         if (!WinSendMsg(pWinData->outmle, MLM_IMPORT, &ipt,
  1526.             MPFROMLONG(pWinData->imp_ptr->inuse-HDRSIZE) )) {
  1527.                                        /* If we still couldn't import         */
  1528.                                        /* anything, give up.                  */
  1529.           WinPostMsg(WinQueryWindow(pWinData->outmle, QW_PARENT),
  1530.                      WM_CLOSE, (MPARAM)0, (MPARAM)0);
  1531.         }
  1532.       }
  1533.  
  1534.       /* Update the ptr structure                                             */
  1535.  
  1536.       *(PUCHAR)(pWinData->imp_ptr->data) = '\0';
  1537.       pWinData->imp_ptr->inuse = HDRSIZE;
  1538.  
  1539.       /* Move the cursor to the end of the new data                           */
  1540.       WinSendMsg(pWinData->outmle, MLM_SETSEL, MPFROMLONG(ipt), MPFROMLONG(ipt));
  1541.  
  1542.       WinEnableWindowUpdate(pWinData->outmle, TRUE);
  1543.  
  1544.       /* Set the MLE to normal export mode                                    */
  1545.       WinSendMsg(pWinData->outmle, MLM_FORMAT, MLE_TXT_FMT, (MPARAM)0);
  1546.  
  1547.       /* Set the MLE back to readonly                                         */
  1548.       WinSendMsg(pWinData->outmle, MLM_SETREADONLY, MPFROMLONG(TRUE), (MPARAM)0);
  1549.  
  1550.     }
  1551.   }
  1552.  
  1553. /************************** START OF SPECIFICATIONS ***************************/
  1554. /*                                                                            */
  1555. /*   SUBROUTINE NAME: SizeWindow                                              */
  1556. /*                                                                            */
  1557. /*   DESCRIPTIVE NAME:                                                        */
  1558. /*               Size the MLE output window and the Entry Field input window  */
  1559. /*               to fit the client area.                                      */
  1560. /*                                                                            */
  1561. /*   FUNCTION:                                                                */
  1562. /*               Whenever the client window is sized, this routine is         */
  1563. /*               called to resize the MLE output window and the Entry Field   */
  1564. /*               control used for input to fit properly within the new        */
  1565. /*               client area.                                                 */
  1566. /*                                                                            */
  1567. /*   NOTES:                                                                   */
  1568. /*                                                                            */
  1569. /*   ENTRY POINT:                                                             */
  1570. /*      LINKAGE:                                                              */
  1571. /*          void SizeWindow(HWND hwnd, PRHWINDATA pWinData)                   */
  1572. /*                                                                            */
  1573. /*   INPUT:                                                                   */
  1574. /*       hwnd           - The handle of the client window.                    */
  1575. /*       pWinData       - A pointer to the RHWINDATA structure of the window. */
  1576. /*                                                                            */
  1577. /*   EXIT-NORMAL:                                                             */
  1578. /*                                                                            */
  1579. /*   EXIT-ERROR:                                                              */
  1580. /*                                                                            */
  1581. /*   EFFECTS:                                                                 */
  1582. /*                                                                            */
  1583. /*   INTERNAL REFERENCES:                                                     */
  1584. /*      ROUTINES:                                                             */
  1585. /*                                                                            */
  1586. /*   EXTERNAL REFERENCES:                                                     */
  1587. /*      ROUTINES:                                                             */
  1588. /*       WinQueryWindow                                                       */
  1589. /*       WinQueryWindowPos                                                    */
  1590. /*       WinSetWindowPos                                                      */
  1591. /*       WinWindowFromID                                                      */
  1592. /*                                                                            */
  1593. /**************************** END OF SPECIFICATIONS ***************************/
  1594.  
  1595.   void SizeWindow(HWND hwnd, PRHWINDATA pWinData) {
  1596.     HWND hOwner;                       /* Window handle of parent window      */
  1597.     SWP windowPos;                     /* info on window position             */
  1598.     ULONG  in_hgt = pWinData->in_hgt;  /* Height for input entry field        */
  1599.  
  1600.  
  1601.     if (!pWinData->visible)
  1602.       return ;                         /* If the window is not visible, do    */
  1603.                                        /* nothing                             */
  1604.     hOwner = WinQueryWindow(hwnd, QW_PARENT);
  1605.  
  1606.    /* Get Window positions                                                    */
  1607.     WinQueryWindowPos(WinWindowFromID(hOwner, (USHORT) FID_CLIENT), &windowPos);
  1608.  
  1609.    /* adjust MLE and input field, if created                                  */
  1610.     if (pWinData->outmle && pWinData->insle) {
  1611.  
  1612.       WinSetWindowPos(pWinData->outmle,   /* set window a bit smaller         */
  1613.                       HWND_TOP,
  1614.                       (SHORT)BORDER_MARGIN,
  1615.                       (SHORT)BORDER_MARGIN-1,
  1616.                       (SHORT)(windowPos.cx-(BORDER_MARGIN *2)+1),
  1617.                       (SHORT)(windowPos.cy-in_hgt-(BORDER_MARGIN *6)),
  1618.                       SWP_SIZE|SWP_MOVE|SWP_ZORDER|SWP_SHOW);
  1619.  
  1620.       WinSetWindowPos(pWinData->insle,   /* set window a bit smaller          */
  1621.                       HWND_TOP,
  1622.                       (SHORT)(BORDER_MARGIN *3+pWinData->wtitle),
  1623.                       (SHORT)(windowPos.cy-in_hgt-BORDER_MARGIN *3),
  1624.                       (SHORT)(windowPos.cx-BORDER_MARGIN *5-pWinData->wtitle),
  1625.                       (SHORT)pWinData->in_hgt,
  1626.                       SWP_SIZE|SWP_MOVE|SWP_ZORDER|SWP_SHOW);
  1627.     }
  1628.     return ;
  1629.   }
  1630.  
  1631. /************************** START OF SPECIFICATIONS ***************************/
  1632. /*                                                                            */
  1633. /*   SUBROUTINE NAME: io_routine                                              */
  1634. /*                                                                            */
  1635. /*   DESCRIPTIVE NAME:                                                        */
  1636. /*               Process the REXX IO exit.                                    */
  1637. /*                                                                            */
  1638. /*   FUNCTION:                                                                */
  1639. /*               This function has been registered to handle the IO exits     */
  1640. /*               for the REXX procedure. The interface is defined by REXXSAA. */
  1641. /*               For the input requests (RXSIOTRD and RXSIODTR), first the    */
  1642. /*               window is made visible, if it isn't already, and then the    */
  1643. /*               trace options are enabled/disabled as appropriate. Then      */
  1644. /*               a return code is set to allow normal operation of I/O by     */
  1645. /*               REXX.                                                        */
  1646. /*                                                                            */
  1647. /*   NOTES:                                                                   */
  1648. /*                                                                            */
  1649. /*   ENTRY POINT:                                                             */
  1650. /*      LINKAGE:                                                              */
  1651. /*          LONG  io_routine( LONG  exitno, LONG  subfunc, PUCHAR parmblock)  */
  1652. /*                                                                            */
  1653. /*   INPUT:                                                                   */
  1654. /*       The arguments are defined by the REXX interface specifications.      */
  1655. /*                                                                            */
  1656. /*   EXIT-NORMAL:                                                             */
  1657. /*                                                                            */
  1658. /*   EXIT-ERROR:                                                              */
  1659. /*                                                                            */
  1660. /*   EFFECTS:                                                                 */
  1661. /*                                                                            */
  1662. /*   INTERNAL REFERENCES:                                                     */
  1663. /*      ROUTINES:                                                             */
  1664. /*       Remove_Q_Element: Remove a queue element, wait if none there         */
  1665. /*       SetCheckMark   - Check/uncheck a menu item                           */
  1666. /*       SetOptions     - Enable/disable menu items.                          */
  1667. /*                                                                            */
  1668. /*   EXTERNAL REFERENCES:                                                     */
  1669. /*      ROUTINES:                                                             */
  1670. /*                                                                            */
  1671. /**************************** END OF SPECIFICATIONS ***************************/
  1672.  
  1673. LONG  io_routine(LONG  exitno, LONG  subfunc, PUCHAR parmblock)
  1674. {
  1675.     LONG           rc;                 /* rc=1 says use standard I/O routines */
  1676.     PLIST_ENTRY    q_elem;             /* entry in queue                      */
  1677.     RXSIOSAY_PARM *sparm = (RXSIOSAY_PARM *)parmblock;/* struc for IO exit    */
  1678.     PRHWINDATA     userdata[2];        /* registered user data                */
  1679.     PRHWINDATA     pWinData;           /* global data anchor                  */
  1680.     USHORT         exists;             /* existance flag                      */
  1681.  
  1682.                                        /* retrieve the anchor                 */
  1683.     if (RexxQueryExit(PMRXIO_EXIT, NULL, &exists, (PUCHAR)userdata))
  1684.                                        /* failed?                             */
  1685.       return RXEXIT_RAISE_ERROR;       /* raise a system failure error        */
  1686.  
  1687.     rc = RXEXIT_NOT_HANDLED;           /* let others go through               */
  1688.     pWinData = userdata[0];            /* get saved global anchor             */
  1689.  
  1690.     if (exitno == RXSIO) {
  1691.  
  1692.       switch (subfunc) {
  1693.  
  1694.         case  RXSIODTR :               /* For trace read we want to enable the*/
  1695.                                        /* trace menu items so we must perform */
  1696.                                        /* the read ourselves.                 */
  1697.                                        /* Enable all the options              */
  1698.           SetOptions(pWinData->frame, RXIOA_TRCSTEP, TRUE);
  1699.           SetOptions(pWinData->frame, RXIOA_TRCLAST, TRUE);
  1700.           SetOptions(pWinData->frame, RXIOA_TRCOFF, TRUE);
  1701.  
  1702.           if (!pWinData->tracebit) {   /* Set tracing active flag in menu     */
  1703.             SetCheckMark(pWinData->frame, RXIOA_TRACE,
  1704.                 (BOOL)(!pWinData->tracebit));
  1705.           }
  1706.           pWinData->trace_inp = TRUE;  /* Set the trace active flag for IO    */
  1707.           pWinData->in_type = TRC_IN;
  1708.  
  1709.           q_elem = Remove_Q_Element(&pWinData->trace_in);/* And get input     */
  1710.           pWinData->in_type = STD_IN;
  1711.           pWinData->trace_inp = FALSE; /* Reset the trace active flag for IO  */
  1712.                                        /* Disable all the options             */
  1713.           SetOptions(pWinData->frame, RXIOA_TRCSTEP, FALSE);
  1714.           SetOptions(pWinData->frame, RXIOA_TRCLAST, FALSE);
  1715.           SetOptions(pWinData->frame, RXIOA_TRCOFF, FALSE);
  1716.  
  1717.           if (!pWinData->tracebit) {   /* Reset the trace flag as appropriate */
  1718.             SetCheckMark(pWinData->frame, RXIOA_TRACE, pWinData->tracebit);
  1719.           }
  1720.  
  1721.          /* Copy the input line to the return area.                           */
  1722.  
  1723.           strcpy(sparm->rxsio_string.strptr, q_elem->ptr);
  1724.           sparm->rxsio_string.strlength = strlen(q_elem->ptr);
  1725.           free(q_elem->ptr);           /* And free the memory.                */
  1726.           free(q_elem);
  1727.           rc = RXEXIT_HANDLED;         /* Set the return code to              */
  1728.           break;                       /* input complete.                     */
  1729.  
  1730.         case  RXSIOTRD :               /* If a read occurs and the window is  */
  1731.                                        /* not visible, make it visible.       */
  1732.  
  1733.           if (!pWinData->visible) {
  1734.  
  1735.             while (!WinPostMsg(pWinData->client, (USHORT)REXX_MAKE_VISIBLE,
  1736.                 (MPARAM)0, (MPARAM)0)) {
  1737.               DosSleep((ULONG)TIMER_DELAY);
  1738.             }
  1739.           }
  1740.           break;
  1741.  
  1742.         default  :                     /* For all else, let REXX do the       */
  1743.           break;                       /* work.                               */
  1744.       }                                /* endswitch                           */
  1745.     }
  1746.     return  rc;
  1747. }
  1748.  
  1749. /************************** START OF SPECIFICATIONS ***************************/
  1750. /*                                                                            */
  1751. /*   SUBROUTINE NAME: stdinpipe                                               */
  1752. /*                                                                            */
  1753. /*   DESCRIPTIVE NAME:                                                        */
  1754. /*               Send input lines to the standard input of child processes.   */
  1755. /*                                                                            */
  1756. /*   FUNCTION:                                                                */
  1757. /*               This function is the thread that waits for input for child   */
  1758. /*               processes started by calls to the subcommand environment,    */
  1759. /*               passes that input through to the pipe connected to their     */
  1760. /*               standard input handle.                                       */
  1761. /*                                                                            */
  1762. /*   NOTES:                                                                   */
  1763. /*                                                                            */
  1764. /*   ENTRY POINT:                                                             */
  1765. /*      LINKAGE:                                                              */
  1766. /*          void stdinpipe()                                                  */
  1767. /*                                                                            */
  1768. /*   INTERNAL REFERENCES:                                                     */
  1769. /*      ROUTINES:                                                             */
  1770. /*       Remove_Q_Element - Removes an entry from an input queue. Waits for   */
  1771. /*                          one if the queue is empty.                        */
  1772. /*                                                                            */
  1773. /*   EXTERNAL REFERENCES:                                                     */
  1774. /*      ROUTINES:                                                             */
  1775. /*       DosWaitEventSem                                                      */
  1776. /*       DosWrite                                                             */
  1777. /*                                                                            */
  1778. /**************************** END OF SPECIFICATIONS ***************************/
  1779.  
  1780.   void stdinpipe(PRHWINDATA pWinData) {
  1781.     PLIST_ENTRY q_elem;                /* element from queue                  */
  1782.     UCHAR       str[ANSLEN+5];         /* data from queue entry               */
  1783.     ULONG       written;               /* bytes written by DosWrite           */
  1784.  
  1785.     while (TRUE) {
  1786.       q_elem = Remove_Q_Element(&pWinData->pipe_in);
  1787.       strcpy(str, q_elem->ptr);
  1788.       strcat(str, "\r\n");
  1789.  
  1790.       DosWrite(pWinData->stdin_w, str, strlen((const char *)str), &written);
  1791.       free(q_elem->ptr);
  1792.       free(q_elem);
  1793.     }
  1794.     DosExit(EXIT_THREAD, 0);           /* end the thread                      */
  1795.   }
  1796.  
  1797. /************************** START OF SPECIFICATIONS ***************************/
  1798. /*                                                                            */
  1799. /*   SUBROUTINE NAME: stdoutpipe                                              */
  1800. /*                                                                            */
  1801. /*   DESCRIPTIVE NAME:                                                        */
  1802. /*               Send lines from the standard output of child processes to    */
  1803. /*               the output window.                                           */
  1804. /*                                                                            */
  1805. /*   FUNCTION:                                                                */
  1806. /*               This function is the thread that waits for output from child */
  1807. /*               processes started by calls to the subcommand environment,    */
  1808. /*               passes that output through to the output window.             */
  1809. /*                                                                            */
  1810. /*   NOTES:                                                                   */
  1811. /*                                                                            */
  1812. /*   ENTRY POINT:                                                             */
  1813. /*      LINKAGE:                                                              */
  1814. /*          void stdoutpipe()                                                 */
  1815. /*                                                                            */
  1816. /*   INPUT:                                                                   */
  1817. /*                                                                            */
  1818. /*   EXIT-NORMAL:                                                             */
  1819. /*                                                                            */
  1820. /*   EXIT-ERROR:                                                              */
  1821. /*                                                                            */
  1822. /*   EFFECTS:                                                                 */
  1823. /*                                                                            */
  1824. /*   INTERNAL REFERENCES:                                                     */
  1825. /*      ROUTINES:                                                             */
  1826. /*       addline - Macro to add a line to the output window                   */
  1827. /*                                                                            */
  1828. /*   EXTERNAL REFERENCES:                                                     */
  1829. /*      ROUTINES:                                                             */
  1830. /*       DosPostEventSem                                                      */
  1831. /*       DosRequestMutexSem                                                   */
  1832. /*       DosReleaseMutexSem                                                   */
  1833. /*       DosWaitEventSem                                                      */
  1834. /*       DosSleep                                                             */
  1835. /*                                                                            */
  1836. /**************************** END OF SPECIFICATIONS ***************************/
  1837.  
  1838.   void stdoutpipe(PRHWINDATA pWinData) {
  1839.     UCHAR  buffer[MAXWIDTH];           /* holds data from standard out        */
  1840.     UCHAR  tchar = '\0';               /* temporary character variable        */
  1841.     PUCHAR tptr;                       /* character pointer                   */
  1842.     ULONG  len;                        /* counter                             */
  1843.     ULONG  nread;                      /* bytes read                          */
  1844.  
  1845.     USHORT         exists;             /* existance flag                      */
  1846.  
  1847.                                        /* retrieve the anchor                 */
  1848.     RexxQueryExit(PMRXIO_EXIT, NULL, &exists, NULL);
  1849.  
  1850.     while (!pWinData->stopoutpipe) {
  1851.  
  1852.       len = 0;                         /* initialize count back to 0          */
  1853.       buffer[0] = '\0';                /* initialize buffer                   */
  1854.  
  1855.       /* Loop here until we see a new line, or the buffer is full             */
  1856.       do {
  1857.         if (!DosRead(pWinData->stdout_r,&tchar, 1, &nread) && nread) {
  1858.           if (tchar == '\r') {
  1859.             DosRead(pWinData->stdout_r,&tchar, 1, &nread);
  1860.             if (tchar != '\n')
  1861.               buffer[len++] = '\n';
  1862.           }
  1863.           buffer[len++] = (UCHAR)tchar;
  1864.         }
  1865.       }
  1866.  
  1867.       while (len < MAXWIDTH-1 && tchar != '\n');
  1868.  
  1869.       buffer[len] = END_STR;           /* Terminate the string                */
  1870.  
  1871.       if (pWinData->stopoutpipe)       /* shutdown flag?                      */
  1872.         break;                         /* time to leave                       */
  1873.  
  1874.       /* Now add the data into the import structure, but first get            */
  1875.       /* the semaphore.                                                       */
  1876.  
  1877.       DosRequestMutexSem(pWinData->imp_ptr->sem, SEM_INDEFINITE_WAIT);
  1878.  
  1879.       /* If there is no more room in the import area, add the data            */
  1880.       if (pWinData->imp_ptr->total_size <= pWinData->imp_ptr->inuse+len+2) {
  1881.         DosReleaseMutexSem(pWinData->imp_ptr->sem);
  1882.         addline(pWinData->client, strdup((const char *)buffer));
  1883.  
  1884.          /* Give the MLE a chance to add the data                             */
  1885.  
  1886.         DosSleep((ULONG)TIMER_DELAY);
  1887.  
  1888.       /* There is room in the import area, so add the data                    */
  1889.  
  1890.       }
  1891.  
  1892.       else {
  1893.         tptr = (PUCHAR)pWinData->imp_ptr;
  1894.         strcat((tptr + pWinData->imp_ptr->inuse), (const char *)buffer);
  1895.         pWinData->imp_ptr->inuse += len;
  1896.         DosReleaseMutexSem(pWinData->imp_ptr->sem);
  1897.  
  1898.          /* Set (or reset) the timer                                          */
  1899.         if (!pWinData->imp_queued) {
  1900.           pWinData->imp_queued = TRUE;
  1901.  
  1902.           while (!WinPostMsg(pWinData->frame, START_TIMER, NULL, NULL)) {
  1903.             DosSleep((ULONG)TIMER_DELAY);
  1904.           }
  1905.         }
  1906.       }
  1907.     }                                  /* endwhile                            */
  1908.     DosExit(EXIT_THREAD, 0);           /* end the thread                      */
  1909.   }
  1910.  
  1911. /************************** START OF SPECIFICATIONS ***************************/
  1912. /*                                                                            */
  1913. /*   SUBROUTINE NAME: EntryDlgProc                                            */
  1914. /*                                                                            */
  1915. /*   DESCRIPTIVE NAME:                                                        */
  1916. /*               Dialog procedure for the input entry field.                  */
  1917. /*                                                                            */
  1918. /*   FUNCTION:                                                                */
  1919. /*               This is the Dialog Procedure that is registered to handle    */
  1920. /*               the messages coming into the dialog that establishes the     */
  1921. /*               input entry field. The messages that are handled are:        */
  1922. /*       WM_BUTTON1DBLCLK - Copy the marked area from the output window into  */
  1923. /*                          the input window.                                 */
  1924. /*       WM_BUTTON2DBLCLK - Same as pressing ENTER in the input window.       */
  1925. /*       WM_CHAR - several characters are processed here. These include:      */
  1926. /*         VK_NEWLINE   - take the data in the input window and place it on   */
  1927. /*                        current input queue, then clear the entry field.    */
  1928. /*         VK_UP        - place the last entered entry into the input field.  */
  1929. /*               All other messages and keys are handled by default           */
  1930. /*               processing.                                                  */
  1931. /*                                                                            */
  1932. /*   NOTES:                                                                   */
  1933. /*                                                                            */
  1934. /*   ENTRY POINT:                                                             */
  1935. /*      LINKAGE:                                                              */
  1936. /*          This is defined by the PM interface for dialog procedures.        */
  1937. /*                                                                            */
  1938. /*   INPUT:                                                                   */
  1939. /*       item           - The id of the item to enable/disable                */
  1940. /*       option         - TRUE to enable the option, FALSE to disable.        */
  1941. /*                                                                            */
  1942. /*   EXIT-NORMAL:                                                             */
  1943. /*                                                                            */
  1944. /*   EXIT-ERROR:                                                              */
  1945. /*                                                                            */
  1946. /*   EFFECTS:                                                                 */
  1947. /*                                                                            */
  1948. /*   INTERNAL REFERENCES:                                                     */
  1949. /*      ROUTINES:                                                             */
  1950. /*       addline        - Macro to add a line to the output window            */
  1951. /*       Add_Q_Element  - Adds an entry to an input queue.                    */
  1952. /*                                                                            */
  1953. /*                                                                            */
  1954. /*   EXTERNAL REFERENCES:                                                     */
  1955. /*      ROUTINES:                                                             */
  1956. /*       WinDefDlgProc                                                        */
  1957. /*       WinQueryWindow                                                       */
  1958. /*       WinQueryWindowPtr                                                    */
  1959. /*       WinQueryWindowText                                                   */
  1960. /*       WinSendMsg                                                           */
  1961. /*       WinSetFocus                                                          */
  1962. /*       WinSetWindowText                                                     */
  1963. /*                                                                            */
  1964. /**************************** END OF SPECIFICATIONS ***************************/
  1965.  
  1966. MRESULT EXPENTRY EntryDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) {
  1967.     static PUCHAR last_str[2] =  { NULL,NULL };
  1968.     LONG       len = ANSLEN;           /* length of input buffer              */
  1969.     UCHAR      str[ANSLEN+1];          /* holds data from input buffer        */
  1970.     LONG       len1;                   /* number of characters input          */
  1971.     WNDPARAMS  wp;                     /* struc to update input window        */
  1972.     HWND       hOwner;                 /* parent window handle                */
  1973.     IPT        start,end;              /* Insertion point for MLE             */
  1974.     PRHWINDATA pWinData;               /* pointer to WinData structure        */
  1975.  
  1976.     hOwner = WinQueryWindow(hwnd, QW_PARENT);
  1977.     pWinData = WinQueryWindowPtr(hOwner, (SHORT)0);
  1978.  
  1979.     switch (msg) {
  1980.  
  1981.       case  WM_SETFOCUS :
  1982.  
  1983.         pWinData->infocus = (BOOL)(mp2?TRUE:FALSE);
  1984.         break;
  1985.  
  1986.       case  WM_BUTTON1DBLCLK :
  1987.  
  1988.         start = (IPT)WinSendMsg(pWinData->outmle, MLM_QUERYSEL,
  1989.             MPFROMSHORT(1), (MPARAM)0);
  1990.         end = (IPT)WinSendMsg(pWinData->outmle, MLM_QUERYSEL,
  1991.                               MPFROMSHORT(2), (MPARAM)0);
  1992.  
  1993.         if (end > start) {
  1994.           PUCHAR ptr = (PUCHAR)malloc((LONG )(end-start+2));
  1995.           ULONG len = end-start;
  1996.           ULONG got;
  1997.  
  1998.           if (ptr && WinSendMsg(pWinData->outmle, MLM_SETIMPORTEXPORT, ptr,
  1999.               MPFROMLONG(end-start+1))) {
  2000.  
  2001.             if (got = (ULONG)WinSendMsg(pWinData->outmle, MLM_EXPORT,
  2002.                 MPFROMLONG(&start), MPFROMLONG(&len))) {
  2003.               PUCHAR ptr1 = ptr;
  2004.               PUCHAR ptr2;
  2005.  
  2006.               while (!*ptr1)
  2007.                 ptr1++;                /* Skip over any nulls.                */
  2008.               ptr2 = ptr1;             /* Now find the end                    */
  2009.  
  2010.               while (*ptr2 &&          /* at NULL, newline or                 */
  2011.                   (*ptr2 != '\n') &&   /* carraige return.                    */
  2012.                   *ptr2 != '\r' && ptr2-ptr < (INT)got)
  2013.                 *ptr2++;
  2014.               *(ptr2) = '\0';
  2015.               WinSetWindowText(hwnd,
  2016.                                ptr1);  /* Put into SLE                        */
  2017.             }
  2018.           }
  2019.  
  2020.           if (ptr) {
  2021.             free(ptr);
  2022.           }
  2023.         }
  2024.         break;
  2025.  
  2026.       case  WM_BUTTON2DBLCLK :
  2027.  
  2028.         WinSendMsg(hwnd, WM_CHAR, MPFROM2SHORT(KC_VIRTUALKEY, NULL),
  2029.                    MPFROM2SHORT(NULL, VK_NEWLINE));
  2030.         break;
  2031.  
  2032.       case  WM_CHAR :
  2033.  
  2034.         if (!(SHORT1FROMMP(mp1)&KC_KEYUP) &&
  2035.             (SHORT1FROMMP(mp1)&KC_VIRTUALKEY) ) {
  2036.  
  2037.           switch (SHORT2FROMMP(mp2)) {
  2038.  
  2039.             case  VK_BREAK :
  2040.               WinSendMsg(pWinData->client, WM_COMMAND,
  2041.                   MPFROMSHORT(RXIOA_HALT), (MPARAM)0);
  2042.               break;
  2043.  
  2044.             case  VK_NEWLINE :
  2045.             case  VK_ENTER : {
  2046.  
  2047.                 PLIST_ENTRY qe = malloc(sizeof *qe);
  2048.  
  2049.                 len1 = WinQueryWindowText(hwnd, (SHORT)len, str);
  2050.  
  2051.                 if (qe) {
  2052.                   PUCHAR str1 = malloc(len1+4);
  2053.  
  2054.                   if (last_str[pWinData->in_type]) {
  2055.                     free(last_str[pWinData->in_type]);
  2056.                   }
  2057.                   memcpy(str1, str, len1);
  2058.                   strcpy(str1+len1, "\n");
  2059.                                        /* only add input if executing         */
  2060.                   last_str[pWinData->in_type] = strdup((const char *)str1);
  2061.  
  2062.                   addline(pWinData->client, strdup((const char *)str1));
  2063.                   qe->len = len1;
  2064.                   qe->ptr = strdup((const char *)str);
  2065.                   *(str+len1) = '\0';
  2066.  
  2067.                   if (pWinData->trace_inp) {
  2068.                     Add_Q_Element(&pWinData->trace_in, qe);
  2069.                   }
  2070.  
  2071.                   else {
  2072.                     Add_Q_Element(&pWinData->pipe_in, qe);
  2073.                   }
  2074.                   free(str1);
  2075.                 }
  2076.               }
  2077.               WinSendMsg(hwnd, EM_SETSEL, MPFROM2SHORT(0, len1), (MPARAM)0);
  2078.               WinSendMsg(hwnd, EM_CLEAR, (MPARAM)0, (MPARAM)0);
  2079.               return (MRESULT)TRUE;
  2080.               break;
  2081.  
  2082.             case  VK_UP :
  2083.  
  2084.               if (last_str[pWinData->in_type]) {
  2085.                 WinSendMsg(hwnd, EM_SETSEL, MPFROM2SHORT(0, len1), (MPARAM)0);
  2086.                 WinSendMsg(hwnd, EM_CLEAR, (MPARAM)0, (MPARAM)0);
  2087.                 *(last_str[pWinData->in_type] +
  2088.                     strlen((const char *)last_str[pWinData->in_type])-1) = '\0';
  2089.                 wp.fsStatus = WPM_TEXT+WPM_CCHTEXT;
  2090.                 wp.cchText = (SHORT)strlen((const char *)last_str[pWinData->in_type]);
  2091.                 wp.pszText = strdup((const char *)last_str[pWinData->in_type]);
  2092.                 WinSendMsg(hwnd, WM_SETWINDOWPARAMS, &wp, (MPARAM)0);
  2093.                 *(last_str[pWinData->in_type] +
  2094.                     strlen((const char *)last_str[pWinData->in_type])) = '\r';
  2095.                 return (MRESULT)TRUE;
  2096.               }
  2097.               break;
  2098.  
  2099.             case  VK_TAB :
  2100.             case  VK_BACKTAB :
  2101.  
  2102.               return (MRESULT)WinSetFocus(HWND_DESKTOP,
  2103.                   pWinData->infocus?pWinData->outmle: pWinData->insle);
  2104.               break;
  2105.  
  2106.             default  :
  2107.               break;
  2108.           }
  2109.         }
  2110.       default  :
  2111.         break;
  2112.     }
  2113.     return  WinDefDlgProc(hwnd, msg, mp1, mp2);
  2114.   }
  2115.  
  2116. /************************** START OF SPECIFICATIONS ***************************/
  2117. /*                                                                            */
  2118. /*   SUBROUTINE NAME: SelectFont                                              */
  2119. /*                                                                            */
  2120. /*   DESCRIPTIVE NAME:                                                        */
  2121. /*               Interface to the Font Selection dialog.                      */
  2122. /*                                                                            */
  2123. /*   FUNCTION:                                                                */
  2124. /*               This routine sets up the parameters and calls the Font       */
  2125. /*               Selection dialog routines. Responses from the dialog will    */
  2126. /*               be via WM_CONTROL messages to the parent window procedure.   */
  2127. /*                                                                            */
  2128. /*   NOTES:                                                                   */
  2129. /*                                                                            */
  2130. /*   ENTRY POINT:                                                             */
  2131. /*      LINKAGE:                                                              */
  2132. /*          ULONG  SelectFont(PRHWINDATA pWinData)                            */
  2133. /*                                                                            */
  2134. /*   INPUT:                                                                   */
  2135. /*       pWinData       - Pointer to the WinData structure of the parent      */
  2136. /*                        window.                                             */
  2137. /*                                                                            */
  2138. /*   EXIT-NORMAL:                                                             */
  2139. /*                                                                            */
  2140. /*   EXIT-ERROR:                                                              */
  2141. /*                                                                            */
  2142. /*   EFFECTS:                                                                 */
  2143. /*                                                                            */
  2144. /*   INTERNAL REFERENCES:                                                     */
  2145. /*      ROUTINES:                                                             */
  2146. /*       FontDialog - Load and initialize the Font dialog                     */
  2147. /*                                                                            */
  2148. /*   EXTERNAL REFERENCES:                                                     */
  2149. /*      ROUTINES:                                                             */
  2150. /*       WinProcessDlg                                                        */
  2151. /*       WinSendMsg                                                           */
  2152. /*                                                                            */
  2153. /**************************** END OF SPECIFICATIONS ***************************/
  2154.  
  2155.   ULONG  SelectFont(PRHWINDATA pWinData) {
  2156.     PFONTDLG   fntd;                   /* font dialog control                 */
  2157.     BOOL       rc;                     /* success/failure flag                */
  2158.  
  2159.     fntd = &pWinData->MleFontAttrs;    /* point to control structure          */
  2160.     fntd->cbSize = sizeof(FONTDLG);
  2161.     if (!fntd->pszFamilyname)         {/* do first time set up               */
  2162.                                        /* set the buffer                     */
  2163.       fntd->pszFamilyname = pWinData->MleFamilyName;
  2164.       strcpy(fntd->pszFamilyname, fntd->fAttrs.szFacename);
  2165.       fntd->fxPointSize = MAKEFIXED(8,0);
  2166.     }
  2167.     fntd->pszPreview = getstring(pWinData->hab, pWinData->hResource,
  2168.         SAMPLE_TEXT);
  2169.     fntd->pszTitle = getstring(pWinData->hab, pWinData->hResource,
  2170.         FONT_TITLE);
  2171.     fntd->fl = FNTS_CENTER + FNTS_HELPBUTTON;
  2172.     fntd->clrFore = CLR_NEUTRAL;    /* Selected foreground color */
  2173.     fntd->clrBack = CLR_BACKGROUND; /* Selected Background color */
  2174.     fntd->usWeight = FWEIGHT_NORMAL;
  2175.     fntd->usWidth = FWIDTH_NORMAL;
  2176.     fntd->hpsScreen = WinGetPS(pWinData->outmle);
  2177.     fntd->fAttrs.usCodePage = (USHORT)pWinData->CountryInfo.codepage;
  2178.     fntd->clrFore = CLR_BLACK;
  2179.     fntd->clrBack = CLR_WHITE;
  2180.     fntd->usFamilyBufLen = MAXWIDTH;
  2181.     fntd->pszPtSizeList = NULL;        /* use default point sizes*/
  2182.     rc = TRUE;
  2183.  
  2184.     /* Disable the window for update, and call the font dialog   */
  2185.     WinEnableWindowUpdate(pWinData->outmle, FALSE);
  2186.     if (!WinFontDlg(HWND_DESKTOP, pWinData->frame, fntd) ||
  2187.         fntd->lReturn != DID_OK) {
  2188.       rc = FALSE;
  2189.       } else {
  2190.  
  2191.        /**********************************************************/
  2192.        /* If outline font, calculate the maxbaselineext and      */
  2193.        /*  avecharwidth for the point size selected              */
  2194.        /**********************************************************/
  2195.        if ( fntd->fAttrs.fsFontUse == FATTR_FONTUSE_OUTLINE )
  2196.        {
  2197.          HDC   hDC;
  2198.          LONG  lxFontResolution;
  2199.          LONG  lyFontResolution;
  2200.          SIZEF sizef;
  2201.  
  2202.          /********************************************************/
  2203.          /* Query device context for the screen and then query   */
  2204.          /* the resolution of the device for the device context. */
  2205.          /********************************************************/
  2206.          hDC = GpiQueryDevice(fntd->hpsScreen);
  2207.          DevQueryCaps( hDC, CAPS_HORIZONTAL_FONT_RES,
  2208.                        (LONG)1, &lxFontResolution);
  2209.          DevQueryCaps( hDC, CAPS_VERTICAL_FONT_RES,
  2210.                        (LONG)1, &lyFontResolution);
  2211.  
  2212.          /********************************************************/
  2213.          /* Calculate the size of the character box, based on the*/
  2214.          /* point size selected and the resolution of the device.*/
  2215.          /* The size parameters are of type FIXED, NOT int.      */
  2216.          /*  NOTE: 1 point == 1/72 of an inch.                   */
  2217.          /********************************************************/
  2218.          sizef.cx = (FIXED)(((fntd->fxPointSize) / 72 ) *
  2219.                            lxFontResolution );
  2220.          sizef.cy = (FIXED)(((fntd->fxPointSize) / 72 ) *
  2221.                            lyFontResolution );
  2222.  
  2223.          fntd->fAttrs.lMaxBaselineExt =
  2224.                                MAKELONG( HIUSHORT( sizef.cy ), 0 );
  2225.          fntd->fAttrs.lAveCharWidth =
  2226.                                MAKELONG( HIUSHORT( sizef.cx ), 0 );
  2227.         }/* endif fsFontUse == FATTR_FONTUSE_OUTLINE */
  2228.  
  2229.  
  2230.       } /* endif !WinFontDlg */
  2231.     WinReleasePS(fntd->hpsScreen);
  2232.  
  2233.     if (rc) {
  2234.       WinSendMsg(pWinData->outmle,     /* set font of multiline edit field    */
  2235.           MLM_SETFONT, MPFROMP((PFATTRS)&fntd->fAttrs), (MPARAM)0);
  2236.     }
  2237.     WinEnableWindowUpdate(pWinData->outmle, TRUE);
  2238.     free(fntd->pszTitle);
  2239.     free(fntd->pszPreview);
  2240.     return (TRUE);
  2241.   }
  2242.  
  2243.  
  2244. /************************** START OF SPECIFICATIONS ***************************/
  2245. /*                                                                            */
  2246. /*   SUBROUTINE NAME: SearchDlgProc                                           */
  2247. /*                                                                            */
  2248. /*   DESCRIPTIVE NAME: Search Dialog Procedure                                */
  2249. /*                                                                            */
  2250. /*   FUNCTION:                                                                */
  2251. /*               This routine is the dialog procedure for diaply of the       */
  2252. /*               Search dialog.                                               */
  2253. /*                                                                            */
  2254. /*   NOTES:                                                                   */
  2255. /*                                                                            */
  2256. /*   ENTRY POINT:                                                             */
  2257. /*      LINKAGE: Standard Dialog procedure interface.                         */
  2258. /*                                                                            */
  2259. /*   INPUT: Standard Dialog procedure interface.                              */
  2260. /*                                                                            */
  2261. /*   EXIT-NORMAL:                                                             */
  2262. /*                                                                            */
  2263. /*   EXIT-ERROR:                                                              */
  2264. /*                                                                            */
  2265. /*   EFFECTS:                                                                 */
  2266. /*                                                                            */
  2267. /*   INTERNAL REFERENCES:                                                     */
  2268. /*      ROUTINES:                                                             */
  2269. /*                                                                            */
  2270. /*   EXTERNAL REFERENCES:                                                     */
  2271. /*      ROUTINES:                                                             */
  2272. /*        WinDefDlgProc                                                       */
  2273. /*        WinDismissDlg                                                       */
  2274. /*                                                                            */
  2275. /**************************** END OF SPECIFICATIONS ***************************/
  2276.  
  2277. MRESULT EXPENTRY SearchDlgProc(HWND hdlg, ULONG msg, MPARAM mp1,
  2278.                                MPARAM mp2)
  2279. {
  2280.    HWND hwndEntryFld;
  2281.    static PSZ szSearchString;
  2282.    static PSEARCHINFO psearchinfo;
  2283.  
  2284.     switch (msg) {
  2285.       case  WM_CLOSE :
  2286.          WinSendMsg(hdlg, WM_COMMAND, MPFROMSHORT(PB_CANCEL),
  2287.                     MPFROM2SHORT (CMDSRC_PUSHBUTTON, TRUE));
  2288.          return 0;
  2289.  
  2290.       case  WM_INITDLG :
  2291.          psearchinfo = (PSEARCHINFO)mp2;
  2292.          return 0;
  2293.  
  2294.       case  WM_COMMAND :
  2295.       {
  2296.         switch(SHORT1FROMMP(mp1))
  2297.         {
  2298.           case PB_OK:
  2299.             hwndEntryFld = WinWindowFromID(hdlg, RX_SEARCH_FIELD);
  2300.             WinQueryWindowText(hwndEntryFld, 100,
  2301.                psearchinfo->szSearchString);
  2302.             if ((BOOL)WinSendDlgItemMsg(hdlg, RX_CASEBOX,
  2303.                                         BM_QUERYCHECK, NULL, NULL)) {
  2304.                psearchinfo->caseSensitive = TRUE;
  2305.             } else {
  2306.                psearchinfo->caseSensitive = FALSE;
  2307.             } /* endif */
  2308.             WinDismissDlg(hdlg, PB_OK);
  2309.             return 0;
  2310.  
  2311.           case PB_CANCEL:
  2312.            WinDismissDlg(hdlg, PB_CANCEL);
  2313.            break;
  2314.         }
  2315.       }
  2316.  
  2317.     }
  2318.     return WinDefDlgProc(hdlg, msg, mp1, mp2);
  2319. }
  2320.  
  2321.