Have you heard of the Xerox PARC Alto? It was the first personal computer and innovated the graphical menu bar interface that we love (or loathe) today. Now, Im sure that you know how a menu bar works: Click a menu bar item to get a pull-down list of commands apt for your current window. Click, drop, click. Although using a menu bar interface is not immediately intuitive (I had to be told to click a menu bar item the first time I faced a computer with a GUI, just as I had to be told not to step on the start pedal during my first computers boot-up), clicking menu bar items is nevertheless a pretty easy skill to master.
With V2R2, IBM added clickable menu bars and pull-down windows to the AS/400s native 5250 data stream. Its worth noting that venerable DDS, with its high-level MNUBAR and MNUBARCHC keywords for creating menu bars, neither allows immediate-selection menu bar items sans pull-down windows nor allows menu bars within windows. These capabilities do exist, however, in the 5250 data stream, and you can access them through Dynamic Screen Manager (DSM) APIs but not through DDS. The key DSM APIs that create menu bars are Write Structured Field Major (QsnWrtSFMaj) and Write Structured Field Minor (QsnWrtSFMin). To show you how these APIs work, Im going to give you a backstage tour of a DDS menu bar in action.
The DDS Curtain Raiser
Figures 1 and 2 show DDS and RPG IV source code for a small menu bar program with four choice items: Nurse, Procedure, ICD9, and Drug. Each item has an associated pull- down window. In the DDS way of doing things, pull-down records are required, so the four PULLDOWN keywords in Figure 1 denote four pull-down windows. A pushbutton field in the fourth pull-down window (Figure 1) contains three choices for drug name type: Generic, Brand, and National.
Figure 3 shows a screen shot of the pull-down menu in action. Here, the RPG IV program is stopped between the WRITE and READ statements. The user has selected the fourth menu bar item, Drug, and opened the fourth pull-down window. At this point, the user can select a pushbutton in one of three ways:
The user can position the cursor on a pushbutton item and press Enter.
The user can press a keyboard mnemonic (G, B, or N) for the drug name type.
The user can click a pushbutton item with the mouse. After the user selects a pushbutton, the BAR_NUM field contains 4, the PUSH_NUM field contains 0, and the WDW_ROW field contains either 1 or 2 or 3. The RPG IV program can determine which button is pushed by testing the value in WDW_ROW. The WDW_ROW field, defined in workstation file feedback position 382, contains the row position of the cursor, relative to the top of the current window. A row value of 1 means that Generic was pushed; 2 means Brand; and 3, National. However, the exact method of selectionEnter key, keyboard mnemonic, or mouse clickcannot be determined.
So what does the real 5250 data stream look like in this menu bar? I hauled out the Trace 5250 (TRC5250) utility to find out. TRC5250 puts a workstation into a virtual terminal (VT) session, intercepts and disassembles the 5250 data stream, and prints each component of the data stream into a spooled file. This gives you a hard-copy trace history of screen commands, orders, and input buffers generated under display files. (You can download TRC5250 from the MC Web site at www.midrangecomputing.com/mc or read about the utility in Getting Started with DSM Input Fields in the June 2000 issue of MC.)
I typed TRC5250 on a command line and pressed Enter, and a VT sign-on screen appeared. I then typed a test user profile and password and pressed Enter, and a VT session began running on my workstation. (By the way, TRC5250 prints the plain-text password from the VT sign-on screen, so be sure that you use a test user profile and password with this utility.) In the VT session, I called the Figure 2 program, selected the fourth menu bar item (Drug), selected the third drug name type (National), and pressed Attn. The Attn key ended the VT session and returned my workstation to the command line where I typed TRC5250.
I examined the spooled file generated during that little VT session. The spooled file revealed that several steps occurred between the WRITE and READ statements in the RPG IV program. The entire TRC5250 spooled file copy is too long to list in these pages, but
here is the basic sequence of events that occurred between the WRITE and READ statements:
The system sent four menu bar items and a Read Modified Data Tag (MDT) Fields command to the screen.
The system waited for input.
After Drug was selected, the system received input value X0023.
The system sent four menu bar items, a pull-down window, three pushbuttons, and a Read MDT Fields command to the screen.
The system waited for input.
After National was selected, the system received input value X0022.
Figure 4 (page 104) shows the portion of the spooled file generated when the four menu bar items, pull-down window, three pushbuttons, and a Read MDT Fields command were sent to the screen. This was also the moment when the Figure 3 snapshot was taken. The numbers in the left-hand column of Figure 4 show the 5250 commands and orders in hexadecimal. Angle brackets (< and >) delimit the start and end of each component, and the words in the right-hand column are comments, inserted by TRC5250, that describe each component.
The 5250 Cue-to-cue Sheet
A single-byte component, X15, exists three times in the left-hand column of Figure 4. These single-byte components are Write to Display Structured Field (WTDSF) orders; X15 is an escape character that tells the workstation that a single structured field immediately follows in the data stream. This single structured field is a GUI field. Structured fields contain one major subfield followed by zero or more minor subfields. Major and minor subfields create things such as buttons, boxes, sliders, and windows. The three structured fields in Figure 4 are a menu bar field to be drawn at row 1, column 2, with six minor subfields; a window field to be drawn at row 2, column 28, with no minor subfields; and a pushbutton field to be drawn at row 3, column 31, with four minor subfields. The screen row and column numbers for these fields can be found in the Set Buffer Address (SBA) orders that precede each X15 order.
The components that follow each X15 are major subfields, which have a specific format. Bytes 1 and 2 contain the length of the structured field in bytes, including the two length bytes and all minor subfields. (The maximum length of a structured field is 8,191 bytes.) Byte 3 contains the structured field class, whose value is always XD9. Byte 4 contains the structured field type, whose common types include X50 (selection field),
X51 (window field), and X53 (scrollbar field). Bytes 5 and up contain flags specific to each structured field type. For example, byte 8 in a selection field denotes the selection type as follows:
X01menu bar
X11single-choice selection field
X12multiple-choice selection field
X21single-choice selection list
X22multiple-choice selection list
X31single-choice selection field and pull-down list
X32multiple-choice selection list and pull-down list
X41pushbuttons
X51pushbuttons in pull-down menu
Byte 5, bit 1, in a window field denotes a pull-down window. When this bit value is 1, the system does not write the top border in a pull-down window, except for T characters in the top left and right corners. The T characters visually link the pull-down window to the menu bar bottom. Bytes 8 and 9 in a window field denote the numbers of rows and columns inside the window. Finally, bytes 15 and 16 in a selection field denote the numbers of choice rows and columns. By referring to this format, you can see that the three structured field lengths in Figure 4 are X0055, X0009, and X0054; these lengths include the lengths of the minor subfields that follow the major subfields.
Minor subfields have their own set of formats. Byte 1 contains the length of the minor subfield, including the length byte. Byte 2 contains the minor subfield type, whose common types include X01 (selection-field or window-border colors), X02 (selection- field choice indicators), X03 (selection-field scrollbar indicators), X09 (menu bar separator), and X10 (selection-field choice text or window-title or -footer text). Bytes 3 and up contain flags specific to each minor subfield type. For example, bytes 4 and 5 in a minor subfield for a menu bar separator contain the start and end columns for the separator line, and byte 6 in a minor subfield for selection-field choice text denotes the mnemonic offset within the choice text. Minor subfields are optional; if you omit them, the system uses defaults. You can find complete specifications for all major and minor subfields in the Display Data Streams section of 5494 Remote Control Unit Functions Reference.
DSM, Center Stage
I used the TRC5250 spooled file as a guide to help me write DSM002R, a little program of DSM calls in RPG IV that you can also download from the MC Web site atwww.midrangecomputing. com/mc. DSM002R imitates the DDS menu bar behavior that appears in Figure 3; it sends four menu bar items, a pull-down window, three pushbutton items, and a Read MDT command to the screen in one fell swoop and waits for input. In a real menu bar application, you probably wouldnt do it that way; you would probably write and read the menu bar items, wait for user input, process the input, and then write and read a pull-down window containing pushbuttons. I chose the one-fell-swoop DSM002R approach merely to expedite an explanation of structured fields.
Figure 5 shows a portion of DSM002R that invokes DSM APIs through prototyped procedure calls that build the menu bar, pull-down window, and pushbuttons. The procedure prototype names are very similar to the DSM API names, which, in turn, are very similar to 5250 data stream component names. I copied (almost verbatim) the hexadecimal major/minor subfield strings from the TRC5250 spooled file into the DSM002R calls to the QsnWrtSFMaj and QsnWrtSFMin APIs. There are eight parameters for QsnWrtSFMaj:
Major fieldChar(*)
Major field lengthBinary(4)
Field IDBinary(4)
RowBinary(4)
ColumnBinary(4)
Command buffer handleBinary(4)
Low-level handleBinary(4)
API error data structureChar(*)
In the QsnWrtSFMaj API, the major field length in the second parameter is the length of only the first parameter; it does not include the lengths of minor subfields. Moreover, the first two bytes in QsnWrtSFMajs first parameter denote the length of only the major subfield; the DSM processor adds the lengths contained in subsequent minor subfields to the stored length of the major subfield. In this way, you need only calculate the length of each individual subfield to construct a structured field operation in DSM. This API behavior is slightly different from real 5250 data stream behavior, which requires you to sum the minor subfield lengths with the major subfield length.
If a GUI field requires minor subfields, you call QsnWrtSFMin immediately after calling QsnWrtSFMaj, once for each minor subfield. There are five parameters for QsnWrtSFMin:
Minor fieldChar(*)
Minor field lengthBinary(4)
Command buffer handleBinary(4)
Low-level handleBinary(4)
API error data structureChar(*)
Getting User Feedback
Structured selection fields are input fields. To retrieve input from selection fields, you can use the Retrieve Pointer to Data in Input Buffer (QsnRtvDta) API. (For more information on QsnRtvDta, see Getting Started with DSM Input Fields, MC, June 2000.) Selection field input can be mixed with nonselection field input. There are two types of selection fields: single choice (e.g., menu bar, pushbutton, or single-choice selection field or list) and multiple choice. Input from a single-choice selection field is a 2-byte binary number that consists of the selected choice number offset by X001F. In other words, a first
choice selection returns a value of X0020, a second choice selection returns X0021, and so on.
Input from a multiple-choice selection field consists of 1 byte for each choice item. The number of bytes returned is the product of the number of choice rows and choice columns. XF1 denotes a selected choice; X00 denotes an unselected choice. Ill leave it as an exercise for you to determine whether multiple-choice selection-field input data should come in row-major form or column-major form.
Try running TRC5250 under some of your own DDS applications with GUI fields. When you get a TRC5250 spooled file, copy some of the hexadecimal major/minor subfield strings from the spooled file into a DSM program, such as DSM002R, and then tweak the hexadecimal strings to customize your GUI fields. Follow the guidelines in 5494 Remote Control Unit Functions Reference.
DSM and DDS Take a Bow DSM gives you more flexibility than DDS in several ways. Menu bars in DSM do not have to start on row 1, column 2 (as DDS menu bars do), nor do they have to have separator lines only 80 columns wide (as DDS menu bars do). With the correct row and column parameter list on the QsnWrtSFMaj API, you can place a menu bar within a window, and you can specify a short menu bar separator length in the QsnWrtSFMin API. Using DSM, you can even write multiple menu bars at once onto separate lines. (See 5494 Remote Control Unit Functions Reference to explore further possibilities with structured fields.)
However, DDS does have at least one advantage over DSM: The operating system below DDS automatically generates an alternative character-only 5250 data stream if it determines that the target workstation cannot handle Write to Display Structured Field (WTDSF) orders or other enhanced user interface capabilities, such as windows and menu bars. In DSM, the application programmer is responsible for providing an alternative code path if the target workstation cannot handle the enhanced user interface capabilities. A program can call the Query 5250 (QsnQry5250) API to test workstation capabilities before building 5250 data streams. If QsnQry5250 receiver byte 55, bit 6, is on, the workstation can accept WTDSF orders and other window and menu bar fields. DSM002R tests QsnQry5250 receiver byte 55, bit 6, at program initialization.
If you are writing for enhanced user-interface-capable workstations, QsnWrtSFMaj and QsnWrtSFMin give you the freedom to design unique GUI fields without the limitations imposed by DDS. For more information on DSM, take a look at OS/400 Dynamic Screen Manager APIs V4R4.
Gene Gaunt is a programmer and pianist who lives with his Yamaha grand piano and too many synthesizers with foot pedals in Ann Arbor, Michigan. He can be reached by email at
REFERENCES AND RELATED MATERIALS
5494 Remote Control Unit Functions Reference (SC30-3533-04, CD-ROM CO2E2001)
Getting Started with DSM Input Fields, Gene Gaunt, MC, June 2000
OS/400 Dynamic Screen Manager APIs V4R4 (SC41-5855-03, CD-ROM QB3AMG03)
A DSPSIZ(24 80 *DS3)
A R ZZ01 MNUBAR MNUBARDSP
A BAR_NUM 2Y 0B 1 2MNUBARCHC(1 ZZ01A >Nurse)
A MNUBARCHC(2 ZZ01B >Procedure)
A MNUBARCHC(3 ZZ01C >ICD9)
A MNUBARCHC(4 ZZ01D >Drug)
A R ZZ01A PULLDOWN
A R ZZ01B PULLDOWN
A R ZZ01C PULLDOWN
A R ZZ01D PULLDOWN
A PUSH_NUM 2Y 0B 1 2PSHBTNFLD(*RSTCSR (*NUMROW 3))
A PSHBTNCHC(1 >Generic)
A PSHBTNCHC(2 >Brand)
A PSHBTNCHC(3 >National)
FBARTEST CF E workstn infds( WsInfo )
D WsInfo DS
D Wdw_Row 382 382I 0
C write ZZ01
C read ZZ01
C move *on *INLR <04 11 00 28> | | Write to Display Command
<11 01 02> | | Set Buffer Address Order
<15> | | Write to Display Structured Field
Order
<00 55 D9 50 04 08 00 01 F1 F1 F7 00 00 09 01 04 | R& 117 | Define Selection Field Major
Structure
01 00 00 00> | |
<13 01 E0 00 21 00 23 00 23 22 20 20 22 20 22 00 | | Choice Presentation Display
Attributes Minor Structure
20 00 22> | |
<0B 10 08 00 E0 00 D5 A4 99 A2 85> | Nurse | Choice Text Minor Structure
[.radical]
<0F 10 08 00 E0 00 D7 99 96 83 85 84 A4 99 85> | Procedure | Choice Text Minor Structure
<0A 10 08 00 E0 00 C9 C3 C4 F9> | ICD9 | Choice Text Minor Structure
<0A 10 88 80 E0 00 C4 99 A4 87> | h Drug | Choice Text Minor Structure
<08 09 80 01 50 3A 3A 00> | & | Menu Bar Separator Minor Structure
<11 02 1C> | | Set Buffer Address Order
<15> | | Write to Display Structured Field
Order
<00 09 D9 51 40 00 00 03 0B> | R | Create Window Major Structure
<11 03 1F> | | Set Buffer Address Order
Figure 1: Each choice item in this menu bar program has an associated pull- down window.
Figure 2: The RPG needed to drive the menu bar is simple.
Figure 3: This is an example of the Figure 1 program in action; the program is stopped between the WRITE and READ statements.
<15> | | Write to Display Structured Field
[.radical]
Order
<00 54 D9 50 06 06 80 51 21 31 32 00 00 0A 03 01 | R& | Define Selection Field Major
Structure 01 00 00 00> | |
<13 01 E0 00 21 00 22 00 3B 22 20 20 23 20 3A 24 | | Choice Presentation Display
Attributes Minor Structure 20 20 3A> | |
<0F 10 0C 18 E0 00 F1 C7 85 95 85 99 89 83 40> | 1Generic | Choice Text Minor Structure
<0F 10 0C 18 E0 01 F1 40 C2 99 81 95 84 40 40> | 1 Brand | Choice Text Minor Structure
<0F 10 0C 18 E0 00 F1 D5 81 A3 89 96 95 81 93> | 1National | Choice Text Minor Structure
<13 03 20> | | Insert Cursor Order
<04 52 00 00> | | Read MDT Fields Command
Figure 4: This portion of the spooled file is generated when the four menu bar items, pull-down window, three pushbuttons, and a Read MDT Fields command are sent to the screen.
* create command buffer
C callp CrtCmdBuf( 6300 : 6300 : 0 : CmdBuf : 0 )
* create input buffer
C callp CrtInpBuf( 6300 : 6300 : 0 : InpBuf : 0 )
* clear screen
C callp ClrScr( '3' : CmdBuf : 0 : 0 )
* write to display
C callp WTD( X'00' : X'28' : CmdBuf : 0 : 0 )
* draw menu bar at row 1, column 2
C callp WrtSFMaj(
C X'0014D95004080001F1F1F7000009010401000000'
C : 20 : 0 : 1 : 2 : CmdBuf : 0 : 0 )
* define menu bar colors
C callp WrtSFMin(
C X'1301E000210023002322202022202200200022'
C : 19 : CmdBuf : 0 : 0 )
* draw menu bar choices
C callp WrtSFMin( X'0B100800E000' + 'Nurse'
C : 11 : CmdBuf : 0 : 0 )
C callp WrtSFMin( X'0F100800E000' + 'Procedure'
C : 15 : CmdBuf : 0 : 0 )
C callp WrtSFMin( X'0A100800E000' + 'ICD9'
C : 10 : CmdBuf : 0 : 0 )
C callp WrtSFMin( X'0A108800E000' + 'Drug'
C : 10 : CmdBuf : 0 : 0 )
* draw menu bar separator
C callp WrtSFMin( X'08098001503A3A00'
C : 8 : CmdBuf : 0 : 0 )
* draw pull-down window at row 2, column 28
C callp WrtSFMaj( X'0009D951400000030B'
C : 9 : 0 : 2 : 28 : CmdBuf : 0 : 0 )
* draw push buttons at row 3, column 31
C callp WrtSFMaj(
C X'0014D9500606805121313200000A030101000000'
C : 20 : 0 : 3 : 31 : CmdBuf : 0 : 0 )
* draw push button choices
C callp WrtSFMin( X'0F100C18E000F1' + 'Generic '
C : 15 : CmdBuf : 0 : 0 )
C callp WrtSFMin( X'0F100C18E001F1' + ' Brand '
C : 15 : CmdBuf : 0 : 0 )
C callp WrtSFMin( X'0F100C18E000F1' + 'National'
C : 15 : CmdBuf : 0 : 0 )
* insert cursor at row 3, column 32
C callp InsCsr( 0 : 3 : 32 : CmdBuf : 0 : 0 )
* read modified input fields
C callp ReadMDT( X'00' : X'00' :
C FldCnt : InpBuf : CmdBuf : 0 : 0 )
Figure 5: This portion of DSM002R invokes DSM APIs through prototyped procedure calls that build the menu bar, pull-down window, and pushbuttons.
LATEST COMMENTS
MC Press Online