'***** 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
'*** Name:                  EXELDATA.BAS

'*** Date of second issue:  10.9.97
'*** Name:                  EXELDAT2.BAS
'*** Description:           In order to process .LOG files which were
'                           generated using VLCT Bench Test software earlier
'                           than VLCTBT5D.BAS, EXELDAT2.BAS reads the old
'                           type of .LOG file and converts that to the
'                           Excel spreadsheet format.
'                           This file has the following additional features:
'                           1. Error handling
'                           2. Option to enter the Log filename
'                           3. Option to Shell to DOS
'                           4. Option to Quit

'*** Date of third issue:   25.9.97
'*** Name:                  EXELDAT3.BAS (this program)
'*** Description:           This performs the task of EXELDATA.BAS
'                           but with the added features of EXELDAT2.DAT
'                           plus the following:
'                           1. Option to enter the Log filepath


'*** Subprogram declarations
DECLARE SUB CheckLogFilepath (VLCTParam AS ANY, GraphicParam AS ANY)
DECLARE SUB UpdateDataFilepath (VLCTParam AS ANY, GraphicParam AS ANY)
DECLARE SUB WriteFileParams (VLCTParam AS ANY)
DECLARE SUB LoadFileParams (VLCTParam AS ANY)
DECLARE SUB FinalMessage (GraphicParam AS ANY, TimeMins%, TimeSecs%)
DECLARE SUB InitialMessage (GraphicParam AS ANY)
DECLARE SUB VLCTMenu (VLCTParam AS ANY, GraphicParam AS ANY)
DECLARE SUB UpdateDataFilename (VLCTParam AS ANY, GraphicParam AS ANY)
DECLARE SUB ErrorSub (GraphicParam AS ANY)
DECLARE SUB ErrorMessage (GraphicParam AS ANY, ErrNum%, OptionalVal!)
DECLARE SUB CheckLogFilename (VLCTParam AS ANY, GraphicParam AS ANY)
DECLARE FUNCTION ScrollMenu$ (GraphicParam AS ANY, VLCTParam AS ANY)
DECLARE SUB EnterString (GraphicParam AS ANY, StringVar$, Max%, Row%, Col%)
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 SUB ViewPort (GraphicParam AS ANY, BoxNum%)
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 STRING * 7          'Nominal TAT
    TATtestB AS STRING * 7          'TAT with int'tion pulses closer by 0.95ms
    TATtestC AS STRING * 7          'TAT with int'tion pulses further by 0.95ms
    TATtestD AS STRING * 7          'TAT with int'tion freqs increased by 250Hz
    TATtestE AS STRING * 7          '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

'*** Common Shared variables
COMMON SHARED ErrorFlag%

'*** Dimension records
DIM VLCTParam AS VLCTParams
DIM GraphicParam AS GraphicParams


'*************** Specifying & initialising Event traps ********************
ON ERROR GOTO ErrorHandler
'**************************************************************************


'*** Start of program proper...

SCREEN 9, 0, 0

'*** Define colours and other screen parameters
CALL GraphicsDefine(GraphicParam)

'*** Generate background tiling
CALL MakeTile

'*** Load filename & path parameters of Log & Data files
CALL LoadFileParams(VLCTParam)

'*** Define file parameters from Menu options
CALL VLCTMenu(VLCTParam, GraphicParam)

'*** Stop here if Quit was pressed
IF GraphicParam.MenuNum = 0 THEN END

'*** Initial message warning operator of a respectable time to wait
CALL InitialMessage(GraphicParam)

'*** Begin Timer to measure the time taken to perform the conversion
StartTime! = TIMER

'*** 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 Date, 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)

'*** Write the Log & Data file parameters to file
CALL WriteFileParams(VLCTParam)

'*** Calculate the time taken to complete the operation
TimeToComplete! = TIMER - StartTime!        'seconds
TimeMins% = FIX(TimeToComplete! / 60)
TimeSecs% = TimeToComplete! MOD 60

'*** Print confirmation of completion
CALL FinalMessage(GraphicParam, TimeMins%, TimeSecs%)

END


'**************************************************************************
'*** ERROR HANDLER
'**************************************************************************
ErrorHandler:

    ErrorFlag% = 1

    '*** Call Error Handler
    CALL ErrorSub(GraphicParam)

RESUME NEXT

'*** 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 FILE NAME ***************
'
SUB CheckLogFilename (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.
'GraphicParam.ElementNum is the menu element which will be highlighted
'if invalid.

'*** Check entry for Test Results Filename
FullLogFile$ = RTRIM$(VLCTParam.RawLogPath) + "\" + RTRIM$(VLCTParam.RawLogFile)
LogFile% = FREEFILE
OPEN FullLogFile$ FOR INPUT AS #LogFile%

'*** If the Log filename is invalid, then re-try
IF ErrorFlag% = 1 THEN
        GraphicParam.ElementNum = 2
    ELSE
        CLOSE #LogFile%
END IF

END SUB

'**************** SUBPROGRAM TO CHECK THE ENTERED FILE PATH ***************
'
SUB CheckLogFilepath (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.
'GraphicParam.ElementNum is the menu element which will be highlighted
'if invalid.

'*** Remove backslash if the operator has entered it
IF RIGHT$(RTRIM$(VLCTParam.RawLogPath), 1) = "\" THEN
    NewStrLen% = LEN(RTRIM$(VLCTParam.RawLogPath)) - 1
    VLCTParam.RawLogPath = LEFT$(VLCTParam.RawLogPath, NewStrLen%)
END IF

'*** Check entry for Test Results Filename
FullLogFile$ = RTRIM$(VLCTParam.RawLogPath) + "\" + RTRIM$(VLCTParam.RawLogFile)
LogFile% = FREEFILE
OPEN FullLogFile$ FOR INPUT AS #LogFile%

'*** If the Log filename or path is/are invalid, then re-try
IF ErrorFlag% = 1 THEN
        GraphicParam.ElementNum = 3
    ELSE
        CLOSE #LogFile%
END IF

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

'****************** SUBPROGRAM TO DISPLAY ERROR MESSAGES ******************
'
SUB ErrorMessage (GraphicParam AS GraphicParams, ErrNum%, OptionalVal!)

'*** ErrNum% selects the text to be displayed
'*** OptionalVal! is a paramater used in conjunction with text, if required

'*** Ensure the bottom Viewport is active
CALL ViewPort(GraphicParam, 2)
CLS 1

COLOR GraphicParam.TextErrorMessage, GraphicParam.Background
Row% = 24: Col% = 44
LOCATE Row%, Col%: PRINT "Press any key to continue...";

'*** Define screen location for error message
SELECT CASE ErrNum%
    CASE 24, 77
        Row% = GraphicParam.StatusErrorRow + 2
        Col% = GraphicParam.StatusErrorCol
    CASE ELSE
        Row% = GraphicParam.StatusErrorRow + 2
        Col% = GraphicParam.StatusErrorCol
END SELECT

'*** Print error message
COLOR GraphicParam.TextErrorMessage, GraphicParam.Background
SELECT CASE ErrNum%
    CASE 3
        LOCATE Row%, Col%: PRINT "RETURN without GOSUB"
    CASE 4
        LOCATE Row%, Col%: PRINT "Out of DATA"
    CASE 5
        LOCATE Row%, Col%: PRINT "Illegal function call"
    CASE 6
        LOCATE Row%, Col%: PRINT "Overflow"
    CASE 7
        LOCATE Row%, Col%: PRINT "Out of memory"
    CASE 9
        LOCATE Row%, Col%: PRINT "Subscript out of range"
    CASE 11
        LOCATE Row%, Col%: PRINT "Division by zero"
    CASE 14
        LOCATE Row%, Col%: PRINT "Out of string space"
    CASE 16
        LOCATE Row%, Col%: PRINT "String formula too complex"
    CASE 19
        LOCATE Row%, Col%: PRINT "No RESUME"
    CASE 20
        LOCATE Row%, Col%: PRINT "RESUME without error"
    CASE 24
        LOCATE Row%, Col%
        PRINT "ANT or Control Box communication path not establised."
        LOCATE CSRLIN, Col%
        PRINT "Probable cause: Cable not connected at either COM1 or COM2."
    CASE 25
        LOCATE Row%, Col%: PRINT "Device fault"
    CASE 27
        LOCATE Row%, Col%: PRINT "Out of paper"
    CASE 39
        LOCATE Row%, Col%: PRINT "CASE ELSE expected"
    CASE 40
        LOCATE Row%, Col%: PRINT "Variable required"
    CASE 50
        LOCATE Row%, Col%: PRINT "FIELD overflow"
    CASE 51
        LOCATE Row%, Col%: PRINT "Internal error"
    CASE 52
        LOCATE Row%, Col%: PRINT "Bad file name or number"
    CASE 53
        LOCATE Row%, Col%: PRINT "File not found"
    CASE 54
        LOCATE Row%, Col%: PRINT "Bad file mode"
    CASE 55
        LOCATE Row%, Col%: PRINT "File already open"
    CASE 56
        LOCATE Row%, Col%: PRINT "FIELD statement active"
    CASE 57
        LOCATE Row%, Col%: PRINT "Device I/O error"
    CASE 58
        LOCATE Row%, Col%: PRINT "File already exists"
    CASE 59
        LOCATE Row%, Col%: PRINT "Bad record length"
    CASE 61
        LOCATE Row%, Col%: PRINT "Disk full"
    CASE 62
        LOCATE Row%, Col%: PRINT "Input past end of file"
    CASE 63
        LOCATE Row%, Col%: PRINT "Bad record number"
    CASE 64
        LOCATE Row%, Col%: PRINT "Bad file name"
    CASE 67
        LOCATE Row%, Col%: PRINT "Too many files"
    CASE 68
        LOCATE Row%, Col%: PRINT "Device unavailable"
    CASE 69
        LOCATE Row%, Col%: PRINT "Communication-buffer overflow"
    CASE 70
        LOCATE Row%, Col%: PRINT "Permission denied"
    CASE 71
        LOCATE Row%, Col%: PRINT "Disk not ready"
    CASE 72
        LOCATE Row%, Col%: PRINT "Disk-media error"
    CASE 73
        LOCATE Row%, Col%: PRINT "Advanced feature unavailable"
    CASE 74
        LOCATE Row%, Col%: PRINT "Rename across disks"
    CASE 75
        LOCATE Row%, Col%: PRINT "Path/File access error"
    CASE 76
        LOCATE Row%, Col%: PRINT "Path not found"
    CASE 77
        LOCATE Row%, Col%
        PRINT "ANT communications link not established."
        LOCATE CSRLIN, Col%
        PRINT "Ensure ANT is switched on and connects to COM1."
    CASE 78
        LOCATE Row%, Col%: PRINT "Scope communications link not established"
    CASE 79
        LOCATE Row%, Col%: PRINT "DAS-801 board or function failure"
    CASE 80
        LOCATE Row%, Col%: PRINT "XOFF incorrectly received in ANTHandshake."
        LOCATE CSRLIN, Col%: PRINT "About to reapeat the G command..."
    CASE 81
        LOCATE Row%, Col%: PRINT "XON incorrectly received in ANTHandshake."
        LOCATE CSRLIN, Col%: PRINT "About to reapeat the G command..."
    CASE 82
        LOCATE Row%, Col%: PRINT "XON not received in allotted time in ANTHandshake."
        LOCATE CSRLIN, Col%: PRINT "About to reapeat the G command..."
    CASE 83
        LOCATE Row%, Col%: PRINT "Unknown error in FUNCTION ANTHandshake%"
        LOCATE CSRLIN, Col%: PRINT "About to reapeat the G command..."
    CASE 84
        LOCATE Row%, Col%: PRINT "Compatt Parameters not yet selected"
    CASE 85
        LOCATE Row%, Col%: PRINT "ANT has to be initialised and Baud Rate set"
    CASE 100
        LOCATE Row%, Col%: PRINT "THIS ROUTINE HAS YET TO BE WRITTEN..."
    CASE 101
        LOCATE Row%, Col%: PRINT "THIS ROUTINE NEEDS FURTHER DEVELOPMENT..."
    CASE ELSE
        LOCATE Row%, Col%: PRINT "Unrecognised Error Number"
END SELECT

END SUB

'****** SUBPROGRAM CONTAINING A LIBRARY OF ERROR HANDLERS SELECTED BY ******
'************** THE ERR FUNCTION FOLLOWING A RUN-TIME ERROR ****************
'
SUB ErrorSub (GraphicParam AS GraphicParams)

SELECT CASE ERR
    CASE 3
        CALL ErrorMessage(GraphicParam, 3, 0)    'RETURN without GOSUB
    CASE 4
        CALL ErrorMessage(GraphicParam, 4, 0)    'Out of Data
    CASE 5
        CALL ErrorMessage(GraphicParam, 5, 0)    'Illegal function call
    CASE 6
        CALL ErrorMessage(GraphicParam, 6, 0)    'Overflow
    CASE 7
        CALL ErrorMessage(GraphicParam, 7, 0)    'Out of memory
    CASE 9
        CALL ErrorMessage(GraphicParam, 9, 0)    'Subscript out of range
    CASE 11
        CALL ErrorMessage(GraphicParam, 11, 0)   'Division by zero
    CASE 14
        CALL ErrorMessage(GraphicParam, 14, 0)   'Out of string space
    CASE 16
        CALL ErrorMessage(GraphicParam, 16, 0)   'String formula too complex
    CASE 19
        CALL ErrorMessage(GraphicParam, 19, 0)   'No RESUME
    CASE 20
        CALL ErrorMessage(GraphicParam, 20, 0)   'RESUME without error
    CASE 24
        CALL ErrorMessage(GraphicParam, 24, 0)   'Device timeout
    CASE 25
        CALL ErrorMessage(GraphicParam, 25, 0)   'Device fault
    CASE 27
        CALL ErrorMessage(GraphicParam, 27, 0)   'Out of paper
    CASE 39
        CALL ErrorMessage(GraphicParam, 39, 0)   'CASE ELSE expected
    CASE 40
        CALL ErrorMessage(GraphicParam, 40, 0)   'Variable required
    CASE 50
        CALL ErrorMessage(GraphicParam, 50, 0)   'FIELD overflow
    CASE 51
        CALL ErrorMessage(GraphicParam, 51, 0)   'Internal error
    CASE 52
        CALL ErrorMessage(GraphicParam, 52, 0)   'Bad file name or number
    CASE 53
        CALL ErrorMessage(GraphicParam, 53, 0)   'File not found
    CASE 54
        CALL ErrorMessage(GraphicParam, 54, 0)   'Bad file mode
    CASE 55
        CALL ErrorMessage(GraphicParam, 55, 0)   'File already open
    CASE 56
        CALL ErrorMessage(GraphicParam, 56, 0)   'FIELD statement active
    CASE 57
        CALL ErrorMessage(GraphicParam, 57, 0)   'Device I/O error
    CASE 58
        CALL ErrorMessage(GraphicParam, 58, 0)   'File already exists
    CASE 59
        CALL ErrorMessage(GraphicParam, 59, 0)   'Bad record length
    CASE 61
        CALL ErrorMessage(GraphicParam, 61, 0)   'Disk full
    CASE 62
        CALL ErrorMessage(GraphicParam, 62, 0)   'Input past end of file
    CASE 63
        CALL ErrorMessage(GraphicParam, 63, 0)   'Bad record number
    CASE 64
        CALL ErrorMessage(GraphicParam, 64, 0)   'Bad file name
    CASE 67
        CALL ErrorMessage(GraphicParam, 67, 0)   'Too many files
    CASE 68
        CALL ErrorMessage(GraphicParam, 68, 0)   'Device unavailable
    CASE 69
        CALL ErrorMessage(GraphicParam, 69, 0)   'Communication-buffer overflow
    CASE 70
        CALL ErrorMessage(GraphicParam, 70, 0)   'Permission denied
    CASE 71
        CALL ErrorMessage(GraphicParam, 71, 0)   'Disk not ready
    CASE 72
        CALL ErrorMessage(GraphicParam, 72, 0)   'Disk-media error
    CASE 73
        CALL ErrorMessage(GraphicParam, 73, 0)   'Advanced feature unavailable
    CASE 74
        CALL ErrorMessage(GraphicParam, 74, 0)   'Rename across disks
    CASE 75
        CALL ErrorMessage(GraphicParam, 75, 0)   'Path/File access error
    CASE 76
        CALL ErrorMessage(GraphicParam, 76, 0)   'Path not found
    CASE 77
        CALL ErrorMessage(GraphicParam, 77, 0)   'ANT Comms Link
    CASE 78
        CALL ErrorMessage(GraphicParam, 78, 0)   'Scope Comms link
    CASE 79
        CALL ErrorMessage(GraphicParam, 79, 0)   'DAS-801 error
    CASE 80
        CALL ErrorMessage(GraphicParam, 80, 0)   'XOFF incorrectly received
    CASE 81
        CALL ErrorMessage(GraphicParam, 81, 0)   'XON incorrectly received
    CASE 82
        CALL ErrorMessage(GraphicParam, 82, 0)   'XON not received in allotted time
    CASE 83
        CALL ErrorMessage(GraphicParam, 83, 0)   'Unknown error in FUNCTION ANTHandshake%
    CASE 84
        CALL ErrorMessage(GraphicParam, 84, 0)   'Compatt Parameters not yet selected
    CASE 85
        CALL ErrorMessage(GraphicParam, 85, 0)   'ANT not initialised or B.R. set
    CASE 100
        CALL ErrorMessage(GraphicParam, 100, 0)   'TO BE WRITTEN...
    CASE 101
        CALL ErrorMessage(GraphicParam, 101, 0)   'DEVELOPMENT REQUIRED...
    CASE ELSE
        CALL ErrorMessage(GraphicParam, 2000, 0) 'Undefined error
END SELECT

'*** Flush the keyboard buffer
DO: LOOP UNTIL INKEY$ = ""

DO: LOOP UNTIL INKEY$ <> ""

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, TimeMins%, TimeSecs%)

Row% = 21
Col% = 11

'*** Clear the viewport
CLS 1

'*** Flush the keyboard buffer
DO: LOOP UNTIL INKEY$ = ""

COLOR 4, GraphicParam.Background
LOCATE Row%, Col%
PRINT "OPERATION COMPLETE."
LOCATE CSRLIN, Col% + 20
PRINT "Time to complete:";
PRINT TimeMins%; "minutes,"; TimeSecs%; "seconds"

LOCATE (CSRLIN + 1), Col% + 16
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

'***************** SUBPROGRAM TO DISPLAY AN INITIAL MESSAGE *****************
'
SUB InitialMessage (GraphicParam AS GraphicParams)

Row% = 21
Col% = 11

'*** Clear the viewport
CLS 1

'*** Flush the keyboard buffer
DO: LOOP UNTIL INKEY$ = ""

COLOR 4, GraphicParam.Background
LOCATE Row%, Col%
PRINT "PLEASE WAIT..."

LOCATE CSRLIN, Col%
PRINT "                 This operation may take several minutes"
LOCATE CSRLIN, Col%
PRINT "                 depending on the size of the data file."

END SUB

'************ SUBPROGRAM TO LOAD THE LOG & DATA FILE PARAMETERS *************
'
SUB LoadFileParams (VLCTParam AS VLCTParams)

'If the EXELPARM.DAT is available, then use the filename & paths for
'the Data & Log files from there.
'If the file is not present, then use hard-wired default values.

ParamFile% = FREEFILE
OPEN "EXELPARM.DAT" FOR INPUT AS #ParamFile%

'*** If an error is returned, then use the hard-wired defaults
IF ErrorFlag% = 0 THEN
        INPUT #ParamFile%, a$
        INPUT #ParamFile%, b$
        INPUT #ParamFile%, c$
        INPUT #ParamFile%, d$
        CLOSE #ParamFile%

        VLCTParam.RawLogFile = RTRIM$(a$)
        VLCTParam.RawLogPath = RTRIM$(b$)
        VLCTParam.FormattedDataFile = RTRIM$(c$)
        VLCTParam.FormattedDataPath = RTRIM$(d$)

    ELSE

        VLCTParam.RawLogFile = "TEST1.LOG"
        VLCTParam.RawLogPath = "C:\TESTS\VLCT"
        VLCTParam.FormattedDataFile = "TEST1.DAT"
        VLCTParam.FormattedDataPath = "C:\TESTS\VLCT"
        ErrorFlag% = 0
END IF

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 ScrollMenu$ (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) = " Shell to DOS"
Option$(8) = " "
Option$(9) = " Start Conversion"
Option$(10) = " "
Option$(11) = " "
Option$(12) = " "
Option$(13) = " "
Option$(14) = " Quit"

'***Display and select
ScrollMenu$ = 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 UPDATE THE DATA (.DAT) FILENAME *************
'******************* IF A NEW LOG (.LOG) FILE IS SELECTED *****************
'
SUB UpdateDataFilename (VLCTParam AS VLCTParams, GraphicParam AS GraphicParams)

'The .LOG filename is also converted to uppercase

DecPointPos% = 0
FilenameStr$ = ""
DO
    DecPointPos% = DecPointPos% + 1
    CharStr$ = MID$(VLCTParam.RawLogFile, DecPointPos%, 1)
    IF CharStr$ = "." THEN
            DecPointFound% = 1
        ELSE
            DecPointFound% = 0
            FilenameStr$ = FilenameStr$ + UCASE$(CharStr$)
    END IF
LOOP UNTIL (DecPointFound% = 1) OR (DecPointPos% = 9)

VLCTParam.FormattedDataFile = FilenameStr$ + ".DAT"

'*** Convert Log filename to upper case
VLCTParam.RawLogFile = FilenameStr$ + ".LOG"

END SUB

'************** SUBPROGRAM TO UPDATE THE DATA (.DAT) FILEPATH *************
'******************* IF A NEW LOG (.LOG) PATH IS SELECTED *****************
'
SUB UpdateDataFilepath (VLCTParam AS VLCTParams, GraphicParam AS GraphicParams)

'The .LOG filepath is also converted to uppercase

VLCTParam.RawLogPath = UCASE$(VLCTParam.RawLogPath)
VLCTParam.FormattedDataPath = VLCTParam.RawLogPath

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 VLCTMenu (VLCTParam AS VLCTParams, GraphicParam AS GraphicParams)

Row% = 22
Col% = 10

GraphicParam.MenuNum = 1
GraphicParam.ElementNum = 2
 
DO

    '*** Draw a Main Menu viewport
    CALL MakeTile
    CALL ViewPort(GraphicParam, 1)

    '*** Draw a viewport for changes.
    CALL ViewPort(GraphicParam, 2)
 
    '*** Flush the keyboard buffer.
    DO: LOOP UNTIL INKEY$ = ""

    Instruction$ = ScrollMenu$(GraphicParam, VLCTParam)

    SELECT CASE LEFT$(Instruction$, 3)
        CASE " 1."
            GraphicParam.ElementNum = 3
            CALL EnterString(GraphicParam, VLCTParam.RawLogFile, 12, Row%, Col%)
            CALL CheckLogFilename(VLCTParam, GraphicParam)
            IF ErrorFlag% = 0 THEN
                    CALL UpdateDataFilename(VLCTParam, GraphicParam)
                ELSE
                    ErrorFlag% = 0
            END IF
        CASE " 2."
            GraphicParam.ElementNum = 4
            CALL EnterString(GraphicParam, VLCTParam.RawLogPath, 40, Row%, Col%)
            CALL CheckLogFilepath(VLCTParam, GraphicParam)
            IF ErrorFlag% = 0 THEN
                    CALL UpdateDataFilepath(VLCTParam, GraphicParam)
                ELSE
                    ErrorFlag% = 0
            END IF
        CASE " 3."
            GraphicParam.ElementNum = 5
            'CALL EnterString(GraphicParam, VLCTParam.FormattedDataFile, 12, Row%, Col%)
            CALL TemporaryMessage(GraphicParam, Row%, Col%)
        CASE " 4."
            GraphicParam.ElementNum = 7
            'CALL EnterString(GraphicParam, VLCTParam.FormattedDataPath, 40, Row%, Col%)
            CALL TemporaryMessage(GraphicParam, Row%, Col%)

        CASE " Sh"
            GraphicParam.ElementNum = 2
            VIEW
            CLS 0
            COLOR 7, 0
            SHELL

        CASE " St"
            CALL CheckLogFilename(VLCTParam, GraphicParam)
            IF ErrorFlag% = 0 THEN
                    CALL UpdateDataFilename(VLCTParam, GraphicParam)
                    GraphicParam.MenuNum = -1
                ELSE
                    ErrorFlag% = 0
                    GraphicParam.ElementNum = 2
            END IF

        CASE " "
        CASE " Qu"
            GraphicParam.MenuNum = 0
           
        CASE ELSE
    END SELECT
LOOP UNTIL GraphicParam.MenuNum <> 1

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

'******** SUBPROGRAM TO WRITE THE LOG & DATA FILE PARAMETERS TO FILE ********
'
SUB WriteFileParams (VLCTParam AS VLCTParams)

ParamFile% = FREEFILE
OPEN "EXELPARM.DAT" FOR OUTPUT AS #ParamFile%

WRITE #ParamFile%, VLCTParam.RawLogFile
WRITE #ParamFile%, VLCTParam.RawLogPath
WRITE #ParamFile%, VLCTParam.FormattedDataFile
WRITE #ParamFile%, VLCTParam.FormattedDataPath
CLOSE ParamFile%

END SUB

