'***** PROGRAM TO CONVERT RAW DATA FILE CONTAINING VLCT BENCH TEST DATA ****
'*** INTO A MORE ORGANISED FORMAT FOR USE WITH THE MAIN VLCT SPREADSHEET ***

'This program converts the raw data file (filename.LOG) into a more organised
'file (filename.DAT). This file will be used to create an Excel file
'(filename.XLS) to improve the speed of data entry into the main VLCT
'spreadsheet, U:\PRODUCTS\VLCT.XLS.
'A temporary file, (filename.TMP) is used for file element swapping etc.

'*** Designer:              Pete Follon
'*** Date of first issue:   29.8.97


'*** Subprogram declarations
DECLARE SUB FinalMessage (GraphicParam AS ANY)
DECLARE SUB SeperateSNBlocks (VLCTParam AS ANY)
DECLARE SUB PrintDataFile (VLCTParam AS ANY, GraphicParam AS ANY)
DECLARE FUNCTION ModifyDate$ (DateToModify$)
DECLARE SUB FormatLines (VLCTParam AS ANY)
DECLARE SUB LoadSNArray (VLCTParam AS ANY, SerialNumberArray$())
DECLARE SUB AssignSNs (VLCTParam AS ANY, SerialNumberArray$())
DECLARE SUB FileDuplicateUpdate (VLCTParam AS ANY, LineToDelete%)
DECLARE SUB CompareTimes (TimeOfTest1$, TimeOfTest2$, OldestLine%)
DECLARE SUB CompareDates (DateOfTest1$, DateOfTest2$, OldestLine%)
DECLARE SUB Get2Lines (VLCTParam AS ANY, Line1%, Line2%)
DECLARE SUB GetOldestLine (VLCTParam AS ANY, OldestLine%)
DECLARE SUB EliminateDuplicates (VLCTParam AS ANY, SerialNumberArray$())
DECLARE SUB LoadFiles (VLCTParam AS ANY)
DECLARE SUB SortSerialNumbers (VLCTParam AS ANY, SerialNumberArray$())
DECLARE SUB GetNumberOfLines (VLCTParam AS ANY)
DECLARE SUB DisplayParams (VLCTParam AS ANY)
DECLARE SUB TemporaryMessage (GraphicParam AS ANY, Row%, Col%)
DECLARE FUNCTION VLCTScroller$ (Option$(), GraphicParam AS ANY)
DECLARE FUNCTION ScrollMenu1$ (GraphicParam AS ANY, VLCTParam AS ANY)
DECLARE SUB ViewPort (GraphicParam AS ANY, BoxNum%)
DECLARE SUB VLCTMenu1 (VLCTParam AS ANY, GraphicParam AS ANY)
DECLARE SUB GraphicsDefine (GraphicParam AS ANY)
DECLARE SUB MakeTile ()
DECLARE SUB ReadTempFile (VLCTParam AS ANY, LineNumber%)

'*** Record declarations
TYPE VLCTParams
    SerialNumber AS STRING * 8
    DateOfTest AS STRING * 10
    TimeOfTest AS STRING * 8
    TATtestA AS SINGLE              'Nominal TAT
    TATtestB AS SINGLE              'TAT with int'tion pulses closer by 0.95ms
    TATtestC AS SINGLE              'TAT with int'tion pulses further by 0.95ms
    TATtestD AS SINGLE              'TAT with int'tion freqs increased by 250Hz
    TATtestE AS SINGLE              'TAT with int'tion freqs decreased by 250Hz
    Current AS SINGLE
    TestStatus AS STRING * 4        'Pass or Fail
    OperatorInitials AS STRING * 4
    FaultReport AS STRING * 500     'Details of faults, if any
    RawLogFile AS STRING * 12       'File containing raw VLCT data (.LOG)
    RawLogPath AS STRING * 100      'Path containing .LOG file
    RawTempFile AS STRING * 12      'Temporary file containing raw data (.TMP)
    FormattedDataFile AS STRING * 12    'Formatted VLCT data (.DAT file)
    FormattedDataPath AS STRING * 100   'Path containing .DAT file & .TMP file
    ErrorMessage AS STRING * 40     'Error message to be displayed, if any
    NumberOfLines AS SINGLE         'Number of lines in .LOG file
END TYPE

TYPE GraphicParams
    Background AS INTEGER           'Background colour for text
    BoxBorder AS INTEGER            'Colour of Viewport border
    BoxShadow AS INTEGER            'Colour of Viewport shadow
    TextHi AS INTEGER               'Highlighted text
    TextLo AS INTEGER               'Non-highlighted text
    TextTitle AS INTEGER            'Colour of Menu Title
    TextCompattReply AS INTEGER     'Colour of Compatt reply
    TextChange AS INTEGER           'Colour of text to be changed by operator
    TextErrorNum AS INTEGER         'Colour of error number
    TextErrorMessage AS INTEGER     'Colour of error message text
    TextStatusTitle AS INTEGER      'Colour of "Status/Error Box"
    TextStatus AS INTEGER           'Colour of Status text
    TextPass AS INTEGER             'Colour of PASS text
    TextFail AS INTEGER             'Colour of FAIL text
    TextNTM AS INTEGER              'Colour of NO TEST MADE text
    TextIT AS INTEGER               'Colour of IGNORE TEST text

    ScrollRow AS INTEGER            'Row of scroll bar
    DescrColumn AS INTEGER          'Column for descriptive text in scroll
    DataColumn AS INTEGER           'Column for test result in scroll
    StatusErrorRow AS INTEGER       'Row of "Status/Error Box" & Error Number
    StatusErrorCol AS INTEGER       'Col of "Status/Error Box" & Error Number
    TestTextCol AS INTEGER          '1st Column for text in main Test viewport
    MainTestVPTopRow AS INTEGER     'Top row of Main Test viewport (for text)
    MainTestVPBottomRow AS INTEGER  'Bottom row of Main Test viewport

    ActiveViewport AS INTEGER       'Record of Viewport number prior to error

    MaxElementNum AS INTEGER
    MaxStringLen AS INTEGER
    MenuNum AS INTEGER
    ElementNum AS INTEGER
END TYPE

'*** Dimension records
DIM VLCTParam AS VLCTParams
DIM GraphicParam AS GraphicParams


'*** TESTING
VLCTParam.RawLogFile = "TEST1.LOG"
VLCTParam.RawLogPath = "C:\TESTS\VLCT"
VLCTParam.FormattedDataFile = "TEST1.DAT"
VLCTParam.FormattedDataPath = "C:\TESTS\VLCT"


'*** Start of program proper...

SCREEN 9, 0, 0

'*** Define colours and other screen parameters
CALL GraphicsDefine(GraphicParam)

'*** Generate background tiling
CALL MakeTile

'*** Define file parameters from Menu options
CALL VLCTMenu1(VLCTParam, GraphicParam)

'*** Determine the number of lines in the .LOG file
CALL GetNumberOfLines(VLCTParam)

'*** Copy contents of Log (.LOG) file to Temporary (.TMP) and Data (.DAT) files
CALL LoadFiles(VLCTParam)

'*** Assign an array to hold the list of Serial Number (including duplicates)
DIM SerialNumberArray$(VLCTParam.NumberOfLines)

'*** Load the Serial Number array
CALL LoadSNArray(VLCTParam, SerialNumberArray$())

'*** Sort the Serial Numbers into ascending order
CALL SortSerialNumbers(VLCTParam, SerialNumberArray$())

'*** Eliminate duplicate Serial Numbers
CALL EliminateDuplicates(VLCTParam, SerialNumberArray$())

'*** Re-dimension Serial Number Array to reflect the latest num of elements
REDIM SerialNumberArray$(VLCTParam.NumberOfLines)

'*** Re-load the Serial Number array. (This will not have any duplicates)
CALL LoadSNArray(VLCTParam, SerialNumberArray$())

'*** Sort the Serial Numbers into ascending order
CALL SortSerialNumbers(VLCTParam, SerialNumberArray$())

'*** Assign file line locations to Serial Numbers and write to Temp file
CALL AssignSNs(VLCTParam, SerialNumberArray$())

'*** Re-format Dat, remove Time, and add field prior to Fault Report
'*** for each line in the .DAT and .TMP files
CALL FormatLines(VLCTParam)

'*** TESTING
'CALL PrintDataFile(VLCTParam, GraphicParam)

'*** Add Work Order number before each block and separate blocks with
'*** a blank line
CALL SeperateSNBlocks(VLCTParam)

'*** Print confirmation of completion
CALL FinalMessage(GraphicParam)

END

'*** SUBPROGRAM TO ASSIGN FILE LINE LOCATIONS TO THE SERIAL NUMBER FIELDS ***
'
SUB AssignSNs (VLCTParam AS VLCTParams, SerialNumberArray$())

'*** Open Temp file to read
FullTempFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.RawTempFile)
TempFile% = FREEFILE
OPEN FullTempFile$ FOR INPUT AS #TempFile%

'*** Open Data file to write to
FullDataFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.FormattedDataFile)
DataFile% = FREEFILE
OPEN FullDataFile$ FOR OUTPUT AS #DataFile%

'*** Write the Serial Numbers etc to the Data file in chronological order
FOR DataFileLineNum% = 1 TO VLCTParam.NumberOfLines
    FOR TempFileLineNum% = 1 TO VLCTParam.NumberOfLines
        INPUT #TempFile%, VLCTParam.SerialNumber, b$, c$, d!, e!, f!, g!, h!, i!, j$, k$, l$
        IF VLCTParam.SerialNumber = SerialNumberArray$(DataFileLineNum%) THEN
            WRITE #DataFile%, VLCTParam.SerialNumber, b$, c$, d!, e!, f!, g!, h!, i!, j$, k$, l$
        END IF
    NEXT TempFileLineNum%
   
    '*** Go to start of the Temp file
    SEEK #TempFile%, 1

NEXT DataFileLineNum%

CLOSE #TempFile%
CLOSE #DataFile%


'*** Now write the modified file back into the Temp (.TMP) file
'*** Open Data file to read
FullDataFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.FormattedDataFile)
DataFile% = FREEFILE
OPEN FullDataFile$ FOR INPUT AS #DataFile%

'*** Open Temp file to write to
FullTempFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.RawTempFile)
TempFile% = FREEFILE
OPEN FullTempFile$ FOR OUTPUT AS #TempFile%

FOR x% = 1 TO VLCTParam.NumberOfLines
    INPUT #DataFile%, a$, b$, c$, d!, e!, f!, g!, h!, i!, j$, k$, l$
    WRITE #TempFile%, a$, b$, c$, d!, e!, f!, g!, h!, i!, j$, k$, l$
NEXT x%

CLOSE #TempFile%
CLOSE #DataFile%

END SUB

'**************** SUBPROGRAM TO CHECK THE ENTERED PARAMETERS ***************
'
SUB CheckEntry (VLCTParam AS VLCTParams, GraphicParam AS GraphicParams)

'Checks the entry made by the operator.
'If invalid, returns the number of the Menu in which the data is invalid
'(GraphicParam.MenuNum), together with an error message,
'VLCTParam.ErrorMessage.
'GraphicParam.ElementNum is the menu element which will be highlighted
'if invalid.

VLCTParam.ErrorMessage = ""

'*** Check entry for Test Results Filename      - TO BE WRITTEN

'*** Check entry for Path of Test Results File  - TO BE WRITTEN

END SUB

'************* SUBPROGRAM TO DETERMINE THE OLDER OF TWO DATES ***************
'
SUB CompareDates (DateOfTest1$, DateOfTest2$, OldestLine%)

'OldestLine% = 0: Identical dates
'OldestLine% = 1: Oldest date is Line 1
'OldestLine% = 2: Oldest date is Line 2

'*** Check Year
IF RIGHT$(DateOfTest1$, 4) <> RIGHT$(DateOfTest2$, 4) THEN
        IF RIGHT$(DateOfTest1$, 4) < RIGHT$(DateOfTest2$, 4) THEN
                OldestLine% = 1
            ELSE
                OldestLine% = 2
        END IF
    ELSE
        OldestLine% = 0
END IF

'*** Check Month if Years are identical
IF OldestLine% = 0 THEN
    IF LEFT$(DateOfTest1$, 2) <> LEFT$(DateOfTest2$, 2) THEN
            IF LEFT$(DateOfTest1$, 2) < LEFT$(DateOfTest2$, 2) THEN
                    OldestLine% = 1
                ELSE
                    OldestLine% = 2
            END IF
        ELSE
            OldestLine% = 0
    END IF
END IF

'*** Check Day if Years and Months are identical
IF OldestLine% = 0 THEN
    IF MID$(DateOfTest1$, 4, 2) <> MID$(DateOfTest2$, 4, 2) THEN
            IF MID$(DateOfTest1$, 4, 2) < MID$(DateOfTest2$, 4, 2) THEN
                    OldestLine% = 1
                ELSE
                    OldestLine% = 2
            END IF
        ELSE
            OldestLine% = 0
    END IF
END IF

END SUB

'************* SUBPROGRAM TO DETERMINE THE OLDER OF TWO TIMES ***************
'
SUB CompareTimes (TimeOfTest1$, TimeOfTest2$, OldestLine%)

'OldestLine% = 0: Identical times
'OldestLine% = 1: Oldest time is Line 1
'OldestLine% = 2: Oldest time is Line 2

'*** Check Hours
IF LEFT$(TimeOfTest1$, 2) <> LEFT$(TimeOfTest2$, 2) THEN
        IF LEFT$(TimeOfTest1$, 2) < LEFT$(TimeOfTest2$, 2) THEN
                OldestLine% = 1
            ELSE
                OldestLine% = 2
        END IF
    ELSE
        OldestLine% = 0
END IF

'*** Check Minutes, if Hours are identical
IF OldestLine% = 0 THEN
    IF MID$(TimeOfTest1$, 4, 2) <> MID$(TimeOfTest2$, 4, 2) THEN
            IF MID$(TimeOfTest1$, 4, 2) < MID$(TimeOfTest2$, 4, 2) THEN
                    OldestLine% = 1
                ELSE
                    OldestLine% = 2
            END IF
        ELSE
            OldestLine% = 0
    END IF
END IF

'*** Check Seconds, if Hours and Minutes are identical
IF OldestLine% = 0 THEN
    IF RIGHT$(TimeOfTest1$, 2) <> RIGHT$(TimeOfTest2$, 2) THEN
            IF RIGHT$(TimeOfTest1$, 2) < RIGHT$(TimeOfTest2$, 2) THEN
                    OldestLine% = 1
                ELSE
                    OldestLine% = 2
            END IF
        ELSE
            OldestLine% = 0
    END IF
END IF

END SUB

'*************** SUBPROGRAM TO DISPLAY VLCT FILE PARAMETERS **************
'
SUB DisplayParams (VLCTParam AS VLCTParams)

PRINT VLCTParam.SerialNumber
PRINT VLCTParam.DateOfTest
PRINT VLCTParam.TimeOfTest
PRINT VLCTParam.TATtestA
PRINT VLCTParam.TATtestB
PRINT VLCTParam.TATtestC
PRINT VLCTParam.TATtestD
PRINT VLCTParam.TATtestE
PRINT VLCTParam.Current
PRINT VLCTParam.TestStatus
PRINT VLCTParam.OperatorInitials
PRINT RTRIM$(VLCTParam.FaultReport)

END SUB

'*********** SUBPROGRAM TO ELIMINATE DUPLICATE SERIAL NUMBERS **************
'
SUB EliminateDuplicates (VLCTParam AS VLCTParams, SerialNumberArray$())

'If duplicate Serial Numbers are present, only the latest entry will be saved.
'Remember, that the Serial Numbers have already been sorted into ascending
'order at this stage.

'*** Keep a record of the original number of lines in the Temp & Data files
OriginalNumOfLines% = VLCTParam.NumberOfLines

'*** Compare adjacent lines. If identical S/Ns, then delete that line
'*** from the Temp (.TMP) file
x% = 0
DO
    x% = x% + 1

    IF SerialNumberArray$(x%) = SerialNumberArray$(x% + 1) THEN
       
        VLCTParam.SerialNumber = SerialNumberArray$(x%)

        '*** Return the older of the two lines according to date & time
        CALL GetOldestLine(VLCTParam, OldestLine%)

        '*** Re-write parameters to the Temp file, without the oldest
        '*** identical line.
        '*** (VLCTParam.NumberOfLines is decremented in this procedure).
        CALL FileDuplicateUpdate(VLCTParam, OldestLine%)

    END IF

LOOP UNTIL x% = (OriginalNumOfLines% - 1)

END SUB

'************* SUBPROGRAM TO ENTER A STRING WITH ERROR CHECKING ************
'
SUB EnterString (GraphicParam AS GraphicParams, StringVar$, Max%, Row%, Col%)

COLOR GraphicParam.TextChange, GraphicParam.Background

DO
    '*** Clear the viewport
    CLS 1

    '*** Flush the keyboard buffer
    DO: LOOP UNTIL INKEY$ = ""

    '*** Print entering-instructions to operator
    LOCATE (Row% - 1), Col%
    PRINT " Enter new value (Upto"; Max%; "characters):"
  
    '*** Assign the default value to InStr$ and determine num of characters
    InStr$ = RTRIM$(LTRIM$(StringVar$))
    NumOfChars% = LEN(InStr$)

    '*** Get each character input individually to ensure that the maximum
    '*** number of characters is not exceeded
    LOCATE CSRLIN, (Col% + 5)
    PRINT InStr$;
    InputRow% = CSRLIN: InputCol% = POS(0)
    DO
        '*** Get Character
        DO
            KeyPress$ = INKEY$
        LOOP UNTIL KeyPress$ <> ""

        '*** Concatonate characters and print if not <CR> or backspace
        IF ((ASC(KeyPress$) <> 13) AND (ASC(KeyPress$) <> 8)) THEN
            InStr$ = InStr$ + KeyPress$
            LOCATE InputRow%, InputCol%
            PRINT KeyPress$;
            InputRow% = CSRLIN: InputCol% = POS(0)
            NumOfChars% = NumOfChars% + 1
        END IF
    
        '*** Print a running tally of characters entered, unless backspace pressed.
        '*** If backspace pressed, then reprint minus the right character,
        '*** assuming a character exists
        IF (ASC(KeyPress$) = 8) AND (NumOfChars% > 0) THEN
                
            '*** Clear the viewport
            CLS 1

            '*** Flush the keyboard buffer
            DO: LOOP UNTIL INKEY$ = ""

            '*** Print entering-instructions to operator
            LOCATE (Row% - 1), Col%
            PRINT " Enter new value (Upto"; Max%; "characters):"

            '*** Strip the right-most character form InStr$, & re-print
            InStr$ = LEFT$(InStr$, LEN(InStr$) - 1)
            LOCATE CSRLIN, (Col% + 5)
            PRINT InStr$;
            InputRow% = CSRLIN: InputCol% = POS(0)

            '*** Update unmber of chracters
            NumOfChars% = NumOfChars% - 1

        END IF

        '*** Print a running tally of the number of chars. entered
        LOCATE (Row% + 1), Col%
        PRINT NumOfChars%

    LOOP UNTIL (NumOfChars% > Max%) OR (ASC(KeyPress$) = 13)

LOOP UNTIL ASC(KeyPress$) = 13

'*** Providing operator did not hit <CR> first, assign new value to variable
IF LEN(InStr$) > 0 THEN StringVar$ = InStr$

'*** Clear the viewport
CLS 1

END SUB

' READ THE TEMP (.tmp) FILE AND THEN WRITE BACK WITHOUT LINE, LineToDelete%
'
SUB FileDuplicateUpdate (VLCTParam AS VLCTParams, LineToDelete%)

'*** Open Temp file to read
FullTempFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.RawTempFile)
TempFile% = FREEFILE
OPEN FullTempFile$ FOR INPUT AS #TempFile%

'*** Open Data file to write to
FullDataFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.FormattedDataFile)
DataFile% = FREEFILE
OPEN FullDataFile$ FOR OUTPUT AS #DataFile%

FOR x% = 1 TO VLCTParam.NumberOfLines
    INPUT #TempFile%, a$, b$, c$, d!, e!, f!, g!, h!, i!, j$, k$, l$

    '*** Do not write into Data file the line to delete
    IF LineToDelete% <> x% THEN
        WRITE #DataFile%, a$, b$, c$, d!, e!, f!, g!, h!, i!, j$, k$, l$
    END IF
NEXT x%

CLOSE #TempFile%
CLOSE #DataFile%

'*** Now write the modified file back into the Temp (.TMP) file
VLCTParam.NumberOfLines = VLCTParam.NumberOfLines - 1

'*** Open Data file to read
FullDataFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.FormattedDataFile)
DataFile% = FREEFILE
OPEN FullDataFile$ FOR INPUT AS #DataFile%

'*** Open Temp file to write to
FullTempFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.RawTempFile)
TempFile% = FREEFILE
OPEN FullTempFile$ FOR OUTPUT AS #TempFile%

FOR x% = 1 TO VLCTParam.NumberOfLines
    INPUT #DataFile%, a$, b$, c$, d!, e!, f!, g!, h!, i!, j$, k$, l$
    WRITE #TempFile%, a$, b$, c$, d!, e!, f!, g!, h!, i!, j$, k$, l$
NEXT x%

CLOSE #TempFile%
CLOSE #DataFile%

END SUB

'**************** SUBPROGRAM TO DISPLAY A FINAL MESSAGE *******************
'
SUB FinalMessage (GraphicParam AS GraphicParams)

Row% = 22
Col% = 16

'*** Clear the viewport
CLS 1

'*** Flush the keyboard buffer
DO: LOOP UNTIL INKEY$ = ""

LOCATE Row%, Col%
COLOR 4, GraphicParam.Background
PRINT "OPERATION COMPLETE"

LOCATE (CSRLIN + 1), Col% + 26
PRINT "Press any key to continue...";

'*** Wait for keypress
DO: LOOP UNTIL INKEY$ <> ""

'*** Return to full screen co-ordinates and default colour
VIEW
CLS 0
COLOR 7, 0

END SUB

'***** SUBPROGRAM TO RE-FORMAT THE DATE STRING, REMOVE THE TIME STRING *****
'***** AND ADD AN EXTRA FIELD PRIOR TO THE FAULT REPORT, FOR EACH LINE *****
'************* IN THE DATA (.DAT) AND TEMPORARY (.TMP) FILES ***************
'
SUB FormatLines (VLCTParam AS VLCTParams)

'*** Open Temp file to read
FullTempFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.RawTempFile)
TempFile% = FREEFILE
OPEN FullTempFile$ FOR INPUT AS #TempFile%

'*** Open Data file to write to
FullDataFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.FormattedDataFile)
DataFile% = FREEFILE
OPEN FullDataFile$ FOR OUTPUT AS #DataFile%

'*** Read each line from Temp file in turn, modify & write to Data file
FOR x% = 1 TO VLCTParam.NumberOfLines
    INPUT #TempFile%, a$, VLCTParam.DateOfTest, VLCTParam.TimeOfTest, d!, e!, f!, g!, h!, i!, j$, k$, l$
   
    '*** Modify the Date string
    ModifiedDate$ = ModifyDate$((VLCTParam.DateOfTest))

    WRITE #DataFile%, a$, ModifiedDate$, d!, e!, f!, g!, h!, i!, j$, k$, "", l$
NEXT x%

CLOSE #TempFile%
CLOSE #DataFile%


'*** Now write the modified file back into the Temp (.TMP) file
'*** Open Data file to read
FullDataFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.FormattedDataFile)
DataFile% = FREEFILE
OPEN FullDataFile$ FOR INPUT AS #DataFile%

'*** Open Temp file to write to
FullTempFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.RawTempFile)
TempFile% = FREEFILE
OPEN FullTempFile$ FOR OUTPUT AS #TempFile%

FOR x% = 1 TO VLCTParam.NumberOfLines
    INPUT #DataFile%, a$, b$, d!, e!, f!, g!, h!, i!, j$, k$, l$, m$
    WRITE #TempFile%, a$, b$, d!, e!, f!, g!, h!, i!, j$, k$, l$, m$
NEXT x%

CLOSE #TempFile%
CLOSE #DataFile%

END SUB

'*********** SUBPROGRAM TO RETURN THE FIRST TWO LINE NUMBERS ***************
'*************** WHOSE SERIAL NUMBER FIELDS ARE IDENTICAL ******************
'
SUB Get2Lines (VLCTParam AS VLCTParams, Line1%, Line2%)

'*** Open Temp file to read
FullTempFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.RawTempFile)
TempFile% = FREEFILE
OPEN FullTempFile$ FOR INPUT AS #TempFile%

SerNumCount% = 0
LineNumber% = 0
DO
    '*** Increment line number
    LineNumber% = LineNumber% + 1

    '*** Read VLCT data
    INPUT #TempFile%, a$, b$, c$, d!, e!, f!, g!, h!, i!, j$, k$, l$

    '*** Look for the Serial Number in question (twice)
    IF a$ = VLCTParam.SerialNumber THEN
        SerNumCount% = SerNumCount% + 1
        IF SerNumCount% = 1 THEN Line1% = LineNumber%
        IF SerNumCount% = 2 THEN Line2% = LineNumber%
    END IF

LOOP UNTIL SerNumCount% = 2

CLOSE #TempFile%

END SUB

'****** SUBPROGRAM TO DETERMINE THE NUMBER OF LINES IN THE .LOG FILE *******
'
SUB GetNumberOfLines (VLCTParam AS VLCTParams)

'*** Open Log file to read
FullLogFile$ = RTRIM$(VLCTParam.RawLogPath) + "\" + RTRIM$(VLCTParam.RawLogFile)
LogFile% = FREEFILE
OPEN FullLogFile$ FOR INPUT AS #LogFile%

'*** Determine the number of lines
VLCTParam.NumberOfLines = 0
DO UNTIL EOF(LogFile%)
    INPUT #LogFile%, a$, b$, c$, d!, e!, f!, g!, h!, i!, j$, k$, l$
    VLCTParam.NumberOfLines = VLCTParam.NumberOfLines + 1
LOOP

'*** TESTING
'PRINT "Number of lines ="; VLCTParam.NumberOfLines
'DO: LOOP UNTIL INKEY$ <> ""

CLOSE #LogFile%

END SUB

'************* SUBPROGRAM TO RETURN THE OLDER OF TWO LINES ***************
'***************** WHOSE SERIAL NUMBERS ARE IDENTICAL ********************
'
SUB GetOldestLine (VLCTParam AS VLCTParams, OldestLine%)

'*** Return the first two lines found with the same Serial Numbers
CALL Get2Lines(VLCTParam, Line1%, Line2%)

'*** Get the Date & time for each line
CALL ReadTempFile(VLCTParam, Line1%)
DateOfTest1$ = VLCTParam.DateOfTest
TimeOfTest1$ = VLCTParam.TimeOfTest
CALL ReadTempFile(VLCTParam, Line2%)
DateOfTest2$ = VLCTParam.DateOfTest
TimeOfTest2$ = VLCTParam.TimeOfTest

'*** TESTING
'PRINT "Date of Test 1 = "; DateOfTest1$
'PRINT "Time of Test 1 = "; TimeOfTest1$
'PRINT "Date of Test 2 = "; DateOfTest2$
'PRINT "Time of Test 2 = "; TimeOfTest2$

'*** Check the dates. (OldestLine% = 0 for identical dates)
CALL CompareDates(DateOfTest1$, DateOfTest2$, OldestLine%)

'*** Check the times if dates identical. (OldestLine% = 0 for identical times)
IF OldestLine% = 0 THEN
    CALL CompareTimes(TimeOfTest1$, TimeOfTest2$, OldestLine%)
END IF

'*** TESTING
'PRINT "Oldest line = Line"; OldestLine%

'*** In the unlikely case that every time parameter is identical,
'*** then take the first line as the oldest
IF (OldestLine% = 0) OR (OldestLine% = 1) THEN
        OldestLine% = Line1%
    ELSE
        OldestLine% = Line2%
END IF

END SUB

'*************** SUBPROGRAM TO ASSIGN COLOURS & OTHER PARAMETERS ************
'
SUB GraphicsDefine (GraphicParam AS GraphicParams)

GraphicParam.TextHi = 14            'Yellow
GraphicParam.TextLo = 8             'Grey
GraphicParam.TextTitle = 1          'Blue
GraphicParam.TextChange = 8         'Grey
GraphicParam.TextErrorNum = 14      'Yellow
GraphicParam.TextErrorMessage = 8   'Grey
GraphicParam.TextStatusTitle = 15   'High Intensity White
GraphicParam.TextCompattReply = 4   'Red
GraphicParam.TextStatus = 8         'Grey
GraphicParam.TextPass = 9           'Light Blue
GraphicParam.TextFail = 4           'Red
GraphicParam.TextNTM = 15           'High Intensity White
GraphicParam.TextIT = 3             'Cyan
GraphicParam.Background = 7         'Dull White
GraphicParam.BoxBorder = 15         'High Intensity White
GraphicParam.BoxShadow = 8          'Grey

GraphicParam.StatusErrorRow = 19
GraphicParam.StatusErrorCol = 11

GraphicParam.MainTestVPTopRow = 3
GraphicParam.MainTestVPBottomRow = 16
GraphicParam.TestTextCol = 20

END SUB

'*** WRITE THE CONTENTS OF THE LOG (.LOG) FILE TO A TEMPORARY (.TMP) FILE ***
'*********************** AND THE DATA FILE (.DAT) ***************************
'
SUB LoadFiles (VLCTParam AS VLCTParams)

'Also copy the contents to the Data (.DAT) file

'*** Cut off the .LOG extension from the raw log file and replace with .TMP
TrimmedFile$ = RTRIM$(VLCTParam.RawLogFile)
MainFilename$ = LEFT$(TrimmedFile$, (LEN(TrimmedFile$) - 4))
VLCTParam.RawTempFile = MainFilename$ + ".TMP"

'*** Open Temp file to write to
FullTempFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.RawTempFile)
TempFile% = FREEFILE
OPEN FullTempFile$ FOR OUTPUT AS #TempFile%

'*** Open Data file to write to
FullDataFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.FormattedDataFile)
DataFile% = FREEFILE
OPEN FullDataFile$ FOR OUTPUT AS #DataFile%

'*** Open Log file to read
FullLogFile$ = RTRIM$(VLCTParam.RawLogPath) + "\" + RTRIM$(VLCTParam.RawLogFile)
LogFile% = FREEFILE
OPEN FullLogFile$ FOR INPUT AS #LogFile%

'*** Read from Log file & write to Temp file
FOR x% = 1 TO VLCTParam.NumberOfLines
    INPUT #LogFile%, a$, b$, c$, d!, e!, f!, g!, h!, i!, j$, k$, l$
    WRITE #TempFile%, a$, b$, c$, d!, e!, f!, g!, h!, i!, j$, k$, l$
    WRITE #DataFile%, a$, b$, c$, d!, e!, f!, g!, h!, i!, j$, k$, l$
NEXT x%

CLOSE #LogFile%
CLOSE #TempFile%
CLOSE #DataFile%

END SUB

'** SUBPROGRAM TO LOAD ARRAY, SerialNumberArray$() WITH THE SERAIL NUMBER **
'*************** FROM EACH LINE OF THE TEMPORRY (.TMP) FILE ****************
'
SUB LoadSNArray (VLCTParam AS VLCTParams, SerialNumberArray$())

FOR x% = 1 TO VLCTParam.NumberOfLines
    CALL ReadTempFile(VLCTParam, x%)
    SerialNumberArray$(x%) = VLCTParam.SerialNumber

    '*** TESTING
    'PRINT SerialNumberArray$(x%)

NEXT x%

END SUB

'************** SUBPROGRAM TO GENERATE BACKGROUND TILING *****************
'
SUB MakeTile

VIEW
CLS

LINE (1, 1)-(639, 349), 1, B

Row1$ = CHR$(&HFF) + CHR$(&HFF) + CHR$(&HFF) + CHR$(&H0)
Row2$ = CHR$(&HFF) + CHR$(&HFE) + CHR$(&HFE) + CHR$(&H7E)
Row3$ = CHR$(&HFF) + CHR$(&HFC) + CHR$(&HFC) + CHR$(&H3E)
Row4$ = CHR$(&HFF) + CHR$(&HF8) + CHR$(&HF8) + CHR$(&H1E)
Row5$ = CHR$(&HFF) + CHR$(&HF0) + CHR$(&HF0) + CHR$(&HE)
Row6$ = CHR$(&HFF) + CHR$(&HF8) + CHR$(&HF8) + CHR$(&H6)
Row7$ = CHR$(&HFF) + CHR$(&HFC) + CHR$(&HFC) + CHR$(&H2)
Row8$ = CHR$(&HFF) + CHR$(&H80) + CHR$(&H80) + CHR$(&H0)

Tile$ = Row1$ + Row2$ + Row3$ + Row4$ + Row5$ + Row6$ + Row7$ + Row8$

PAINT (5, 5), Tile$

END SUB

'******** FUNCTION TO RETURN THE DATE STRING IN A DIFFERENT FORMAT *********
'
FUNCTION ModifyDate$ (DateToModify$)

'The date reported by the PC (mm-dd-yyyy) is to be changed to dd/mm/yyyy

DayStr$ = MID$(DateToModify$, 4, 2)
Month$ = LEFT$(DateToModify$, 2)
YearStr$ = RIGHT$(DateToModify$, 4)

ModifyDate$ = DayStr$ + "/" + Month$ + "/" + YearStr$

END FUNCTION

'***** SUBPROGRAM TO PRINT THE CONTENTS OF THE DATA FILE (TESTING ONLY) *****
'
SUB PrintDataFile (VLCTParam AS VLCTParams, GraphicParam AS GraphicParams)

CLS 0
COLOR GraphicParam.TextLo, GraphicParam.Background

'*** Open Data file to read
FullDataFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.FormattedDataFile)
DataFile% = FREEFILE
OPEN FullDataFile$ FOR INPUT AS #DataFile%

FOR x% = 1 TO VLCTParam.NumberOfLines
    INPUT #DataFile%, a$, b$, d!, e!, f!, g!, h!, i!, j$, k$, l$, m$
    PRINT a$; " "; b$; " "; d!; " "; e!; " "; f!; " "; g!; " "; h!; " ";
    PRINT i!; " "; j$; " "; k$; " "; l$; " "; m$
NEXT x%

CLOSE #DataFile%

END SUB

'*************** SUBPROGRAM TO READ THE CONTENTS OF ONE LINE **************
'******************** OF THE RAW TEMP FILE (FILENAME.TMP) ******************
'
SUB ReadTempFile (VLCTParam AS VLCTParams, LineNumber%)

'LineNumber% = line number of the file required to be read

'*** Open Temp file to read
FullTempFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.RawTempFile)
TempFile% = FREEFILE
OPEN FullTempFile$ FOR INPUT AS #TempFile%

FOR x% = 1 TO LineNumber%

    '*** Read VLCT data
    INPUT #TempFile%, a$, b$, c$, d!, e!, f!, g!, h!, i!, j$, k$, l$

    '*** Assign single character variable names to proper names
    VLCTParam.SerialNumber = a$
    VLCTParam.DateOfTest = b$
    VLCTParam.TimeOfTest = c$
    VLCTParam.TATtestA = d!
    VLCTParam.TATtestB = e!
    VLCTParam.TATtestC = f!
    VLCTParam.TATtestD = g!
    VLCTParam.TATtestE = h!
    VLCTParam.Current = i!
    VLCTParam.TestStatus = j$
    VLCTParam.OperatorInitials = k$
    VLCTParam.FaultReport = l$
NEXT x%

CLOSE #TempFile%

END SUB

'****************************** MENU 1 OPTIONS ******************************
'
FUNCTION ScrollMenu1$ (GraphicParam AS GraphicParams, VLCTParam AS VLCTParams)

GraphicParam.ScrollRow = 3
GraphicParam.DescrColumn = 10

GraphicParam.MaxElementNum = 14
REM $DYNAMIC
DIM Option$(GraphicParam.MaxElementNum)
Option$(0) = " VLCT File Parameters                         <CR> to Change..."
Option$(1) = " "
Option$(2) = " 1. Raw Data filename                  " + RTRIM$(VLCTParam.RawLogFile)
Option$(3) = " 2. Raw Data file path                 " + RTRIM$(VLCTParam.RawLogPath)
Option$(4) = " 3. Formatted Data filename            " + RTRIM$(VLCTParam.FormattedDataFile)
Option$(5) = " 4. Formatted Data file path           " + RTRIM$(VLCTParam.FormattedDataPath)
Option$(6) = " "
Option$(7) = " "
Option$(8) = " "
Option$(9) = " "
Option$(10) = " "
Option$(11) = " "
Option$(12) = " "
Option$(13) = " "
Option$(14) = " Quit"

'***Display and select
ScrollMenu1$ = VLCTScroller$(Option$(), GraphicParam)

ERASE Option$

END FUNCTION

REM $STATIC
'***** SUBPROGRAM TO SEPERATE BLOCKS OF SERIAL NUMBERS IN THE DATA FILE *****
'************ AND HEAD EACH BLOCK WITH THE WORKS ORDER NUMBER ***************
'
SUB SeperateSNBlocks (VLCTParam AS VLCTParams)

'*** Open Temp file to read
FullTempFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.RawTempFile)
TempFile% = FREEFILE
OPEN FullTempFile$ FOR INPUT AS #TempFile%

'*** Open Data file to write to
FullDataFile$ = RTRIM$(VLCTParam.FormattedDataPath) + "\" + RTRIM$(VLCTParam.FormattedDataFile)
DataFile% = FREEFILE
OPEN FullDataFile$ FOR OUTPUT AS #DataFile%

'*** Read each Serial Number from the Temp file and update the Data file
PreviousWONumber$ = ""
FOR x% = 1 TO VLCTParam.NumberOfLines
    INPUT #TempFile%, VLCTParam.SerialNumber, b$, d!, e!, f!, g!, h!, i!, j$, k$, l$, m$

    '*** Extract the Works Order number
    WONumber$ = LEFT$(VLCTParam.SerialNumber, 5)

    '*** If the most recently read W.O. number is different to the one
    '*** before, then start a new W.O. block in the Data (.DAT) file.
    IF WONumber$ <> PreviousWONumber$ THEN
        WRITE #DataFile%, "", "", "", "", "", "", "", "", "", "", "", ""
        WRITE #DataFile%, WONumber$, "", "", "", "", "", "", "", "", "", "", ""
    END IF

    '*** Copy the data line
    WRITE #DataFile%, VLCTParam.SerialNumber, b$, d!, e!, f!, g!, h!, i!, j$, k$, l$, m$

    PreviousWONumber$ = WONumber$
NEXT x%

CLOSE #TempFile%
CLOSE #DataFile%

END SUB

'*************** SORT SERIAL NUMBERS INTO ASCENDING ORDER ****************
'
SUB SortSerialNumbers (VLCTParam AS VLCTParams, SerialNumberArray$())

'*** Sort the Serial Numbers in ascending order
FOR x% = 1 TO (VLCTParam.NumberOfLines - 1)
    FOR y% = (x% + 1) TO VLCTParam.NumberOfLines
        IF SerialNumberArray$(y%) < SerialNumberArray$(x%) THEN
            TempStr$ = SerialNumberArray$(y%)
            FOR z% = (y% - 1) TO x% STEP -1
                SerialNumberArray$(z% + 1) = SerialNumberArray$(z%)
            NEXT z%
            SerialNumberArray$(x%) = TempStr$
        END IF
    NEXT y%
NEXT x%

'*** TESTING
'PRINT
'FOR x% = 1 TO VLCTParam.NumberOfLines
'    PRINT SerialNumberArray$(x%)
'NEXT x%

END SUB

'********* SUBPROGRAM TO DISPLAY A MESSAGE IN THE BOTTOM WINDOW **********
'
SUB TemporaryMessage (GraphicParam AS GraphicParams, Row%, Col%)

'*** Flush the keyboard buffer
DO: LOOP UNTIL INKEY$ = ""

'*** Clear bottom window
CLS 1

COLOR GraphicParam.TextLo, GraphicParam.Background

'*** Print text in bottom window
LOCATE Row%, Col%
PRINT " This parameter is fixed for the time being"
LOCATE (CSRLIN + 1), (Col% + 35)
PRINT "Press any key to continue...";

'*** Wait for keypress
DO: LOOP UNTIL INKEY$ <> ""

'*** Clear bottom window
CLS 1

END SUB

'*** SUBPROGRAM TO DRAW ONE OF THREE GRAPHICS VIEW PORTS IN SCREEN 9 MODE ***
'
SUB ViewPort (GraphicParam AS GraphicParams, BoxNum%)

'BoxNum% = 1, 2, 3, & 4 - number of the View Port to be drawn.

'*** Assign BoxNum% to GraphicParam.ActiveViewport so that if an error
'*** occurs, SUB ErrorSub can print the error in the bottom box
'*** then re-assign the Viewport to the BoxNum% just prior to the error.
GraphicParam.ActiveViewport = BoxNum%

'*** Assign arrays to define the dimensions of 3 Graphics View Ports
DIM TopTextRow%(1 TO 4)
DIM BottomTextRow%(1 TO 4)
DIM LeftTextColumn%(1 TO 4)
DIM RightTextColumn%(1 TO 4)

'*** Define the dimensions of the Graphics View Ports
'*** View Port #1
TopTextRow%(1) = 2
BottomTextRow%(1) = 18
LeftTextColumn%(1) = 10
RightTextColumn%(1) = 72

'*** View Port #2
TopTextRow%(2) = 21
BottomTextRow%(2) = 24
LeftTextColumn%(2) = 10
RightTextColumn%(2) = 72

'*** View Port #3
TopTextRow%(3) = 14
BottomTextRow%(3) = 17
LeftTextColumn%(3) = 40
RightTextColumn%(3) = 61

'*** View Port #4
TopTextRow%(4) = 14
BottomTextRow%(4) = 17
LeftTextColumn%(4) = 56
RightTextColumn%(4) = 63

'*** Draw View Port Shadows
ShadowOffset% = 5
LeftPixcel% = ((((LeftTextColumn%(BoxNum%) - 1) * 8)) - 4) + ShadowOffset%
RightPixcel% = ((RightTextColumn%(BoxNum%) * 8) + 4) + ShadowOffset%
TopPixelRow% = (((TopTextRow%(BoxNum%) - 1) * 14) - 2) + ShadowOffset%
BottomPixelRow% = ((BottomTextRow%(BoxNum%) * 14)) + ShadowOffset%
VIEW SCREEN (LeftPixcel%, TopPixelRow%)-(RightPixcel%, BottomPixelRow%), GraphicParam.BoxShadow, GraphicParam.BoxShadow

'*** Draw View Ports
LeftPixcel% = (((LeftTextColumn%(BoxNum%) - 1) * 8)) - 4
RightPixcel% = (RightTextColumn%(BoxNum%) * 8) + 4
TopPixelRow% = ((TopTextRow%(BoxNum%) - 1) * 14) - 2
BottomPixelRow% = (BottomTextRow%(BoxNum%) * 14)
VIEW SCREEN (LeftPixcel%, TopPixelRow%)-(RightPixcel%, BottomPixelRow%), GraphicParam.Background, GraphicParam.BoxBorder

END SUB

'******************* SUBPROGRAM TO SELECT THE MENU OPTION ******************
'
SUB VLCTMenu1 (VLCTParam AS VLCTParams, GraphicParam AS GraphicParams)

Row% = 22
Col% = 10

GraphicParam.MenuNum = 1
GraphicParam.ElementNum = 2
  
DO UNTIL GraphicParam.MenuNum <> 1

    '*** Draw a Main Menu viewport
    CALL MakeTile
    CALL ViewPort(GraphicParam, 1)

    '*** Draw a viewport for changes.
    '*** This clears the viewport. If an error message if being displayed,
    '*** then do not clear
    'IF LEN(CompattParam.ErrorMessage) = 0 THEN CALL ViewPort(GraphicParam, 2)
    CALL ViewPort(GraphicParam, 2)
  
    '*** Flush the keyboard buffer.
    DO: LOOP UNTIL INKEY$ = ""

    Instruction$ = ScrollMenu1$(GraphicParam, VLCTParam)

    SELECT CASE LEFT$(Instruction$, 3)
        CASE " 1."
            GraphicParam.ElementNum = 3
            'CALL EnterString(GraphicParam, VLCTParam.RawLogFile, 12, Row%, Col%)
            'CALL CheckParamEntry(VLCTParam, GraphicParam)
            CALL TemporaryMessage(GraphicParam, Row%, Col%)
        CASE " 2."
            GraphicParam.ElementNum = 4
            'CALL EnterString(GraphicParam, VLCTParam.RawLogPath, 40, Row%, Col%)
            'CALL CheckParamEntry(VLCTParam, GraphicParam)
            CALL TemporaryMessage(GraphicParam, Row%, Col%)
        CASE " 3."
            GraphicParam.ElementNum = 5
            'CALL EnterString(GraphicParam, VLCTParam.FormattedDataFile, 12, Row%, Col%)
            'CALL CheckParamEntry(VLCTParam, GraphicParam)
            CALL TemporaryMessage(GraphicParam, Row%, Col%)
        CASE " 4."
            GraphicParam.ElementNum = 14
            'CALL EnterString(GraphicParam, VLCTParam.FormattedDataPath, 40, Row%, Col%)
            'CALL CheckParamEntry(VLCTParam, GraphicParam)
            CALL TemporaryMessage(GraphicParam, Row%, Col%)
        CASE " "
        CASE " Qu"
            GraphicParam.MenuNum = 0
            'CALL CheckParamEntry(CompattParam, GraphicParam)
        CASE ELSE
    END SELECT
LOOP

END SUB

'***** FUNCTION TO CREATE A SCROLLING MENU & RETURN THE SELECTED OPTION *****
'
FUNCTION VLCTScroller$ (Option$(), GraphicParam AS GraphicParams)

'*** Display all the Options
COLOR GraphicParam.TextLo, GraphicParam.Background
FOR Scroll% = 0 TO GraphicParam.MaxElementNum
    LOCATE GraphicParam.ScrollRow + Scroll%, GraphicParam.DescrColumn
    PRINT Option$(Scroll%);
NEXT Scroll%

'*** Highlight the Menu Title
Scroll% = 0
LOCATE GraphicParam.ScrollRow, GraphicParam.DescrColumn
COLOR GraphicParam.TextTitle, GraphicParam.Background
PRINT Option$(Scroll%);

'*** Highlight the top option
Scroll% = GraphicParam.ElementNum
IF Scroll% > GraphicParam.MaxElementNum THEN Scroll% = 2
COLOR GraphicParam.TextHi, GraphicParam.Background
LOCATE GraphicParam.ScrollRow + Scroll%, GraphicParam.DescrColumn
PRINT Option$(Scroll%);

'*** Only act on UP, DOWN, and <CR> keys. Exit loop on <CR>.
DO

    '*** Wait for next key press
    DO
        KeyPress$ = INKEY$
    LOOP UNTIL KeyPress$ <> ""

    '*** Highlight the next Option DOWN
    IF (ASC(LEFT$(KeyPress$, 1)) = 0) AND (ASC(RIGHT$(KeyPress$, 1)) = 80) THEN
        COLOR GraphicParam.TextLo, GraphicParam.Background
        LOCATE GraphicParam.ScrollRow + Scroll%, GraphicParam.DescrColumn
        PRINT Option$(Scroll%);
     
        '*** Advance the scroll but skip any empty options
        DO
            Scroll% = Scroll% + 1
            IF Scroll% > GraphicParam.MaxElementNum THEN Scroll% = 2
        LOOP UNTIL Option$(Scroll%) <> " "

        COLOR GraphicParam.TextHi, GraphicParam.Background
        LOCATE GraphicParam.ScrollRow + Scroll%, GraphicParam.DescrColumn
        PRINT Option$(Scroll%);
    END IF

    '*** Highlight the next Option UP
    IF (ASC(LEFT$(KeyPress$, 1)) = 0) AND (ASC(RIGHT$(KeyPress$, 1)) = 72) THEN
        COLOR GraphicParam.TextLo, GraphicParam.Background
        LOCATE GraphicParam.ScrollRow + Scroll%, GraphicParam.DescrColumn
        PRINT Option$(Scroll%);

        '*** Retard the scroll but skip any empty options
        DO
            Scroll% = Scroll% - 1
            IF Scroll% < 2 THEN Scroll% = GraphicParam.MaxElementNum
        LOOP UNTIL Option$(Scroll%) <> " "

        COLOR GraphicParam.TextHi, GraphicParam.Background
        LOCATE GraphicParam.ScrollRow + Scroll%, GraphicParam.DescrColumn
        PRINT Option$(Scroll%);
    END IF

LOOP UNTIL KeyPress$ = CHR$(13)     '<CR>

'*** Re-draw a viewport for changes
CALL ViewPort(GraphicParam, 2)

COLOR , GraphicParam.Background

VLCTScroller$ = Option$(Scroll%)

END FUNCTION

