Introduction to IBM Standard EHLLAPI, IBM Enhanced EHLLAPI and WinHLLAPI Programming

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.

EHLLAPI Overviews

Following are overviews for HLLAPI programming interfaces.

IBM Standard EHLLAPI

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

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.

WinHLLAPI and IBM Standard EHLLAPI

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 and IBM Standard EHLLAPI

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.

Languages

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.

Note:
The data structure layout for 16- and 32-bit applications are not the same (see Standard and Enhanced Interface Considerations).

EHLLAPI Call Format

The EHLLAPI entry point (hllapi) is always called with the following four parameters:

  1. EHLLAPI Function Number (input)
  2. Data Buffer (input/output)
  3. Buffer Length (input/output)
  4. Position (input); Return Code (output)

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.

Data Structures

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
    }

Memory Allocation

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 Return Codes

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.

Table 3. EHLLAPI Return Codes
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).

Compiling and Linking

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

Static Link Method

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.

Dynamic Link Method

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
  }

Multithreading

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.

Presentation Spaces

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.

IBM Enhanced 32-Bit Interface Presentation Space IDs

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);

Types of Presentation Spaces

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.

Size of Presentation Spaces

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.

Presentation Space IDs

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.

Host-Connected Presentation Space

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:

Presentation Space ID Handling

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:

  1. The method used to specify the PSID:
    1. As the calling data string parameter of a preceding call to the Connect Presentation Space (1) function
    2. As a character in the calling data string of the function being executed. Handling varies depending on whether the character is:
      • A letter A through Z
      • A blank or a null
  2. The status of the connection to the host presentation space.

The following paragraphs describe how the PSID is handled for the various combinations of these two factors.

PSID Handling for Functions Requiring Connect

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:

PSID Handling for Functions Not Requiring Connect

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:

Sharing EHLLAPI Presentation Space between Processes

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:

SUPER_WRITE

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.

WRITE_SUPER

The application requires write access and allows only supervisory applications to concurrently connect to its presentation space. This is the default value.

WRITE_WRITE

The application requires write access and allows partner or other applications with predictable behavior to share the presentation space.

WRITE_READ

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.

WRITE_NONE

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.

READ_WRITE

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.

Note:
Sharing presentation space is not available between threads in a process.
Table 4. EHLLAPI Read and Write Sharing Option Combinations
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.

Notes:
  1. The Start Keystroke Intercept (50) function is non-shareable. Only one application at a time can trap keystrokes.
  2. The Connect To Presentation Space (1) and Start Keystroke Intercept (50) functions share common subsystem functions. Successful requests by an application to share either of these functions can affect the requests of these two functions by other applications. For example, if application A successfully requests a Connect To Presentation Space (1) with Write_Read access and KEY$abcdefgh as the keyword, a request by application B to Connect To Presentation Space (1) or Start Keystroke Intercept (50) is successful only if both applications have set compatible read and write options.
Table 5. Prerequisite Functions and Associated Dependent Functions
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

Locking Presentation Space

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.

Using mouse actions to select, copy, and paste text in the Presentation Space

The following mouse actions can be used in the Presentation Space.

ASCII Mnemonics

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.

General

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 Print @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
Notes:
  1. The first @ symbol in the first table represents the escape character. The first and second @ symbol in the second table is the escape character. The @ symbol is the default escape character. You can change the value of the escape character using the ESC=c option of the Set Session Parameters (9) function.

    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 #@.

  2. If you send the mnemonic for print screen (that is, either @P or @A@T), place it at the end of the calling data string.
  3. If you send the mnemonic for device cancel (that is, @A@R), it is passed through with no error message; however, local copy is not stopped.

Get Key (51) Function

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.

Send Key (3) Function

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.

Debugging

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.

A Simple EHLLAPI Sample Program

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

Standard and Enhanced Interface Considerations

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
   ...

Host Automation Scenarios

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:

Scenario 1. A Search Function

There are four phases in a typical host system transaction:

  1. Starting the transaction
  2. Waiting for the host system to respond
  3. Analyzing the response to see if it is the expected response
  4. Extracting and using the data from the response

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:

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.

Scenario 2. Sending Keystrokes

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.

Scenario 3. Distributed Processing

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:

Scenario 4. File Transfer

In this scenario, assume that you want to automate a file transfer:

Scenario 5. Automation

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.

Scenario 6. Keystroke Filtering

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.

Figure 1. Keystroke Flow
The Keystroke Flow

Scenario 7. Keyboard Enhancement

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:

  1. Your EHLLAPI application program calls the Connect Presentation Space (1) function to connect to the presentation space whose keystrokes are to be filtered.
  2. Your EHLLAPI program next calls the Start Keystroke Intercept (50) function specifying the L option. This causes all keystrokes to be routed to the filtering application program.
  3. The filtering application program can now define a loop in which:
    1. The Get Key (51) function intercepts all keystrokes being sent to the target presentation space.
    2. The filtering application examines each keystroke and performs a keyboard macro task, such as:
      • Abbreviating program commands so that three- or four-keystroke command can be condensed into a single keystroke
      • Customizing commands so that they are easier to remember or consistent with other software packages
      • Creating boiler plates for contracts or frequently used letters
      • Rearranging the keyboard for concurrent applications that use the same keys for differing functions
      For example, the filtering application might convert a key combination such as Alt+Y into a command to move the cursor to column 35 of the second line in presentation space and write the string "XYZ Tool Corporation, Dallas, Texas".
    3. If a keystroke is rejected, your EHLLAPI program can cause a beep to be sounded, using the Post Intercept Status (52) function.
  4. After your EHLLAPI program exits the filtering loop, Stop Keystroke Intercept (53) function to end the filtering process.

1.
This means that two EHLLAPI programs will not be vying for the same Presentation Space at the same time; or that there is logic in those programs which will allow the program to wait until the PS is available; or that the applications never use the Session in a way which would lock out other applications.