'===========================================================================
' Subject: HEX EDITOR V1.00 (ONLY VIEWER)     Date: 09-11-98 (09:01)       
'  Author: William Deer                       Code: QB, QBasic, PDS        
'  Origin: ag31235@student.uq.edu.au        Packet: BINARY.ABC
'===========================================================================
DECLARE SUB Hex2Ascii (HEXI$, ASCII&)
DECLARE SUB Box (X1!, Y1!, X2!, Y2!, Gutz!)
DECLARE SUB ReadFile (Offset AS LONG)
DECLARE SUB Border (A!, B!)
DECLARE SUB Info (A!, B!)

' HexEditor v1.00
' by RedBear.
'
' This program will pull up any size file. I have tested it to 145Mb files and
' it works well.
' you will have specify a file to read (Line 30) if you don't want to read
' The COMMAND.COM
'
' FIX1 16/3/98 Well isn't my face red. I have been using this program for weeks and
' the address display on the left has been one value too high all the time.
' DUMB DUMB DUMB DUMB
'
' FIX2 09/08/98 Was using the qbasic hex conversion features which have BUGS.
' Installed my Hex2Ascii Subrountine to fix problem.
'
' For more information about Keys and how to use this program, look in the
' Help Subrountine.
'
' Well, feel free to use this program, but try to give me a mention if you
' feel like it.

SCREEN 0
WIDTH 80
CLS
OPEN "C:\command.com" FOR BINARY AS #1
FileLength& = LOF(1)
LastScreen& = FileLength& - &H140
DIM SHARED Char(341) AS STRING * 1
DIM BookMark(10) AS LONG

FOR CC = 1 TO 10
 BookMark(CC) = (FileLength& / 11) * CC
NEXT CC


HexShowRow = 2
HexShowCol = 1
ColorOffset = 10:                ColorOffsetB = 0
ColorHex = 15:                   ColorHexB = 0
ColorASCII = 14:                 ColorASCIIB = 0
ColorUnprintable = 15:           ColorUnprintableB = 0

Offset& = 0


Refresh:
CALL Border(9, 0)
CALL Info(13, 0)
GOSUB Scroll
CALL ReadFile(Offset&)

' Now we must display the information.
Row = 0
FOR A& = Offset& TO Offset& + &H140 STEP &H10
 Row = Row + 1
 HEXA$ = HEX$(A&)
 LOCATE Row + HexShowRow, HexShowCol + 1:
        COLOR ColorOffset, ColorOffsetB
        PRINT STRING$(8 - LEN(HEXA$), "0"); HEXA$;
 LOCATE Row + HexShowRow, HexShowCol + 11

 FOR B = 1 TO 13 STEP 4
  FOR C = 1 TO 4
   Value% = (16 * (Row - 1)) + B + C - 1
   HexChar$ = HEX$(ASC(Char(Value%)))
        COLOR ColorHex, ColorHexB
   PRINT STRING$(2 - LEN(HexChar$), "0"); HexChar$;
   PRINT " ";
  NEXT C
  IF B < 10 THEN PRINT " ";
 NEXT B
 Mask$ = ""
 LOCATE Row + HexShowRow, HexShowCol + 63
 FOR D = 1 TO 16
  COLOR ColorASCII, ColorASCIIB
  Newbie$ = Char(((Row - 1) * 16) + D)
  SELECT CASE Newbie$
        CASE CHR$(7) TO CHR$(13), CHR$(0)
         COLOR ColorUnprintable, ColorUnprintableB
         Newbie$ = "."

  END SELECT
 
  PRINT Newbie$;
 NEXT D
NEXT A&
GOTO Inkey.Loop

END
' KEYBOARD FILTERING ROUNTINE.
' This rountine is my keyboard inputing rountine. It filters out individual
' characters
Inkey.Loop:
        Key.Hit$ = INKEY$
        IF Key.Hit$ = "" THEN GOTO Inkey.Loop:
        Key.Hit.Length% = LEN(Key.Hit$)

        IF Key.Hit.Length% = 1 THEN
                ' Key hit is a simple key.
                Key.Hit.Value% = ASC(Key.Hit$)
                SELECT CASE Key.Hit.Value%
                        CASE IS = 27:
                                ' Escape Rountine
                                CLOSE
                                END
                        CASE 71, 103
                                ' The Letter <G> or <g>
                                GOSUB GoToRegion
                                GOTO Refresh
                        CASE 49 TO 57
                                ' BookMark 1 to 9
                                Offset& = BookMark(Key.Hit.Value% - 48)
                                GOTO Refresh
                        CASE 48
                                ' BookMark 0
                                Offset& = BookMark(10)
                                GOTO Refresh

                        CASE ELSE
                        ' Well, it wasn't the keys above
                       GOTO Inkey.Loop:
                END SELECT
                GOTO Inkey.Loop:
        ELSE
                        IF Key.Hit.Length% > 2 THEN
                                ' Something else is wrong
                                GOTO Inkey.Loop:
                                ELSE
                                ' Everything's OK
                        END IF

                        ' Key hit is a complex key,
                        ' 2 digits with the first one a 0
                        Complex.Key$ = RIGHT$(Key.Hit$, 1)
                        Complex.Key.Value% = ASC(Complex.Key$)


                SELECT CASE Complex.Key.Value%

                                CASE 120 TO 129
        ' Alt 1 to Alt 0
        Actual = Complex.Key.Value% - 119
        BookMark(Actual) = Offset&
        GOTO Refresh
                                CASE IS = 71:     ' <Home>
        ' Home key will send the listing to the beginning of the file
        Offset& = 0
        GOTO Refresh
                                CASE IS = 79:     ' <End>
        ' End Key will send the listing to the end of the file.
        Offset& = LastScreen&
        GOTO Refresh
                                CASE IS = 72:     ' <Up Arrow>
        ' The up key will decrement the listing one line &10
        Offset& = Offset& - &H10
        IF Offset& < 0 THEN Offset& = 0
        GOTO Refresh

                                CASE IS = 80:     ' <Down Arrow>
        ' The down key will increment the listing one line &H10
        Offset& = Offset& + &H10
        IF Offset& > LastScreen& THEN Offset& = LastScreen&
        GOTO Refresh
       
                                CASE IS = 75:     ' <Left Arrow>
        ' Left arrow key will decrement the list 1 byte
        Offset& = Offset& - &H1
        IF Offset& < 0 THEN Offset& = 0
        GOTO Refresh
       
                                CASE IS = 77:     ' <Right Arrow>
        ' Right arrow key will increment the list 1 byte
        Offset& = Offset& + &H1
        IF Offset& > LastScreen& THEN Offset& = LastScreen&
        GOTO Refresh

                                CASE IS = 73:     ' <Page Up>
        ' Page Up will jump an entire screen
        Offset& = Offset& - &H140
        IF Offset& < 0 THEN Offset& = 0
        GOTO Refresh
                                CASE IS = 81:     ' <Page Down>
        ' Page Up will down an entire screen
        Offset& = Offset& + &H140
        IF Offset& > LastScreen& THEN Offset& = LastScreen&
        GOTO Refresh



                                CASE IS = 82:     ' <Insert>
                                CASE IS = 83:     ' <Delete>
                           
                                CASE ELSE
                                ' Key pressed not accounted for
                                GOTO Inkey.Loop
                END SELECT
        END IF
        GOTO Inkey.Loop

Scroll:
' This piece will plot the position of the screen over the bottom line.
FOR CC% = 1 TO 10
  Position% = INT((BookMark(CC%) / FileLength&) * 79)
  COLOR 7, 0: LOCATE 24, Position% + 1: PRINT HEX$(CC%);
NEXT CC%
Position% = INT((Offset& / FileLength&) * 79)
COLOR 12, 0: LOCATE 24, Position% + 1: PRINT "²";

RETURN


GoToRegion:
' This rountine, called by the KeyInput Region asks the user for a new
' Offset value, checks that it is valid, and then updates the Offset value
' and returns to the main part of the program

COLOR 12, 0:
XXX = 10
YYY = 10

CALL Box(XXX, YYY, XXX + 25, YYY + 4, 1)
COLOR 15, 0
LOCATE YYY + 1, XXX + 2: PRINT "Goto Which Address ? ";
COLOR 14, 0
LOCATE YYY + 3, XXX + 2: PRINT "Enter Nothing to cancel";
COLOR 15, 0
LOCATE YYY + 2, XXX + 2: INPUT "&H"; VVV$
IF VVV$ = "" THEN GOTO EndOfGotoRegion
CALL Hex2Ascii(VVV$, VV&)
'VV& = VAL("&H" + VVV$)
IF VV& <= LastScreen& AND VV& >= 0 THEN Offset& = VV&
EndOfGotoRegion:

RETURN

SUB Border (A, B)
' Draws a border around the Hex World
COLOR A, B
LOCATE 2, 1
PRINT "ÚÄÄÄÄÄÄÄÄÂ";
PRINT "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ";
PRINT "ÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿";
FOR C = 3 TO 23
 LOCATE C, 1: PRINT "³";
 LOCATE C, 10: PRINT "³";
 LOCATE C, 63: PRINT "³";
 LOCATE C, 80: PRINT "³";
NEXT C
LOCATE 24, 1
PRINT "ÀÄÄÄÄÄÄÄÄÁ";
PRINT "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ";
PRINT "ÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ";

END SUB

SUB Box (X1, Y1, X2, Y2, Gutz)
' Yehh Yehh you know what it does.

Dx = X2 - X1
Dy = Y2 - Y1

LOCATE Y1, X1: PRINT "Ú" + STRING$(Dx - 1, "Ä") + "¿";
LOCATE Y2, X1: PRINT "À" + STRING$(Dx - 1, "Ä") + "Ù";
FOR YY = Y1 + 1 TO Y2 - 1
 LOCATE YY, X1: PRINT "³";
 LOCATE YY, X2: PRINT "³";
 IF Gutz = 1 THEN LOCATE YY, X1 + 1: PRINT STRING$(Dx - 1, " ");
NEXT YY

END SUB

SUB Help
' HexEditor v1.00
' by RedBear.                           Designed from 21/01/98 onwards
'
' This program does not EDIT (yet!!). I wrote this program to assist me in
' reading long datafiles, which were stored on CD-ROM. Hence I had no reason
' to edit the files, so I left out the editing procedures.

' Keys
'
' Home          : go to beginning of file
' End           : go to the end   of file
' Page Up       : jump  up  one screen in file
' Page Down     : jump down one screen in file
' Cursor Up     : scroll up one line   in file
' Cursor Down   : scroll down one line in file

' Esc           : Escapes from file and exits

' <G> is a hotkey to the Goto Menu. It allows you to quickly jump to any
' address in the file. Also included are Points, access by hitting 1-9,A.
' These points are chosen initially by the program, but can be reassigned
' by the user by pressing keys Alt-<1> thru to Alt-<9> and Alt-<A>.

' <F1> has not yet been implemented because , well, the keys are really simple.




                SELECT CASE Complex.Key.Value%
                                CASE IS = 30:     ' <ALT> <A/a>
                                CASE IS = 48:     ' <ALT> <B/b>
                                CASE IS = 46:     ' <ALT> <C/c>
                                CASE IS = 32:     ' <ALT> <D/d>
                                CASE IS = 18:     ' <ALT> <E/e>
                                CASE IS = 33:     ' <ALT> <F/f>
                                CASE IS = 34:     ' <ALT> <G/g>
                                CASE IS = 35:     ' <ALT> <H/h>
                                CASE IS = 23:     ' <ALT> <I/i>
                                CASE IS = 36:     ' <ALT> <J/j>
                                CASE IS = 37:     ' <ALT> <K/k>
                                CASE IS = 38:     ' <ALT> <L/l>
                                CASE IS = 50:     ' <ALT> <M/m>
                                CASE IS = 49:     ' <ALT> <N/n>
                                CASE IS = 24:     ' <ALT> <O/o>
                                CASE IS = 25:     ' <ALT> <P/p>
                                CASE IS = 16:     ' <ALT> <Q/q>
                                CASE IS = 19:     ' <ALT> <R/r>
                                CASE IS = 31:     ' <ALT> <S/s>
                                CASE IS = 20:     ' <ALT> <T/t>
                                CASE IS = 22:     ' <ALT> <U/u>
                                CASE IS = 47:     ' <ALT> <V/v>
                                CASE IS = 17:     ' <ALT> <W/w>
                                CASE IS = 45:     ' <ALT> <X/x>
                                CASE IS = 21:     ' <ALT> <Y/y>
                                CASE IS = 44:     ' <ALT> <Z/z>

                                CASE 120 TO 129
                                        ' Alt 1 to Alt 0
                                CASE IS = 130:    ' <ALT> <-/_>
                                CASE IS = 131:    ' <ALT> <=/+>
                                CASE IS = 71:     ' <Home>
        
                                CASE IS = 79:     ' <End>
                                CASE IS = 72:     ' <Up Arrow>
                                CASE IS = 80:     ' <Down Arrow>
                                CASE IS = 75:     ' <Left Arrow>
                                CASE IS = 77:     ' <Right Arrow>
                                CASE IS = 73:     ' <Page Up>
                                CASE IS = 81:     ' <Page Down>


                                CASE IS = 82:     ' <Insert>
                                CASE IS = 83:     ' <Delete>
                          
                                CASE ELSE
                                ' Key pressed not accounted for
                                
                END SELECT



END SUB

SUB Hex2Ascii (HEXI$, ASCII&)
'
' This Subroutine should help get around an annoying Quirk in Qbasic.
' When given a string containing Hex (with NO &H) at beginning,
' it will calculate the appropriate ASCII value
ASCII& = 0
FOR A = 1 TO 4
 Power = 16 ^ (4 - A)
 B$ = MID$(HEXI$, A, 1)
 ASCII& = ASCII& + (VAL("&H" + B$) * Power)
NEXT A

END SUB

SUB Info (A, B)
' This subrountine will display information like arrow keys and that sort
' of thing/

COLOR A, B
LOCATE 1, 1
COLOR 15, 0: PRINT "H";
COLOR 7, 0: PRINT "ex";
COLOR 15, 0: PRINT "V";
COLOR 7, 0: PRINT "iew";
PRINT " v";
COLOR 4, 0: PRINT "1";
COLOR 7, 0: PRINT ".";
COLOR 4, 0: PRINT "00";
COLOR 7, 0: PRINT " by ";
COLOR 15, 0: PRINT "R";
COLOR 12, 0: PRINT "ed";
COLOR 15, 0: PRINT "B";
COLOR 12, 0: PRINT "ear";

COLOR A, B
PRINT "  <";
COLOR 15, 0: PRINT "Esc";
COLOR A, B
PRINT ">";
COLOR 14, 0
PRINT " Quit  ";

COLOR A, B
PRINT "<";
COLOR 15, 0: PRINT "F1";
COLOR A, B
PRINT ">";
COLOR 14, 0
PRINT " Help  ";

COLOR A, B:             PRINT "<";
COLOR 15, 0:            PRINT CHR$(27); CHR$(24); CHR$(25); CHR$(26); " PgUp PgDn Home End";
COLOR A, B:             PRINT ">";
COLOR 14, 0:            PRINT " Move";

LOCATE 25, 1
COLOR A, B:             PRINT "<";
COLOR 15, 0:            PRINT "G";
COLOR A, B:             PRINT ">";
COLOR 14, 0:            PRINT "oto  ";

COLOR A, B:             PRINT "<";
COLOR 15, 0:            PRINT "Alt-1..0";
COLOR A, B:             PRINT ">";
COLOR 14, 0:            PRINT " Set Bookmark ";

COLOR A, B:             PRINT "<";
COLOR 15, 0:            PRINT "1..0";
COLOR A, B:             PRINT ">";
COLOR 14, 0:            PRINT " Goto Bookmark ";







END SUB

SUB ReadFile (Offset AS LONG)

FOR A& = 1 TO 341
 GET #1, Offset& + A&, Char(A&)
NEXT A&

END SUB
