'===========================================================================
' Subject: ASCII TEXT VIEWER V1.1             Date: 07-29-98 (00:44)       
'  Author: Anti Ramst                         Code: QB, QBasic, PDS        
'  Origin: margus@peak.edu.ee               Packet: TEXT.ABC
'===========================================================================
'                   --Text Viewer v1.1 by Anti Ramst--
'                              (ASCII only)
'
'                       * Full text scrolling
'                       * View files of ANY size
'
'          Differences from v1.0:
'                       * A few bug fixes
'                       * PgUp/PgDn Home/End support
'                       * Shift functions
'
'         I've tried to work out all the bugs scince the last version
'      which was a kind of a 'test version'. The basic idea of the
'      program is simple - to use a string array to make a scrolling
'      ASCII file viewer, pretty similar to WpView (NC text viewer).
'      So what, if it uses up a whole lot of string space? Who cares??
'         Use the arrow keys and PgUP/PgDn Home/End to move around in
'      the file. Hold down the Shift key to make latteral movement easyer:
'      Shift+ L or R arrow - move 25 columns
'      Shift+ End          - end of line
'      Shift+ Home         - beginning of line
'            The FUNCTION CtrKey was made by someone else (the source
'            KEYS.BAS was anonymous), I only modified it.
'
'         I don't recommend running this from windows -
'      that never has a good impact on the speed of a Qbasic source.
'
'         I admit the code is pretty hard to understand, but -
'      it gets the job done!
'
'              Please mail your comments and/or suggestions to:
'                            MARGUS@PEAK.EDU.EE
'                Also, please report any bug(s) you may meet
'
'       !!! Don't forget to give me credit if you use any part of
'           this program in your own code !!!
'_____________________________________________________________________________
'
'
' 198 = nine pages (22*9), 176 = eight pages (22*8)

DECLARE FUNCTION CtrKey% ()

PATH$ = "e:\qbasic\anti\"    'Text Viewer will list the dir spec. here

ON ERROR GOTO ErrorHandler

SCREEN 0



'      Do some palette modification

OUT &H3C7, 9: R = INP(&H3C9): G = INP(&H3C9): B = INP(&H3C9)
OUT &H3C8, 0: OUT &H3C9, R: OUT &H3C9, G: OUT &H3C9, B - 20
OUT &H3C8, 7: OUT &H3C9, 40: OUT &H3C9, 40: OUT &H3C9, 55
OUT &H3C8, 1: OUT &H3C9, 0: OUT &H3C9, 0: OUT &H3C9, 35
OUT &H3C8, 2: OUT &H3C9, 10: OUT &H3C9, 10: OUT &H3C9, 45
OUT &H3C8, 3: OUT &H3C9, 0: OUT &H3C9, 23: OUT &H3C9, 43
OUT &H3C8, 4: OUT &H3C9, 63: OUT &H3C9, 53: OUT &H3C9, 33

Page = 22 '-- do not change
PerCentFormat$ = "###%"
ColFormat$ = "Col ###"

FOR BuildString = 1 TO 80
        edgeString$ = edgeString$ + CHR$(205)
NEXT

CLS

FILES PATH$
s1$ = "±²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û²±°±°Text Vie"
s2$ = "wer v1.1²Û²±°±²Û²±°±²Û²±°±²Û²±°±²Û±²Û²±°"
LOCATE 23: COLOR 3, 1: PRINT s1$: LOCATE 23, 41: COLOR 1, 3: PRINT s2$
COLOR 7, 0
INPUT ; "Name >", NAME$

DIM Row$(198)    ' DIM the string array to hold 9 pages (22 lines each)

OPEN PATH$ + NAME$ FOR INPUT AS #1

DO WHILE NOT EOF(1)   ' Find out the total length of the file opened
LINE INPUT #1, Check$
Length = Length + 1
LOOP
CLOSE #1

OPEN PATH$ + NAME$ FOR INPUT AS #1  ' Load the first 9 pages or less,
DO WHILE NOT EOF(1) AND R < 198     ' if the file is shorter than 198 lines
R = R + 1
LINE INPUT #1, Row$(R)
IF LEN(Row$(R)) < 80 THEN Row$(R) = Row$(R) + SPACE$(80 - LEN(Row$(R)))
' the above line adds a bunch of spaces to the end of the current row$.
' That makes erasing the last line faster when scrolling. The reason why
' we only add spaces to a string shorter than 80 chars is simple:
' otherwise the little arrows at the edge of the screen would pop up to
' show a long line, even though there's nothing there but a bunch of spaces.
LOOP
CLOSE #1
CLS
               COLOR 2, 1
                LOCATE Page + 1, 1: PRINT edgeString$
               COLOR 7, 0


        FOR a = 1 TO Page   ' Print the first screenful
        LOCATE a
        IF LEN(Row$(a + offY)) > 80 THEN
                PRINT LEFT$(Row$(a + offY), 80)
                COLOR 4
                LOCATE a, 80: PRINT ">"
                COLOR 7
        END IF
        IF LEN(Row$(a + offY)) <= 80 THEN PRINT Row$(a + offY)
        NEXT

IF Length <= 22 THEN PerCent = 100 ELSE PerCent = INT((offY * 100) / (Length - 22))
COLOR 7, 1
LOCATE 23, 75: PRINT USING PerCentFormat$; PerCent
LOCATE 23, 60: PRINT USING ColFormat$; offX
COLOR 7, 0

' Below is the main loop
DO
    SELECT CASE INKEY$
'____________________________________________________________________________
CASE CHR$(0) + CHR$(80)

      IF offY + 22 < Length THEN offY = offY + 1
      IF offY - offYSet > 176 THEN offYSet = offYSet + 176: GOSUB LoadNext
      GOSUB MoveScreen1
'____________________________________________________________________________
CASE CHR$(0) + CHR$(72)
      IF offY + 1 > 1 THEN offY = offY - 1
      IF offY - offYSet < 1 AND offY > 1 THEN offYSet = offYSet - 176: GOSUB LoadPrevious
      GOSUB MoveScreen1
'____________________________________________________________________________
CASE CHR$(0) + CHR$(77)
       IF CtrKey% = 1 THEN
         IF offX < 150 THEN offX = offX + 25: GOSUB MoveScreen1 ELSE offX = 175: GOSUB MoveScreen1
        ELSEIF offX < 175 THEN offX = offX + 1: GOSUB MoveScreen1
       END IF
'____________________________________________________________________________
CASE CHR$(0) + CHR$(75)
       IF CtrKey% = 1 THEN
         IF offX > 25 THEN offX = offX - 25: GOSUB MoveScreen1 ELSE offX = 0: GOSUB MoveScreen1
        ELSEIF offX > 0 THEN offX = offX - 1: GOSUB MoveScreen1
       END IF
'____________________________________________________________________________
CASE CHR$(27): SCREEN 2: SCREEN 0: END
' We switch to screen 2 before exiting because
' the palette modification would otherwise stay
' resident and make a mess of DOS or NC...
'----------------------------------------------------------------------------
CASE CHR$(0) + CHR$(81)
        IF offY + 22 < Length THEN GOSUB PageDown
'----------------------------------------------------------------------------
CASE CHR$(0) + CHR$(73)
        IF offY > 0 THEN GOSUB PageUp
'----------------------------------------------------------------------------
CASE CHR$(0) + CHR$(71)
        IF CtrKey% = 1 THEN
                offX = 0: GOSUB MoveScreen1
                ELSEIF offY > 0 THEN offX = 0: GOSUB Home
        END IF
'----------------------------------------------------------------------------
CASE CHR$(0) + CHR$(79)
        IF CtrKey% = 1 THEN
                offX = 175: GOSUB MoveScreen1
                ELSEIF offY + 22 < Length THEN offX = 0: GOSUB Endd
        END IF
'----------------------------------------------------------------------------
   END SELECT
LOOP
'==========================================
'==========================================

' Subprogram to load the next portion of the loaded file
LoadNext:
'SOUND 1500, .5
OPEN PATH$ + NAME$ FOR INPUT AS #1

DO WHILE R < offY + 197 AND NOT EOF(1) ' Put the file pointer to
R = R + 1                              ' the correct position in
LINE INPUT #1, Check$                  ' preparation for sequential input.
LOOP
R = 0

DO WHILE NOT EOF(1) AND R < 198        ' Input the requiered portion
R = R + 1
LINE INPUT #1, Row$(R)
IF LEN(Row$(R)) < 80 THEN Row$(R) = Row$(R) + SPACE$(80 - LEN(Row$(R)))
LOOP
CLOSE #1
FOR a = 1 TO 15: a$ = INKEY$: NEXT 'Clear the kybrd buffer to prevent jumping
RETURN
'==========================================
'==========================================

' Subprogram to load the previous portion of the loaded file
LoadPrevious:
'SOUND 1000, .5
OPEN PATH$ + NAME$ FOR INPUT AS #1

R = 0
DO WHILE R < offY - 176        ' Put the file pointer to
R = R + 1                      ' the correct position in
LINE INPUT #1, Check$          ' preparation for sequential input.
LOOP
R = 0
DO WHILE R < 198 AND NOT EOF(1)     ' Input the requiered portion
R = R + 1
LINE INPUT #1, Row$(R)
IF LEN(Row$(R)) < 80 THEN Row$(R) = Row$(R) + SPACE$(80 - LEN(Row$(R)))
LOOP
CLOSE #1
FOR a = 1 TO 15: a$ = INKEY$: NEXT
RETURN
'==========================================
'==========================================


PageUp:
IF offY > 0 THEN
        IF offY < 21 THEN offY = 0 ELSE offY = offY - 21
END IF
IF offY - offYSet < 1 AND offY > 1 THEN
        IF offY - offYSet < 0 THEN
         HoldValue = offY
         offY = offYSet
         offYSet = offYSet - 176
         GOSUB LoadPrevious
         offY = HoldValue
         ELSE offYSet = offYSet - 176: GOSUB LoadPrevious
        END IF
END IF
GOSUB MoveScreen1
FOR a = 1 TO 15: a$ = INKEY$: NEXT
RETURN
'==========================================
'==========================================


PageDown:
IF offY < Length - 22 THEN
  IF offY > Length - 42 THEN offY = offY + ((Length - 22) - offY) ELSE offY = offY + 21
END IF
IF offY - offYSet > 176 THEN
        IF offY - offYSet <> 177 THEN
         HoldValue = offY
         offY = offYSet + 177
         offYSet = offYSet + 176
         GOSUB LoadNext
         offY = HoldValue
          ELSE offYSet = offYSet + 176: GOSUB LoadNext
        END IF
END IF
GOSUB MoveScreen1
FOR a = 1 TO 15: a$ = INKEY$: NEXT
RETURN
'==========================================
'==========================================


Home:
IF offYSet = 0 THEN offY = 0: GOSUB MoveScreen1: RETURN
IF offYSet > 0 THEN : offY = 0: offYSet = 0: GOSUB LoadPrevious: GOSUB MoveScreen1: RETURN
'==========================================
'==========================================


Endd:
IF Length <= 198 THEN offY = Length - 22: GOSUB MoveScreen1: RETURN
IF Length > 198 THEN
    offYSet = 0
      DO UNTIL offYSet + 176 >= Length
      offYSet = offYSet + 176
      LOOP
offY = offYSet + 1: GOSUB LoadNext
offY = Length - 22: GOSUB MoveScreen1
RETURN
END IF

     
'==========================================
'==========================================

' The following sub draws/redraws the screen.

MoveScreen1:
        FOR a = 1 TO Page
        LOCATE a
        IF LEN(Row$(a + (offY - offYSet))) > 80 AND offX = 0 THEN
                PRINT LEFT$(Row$(a + (offY - offYSet)), 80)
                COLOR 4
                LOCATE a, 80: PRINT ">"
                COLOR 7
        END IF
        IF LEN(Row$(a + (offY - offYSet))) - offX > 80 AND offX > 0 THEN
                PRINT MID$(Row$(a + (offY - offYSet)), offX + 1, 80)
                COLOR 4
                LOCATE a, 80: PRINT ">"
                LOCATE a, 1: PRINT "<"
                COLOR 7
        END IF
        IF LEN(Row$(a + (offY - offYSet))) - offX <= 80 AND offX > 0 THEN
                IF offX <= LEN(Row$(a + (offY - offYSet))) THEN
                        textX = LEN(Row$(a + (offY - offYSet))) - offX
                        PRINT RIGHT$(Row$(a + (offY - offYSet)), textX) + SPACE$(80 - textX)
                        COLOR 4
                        LOCATE a, 1: PRINT "<"
                        COLOR 7
                END IF
                IF offX > LEN(Row$(a + (offY - offYSet))) AND Length - a > 0 THEN
                        COLOR 4
                        PRINT SPACE$(80): LOCATE a: PRINT "<"
                        COLOR 7
                END IF
        END IF
                       
        IF LEN(Row$(a + (offY - offYSet))) <= 80 AND offX = 0 THEN PRINT Row$(a + (offY - offYSet))
       
        NEXT
        COLOR 7, 1
        PerCent = INT((offY * 100) / (Length - 22))
        IF Length <= 22 THEN PerCent = 100
        LOCATE 23, 75: PRINT USING PerCentFormat$; PerCent
        LOCATE 23, 60: PRINT USING ColFormat$; offX
        COLOR 7, 0
        
RETURN
'==========================================
'==========================================


' You guessed it! This is the error handler
ErrorHandler:
COLOR 12
SELECT CASE ERR
        CASE 53: PRINT " File not found!"; : SLEEP 1: SCREEN 2: SCREEN 0: END
        CASE ELSE: PRINT "Something went wrong... Bye!"; : SLEEP 1: SCREEN 2: SCREEN 0: END
END SELECT

FUNCTION CtrKey%

  DEF SEG = 0
  KeySts% = PEEK(1047)

  CtrKey% = 0

  KeySts% = KeySts% + 1
  IF KeySts% > 128 THEN KeySts% = KeySts% - 128
  IF KeySts% > 64 THEN KeySts% = KeySts% - 64
  IF KeySts% > 32 THEN KeySts% = KeySts% - 32
  IF KeySts% > 16 THEN KeySts% = KeySts% - 16
  IF KeySts% > 8 THEN KeySts% = KeySts% - 8
  IF KeySts% > 4 THEN KeySts% = KeySts% - 4
  IF KeySts% > 2 THEN KeySts% = KeySts% - 2: LeftShift% = 1
  IF KeySts% > 1 THEN KeySts% = KeySts% - 1: RightShift% = 1
IF LeftShift% OR RightShift% THEN CtrKey% = 1
END FUNCTION
