home *** CD-ROM | disk | FTP | other *** search
- {
- --------------------------------------------------------------------------
- F i l e I n f o r m a t i o n
-
- * DESCRIPTION
- File used with FM.PAS.
-
- * ASSOCIATED FILES
- FM.PAS
- FM.DOC
- FM.EXE
- FM.TPU
- FMFILE.PAS
- FMINPUT.PAS
- FMSCREEN.PAS
- FMUTEST.EXE
- FMUTEST.PAS
- FMVIEW.PAS
-
- ==========================================================================
- }
- {$R-} { Range checking off } { Unit: FMView.PAS }
- {$S-} { Stack checking off } { Program: FM.PAS }
- {$I-} { I/O checking off } { Author: Jim Zwick }
- {$B-} { Boolean short-circuit evaluation on } { Version: 1.0 }
- {$V+} { Strict String type checking on } { Date: 03-04-88 }
-
- UNIT FMView;
-
- INTERFACE
-
- USES
- Crt,
- Dos,
- FMScreen,
- FMFile,
- FMInput;
-
-
- PROCEDURE View(Name : Str12);
-
-
- IMPLEMENTATION
-
- PROCEDURE View(Name : Str12);
- CONST
- NL = 24;
- MoveChar : SET OF CHAR = [Home, Up, PgUp, Left, Right, EndKey, Down, PgDn];
- TYPE
- VPageLinesType = ARRAY[1..NL] OF STRING[90];
- VPagePtr = ^VPageRec;
- VPageRec = RECORD
- Key : INTEGER; { PageNumber }
- Pg : VPageLinesType;
- Next : VPagePtr;
- Last : VPagePtr;
- END;
- VAR
- CurrPage, FirstPg, LastPg : VPagePtr;
- BufferStart : INTEGER;
- MaxPages, PagesInBuffer : INTEGER;
- TempPage, LastPageInFile : INTEGER;
- Line, Place : BYTE;
- Reply : CHAR;
- BufferFull, EndOfFile : BOOLEAN;
- NewScr, BufPagesFull : BOOLEAN;
- TempStr : STRING[78];
- Source : TEXT;
-
- { --------------------------------- }
-
- PROCEDURE InsertViewPage(VAR FirstPtr, LastPtr, NewPtr : VPagePtr);
- VAR
- SearchPtr : VPagePtr; { FirstPtr and LastPtr must be }
- Found : BOOLEAN; { initialized to NIL before }
- BEGIN { calling this procedure the }
- SearchPtr := FirstPtr; { first time. NewPtr must be }
- Found := FALSE; { allocated and initialized. }
- NewPtr^.Next := NIL;
- NewPtr^.Last := NIL;
- IF (SearchPtr = NIL) THEN
- BEGIN
- FirstPtr := NewPtr;
- LastPtr := FirstPtr;
- END
- ELSE
- BEGIN
- WHILE (SearchPtr <> NIL) AND (NOT Found) DO
- IF (SearchPtr^.Key < NewPtr^.Key) THEN SearchPtr := SearchPtr^.Next
- ELSE Found := TRUE;
- NewPtr^.Next := SearchPtr;
- IF (SearchPtr = FirstPtr) THEN
- BEGIN
- FirstPtr := NewPtr;
- SearchPtr^.Last := FirstPtr;
- END
- ELSE IF (SearchPtr = NIL) THEN
- BEGIN
- NewPtr^.Last := LastPtr;
- LastPtr^.Next := NewPtr;
- LastPtr := NewPtr;
- END
- ELSE
- BEGIN
- NewPtr^.Last := SearchPtr^.Last;
- SearchPtr^.Last^.Next := NewPtr;
- SearchPtr^.Last := NewPtr;
- END;
- END;
- END;
- { --------------------------------- }
-
- PROCEDURE DeleteViewPage(VAR FirstPtr, LastPtr : VPagePtr; OldKey : INTEGER);
- VAR
- DelPtr : VPagePtr; { FirstPtr and LastPtr }
- BEGIN { must be initialized }
- IF (FirstPtr = NIL) THEN DelPtr := NIL { to NIL before calling }
- ELSE IF (OldKey = FirstPtr^.Key) THEN { this procedure the }
- BEGIN { first time. }
- DelPtr := FirstPtr;
- FirstPtr := FirstPtr^.Next;
- IF (FirstPtr <> NIL) THEN FirstPtr^.Last := NIL;
- IF (FirstPtr = NIL) THEN LastPtr := NIL;
- END
- ELSE IF (OldKey = LastPtr^.Key) THEN
- BEGIN
- DelPtr := LastPtr;
- LastPtr := LastPtr^.Last;
- IF (LastPtr <> NIL) THEN LastPtr^.Next := NIL;
- END
- ELSE
- BEGIN
- DelPtr := FirstPtr;
- WHILE (DelPtr <> NIL) AND (DelPtr^.Key <> OldKey) DO
- DelPtr := DelPtr^.Next;
- IF (DelPtr <> NIL) THEN { DelPtr is NIL if OldKey is not found }
- BEGIN
- DelPtr^.Next^.Last := DelPtr^.Last;
- DelPtr^.Last^.Next := DelPtr^.Next;
- END;
- END;
- IF (DelPtr <> NIL) THEN DISPOSE(DelPtr);
- END;
- { --------------------------------- }
-
- PROCEDURE ReadPage(PageNum : INTEGER);
- VAR
- Line : BYTE;
- NewPage : VPageRec;
- TempPtr : VPagePtr;
- BEGIN
- Line := 1;
- WHILE (Line <= NL) DO
- BEGIN
- READLN(Source, Newpage.Pg[Line]);
- Inc(Line);
- END;
- IF EOF(Source) THEN
- BEGIN
- EndOfFile := TRUE;
- LastPageInFile := PageNum;
- END;
- NewPage.Key := PageNum;
- NEW(TempPtr);
- TempPtr^ := NewPage;
- InsertViewPage(FirstPg, LastPg, TempPtr);
- IF (NOT BufferFull) AND (CurrPage <> NIL) THEN
- BEGIN
- HIGHVIDEO;
- GotoXY(1, 25);
- WRITE(Name, ' Page: ', CurrPage^.Key, ' of ', PageNum, ' ');
- LOWVIDEO;
- END;
- END;
- { --------------------------------- }
-
- PROCEDURE WritePage(Position : BYTE);
- VAR
- Line : BYTE;
- WorkStr : STRING[80];
- BEGIN
- ClrScr;
- HIGHVIDEO;
- GotoXY(1, 25);
- WRITE(Name, ' Page: ', CurrPage^.Key, ' of ', LastPageInFile);
- GotoXY(54, 25);
- WRITE(#26#24#25#27, ' <Home> <End> <Esc>');
- LOWVIDEO;
- Line := 1;
- WHILE (Line <= NL) DO
- BEGIN
- WorkStr := COPY(CurrPage^.Pg[Line], Position, { Truncate line to }
- LENGTH(CurrPage^.Pg[Line]) - Position + 1); { 80 characters }
- GotoXY(1, Line);
- WRITE(WorkStr);
- Inc(Line);
- END;
- NewScr := FALSE;
- END;
- { --------------------------------- }
-
- PROCEDURE FillBuffer(PageNum : INTEGER);
- VAR
- TempPage : INTEGER;
- Line : BYTE;
- BEGIN
- WHILE (FirstPg <> NIL) DO { Clear Buffer }
- DeleteViewPage(FirstPg, LastPg, FirstPg^.Key);
- PagesInBuffer := 0;
-
- IF (PageNum = LastPageInFile) THEN { Position BufferStart }
- BufferStart := LastPageInFile - MaxPages + 1 { for maximum pages }
- ELSE BufferStart := PageNum - MaxPages DIV 2;
- IF ((BufferStart + MaxPages - 1) >= LastPageInFile) THEN
- BufferStart := LastPageInFile - MaxPages + 1;
- IF (BufferStart < 1) THEN BufferStart := 1;
-
- TempPage := 1;
- RESET(Source);
- ClrLn(1, 25); WRITE('Reading Page');
- WHILE (TempPage < BufferStart) DO { Skip to Buffer Start }
- BEGIN
- FOR Line := 1 TO NL DO READLN(Source, TempStr);
- GotoXY(14, 25);
- WRITE(TempPage);
- Inc(TempPage);
- END;
-
- GotoXY(1, 25); { Fill Buffer }
- WRITE('Filling Buffer, Page ', TempPage);
- WHILE (((BufferStart + PagesInBuffer - 1) <= LastPageInFile)
- AND (PagesInBuffer <= MaxPages)) OR EOF(Source) DO
- BEGIN
- ReadPage(TempPage);
- GotoXY(22, 25);
- WRITE(TempPage);
- IF (TempPage = PageNum) THEN
- BEGIN
- CurrPage := LastPg;
- WritePage(1);
- BufPagesFull := (PagesInBuffer = MaxPages) OR EOF(Source);
- WHILE KEYPRESSED DO Reply := ReadKey; { Clear Kbd }
- EXIT;
- END;
- Inc(TempPage);
- Inc(PagesInBuffer);
- END;
- END;
- { --------------------------------- }
-
- BEGIN
- WOpen(3);
- ClrScr;
- FileBufSize := 4096; { FileBufSize is kept relatively }
- GETMEM(FileBuffer, FileBufSize); { small to maximize number of pages }
- ASSIGN(Source, Name);
- SetTextBuf(Source, FileBuffer^, FileBufSize);
- GetFAttr(Source, Attribute); { Save file attribute }
- SetFAttr(Source, Archive);
- RESET(Source);
- IF (IOResult = 0) THEN
- BEGIN
- FirstPg := NIL;
- LastPg := NIL;
- CurrPage := NIL;
- NewScr := TRUE;
- BufferFull := FALSE;
- BufPagesFull := TRUE;
- EndOfFile := FALSE;
- LastPageInFile := 0;
- MaxPages := 0;
- SpaceStr := ' ';
- CursorOn(FALSE);
- Place := 1;
- ReadPage(1);
- CurrPage := FirstPg;
- REPEAT
- IF NewScr THEN WritePage(Place);
- WHILE (NOT BufferFull) AND (NOT KeyPressed) AND (NOT EndOfFile) DO
- BEGIN
- ReadPage(LastPg^.Key + 1);
- BufferFull := (MaxAvail < 10240);
- IF BufferFull AND (NOT EndOfFile) THEN
- BEGIN
- BufferStart := 1;
- MaxPages := LastPg^.Key;
- LastPageInFile := MaxPages + 1;
- Line := 1;
- ClrLn(1, 25);
- WRITE('Reading Page ', LastPageInFile);
- WHILE NOT EOF(Source) DO
- BEGIN
- IF (Line > NL) THEN
- BEGIN
- Line := 1;
- GotoXY(14, 25); WRITE(LastPageInFile);
- Inc(LastPageInFile);
- END;
- READLN(Source, TempStr);
- Inc(Line);
- END;
- WritePage(Place);
- END;
- END;
- IF BufferFull THEN
- WHILE (NOT KEYPRESSED) AND (NOT BufPagesFull) DO
- BEGIN
- ReadPage(LastPg^.Key + 1);
- Inc(PagesInBuffer);
- BufPagesFull := (PagesInBuffer + 1 = MaxPages) OR EOF(Source);
- END;
- Reply := GetKey(#0+#27, FALSE);
- NewScr := (Reply IN MoveChar);
- CASE Reply OF
- Down, PgDn : IF NOT BufferFull THEN
- BEGIN
- IF (CurrPage^.Next <> NIL) THEN
- CurrPage := CurrPage^.Next;
- END
- ELSE
- BEGIN
- IF (CurrPage^.Key < LastPageInFile) THEN
- IF (CurrPage^.Next = NIL)
- THEN FillBuffer(CurrPage^.Key + 1)
- ELSE CurrPage := CurrPage^.Next;
- END;
- Up, PgUp : IF NOT BufferFull THEN
- BEGIN
- IF (CurrPage^.Last <> NIL) THEN
- CurrPage := CurrPage^.Last;
- END
- ELSE
- BEGIN
- IF (CurrPage^.Key > 1) THEN
- IF (CurrPage^.Last = NIL)
- THEN FillBuffer(CurrPage^.Key - 1)
- ELSE CurrPage := CurrPage^.Last;
- END;
- Home : BEGIN
- Place := 1;
- IF NOT BufferFull THEN CurrPage := FirstPg
- ELSE
- BEGIN
- IF (BufferStart > 1) THEN FillBuffer(1)
- ELSE CurrPage := FirstPg;
- END;
- END;
- EndKey : BEGIN
- Place := 1;
- IF NOT BufferFull THEN CurrPage := LastPg
- ELSE
- BEGIN
- IF (BufferStart + MaxPages - 1 < LastPageInFile)
- AND (BufPagesFull) THEN FillBuffer(LastPageInFile)
- ELSE CurrPage := LastPg;
- END;
- END;
- Left : Place := 1;
- Right : Place := 10;
- END;
- UNTIL (Reply = #27);
- END;
- CLOSE(Source);
- IF (IOResult = 0) THEN SetFAttr(Source, Attribute); { Restore attribute }
- WHILE (FirstPg <> NIL) DO DeleteViewPage(FirstPg, LastPg, FirstPg^.Key);
- FREEMEM(FileBuffer, FileBufSize);
- WClose;
- SpaceStr := '─';
- END;
- { ------------------------------------------------------------------------- }
-
- END.
-