This chapter provides information needed to incorporate IBM® Standard EHLLAPI (16- and 32-bit), WinHLLAPI (16- and 32-bit), and IBM Enhanced 32-bit EHLLAPI (EHLAPI32) functions into applications written in a high level language. It provides details on call format, memory allocation considerations, initializing the interfaces, and compiling and linking applications. Also included is a short sample EHLLAPI program and the compile/link instructions used to build it. Finally, a set of possible uses for the EHLLAPI interface (scenarios) is described.
An EHLLAPI application is any application program which uses the EHLLAPI interface to access the host 3270/5250/VT presentation space. The presentation space includes the visible emulator character data, fields and attribute data, keystroke data, and other information.
Following are overviews for HLLAPI programming interfaces.
EHLLAPI is a standard programming interface which allows programmatic access to a host emulator session. Functions are provided for reading host screen data (such as the characters and attributes), for sending keystrokes, and performing other emulator-related functions.
The EHLLAPI interface is a single call-point interface. There is a single callable API through which all EHLLAPI functions are requested. On each call to the interface the application provides a function number which identifies the function requested, a pointer to a data buffer, a pointer to the length of the data buffer, and a pointer to a return code (see EHLLAPI Call Format).
WinHLLAPI is based on the familiar EHLLAPI.API. It encompasses all of the existing functionality and adds extensions that take advantage of the Windows® message driven environment. Users of the IBM Personal Communications EHLLAPI interface will notice no functional difference unless they incorporate the WinHLLAPI extensions.
The WinHLLAPI extension functions and any functions that deviate from the EHLLAPI form are described in WinHLLAPI Extension Functions. For information on common functions, refer to EHLLAPI Functions.
The entry symbol for WinHLLAPI, is appropriately, WinHLLAPI. EHLLAPI users wishing to switch to the WinHLLAPI implementation must change from the hllapi standard entry. New users should follow all of the directions in EHLLAPI Functions, and use the WinHLLAPI entry in place of the standard hllapi entry.
IBM Enhanced EHLLAPI is based on the familiar EHLLAPI API. It encompasses all of the existing functionality but takes advantage of the 32-bit environment and uses modified data structures. Standard interface users wishing to switch to IBM Enhanced 32-bit EHLLAPI need to change only the entry symbol from LPWORD to LPINT in the first, third, and fourth parameters. New users should use the procedures in the following sections.
Any programming language which can invoke an entry point in a DLL with the "Pascal" calling convention can be used to execute EHLLAPI functions. However, the Personal Communications EHLLAPI toolkit provides header files and function prototypes only for the C++ languages. A clear understanding of data structure layout and calling conventions is required to use any other language. The EHLLAPI toolkit supports the following C/C++ compilers:
Most other C/C++ compilers will also work with the toolkit.
EHLLAPI C/C++ applications must include the Personal Communications EHLLAPI header file (HAPI_C.H). This file defines the layout of data structures and provides a prototype for the EHLLAPI entry point.
The EHLLAPI entry point (hllapi) is always called with the following four parameters:
The prototype for IBM Standard EHLLAPI is:
[long hllapi (LPWORD, LPSTR, LPWORD, LPWORD);
The prototype for IBM Enhanced EHLLAPI is:
[long hllapi (LPINT, LPSTR, LPINT, LPINT);
Each parameter is passed by reference not by value. Thus each parameter to the function call must be a pointer to the value, not the value itself. For example, the following is a correct example of calling the EHLLAPI Query Session Status function:
#include "hapi_c.h" struct HLDQuerySessionStatus QueryData; int Func, Len, Rc; long Rc; memset(QueryData, 0, sizeof(QueryData)); // Init buffer QueryData.qsst_shortname = 'A'; // Session to query Func = HA_QUERY_SESSION_STATUS; // Function number Len = sizeof(QueryData); // Len of buffer Rc = 0; // Unused on input hllapi(&Func, (char *)&QueryData, &Len, &Rc); // Call EHLLAPI if (Rc != 0) { // Check return code // ...Error handling }
All the parameters in the hllapi call are pointers and the return code of the EHLLAPI function is returned in the value of the 4th parameter, not as the value of the function. For example, the following is not correct:
if (hllapi(&Func, (char *)&QueryData, &Len, &Rc) != 0) { // WRONG! // ...Error handling }
Although the hllapi function is defined to return a long data type for IBM Standard and Enhanced EHLLAPI, and void data type for WinHLLAPI, its value is undefined and should not be used.
The second through fourth parameters of the hllapi call can return information to the application. The description of each EHLLAPI function describes what, if any, information is returned in these parameters.
Many EHLLAPI functions use a formatted data structure to pass information to or from the application program. The description of each function shows the layout of the data structure. The data passed to or from the EHLLAPI function must exist in storage exactly as documented, byte for byte. Note that the structure layout is the same for all IBM Standard and WinHLLAPI 16- and 32-bit applications. Data structures for the IBM Enhanced 32-bit applications are packed to a 4-byte alignment.
It is highly recommended that the supplied header file and data structure definitions be used to ensure proper data alignment and layout. Although it is technically possible, the following is not recommended:
char QueryData[20]; // Not recommended ... Func = HA_QUERY_SESSION_STATUS; hllapi(&Func, QueryData, &Len, &Rc); if (QueryData[13] == 'F') { // ...this is a 5250 session }
The recommended way to write this function would be:
#include "hapi_c.h" struct HLDQuerySessionStatus QueryData; // Recommended ... Func = HA_QUERY_SESSION_STATUS; hllapi(&Func, (char *)&QueryData, &Len, &Rc); if (QueryData.qsst_sestype == 'F') { // ...this is a 5250 session }
EHLLAPI functions do not allocate or free memory. The application program must preallocate buffer space for EHLLAPI functions which require it before calling the hllapi entry point. The buffer space may be pre-allocated as a dynamic variable such as:
struct HLDQuerySessionStatus QueryBuff;
or it may be allocated by a call to a C library or operating system function such as:
struct HLDQuerySessionStatus *QueryBuff; ... QueryBuff = malloc(sizeof(struct HLDQuerySessionStatus));
In any case, the application is responsible for allocating sufficient buffer space before calling EHLLAPI functions and for freeing buffers when they are not needed.
EHLLAPI functions return a completion code or return codein the 4th parameter of the hllapi function call (except for the Convert Position or RowCol (99) function). The return code indicates the success or failure of the requested function.
Unless indicated otherwise in the description of each function, the following table shows the meaning of each return code value. Some functions may have a slightly different interpretation of these return codes; refer to the individual function descriptions for details.
Return Code | Explanation |
---|---|
0 | The function successfully executed, or no update since the last call was issued. |
1 | An incorrect host presentation space ID was specified. The specified session either was not connected, does not exist, or is a logical printer session. |
2 | A parameter error was encountered, or an incorrect function number was specified. (Refer to the individual function for details.) |
4 | The execution of the function was inhibited because the target presentation space was busy, in X CLOCK state (X []), or in X SYSTEM state. |
5 | The execution of the function was inhibited for some reason other than those stated in return code 4. |
6 | A data error was encountered due to specification of an incorrect parameter (for example, a length error causing truncation). |
7 | The specified presentation space position was not valid. |
8 | A functional procedure error was encountered (for example, use of conflicting functions or missing prerequisite functions). |
9 | A system error was encountered. |
10 | This function is not available for EHLLAPI. |
11 | This resource is not available. |
12 | This session stopped. |
24 | The string was not found, or the presentation space is unformatted. |
25 | Keystrokes were not available on input queue. |
26 | A host event occurred. See Query Host Update (24) for details. |
27 | File transfer was ended by a Ctrl+Break command. |
28 | Field length was 0. |
31 | Keystroke queue overflow. Keystrokes were lost. |
32 | An application has already connected to this session for communications. |
33 | Reserved. |
34 | The message sent to the host was canceled. |
35 | The message sent from the host was canceled. |
36 | Contact with the host was lost. |
37 | Inbound communication has been disabled. |
38 | The requested function has not completed its execution. |
39 | Another DDM session is already connected. |
40 | The disconnection attempt was successful, but there were asynchronous requests that had not been completed at the time of the disconnection. |
41 | The buffer you requested is being used by another application. |
42 | There are no outstanding requests that match. |
43 | The API was already locked by another EHLLAPI application (on LOCK) or API not locked (on UNLOCK). |
Applications using EHLLAPI functions must include the appropriate header file to obtain the proper function prototypes, constants, and data structure definitions. These header files may be used with any of the supported C/C++ compilers (see Languages). If a different compiler or language is used, then you must provide your own equivalent definitions and structures.
There are two possible ways to link the application program, depending on how the entry point is to be resolved. The simplest way is to statically link the application with the appropriate Personal Communications library. This will resolve the entry point at link time. The operating system will load the correct DLL with the application when it starts. Another way to link to the entry point is to perform dynamic linking. In this case, the application uses operating system calls to load the correct DLL and obtain the entry point address at run time.
The following table shows which header files to use, which .LIB should be used for static linking, and which .DLL should be used for dynamic loading.
Interface | Entry Point | Header File | LIB | DLL |
---|---|---|---|---|
IBM Standard (16-bit) | hllapi | hapi_c.h | PCSCALLS.DLL | PCSHLL.DLL |
IBM Standard (32-bit) | hllapi | ehlapi32.h | EHLAPI32.LIB | EHLAPI32.DLL |
IBM Enhanced (32-bit) | hllapi | hapi_c.h | PCSCAL32.LIB | PCSHLL32.DLL |
WinHLLAPI (16-bit) | winhllapi | whllapi.h | WHLLAPI.LIB | WHLLAPI.DLL |
WinHLLAPI (32-bit) | winhllapi | whllapi.h | WHLAPI32.LIB | WHLAPI32.DLL |
Using the static link method the application can simply call the hllapi entry point when needed such as:
#include "hapi_c.h" int HFunc, HLen, HRc; // Function parameters char HBuff[1]; // Function parameters ... HFunc = HA_RESET_SYSTEM; // Run EHLLAPI function HLen = 0; HRc = 0; hllapi(&Func, HBuff, &HLen, &HRc); if (HRc != 0) { // ... EHLLAPI access error }
When the application is linked, the appropriate Personal Communications library files must be linked with the application executable code. For example, the following link command might be used (IBM VisualAge C/C++):
ilink /de /noe pcscal32.lib sample.obj
When the operating system loads an application constructed in this way, the Personal Communications EHLLAPI module is loaded automatically.
Using the dynamic link method the application makes calls to the operating system at run time to load the Personal Communications EHLLAPI module and to locate the hllapi entry point within it. This method requires more code in the application but gives the application greater control over error conditions. For example, the application can display a specific error message to the user if the Personal Communications EHLLAPI module cannot be found.
To use dynamic linking, the application needs to load the appropriate Personal Communications module and locate the entry point. It is recommended that the entry point be located by its ordinal number and not by name. The ordinal number is defined in the header file. The following 32-bit Windows code loads the IBM Standard 32-bit EHLLAPI module, locates the hllapi entry point, and makes an EHLLAPI function call.
#include "hapi_c.h" HMODULE Hmod; // Handle of PCSHLL32.DLL long (APIENTRY hllapi)(int *, char *, int *, int *); // Function pointer int HFunc, HLen, HRc; // Function parameters char HBuff[1]; // Function parameters Hmod = LoadLibrary("PCSHLL32.DLL"); // Load EHLLAPI module if (Hmod == NULL) { // ... Error, cannot load EHLLAPI module } hllapi = GetProcAddress(Hmod, MAKEINTRESOURCE(ord_hllapi)); // Get EHLLAPI entry point if (hllapi == NULL) { // ... Error, cannot find EHLLAPI entry point } HFunc = HA_RESET_SYSTEM; // Run EHLLAPI function HLen = 0; HRc = 0; (*hllapi)(&Func, HBuff, &HLen, &HRc); if (HRc != 0) { // ... EHLLAPI access error }
IBM Enhanced EHLLAPI (32-bit) and IBM Standard EHLLAPI 16-bit connect on a per process basis. All threads access the same connected host session. The thread that performs the connections must also perform the disconnection.
IBM Standard EHLLAPI (32-bit) and WinHLLAPI connect on a per thread basis. Each thread must maintain its own connections. This allows a multithreaded process to maintain connections to more than one connected host session at a time. This eliminates the need for multi-process schemes when using a WinHLLAPI program to coordinate data between different hosts. It also puts the burden of connecting and disconnecting as necessary on the individual thread.
Many EHLLAPI functions require a presentation space ID (PSID) to indicate which host emulator session is to be used for the function. (This is also referred to as the short session ID). A presentation space ID is a single character in the range A to Z. There are a maximum of 26 sessions.
For IBM Enhanced EHLLAPI applications, the session ID is extended with three additional bytes. These extended session bytes must be set to zero for future compatibility. This is most easily accomplished by setting the contents of EHLLAPI buffers to all binary zero before filling them in with the required information. For example, the following might be used to query the status of session B:
#include "hapi_c.h" int HFunc, HLen, HRc; // Function parameters struct HLDPMWindowStatus StatusData; // Function parameters Func = HA_PM_WINDOW_STATUS; HLen = sizeof(StatusData); HRc = 0; // Set data buffer to zeros and fill in request memset(&StatusData, 0x00, sizeof(StatusData)); StatusData.cwin_shortname = 'B'; // Short session ID StatusData.cwin_option = 0x02; // Query command hllapi(&Func, (char *)&StatusData, &HLen, &HRc);
An emulator session can be configured as a display session or a printer session. EHLLAPI applications cannot connect to printer or router sessions of PC400. The Query Sessions (10) function can be used to determine the type of a particular session.
An emulator display session can be configured for a range of screen sizes from 1920 bytes (24x80 screen size) to 9920 bytes (62x160 screen size). Some EHLLAPI functions such as Copy PS to String (8) require the application to allocate enough storage to hold (possibly) the entire presentation space. The size of the presentation space for a given session can be obtained using the Query Session Status (22) function.
EHLLAPI functions interact with only one presentation space at a time. The presentation space ID (PSID) is used to identify the particular presentation space in which a function is to operate.
For some functions, the PSID is contained in a preceding call to the Connect Presentation Space (1) function. For other functions, the PSID is contained in the calling data string parameter.
Connection to the host presentation space (or session) is controlled by using the Connect Presentation Space (1) and Disconnect Presentation Space (2) functions. The status of the connection determines whether some functions can be executed. It also affects how the PSID is defined. The following text explains how to control the status of the connection to the host presentation space:
The PSID is used to specify the host presentation space (or session) in which you desire a function to operate. The way the PSID is handled is affected by two factors:
The following paragraphs describe how the PSID is handled for the various combinations of these two factors.
Some functions interact only with the host-connected presentation space. These functions require the Connect Presentation Space (1) function as a prerequisite call. The PSID for these functions is determined by the Connect Presentation Space (1) and the Disconnect Presentation Space (2) functions as follows:
Some functions can interact with a host presentation space whether it is connected or not. These functions allow you to specify the PSID in the calling data string parameter. They are as follows:
All except the first two of these functions allow you to specify the PSID using either:
The first two functions require that a letter be used to specify the PSID.
When there is no host-connected presentation space, the following rules apply:
When there is one host-connected presentation space, the following rules apply:
The following functions are available for printer sessions:
More than one EHLLAPI application can share a presentation space if the applications support sharing (that is, if they were developed to work together or if they exhibit predictable behavior1). To determine which applications support sharing, EHLLAPI applications are specified as one of following types:
The type of shared access can be defined by setting the following read and write sharing options for each function in the Set Session Parameters (9) function call:
The application allows other applications that allow sharing and have write access permissions to concurrently connect to the same presentation space. The originating application performs supervisory-type functions but does not create errors for other applications that share the presentation space.
The application requires write access and allows only supervisory applications to concurrently connect to its presentation space. This is the default value.
The application requires write access and allows partner or other applications with predictable behavior to share the presentation space.
The application requires write access and allows other applications that perform read-only functions to share the presentation space. The application is also allowed to copy the presentation space and perform other read-only operations as usual.
The application has exclusive use of the presentation space. No other applications are allowed to share the presentation space, including supervisory applications. The application is allowed to copy the presentation space and perform read-only operations as usual.
The application requires only read access to monitor the presentation space and allows other applications that perform read or write, or both, functions to share the presentation space. The application is also allowed to copy the presentation space and perform other read-only operations as usual.
Calling Application | Super_Write | Write_Super | Write_Write | Write_Read | Write_None | Read_Write |
---|---|---|---|---|---|---|
Super_Write | Yes | Yes | Yes | No | No | Yes |
Write_Super (default) | Yes | No | No | No | No | No |
Write_Write | Yes | No | Yes | No | No | Yes |
Write_Read | No | No | No | No | No | Yes |
Write_None | No | No | No | No | No | No |
Read_Write | Yes | No | Yes | Yes | No | Yes |
In addition to specifying compatible read and write access options, applications that are designed to work together but cannot allow others to work in the same presentation space can optionally define a keyword, KEY$nnnnnnnn, in the Set Session Parameters (9) function call. This keyword allows only those applications that use the same keyword to share the presentation space.
Prerequisite Call |
Functions |
Access |
---|---|---|
Allocate Communications Buffer (120) |
Free Communication Buffer (120) |
N/A |
Connect Window Service (101) |
Change PS Window Name (106) Change Switch List Name (105) Disconnect Window Service (102) Query Window Service (103) Window Status (104) |
Write Read Query=Read Set=Write Write |
Connect Presentation Space (1) |
Copy Field to String (34) Copy OIA (13) Copy Presentation Space (5) Copy Presentation Space to String (8) Copy String to Field (33) Copy String to Presentation Space (15) Disconnect Presentation Space (2) Find Field Length (32) Find Field Position (31) Query Cursor Location (7) Query Field Attribute (14) Release (12) Reserve (11) Search Field (30) Search Presentation Space (6) Send key (3) Set Cursor (40) Start Playing Macro (110) Wait (4) |
Read Read Read Read Write Write Write Read Read Read Read Write Write Read Read Read Write Write Read |
Connect Structured Field (120) |
Disconnect Structured Field (121) Get Request Completion (125) Read Structured Field (126) Write Structured Field (127) |
N/A |
Read Structured Field (126) |
Get Request Completion (125) |
N/A |
Start Close Intercept (41) |
Query Close Intercept (42) Stop Close Intercept (43) |
N/A |
Start Host Notification (23) |
Query Host Update (24) Stop Host Notification (25) |
|
Start Keystroke Intercept (50) |
Get Key (51) Post Intercept Status (52) Stop Keystroke Intercept (53) Send Key (3) if edit keystrokes are to be sent (edit keystroked support is available in Enhanced Mode) |
N/A |
Write Structured Field (127) |
Get Request Completion (125) |
N/A |
An application, even if specified with shared presentation space, can obtain exclusive control of a presentation space by using the Lock Presentation Space API (60) or the Lock Windows Services API (61) functions. Requests by the other applications to use a presentation space locked by these functions are queued and processed in first-in-first-out (FIFO) order when the originating application unlocks the presentation space.
If the application that locked the presentation space does not unlock it by using the same call with an Unlock option or Reset System (21) call, the lock is removed when the application terminates or the session stops.
The following mouse actions can be used in the Presentation Space.
Keystrokes originating at a host keyboard might have a corresponding ASCII value. The response of the Get Key (51) function to a keystroke depends on whether the key is defined and also on whether the key is defined as an ASCII value or an ASCII mnemonic.
The keyboard for one session might not be capable of producing some codes needed by the another session. ASCII mnemonics that represent these codes can be included in the data string parameter of the Send Key (3) function.
The capabilities of the Send Key (3) function and the Get Key (51) function allow sessions to exchange keystrokes that might not be represented by ASCII values or by an available key. A set of mnemonics that can be generated from a keyboard is provided. These mnemonics let you use ASCII characters to represent the special function keys of the workstation keyboard.
Mnemonics for unshifted keys consist of the escape character followed by an abbreviation. This is also true for the shift keys themselves, Upper shift, Alt, and Ctrl. Mnemonics for shifted keys consist of the mnemonic for the shift key followed by the mnemonic for the unshifted key. Hence the mnemonic for a shifted key is a 4-character sequence of escape character, abbreviation, escape character, abbreviation.
The default escape character is @. You can change the value of the escape character to any other character with the ESC=c option of the Set Session Parameters (9) function. The following text uses the default escape character, however.
Shift indicators that are not part of the ASCII character set are represented to the host application by 2-byte ASCII mnemonics as follows:
Upper shift | @S |
Alt | @A |
Ctrl | @r |
Mnemonics for these shift indicators are never received separately by an application. Likewise, they are never sent separately by an application. Shift indicator mnemonics are always accompanied by a non-shift-indicator character or mnemonic.
The abbreviations used make the mnemonics for special keys easy to remember. An alphabetic key code has been used for the most common keys. For example, the Clear key is C; the Tab key is T, and so on. Please note that the uppercase and lowercase alphabetic characters are mnemonic abbreviations for different keys.
The following text describes the use of these functions.
All defined keys are represented by either:
To represent a key defined as an ASCII character, a 1-byte ASCII value that corresponds to that character is used.
To represent a key defined as a function, a 2-, 4-, or 6-byte ASCII mnemonic that corresponds to that function is used. For example, to represent the backtab key, @B is used. To represent PF1, @1 is used. To represent Erase Input, @A@F is used. See the following lists:
@B | Left Tab | @0 | Home | @h | PF17 |
@C | Clear | @1 | PF1/F1 | @i | PF18 |
@D | Delete | @2 | PF2/F2 | @j | PF19 |
@E | Enter | @3 | PF3/F3 | @k | PF20 |
@F | Erase EOF | @4 | PF4/F4 | @l | PF21 |
@H | Help (PC400) | @5 | PF5/F5 | @m | PF22 |
@I | Insert | @6 | PF6/F6 | @n | PF23 |
@J | Jump | @7 | PF7/F7 | @o | PF24 |
@L | Cursor Left | @8 | PF8/F8 | @q | End |
@N | New Line | @9 | PF9/F9 | @u | Page UP (PC400) |
@O | Space | @a | PF10/F10 | @v | Page Down (PC400) |
@P | @b | PF11/F11 | @x | PA1 | |
@R | Reset | @c | PF12/F12 | @y | PA2 |
@T | Right Tab | @d | PF13 | @z | PA3 |
@U | Cursor Up | @e | PF14 | @@ | @ (at) symbol |
@V | Cursor Down | @f | PF15 | @$ | Alternate Cursor |
@X | DBCS | @g | PF16 | @< | Backspace |
@Z | Cursor Right |
@A@C | Test (PC400) | @A@e | Pink (PC/3270) |
@A@D | Word Delete | @A@f | Green (PC/3270) |
@A@E | Field Exit | @A@g | Yellow (PC/3270) |
@A@F | Erase Input | @A@h | Blue (PC/3270) |
@A@H | System Request | @A@i | Turquoise (PC/3270) |
@A@I | Insert Toggle | @A@j | White (PC/3270) |
@A@J | Cursor Select | @A@l | Reset Host Color (PC/3270) |
@A@L | Cursor Left Fast | @A@t | Print (Personal Computer) |
@A@Q | Attention | @A@u | Rollup (PC400) |
@A@R | Device Cancel | @A@v | Rolldown (PC400) |
@A@T | Print Presentation Space | @A@y | Forward Word Tab |
@A@U | Cursor Up Fast | @A@z | Backward Word Tab |
@A@V | Cursor Down Fast | @A@- | Field - (PC400) |
@A@Z | Cursor Right Fast | @A@+ | Field + (PC400) |
@A@9 | Reverse Video | @A@< | Record Backspace (PC400) |
@A@b | Underscore (PC/3270) | @S@E | Print Presentation Space on Host (PC400) |
@A@c | Reset Reverse Video (PC/3270) | @S@x | Dup |
@A@d | Red (PC/3270) | @S@y | Field Mark |
If you change the escape character to #, the literal sequences used to represent the Backtab, Home, and Erase Input keys become #B, #0, and #A#F, respectively.
Also, the literal sequence used to represent the @ symbol becomes #@.
If the terminal operator types a key defined as an ASCII character, the host application receives a 1-byte ASCII value that corresponds to that character.
If the operator types a key defined as a function, the host application receives a 2-, 4-, or 6-byte ASCII mnemonic that corresponds to that function. For example, if the Backtab key is typed, @B is received. If PF1 is pressed, @1 is received. If Erase Input is pressed, @A@F is received.
If the operator types a defined shift key combination, the host application receives the ASCII character, or the 2-, 4-, or 6-byte ASCII mnemonic that corresponds to the defined character or function.
If the operator types an individual key that is not defined, the Get Key (51) function returns a return code of 20 and nothing is sent to the host application.
The Get Key (51) function prefixes all characters and mnemonics sent to the host application with two ASCII characters. The first ASCII character is the PSID of the host presentation space to which the keystrokes are sent. The other character is an A, S, or M for ASCII, special shift, or mnemonic, respectively. See Return Parameters.
To send an ASCII character to another session, include that character in the data string parameter of the Send Key (3) function.
To send a function key to another session, include the ASCII mnemonic for that function in the data string parameter of the Send Key (3) function.
If the Send Key (3) function sends an unrecognized mnemonic to the host session a return code rejecting the key might result.
As an aid in debugging EHLLAPI applications, the Trace Facility of Personal Communications may be used. This facility will produce a log of all EHLLAPI calls, parameters, return values, and return codes. For more information on using the Trace Facility, refer to Administrator's Guide and Reference.
The following sample Windows application will enter the character string "Hello World!" in the first input field of host session 'A'.
#include <stdlib.h> #include <stdio.h> #include <windows.h> #include "hapi_c.h" int main(char **argv, int argc) { int HFunc, HLen, HRc; char HBuff[1]; struct HLDConnectPS ConnBuff; // Send Key string for HOME+string+ENTER: char SendString[] = "@0Hello World!@E"; HFunc = HA_RESET_SYSTEM; HLen = 0; HRc = 0; hllapi(&HFunc, HBuff, &HLen, &HRc); if (HRc != HARC_SUCCESS) { printf("Unable to access EHLLAPI.\n"); return 1; } HFunc = HA_CONNECT_PS; HLen = sizeof(ConnBuff); HRc = 0; memset(&ConnBuff, 0x00, sizeof(ConnBuff)); ConnBuff.stps_shortname = 'A'; hllapi(&HFunc, (char *)&ConnBuff, &HLen, &HRc); switch (HRc) { case HARC_SUCCESS: case HARC_BUSY: case HARC_LOCKED: // All these are OK break; case HARC_INVALID_PS: printf("Host session A does not exist.\n"); return 1; case HARC_UNAVAILABLE: printf("Host session A is in use by another EHLLAPI application.\n"); return 1; case HARC_SYSTEM_ERROR: printf("System error connecting to session A.\n"); return 1; default: printf("Error connecting to session A.\n"); return 1; } HFunc = HA_SENDKEY; HLen = strlen(SendString); HRc = 0; hllapi(&HFunc, SendString, &HLen, &HRc); switch (HRc) { case HARC_SUCCESS: break; case HARC_BUSY: case HARC_LOCKED: printf("Send failed, host session locked or busy.\n"); break; default: printf("Send failed.\n"); break; } HFunc = HA_DISCONNECT_PS; HLen = 0; HRc = 0; hllapi(&HFunc, HBuff, &HLen, &HRc); printf("EHLLAPI program ended.\n"); return 0; }
The following MAKEFILE file could be used to build this application with the IBM VisualAge C/C++ for Windows compiler (assuming the source file is named SAMPLE.C):
all: sample.exe hlldir = C:\PCOMWIN\SAMPLES hlllib = C:\PCOMWIN\SAMPLES .SUFFIXES: .C .OBJ .c.obj: icc.exe /Ti /Gh /Gm /Gd /C /I $(hlldir) /Tc $*.c sample.exe: sample.obj ilink.exe /de /noe $(hlllib)\pcscal32.lib $** sample.obj: sample.c
The application could be built with the following command:
nmake /a all
There is no functional difference between the standard and enhanced EHLLAPI interfaces on a given platform. However there are other important differences:
By prefilling EHLLAPI data buffers with binary zeros, and using the data structures supplied in HAPI_C.H, an application can be compiled for standard or enhanced operation without any source code changes. For example, the following section of code would work for standard EHLLAPI but would fail for enhanced EHLLAPI:
#include "hapi_c.h" ... int Func, Len, Rc; char Buff[18]; char SessType; Func = HA_QUERY_SESSION_STATUS; // Function Len = 18; // Buffer length Rc = 0; Buff[0] = 'A' // Session to query hllapi(&Func, Buff, &Len, &Rc); // Execute function SessType = Buff[9]; // Get session type ...
The above example would fail if compiled as a enhanced EHLLAPI application because:
The following is the same function written to work correctly if compiled for standard or enhanced operation. Changed lines are indicated with a >:
#include "hapi_c.h" ... int Func, Len, Rc; > struct HLDQuerySessionStatus Buff; char SessType; Func = HA_QUERY_SESSION_STATUS; // Function > Len = sizeof(Buff); // Buffer length Rc = 0; > memset(&Buff, 0x00, sizeof(Buff));// Zero buffer > Buff.qsst_shortname = 'A'; // Session to query hllapi(&Func, (char *)&Buff, &Len, &Rc); // Execute function > SessType = Buff.qsst_sestype; // Get session type ...
The sample scenarios presented here provide conceptual information about activities that can be facilitated by using EHLLAPI. The scenarios deal with the duties your EHLLAPI programmed operator can perform in these areas:
There are four phases in a typical host system transaction:
Your programmed operator can use a series of EHLLAPI functions to mimic these actions. After determining the correct starting point for the host system transaction, the programmed operator can call the Search Presentation Space (6) function to determine which keyword messages or prompting messages are on the display screen.
Next, the programmed operator can use the Send Key (3) function to type data into a host system session and enter a host system transaction. Then the programmed operator can:
If the keyboard is inhibited, your EHLLAPI program can call the Copy OIA (13) function to get more information about the error condition.
The Search Presentation Space (6) function is critical to simulate another task of the terminal operator. Some host systems do not stay locked in X CLOCK, X [], or X SYSTEM mode until they respond; instead, they quickly unlock the keyboard and allow the operator to stack other requests. In this environment, the terminal operator depends on some other visual prompt to know that the data has returned (perhaps a screen title or label). The Search Presentation Space (6) function allows your EHLLAPI program to search the presentation space while waiting. Also, while waiting for a response, calling the Pause (18) function allows other DOS sessions to share the central processing unit resource. The Pause (18) function has an option that allows your EHLLAPI program to wait for a host system update event to occur.
If no host system event occurs after a reasonable time-out period, your EHLLAPI program could call a customized error message such as:
No Response From Host. Retry?
In this environment, program revisions become very important considerations, because the programmed operator must be reprogrammed for even minor changes in the display messages.
For example, if a terminal operator expects the message:
Enter Part Number:
as a prompt, he or she will probably be able to respond properly to an application change that produces the message:
Enter Component Number:
However, because the programmed operator is looking for a literal keyword string, subtle changes in message syntax, even as trivial as uppercase versus lowercase, can make the program take a preprogrammed error action.
There are several considerations that demand attention in designing programs that send keystrokes to the host system. In some application environments, issuing a command is as simple as typing a string and pressing Enter. Other applications involve more complex formatted screens in which data can be entered into any one of several fields. In this environment you must understand the keystrokes required to fill in the display screen.
The Tab key mnemonic (@T; see General for a full list of mnemonics) can be used to skip between fields. When sending keystrokes to a field using the Send Key (3) function, you should be aware of the field lengths and contents. If you fill the fields completely and the next attribute byte is autoskip, your cursor will then be moved to the next field. If you then issued a tab, you would skip to yet another field.
Likewise, if your keystrokes do not completely fill the field, there might be data left from prior input. You should use the Erase End of Field (EOF) command to clear this residual data.
Some applications fall into the category called collaborative. These applications provide a single end-user interface, but their processing is performed at two or more different physical locations.
An EHLLAPI application can interact with host system applications by intercepting the communication between the host system and the terminal user. The host system presentation space is the vehicle used to intercept this data. The local application can request to be notified each time the presentation space is updated or whenever an AID key is pressed by the operator.
This workstation application can then cooperate with a host system application in any of the following ways:
In this scenario, assume that you want to automate a file transfer:
An application can provide all the keystrokes for another application or can intersperse keystrokes to the target destination with those from the keyboard. Sometimes, to do this, the application must lock out other sources of keystroke input that might be destined for a target application or presentation space (using the Reserve (11) function) and the later unlock it (using the Release (12) function).
The origin of keystrokes presented to any application is determined by the design of the application. Keystrokes can originate from:
In all cases the keystrokes that are provided to the target application are indistinguishable from the ordinary operator input.
An application that acts as a filter can intercept a keystroke coming from EHLLAPI (either from the keyboard or a source application) that is targeted for another destination. The keystroke can then be:
Figure 1 provides a simplified representation of the keystroke flow and the objects within a keyboard enhancement environment.
This scenario makes use of filtering to create an enhancer application program. An enhancer application program is one that monitors the data coming in from the keyboard and changes it in some specified way. Typically, these application programs use instructions called keyboard macros, which tell them what keystrokes to look for and what changes to make. The change might involve suppressing a keystroke (so it appears to the target application as though it was never sent), replacing a keystroke with another, or replacing single keystroke with a series of keystrokes.
To do this using EHLLAPI, you might construct this scenario: