Improve & cleanup

Improved images, cleaned up code, revised documentation.
This commit is contained in:
SJLennon
2020-10-19 15:02:55 -04:00
parent 2dc0714b39
commit 066e786d72
12 changed files with 474 additions and 549 deletions
+131 -184
View File
@@ -1,4 +1,11 @@
/TITLE PMTSTATE Search and return a USA State Code
//==============================================================*
// This is a "load all" subfile, where the system takes care or
// paging up and down. All selected data is loaded into the
// subfile. STATES table has only 58 rows, so selecting all
// is approptiate.
// For larger numbers of rows, a "page at at time" approach
// may make more sense.
//==============================================================*
// Displays USA state names and their 2-char codes in a window.
// Can sort the display by name or code.
@@ -22,7 +29,7 @@
// carried across subroutines.
// - UPPERCASE is used for external names, i.e., files, fields, formats
// and anything else not directly coded in the program.
//
// - In the display file, this field naming convention is used:
// Screen Header: Fields begin with SH_
// Subfile: Fields begin with SF_
@@ -35,18 +42,18 @@
// not the default of QRPGLESRC. Change as needed.
//=============================================================
H DftActGrp(*NO) ActGrp(*CALLER) option(*nodebugio: *srcstmt)
H BndDir('UTIL_BND')
H main(Main)
h DftActGrp(*NO) ActGrp(*CALLER) option(*nodebugio: *srcstmt)
h BndDir('UTIL_BND')
h main(Main)
//=== Display File ==============================================
FPMTSTATED CF E WorkStn INFDS(dfInfDS)
F INDDS(dfIndDS)
F SFILE(SFL:SflRRN)
F USROPN
fPMTSTATED CF E WorkStn INFDS(dfInfDS)
f INDDS(dfIndDS)
f SFILE(SFL:SflRRN)
f USROPN
D Main pr extpgm('PMTSTATER')
D 2A
d Main pr extpgm('PMTSTATER')
d ReturnState 2A
//=== Service Program Prototypes ================================
/include DEMO,Srv_Msg_P
@@ -57,8 +64,8 @@
//=== Fields read by SQL ========================================
// NOTE: Only the fields in fetchData which are fetched by the
// SQL Cursor are populated.
D STATES e ds extname(STATES)
D qualified template
d STATES e ds extname(STATES)
d qualified template
d FetchData ds likeds(STATES)
//=== SQL State Constants =======================================
@@ -70,56 +77,58 @@
//=== Display File Information Data Structure ===================
// Allows us to determine which function key was pressed
D dfInfDS DS
D Key 369 369
d dfInfDS DS
d Key 369 369
//=== Display File Indicator Data Structure =====================
// This is a "private" indicator area for the display file.
D dfIndDS ds 99
d dfIndDS ds 99
//--- 01-20 are not automatically cleared after EXFMT ----------
D scSortColor 01 01
d scCodeHi 01 01
d scNameHi 02 02
//--- 21-99 automatically cleared after EXFMT ------------------
D dfIndClr 21 99
d dfIndClr 21 99
//--- Subfile indicators (prefix "sf") -------------------------
D sfSflNxtChg 80 80n
D sfOPT_RI 81 81n
D sfOPT_PC 82 82n
d sfSflNxtChg 80 80n
d sfOPT_RI 81 81n
d sfOPT_PC 82 82n
//--- Subfile Control indicators (prefix "sc") ----------------
D scMDT 95 95n
D scNoDta 96 96n
D scSflEnd 97 97n
D scSflDsp 98 98n
D scSflClr 99 99n
d scMDT 95 95n
d scNoDta 96 96n
d scSflEnd 97 97n
d scSflDsp 98 98n
d scSflClr 99 99n
//=== Fields to control the subfile screen ======================
D SflRRN s 5 0
D RcdsInSfl s 5 0
D SflPageSize c 7
d SflRRN s 5i 0
d RcdsInSfl s 5i 0
d SflPageSize c 6
d SflMaxRecd s 5i 0 inz(9999)
// SC_CSR_RCD is defined in the display file and is set with a
// RRN which determines which subfile page is displayed and on
// which record the cursor is positioned.
//=== Program Status Data Structure =============================
D ProgStatus sds
D PgmName *PROC
d ProgStatus sds
d PgmName *PROC
D MainProc S 10a
d MainProc S 10a
//=== Text for function keys ====================================
D F3Text c 'F3=Exit'
d F3Text c 'F3=Exit'
d F5Text c 'F5=Refresh'
d F12Text c 'F12=Cancel'
D F7Text1 c 'F7=By '
D F7Text2 s 5a inz(' ')
D F7Text S 11a inz(' ')
d F7Text1 c 'F7=By '
d F7Text2 s 5a inz(' ')
d F7Text S 11a inz(' ')
//SortSeq is used in SQL Order By
D SortSeq s 4a inz(' ')
D SortbyName s 4a inz('Name')
D SortbyCode s 4a inz('Code')
//SortSeq is used in SQL Order By in a CASE construct.
d SQLSortSeq s 4a inz(' ')
d SortbyName s 4a inz('Name')
d SortbyCode s 4a inz('Code')
//=== Options Text ==============================================
@@ -127,35 +136,28 @@
//=== Search Criteria Screen Fields =============================
d SearchCriteria ds inz
D SC_NAME
d SC_NAME
//=== Last Search Criteria Fields ===============================
d LastSearchCriteria...
d ds inz
D LastSC_NAME Like(SC_NAME)
d LastSC_NAME Like(SC_NAME)
//=== SQL Search Variables ======================================
D DESCLike S 12 varying
d DESCLike S 12 varying
//=== Global Switches ===========================================
D EofData s n
D CursorOpen s n
D NewSearchCriteria...
D s n
D SflMsgSnt s n
d EofData s n
d CursorOpen s n
d NewSearchCriteria...
d s n
d SflMsgSnt s n
d Opt1OK s n
D OptError s n
D CowsComeHome c const('0')
d OptError s n
d CowsComeHome c const('0')
//=== Work Fields ===============================================
D inx s 10i 0
//=== Translation ===============================================
D Lower c const('abcdefghijklmnopqrstuvwxyz')
D Upper c const('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
D HighVals s 30 inz(*hival)
d inx s 10i 0
//=============================================================
//== Program Starts Here ======================================
@@ -164,7 +166,6 @@
d Main pi
d pState Like(FetchData.STATE)
/FREE
exsr Init;
exsr BldFkeyText;
@@ -173,7 +174,7 @@
exec sql set option datfmt=*iso,
closqlcsr=*endmod;
//=== SQL Cursor Definitions ==================================
// Sort Order is controlled by field SortSeq which is
// Sort Order is controlled by field SQLSortSeq which is
// used in a CASE statement.
exec SQL
declare DataCur cursor for
@@ -182,18 +183,18 @@
NAME
from STATES
where upper(NAME) like :DescLike
order by case :SortSeq
order by case :SQLSortSeq
when :SortByName then NAME
when :SortByCode then STATE
else '1'
end
optimize for 7 rows
for fetch only;
// === Initial screen display =================================
write SH_HDR;
SflClear();
exsr SflFirstPage;
exsr ProcessSearchCriteria;
exsr SflLoadAll;
//=============================================================
// === Main Program Loop ======================================
@@ -206,7 +207,8 @@
// If switching display order, reload first page
if Key = F07;
exsr SflFirstPage;
exsr ProcessSearchCriteria;
exsr SflLoadAll;
endif;
// Write/Read the screen
@@ -219,21 +221,12 @@
if SearchCriteria <> LastSearchCriteria
or NewSearchCriteria = *on;
SflClear();
exsr SflFirstPage;
exsr ProcessSearchCriteria;
exsr SflLoadAll;
else;
exsr ProcessOption;
endif;
iter;
endif;
//--- Page Down -------------------------------------------
if Key = PageDown;
if RcdsInSfl > 0;
exsr SflFillPage;
else;
// Key not active msg
SflMsgSnt= SndSflMsg('DEM0003');
endif;
iter;
endif;
@@ -292,8 +285,8 @@
//--- F3: Exit, close down program -----------------------
when Key = F03;
*inlr = *on;
exsr CloseDownPgm;
*inlr = *on;
return;
//--- F12: Return to caller, leave program active ---------
@@ -309,15 +302,17 @@
//--- F7: Toggle Sort Sequence ---------------------------
when Key = F07;
if SortSeq=SortByName;
SortSeq = SortByCode;
SC_SORTED = SortbyName;
ScSortColor=*on;
if SQLSortSeq=SortByName;
SQLSortSeq = SortByCode;
SC_SORTED = SortByCode;
scCodeHi = *on;
scNameHi = *off;
F7Text2 = SortByName;
else;
SortSeq = SortByName;
SC_SORTED = SortbyCode;
scSortColor = *off;
SQLSortSeq = SortByName;
SC_SORTED = SortByName;
scNameHi = *on;
scCodeHI = *off;
F7Text2 = SortbyCode;
endif;
F7Text = F7Text1 + F7Text2;
@@ -353,9 +348,9 @@
// Return Code to caller
pSTATE = SF_CODE;
exsr CloseDownPgm;
*inlr = *on;
return;
//--- Opt is blank ----------------------------------------
when SF_OPT = ' ';
// If changed, assume clearing an error from last time
@@ -372,7 +367,7 @@
// Not a valid option at this time
SflMsgSnt= SndSflMsg('DEM0004':SF_OPT);
// Leave cursor at first invalid option
exsr SetCursorPosition;
exsr SetScreenCursorPosition;
optError = *on;
// SFLNXTCHG forces this record to be read again
@@ -404,92 +399,44 @@
endsr;
//=== SflFirstPage ============================================
// Processes the Search fields in the Sub file control, then
// fills the first page of the subfile.
// If any errors in the search fields then no records are
// are added to the subfile.
//=== SflLoadAll ==============================================
// Loads all selected records to the subfile.
// Returns:
// EofData = *on if there are no more data records
// *off if there is at least one more data
// record.
// NewSearchCriteria = *on Next time evaluate the
// search fields again.
// RcdsInSfl contains relative record number of last record
// written to the subfile.
begsr SflFirstPage;
exsr ProcessSearchCriteria;
if NewSearchCriteria = *off;
EofData = FetchNextData();
if EofData = *off;
exsr SflFillPage;
else;
// No records match selection criteria
SflMsgSnt= SndSflMsg('DEM0002');
NewSearchCriteria = *on;
endif;
endif;
endsr;
//=== SflFillPage =============================================
// Adds a page worth of records to the subfile.
// Assumes:
// One record is already read from the SQL cursor.
// Returns:
// EofData = *on if no more data records.
// *off if at least one data record is read
// and has not been displayed.
// EofData = *on (there are no more data records.)
// RcdsInSfl contains relative record number of last record
// written to the subfile.
// SC_CSR_RCD contains relative record number of 1st record
// on the page & positions cursor there.
begsr SflFillPage;
select;
begsr SflLoadAll;
when EofData = *on;
// do nothing
other;
// Add a subfile page. If not EOF, then one extra recd is
// read for the next time.
// Position cursor at first record on the subfile page.
SC_CSR_RCD = 0;
for inx = 1 to SflPageSize;
SC_CSR_RCD = 1;
for inx = 1 to SflMaxRecd;
EofData = FetchNextData();
if EofData = *on;
leave;
endIf;
// Build/Format the subfile record
clear SF_OPT;
SF_CODE = FetchData.STATE;
SF_NAME = FetchData.NAME;
SflRRN = inx;
RcdsinSfl = RcdsInSfl + 1;
SflRRN = RcdsInSfl;
write SFL;
// Leave curson on first SFL record
if SC_CSR_RCD = 0;
SC_CSR_RCD = SflRRN;
endif;
// Can't display more than 9,9999 records.
if SflRRN = 9999;
if SflRRN = SflMaxRecd;
EofData = *on;
SflMsgSnt= SndSflMsg('DEM0006');
leave;
endif;
EofData = FetchNextData();
if EofData = *on;
leave;
endIf;
endfor;
endsl;
endsr;
//=== ProcessSearchCriteria====================================
@@ -510,7 +457,6 @@
NewSearchCriteria = *off;
// Save entered values. (Never change screen fields.)
LastSearchCriteria = SearchCriteria;
//exsr SaveSearchCriteria;
CloseCursor();
//---------------------------------------------------------------
@@ -522,7 +468,7 @@
endif;
//---------------------------------------------------------------
// If no errors, open the SQL cursor
// If no errors in search criteria, open the SQL cursor
if NewSearchCriteria = *off;
exec sql open DataCur;
if SQLSTT <> SQLSuccess;
@@ -536,7 +482,7 @@
//=== SetCursorPostion ========================================
// If Invalid Option, position screen cursor on first one,
// else postion cursor on the last valid option.
begsr SetCursorPosition;
begsr SetScreenCursorPosition;
if OptError = *off;
SC_CSR_RCD=SflRRN;
endif;
@@ -556,15 +502,18 @@
// Things to do before we issue a return to the caller
begsr CloseDownPgm;
CloseCursor();
if %open(PMTSTATED);
close PMTSTATED;
endif;
endsr;
//=== Init ====================================================
// Must be executed each time program is entered, because F12
// and Enter key leave with LR off.
// Must be executed each time program is entered
begsr Init;
SortSeq = SortByCode;
SC_SORTED = SortbyName;
scSortColor = *off;
SQLSortSeq = SortByName;
SC_SORTED = SortByName;
scNameHi = *on; // Name highlighted
scCodeHi = *off;
F7Text2 = SortByCode;
F7Text = F7Text1 + F7Text2;
@@ -578,9 +527,11 @@
MSGPGMQF = MainProc;
MSGPGMQC = MSGPGMQF;
SH_PGM = PgmName;
if not %open(PMTSTATED);
open PMTSTATED;
endif;
// Clear fields left over from previous F12.
reset LastSearchCriteria;
reset SearchCriteria;
@@ -602,10 +553,10 @@
// If the target string is all blank to start with it will not
// end up with a leading blank.
/END-FREE
PCatB b
pCatB b
dCatB PI 79 varying
D ToStr 79 varying value
D AddStr 79 varying value
d ToStr 79 varying value
d AddStr 79 varying value
/FREE
if ToStr=' ';
return AddStr;
@@ -613,7 +564,8 @@
return %trimr(ToStr) + ' ' + AddStr;
endif;
/END-FREE
PCatB e
pCatB e
// === SQLProblem ================================================
// For those "Never should happen" SQL errors.
// Issues DUMP(A) to dump memory, then ends program by
@@ -635,7 +587,6 @@
/end-free
p SQLProblem E
//--------------------------------------------------
// Procedure name: FetchNextData
// Purpose: Fetch the next row from the cursor
@@ -643,11 +594,11 @@
// *ON No more data, nothing returned
// *OFF Data returned
//--------------------------------------------------
P FetchNextData B
D FetchNextData PI N
p FetchNextData B
d FetchNextData PI N
// Local fields
D wkEof S N
d wkEof S N
/FREE
wkEoF= *off;
exec sql fetch DataCur into
@@ -666,7 +617,7 @@
RETURN wkEof;
/END-FREE
P FetchNextData E
p FetchNextData E
//--------------------------------------------------
// Procedure name: SndSflMsg
@@ -677,19 +628,19 @@
// Parameter: ErrMsgFile => Optional Error Message File
// Defaults to CUSTMSGF
//--------------------------------------------------
P SndSflMsg B
D SndSflMsg PI N
D ErrMsgId 7A CONST
D ErrMsgData 80A CONST
D OPTIONS(*NOPASS:*VARSIZE)
D ErrMsgFile 10A CONST
D OPTIONS(*NOPASS)
p SndSflMsg B
d SndSflMsg PI N
d ErrMsgId 7A CONST
d ErrMsgData 80A CONST
d OPTIONS(*NOPASS:*VARSIZE)
d ErrMsgFile 10A CONST
d OPTIONS(*NOPASS)
// Local fields
D retField S N
D wkMsgId s 7a
D wkMsgFile s 10a
D wkMsgData s 80a varying
d retField S N
d wkMsgId s 7a
d wkMsgFile s 10a
d wkMsgData s 80a varying
/FREE
if %parms >2;
@@ -712,14 +663,14 @@
RETURN retField;
/END-FREE
P SndSflMsg E
p SndSflMsg E
//--------------------------------------------------
// Procedure name: CloseCurssor
// Purpose: Closes the SQL Cursor
//--------------------------------------------------
P CloseCursor B
D CloseCursor PI
p CloseCursor B
d CloseCursor PI
/FREE
if CursorOpen = *on;
exec sql close DataCur;
@@ -730,16 +681,15 @@
endif;
RETURN;
/END-FREE
P CloseCursor E
p CloseCursor E
//--------------------------------------------------
// Procedure name: SflClear
// Purpose: Clears the Subfile
// Returns:
//--------------------------------------------------
P SflClear B
D SflClear PI
p SflClear B
d SflClear PI
/FREE
clear SflRRN;
clear RcdsInSfl;
@@ -748,7 +698,4 @@
scSflClr = *OFF;
return;
/END-FREE
P SflClear E
p SflClear E