home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
VSCPPv8.zip
/
VACPP
/
IBMCPP
/
samples
/
TOOLKIT
/
CREXX
/
PMREXX
/
PMREXXIO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-17
|
122KB
|
2,109 lines
/* static char *SCCSID = "@(#)pmrexxio.c 6.3 91/12/24"; */
/********************* START OF SPECIFICATIONS ******************************/
/* */
/* SOURCE FILE NAME: pmrexxio.c */
/* */
/* DESCRIPTIVE NAME: PM I/O environment for REXX command files. */
/* */
/* Provide a means for REXX command files to do Pull, Say and */
/* Trace interactions when called from a PM application by simulating */
/* stdin, stdout and stderr I/O operations. */
/* */
/* COPYRIGHT: IBM Corporation 1991 */
/* */
/* STATUS: Version 2.00 */
/* */
/* FUNCTION: */
/* This program provides a Presentation Manager Shell for */
/* RexxStart programs. */
/* */
/* */
/* NOTES: */
/* DEPENDENCIES: */
/* This function has dependencies on the following */
/* files for compilation. */
/* pmrexxio.h - Definitions for control of the PMREXXIO */
/* dialog. */
/* pmrxiodt.h - Definitions necessary for the resource */
/* file compilation. */
/* rhdtatyp.h - Macros, structures, typedefs and defines */
/* local to and necessary for this program. */
/* The C runtime multi-threaded header files */
/* */
/* EXECUTION INSTRUCTIONS: */
/* PMREXXIO is invoked via a call to RexxCreateIOWindow. */
/* This call redirects stdin, stdout and stderr to pips which */
/* are processed by PMREXXIO. The calling application enables */
/* execution of a Rexx program by posting message REXX_STARTPROC, */
/* passing the id of the thread the Rexx program will execute on. */
/* On completion of the Rexx program, the message REXX_ENDPROC */
/* should be sent to the window. RexxDestroyIOWindow should be */
/* called to perform cleanup of the I/O resources at program */
/* termination. */
/* */
/* EXPECTED OUTPUT: */
/* The REXX procedure file will be executed with all */
/* output directed into PM windows. */
/* */
/* PROCEDURES: */
/* RexxCreateIOWindow: Initialize I/O subsystem */
/* RexxDestroyIOWindow: Terminate I/O subsystem */
/* EntryDlgProc: Dialog procedure for the input entry field */
/* initialize: Initialize data structures and threads */
/* io_routine: Process the REXX IO system exit */
/* MainWndProc: Main window procedure */
/* SizeWindow: Size the output window and input window */
/* ClipBoard: Process MLE clipboard functions */
/* RXIOCmds: Process WM_COMMAND messages from the main window proc */
/* Import: Add information from import buffer to the MLE */
/* SelectFont: Interface to the font selection dialog */
/* stdinpipe: Send input to the standard input of a child process */
/* stdoutpipe: Send standard output from child proc to output window */
/* */
/*********************** END OF SPECIFICATIONS ******************************/
#include <malloc.h>
#include <process.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Define the sections of the OS/2 header files that we need. */
#define INCL_RXSYSEXIT /* REXX system exits */
#define INCL_RXARI /* REXX Asynchronous Request Interface */
#define INCL_DOSSEMAPHORES /* OS/2 semaphore support */
#define INCL_DOSERRORS /* OS/2 errors */
#define INCL_DOSPROCESS /* Process and thread support */
#define INCL_DOSQUEUES /* Queues */
#define INCL_DOSMISC /* Miscellaneous doscalls */
#define INCL_DOSNLS /* NLS (code page) support */
#define INCL_DOSMODULEMGR /* OS/2 module support */
#define INCL_GPILCIDS /* Physical and logical fonts with */
/* lcids */
#define INCL_GPIPRIMITIVES /* Drawing primitives and primitive */
/* attributes */
#define INCL_WINCOUNTRY /* Code page support */
#define INCL_WINDIALOGS /* Dialog boxes */
#define INCL_WINENTRYFIELDS /* Entry fields */
#define INCL_WINFRAMEMGR /* Frame manager */
#define INCL_WINHELP /* Help manager definitions */
#define INCL_WININPUT /* Mouse and keyboard input */
#define INCL_WINMESSAGEMGR /* Message management */
#define INCL_WINSHELLDATA /* Profile calls */
#define INCL_WINSWITCHLIST /* Task list calls */
#define INCL_WINTIMER /* Timer routines */
#define INCL_WINWINDOWMGR /* General window management */
#define INCL_WINMENUS /* Menu controls */
#define INCL_WINMLE /* Multiple line edit fields */
#define INCL_WINPOINTERS /* Mouse pointers */
#define INCL_WINSTDFONT /* Standard Font dialog */
#define INCL_WINERRORS /* Standard Font dialog */
#include <os2.h>
#include <rexxsaa.h> /* Include the REXX header file */
/* Defines, typedefs and function prototypes for pmrexx */
#include "rhdtatyp.h"
#include "pmrxiodt.h"
#include "pmrexxio.h"
/************************** START OF SPECIFICATIONS ***************************/
/* */
/* SUBROUTINE NAME: RexxCreateIOWindow */
/* */
/* DESCRIPTIVE NAME: */
/* Initialize a Rexx stdin/stdout/stderr transaction subsystem. */
/* */
/* FUNCTION: */
/* Creates Rexx I/O windows and redirects stdin, stdout, and */
/* stderr to pipes. */
/* */
/* NOTES: */
/* */
/* ENTRY POINT: */
/* LINKAGE: RexxCreateIOWindow(HWND hwndOwner, PHWND phwndClient) */
/* */
/* INPUT: */
/* phwndClient is the handle of the I/O window client window. */
/* */
/* EXIT-NORMAL: */
/* Exit with handle to I/O frame window. */
/* */
/* EXIT-ERROR: */
/* If unable to duplicate the write handle for stderr pipe, exit rc=5. */
/* If unable to register the window class, exit rc=1. */
/* If no procedure name was specified, exit with rc=3. */
/* If window was not displayed, exit with return code from the REXX */
/* procedure. */
/* Otherwise: exit with created frame and client handles. */
/* */
/* EFFECTS: */
/* Initializes the Rexx Presentation Manager I/O subsystem. */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: */
/* getstring - To obtain the title bar name and window name. */
/* initialize - Sets up the environment for the program. Starts all */
/* necessary threads, sets up the input queues, etc. */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* WinQueryAnchorBlock WinRegisterClass */
/* WinCreateStdWindow */
/* */
/**************************** END OF SPECIFICATIONS ***************************/
HWND RexxCreateIOWindow(
HWND hwndOwner, /* Owner handle */
PHWND phwndClient) /* Returned client window */
{
/* We set the creation flags to be the standard window frame flags */
/* but without scroll bars and without a task list entry. */
ULONG flCreate = FCF_STANDARD&~(FCF_VERTSCROLL|FCF_HORZSCROLL|FCF_ACCELTABLE);
PUCHAR windowtext; /* Text for title bar */
ULONG argnum = 1; /* Counter for looking at arguments */
HAB hab; /* anchor block */
HMODULE handle; /* module handle */
HWND hwndFrame; /* frame handle */
/* get desktop anchor */
hab = WinQueryAnchorBlock(hwndOwner);
if (!hab) { /* no anchor block? */
return NULLHANDLE; /* return with nothing */
}
if (DosQueryModuleHandle(MODULE_NAME, &handle)) {
return NULLHANDLE; /* return with nothing */
}
if (!WinRegisterClass( /* Register Window Class */
hab, /* Anchor block handle */
PMREXXCLASSNAME, /* Window Class name */
(PFNWP)MainWndProc, /* Address of Window Procedure */
CS_SIZEREDRAW, /* Class Style */
sizeof(PUCHAR))) { /* Extras words for a far ptr. */
return NULLHANDLE; /* Exit if we couldn't register the */
} /* class */
/* Get the title bar text */
windowtext = getstring(hab, handle, WINDOW_TEXT);
if (!windowtext) { /* no title string */
return NULLHANDLE; /* return with nothing */
}
/* Create the standard window */
hwndFrame = WinCreateStdWindow(hwndOwner,/* Supplied owner */
0, /* Frame Style */
&flCreate, /* Control Data */
PMREXXCLASSNAME, /* Window Class name */
NULL, /* Window Text */
WS_VISIBLE, /* Client style */
handle, /* Module handle==this module */
RXHOST_WIN, /* Window ID */
phwndClient); /* Client Window handle */
if (!hwndFrame) { /* no anchor block? */
return NULLHANDLE; /* return with nothing */
}
/* set the window text */
WinSetWindowText(WinWindowFromID(hwndFrame, (USHORT)FID_TITLEBAR),
windowtext);
free(windowtext); /* release window text */
return hwndFrame; /* return created frame handle */
}
/************************** START OF SPECIFICATIONS ***************************/
/* */
/* SUBROUTINE NAME: RexxDestroyIOWindow */
/* */
/* DESCRIPTIVE NAME: */
/* Terminate a Rexx stdin/stdout/stderr transaction subsystem. */
/* */
/* FUNCTION: */
/* Cleans up the Rexx I/O subsystem. */
/* */
/* NOTES: */
/* */
/* ENTRY POINT: */
/* LINKAGE: RexxDestroyIOWindow(HWND hwndClient) */
/* */
/* INPUT: */
/* phwndClient is the handle of the I/O window client window. */
/* */
/* EXIT-NORMAL: */
/* */
/* EXIT-ERROR: */
/* */
/* EFFECTS: */
/* Terminates the Rexx Presntation Manager I/O subsystem. */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* WinQueryWindowPtr WinDestroyHelpInstance */
/* WinAssociateHelpInstance WinDestroyWindow */
/* DosSuspendThread RexxDeregisterExit */
/* DosFreeMem */
/* */
/**************************** END OF SPECIFICATIONS ***************************/
void RexxDestroyIOWindow(HWND hwnd)
{
PRHWINDATA pWinData = NULL; /* pointer to the windata structure */
pWinData = WinQueryWindowPtr(WinWindowFromID(hwnd, (USHORT)FID_CLIENT),
(SHORT)0);
/* And now, clean everything up. */
if (pWinData->HelpInst) {
WinDestroyHelpInstance(pWinData->HelpInst);
WinAssociateHelpInstance(NULLHANDLE, pWinData->frame);
}
/* cleanup semaphores */
DosCloseMutexSem(pWinData->pipe_in.q_sem);
DosCloseMutexSem(pWinData->trace_in.q_sem);
DosCloseEventSem(pWinData->pipe_in.q_data);
DosCloseEventSem(pWinData->trace_in.q_data);
RexxDeregisterExit(PMRXIO_EXIT, NULL);
WinDestroyWindow(pWinData->frame);
DosFreeMem(pWinData); /* release storage */
}
/************************** START OF SPECIFICATIONS ***************************/
/* */
/* SUBROUTINE NAME: initialize */
/* */
/* DESCRIPTIVE NAME: */
/* Initialize the data structures and threads necessary for the */
/* program to operate. */
/* */
/* FUNCTION: */
/* Initializes the input queues and their semaphores, set up */
/* the file handles for redirection of standard input/output and*/
/* error streams, allocate stacks for and begin the threads. /
/* subcommand environments. */
/* */
/* NOTES: */
/* */
/* ENTRY POINT: */
/* LINKAGE: initialize */
/* */
/* INPUT: none */
/* */
/* EXIT-NORMAL: returns 0 */
/* */
/* EXIT-ERROR: returns error code from call causing the error. */
/* */
/* EFFECTS: */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: */
/* makepipe - Creates a pipe with the read and write handles at */
/* desired positions. */
/* setinherit - Sets the inheritance characteristcs of the passed */
/* file handle. */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* DosDupHandle */
/* DosCreateMutexSem */
/* DosCreateEventSem */
/* DosGetInfoBlocks */
/* RexxRegisterExitExe */
/* */
/**************************** END OF SPECIFICATIONS ***************************/
LONG initialize(PRHWINDATA pWinData)
{
LONG rc; /* return code */
PTIB TI; /* Thread info block pointer */
PPIB PI; /* Process info block pointer */
PRHWINDATA userdata[2]; /* registered user data */
/* Initialization Section: */
/* First initialize the semaphores for the input queue. */
/* Using a queue and a separate thread ensures that we don't */
/* tie up the window procedure if the pipe backs up. */
DosCreateMutexSem(NULL, &pWinData->pipe_in.q_sem, 0, FALSE);
DosCreateMutexSem(NULL, &pWinData->trace_in.q_sem, 0, FALSE);
DosCreateEventSem(NULL, &pWinData->pipe_in.q_data, FALSE, FALSE);
DosCreateEventSem(NULL, &pWinData->trace_in.q_data, FALSE, FALSE);
/* Next, set up the redirection pipes to capture standard */
/* I/O from subcommand processing. */
/* First make sure all C handles are closed. */
DosClose(STDIN); /* close stdin, stdout, stderr */
DosClose(STDOUT);
DosClose(STDERR);
/* Since we closed all open file handles, we are free to use any *
* handles we want. */
/* First, standard input */
makepipe(&pWinData->stdin_r, STDIN, &pWinData->stdin_w, 4, PIPE_SIZE);
setinherit(pWinData->stdin_r, TRUE);
setinherit(pWinData->stdin_w, FALSE);
/* Next, standard output */
makepipe(&pWinData->stdout_r, 5, &pWinData->stdout_w, STDOUT, PIPE_SIZE);
setinherit(pWinData->stdout_w, TRUE);
setinherit(pWinData->stdout_r, FALSE);
/* And, finally, standard error */
/* Just dup the standard output and handle it once. */
pWinData->stderr_w = STDERR;
if (rc = DosDupHandle(pWinData->stdout_w, &pWinData->stderr_w)) {
return rc;
}
DosGetInfoBlocks(&TI, &PI); /* Get the thread information */
pWinData->proc_id = PI->pib_ulpid; /* set the process id */
userdata[0] = pWinData; /* save our anchor */
/* register I/O handler */
RexxRegisterExitExe(PMRXIO_EXIT, (PFN)io_routine, (PUCHAR)userdata);
/* And, of course, start the various threads! */
rc = DosCreateThread(&pWinData->in_tid, (PFNTHREAD)stdinpipe, (ULONG)pWinData,
(ULONG)0, STACK_SIZE);
if (!rc) rc = DosCreateThread(&pWinData->out_tid, (PFNTHREAD)stdoutpipe, (ULONG)pWinData,
(ULONG)0, STACK_SIZE);
return rc;
}
/************************** START OF SPECIFICATIONS ***************************/
/* */
/* SUBROUTINE NAME: MainWndProc */
/* */
/* DESCRIPTIVE NAME: */
/* Main window procedure for the PMREXX program. */
/* */
/* FUNCTION: */
/* This procedure handles all interesting messages for the */
/* client area for the PMREXX program. The messages handled */
/* are: */
/* WM_CREATE - Allocates and initializes the RHWINDATA structure */
/* (defined in rhdtatyp.h) and places a pointer to it */
/* into the window words. */
/* WM_TIMER - A 100 millisecond timer is set when output is added */
/* to a buffer for later adding to the MLE output */
/* window. Thus if many lines are being added, output */
/* time is improved, and window flashing is reduced. */
/* If the timer pops, then no output has been */
/* added for the 100 milliseconds and it is time to */
/* add the output to the MLE. */
/* WM_ERASEBACKGROUND - Just return TRUE to force a background erase. */
/* WM_SIZE - Calls routine SizeWindow to re-adjust the sizes */
/* of the MLE and input areas. */
/* WM_PAINT - Paints the header for the input window, and lets */
/* the child controls do the rest. */
/* WM_COMMAND - All WM_COMMAND messages are processed in routine */
/* RXIOCmds. */
/* WM_CHAR - Handles tab and backtab keys to switch the focus */
/* window and the break key as a halt procedure. */
/* REXX_MAKE_VISIBLE - Is a user defined message requesting that */
/* the window be made visible. The window is initially */
/* created invisible and is not made visible until */
/* something is output, or until some input is */
/* requested. This way, a REXX procedure that does not */
/* need this window, will not clutter up the screen */
/* with it (e.g. a DM exec that uses DM for all I/O). */
/* REXX_MAKE_INVISIBLE - Is a user defined message requesting that */
/* the window be made invisible. */
/* REXX_ENDPROC - This signals the end of a Rexx procedure. The */
/* I/O subsystem is flushed and reinitialized. */
/* REXX_STARTPROC - This signals the start of a Rexx procedure. This */
/* identifies the thread running the procedure. */
/* RXIOB_MSGBOX - Puts up a message box with the requested message. */
/* START_TIMER - Starts a timer. When the timer pops, the buffered */
/* output is added to the MLE. See also, WM_TIMER and */
/* ADD_STDOUTWIN. This message is posted by the thread */
/* reading the input pipe. */
/* ADD_STDOUTWIN - This user defined message is a request to add */
/* output to the output window. To reduce window */
/* flicker and improve performance, data is internally */
/* buffered until the buffer is full, or until there */
/* is a lull in output, before being sent on to the */
/* MLE window. See also the WM_TIMER message. */
/* WM_SAVEAPPLICATION - Save the current font and window information */
/* */
/* NOTES: */
/* */
/* ENTRY POINT: */
/* LINKAGE: */
/* Standard window procedure linkage is followed. */
/* */
/* INPUT: */
/* Standard window procedure inputs are passed in. */
/* */
/* EXIT-NORMAL: */
/* */
/* EXIT-ERROR: */
/* */
/* EFFECTS: */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: */
/* getfixedfont - Get a fixed font for the default display */
/* getstring - Retrieve a string resource */
/* RestoreWindow - Gets saved window position from user profile */
/* RHWinErrorBox - Display an error message box */
/* SizeWindow - Sizes all the child windows (MLE & Entry field) to */
/* fit the frame window. */
/* RXIOCmds - This routine processes the various WM_COMMAND */
/* messages. */
/* Import - Sends the data from the internal buffer to the MLE. */
/* See the WM_TIMER and ADD_STDOUTWIN messages. */
/* SaveWindow - Saves current window position to user profile */
/* SetCheckMark - Check/uncheck a menu item */
/* ProcessSaveQuit - Interface to the Save/Quit dialog */
/* */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* DosAllocMem WinLoadString */
/* DosCreateMutexSem WinMessageBox */
/* DosFreeMem WinPostMsg */
/* DosReleaseMutexSem WinQueryAnchorBlock */
/* DosRequestMutexSem WinQueryWindow */
/* DosSuspendThread WinQueryWindowPos */
/* GpiCharStringAt WinQueryWindowPtr */
/* GpiQueryCurrentPosition WinReleasePS */
/* RexxDeregisterExit WinSendMsg */
/* WinAlarm WinSetFocus */
/* WinAssociateHelpInstance WinSetWindowPtr */
/* WinCreateHelpInstance WinShowWindow */
/* WinDefWindowProc WinStartTimer */
/* WinDestroyHelpInstance WinStopTimer */
/* WinGetPS WinWindowFromID */
/* */
/**************************** END OF SPECIFICATIONS ***************************/
MRESULT EXPENTRY MainWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
ULONG rc; /* return code */
PRHWINDATA pWinData = NULL; /* pointer to the windata structure */
HPS hps; /* presentation space handle */
PIMPORT im_ptr; /* Pointer to buffer for data waiting */
ULONG postcount; /* number of posted lines */
FONTMETRICS fm; /* font size information */
HWND hEntry; /* entry dialog handle */
/* Creation flags for the MLE requests */
/* scroll bars. */
ULONG flCreate = MLS_HSCROLL|MLS_VSCROLL|MLS_BORDER;
pWinData = WinQueryWindowPtr(hwnd, (SHORT)0);
switch (msg) {
case WM_CREATE :
/* When the window is created, we also create a structure to hold */
/* all the window specific data. */
if (pWinData = malloc(sizeof(*pWinData))) {
memset(pWinData, '\0', sizeof(*pWinData));
pWinData->hab = WinQueryAnchorBlock(hwnd);
/* and client handle */
pWinData->client = hwnd;
/* save frame handle */
pWinData->frame = WinQueryWindow(hwnd, QW_PARENT);
if (DosQueryModuleHandle(MODULE_NAME, &pWinData->hResource)) {
return NULL; /* return with nothing */
}
pWinData->imp_ptr = NULL; /* This is the timer to be used for */
/* import time-out. */
pWinData->timer = (USHORT)WinStartTimer(pWinData->hab, (HWND)0,
(USHORT)0, (ULONG)0);
/* get code page information */
DosQueryCtryInfo(sizeof(COUNTRYINFO), &pWinData->CountryCode,
&pWinData->CountryInfo, &postcount);
/* Attempt to find a fixed font for the*/
/* display, if we are not successful, */
/* we will use the system font. */
getfixedfont(hwnd, &pWinData->MleFontAttrs.fAttrs);
/* system font attributes */
pWinData->infocus = FALSE;
/* get the input text */
/* prompt from the resource file */
pWinData->pszInputText = getstring(pWinData->hab,
pWinData->hResource, INPUT_TITLE);
WinSetWindowPtr(hwnd, (SHORT)0, pWinData);
/* Now allocate a segment for the */
/* import buffer for the MLE */
pWinData->imp_ptr = (PIMPORT)(pWinData->ImportBuffer);
/* initialize the buffer */
im_ptr = pWinData->imp_ptr;
im_ptr->total_size = ALLOCSIZE;
im_ptr->inuse = HDRSIZE;
*(PUCHAR)(im_ptr->data) = '\0';
/* create the semaphore */
DosCreateMutexSem(NULL, &im_ptr->sem, 0, FALSE);
/* Set up the threads and initialize the data structures */
rc = initialize(pWinData);
/* If initialization failed, alert the user and exit */
if (rc) {
WinAlarm(HWND_DESKTOP, WA_ERROR);
WinMessageBox(HWND_DESKTOP, NULLHANDLE,
getstring(pWinData->hab, pWinData->hResource, INIT_FAILED),
getstring(pWinData->hab, pWinData->hResource, RXHB_MSGBOXHDR), 1,
MB_CANCEL|MB_CUACRITICAL|MB_MOVEABLE);
}
/* Find out the character */
/* height for the input entry field */
hps = WinGetPS(pWinData->client);
GpiQueryFontMetrics(hps, (LONG)sizeof fm, &fm);
pWinData->in_hgt = (ULONG )fm.lMaxBaselineExt+2;
WinReleasePS(hps);
/* Create the child MLE for */
/* output */
pWinData->outmle = WinCreateWindow(pWinData->client, WC_MLE, NULL,
flCreate, 0, 0, 0, 0, pWinData->client, HWND_TOP,
MLE_WNDW, NULL, NULL);
if (!pWinData->outmle) { /* If we couldn't do it, tell the user */
/* why. */
RHWinErrorBox(pWinData->hab, hwnd, pWinData->hResource,
MLE_CREATE_ERROR, MB_OK|MB_CUAWARNING);
} /* Delay redrawing window until */
/* we're done updating it */
WinEnableWindowUpdate(pWinData->client, FALSE);
/* Set the format for the MLE */
WinSendMsg(pWinData->outmle, MLM_FORMAT, MLE_TXT_FMT, (MPARAM)0);
/* Make the MLE readonly */
WinSendMsg(pWinData->outmle, MLM_SETREADONLY, MPFROMLONG(TRUE),
(MPARAM)0);
/* set the new font */
WinSendMsg(pWinData->outmle, MLM_SETFONT,
&(pWinData->MleFontAttrs.fAttrs), (MPARAM)0);
/* Update the window */
WinShowWindow(pWinData->outmle, TRUE);
/* set the title width */
pWinData->wtitle = (strlen(pWinData->pszInputText)+5)*(USHORT)
fm.lAveCharWidth;
/* Load the dialog box for the input */
/* window */
hEntry = WinLoadDlg(pWinData->client, pWinData->client,
(PFNWP)EntryDlgProc, (HMODULE)pWinData->hResource, RH_EF1, NULL);
pWinData->insle = hEntry; /* save input window handle Set the */
/* maximum input length to ANSLEN */
WinSendMsg(hEntry, EM_SETTEXTLIMIT, MPFROMSHORT(ANSLEN), (MPARAM)0);
/* Set the offset to the first */
/* character in the input box to 0 */
WinSendMsg(hEntry, EM_SETFIRSTCHAR, (MPARAM)0, (MPARAM)0);
/* Set the first character to be */
/* selected as 0 */
WinSendMsg(hEntry, EM_SETSEL, (MPARAM)0, (MPARAM)0);
/* Update the windows */
WinShowWindow(hEntry, TRUE);
WinEnableWindowUpdate(hEntry, TRUE);
WinEnableWindowUpdate(pWinData->client, TRUE);
WinSetFocus(HWND_DESKTOP, pWinData->outmle);
}
else { /* If we couldn't allocate the data */
/* structure, then we cannot continue, */
/* so alert the user, and exit. */
WinSendMsg(WinWindowFromID(hwnd, (USHORT)FID_CLIENT),
RXIOB_MSGBOX,
MPFROM2SHORT(RX_ALLOCERR, RXHB_MSGBOXHDR),
MPFROMLONG(MB_ENTER|MB_CUACRITICAL|MB_MOVEABLE));
return (MRESULT)TRUE;
}
break;
case WM_TIMER :
if (hwnd) { /* We have gone for the designated time*/
/* without adding any new data to the */
/* output buffer, so it is now time to */
/* import the information to the MLE */
/* output window. */
WinStopTimer(pWinData->hab, hwnd, pWinData->timer);
/* Get the semaphore so that the */
/* input pipe thread won't interfere. */
DosRequestMutexSem(pWinData->imp_ptr->sem, SEM_INDEFINITE_WAIT);
Import(pWinData);
/* Now clear the */
/* thread so that the input pipe can */
/* continue. */
DosReleaseMutexSem(pWinData->imp_ptr->sem);
}
break;
case WM_ERASEBACKGROUND :
return (MRESULT)TRUE; /* Return TRUE to indicate we want the */
/* background cleared to the system */
/* default window background color. */
case WM_SIZE :
SizeWindow(hwnd, pWinData); /* Re-size the client area windows. */
break;
case WM_PAINT :
if (hps = WinGetPS(hwnd)) { /* The title for the input window needs*/
/* to be re-painted by us. The child */
/* windows do all the rest of the */
/* drawing for us. */
POINTL p;
SWP wp;
HWND hOwner;
PUCHAR ptr; /* Ensure that we get a proper handle */
/* to the client area. */
hOwner = WinQueryWindow(hwnd, QW_PARENT);
/* Calculate the proper positioning. */
WinQueryWindowPos(pWinData->client, &wp);
p.x = BORDER_MARGIN *2;
p.y = wp.cy-pWinData->in_hgt-(BORDER_MARGIN *2);
ptr = pWinData->pszInputText; /* Output the title, and find the */
/* resulting position for the next */
/* character. That is where we will */
/* start the input box. */
GpiCharStringAt(hps, &p, (LONG)strlen(ptr), ptr);
GpiQueryCurrentPosition(hps, &p);
pWinData->wtitle = (ULONG )p.x;
WinReleasePS(hps);
}
break;
case WM_COMMAND :
/* WM_COMMAND processing in RXIOCMDS */
return (RXIOCmds(hwnd, mp1, pWinData));
break;
case WM_CHAR :
/* Check for a valid (complete) key message. */
if (!(SHORT1FROMMP(mp1)&KC_KEYUP) &&
(SHORT1FROMMP(mp1)&KC_VIRTUALKEY) ) {
switch (SHORT2FROMMP(mp2)) {
case VK_TAB :
case VK_BACKTAB : /* For tab and back-tab, switch focus */
/* windows */
return (MRESULT)WinSetFocus(HWND_DESKTOP,
pWinData->infocus?pWinData->outmle: pWinData->insle);
break;
default :
break;
} /* endswitch */
}
break;
case REXX_STARTPROC :
/* This is the request to start everything up. It is sent by the */
/* main procedure at startup time. */
pWinData->rexx_tid = LONGFROMMP(mp1);
break;
case REXX_ENDPROC : {
PLIST_ENTRY q_elem; /* pointer for an element in the input */
/* queue */
/* Clear out any entries on input queue*/
if (!DosRequestMutexSem(pWinData->pipe_in.q_sem, SEM_INDEFINITE_WAIT)) {
for (q_elem = pWinData->pipe_in.q_1st; q_elem; q_elem = q_elem->next) {
free(q_elem->ptr);
free(q_elem);
}
/* Set the queue to empty */
DosResetEventSem(pWinData->pipe_in.q_data, &postcount);
/* Clear the list */
pWinData->pipe_in.q_1st = NULL;
/* We're done with the queue */
DosReleaseMutexSem(pWinData->pipe_in.q_sem);
}
/* Clear the input pipe, so that any unprocessed data is deleted. */
/* The only way to do this is to close the pipe, and then reopen it. */
DosClose(pWinData->stdin_r);
DosClose(pWinData->stdin_w);
makepipe(&pWinData->stdin_r, STDIN, &pWinData->stdin_w, 4, PIPE_SIZE);
setinherit(pWinData->stdin_r, TRUE);
setinherit(pWinData->stdin_w, FALSE);
break;
}
case REXX_MAKE_INVISIBLE :
if (pWinData->visible) {
pWinData->visible = FALSE; /* reset flag to invisible */
WinShowWindow(pWinData->frame, FALSE);
/* Make it invisible. */
}
break;
case REXX_MAKE_VISIBLE :
/* At start-up, the window is left invisible. When output or */
/* trace mode input occurs for the first time, this message is */
/* sent to make the window visible. It is at this time that */
/* the Help Manager gets initialized. */
if (!pWinData->visible) {
HELPINIT hmiData;
pWinData->visible = TRUE; /* Set so we don't get called */
/* unnecessarily */
RestoreWindow(hwnd, pWinData);/* From last invocation */
WinShowWindow(pWinData->frame, TRUE);
/* Make it visible. Initialize the Help*/
/* Manager data structure */
memset(&hmiData, '\0', sizeof hmiData);
hmiData.cb = sizeof(hmiData);
hmiData.pszHelpWindowTitle =
getstring(pWinData->hab, pWinData->hResource, PMREXX_HELP_TITLE);
hmiData.phtHelpTable = (PHELPTABLE)(PMREXX_HELPTABLE|RESOURCE_FLAG);
hmiData.pszHelpLibraryName =
getstring(pWinData->hab, pWinData->hResource, PMREXX_HELPFILENAME);
hmiData.fShowPanelId = CMIC_HIDE_PANEL_ID;
hmiData.hmodHelpTableModule = pWinData->hResource;
hmiData.hmodAccelActionBarModule = pWinData->hResource;
hmiData.idAccelTable = 0;
hmiData.idActionBar = 0;
/* Attempt to create help instance */
if (pWinData->HelpInst = WinCreateHelpInstance(pWinData->hab,
&hmiData)) {
/* If the create succeeded, then we */
/* need to associate it with the frame */
/* window. */
if (!WinAssociateHelpInstance(pWinData->HelpInst, pWinData->frame)) {
/* If the associate failed, inform the */
/* user and destroy the instance. */
RHWinErrorBox(pWinData->hab, hwnd, pWinData->hResource,
ERROR_HELPASSOC, MB_OK|MB_CUAWARNING);
WinDestroyHelpInstance(pWinData->HelpInst);
pWinData->HelpInst = NULLHANDLE;
}
}
else {
/* If the create failed, inform the */
/* user. */
RHWinErrorBox(pWinData->hab, hwnd, pWinData->hResource,
ERROR_HELPCREATE, MB_OK|MB_CUAWARNING);
}
WinSetFocus(HWND_DESKTOP, pWinData->insle);
}
break;
case RXIOB_MSGBOX : { /* Put up a message box. The mp1 */
/* parameter has the resource ids for */
/* the message and the title. */
USHORT msgid = SHORT1FROMMP(mp1);
PUCHAR header = getstring(pWinData->hab, pWinData->hResource,
SHORT2FROMMP(mp1));
PUCHAR content = getstring(pWinData->hab, pWinData->hResource,
SHORT1FROMMP(mp1));
/* If we are */
/* displaying the ended message, set */
/* the owner to the desktop so we don't*/
/* steal the focus back from other */
/* apps. */
LONG rc = WinMessageBox(HWND_DESKTOP, hwnd, content, header,
msgid, SHORT1FROMMP(mp2));
free(header);
free(content);
return MPFROMSHORT(rc);
}
break;
case START_TIMER :
/* Start a timer to force output after a period of inactivity. */
if (!pWinData->visible) { /* Make the window visible, if not */
/* already. */
WinSendMsg(WinWindowFromID(hwnd, (USHORT)FID_CLIENT),
REXX_MAKE_VISIBLE, (MPARAM)0, (MPARAM)0);
}
WinStartTimer(pWinData->hab, hwnd, pWinData->timer, TIMER_DELAY);
pWinData->imp_queued = FALSE;
break;
case ADD_STDOUTWIN :
/* Add an output line to the MLE buffer, and start the timer. */
if (!pWinData->visible) { /* Make the window visible, if not */
/* already. */
WinSendMsg(WinWindowFromID(hwnd, (USHORT)FID_CLIENT),
REXX_MAKE_VISIBLE, (MPARAM)0, (MPARAM)0);
}
if (pWinData->client == hwnd) {
HWND wnd = pWinData->outmle;
PIMPORT im_ptr = pWinData->imp_ptr;
PUCHAR ptr = (PUCHAR)im_ptr->data;
PUCHAR tmp1 = (PUCHAR)mp1; /* Obtain the buffer semaphore to */
/* prevent interference with the input */
/* pipe thread. */
DosRequestMutexSem(im_ptr->sem, SEM_INDEFINITE_WAIT);
/* If the string is too */
/* large, break it up into pieces and */
/* add to the window. */
while (strlen(tmp1) > (ULONG)IMPORTSIZE-HDRSIZE-1) {
/* Save the character we are about to */
/* null out */
UCHAR tch = *(tmp1+IMPORTSIZE-HDRSIZE-1);
/* Add smaller string to the window */
*(tmp1+IMPORTSIZE-HDRSIZE-1) = '\0';
WinSendMsg(hwnd, ADD_STDOUTWIN, tmp1, (MPARAM)mp1);
/* Then bump the pointer and restore */
/* the character. */
tmp1 += IMPORTSIZE - HDRSIZE - 1;
*tmp1 = tch;
} /* endwhile See if there is room left */
/* in the buffer. */
while (((im_ptr->total_size)-(im_ptr->inuse)) <= strlen(tmp1)) {
/* need to import what we have */
WinStopTimer(pWinData->hab, hwnd, pWinData->timer);
/* empty the buffer */
Import(pWinData);
}
strcat(ptr, tmp1); /* Copy the data to the end of the */
/* buffer */
im_ptr->inuse = HDRSIZE+strlen(ptr);/* Reset the use count */
/* and free the semaphore */
DosReleaseMutexSem(im_ptr->sem);
free(mp1); /* free the text */
/* Start the timer to force output if */
/* nothing added for the specified */
/* time. */
WinStartTimer(pWinData->hab, hwnd, pWinData->timer, TIMER_DELAY);
pWinData->imp_queued = FALSE;
return (MRESULT)TRUE;
}
return (MRESULT)FALSE;
break;
case HM_QUERY_KEYS_HELP :
return (MRESULT)RX_KEYSHELP;
case WM_SAVEAPPLICATION :
SaveWindow(pWinData);
break;
default :
break;
}
return (WinDefWindowProc(hwnd, msg, mp1, mp2));
}
/************************** START OF SPECIFICATIONS ***************************/
/* */
/* SUBROUTINE NAME: RXIOCmds */
/* */
/* DESCRIPTIVE NAME: */
/* Process WM_COMMAND messages for the window procedure. */
/* */
/* FUNCTION: */
/* This routine processes all the WM_COMMAND messages that have */
/* been passed into the MainWndProc. The messages handled are: */
/* RXIOA_TRCSTEP - This requests that the REXX trace be advanced one */
/* step. It is equivalent to an input of a blank line */
/* to a REXX trace read. It is only valid when REXX is */
/* waiting for trace input. */
/* RXIOA_TRCLAST - This requests that the REXX re-trace the last */
/* clause executed. Is is equivalent to an input of an */
/* equal sign to a REXX trace read. It is only valid */
/* when REXX is waiting for trace input. */
/* RXIOA_TRCOFF - This requests that the REXX turn off interactive */
/* tracing. Is is equivalent to an input of a "TRACE */
/* OFF" statement to a REXX trace read. It is only */
/* valid when REXX is waiting for trace input. */
/* RXIOA_TRACE - This is a request to turn interactive tracing on */
/* or off. It is only valid when the REXX procedure */
/* has ended and the user has not yet restarted it. */
/* This is because REXX only looks at the trace flag */
/* when it is first called to execute a procedure. */
/* RXIOA_HALT - This requests that the REXX HALT indicator be */
/* raised, requesting the procedure to be interrupted. */
/* RXIOA_CLEAR - This is a request to clear the marked area of the */
/* focus window. */
/* RXIOA_PASTE - Paste from the clipboard into the input window. */
/* RXIOA_COPY - This is a request to copy the marked area of the */
/* focus window into the clipboard. */
/* RXIOA_ALL - This is a request to mark the entire output area. */
/* RXIOA_FONTS - Present the user with a dialog to select a font for */
/* the output window. */
/* */
/* NOTES: */
/* */
/* ENTRY POINT: */
/* LINKAGE: */
/* MRESULT RXIOCmds(HWND hwnd, MPARAM mp1, PRHWINDATA pWinData) */
/* */
/* INPUT: */
/* hwnd - The window handle of the window that received the */
/* command. */
/* mp1 - The first parameter of the WM_COMMAND message. */
/* pWinData - A pointer to the RHWINDATA structure of the window. */
/* */
/* EXIT-NORMAL: */
/* returns TRUE if the file was saved successfully or user response */
/* from SAVEAS dialog. */
/* EXIT-ERROR: */
/* returns FALSE if the file was not saved successfully. */
/* */
/* EFFECTS: */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: */
/* Add_Q_Element - Adds an entry to an input queue. */
/* RHWinErrorBox - Display an error message box. */
/* ClipBoard - Perform clipboard related commands. */
/* SizeWindow - Resize the child windows within the client area. */
/* SelectFont - Interface to the font selection dialog */
/* SetCheckMark - Check/uncheck a menu item */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* DosRequestMutexSem WinInvalidateRect */
/* DosReleaseMutexSem WinLoadDlg */
/* GpiQueryFontMetrics WinLoadString */
/* WinAlarm WinPostMessage */
/* WinCreateWindow WinReleasePS */
/* WinDlgBox WinSendMsg */
/* WinEnableWindowUpdate WinShowWindow */
/* WinGetPS WinWindowFromID */
/* */
/* */
/* */
/* */
/* */
/**************************** END OF SPECIFICATIONS ***************************/
MRESULT RXIOCmds(HWND hwnd, MPARAM mp1, PRHWINDATA pWinData)
{
CHAR Temp = '\0'; /* temporary character */
/* dialog */
PLIST_ENTRY q_elem; /* pointer for an element in the input */
/* queue */
switch (LOUSHORT(mp1)) {
case RXIOA_TRCSTEP :
/* Trace the next clause. This is accomplished by inputting a */
/* null line. */
if (q_elem = malloc(sizeof(*q_elem))) {
q_elem->ptr = strdup("");
q_elem->len = strlen(q_elem->ptr);
Add_Q_Element(&pWinData->trace_in, q_elem);
}
break;
case RXIOA_TRCLAST :
/* Re-trace the previous clause. This is accomplished by */
/* inputting an equal (=) sign alone on a line. */
if (q_elem = malloc(sizeof(*q_elem))) {
q_elem->ptr = strdup("=");
q_elem->len = strlen(q_elem->ptr);
Add_Q_Element(&pWinData->trace_in, q_elem);
}
break;
case RXIOA_TRCOFF :
/* Turn tracing off by calling RexxResetTrace */
RexxResetTrace(pWinData->proc_id, pWinData->rexx_tid);
pWinData->tracebit = FALSE;
/* Clear the checkmark */
SetCheckMark(pWinData->frame, RXIOA_TRACE, FALSE);
/* send a null line to end pause */
if (q_elem = malloc(sizeof(*q_elem))) {
q_elem->ptr = strdup("");
q_elem->len = strlen(q_elem->ptr);
Add_Q_Element(&pWinData->trace_in, q_elem);
}
break;
case RXIOA_TRACE :
/* Change the state of the interactive trace indiciator. This */
/* will turn tracing on immediately (with the next phrase */
/* executed). */
if (pWinData->tracebit = (BOOL)(!pWinData->tracebit)) {
RexxSetTrace(pWinData->proc_id, pWinData->rexx_tid);
}
else {
RexxResetTrace(pWinData->proc_id, pWinData->rexx_tid);
}
SetCheckMark(pWinData->frame, RXIOA_TRACE, pWinData->tracebit);
break;
case RXIOA_HALT :
/* Change the Halt Procedure indicator. This will cause REXX to */
/* terminate execution of the procedure when the next phrase */
/* is executed. */
RexxSetHalt(pWinData->proc_id, pWinData->rexx_tid);
if (!pWinData->RxHalt) {
pWinData->RxHalt = TRUE;
SetCheckMark(pWinData->frame, RXIOA_HALT, pWinData->RxHalt);
}
break;
/************************************************************************/
/* These messages relate to clipboard operations */
/************************************************************************/
case RXIOA_CLEAR :
if (pWinData->infocus) { /* clear the input window, because it */
/* has the focus */
WinSendMsg(pWinData->insle, EM_CLEAR, (MPARAM)0, (MPARAM)0);
}
else { /* clear the MLE */
ClipBoard(hwnd, MLM_CLEAR, RXIOH_ERR_CLEAR, pWinData);
}
break;
case RXIOA_PASTE :
/* put the text from the clipboard into the input window */
WinSendMsg(pWinData->insle, EM_PASTE, (MPARAM)0, (MPARAM)0);
break;
case RXIOA_COPY :
if (pWinData->infocus) { /* Copy text from input window */
WinSendMsg(pWinData->insle, EM_COPY, (MPARAM)0, (MPARAM)0);
}
else { /* Get the text from the MLE */
ClipBoard(hwnd, MLM_COPY, RXIOH_ERR_COPY, pWinData);
}
break;
/************************************************************************/
/* Select all */
/************************************************************************/
case RXIOA_ALL : {
ULONG usFileSize;
WinEnableWindowUpdate(hwnd, FALSE);
/* disable updates Get length of the */
/* output in the MLE */
usFileSize = (ULONG )WinSendMsg(WinWindowFromID(hwnd,
(USHORT)MLE_WNDW),
MLM_QUERYTEXTLENGTH,
(MPARAM)0, (MPARAM)0);
/* Select all of the output in the MLE */
WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
MLM_SETSEL, (MPARAM)0L, MPFROMSHORT(usFileSize));
WinInvalidateRect(hwnd, NULL, TRUE);
/* update the window */
WinEnableWindowUpdate(hwnd, TRUE);
/* Make MLE so that it can't be undone */
WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
MLM_RESETUNDO, (MPARAM)0, (MPARAM)0);
}
break;
/************************************************************************/
/* Present Font dialog; the dialog will change the PS attribute */
/************************************************************************/
case RXIOA_FONTS :
WinSendMsg(WinWindowFromID(hwnd, (USHORT) MLE_WNDW),
MLM_RESETUNDO, (MPARAM)0, (MPARAM)0);
SelectFont(pWinData);
break;
/************************************************************************/
/* Display Help for help panel */
/************************************************************************/
case RXIOM_HELPHELP :
if (pWinData->HelpInst != NULLHANDLE) {
WinSendMsg(pWinData->HelpInst, HM_DISPLAY_HELP, (MPARAM)0, (MPARAM)0);
}
else {
WinSendMsg(pWinData->client,
RXIOB_MSGBOX,
MPFROM2SHORT(NO_HELP_MGR, HELP_ERR),
MPFROMLONG(MB_ENTER|MB_CUACRITICAL|MB_MOVEABLE));
}
break;
/************************************************************************/
/* Display Extended help panel */
/************************************************************************/
case RXIOM_EXTHELP :
if (pWinData->HelpInst != NULLHANDLE) {
WinSendMsg(pWinData->HelpInst, HM_EXT_HELP, (MPARAM)0, (MPARAM)0);
}
else {
WinSendMsg(pWinData->client,
RXIOB_MSGBOX,
MPFROM2SHORT(NO_HELP_MGR, HELP_ERR),
MPFROMLONG(MB_ENTER|MB_CUACRITICAL|MB_MOVEABLE));
}
break;
/************************************************************************/
/* Display keys help panel */
/************************************************************************/
case RXIOM_KEYSHELP :
if (pWinData->HelpInst != NULLHANDLE) {
WinSendMsg(pWinData->HelpInst, HM_KEYS_HELP, (MPARAM)0, (MPARAM)0);
}
else {
WinSendMsg(pWinData->client, RXIOB_MSGBOX,
MPFROM2SHORT(NO_HELP_MGR, HELP_ERR),
MPFROMLONG(MB_ENTER|MB_CUACRITICAL|MB_MOVEABLE));
}
break;
/************************************************************************/
/* Display help index */
/************************************************************************/
case RXIOM_INDEXHELP :
if (pWinData->HelpInst != NULLHANDLE) {
WinSendMsg(pWinData->HelpInst, HM_HELP_INDEX, (MPARAM)0, (MPARAM)0);
}
else {
WinSendMsg(pWinData->client, RXIOB_MSGBOX,
MPFROM2SHORT(NO_HELP_MGR, HELP_ERR),
MPFROMLONG(MB_ENTER|MB_CUACRITICAL|MB_MOVEABLE));
}
break;
/************************************************************************/
/* Option not implemented: Warn the user */
/************************************************************************/
default :
WinAlarm(HWND_DESKTOP, WA_ERROR);
} /* endswitch */
return (MRESULT)FALSE;
}
/************************** START OF SPECIFICATIONS ***************************/
/* */
/* SUBROUTINE NAME: ClipBoard */
/* */
/* DESCRIPTIVE NAME: */
/* Process the MLE clipboard functions by passing the message */
/* on to the MLE window. */
/* */
/* FUNCTION: */
/* All of the clipboard related functions are handled very */
/* simliarly and so are just passed directly on to the MLE */
/* window for processing. In case of a failure, a message */
/* box is popped up to notify the user. */
/* */
/* NOTES: */
/* */
/* ENTRY POINT: */
/* LINKAGE: */
/* CipBoard(hWnd, MLECMsg, ErrMsg, pWinData) */
/* */
/* INPUT: */
/* hWnd - The handle of the window that received the message */
/* MLECMsg - The message to be processed. */
/* ErrMsg - The resource ID of the error message to use in */
/* case of an error. */
/* */
/* EXIT-NORMAL: */
/* */
/* EXIT-ERROR: */
/* */
/* EFFECTS: */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* WinSendMsg */
/* WinWindowFromID */
/* */
/**************************** END OF SPECIFICATIONS ***************************/
void ClipBoard(HWND hwnd, USHORT MLECMsg, ULONG ErrMsg,
PRHWINDATA pWinData) {
/* If an error occurs, put up a message box */
if (!((MRESULT)WinSendMsg(WinWindowFromID(hwnd, (USHORT)MLE_WNDW),
MLECMsg, (MPARAM)0, (MPARAM)0)))
WinSendMsg(pWinData->client, RXIOB_MSGBOX,
MPFROM2SHORT(ErrMsg, RXIOH_ERR_CLIPBRD),
MPFROMLONG(MB_ENTER|MB_CUACRITICAL|MB_MOVEABLE));
}
/************************** START OF SPECIFICATIONS ***************************/
/* */
/* SUBROUTINE NAME: Import */
/* */
/* DESCRIPTIVE NAME: */
/* Add the information collected into the import buffer into */
/* the MLE window. */
/* */
/* FUNCTION: */
/* Adding information to the MLE involves considerable */
/* overhead. To do so on each individual line would be */
/* unacceptably slow for any considerable amount of output. */
/* Therefore, output is collected into a buffer and output */
/* to the MLE when the buffer is full, or there has been no */
/* output added for some period of time. This is the routine */
/* to take the information collected in the buffer area and */
/* add it to the output window. */
/* */
/* NOTES: */
/* */
/* ENTRY POINT: */
/* LINKAGE: */
/* void Import(PRHWINDATA pWinData) */
/* */
/* INPUT: */
/* pWinData - Pointer to global control block. */
/* */
/* EXIT-NORMAL: */
/* */
/* EXIT-ERROR: */
/* */
/* EFFECTS: */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: */
/* RHWinErrorBox - Display an error message box. */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* WinPostMsg */
/* WinQueryWindow */
/* WinSendMsg */
/* */
/**************************** END OF SPECIFICATIONS ***************************/
void Import(PRHWINDATA pWinData) {
IPT ipt = (IPT)NULL; /* Integer pointer type for MLE */
if (pWinData->imp_ptr->inuse > HDRSIZE) {
/* Get the number of characters currently in the MLE */
ipt = (IPT)WinSendMsg(pWinData->outmle, MLM_QUERYTEXTLENGTH,
(MPARAM)0, (MPARAM)0);
/* If we had an error setting up the transfer buffer, display a message */
if (!WinSendMsg(pWinData->outmle, MLM_SETIMPORTEXPORT,
pWinData->imp_ptr->data,
MPFROMLONG(pWinData->imp_ptr->total_size-HDRSIZE))) {
RHWinErrorBox(pWinData->hab, pWinData->outmle, pWinData->hResource,
MLE_IMEXPORT_ERROR, MB_OK|MB_CUACRITICAL);
WinPostMsg(WinQueryWindow(pWinData->outmle, QW_PARENT),
WM_CLOSE, (MPARAM)0, (MPARAM)0);
return ;
}
WinEnableWindowUpdate(pWinData->outmle, FALSE);
/* Set the MLE to not translate the input */
WinSendMsg(pWinData->outmle, MLM_FORMAT, MPFROMSHORT(MLFIE_NOTRANS),
(MPARAM)0);
/* Set the MLE so we can add data to it */
WinSendMsg(pWinData->outmle, MLM_SETREADONLY, FALSE, (MPARAM)0);
/* Add the data to the MLE, if we get an error, display a message */
/* upon return, point to end of data */
if (!WinSendMsg(pWinData->outmle, MLM_IMPORT, &ipt,
MPFROMLONG(pWinData->imp_ptr->inuse-HDRSIZE))) {
RHWinErrorBox(pWinData->hab, pWinData->outmle, pWinData->hResource,
MLE_IMPORT_ERROR, MB_OK|MB_CUACRITICAL);
/* It probably failed because the line is too long, so append a */
/* new line and try again. */
WinSendMsg(pWinData->outmle, MLM_SETSEL, MPFROMLONG(ipt),
MPFROMLONG(ipt));
WinSendMsg(pWinData->outmle, MLM_INSERT, "\r", (MPARAM)0);
/* Move the selection to the end of the input */
ipt = (IPT)WinSendMsg(pWinData->outmle, MLM_QUERYTEXTLENGTH, (MPARAM)0,
(MPARAM)0);
if (!WinSendMsg(pWinData->outmle, MLM_IMPORT, &ipt,
MPFROMLONG(pWinData->imp_ptr->inuse-HDRSIZE) )) {
/* If we still couldn't import */
/* anything, give up. */
WinPostMsg(WinQueryWindow(pWinData->outmle, QW_PARENT),
WM_CLOSE, (MPARAM)0, (MPARAM)0);
}
}
/* Update the ptr structure */
*(HDRSIZE+(PUCHAR)pWinData->imp_ptr) = '\0';
pWinData->imp_ptr->inuse = HDRSIZE+strlen(HDRSIZE+(PUCHAR)pWinData->imp_ptr);
/* Move the cursor to the end of the new data */
WinSendMsg(pWinData->outmle, MLM_SETSEL, MPFROMLONG(ipt), MPFROMLONG(ipt));
WinEnableWindowUpdate(pWinData->outmle, TRUE);
/* Set the MLE to normal export mode */
WinSendMsg(pWinData->outmle, MLM_FORMAT, MLE_TXT_FMT, (MPARAM)0);
/* Set the MLE back to readonly */
WinSendMsg(pWinData->outmle, MLM_SETREADONLY, MPFROMLONG(TRUE), (MPARAM)0);
}
}
/************************** START OF SPECIFICATIONS ***************************/
/* */
/* SUBROUTINE NAME: SizeWindow */
/* */
/* DESCRIPTIVE NAME: */
/* Size the MLE output window and the Entry Field input window */
/* to fit the client area. */
/* */
/* FUNCTION: */
/* Whenever the client window is sized, this routine is */
/* called to resize the MLE output window and the Entry Field */
/* control used for input to fit properly within the new */
/* client area. */
/* */
/* NOTES: */
/* */
/* ENTRY POINT: */
/* LINKAGE: */
/* void SizeWindow(HWND hwnd, PRHWINDATA pWinData) */
/* */
/* INPUT: */
/* hwnd - The handle of the client window. */
/* pWinData - A pointer to the RHWINDATA structure of the window. */
/* */
/* EXIT-NORMAL: */
/* */
/* EXIT-ERROR: */
/* */
/* EFFECTS: */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* WinQueryWindow */
/* WinQueryWindowPos */
/* WinSetWindowPos */
/* WinWindowFromID */
/* */
/**************************** END OF SPECIFICATIONS ***************************/
void SizeWindow(HWND hwnd, PRHWINDATA pWinData) {
HWND hOwner; /* Window handle of parent window */
SWP windowPos; /* info on window position */
ULONG in_hgt = pWinData->in_hgt; /* Height for input entry field */
if (!pWinData->visible)
return ; /* If the window is not visible, do */
/* nothing */
hOwner = WinQueryWindow(hwnd, QW_PARENT);
/* Get Window positions */
WinQueryWindowPos(WinWindowFromID(hOwner, (USHORT) FID_CLIENT), &windowPos);
/* adjust MLE and input field, if created */
if (pWinData->outmle && pWinData->insle) {
WinSetWindowPos(pWinData->outmle, /* set window a bit smaller */
HWND_TOP,
(SHORT)BORDER_MARGIN,
(SHORT)BORDER_MARGIN-1,
(SHORT)(windowPos.cx-(BORDER_MARGIN *2)+1),
(SHORT)(windowPos.cy-in_hgt-(BORDER_MARGIN *6)),
SWP_SIZE|SWP_MOVE|SWP_ZORDER|SWP_SHOW);
WinSetWindowPos(pWinData->insle, /* set window a bit smaller */
HWND_TOP,
(SHORT)(BORDER_MARGIN *3+pWinData->wtitle),
(SHORT)(windowPos.cy-in_hgt-BORDER_MARGIN *3),
(SHORT)(windowPos.cx-BORDER_MARGIN *5-pWinData->wtitle),
(SHORT)pWinData->in_hgt,
SWP_SIZE|SWP_MOVE|SWP_ZORDER|SWP_SHOW);
}
return ;
}
/************************** START OF SPECIFICATIONS ***************************/
/* */
/* SUBROUTINE NAME: io_routine */
/* */
/* DESCRIPTIVE NAME: */
/* Process the REXX IO exit. */
/* */
/* FUNCTION: */
/* This function has been registered to handle the IO exits */
/* for the REXX procedure. The interface is defined by REXXSAA. */
/* For the input requests (RXSIOTRD and RXSIODTR), first the */
/* window is made visible, if it isn't already, and then the */
/* trace options are enabled/disabled as appropriate. Then */
/* a return code is set to allow normal operation of I/O by */
/* REXX. */
/* */
/* NOTES: */
/* */
/* ENTRY POINT: */
/* LINKAGE: */
/* LONG io_routine( LONG exitno, LONG subfunc, PUCHAR parmblock) */
/* */
/* INPUT: */
/* The arguments are defined by the REXX interface specifications. */
/* */
/* EXIT-NORMAL: */
/* */
/* EXIT-ERROR: */
/* */
/* EFFECTS: */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: */
/* Remove_Q_Element: Remove a queue element, wait if none there */
/* SetCheckMark - Check/uncheck a menu item */
/* SetOptions - Enable/disable menu items. */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* */
/**************************** END OF SPECIFICATIONS ***************************/
LONG io_routine(LONG exitno, LONG subfunc, PUCHAR parmblock)
{
LONG rc; /* rc=1 says use standard I/O routines */
PLIST_ENTRY q_elem; /* entry in queue */
RXSIOSAY_PARM *sparm = (RXSIOSAY_PARM *)parmblock;/* struc for IO exit */
PRHWINDATA userdata[2]; /* registered user data */
PRHWINDATA pWinData; /* global data anchor */
USHORT exists; /* existance flag */
/* retrieve the anchor */
if (RexxQueryExit(PMRXIO_EXIT, NULL, &exists, (PUCHAR)userdata))
/* failed? */
return RXEXIT_RAISE_ERROR; /* raise a system failure error */
rc = RXEXIT_NOT_HANDLED; /* let others go through */
pWinData = userdata[0]; /* get saved global anchor */
if (exitno == RXSIO) {
switch (subfunc) {
case RXSIODTR : /* For trace read we want to enable the*/
/* trace menu items so we must perform */
/* the read ourselves. */
/* Enable all the options */
SetOptions(pWinData->frame, RXIOA_TRCSTEP, TRUE);
SetOptions(pWinData->frame, RXIOA_TRCLAST, TRUE);
SetOptions(pWinData->frame, RXIOA_TRCOFF, TRUE);
if (!pWinData->tracebit) { /* Set tracing active flag in menu */
SetCheckMark(pWinData->frame, RXIOA_TRACE,
(BOOL)(!pWinData->tracebit));
}
pWinData->trace_inp = TRUE; /* Set the trace active flag for IO */
pWinData->in_type = TRC_IN;
q_elem = Remove_Q_Element(&pWinData->trace_in);/* And get input */
pWinData->in_type = STD_IN;
pWinData->trace_inp = FALSE; /* Reset the trace active flag for IO */
/* Disable all the options */
SetOptions(pWinData->frame, RXIOA_TRCSTEP, FALSE);
SetOptions(pWinData->frame, RXIOA_TRCLAST, FALSE);
SetOptions(pWinData->frame, RXIOA_TRCOFF, FALSE);
if (!pWinData->tracebit) { /* Reset the trace flag as appropriate */
SetCheckMark(pWinData->frame, RXIOA_TRACE, pWinData->tracebit);
}
/* Copy the input line to the return area. */
strcpy(sparm->rxsio_string.strptr, q_elem->ptr);
sparm->rxsio_string.strlength = strlen(q_elem->ptr);
free(q_elem->ptr); /* And free the memory. */
free(q_elem);
rc = RXEXIT_HANDLED; /* Set the return code to */
break; /* input complete. */
case RXSIOTRD : /* If a read occurs and the window is */
/* not visible, make it visible. */
if (!pWinData->visible) {
while (!WinPostMsg(pWinData->client, (USHORT)REXX_MAKE_VISIBLE,
(MPARAM)0, (MPARAM)0)) {
DosSleep((ULONG)TIMER_DELAY);
}
}
break;
default : /* For all else, let REXX do the */
break; /* work. */
} /* endswitch */
}
return rc;
}
/************************** START OF SPECIFICATIONS ***************************/
/* */
/* SUBROUTINE NAME: stdinpipe */
/* */
/* DESCRIPTIVE NAME: */
/* Send input lines to the standard input of child processes. */
/* */
/* FUNCTION: */
/* This function is the thread that waits for input for child */
/* processes started by calls to the subcommand environment, */
/* passes that input through to the pipe connected to their */
/* standard input handle. */
/* */
/* NOTES: */
/* */
/* ENTRY POINT: */
/* LINKAGE: */
/* void stdinpipe() */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: */
/* Remove_Q_Element - Removes an entry from an input queue. Waits for */
/* one if the queue is empty. */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* DosWaitEventSem */
/* DosWrite */
/* */
/**************************** END OF SPECIFICATIONS ***************************/
void stdinpipe(PRHWINDATA pWinData) {
PLIST_ENTRY q_elem; /* element from queue */
UCHAR str[ANSLEN+5]; /* data from queue entry */
ULONG written; /* bytes written by DosWrite */
while (TRUE) {
q_elem = Remove_Q_Element(&pWinData->pipe_in);
strcpy(str, q_elem->ptr);
strcat(str, "\r\n");
DosWrite(pWinData->stdin_w, str, strlen(str), &written);
free(q_elem->ptr);
free(q_elem);
}
DosExit(EXIT_THREAD, 0); /* end the thread */
}
/************************** START OF SPECIFICATIONS ***************************/
/* */
/* SUBROUTINE NAME: stdoutpipe */
/* */
/* DESCRIPTIVE NAME: */
/* Send lines from the standard output of child processes to */
/* the output window. */
/* */
/* FUNCTION: */
/* This function is the thread that waits for output from child */
/* processes started by calls to the subcommand environment, */
/* passes that output through to the output window. */
/* */
/* NOTES: */
/* */
/* ENTRY POINT: */
/* LINKAGE: */
/* void stdoutpipe() */
/* */
/* INPUT: */
/* */
/* EXIT-NORMAL: */
/* */
/* EXIT-ERROR: */
/* */
/* EFFECTS: */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: */
/* addline - Macro to add a line to the output window */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* DosPostEventSem */
/* DosRequestMutexSem */
/* DosReleaseMutexSem */
/* DosWaitEventSem */
/* DosSleep */
/* */
/**************************** END OF SPECIFICATIONS ***************************/
void stdoutpipe(PRHWINDATA pWinData) {
UCHAR buffer[MAXWIDTH]; /* holds data from standard out */
UCHAR tchar = '\0'; /* temporary character variable */
ULONG len; /* counter */
ULONG nread; /* bytes read */
USHORT exists; /* existance flag */
/* retrieve the anchor */
RexxQueryExit(PMRXIO_EXIT, NULL, &exists, NULL);
while (!pWinData->stopoutpipe) {
len = 0; /* initialize count back to 0 */
/* Loop here until we see a new line, or the buffer is full */
do {
if (!DosRead(pWinData->stdout_r,&tchar, 1, &nread) && nread) {
if (tchar == '\r') {
DosRead(pWinData->stdout_r,&tchar, 1, &nread);
if (tchar != '\n')
buffer[len++] = '\n';
}
buffer[len++] = (UCHAR)tchar;
}
}
while (len < MAXWIDTH-1 && tchar != '\n');
buffer[len] = END_STR; /* Terminate the string */
if (pWinData->stopoutpipe) /* shutdown flag? */
break; /* time to leave */
/* Now add the data into the import structure, but first get */
/* the semaphore. */
DosRequestMutexSem(pWinData->imp_ptr->sem, SEM_INDEFINITE_WAIT);
/* If there is no more room in the import area, add the data */
if (pWinData->imp_ptr->total_size <= pWinData->imp_ptr->inuse+len+2) {
DosReleaseMutexSem(pWinData->imp_ptr->sem);
addline(pWinData->client, strdup(buffer));
/* Give the MLE a chance to add the data */
DosSleep((ULONG)TIMER_DELAY);
/* There is room in the import area, so add the data */
}
else {
strcat(pWinData->imp_ptr->data, buffer);
pWinData->imp_ptr->inuse += len;
DosReleaseMutexSem(pWinData->imp_ptr->sem);
/* Set (or reset) the timer */
if (!pWinData->imp_queued) {
pWinData->imp_queued = TRUE;
while (!WinPostMsg(pWinData->frame, START_TIMER, NULL, NULL)) {
DosSleep((ULONG)TIMER_DELAY);
}
}
}
} /* endwhile */
DosExit(EXIT_THREAD, 0); /* end the thread */
}
/************************** START OF SPECIFICATIONS ***************************/
/* */
/* SUBROUTINE NAME: EntryDlgProc */
/* */
/* DESCRIPTIVE NAME: */
/* Dialog procedure for the input entry field. */
/* */
/* FUNCTION: */
/* This is the Dialog Procedure that is registered to handle */
/* the messages coming into the dialog that establishes the */
/* input entry field. The messages that are handled are: */
/* WM_BUTTON1DBLCLK - Copy the marked area from the output window into */
/* the input window. */
/* WM_BUTTON2DBLCLK - Same as pressing ENTER in the input window. */
/* WM_CHAR - several characters are processed here. These include: */
/* VK_NEWLINE - take the data in the input window and place it on */
/* current input queue, then clear the entry field. */
/* VK_UP - place the last entered entry into the input field. */
/* All other messages and keys are handled by default */
/* processing. */
/* */
/* NOTES: */
/* */
/* ENTRY POINT: */
/* LINKAGE: */
/* This is defined by the PM interface for dialog procedures. */
/* */
/* INPUT: */
/* item - The id of the item to enable/disable */
/* option - TRUE to enable the option, FALSE to disable. */
/* */
/* EXIT-NORMAL: */
/* */
/* EXIT-ERROR: */
/* */
/* EFFECTS: */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: */
/* addline - Macro to add a line to the output window */
/* Add_Q_Element - Adds an entry to an input queue. */
/* */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* WinDefDlgProc */
/* WinQueryWindow */
/* WinQueryWindowPtr */
/* WinQueryWindowText */
/* WinSendMsg */
/* WinSetFocus */
/* WinSetWindowText */
/* */
/**************************** END OF SPECIFICATIONS ***************************/
MRESULT EXPENTRY EntryDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) {
static PUCHAR last_str[2] = { NULL,NULL };
LONG len = ANSLEN; /* length of input buffer */
UCHAR str[ANSLEN+1]; /* holds data from input buffer */
LONG len1; /* number of characters input */
WNDPARAMS wp; /* struc to update input window */
HWND hOwner; /* parent window handle */
IPT start,end; /* Insertion point for MLE */
PRHWINDATA pWinData; /* pointer to WinData structure */
hOwner = WinQueryWindow(hwnd, QW_PARENT);
pWinData = WinQueryWindowPtr(hOwner, (SHORT)0);
switch (msg) {
case WM_SETFOCUS :
pWinData->infocus = (BOOL)(mp2?TRUE:FALSE);
break;
case WM_BUTTON1DBLCLK :
start = (IPT)WinSendMsg(pWinData->outmle, MLM_QUERYSEL,
MPFROMSHORT(1), (MPARAM)0);
end = (IPT)WinSendMsg(pWinData->outmle, MLM_QUERYSEL,
MPFROMSHORT(2), (MPARAM)0);
if (end > start) {
PUCHAR ptr = (PUCHAR)malloc((LONG )(end-start+2));
ULONG len = end-start;
ULONG got;
if (ptr && WinSendMsg(pWinData->outmle, MLM_SETIMPORTEXPORT, ptr,
MPFROMLONG(end-start+1))) {
if (got = (ULONG)WinSendMsg(pWinData->outmle, MLM_EXPORT,
MPFROMLONG(&start), MPFROMLONG(&len))) {
PUCHAR ptr1 = ptr;
PUCHAR ptr2;
while (!*ptr1)
ptr1++; /* Skip over any nulls. */
ptr2 = ptr1; /* Now find the end */
while (*ptr2 && /* at NULL, newline or */
(*ptr2 != '\n') && /* carraige return. */
*ptr2 != '\r' && ptr2-ptr < (INT)got)
*ptr2++;
*(ptr2) = '\0';
WinSetWindowText(hwnd,
ptr1); /* Put into SLE */
}
}
if (ptr) {
free(ptr);
}
}
break;
case WM_BUTTON2DBLCLK :
WinSendMsg(hwnd, WM_CHAR, MPFROM2SHORT(KC_VIRTUALKEY, NULL),
MPFROM2SHORT(NULL, VK_NEWLINE));
break;
case WM_CHAR :
if (!(SHORT1FROMMP(mp1)&KC_KEYUP) &&
(SHORT1FROMMP(mp1)&KC_VIRTUALKEY) ) {
switch (SHORT2FROMMP(mp2)) {
case VK_BREAK :
WinSendMsg(pWinData->client, WM_COMMAND,
MPFROMSHORT(RXIOA_HALT), (MPARAM)0);
break;
case VK_NEWLINE :
case VK_ENTER : {
PLIST_ENTRY qe = malloc(sizeof *qe);
len1 = WinQueryWindowText(hwnd, (SHORT)len, str);
if (qe) {
PUCHAR str1 = malloc(len1+4);
if (last_str[pWinData->in_type]) {
free(last_str[pWinData->in_type]);
}
memcpy(str1, str, len1);
strcpy(str1+len1, "\n");
/* only add input if executing */
last_str[pWinData->in_type] = strdup(str1);
addline(pWinData->client, strdup(str1));
qe->len = len1;
qe->ptr = strdup(str);
*(str+len1) = '\0';
if (pWinData->trace_inp) {
Add_Q_Element(&pWinData->trace_in, qe);
}
else {
Add_Q_Element(&pWinData->pipe_in, qe);
}
free(str1);
}
}
WinSendMsg(hwnd, EM_SETSEL, MPFROM2SHORT(0, len1), (MPARAM)0);
WinSendMsg(hwnd, EM_CLEAR, (MPARAM)0, (MPARAM)0);
return (MRESULT)TRUE;
break;
case VK_UP :
if (last_str[pWinData->in_type]) {
WinSendMsg(hwnd, EM_SETSEL, MPFROM2SHORT(0, len1), (MPARAM)0);
WinSendMsg(hwnd, EM_CLEAR, (MPARAM)0, (MPARAM)0);
*(last_str[pWinData->in_type] +
strlen(last_str[pWinData->in_type])-1) = '\0';
wp.fsStatus = WPM_TEXT+WPM_CCHTEXT;
wp.cchText = (SHORT)strlen(last_str[pWinData->in_type]);
wp.pszText = strdup(last_str[pWinData->in_type]);
WinSendMsg(hwnd, WM_SETWINDOWPARAMS, &wp, (MPARAM)0);
*(last_str[pWinData->in_type] +
strlen(last_str[pWinData->in_type])) = '\r';
return (MRESULT)TRUE;
}
break;
case VK_TAB :
case VK_BACKTAB :
return (MRESULT)WinSetFocus(HWND_DESKTOP,
pWinData->infocus?pWinData->outmle: pWinData->insle);
break;
default :
break;
}
}
default :
break;
}
return WinDefDlgProc(hwnd, msg, mp1, mp2);
}
/************************** START OF SPECIFICATIONS ***************************/
/* */
/* SUBROUTINE NAME: SelectFont */
/* */
/* DESCRIPTIVE NAME: */
/* Interface to the Font Selection dialog. */
/* */
/* FUNCTION: */
/* This routine sets up the parameters and calls the Font */
/* Selection dialog routines. Responses from the dialog will */
/* be via WM_CONTROL messages to the parent window procedure. */
/* */
/* NOTES: */
/* */
/* ENTRY POINT: */
/* LINKAGE: */
/* ULONG SelectFont(PRHWINDATA pWinData) */
/* */
/* INPUT: */
/* pWinData - Pointer to the WinData structure of the parent */
/* window. */
/* */
/* EXIT-NORMAL: */
/* */
/* EXIT-ERROR: */
/* */
/* EFFECTS: */
/* */
/* INTERNAL REFERENCES: */
/* ROUTINES: */
/* FontDialog - Load and initialize the Font dialog */
/* */
/* EXTERNAL REFERENCES: */
/* ROUTINES: */
/* WinProcessDlg */
/* WinSendMsg */
/* */
/**************************** END OF SPECIFICATIONS ***************************/
ULONG SelectFont(PRHWINDATA pWinData) {
PFONTDLG fntd; /* font dialog control */
BOOL rc; /* success/failure flag */
fntd = &pWinData->MleFontAttrs; /* point to control structure */
fntd->cbSize = sizeof(FONTDLG);
if (!fntd->pszFamilyname) {/* do first time set up */
/* set the buffer */
fntd->pszFamilyname = pWinData->MleFamilyName;
strcpy(fntd->pszFamilyname, fntd->fAttrs.szFacename);
fntd->fxPointSize = MAKEFIXED(8,0);
}
fntd->pszPreview = getstring(pWinData->hab, pWinData->hResource,
SAMPLE_TEXT);
fntd->pszTitle = getstring(pWinData->hab, pWinData->hResource,
FONT_TITLE);
fntd->fl = FNTS_CENTER + FNTS_HELPBUTTON;
fntd->clrFore = CLR_NEUTRAL; /* Selected foreground color */
fntd->clrBack = CLR_BACKGROUND; /* Selected Background color */
fntd->usWeight = FWEIGHT_NORMAL;
fntd->usWidth = FWIDTH_NORMAL;
fntd->hpsScreen = WinGetPS(pWinData->outmle);
fntd->fAttrs.usCodePage = (USHORT)pWinData->CountryInfo.codepage;
fntd->clrFore = CLR_BLACK;
fntd->clrBack = CLR_WHITE;
fntd->usFamilyBufLen = MAXWIDTH;
fntd->pszPtSizeList = NULL; /* use default point sizes*/
rc = TRUE;
/* Disable the window for update, and call the font dialog */
WinEnableWindowUpdate(pWinData->outmle, FALSE);
if (!WinFontDlg(HWND_DESKTOP, pWinData->frame, fntd) ||
fntd->lReturn != DID_OK) {
rc = FALSE;
} else {
/**********************************************************/
/* If outline font, calculate the maxbaselineext and */
/* avecharwidth for the point size selected */
/**********************************************************/
if ( fntd->fAttrs.fsFontUse == FATTR_FONTUSE_OUTLINE )
{
HDC hDC;
LONG lxFontResolution;
LONG lyFontResolution;
SIZEF sizef;
/********************************************************/
/* Query device context for the screen and then query */
/* the resolution of the device for the device context. */
/********************************************************/
hDC = GpiQueryDevice(fntd->hpsScreen);
DevQueryCaps( hDC, CAPS_HORIZONTAL_FONT_RES,
(LONG)1, &lxFontResolution);
DevQueryCaps( hDC, CAPS_VERTICAL_FONT_RES,
(LONG)1, &lyFontResolution);
/********************************************************/
/* Calculate the size of the character box, based on the*/
/* point size selected and the resolution of the device.*/
/* The size parameters are of type FIXED, NOT int. */
/* NOTE: 1 point == 1/72 of an inch. */
/********************************************************/
sizef.cx = (FIXED)(((fntd->fxPointSize) / 72 ) *
lxFontResolution );
sizef.cy = (FIXED)(((fntd->fxPointSize) / 72 ) *
lyFontResolution );
fntd->fAttrs.lMaxBaselineExt =
MAKELONG( HIUSHORT( sizef.cy ), 0 );
fntd->fAttrs.lAveCharWidth =
MAKELONG( HIUSHORT( sizef.cx ), 0 );
}/* endif fsFontUse == FATTR_FONTUSE_OUTLINE */
} /* endif !WinFontDlg */
WinReleasePS(fntd->hpsScreen);
if (rc) {
WinSendMsg(pWinData->outmle, /* set font of multiline edit field */
MLM_SETFONT, MPFROMP((PFATTRS)&fntd->fAttrs), (MPARAM)0);
}
WinEnableWindowUpdate(pWinData->outmle, TRUE);
free(fntd->pszTitle);
free(fntd->pszPreview);
return (TRUE);
}