Chances are youll need variable-length input fields in the future. More and more self- defining files are emerging from e-commerce, and editing these files may require you to use late-bound input field lengths. Perhaps youll need a user response on a startup screen to determine a field length on a subsequent screen. How do you work this dynamic field data into AS/400 green-screen applications? With a screen tool such as display file DDS, you face an impasse because display file DDS fields cant be variable-length.
DDS is a powerful tool, but it doesnt support the full potential of green-screens. Variable-length input fields are possible on AS/400 displays, if you (gasp!) discard DDS for something else. In this article, Ill show you the components necessary to develop variable-length input fields with Dynamic Screen Manager (DSM) APIs.
Interactive jobs on the AS/400 generate 5250 data streams. The 5250 data streams are binary strings of commands, orders, and structured major/minor fields that control workstation behavior. Ordinarily, you let DDS runtime support generate these strings, but you can also build them on the fly with DSM APIs. Assembling these data stream pieces in the correct order is key. Because it helps to see the components of 5250 data streams in context with one another, I wrote TRC5250, a utility that traces and disassembles a jobs actual 5250 data streams into a spool file. By way of background to DSM input fields, the TRC5250 utility forays into the arcane world of virtual terminal APIs (VTAPIs).
VTAPIs convey display emulation in a client/server environment. VTAPIs interact with a user-written server program on one AS/400 through a data queue and 5250 data streams. VTAPIs link only to the server program; a user-written client program can run on the same AS/400, a different AS/400, or another machine type that can interpret 5250. Below the client and server programs, OS/400 manages the connection between VTAPIs and a virtual terminal, a logical device not associated with hardware.
Figure 1 (page 103) shows the data flow configuration in TRC5250. Here, client and server run on the same AS/400 and, in fact, in the same program. TRC5250 creates a data queue, links the data queue to a display file, opens the display file, and sends the data
queue name to the Open Virtual Terminal Path (QTVOPNVT) API, which starts a new job running on the same AS/400. This new job is interactive but not tied to any physical workstation; its linked to VTAPIs and to the data queue. The new job name is usually something like QPADEVnnnn.
When the QPADEVnnnn job sends output to the screen (which is really a virtual screen), OS/400 intercepts the output and sends an entry prefixed with *VRTTRM to the data queue. Meanwhile, TRC5250 waits for a data queue entry arrival. When a *VRTTRM entry arrives, TRC5250 calls the Read from Virtual Terminal (QTVRDVT) API, receives the 5250 data stream built by the QPADEVnnnn job, disassembles it, prints the disassembly into a spool file, and then passes the data stream into the TRC5250 display file. The user sees this screen and types a response, and OS/400 sends an entry prefixed with *DSPF to the data queue while TRC5250 waits for a data queue entry arrival. When a *DSPF entry arrives, TRC5250 reads from the display file, gets the input buffer, prints the buffer into the spool file, and sends the buffer to the Write to Virtual Terminal (QTVWRTVT) API, which forwards the buffer into the QPADEVnnnn job. Finally, the QPADEVnnnn job wakes up and continues running like an interactive job after receiving screen input. Eventually, this job sends more output to the screen, and the whole cycle repeats.
You can download TRC5250 at www. midrangecomputing.com/mc. It contains three pieces to compile: command TRC5250, display file TRC5250D, and RPG IV program TRC5250R. To start the utility, type TRC5250 on a command line and press the Enter key. A welcome screen like the one shown in Figure 2 will appear and say that a virtual sign-on screen will appear next. Here, you can select a device emulation type 1 through 15. Type 1, the default, emulates a 24 x 80 monochrome terminal; type 15 emulates a 27 x 132 color terminal. Press the Enter key, and a QPADEVnnnn sign-on screen will appear. Type a user name and password and press the Enter key, and a QPADEVnnnn job will begin running. Your current job will emulate the QPADEVnnnn job, disassembling it and tracing it into a spool file. Try running several screen programs under this emulation.
To end the emulation, press the Attn key. (The Attn key is mapped to the Esc key on some PC keyboards.) The Attn key ends the QPADEVnnnn job and returns you to the command line where you typed TRC5250. Be aware that this Attn key exit function overrides any Attn key programming in the QPADEVnnnn job. Also be aware that TRC5250 prints all input buffers, including the user ID and plain-text password from the sign-on screen; for security, you should create a test user profile and password for the QPADEVnnnn sign-on screen.
A TRC5250 Example
Figure 3 shows a little RPG IV program and associated DDS file with two I/O fields named ITEM_NO and ITEM_COST. I compiled both of these source members into a program and display file, started TRC5250, received a QPADEVnnnn sign-on screen, signed on, called the Figure 3 program, typed SOUP in item number and typed 98 in item cost, pressed the Enter key, and then pressed the Attn key to exit TRC5250. Then, I examined the trace spool file generated during the QPADEVnnnn job.
The spool file was longIll spare you the bloody detailsbut Figure 4 shows the pertinent portion generated while the Figure 3 program ran. The spool file timestamped each output and input buffer. The left section of Figure 4 shows the data stream components in hexadecimal; the center section shows EBCDIC characters greater than X40; and the right section names each 5250 command, order, and structured
Compare Figure 3 with Figure 4. Can you spot any patterns? Using the component names in the right column of Figure 4, I looked up descriptions of the components in
chapter 15 of IBMs Functions Reference, Display Data Streams. Here are some notes about the components in Figure 4:
The Clear Unit command (X0440) prepares the workstation for a new screen.
The Write to Display command (X04110018) unlocks the keyboard and blinks the cursor.
The start of header (SOH) order (X010700000019000000) sets the error message line to 25.
The set buffer address (SBA) order (X110702) positions screen writing to row 7, column 2.
The start of field (SF) order (X1D402024000A) creates a 10-byte alphanumeric input field.
The Read MDT Fields command (X04520000) waits until an AID key is pressed and then reads only fields that were changed (i.e., Modified Data Tag [MDT] fields).
Input data X090CF1 means that the cursor is on row 9, column 12, when the Enter key is pressed.
Input data X11070A... means that SOUP comes from the input field at row 7, column
Input data X11090A... means that 98 comes from the input field at row 9, column 10.
An Equivalent DSM Program
Using the component names in the right column of Figure 4, I searched for analogous DSM APIs in OS/400 Dynamic Screen Manager APIs V4R4. Fortunately, the names of DSM APIs are very similar to 5250 data stream component names, and I found a collection of DSM APIs close to the set of component names in Figure 4. I compiled them into program DSM001R, which you can also download at www. midrangecomputing.com/mc. DSM001R and the program in Figure 3 produce identical appearance and behavior, but one is pure DSM and the other is DDS.
DSM001R uses the following set of APIs:
QsnCrtCmdBuf creates an output buffer.
QsnCrtInpBuf creates an input buffer.
QsnClrScr adds a Clear Unit command to the output buffer.
QsnWTD adds a Write to Display command to the output buffer.
QsnWrtDta adds an SBA order and data to the output buffer.
QsnSetFld adds an SF order to the output buffer.
QsnReadMDT writes the output buffer and executes a Read MDT Fields command.
QsnRtvDta retrieves a pointer to data in the input buffer.
QsnRtvDtaLen retrieves the length of data in the input buffer.
The key API that shapes input fields is QsnSetFld. This APIs first parameter is Field ID, a unique number the API caller makes up. (DSM001R doles out field IDs from a simple counter, starting with 1.) The other parameters are Row/column address, Length, Display attribute, Field format word, and Field control words. After you create an input field with QsnSetFld, you can modify its color and data by passing its field ID to other APIs.
Did you notice that the Figure 3 program redisplays ITEM_NO in reverse image by setting on indicator 51 in conjunction with the PUTOVR, OVRATR, and OVRDTA keywords? The DSM001R program uses field IDs for the same effect.
Read MDT Fields
With traditional DDS display files, a programmer or precompiler usually codes from-and- through specifications on input records, but DSM is more complicated than that. After executing a Read MDT Fields command, a program receives input field data in variable positions. Figure 5 shows this format. Starting in input byte four, the X11 component delimits the start of field data, and row/column addresses following each X11 identify fields. This combination repeats for each modified input field, but fields not modified by the user do not appear in the input.
A program parsing this type of input must scan for X11 components and then map subsequent row/column addresses to program variables. For this reason, DSM001R builds parallel arrays of row/column field addresses and dynamic heap storage pointers. When DSM001R finds an X11 component in the input buffer, it extracts the subsequent row/column address into a search argument for a row/column array lookup operation and then copies subsequent input field data into the corresponding dynamic heap storage.
You can create variable-length input fields in DSM001R by tweaking the entries in an array named VarLen before calling the QsnSetFld API. You can also increase the value in a program constant named Max to make room for more input fields. Thus, DSM001R gives you a template that you can cut, paste, and customize into a new dynamic screen application.
Begin with a Single Step
The majority of AS/400 screens use the basic component set in Figure 4, yet many more exotic components exist. For example, GUI fields, which use structured major/minor fields in the 5250 data stream, can get complex. But when you begin programming with 5250 data streams, ignore that exotic stuff for a moment and stick with the core component set in Figure 4. Everything else is ornamental.
I know the information in both the Functions Reference and the OS/400 Dynamic Screen Manager APIs V4R4 manuals can overwhelm a first-time reader. How does a newcomer distinguish the common and important stuff from the arcane stuff? Try running TRC5250 under one of your existing screen applications where you already know the DDS. By studying the TRC5250 output and looking for recurring patterns, you can begin to understand how 5250 input fields work, and you can prepare to tackle the next challenge of variable-length input fields that may arise.
References and Related Materials
Functions Reference (SC30-3533-04, CD-ROM CO2E2001)
OS/400 Dynamic Screen Manager APIs V4R4 (SC41-5855-03, CD-ROM QB3AMG03)
DSPnn Job TRC5250Q Data Queue
QPADEVnnnn Job Physical Workstation
Virtual Terminal APIs
TRC5250D Display File
Figure 1: In TRC5250, client and server run in the same program.
Figure 2: When you begin TRC5250, this welcome screen allows you to select your emulation type before signing on.
A R SCREEN1 BLINK PUTOVR
A 7 3'ITEM:'
A ITEM_NO 10A B 7 10
A 51 DSPATR(RI PC) OVRATR
A 9 3'COST:'
A ITEM_COST 7Y 0B 9 10EDTCDE(4) OVRATR
A 23 2'ENTER=ok' COLOR(BLU)
FTest CF E workstn
C movel(p) 'HAMMER' Item_No
C exfmt Screen1
C move *on *IN51
C exfmt Screen1
C move *on *INLR ----------------------------------------------------|----------------|-
OUTPUT | | 12/31/1999 11:30:44.752
<04 40> | | Clear Unit Command
<04 11 00 18> | | Write to Display Command
<01 07 00 00 00 19 00 00 00> | | Start of Header Order
<11 07 02> | | Set Buffer Address Order
<20 C9 E3 C5 D4 7A 20> | ITEM: | Data
<11 07 09> | | Set Buffer Address Order
<1D 40 20 24 00 0A> | | Start of Field Order
<11 09 02> | | Set Buffer Address Order
<20 C3 D6 E2 E3 7A 20> | COST: | Data
<11 09 09> | | Set Buffer Address Order
<1D 43 00 24 00 07> | | Start of Field Order
<40 40 40 40 40 40 40> | | Data
<11 17 01> | | Set Buffer Address Order
<3A C5 D5 E3 C5 D9 7E 96 92 20> | ENTER=ok | Data
<04 52 00 00> | | Read MDT Fields Command
INPUT | | 12/31/1999 11:30:49.187
<09 0C F1 11 07 0A E2 D6 E4 D7 11 09 0A F9 F8> | 1 SOUP 98 |----------------------------------------------------|----------------|------------------------------
Figure 3: Here are DDS and RPG for a little screen program.
Figure 4: Running the program in Figure 3 under TRC5250 generates this output.
Cursor Row/Column 2 Bytes AID Code 1 Byte Field Row/ Column 2 Bytes Field Row/ Column 2 Bytes
Field Data X'11'
Figure 5: Input field data comes in variable positions after a READ MDT FIELDS command is executed.