On RPG-LE Development

Postings on RPG-LE and i5/OS

Archive for the ‘RPG-Free Subfile programming’ Category

Error Message Subfile

leave a comment »

Interactive programs present data to the user in an organized manner. They have the additional responsibility to inform the user about the state of the data being accessed or about an event which took place when manipulating the data. RPG developers who are designing interactive applications can use Error Message Subfiles to present error, warning, and informational messages in a standard manner consistent with the rest of the operating system’s screens.

 
A**************************************************************** A* ERROR MESSAGE SUBFILE RECORD A**************************************************************** A R ERRMSGSF SFL A SFLMSGRCD(24) A EMSMSGKEY SFLMSGKEY A EMSPGMQUE SFLPGMQ A* A**************************************************************** A* ERROR MESSAGE SUBFILE CONTROL RECORD DEFINITION A***************************************************************** A R ERRMSGCT SFLCTL(ERRMSGSF) A 34 PROTECT A N01 OVERLAY A 48 CSRLOC(EMSLINNBR EMSPOSNBR) A SFLDSP A SFLDSPCTL A SFLINZ A SFLSIZ(0002) A SFLPAG(0001) A 36 SFLEND A EMSPGMQUE SFLPGMQ A EMSLINNBR 3 0H A EMSPOSNBR 3 0H A**************************************************************** A***** END OF SOURCE **************************************** A****************************************************************

In *INZSR, information about the message files are defined in variables used as parameters for sub-procedure calls which send the messages to the error message subfile.

 
//************************************************** // Establish value for Error Message Control file's // SFLPGMQ keyword field, Message file and library. //************************************************** EmsPgmQue = '*'; EMS_MSGFILE = 'YOURMSGF'; EMS_MSGLIB = 'YOURMSGFLIB'; EMS_MSGTEXT = *BLANKS;

Sending a message using a service program sub-procedure call.

 
//*********************************************************************** //* * //* Send a program-defined message to the error message subfile * //* * //*********************************************************************** begsr sendPgmMsg; select; when EMS_FUNCTION = @CLEAR; ClearMsgQue(); when EMS_FUNCTION = @SEND; PutMsgOnQue( EMS_MSGFILE : EMS_MSGLIB : EMS_MSGID : CompMsgTyp: EMS_MSGTEXT : CurrMsgStk : CurrMsgQue); ENDSL; endsr;

Clearing the error message subfile is typically done just after the screen is displayed.

 
//Clear the Error Message Subfile EMS_FUNCTION = @CLEAR; exsr sendPgmMsg;

During subfile load processing or while processing input values for validity, error messages are placed into the error message subfile. Each call of the sub-procedure adds another message which the user can scroll through to view. (The constant @MKT0002 is used to hold a message id assigned to the message when it was added to the message file which acts as the message repository for all applications.)

 
EMS_FUNCTION = @SEND; EMS_MSGID = @MKT0002; exsr sendPgmMsg;

Subfile Relative Record Number, Page Size and Page Positioning

with 2 comments

Controlling subfiles

There are several areas of programming which make up a successful subfile program. There are DDS-specifications which define certain keywords to govern page initialization and positioning. The RPG program’s WORKSTN F-SPECS define the subfile’s relative record number field.

In the program logic, there are certain principles that govern the type of logic required to ensure the values of the control fields work to produce a properly functioning subfile.

These control fields are used to control the active subfile relative record number, governing the number of records written so that the number matches the size of the subfile page and to control page positioning after the subfile has been loaded.

Naming Convention

Since the fields, there are four, are delegated to a single subfile, they have been named to help identify the subfile to which they belong. The naming convention begin with “Sn” where “S” denotes a subfile while “n” denotes the number. For the first subfile in the application, the number will 1, the second will be 2. The field name assigned to control subfile relative record number of the first subfile in the application is S1RRN. The field to control the RRN of the second subfile, if it exists, will be S2RRN. The same idea holds for the control records. For example, the variable assigned to the SFLRCDNBR keyword for subfile 1 will begin with “C1″ as in C1RCDNBR.

Summary of Control Field Use

Subfile Page (S1PAGE )
S1PAGE is used by the program to determine if a full page has been loaded.

The S1PAGE field values are static and are initialized during program initialization with the value in the subfile’s SFLPAG(nnnn) keyword in the DDS.

D S1PAGE S 5 0

Subfile Relative Record Number (S1RRN)
S1RRN is defined on the F-Spec for the WORKSTN file to assign the file’s RRN field. It should not be used for anything other than for that purpose.

This field is initialized with zero and are referenced by the WORKSTN file using FILE(SF01SF:S1RRN). When the subfile is cleared, S1RRN should be reset to zero. During subfile loading, S1RRN is to be incremented by one for each subfile record written.

F************************************************************************** F* Display File FDSPF01D1 CF E WORKSTN INFDS(DSPFDS) F SFILE(SF01SF:S1RRN) F**************************************************************************

Subfile Line (S1LINENBR )
S1LINENBR is used to control the load-loop.

The S1LINENBR fields are also initialized differently. Subfile page loading is performed with a do-loop at which time S1LINENBR is zero. The do-loop is ‘dou S1LINENBR = S1PAGE ‘. During subfile loading, S1LINENBR is incremented by one for each record written.

D S1LINE S 5 0

Subfile Number (C1RCDNBR)
C1RCDNBR is used to control page positioning after loading. It may also be used to allow the user to control page positioning by moving the value supplied by a control record input field into C1RCDNBR.

C1RCDNBR is defined using the DDS keyword SFLRCDNBR seen on the subfile’s control record. It is used to govern which page is seen after loads.

A C1RCDNBR 4S 0H SFLRCDNBR

After the full page has been loaded with data, it should be the next page to be displayed. To automatically position to the freshly loaded page or to any page, specify that the page to be displayed is the page containing the record whose relative record number is in this field. The default behavior is governed by moving S1RRN into S1RCDNBR after each load.

//************************************************** // INITIALIZE SFLRCDNBR TO POSITION THE SUBFILE TO // THE FIRST PAGE OR ANY OTHER PAGE REQUIRED. //************************************************** if S1RRN > *ZERO; C1RCDNBR = S1RRN; endif;

Creating a /copy member for system-wide use

To take advantage of these control fields for new subfile programming, in addition to other fields related to the programming logic-pattern established to use these fields, the following /copy member is created to be copied into all subfile programs so that they are included during the program’s compile phase. Since it’s a /copy-file containing subfile related control fields and associated constants, create an RPGLE source member named CPYSFCONST and place the code below into it.

A Future post will show how the fields defined by this /copy member are used in an RPG-Free subfile program architecture which establishes a programming pattern which is easy to maintain. It does this by breaking out areas of responsibility using subroutines. In the meantime, refer to this post to see an RPG-IV version of this.

D/EJECT D************************************************************************** D* RECOMMENDED INDICATOR USAGE FOR DISPLAY FILES * D************************************************************************** D* * D* INDICATOR DESCRIPTION * D* ----------- ------------------------------------------------------ * D* 01 TURNS OFF THE OVERLAY WHEN WRITING MSGCT * D* 10 SUBFILE RECORD DSPATR(HI) * D* 20 SUBFILE FOLD/UNFOLD MODE * D* 21 SUBFILE 1 END AND ENABLE ROLLUP KEY * D* 22 SUBFILE 2 END AND ENABLE ROLLUP KEY * D* 23 SUBFILE 3 END AND ENABLE ROLLUP KEY * D* 24 SUBFILE 4 END AND ENABLE ROLLUP KEY * D* 25 SUBFILE 5 END AND ENABLE ROLLUP KEY * D* 26 SUBFILE 6 END AND ENABLE ROLLUP KEY * D* 30 CLEAR KEY PRESSED * D* 31 HOME KEY PRESSED * D* 32 WINDOW ERROR SUBFILE END * D* 33 PROTECT FIELD MODE * D* 34 PROTECT SCREEN MODE * D* 35 ROLLUP KEY PRESSED * D* 36 ROLLDOWN KEY PRESSED * D* 37 ERROR SUBFILE DISPLAY CONTROL RECORD * D* 38 ERROR SUBFILE DISPLAY * D* 39 ERROR SUBFILE CLEAR * D* 40 RECORD NOT FOUND * D* 41 FILE EXCEPTION/DIRECT CALL ERROR * D* 42 OUT OF LIMIT FOR SETLL/SETGT * D* 44 SUBFILE DISPLAY * D* 45 SUBFILE DISPLAY CONTROL * D* 46 SUBFILE CLEAR * D* 47 SUBFILE END AND ENABLE ROLLUP KEY * D* 48 HELP ENABLED * D* 49 SUBFILE NEXT CHANGE * D* 70 EXAMPLE ERROR INDICATOR * D* LR LAST RECORD (LOGICAL END OF PROGRAM) * D************************************************************************** D/EJECT D************************************************************************** D* Screen File Information Data Structure with constants used for D* screen navigation control D* D************************************************************************** D* DISPLAY FILE INFORMATION DATA STRUCTURE * D************************************************************************** D DSPFDS DS D DSP_SDSPFF 1 102 Display File Format D DSP_SCREENID 261 268 Screen ID D DSP_WSID 273 282 Workstation ID D* D DSP_DSPFLAG 367 368 DISPLAY FLAG D DSP_FUNCTKEY 369 369 Function Key Value D DSP_CURSOR 370 371B 0 Cursor Row and Col D DSP_SFPAGERRN 378 379B 0 Subfile Page RRN D* D DSP_FILENAME *FILE File Name D DSP_STATUS *STATUS Status code D DSP_OPCODE *OPCODE Last opcode D DSP_ROUTINE *ROUTINE RPG Routine D DSP_RECFORMAT *RECORD Record format D* D CURSORROWCOL DS D CURSOR_ROW 1 3S 0 D CURSOR_COL 1 3S 0 D************************************************************************** D/EJECT D************************************************************************** D* Function Key Constants - Attention Indicator Byte (AID). D* Function Keys F1 Through F24. These are interrogated by subr s1CmdKeys, D* to determine the appropriate program behavior. D************************************************************************** D @FK01 C CONST(X'31') D @FK02 C CONST(X'32') D @FK03 C CONST(X'33') D @FK04 C CONST(X'34') D @FK05 C CONST(X'35') D @FK06 C CONST(X'36') D @FK07 C CONST(X'37') D @FK08 C CONST(X'38') D @FK09 C CONST(X'39') D @FK10 C CONST(X'3A') D @FK11 C CONST(X'3B') D @FK12 C CONST(X'3C') D @FK13 C CONST(X'B1') D @FK14 C CONST(X'B2') D @FK15 C CONST(X'B3') D @FK16 C CONST(X'B4') D @FK17 C CONST(X'B5') D @FK18 C CONST(X'B6') D @FK19 C CONST(X'B7') D @FK20 C CONST(X'B8') D @FK21 C CONST(X'B9') D @FK22 C CONST(X'BA') D @FK23 C CONST(X'BB') D @FK24 C CONST(X'BC') * * Clear, Enter, Help, Roll Up/Down, Print D @FK_CLEAR C CONST(X'BD') D @FK_ENTER C CONST(X'F1') D @FK_HELP C CONST(X'F3') D @FK_ROLLDOWN C CONST(X'F4') D @FK_PAGEUP C CONST(X'F4') D @FK_ROLLUP C CONST(X'F5') D @FK_PAGEDOWN C CONST(X'F5') D @FK_PRINT C CONST(X'F6') D @FK_HOME C CONST(X'F8') D @NULL C CONST(X'00') D************************************************************************** D* Screen Title D************************************************************************** D @TITLE C CONST( D 'Central United Insurance Company') D/EJECT D******************************************************************** D* To control which screen is to be presented, move one of the D* generic screen names into SCREEN, which is interrogated by D* various screen controllers (subr screenController, s1CmdKeys, etc.) D* to determine which screen is to be presented to the user. D* D* In the event that screen navigation may not be incremental, ie, D* the program design does not ensure navigation will proceed from D* screen 1 through 9 and back down again, but instead may bounce D* from one to another, use PREVSCREEN to store the current screen D* before proceeding to the next screen. When the user presses F12 D* to return to the previous screen, move PREVSCREEN into SCREEN. D******************************************************************** D SCREEN S 8A SCREEN TO DISPLAY D PREVSCREEN S 8A PREVIOUS SCREEN D @PROMPT01 C CONST('PROMPT01') D @PROMPT02 C CONST('PROMPT02') D @PROMPT03 C CONST('PROMPT03') D @PROMPT04 C CONST('PROMPT04') D @PROMPT05 C CONST('PROMPT05') D @SCREEN01 C CONST('SCREEN01') D @SCREEN02 C CONST('SCREEN02') D @SCREEN03 C CONST('SCREEN03') D @SCREEN04 C CONST('SCREEN04') D @SCREEN05 C CONST('SCREEN05') D @SCREEN06 C CONST('SCREEN06') D @SCREEN07 C CONST('SCREEN07') D @SCREEN08 C CONST('SCREEN08') D @SCREEN09 C CONST('SCREEN09') D******************************************************************** D* Once within a screen's controlling logic, certain keyboard driven D* events are conveyed by constants used to determine screen behavior. D* When the user presses "Page up", "Page Down", etc, the related D* value is then moved into NEW_FUNCTION which is interrogated by D* the various screen controllers (subrs S1Init, S1Control, etc) D* to determine the next screen related action. D******************************************************************** D NEW_FUNCTION S 8A FUNCTION DIRECTIVES D @ENDPGM C CONST('ENDPGM ') D @ROLLUP C CONST('ROLLUP ') D @ROLLDOWN C CONST('ROLLDOWN') D @PREVPAGE C CONST('PREVPAGE') D @NEXTPAGE C CONST('NEXTPAGE') D @NOPAGE C CONST('NOPAGE ') D @READNEXT C CONST('READNEXT') D @CANCEL C CONST('CANCEL ') D************************************************************************** D* General Purpose Constants D************************************************************************** D @YES C CONST('Y') D @NO C CONST('N') D @MAYBE C CONST('M') D @NORECORDS C CONST('NORECORDS') D******************************************************************** D* FILE_STATE is used to govern read-oriented loops. To use, D* move *BLANKS to FILE_STATE then start read loop using D* dou FILE_STATE = @EOF. Read the file, test for EOF and when true D* move @EOF to FILE_STATE. D******************************************************************** D FILE_STATE S 8A D LOOP_CONTROL S 8A INZ(' ') D @EOF C CONST('EOF ') D @STOP C CONST('STOP ') D******************************************************************** D* DATASTATUS and FILTERSTATUS are used together to determine the D* outcome of Filter Values entered on the subfile control-record. D* D* In the event no data was found for a subfile load when no filter-by D* values where entered on the control record, DATASTATUS will contain D* @NOTFOUND D* D* In the event no data was found for a subfile load when filter-by D* values where entered on the control record, DATASTATUS will contain D* @NOTFOUND while FILTERSTATUS will contain @FILTERED. D* D* With these, the proper message to be displayed in the error message D* subfile can be determined. For example, normal page loading is D* driven by initial subfile load followed by "Page Down" directives. D* If no data is found or at EOF, DATASTATUS should be populated with D* @NORECORDS while FILTERSTATUS is populated with @NOTFILTERED. As D* a result, a simple "No data found" type of message would appear D* in the error message subfile. D* D* When filtering subfile loads using input fields on the control D* record, if no data is found or at EOF, DATASTATUS should be populated D* with @NOTFOUND while FILTERSTATUS is populated with @FILTERED. As D* a result, the message "No data found for supplied data ?data?" D* might be required. D******************************************************************** D DATASTATUS S 8A D @FOUND C CONST('FOUND ') D @NOTFOUND C CONST('NOTFOUND') D FILTERSTATUS S 8A D @FILTERED C CONST('FILTERED') D @NOTFILTERED C CONST('UNFILTRD') D/EJECT D******************************************************************** D* MISCELLANEOUS D* ACTION holds the function-key mneumonic and is populated by D* s1CommandKeys, s2CommandKeys, s3CommandKeys, etc. D* ERROR holds @YES/@NO D******************************************************************** D ACTION S 8A D ERROR S 3A D******************************************************************** D* Error Message Subfile control and parm fields. D* EMS_FUNCTION hold @CLEAR or @SEND for error message subfile mgmt. D* EMS_MSGFILE and EMS_MSGLIB are initialized in the program's *INZSR D* EMS_MSGID value is moved to this field. D* D* To clear the message file: D* EMS_FUNCTION = @CLEAR; D* exsr sendPgmMsg; D* D* To send a message: D* EMS_FUNCTION = @SEND; D* EMS_MSGID = @MKT0002; D* exsr sendPgmMsg; D* D******************************************************************** D EMS_FUNCTION S 8A D EMS_MSGFILE S 10A D EMS_MSGLIB S 10A D EMS_MSGID S 7A D EMS_MSGTEXT S 2000A D @CLEAR C CONST('CLEAR ') D @SEND C CONST('SEND ') D******************************************************************** D* SCREEN CONTROL FIELDS D******************************************************************** D ERROR_STATUS S 8A ERROR STATUS D SCREEN01_INIT S 1A D SCREEN02_INIT S 1A D SCREEN03_INIT S 1A D SCREEN04_INIT S 1A D SCREEN05_INIT S 1A D SCREEN06_INIT S 1A D SCREEN07_INIT S 1A D SCREEN08_INIT S 1A D SCREEN09_INIT S 1A D******************************************************************** D* Subfile Options and Command Key Legends D******************************************************************** D*S1OPTIONS S 77A D*S1CKLEGND S 79A D*S2OPTIONS S 77A D*S2CKLEGND S 79A D*S3OPTIONS S 77A D*S3CKLEGND S 79A D*S4OPTIONS S 77A D*S4CKLEGND S 79A D*S5OPTIONS S 77A D*S5CKLEGND S 79A D*S6OPTIONS S 77A D*S6CKLEGND S 79A D*S7OPTIONS S 77A D*S7CKLEGND S 79A D*S8OPTIONS S 77A D*S8CKLEGND S 79A D*S9OPTIONS S 77A D*S9CKLEGND S 79A D******************************************************************** D* Subfile Relative Record Number and Page Size Fields D* D* The S1PAGE type field values are static and are initialized D* during progam initialization with the value in the subfile's D* SFLPAG(nnnn) keyword in the DDS. D* D* The S1RRN fields are to be initialized with zero and are D* referenced by the WORKSTN file using SFILE(SF01SF:S1RRN). When D* the subfile is cleared, S1RRN should be reset to zero. During D* subfile loading, S1RRN is to be incremented by one for each subfile D* record written. D* D* The S1LINENBR fields are initialized differently. Subfile page D* loading is performed with a do-loop at which time S1LINE is zero. D* The do-loop is 'dou S1LINENBR = S1PAGE'. During subfile loading, D* S1LINE is incremented by one for each record written. D* D* S1RCDNBR is defined using the DDS keyword SFLRCDNBR seen on D* the subfile's control record. It is used to govern which page is D* seen after loads. To position to a page, specify that the page D* of the subfile to be displayed is the page containing the record D* whose relative record number is in this field. The default D* behavior is governed by moving S1LINE into S1RCDNBR after each load. D* D* In summary, S1PAGE is used by the program to determine if a full D* page has been loaded. S1RRN is defined on the F-Spec for the D* WORKSTN file to define the file's RRN field. It should not be used D* for anything other than for that purpose. Running parallel with D* this field is S1LINENBR which is used to control the load-loop. D* S1RCDNBR is used to control page positioning after loading. It may D* also be used to allow the user to control page positioning by D* moving the value supplied by a control record input field into D* S1RCDNBR. D* D******************************************************************** D S1RRN S 4 0 D S1PAGE S 5 0 D S1LINENBR S 5 0 D S2RRN S 4 0 D S2PAGE S 5 0 D S2LINENBR S 5 0 D S3RRN S 4 0 D S3PAGE S 5 0 D S3LINENBR S 5 0 D S4RRN S 4 0 D S4PAGE S 5 0 D S4LINENBR S 5 0 D S5RRN S 4 0 D S5PAGE S 5 0 D S5LINENBR S 5 0 D S6RRN S 4 0 D S6PAGE S 5 0 D S6LINENBR S 5 0 D S7RRN S 4 0 D S7PAGE S 5 0 D S7LINENBR S 5 0 D S8RRN S 4 0 D S8PAGE S 5 0 D S8LINENBR S 5 0 D S9RRN S 4 0 D S9PAGE S 5 0 D S9LINENBR S 5 0 D******************************************************************** D* Values seen on a subfile record's select field D******************************************************************** D @ZERO C CONST(0) D @ONE C CONST(1) D @TWO C CONST(2) D @THREE C CONST(3) D @FOUR C CONST(4) D @FIVE C CONST(5) D @SIX C CONST(6) D @SEVEN C CONST(7) D @EIGHT C CONST(8) D @NINE C CONST(9) D @ZEROa C CONST('0') D @ONEa C CONST('1') D @TWOa C CONST('2') D @THREEa C CONST('3') D @FOURa C CONST('4') D @FIVEa C CONST('5') D @SIXa C CONST('6') D @SEVENa C CONST('7') D @EIGHTa C CONST('8') D @NINEa C CONST('9') ******************************************************************** * Shared Screen Constants ******************************************************************** * Values for subfile select field D @SELECT C CONST('1') D @DELETE C CONST('4') D @WORKWITH C CONST('5') D @PRINT C CONST('P') * Command Key field values seen at bottom of screen. D @CKHELP C CONST('F1=Help') D @CKEXIT C CONST('F3=Exit') D @CKPROMPT C CONST('F4=Prompt') D @CKREFRESH C CONST('F5=Refresh') D @CKCREATE C CONST('F6=Create') D @CKADD C CONST('F6=Add') D @CKNEW C CONST('F6=New') D @CKCANCEL C CONST('F12=Cancel') D @CKPREV C CONST('F12=Previous') D @CKPRINT C CONST('F17=Print') D******************************************************************** D*** END OF CPYSFCONST COPY MEMBER ****************************** D********************************************************************

See them work together

To see these fields in action within an RPG /free program, refer to this post which shows how they are used to control subfile initialization, loading and page positioning.

Follow

Get every new post delivered to your Inbox.