Like opening Russian nesting Matryoshka dolls, studying an AS/400 interactive job reveals many layers. In the outermost layer, a programmer sends DDS source code to the Create Display File (CRTDSPF) command. In the middle layer, display file objects hold intermediate binary structures. In the innermost layer, data management builds 5250 data streams on the fly. Display files in the middle are neither DDS source code nor 5250 data streams. You can look at display file structures with the Retrieve Display File Description (QDFRTVFD) API.
Sometimes, applications need information about display files. QDFRTVFD provides a base for this. With this API, you can build custom tools to do the following tasks:
Print screen pictures
Re-create lost DDS source code
Retrieve subfile size (SFLSIZ) and subfile page size (SFLPAG) numbers to condition subfile processing logic
Retrieve row and column positions of screen fields to condition program logic
Document how indicators 01 to 99 are used
Convert a display file to another form, such as User Interface Manager (UIM) source and Dynamic Screen Manager (DSM) API calls
Provide a Common Gateway Interface (CGI) program with a source of screen information for dynamic HTML
Build cross-reference lists of objects used by display files, including the names of message files, printer files, panel groups, documents, folders, search indexes, bookshelves, and other help records
QDFRTVFD returns the display file structures directly into a program variable, not into a user space. QDFRTVFD takes five parameters:
Receiver variable (Output)
Length of the receiver variable in a Binary(4) variable (Input)
Receiver format name in a Character(8) variable (the only format available is DSPF0100) (Input)
Qualified display file name in a Character(20) variable (Input)
Standard API error data structure (Input/Output)
This parameter list seems simple, but this simplicity is deceiving! Inside the receiver variable lurks a beastly, complex format. I had to reread the System API Reference documentation untold times, hold it up to the light, turn it sideways, and shout, Eureka! in the bathtub until I made sense of this thing. Unlike other APIs that return data in fixed offsets, QDFRTVFD returns data in offsets relative to prior offsets. To arrive at data you want, you have to add a series of offsets. Traditional RPG language, with fixed from and through I-specs and D-specs, isnt the best choice for this (although recursion and pointer arithmetic help). I rely on recursion and pointer arithmetic in this articles RPG IV program, DSP001R. You can download this program and associated command, Display a Display File (DSPDSPF), from the MC Web page at www.midrangecomputing.com/mc. Inside the RPG IV program are five subprocedures that you can copy to start building new functions based on QDFRTVFD.
You Ought to Be in Pictures
The DSPDSPF command prints a spool file. It takes five parameters:
Display file name (FILE). This is the name of a display file object you want to print. You need only the *FILE object, not the DDS source code.
Print pictures or hexadecimal dumps (TYPE). A value of *PIC (the default) prints all screen pictures from the display file, one screen per page. A value of *HEX prints all structures from the file in hexadecimal dumps.
Lines per page (LINES). The default is 66. The page overflow line number is equal to this number.
Lines per inch (LPI). The default is 6.
Characters per inch (CPI). The default is 10. The combination of LINES, LPI, and CPI lets you fine-tune the spool file size and page breaks for documentation.
Figure 1 shows some sample DDS source code from a window in my users application. It consists of input (I), output (O), and both (B) fields; a multiple-choice selection field with mnemonics; constants; and a window title.
Figure 2 shows the DSPDSPF output TYPE(*PIC) over the compiled display file object in Figure 1. You can see the constants, window title, choice mnemonic underlines, choice field slashes, and input field underlines. One picture is in *DS3 dimensions (24x80 mode), and one picture is in *DS4 dimensions (27x132 mode). The area below each
picture lists I/O field names, row/column locations, keyboard shift attributes, field lengths, and I/O buffer positions. *NOLOC appears for hidden (H) and program-to-system (P) field locations. This command makes a handy documentation tool. Try running it over one of your own display files.
Figure 3 shows the first page of DSPDSPF output TYPE(*HEX) over the compiled display file object in Figure 1. This is the raw data from the QDFRTVFD receiver variable. The left column lists offsets denoting the start of each structure. In this example, the offsets begin with 0, 10, 13, 18, 1D, etc. The dump area in the middle breaks apart each structure onto separate lines. The angle brackets (< and >) delimit the start and end of each structure. To the right, characters are printed for dump bytes greater than X40. On the far right is the name and description of each structure in the dump, as named in System API Reference: OS/400 File APls. See this book for the detailed layout of each structure.
If you begin writing a QDFRTVFD-based utility, this TYPE(*HEX) output can help you understand and locate structures in your display files. Use the structure names in the dump to find things in System API Reference. Likewise, use the book as a road map to find things in the dump. DSPDSPF does the hard part for you, resolving the offsets of structures through recursion. Your role is to choose the correct set of offsets to arrive at data you want.
Pointer arithmetic is key here. The RPG IV program DSP001R contains five procedures containing pointer arithmetic to aid navigating through offsets:
Procedure I2. The input parameter is an absolute offset into the QDFRTVFD receiver variable. The output value is the Binary(2) signed integer value at that location.
Procedure I4. The input parameter is an absolute offset into the QDFRTVFD receiver variable. The output value is the Binary(4) signed integer value at that location.
Procedure U1. The input parameter is an absolute offset into the QDFRTVFD receiver variable. The output value is the Binary(1) unsigned integer value at that location.
Procedure BIT. The input parameters are an absolute offset into the QDFRTVFD receiver variable; they are one byte of mask bits.
The output value is an indicator variable and is set to *ON if the byte value at the input location contains any mask bits.
Procedure GET. The input parameters are an absolute of set into the QDFRTVFD receiver variable; they are a length. The output value is the data substring at that location.
Figure 4 contains an example in pseudocode using some of these procedures. Suppose I wanted to get the window title text from the compiled display file object in Figure 1. Using System API Reference as a road map, Figure 4 shows the travel route to that destination.
Comments on the right denote absolute offset results in hexadecimal. Try following this trail of offsets through the dump in Figure 3. Point your finger to offsets 8, 1D, 5D, 7D, and so on. Eventually, youll arrive at offset X114. Youll see it begins the 10-byte value DISABILITY. Once you understand how these offsets add together, you can experiment with a copy of the five RPG IV procedures in DSP001R to locate more things.
The Organization of Structures
QDFRTVFD structures fall into five basic categories.
File-level structures occur at the beginning of the receiver variable. Values that youll likely use here include the number of screen sizes, the number of record formats, and a record format table. Entries in the record format table contain offsets to the start of each record section.
A set of record-level structures occurs for each record in the file. Values that youll likely use here include the number of fields and field indexing tables. Entries in the field indexing tables contain offsets to the start of each field section.
A set of field-level structures occurs for each field in each record. Values that youll likely use here include the field type.
A set of where-used structures occurs at the end of the QDFRTVFD receiver variable. There is a one-to-one correspondence between a where-used structure and a file, record, and field structure. SDA option 3 (Test display file) and the Display File Field Description (DSPFFD) command use these structures for I/O buffer positions. Workstation data management does not use them. Interestingly, display files in OS/400 libraries do not contain the where-used structures, which may explain why you cant use SDA option 3 and DSPFFD on them.
Nested sets of keyword category structures occur throughout the QDFRTVFD receiver variable for each file, record, and field structure. They contain DDS keyword values that require composite structures. You can study the RPG IV program DSP001R for examples of loops within loops within loops that scan through nests of keyword category structures.
Working Your Way Through
Even if you have no plans to plunge into display file internals, the screen pictures in DSPDSPF output TYPE(*PIC) can still help you quickly document an application. Users will like the pictures.
Programmers will also like the I/O buffer layouts. If, on the other hand, you have the patience to navigate to a new target in display file structures, the DSPDSPF output TYPE(*HEX) can help you visualize and simplify the layout of QDFRTVFD structures as you work your way through its many layers.
References and Related Materials
OS/400 File APIs (SC41-5857, CD-ROM QB3AMI02)
A DSPSIZ(*DS3 *DS4)
A R SCREEN_01
A *DS3 WINDOW(3 11 9 27)
A *DS4 WINDOW(3 11 5 76)
A WDWTITLE((*TEXT 'DISABILITY'))
A CF03
A CF12
A DIS_CUSTOM 9A P
A SHOW_AUTO 1Y 0H
A SHOW_WORK 1Y 0H
A SHOW_TERM 1Y 0H
A SHOW_DIS 1Y 0H
A 2 2'Claimant:'
A *DS4 1 6
A CLAIM_NAME 14A I 2 13
A *DS4 1 17
A 3 2'Employer:'
A *DS4 2 6
A EMPLO_NAME 14A O 3 13
A *DS4 2 17
A 4 2'Provider:'
A *DS4 3 6
A PROVD_NAME 14A B 4 13
A *DS4 3 17
A OPTIONS 2Y 0B 7 2MLTCHCFLD((*NUMROW 2))
A CHOICE(1 '>Auto NF')
A CHCCTL(1 &SHOW_AUTO)
A CHOICE(2 '>Workers')
A CHCCTL(2 &SHOW_WORK)
A CHOICE(3 'Long >Term')
A CHCCTL(3 &SHOW_TERM)
A CHOICE(4 &DIS_CUSTOM)
A CHCCTL(4 &SHOW_DIS)
A *DS4 3 46 Display file . . . . . . : QGPL/FIGURE1 Page: 1
Record . . . . . . . . . : SCREEN_01
Size identifier . . . . : *DS3
Printed on . . . . . . . : 10/13/1999 6:16:39
.........DISABILITY..........
: :
: Claimant: IIIIIIIIIIIIII :
: Employer: OOOOOOOOOOOOOO :
: Provider: BBBBBBBBBBBBBB :
: :
: :
: / Auto NF / Long Term :
: / Workers / OOOOOOOOO :
: :
:...........................:
Field Location Length Input Output
DIS_CUSTOM (*NOLOC) A(9) 1-9
SHOW_AUTO (*NOLOC) Y(1,0) 1-1 10-10
SHOW_WORK (*NOLOC) Y(1,0) 2-2 11-11
SHOW_TERM (*NOLOC) Y(1,0) 3-3 12-12
SHOW_DIS (*NOLOC) Y(1,0) 4-4 13-13
CLAIM_NAME (2,13) A(14) 5-18
EMPLO_NAME (3,13) A(14) 14-27
PROVD_NAME (4,13) A(14) 19-32 28-41
OPTIONS (7,2) Y(2,0) 33-34 42-43
Display file . . . . . . : QGPL/FIGURE1 Page: 2
Record . . . . . . . . . : SCREEN_01
Size identifier . . . . : *DS4
Printed on . . . . . . . : 10/13/1999 6:16:39
..................................DISABILITY..................................
: Claimant: IIIIIIIIIIIIII :
: Employer: OOOOOOOOOOOOOO :
: Provider: BBBBBBBBBBBBBB / Auto NF / Long Term :
: / Workers / OOOOOOOOO :
: :
:............................................................................:
Field Location Length Input Output
DIS_CUSTOM (*NOLOC) A(9) 1-9
SHOW_AUTO (*NOLOC) Y(1,0) 1-1 10-10
SHOW_WORK (*NOLOC) Y(1,0) 2-2 11-11
SHOW_TERM (*NOLOC) Y(1,0) 3-3 12-12
SHOW_DIS (*NOLOC) Y(1,0) 4-4 13-13
CLAIM_NAME (1,17) A(14) 5-18
EMPLO_NAME (2,17) A(14) 14-27
PROVD_NAME (3,17) A(14) 19-32 28-41
OPTIONS (3,46) Y(2,0) 33-34 42-43 Display file: QGPL/FIGURE1 Date: 10/13/1999 6:28:58
Page: 1
_______________________________________________ ________________
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0: <00 00 0B 2D 00 00 0B 2D 00 1D 00 01 00 00 02 00 | | QDFFBASE: Base File Section
10: 00 00 25> | |
13: <03 00 00 00 98 04 00 00 00 98> | q q | QDFFSCRA: Screen Size Table
1D: <00 00 00 | | QDFFINFO: File Header
Section
20: 40 00 00 06 50 00 00 07 96 00 00 00 50 00 01 00 | & o & |
30: 01 00 00 00 01 00 01 00 01 00 00 00 00 00 01 00 | |
40: 24> | |
Figure 1: This is sample DDS source code for a window with two border sizes.
Figure 2: This is DSPDSPF output TYPE(*PIC) over Figure 1s display file.
41: <00 00 04 40 00 00 02 0D 00 01 01 07 00 00 00 | | QDFFDPDD: Display-File-
Level Device-Dependent Secti 50: 18 00 00 00 00 00 00 00 00 00 00 00 00> | |
5D:
60: C5 C5 D5 6D F0 F1 40 00 00 00 00 00 60> |EEN_01 - |
6D:
70: F7 F5 F8 C1 F5 F1 F8 F7 C1 F6 00 00 00> |758A5187A6 |
7D: <00 00 01 | | QDFFRINF: Record Header
Section
80: 40 00 00 00 E0 00 00 00 00 00 01 02 00 00 0C 00 | |
90: 22 00 2B 00 00 00 00 00 00 00 1E> | |
9B: <00 00 00 A2 00 | s | QDFFRDPD: Display-Record-
Level Device-Dependent Sec A0: 07 00 03 00 00 00 00 20 10 00 00 00 00 00 60 00 | - |
B0: 00 00 28 FF FF 00 00 00 40 00 00 00 58> | |
BD: <00 00 00 | | QDFFXRDP: Display-Record-
Level Device-Dependent Ext C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | |
D0: 00 00 00 00 00> | |
D5: <00 01> | | QDFFCOSA: Keyword Category
Displacement String D7: <17 00 5E 00> | ; | QDFFCCOA: Keyword Category
Displacement String Entr DB: <00 02> | | QDFKMRPR: Miscellaneous
Record-Level Structure DD: <08 00 01 | | QDFKMRWP: Miscellaneous
Record-Level Keywords E0: 00 18> | |
E2:
Structure
EE:
F0: 00 03 00 0B 00 05 00 4C 00 00> | < |
FA: <09 00 01 00 1F 00 | | QDFKWDWTTL: Window Title
Structure
100: 00 00 00 00 00 00 00 1A 00 0A 00 00 00 00 00 00 | |
110: 00 00 00 00 C4 C9 E2 C1 C2 C9 D3 C9 E3 E8 00> | DISABILITY |
11F: <02 | | QDFFRCTB: Row-Column Table
120: 01 08 1B 40 00> | |
125:
130: 01 02 0C 03 01 03 0C 04 01 04 0C 07 01> | |
13D: <01 05 04 | | QDFFRCTB: Row-Column Table
140: 47 00 00> |Ü |
143:
150: 10 02 05 02 10 03 05 03 10 03 2D 00 00> | |
15D: <00 00 01 | | QDFFFITB: Field Indexing
Table
160: 40 00 01 00 09 00 00 01 60 00 01 00 01 00 00 01 | - |
170: 80 00 01 00 01 00 00 01 A0 00 01 00 01 00 00 01 |
[.radical] Ê |
180: C0 00 01 00 01 00 00 01 E0 00 01 00 09 00 00 02 |{ |
190: 10 00 01 00 0E 00 00 02 34 00 01 00 09 00 00 02 | |
1A0: 64 00 01 00 0E 00 00 02 84 00 01 00 09 00 00 02 |¥ d |
1B0: B4 00 01 00 0E 00 00 02 D8 00 01 00 02> |ü Q |
1BD: <00 20 07 | | QDFFFINF: Field Header
Section
1C0: 00 00 00> | |
1C3:
Header Table
1CF: <00 | | QDFFFDPD: Display-Field-
Level Device-Dependent Sect 1D0: 20 00 18 00 00> | |
1D5: <00 00 00 01 00 00 00 00> | | QDFFXFDP: Field-Dependent
Extension Structure 1DD: <00 20 06 | | QDFFFINF: Field Header
Section
1E0: 00 00 00> | |
1E3: <00 00 00 09 00 01 00 03 00 00 00 12> | | QDFFFNAM: Named Field
Header Table
1EF: <00 | | QDFFFDPD: Display-Field-
Level Device-Dependent Sect 1F0: 20 00 18 00 00> | |
1F5: <00 00 00 02 00 00 00 00> | | QDFFXFDP: Field-Dependent
Extension Structure 1FD: <00 20 06 | | QDFFFINF: Field Header
Section
200: 00 00 00> | |
203: <00 01 00 0A 00 01 00 03 00 00 00 12> | | QDFFFNAM: Named Field
Header Table
20F: <00 | | QDFFFDPD: Display-Field-
Level Device-Dependent Sect 210: 20 00 18 00 00> | |
215: <00 00 00 03 00 00 00 00> | | QDFFXFDP: Field-Dependent
Extension Structure
Figure 3: This is the first page of DSPDSPF output TYPE(*HEX) over Figure 1s display file.
Calculation Resulting Variable Resulting Value
I2(8) FileHeader X001D FileHeader + I4(FileHeader) RecFormatTab X005D FileHeader + I4(RecFormatTab + 12) RecordHeader X007D RecordHeader + I2(RecordHeader + 28) RecDeviceDep X009B RecordHeader + I2(RecDeviceDep + 32) CategoryDisp X00D5 RecordHeader + I2(CategoryDisp + 3) MiscStruct X00DB MiscStruct + 2 MiscKeyword X00DD MiscKeyword + I2(MiscKeyword + 3) + 5 TitleStruct X00FA I2(TitleStruct + 14) TitleLength X000A TitleStruct + 26 TitleOffset X0114 Get(TitleOffset : TitleLength) WindowTitle DISABILITY
Figure 4: This pseudocode illustrates how the programmer must navigate the offsets returned by QDFRTVFD.
LATEST COMMENTS
MC Press Online