*arrowtable**************************************************************************
!ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
!³ ARROWTABLE: Model file modification to display arrows() on scrolling     ³
!³             tables as needed, if there are more records than will fit      ³
!³             on one screen.                                                 ³
!³                                                                            ³
!³ Modifications by: Jerry Murdock                                            ³
!³                   3118 Greenwood Trail                                     ³
!³                   Marietta, GA 30067                                       ³
!³                                                                            ³
!³                        ***** STANDARD VERSION *****                        ³
!ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
@PROCNAME    PROCEDURE

SCREEN       SCREEN       PRE(SCR),@SCREENOPT
                          @PAINTS
                          @STRINGS
                          @VARIABLES
                          ENTRY,USE(?FIRST_FIELD)
                          @FIELDS
                          ENTRY,USE(?PRE_POINT)
                          REPEAT(@COUNT),EVERY(@PROWS),INDEX(NDX)
              @PLOC         POINT(@PROWS,@COLS),USE(?POINT),ESC(?-1)
                            @SCROLLVARIABLES
             .            .

NDX          BYTE                                !REPEAT INDEX FOR POINT AREA
ROW          BYTE                                !ACTUAL ROW OF SCROLL AREA
COL          BYTE                                !ACTUAL COLUMN OF SCROLL AREA
COUNT        BYTE(@COUNT)                        !NUMBER OF ITEMS TO SCROLL
ROWS         BYTE(@ROWS)                         !NUMBER OF ROWS TO SCROLL
COLS         BYTE(@COLS)                         !NUMBER OF COLUMNS TO SCROLL
FOUND        BYTE                                !RECORD FOUND FLAG
NEWPTR       LONG                                !POINTER TO NEW RECORD

TABLE        TABLE,PRE(TBL)                      !TABLE OF RECORD DATA
               @TABLEFIELDS                      !  SCREEN AND KEY COMPONENTS
PTR            LONG                              !  POINTER TO FILE RECORD
             .
             @SAVEITEMS                          !SELECTOR FIELD SAVE AREA
             @SAVETOTALS                         !TOTAL FIELD ACCUMULATORS

!#----------------
SAVE_REC     GROUP
             BYTE,DIM(SIZE(@PRE:RECORD))
             .

up_arrow      string(1)
dn_arrow      string(1)

last_record   long
first_record  long
totrecords    long
!#----------------
  EJECT
  CODE
!#---------------
  lookup# = 0                                    !! Initialize Counters
  totrecords = 0
!#---------------
  ACTION# = ACTION                               !SAVE ACTION
  OPEN(SCREEN)                                   !OPEN THE SCREEN
  SETCURSOR                                      !TURN OFF ANY CURSOR
  @SETUP                                         !CALL SETUP PROCEDURE
  @INITSELECTS                                   !SAVE SELECTOR FIELDS
  @TOTCLEAR                                      !ZERO TOTAL ACCUMULATORS
  TBL:PTR = 1                                    !START AT TABLE ENTRY
  NDX = 1                                        !PUT SELECTOR BAR ON TOP ITEM
  ROW = ROW(?POINT)                              !REMEMBER TOP ROW AND
  COL = COL(?POINT)                              !LEFT COLUMN OF SCROLL AREA
  RECORDS# = TRUE                                !INITIALIZE RECORDS FLAG
  CACHE(@KEYNAME,.25)                            !CACHE KEY FILE
  @BUILDTABLE                                    !BUILD SCROLLING TABLE
  LOOP                                           !LOOP UNTIL USER EXITS
    ACTION = ACTION#                             !RESTORE ACTION
!#----------

    if records(@filename) <> totrecords then do set_fst_lst.
    !!  Set Pointers to First & Last Records

    get(table,1)
    if error() or tbl:ptr = first_record
       up_arrow = ''
    else
       up_arrow = ''
    .

    get(table,count)
    if error() or tbl:ptr = last_record
       dn_arrow = ''
    else
       dn_arrow = ''
    .
!#----------
    @RESTSELECTS                                 !RESTORE SELECTOR FIELDS
    @TOTSHOW                                     !DISPLAY TOTAL AMOUNTS ON SCRN
    @LOOKUPS                                     !DISPLAY FROM OTHER FILES
    @SHOW                                        !DISPLAY STRING VARIABLES
    @COMPUTE                                     !DISPLAY COMPUTED FIELDS
    @RESULT                                      !MOVE RESULTING VALUES
    ALERT                                        !RESET ALERTED KEYS
    ALERT(REJECT_KEY)                            !ALERT SCREEN REJECT KEY
    ALERT(ACCEPT_KEY)                            !ALERT SCREEN ACCEPT KEY
    @ALERT                                       !ALERT HOT KEYS
    ACCEPT                                       !READ A FIELD
    @TABLEHOT                                    !CALL HOT KEY PROCEDURES
    IF KEYCODE() = REJECT_KEY THEN BREAK.        !RETURN ON SCREEN REJECT KEY

    IF  KEYCODE() = ACCEPT_KEY    |              !ON SCREEN ACCEPT KEY
    AND FIELD() <> ?POINT                        !BUT NOT ON THE POINT FIELD
      UPDATE                                     !  MOVE ALL FIELDS FROM SCREEN
      SELECT(?)                                  !  START WITH CURRENT FIELD
      SELECT                                     !  EDIT ALL FIELDS
      CYCLE                                      !  GO TO TOP OF LOOP
    .

    CASE FIELD()                                 !JUMP TO FIELD EDIT ROUTINE

    OF ?FIRST_FIELD                              !FROM THE FIRST FIELD
      IF KEYCODE() = ESC_KEY   |                 !  RETURN ON ESC KEY
      OR RECORDS# = FALSE                        !  OR NO RECORDS
        BREAK                                    !    EXIT PROGRAM
      .
    @EDITS                                       !FIELD EDIT ROUTINES
    OF ?PRE_POINT                                !PRE POINT FIELD CONDITION
      IF KEYCODE() = ESC_KEY                     !  BACKING UP?
        SELECT(?-1)                              !    SELECT PREVIOUS FIELD
      ELSE                                       !  GOING FORWARD
        SELECT(?POINT)                           !    SELECT MENU FIELD
      .
      @INITLOCATE                                !    SHOW CURSOR FOR LOCATOR
    OF ?POINT                                    !PROCESS THE POINT FIELD
      IF RECORDS(TABLE) = 0                      !IF THERE ARE NO RECORDS
        CLEAR(@PRE:RECORD)                       !  CLEAR RECORD AREA
        ACTION = 1                               !  SET ACTION TO ADD
        GET(@FILENAME,0)                         !  CLEAR PENDING RECORD
        @AUTONUMKEY                              !  AUTO INCREMENT KEY FIELD
        @TOTACTN                                 !  SAVE TOTACTN
        @RESTSELECTS                             !  RESTORE SELECTOR FIELDS
        @UPDATE                                  !  CALL FORM FOR NEW RECORD
        NEWPTR = POINTER(@FILENAME)              !    SET POINTER TO NEW RECORD
        DO FIRST_PAGE                            !  DISPLAY THE FIRST PAGE
        IF RECORDS(TABLE) = 0                    !  IF THERE AREN'T ANY RECORDS
          RECORDS# = FALSE                       !    INDICATE NO RECORDS
          SELECT(?PRE_POINT-1)                   !    SELECT THE PRIOR FIELD
        .
        CYCLE                                    !    AND LOOP AGAIN
      .
      @LOCATE                                    !PERORM LOCATOR LOGIC
      CASE KEYCODE()                             !PROCESS THE KEYSTROKE

      OF INS_KEY                                 !INS KEY
        CLEAR(@PRE:RECORD)                       !  CLEAR RECORD AREA
        ACTION = 1                               !  SET ACTION TO ADD
        GET(@FILENAME,0)                         !  CLEAR PENDING RECORD
        @AUTONUMKEY                              !  AUTO INCREMENT KEY FIELD
        @TOTACTN                                 !  SAVE TOTALS
        @RESTSELECTS                             !  RESTORE SELECTOR FIELDS
        @UPDATE                                  !  CALL FORM FOR NEW RECORD
        IF ~ACTION                               !  IF RECORD WAS ADDED
          NEWPTR = POINTER(@FILENAME)            !    SET POINTER TO NEW RECORD
          DO FIND_RECORD                         !    POSITION IN FILE
!#----------
          do set_fst_lst                  !!Set Pointers to First & Last Records
!#----------
        .
      OF ENTER_KEY                               !ENTER KEY
      OROF ACCEPT_KEY                            !CTRL-ENTER KEY
        DO GET_RECORD                            !  GET THE SELECTED RECORD
        IF ACTION = 4 AND KEYCODE() = ENTER_KEY!    IF THIS IS A LOOKUP REQUEST
          ACTION = 0                             !    SET ACTION TO COMPLETE
          BREAK                                  !    AND RETURN TO CALLER
        .
        IF ~ERROR()                              !  IF RECORD IS STILL THERE
          ACTION = 2                             !    SET ACTION TO CHANGE
          @TOTCHECK                              !    SAVE TOTALS
          @UPDATE                                !    CALL FORM TO CHANGE REC
          IF ACTION THEN CYCLE.                  !    IF SUCCESSFUL RE-DISPLAY
          @TOTMINUS                              !    SUBTRACT CURRENT AMOUNTS
        .
        NEWPTR = POINTER(@FILENAME)              !    SET POINTER TO NEW RECORD
        DO FIND_RECORD                           !    POSITION IN FILE
!#----------
        do set_fst_lst                   !!Set Pointers to First & Last Records
!#----------
      OF DEL_KEY                                 !DEL KEY
        DO GET_RECORD                            !  READ THE SELECTED RECORD
        IF ~ERROR()                              !  IF RECORD IS STILL THERE
          ACTION = 3                             !    SET ACTION TO DELETE
          @TOTCHECK                              !    SAVE TOTALS
          @UPDATE                                !    CALL FORM TO DELETE
          IF ~ACTION                             !    IF SUCCESSFUL
            @TOTMINUS                            !      SUBTRACT CURRENT AMOUNTS
            N# = NDX                             !      SAVE POINT INDEX
            DO SAME_PAGE                         !      RE-DISPLAY
            NDX = N#                             !      RESTORE POINT INDEX
!#----------
            do set_fst_lst               !!Set Pointers to First & Last Records
!#----------
        . .
      OF DOWN_KEY                                !DOWN ARROW KEY
        DO SET_NEXT                              !  POINT TO NEXT RECORD
        DO FILL_NEXT                             !  FILL A TABLE ENTRY
        IF FOUND                                 !  FOUND A NEW RECORD
          SCROLL(ROW,COL,ROWS,COLS,ROWS(?POINT)) !    SCROLL THE SCREEN UP
          GET(TABLE,RECORDS(TABLE))              !  GET RECORD FROM TABLE
          DO FILL_SCREEN                         !  DISPLAY ON SCREEN
        .

      OF PGDN_KEY                                !PAGE DOWN KEY
        DO SET_NEXT                              !  POINT TO NEXT RECORD
        DO NEXT_PAGE                             !  DISPLAY THE NEXT PAGE

      OF CTRL_PGDN                               !CTRL-PAGE DOWN KEY
        DO LAST_PAGE                             !  DISPLAY THE LAST PAGE
        NDX = RECORDS(TABLE)                     !  POSITION POINT BAR

      OF UP_KEY                                  !UP ARROW KEY
        DO SET_PREV                              !  POINT TO PREVIOUS RECORD
        DO FILL_PREV                             !  FILL A TABLE ENTRY
        IF FOUND                                 !  FOUND A NEW RECORD
          SCROLL(ROW,COL,ROWS,COLS,-(ROWS(?POINT)))! SCROLL THE SCREEN DOWN
          GET(TABLE,1)                           !  GET RECORD FROM TABLE
          DO FILL_SCREEN                         !  DISPLAY ON SCREEN
        .

      OF PGUP_KEY                                !PAGE UP KEY
        DO SET_PREV                              !  POINT TO PREVIOUS RECORD
        DO PREV_PAGE                             !  DISPLAY THE PREVIOUS PAGE

      OF CTRL_PGUP                               !CTRL-PAGE UP
        DO FIRST_PAGE                            !  DISPLAY THE FIRST PAGE
        NDX = 1                                  !  POSITION POINT BAR
  . . .
  FREE(TABLE)                                    !FREE MEMORY TABLE
  RETURN                                         !AND RETURN TO CALLER

SAME_PAGE ROUTINE                                !DISPLAY THE SAME PAGE
  GET(TABLE,1)                                   !  GET THE FIRST TABLE ENTRY
  DO FILL_RECORD                                 !  FILL IN THE RECORD
  SET(@KEYNAME,@KEYNAME,TBL:PTR)                 !  POSITION FILE
  FREE(TABLE)                                    !  EMPTY THE TABLE
  DO NEXT_PAGE                                   !  DISPLAY A FULL PAGE

FIRST_PAGE ROUTINE                               !DISPLAY FIRST PAGE
  BLANK(ROW,COL,ROWS,COLS)
  FREE(TABLE)                                    !  EMPTY THE TABLE
  CLEAR(@PRE:RECORD,-1)                          !  CLEAR RECORD TO LOW VALUES
  CLEAR(TBL:PTR)                                 !  ZERO RECORD POINTER
  @SETFILE                                       !  POSITION FILE POINTERS
  LOOP NDX = 1 TO COUNT                          !  FILL UP THE TABLE
    DO FILL_NEXT                                 !    FILL A TABLE ENTRY
    IF NOT FOUND THEN BREAK.                     !    GET OUT IF NO RECORD
  .
  NDX = 1                                        !  SET TO TOP OF TABLE
  DO SHOW_PAGE                                   !  DISPLAY THE PAGE
!#----------
  do set_fst_lst                         !!Set Pointers to First & Last Records
!#----------

LAST_PAGE ROUTINE                                !DISPLAY LAST PAGE
  NDX# = NDX                                     !  SAVE SELECTOR POSITION
  BLANK(ROW,COL,ROWS,COLS)                       !  CLEAR SCROLLING AREA
  FREE(TABLE)                                    !  EMPTY THE TABLE
  CLEAR(@PRE:RECORD,1)                           !  CLEAR RECORD TO HIGH VALUES
  CLEAR(TBL:PTR,1)                               !  CLEAR PTR TO HIGH VALUE
  @SETFILE                                       !  POSITION FILE POINTERS
  LOOP NDX = COUNT TO 1 BY -1                    !  FILL UP THE TABLE
    DO FILL_PREV                                 !    FILL A TABLE ENTRY
    IF NOT FOUND THEN BREAK.                     !    GET OUT IF NO RECORD
  .                                              !  END OF LOOP
  NDX = NDX#                                     !  RESTORE SELECTOR POSITION
  DO SHOW_PAGE                                   !  DISPLAY THE PAGE
!#----------
  do set_fst_lst                         !!Set Pointers to First & Last Records
!#----------

FIND_RECORD ROUTINE                              !POSITION TO SPECIFIC RECORD
  SET(@KEYNAME,@KEYNAME,NEWPTR)                  !POSITION FILE
  IF NEWPTR = 0                                  !NEWPTR NOT SET
    NEXT(@FILENAME)                              !  READ NEXT RECORD
    NEWPTR = POINTER(@FILENAME)                  !  SET NEWPTR
    SKIP(@FILENAME,-1)                           !  BACK UP TO DISPLAY RECORD
  .
  FREE(TABLE)                                    !  CLEAR THE RECORD
  DO NEXT_PAGE                                   !  DISPLAY A PAGE

NEXT_PAGE ROUTINE                                !DISPLAY NEXT PAGE
  SAVECNT# = RECORDS(TABLE)                      !  SAVE RECORD COUNT
  LOOP COUNT TIMES                               !  FILL UP THE TABLE
    DO FILL_NEXT                                 !    FILL A TABLE ENTRY
    IF NOT FOUND                                 !    IF NONE ARE LEFT
      IF NOT SAVECNT#                            !      IF REBUILDING TABLE
        DO LAST_PAGE                             !      FILL IN RECORDS
        EXIT                                     !      EXIT OUT OF ROUTINE
      .
      BREAK                                      !    EXIT LOOP
  . .
  DO SHOW_PAGE                                   !  DISPLAY THE PAGE

SET_NEXT ROUTINE                                 !POINT TO THE NEXT PAGE
  GET(TABLE,RECORDS(TABLE))                      !  GET THE LAST TABLE ENTRY
  DO FILL_RECORD                                 !  FILL IN THE RECORD
  SET(@KEYNAME,@KEYNAME,TBL:PTR)                 !  POSITION FILE
  NEXT(@FILENAME)                                !  READ THE CURRENT RECORD

FILL_NEXT ROUTINE                                !FILL NEXT TABLE ENTRY
  FOUND = FALSE                                  !  ASSUME RECORD NOT FOUND
  LOOP UNTIL EOF(@FILENAME)                      !  LOOP UNTIL END OF FILE
    NEXT(@FILENAME)                              !    READ THE NEXT RECORD
    @CHECKSELECT                                 !    SELECTOR
    IF ~(@FILTER) THEN CYCLE.                    !    FILTER
    FOUND = TRUE                                 !    SET RECORD FOUND
    DO FILL_TABLE                                !    FILL IN THE TABLE ENTRY
    ADD(TABLE)                                   !    ADD LAST TABLE ENTRY
    GET(TABLE,RECORDS(TABLE)-COUNT)              !    GET ANY OVERFLOW RECORD
    DELETE(TABLE)                                !    AND DELETE IT
    EXIT                                         !    RETURN TO CALLER
  .
PREV_PAGE ROUTINE                                !DISPLAY PREVIOUS PAGE
  LOOP COUNT TIMES                               !  FILL UP THE TABLE
    DO FILL_PREV                                 !    FILL A TABLE ENTRY
    IF NOT FOUND THEN BREAK.                     !    GET OUT IF NO RECORD
  .
  DO SHOW_PAGE                                   !  DISPLAY THE PAGE

SET_PREV ROUTINE                                 !POINT TO PREVIOUS PAGE
  GET(TABLE,1)                                   !  GET THE FIRST TABLE ENTRY
  DO FILL_RECORD                                 !  FILL IN THE RECORD
  SET(@KEYNAME,@KEYNAME,TBL:PTR)                 !  POSITION FILE
  PREVIOUS(@FILENAME)                            !  READ THE CURRENT RECORD

FILL_PREV ROUTINE                                !FILL PREVIOUS TABLE ENTRY
  FOUND = FALSE                                  !  ASSUME RECORD NOT FOUND
  LOOP UNTIL BOF(@FILENAME)                      !  LOOP UNTIL BEGINNING OF FILE
    PREVIOUS(@FILENAME)                          !    READ THE PREVIOUS RECORD
    @CHECKSELECT                                 !    SELECTOR
    IF ~(@FILTER) THEN CYCLE.                    !    FILTER
    FOUND = TRUE                                 !    SET RECORD FOUND
    DO FILL_TABLE                                !    FILL IN THE TABLE ENTRY
    ADD(TABLE,1)                                 !    ADD FIRST TABLE ENTRY
    GET(TABLE,COUNT+1)                           !    GET ANY OVERFLOW RECORD
    DELETE(TABLE)                                !    AND DELETE IT
    EXIT                                         !    RETURN TO CALLER
  .
SHOW_PAGE ROUTINE                                !DISPLAY THE PAGE
  NDX# = NDX                                     !  SAVE SCREEN INDEX
  LOOP NDX = 1 TO RECORDS(TABLE)                 !  LOOP THRU THE TABLE
    GET(TABLE,NDX)                               !    GET A TABLE ENTRY
    DO FILL_SCREEN                               !    AND DISPLAY IT
    IF TBL:PTR = NEWPTR                          !    SET INDEX FOR NEW RECORD
      NDX# = NDX                                 !    POINT TO CORRECT RECORD
      @DOTOTALS                                  !    CALCULATE TOTAL FIELDS
  . .
  NDX = NDX#                                     !  RESTORE SCREEN INDEX
  NEWPTR = 0                                     !  CLEAR NEW RECORD POINTER
  CLEAR(@PRE:RECORD)                             !  CLEAR RECORD AREA

FILL_TABLE ROUTINE                               !MOVE FILE TO TABLE
  @LOOKUPSCROLL                                  !  PERFORM LOOKUPS
  @FILLTABLE                                     !  LOAD TABLE FIELDS
  TBL:PTR = POINTER(@FILENAME)                   !  SAVE RECORD POINTER
  @COMPUTESCROLL                                 !  DO COMPUTES AND CONDITIONALS
  @RESULTSCROLL                                  !  MOVE RESULT FIELDS

FILL_RECORD ROUTINE                              !MOVE TABLE TO FILE
  @FILLRECORD                                    !  LOAD FILE KEYS

FILL_SCREEN ROUTINE                              !MOVE TABLE TO SCREEN
  @FILLSCREEN                                    !  DISPLAY SCREEN VARIABLES

GET_RECORD ROUTINE                               !GET SELECTED RECORD
  GET(TABLE,NDX)                                 !  GET TABLE ENTRY
  GET(@FILENAME,TBL:PTR)                         !  GET THE RECORD

  @COMPUTETOTS                                   !CALCULATE TOTAL FIELDS

!#------------
set_fst_lst routine                              !!Routine to set end pointers

  if action = 4 and ~lookup# then tmp_ptr# = pointer(@filename).
  save_rec = @pre:record                         !!Save Current Record

!#Get 1st Record Number
  clear(@pre:record,-1)                          !!Clear Record to Low Values
  @restselects                                   !!Restore Selector Fields
  set(@keyname,@keyname)                         !!Set Key
  loop until eof(@filename)                      !!Read First Record
    next(@filename)
    @checkselect                                 !!Check Selectors
    if ~(@filter) then cycle.                    !!Check Filters
    break
  .
  first_record = pointer(@filename)              !!Set pointer to first record

!#Get Last Record In Key
  clear(@pre:record,1)                           !!Clear Record to High Values
  @restselects                                   !!Restore Selector Fields
  set(@keyname,@keyname)                         !!Set Key
  loop until bof(@filename)                      !!Read Last Record
    previous(@filename)
    @checkselect                                 !!Check Selectors
    if ~(@filter) then cycle.                    !!Check Filters
    break
  .
  last_record = pointer(@filename)               !!Set pointer to last record
  totrecords = records(@filename)                !!Set total records counter
  if action = 4 and ~lookup#                     !! If this is a lookup request
     get(@filename,tmp_ptr#)                     !! Restore original record
     lookup# = true                              !! If this is first lookup
  .
  @pre:record = save_rec                         !!Restore record
!#--------------
