home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
BASIC
/
PANSI2
/
PANSI2.BAS
< prev
next >
Wrap
BASIC Source File
|
1993-05-30
|
29KB
|
928 lines
'PANSI2.BAS
'ANSI emulator for QuickBASIC 4.5(maby PDS) v1.50
'By Richard Geldreich July 24, 1992
'Version 2.0 completed May 30, 1993 (slow, eh?), by John Gallas
'This program is hereby put into the public domain. You may do basically
'whatever you want with it, but we ask that you give the authors some credit
'if you use this program in one of your own programs.
'Don't forget that "CALL INTERRUPT" is used- "INTRPT.OBJ" in the QB.LIB
'library...
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'! Don't forget to modify the "SendStatus" procedure for your !
'! comm package! !
'! You also should modify PrintString for QB4.5 or PDS !
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'NOTE: This program assumes that the current segment is always
'pointing twards the video buffer!! If you change the current
'segment don't forget to change it back or sparks will fly when you
'write to the screen! (see GetVSeg)
'** Additions to version 2.0 **
'All I did was add the Avatar/0+ codes. (Note: There is an additional file
'included in the archive called ANSIAVT.ARJ which contains all of the stats
'for ANSI and Avatar.) The incredible modular design was all done by Rich.
'In fact, if it wasn't put together so well, it would've been VERY hard to
'add the Avatar support.
'Info on usage:
'Boundaries x,y- makes sure that x and y are inside the maximum and minimum
'x and y coordinates, and if they aren't, it puts them there.
'ClearScreen- used internally by the PrintAnsi procedure- you may
'use it to clear the current window(the current background color
'is used in the clear). The cursor is set to the upper left hand corner
'of the window after the window is cleared.
'CursorControl A- if A is non-zero then the SetCursor routine(which
'is called by PrintAnsi) will update the cursor whenever it is moved.
'If it is zero then SetCursor won't touch the cursor's position.
'GetVSeg- Returns the current video segment.
'Init- you must call this before PrintAnsi can work properly. Sets
'up the color translation table, sets the window to the current screen
'page and size, sets the cursor to the upper-left hand corner of the
'window and tests the adapter to see if it's monochrome or color. All
'states are reset when this procedure is called.
'Music A- if A is not zero, then ANSI music is enabled.
'PrintAnsi Char- where Char is an ASCII code from 0-255. Recognizes
'ANSI escape sequences and Avatar/0+ codes. Processes the character and
'updates the display, if needed.
'PrintString A$- prints a string to the display. Calls PrintAnsi for
'each character. Don't forget to modify this for PDS/QuickBASIC.
'ScrollUpScreen- scrolls up the current window. Uses a BIOS call.
'Normally used internally by PrintAnsi.
'SendStatus- sends a CPR sequence to the receiver.
'In other words, SendStatus will output the current X and Y coordinates
'of the cursor to the remote terminal. Used by some BBS's and doors
'to see if the user's terminal has ANSI capibilities. You must modify
'this procedure to output the status string to your comm package!
'(this is used internally by PrintAnsi)
'SetCursor- moves the cursor to its correct position(it doesn't turn
'it on however- use the LOCATE , , 1 command to do that). This procedure
'should work on all adapters, but I haven't tested it out on many
'cards yet... Use this to restore the cursor to where it should be
'after you move it.
'SetWindow WorkPage, Lx,Ly,Hx,Hy- defines a window where all text
'is printed. if WorkPage is -1, then the BIOS data area is examined for
'the current screen page, otherwise WorkPage must indicate which page to
'write to. If Lx is -1, the the window will take up the entire screen
'otherwise Lx and Ly are the upper-left lines of the window(where
'1,1 is the upper corner of the screen) and Hx and Hy are the lower-right
'coordinates of the window.
' The current cursor position is moved to the upper left corner of the
'new window. If the coordinates passed are invalid, the window is not
'modified.
'Recurse Buffer$- Used with the ^V^Y Avatar/0+ repeat string code, repeats
'Buffer$ ASC(AvtBuf$) times.
' That's all! You can add more functions if you need them; I've
'documented the PrintAnsi procedure enough for you to get
'a good idea of how it works.
DEFINT A-Z
DECLARE SUB ClearScreen ()
DECLARE SUB CursorControl (a%)
DECLARE FUNCTION GetVSeg% ()
DECLARE SUB Init ()
DECLARE SUB Music (a%)
DECLARE SUB PrintAnsi (char%)
DECLARE SUB PrintString (b$)
DECLARE SUB Recurse (Buffer$)
DECLARE SUB ScrollUpScreen ()
DECLARE SUB SendStatus (x%, y%)
DECLARE SUB SetCursor ()
DECLARE SUB SetWindow (WorkPage%, Lx%, Ly%, Hx%, Hy%)
DECLARE SUB Scroll (Direction%, Top%, Left%, Bottom%, Right%, Lines%, Attr%)
DECLARE SUB Boundaries (x%, y%)
DECLARE SUB playme (a$)
TYPE RegType
ax AS INTEGER
bx AS INTEGER
cx AS INTEGER
dx AS INTEGER
bp AS INTEGER
si AS INTEGER
di AS INTEGER
flags AS INTEGER
END TYPE
DIM SHARED Xpos, Ypos 'cursor's position
DIM SHARED MinX, MinY, MaxX, MaxY 'current window
DIM SHARED SaveX, SaveY 'used by SCR and RCP
DIM SHARED Colors(7), Attribute
DIM SHARED CursorOn, VideoSegment, VideoOffset, CursorAddress, BytesPerLine
DIM SHARED Monochrome, CRT 'monochrome adapter flag
DIM SHARED ANSIMusic, MusicLevel
DIM SHARED Level
DIM SHARED Reserve, AvtBuf$, Insert, AvtFunc, tempbuf$
CONST True = -1, False = NOT True 'usefull stuff
'******START OF TEST PROGRAM
'The following code is not needed... It's only for testing!
'
'Init
'SetWindow -1, 2, 2, 79, 24
'LOCATE 1, 1: PRINT STRING$(2000, 219);
'SetCursor
'CursorControl 1
'OPEN "com1:2400,n,8,1" FOR RANDOM AS #1
'DO
' IF NOT EOF(1) THEN x$ = INPUT$(LOC(1), #1): PrintString x$
' a$ = INKEY$
' IF LEN(a$) THEN PRINT #1, a$;
'LOOP
SUB Boundaries (x, y)
IF x > MaxX THEN x = MaxX
IF x < MinX THEN x = MinX
IF y > MaxY THEN y = MaxY
IF y < MinY THEN y = MinY
END SUB
'Clears the current window. The cursor is also set to the upper-left hand
'corner of the window.
SUB ClearScreen
DIM Regs AS RegType
Regs.ax = &H600
a& = Attribute * 256&
IF a& > 32767 THEN a = a& - 65536 ELSE a = a&
Regs.bx = a
Regs.cx = (MinY * 256&) + MinX - 257
Regs.dx = (MaxY * 256&) + MaxX - 257
CALL INTERRUPT(&H10, Regs, Regs)
Xpos = MinX: Ypos = MinY
SetCursor
END SUB
'Enables or disables cursor updating.
SUB CursorControl (a)
IF a THEN
CursorOn = True
ELSE
CursorOn = False
END IF
END SUB
'Returns the current video segment.
FUNCTION GetVSeg
GetVSeg = VideoSegment
END FUNCTION
'Initializes everything.
SUB Init
DIM Regs AS RegType
'default color, white on black (or black on white??)
Attribute = 7
Level = 0: MusicLevel = 0 'reset levels
ANSIMusic = True 'ANSI music enabled
CursorOn = True 'cursor movement enabled
'set the color translation table
Colors(0) = 0: Colors(1) = 4: Colors(2) = 2: Colors(3) = 6
Colors(4) = 1: Colors(5) = 5: Colors(6) = 3: Colors(7) = 7
Regs.ax = 15 * 256
CALL INTERRUPT(&H10, Regs, Regs)
'if AL=7 then card is monochrome.
IF (Regs.ax AND 255) = 7 THEN
VideoSegment = &HB000
Monochrome = True
ELSE
VideoSegment = &HB800
Monochrome = False
END IF
DEF SEG = &H40
CRT = PEEK(&H63) + PEEK(&H64) * 256&
'Set segment to the screen.
DEF SEG = VideoSegment
'window defaults to screen's page & size
'Xpos, Ypos, SaveX, SaveY, MinX, MinY, MaxX, MaxY, VideoOffset and the
'cursor are set up within this procedure
SetWindow -1, -1, 0, 0, 0
END SUB
'Enables/Disables ANSI music...
SUB Music (a)
ANSIMusic = a
END SUB
'Prints an ASCII character on the screen; filters out ANSI escape sequences
'and Avatar sequences and parses and prints them.
SUB PrintAnsi (char) STATIC
DIM Parameters(10)
SELECT CASE Level
CASE 0
'normal mode
GOSUB ProcessChar
CASE 1
'Level=1 after a chr$(27) is received.
'valid escape sequence?
IF char <> 91 THEN
Level = 0
GOSUB ProcessChar
ELSE
'a valid escape sequence has been received
Level = 2
CurrentParameter = 0
NumParameters = 0
ValidParameter = False
FOR a = 0 TO 10: Parameters(a) = 1: NEXT
END IF
CASE 2
'inside an escape sequence
GOSUB ProcessCode
END SELECT
EXIT SUB
ProcessChar:
'processes a non-ANSI code
SELECT CASE char
'process CTRL-V
CASE 22
Reserve = -1
AvtBuf$ = ""
Level = 2
'process CTRL-Y
CASE 25
Reserve = 2
AvtBuf$ = ""
AvtFunc = 26
Level = 2
'process new page code
CASE 12
Attribute = 3
ClearScreen
'process escape character
CASE 27
Level = 1
Reserve = 0
'process enter
CASE 13
Xpos = MinX
SetCursor
'process line feed
CASE 10
Ypos = Ypos + 1
IF Ypos > MaxY THEN Ypos = MaxY: ScrollUpScreen
SetCursor
'process backspace(destructive)
CASE 8
IF Xpos > MinX THEN
Xpos = Xpos - 1
CursorAddress = CursorAddress - 2
POKE CursorAddress, 32: POKE CursorAddress + 1, Attribute
SetCursor
END IF
'process tab key(tab stops=8)
CASE 9
Xpos = ((Xpos \ 8) + 1) * 8
IF Xpos > MaxX THEN Xpos = MaxX
SetCursor
'process bell
CASE 7
'don't substitute a "BEEP" statement here!
'BEEP resets the cursor to where QB thinks it is!
SOUND 3140, 1.25
'any other character is sent to the screen
CASE ELSE
'prints a character to the screen
IF Insert THEN
y = (MaxX - Xpos - 1) * 2
y = y + CursorAddress
FOR x = MaxX - 1 TO Xpos STEP -1
POKE y, PEEK(y - 2)
POKE y + 1, PEEK(y - 1)
y = y - 2
NEXT x
END IF
POKE CursorAddress, char: POKE CursorAddress + 1, Attribute
CursorAddress = CursorAddress + 2
Xpos = Xpos + 1
IF Xpos > MaxX THEN
Xpos = MinX
Ypos = Ypos + 1
IF Ypos > MaxY THEN
Ypos = MaxY
ScrollUpScreen
END IF
SetCursor
ELSE
IF CursorOn THEN
Address = CursorAddress \ 2
OUT CRT, &HE
OUT CRT + 1, Address \ 256
OUT CRT, &HF
OUT CRT + 1, Address AND 255
END IF
END IF
END SELECT
RETURN
'processes a character within an ansi escape sequence
'non-valid characters are sent to the screen
ProcessCode:
'handles ANSI music...
IF MusicLevel > 0 THEN
SELECT CASE MusicLevel
'see if the "F" in "ESC[MF" is received...
CASE 1
IF char <> 70 THEN '"F"
MusicLevel = 0
Level = 0
GOSUB ProcessChar
ELSE
MusicLevel = 2
MusicString$ = ""
END IF
'Either add a char to the music string or play it...
CASE 2
IF char <> 14 THEN
'fall out if an escape character is received...
IF char = 27 THEN
MusicString$ = ""
MusicLevel = 0
Level = 0
GOSUB ProcessChar
'assume the character received to be part of the
'PLAY string
ELSE
MusicString$ = MusicString$ + CHR$(char)
END IF
ELSE
IF ANSIMusic THEN
'play the string- the PLAY command is in a seperate
'module to keep error checking out of this module
playme MusicString$
END IF
MusicString$ = ""
MusicLevel = 0
Level = 0
END IF
END SELECT
ELSE
' Reserve tells how many characters we're waiting for before our Avatar
' sequence has been completed. If its -1, it means we've recieved a
' CONTROL-V, and we're awaiting the command character before we do
' anything. If the command requires more characters to come through, it
' sets Reserve to the amount it needs, and it sets AvtFunc so we know
' which function to use the characters for when they get here.
IF Reserve THEN
IF Reserve = -1 THEN
Reserve = 0
SELECT CASE char
CASE 1
'^V^A, set attribute to next byte recieved
Reserve = 1
AvtFunc = char
AvtBuf$ = ""
Insert = False
CASE 2
'^V^B, set blink on
Attribute = Attribute OR 128
Level = 0
Insert = False
CASE 3
'^V^C, move cursor up 1
Ypos = Ypos - 1
IF Ypos < MinY THEN Ypos = MinY
SetCursor
Level = 0
Insert = False
CASE 4
'^V^D, move down
Ypos = Ypos + 1
IF Ypos > MaxY THEN Ypos = MaxY
SetCursor
Level = 0
Insert = False
CASE 5
'^V^E, move left
Xpos = Xpos - 1
IF Xpos < MinX THEN Xpos = MinX
SetCursor
Level = 0
Insert = False
CASE 6
'^V^F, move right
Xpos = Xpos + 1
IF Xpos > MaxX THEN Xpos = MaxX
SetCursor
Level = 0
Insert = False
CASE 7
'^V^G, clear to EOL
a = CursorAddress
FOR x = Xpos TO MaxX
POKE a, 32: POKE a + 1, Attribute: a = a + 2
NEXT
SetCursor
Level = 0
Insert = False
CASE 8
'^V^H, locate cursor at Y,X (next 2 bytes)
Reserve = 2
AvtBuf$ = ""
AvtFunc = char
Insert = False
CASE 9
'^V^I, Insert mode on
Insert = True
Level = 0
CASE 10
'^V^J, scroll area up, reserve the next 5 characters for our
'function.
Reserve = 5
AvtBuf$ = ""
AvtFunc = char
Insert = False
CASE 11
'^V^K, scroll down
Reserve = 5
AvtBuf$ = ""
AvtFunc = char
Insert = False
CASE 12
'^V^L, Clear block
Reserve = 3
AvtBuf$ = ""
AvtFunc = char
Insert = False
CASE 13
'^V^M, fill block to attr, char, etc
Reserve = 4
AvtBuf$ = ""
AvtFunc = char
Insert = False
CASE 14
'^V^N, delete char, scroll line left
a = CursorAddress
FOR x = Xpos TO MaxX - 1
POKE a, PEEK(a + 2): POKE a + 1, PEEK(a + 3): a = a + 2
NEXT
POKE a, 32
POKE a + 1, Attribute
SetCursor
Level = 0
Insert = False
CASE 25
'^V^Y, repeat string
Reserve = 1
AvtBuf$ = ""
AvtFunc = char
CASE ELSE
Level = 0
Reserve = 0
GOSUB ProcessChar
RETURN
END SELECT
ELSE
'reserve > 0
'Add it to our buffer
AvtBuf$ = AvtBuf$ + CHR$(char)
IF LEN(AvtBuf$) = Reserve THEN 'if we got all the chars we need
Reserve = 0
SELECT CASE AvtFunc
CASE 26 'repeat character C, N times
Level = 0
Reserve = 0
a = ASC(RIGHT$(AvtBuf$, 1))
b = ASC(LEFT$(AvtBuf$, 1))
z = CursorAddress
FOR x = 1 TO a
POKE z, b
POKE z + 1, Attribute
z = z + 2
Xpos = Xpos + 1
IF Xpos > MaxX THEN
Xpos = 1
Ypos = Ypos + 1
IF Ypos > MaxY THEN
Ypos = MaxY
ScrollUpScreen
END IF
END IF
NEXT x
SetCursor
CASE 1
'set attribute
Attribute = ASC(AvtBuf$)
SetCursor
Level = 0
Reserve = 0
CASE 8
'locate cursor at Y,X
Xpos = ASC(RIGHT$(AvtBuf$, 1))
Ypos = ASC(LEFT$(AvtBuf$, 1))
Boundaries Xpos, Ypos
Level = 0
Reserve = 0
SetCursor
CASE 10
'scroll up!
a = ASC(LEFT$(AvtBuf$, 1))
y = ASC(MID$(AvtBuf$, 2, 1))
x = ASC(MID$(AvtBuf$, 3, 1))
Y2 = ASC(MID$(AvtBuf$, 4, 1))
X2 = ASC(MID$(AvtBuf$, 5, 1))
'(Direction%, Top%, Left%, Bottom%, Right%, Lines%, Attr%)
Boundaries x, y
Boundaries X2, Y2
Scroll 0, y, x, Y2, X2, a, Attribute
SetCursor
Level = 0
Reserve = 0
CASE 11
'scroll down!
a = ASC(LEFT$(AvtBuf$, 1))
y = ASC(MID$(AvtBuf$, 2, 1))
x = ASC(MID$(AvtBuf$, 3, 1))
Y2 = ASC(MID$(AvtBuf$, 4, 1))
X2 = ASC(MID$(AvtBuf$, 5, 1))
'(Direction%, Top%, Left%, Bottom%, Right%, Lines%, Attr%)
Boundaries x, y
Boundaries X2, Y2
Scroll 1, y, x, Y2, X2, a, Attribute
SetCursor
Level = 0
Reserve = 0
CASE 12
'clear block
a = ASC(LEFT$(AvtBuf$, 1))
y = ASC(MID$(AvtBuf$, 2, 1))
x = ASC(MID$(AvtBuf$, 3, 1))
y = Ypos + y
x = Xpos + x
Boundaries x, y
Scroll 0, Ypos, Xpos, y, x, 0, Attribute
SetCursor
Level = 0
Reserve = 0
CASE 13 'toughie, fill block
At = ASC(LEFT$(AvtBuf$, 1))
c = ASC(MID$(AvtBuf$, 2, 1))
y = ASC(MID$(AvtBuf$, 3, 1))
x = ASC(MID$(AvtBuf$, 4, 1))
z = CursorAddress
Z2 = z
x = Xpos + x
y = Ypos + y
Boundaries x, y
FOR d = Ypos TO y - Ypos
FOR a = Xpos TO x - Xpos
POKE z, c
POKE z + 1, At
z = z + 2
NEXT a
z = Z2 + 160
Z2 = z
NEXT d
SetCursor
Level = 0
Reserve = 0
CASE 28
Level = 0
Reserve = 0
Recurse tempbuf$
SetCursor
tempbuf$ = ""
CASE 27
tempbuf$ = AvtBuf$
AvtBuf$ = ""
Reserve = 1
AvtFunc = 28
CASE 25
Reserve = ASC(AvtBuf$)
AvtBuf$ = ""
AvtFunc = 27
CASE ELSE
END SELECT
END IF
END IF
RETURN
END IF
'ANSI music
SELECT CASE char
CASE 77 '"M"
MusicLevel = 1
CASE 48 TO 57 '0-9
'all parameters should be lower than 199...
IF CurrentParameter < 199 THEN
CurrentParameter = CurrentParameter * 10 + (char - 48)
ValidParameter = True
ELSE
Level = 0
GOSUB ProcessChar
END IF
CASE 59
GOSUB MakeParameter '";"
'CUP-set cursor's position
CASE 72, 102 'H or f
GOSUB MakeParameter
Ypos = MinY + a - 1
a = Parameters(1): IF a = 0 THEN a = 1
Xpos = MinX + a - 1
IF Xpos > MaxX THEN Xpos = MaxX
IF Ypos > MaxY THEN Ypos = MaxY
SetCursor
Level = 0
'CUU- cursor up
CASE 65 'A
GOSUB MakeParameter
Ypos = Ypos - a
IF Ypos < MinY THEN Ypos = MinY
SetCursor
Level = 0
'CUD-cursor down
CASE 66 'B
GOSUB MakeParameter
Ypos = Ypos + a
IF Ypos > MaxY THEN Ypos = MaxY
SetCursor
Level = 0
'CUF-cursor forward
CASE 67 'C
GOSUB MakeParameter
Xpos = Xpos + a
IF Xpos > MaxX THEN Xpos = MaxX
SetCursor
Level = 0
'CUB-cursor backward
CASE 68 'D
GOSUB MakeParameter
Xpos = Xpos - a
IF Xpos < MinX THEN Xpos = MinX
SetCursor
Level = 0
'SCR-save cursor position
CASE 115 's
SaveX = Xpos: SaveY = Ypos
Level = 0
'RCP-restore cursor position
CASE 117 'u
Xpos = SaveX: Ypos = SaveY
Level = 0
SetCursor
'ED-erase display(ESC[2J and ESC[J work
'both work)
CASE 74 'J
ClearScreen
Level = 0
'EL-erase in line
CASE 75 'K
a = CursorAddress
FOR x = Xpos TO MaxX
POKE a, 32: POKE a + 1, Attribute: a = a + 2
NEXT
Level = 0
'SGR-sets new color
CASE 109 'm
GOSUB MakeParameter
'if no color codes then stuff 0 into the table
IF NumParameters = 0 THEN Parameters(0) = 0: NumParameters = 1
FOR a = 0 TO NumParameters - 1
P = Parameters(a)
SELECT CASE P
CASE IS <= 8
SELECT CASE P
'all attributes off
CASE 0
Attribute = 7
'high-intensity
CASE 1
Attribute = Attribute OR 8
'blinking
CASE 5
Attribute = Attribute OR 128
'inverse
CASE 7
Attribute = (Attribute AND 136) OR (Attribute AND 7) * 16 OR (Attribute AND 112) \ 16
END SELECT
'set foreground
CASE 30 TO 37
IF NOT Monochrome THEN
Attribute = (Attribute AND 248) OR Colors(P - 30)
END IF
'set background
CASE 40 TO 47
IF NOT Monochrome THEN
Attribute = (Attribute AND 143)
Attribute = Attribute OR Colors(P - 40) * 16
END IF
END SELECT
NEXT
Level = 0
'DSR-outputs a CPR sequence
'This function outputs the string "ESC[#;#R" where
'#;# is the current Y and current X coordinate
'to the receiver.
'Calls SendStatus to do its dirty work...
CASE 110
SendStatus Xpos, Ypos
Level = 0
'any other code is assumed to be invalid;it's just sent to the
'screen
CASE ELSE
Level = 0
GOSUB ProcessChar
END SELECT
END IF
RETURN
'stores a numeric parameter into the parameter table
MakeParameter:
'check to see if a least one digit has been received
'for this parameter and there's room left in the table
IF ValidParameter AND NumParameters < 10 THEN
'add parameter to table
Parameters(NumParameters) = CurrentParameter
NumParameters = NumParameters + 1
CurrentParameter = 0
ValidParameter = False
END IF
'Set A equal to the first parameter and make it 1 if it's 0
a = Parameters(0)
IF a = 0 THEN a = 1
RETURN
END SUB
'Prints a string to the display.
SUB PrintString (b$)
a& = SADD(b$)
IF a& < 0 THEN a& = a& + 65536
' You must change the next line if you're using QB4.5!
'It is currently coded for PDS.
'Segment = VARSEG(B$) + A& \ 16
Segment = VARSEG(b$) + a& \ 16 'change to VARSEG(B$) for QB4.5 & QBASIC
Address = a& MOD 16
FOR b = Address TO Address + LEN(b$) - 1
DEF SEG = Segment
A1 = PEEK(b)
DEF SEG = VideoSegment
PrintAnsi A1
NEXT
END SUB
SUB Recurse (Buffer$)
'This huge bloated confusing piece of code is what makes the ^V^Y repeat
'code go. It checks for embedded ^V^Y codes, and if they're in there, it
'attempts to expand them. It does still however have the dreaded avatar
'bug where if they send "^V^Y^KHello!!!^V^Y^Z^Z" or something similar,
'it'll lock up. Just go through that string ^^ and you'll figure out where
'the bug is.
y = ASC(AvtBuf$)
FOR a = 1 TO y
FOR b = 1 TO LEN(Buffer$)
c = ASC(MID$(Buffer$, b, 1))
IF c = 22 THEN
IF ASC(MID$(Buffer$, b + 1, 1)) = 25 THEN
'Its a ^V^Y code, so we gotta expand it
c = ASC(MID$(Buffer$, b + 2, 1))
r$ = MID$(Buffer$, b + 3, c)
s$ = ""
FOR z = 1 TO ASC(MID$(Buffer$, b + 3 + c, 1))
s$ = s$ + r$
NEXT z
Buffer$ = LEFT$(Buffer$, b - 1) + s$ + MID$(Buffer$, b + 4 + c)
c = -1
END IF
IF c > -1 THEN PrintAnsi c
ELSE
PrintAnsi c
END IF
NEXT b
NEXT a
END SUB
SUB Scroll (Direction%, Top%, Left%, Bottom%, Right%, Lines%, Attr%)
'CONST UP = &H700, DOWN = &H600
DIM reg AS RegType 'need $include qb.bi
Top% = Top% - 1
Left% = Left% - 1
Bottom% = Bottom% - 1
Right% = Right% - 1
IF Direction% = 1 THEN reg.ax = &H700 ELSE reg.ax = &H600
reg.ax = reg.ax + Lines% 'zero lines will clear viewport
reg.bx = Attr% * 256 'attribute for blank area
reg.cx = Top% * 256 + Left% 'Top Left Coords
reg.dx = Bottom% * 256 + Right% 'Bottom Right Coords
CALL INTERRUPT(&H10, reg, reg)
END SUB
SUB ScrollUpScreen
DIM Regs AS RegType
Regs.ax = &H601
a& = Attribute * 256&
IF a& > 32767 THEN a = a& - 65536 ELSE a = a&
Regs.bx = a
Regs.cx = (MinY * 256&) + MinX - 257
Regs.dx = (MaxY * 256&) + MaxX - 257
CALL INTERRUPT(&H10, Regs, Regs)
END SUB
'Sends the screen's status to the receiver. You must modify the
'"PRINT #1, A$;" command to print to your comm package.
'Sends "ESC[##;##R" where ##;## is Y;X.
SUB SendStatus (x, y)
a$ = CHR$(27) + "[" + RIGHT$("0" + MID$(STR$(y), 2), 2)
a$ = a$ + ";" + RIGHT$("0" + MID$(STR$(x), 2), 2) + "R"
'*****Change the next line to print this string out to your comm package!!****
PRINT #1, a$; 'DON'T insert a line feed!!
END SUB
'Sets the cursor- uses OUT's for speed
SUB SetCursor
'Must do this...
LOCATE , , 1, 12, 13
CursorAddress = (Xpos - 1) * 2 + (Ypos - 1) * BytesPerLine + VideoOffset
IF CursorOn THEN
Address = CursorAddress \ 2
OUT CRT, &HE
OUT CRT + 1, Address \ 256
OUT CRT, &HF
OUT CRT + 1, Address AND 255
END IF
END SUB
'Sets a new printing window.
SUB SetWindow (WorkPage, Lx, Ly, Hx, Hy)
DEF SEG = &H40
IF WorkPage = -1 THEN
VideoOffset = PEEK(&H4E) + PEEK(&H4F) * 256&
ELSE
VideoOffset = (PEEK(&H4C) + PEEK(&H4D) * 256&) * WorkPage
END IF
ScreenX = PEEK(&H4A)
ScreenY = PEEK(&H84) + 1
IF Lx = -1 THEN
MinX = 1: MinY = 1
MaxX = ScreenX: MaxY = ScreenY
BytesPerLine = MaxX * 2
ELSE
'change window size if coordinates are valid
IF Lx <= Hx AND Ly <= Hy AND Hx <= ScreenX AND Hy <= ScreenY THEN
MinX = Lx: MaxX = Hx: MinY = Ly: MaxY = Hy
END IF
END IF
DEF SEG = VideoSegment
Xpos = MinX: Ypos = MinY
SaveX = MinX: SaveY = MinY
SetCursor
END SUB