[Back to TEXTFILE SWAG index] [Back to Main SWAG index] [Original]

    Unit TextUtil;
    {        Written by Wilbert Van.Leijen and posted in the Pascal Echo }

    Interface

    Function TextFilePos(Var f : Text) : LongInt;
    Function TextFileSize(Var f : Text) : LongInt;
    Procedure TextSeek(Var f : Text; n : LongInt);

    Implementation
    Uses Dos;

    {$R-,S- }

    Procedure GetFileMode; Assembler;

    Asm
                                    CLC
                                    CMP    ES:[DI].TextRec.Mode, fmInput
                                    JE     @1
                                    MOV    [InOutRes], 104         { 'File not opened For reading' }
                                    xor    AX, AX                  { Zero out Function result }
                                    xor    DX, DX
                                    STC
    @1:
    end;  { GetFileMode }

    Function TextFilePos(Var f : Text) : LongInt; Assembler;

    Asm
            LES    DI, f
            CALL   GetFileMode
            JC     @1

            xor    CX, CX                  { Get position of File Pointer }
            xor    DX, DX
            MOV    BX, ES:[DI].TextRec.handle
            MOV    AX, 4201h
            inT    21h                     { offset := offset-Bufend+BufPos }
                                    xor    BX, BX
            SUB    AX, ES:[DI].TextRec.Bufend
            SBB    DX, BX
            ADD    AX, ES:[DI].TextRec.BufPos
            ADC    DX, BX
    @1:
    end;  { TextFilePos }

    Function TextFileSize(Var f : Text) : LongInt; Assembler;

    Asm
                                    LES    DI, f
                                    CALL   GetFileMode
                                    JC     @1

                                    xor    CX, CX                  { Get position of File Pointer }
            xor    DX, DX
            MOV    BX, ES:[DI].TextRec.handle
            MOV    AX, 4201h
                                    inT    21h
            PUSH   DX                      { Save current offset on the stack }
                                    PUSH   AX
            xor    DX, DX                  { Move File Pointer to Eof }
            MOV    AX, 4202h
            inT    21h
            POP    SI
            POP    CX
                                    PUSH   DX                      { Save Eof position }
            PUSH   AX
            MOV    DX, SI                  { Restore old offset }
            MOV    AX, 4200h
            inT    21h
            POP    AX                      { Return result}
            POP    DX
    @1:
    end;  { TextFileSize }

    Procedure TextSeek(Var f : Text; n : LongInt); Assembler;

    Asm
            LES    DI, f
                                    CALL   GetFileMode
            JC     @2

            MOV    CX, Word Ptr n+2        { Move File Pointer }
            MOV    DX, Word Ptr n
            MOV    BX, ES:[DI].TextRec.Handle
                                    MOV    AX, 4200h
                                    inT    21h
                                    JNC    @1                      { Carry flag = reading past Eof }
                                    MOV    [InOutRes], AX
                                    JMP    @2
                                                                                                                                                             { Force read next time }
    @1:     MOV    AX, ES:[DI].TextRec.Bufend
                                    MOV    ES:[DI].TextRec.BufPos, AX
    @2:
    end;  { TextSeek }
    end.  { TextUtil }

    {    With the aid of that Unit you could save the position of each line
    in the Text File to an Array of LongInt as you read them. You can also
    open a temporary File, a File of LongInt, where each Record would simply
    represent the offset of that line in the Text File. if you need to go
    back in the Text, simply read the offset of the line where you which to
    restart reading. Suppose you are on line 391 and you decide to go back
    say, 100 lines, simply do a Seek(MyIndex, CurrentLine-100). then use the
    TextSeek Procedure to seek to that position in the Text File and start
    reading again, taking into acount that you allready read those lines so
    you either re-Write the offsets to your index File, which won't hurt
    since you will just be overwriting the Records With the same values
    again or simply skip writing the offsets Until you reach a point where
    NEW lines that haven't yet been read are reached. Save any new offset as
    you read Forward.

        With this method you can go back-wards as well as Forwards. In fact
    if you first read the File, saving all offsets Until the end, you can
    offer the user to seek to any line number.

        When you read new lines or seek backwards, simply flush any lines
    from memory. or maybe you could decide to keep a predetermined number of
    lines in memory say 300. When ever the user asks to read Forward or
    backwards, simply flush the 100 first or Last line, depending on the
    direction the user wants to go, and read 100 new lines from the Text
    File.

        Maybe the best approach to be sure of sufficient memory is to
    determine how many lines will fit. Suppose you limit line lengths to 255
    caracters. Determine how many will fit in a worse Case scenario. Create
    as many 255 caracter Strings as will fit. divide that number of lines by
    4. Say you managed to create 1000 Strings of 255 caracters. divided by 4
    is 250. So set a limit to 750 Strings to be safe and make any disk
    accesses in bundles of 250 Lines.

        You can also keep the line offsets in memory in Arrays but you will
    be limited to 65520 / 8 = 16380 lines. Make that two Arrays stored on
    the heap and you've got yourself enough space to store 32760 line
    offsets which at 255 caracters by line would be an 8.3 Meg File.
     }

[Back to TEXTFILE SWAG index] [Back to Main SWAG index] [Original]