home *** CD-ROM | disk | FTP | other *** search
- comment|
- This source code is for QB NEAR STRINGS only. MASM 5.1 compatible.
- Written by Brian McLaughlin. Released into the public domain 3/5/93.
-
- WARNING: Before *ANY* of the working routines in this group can be called
- safely from your program, the routine XInit must be called once. (No
- further calls to XInit are needed.)
-
- XInit sets several internal variables and default behaviors. It sets the
- active display page and visible display page to zero. It also detects if a
- CGA monitor is in use and sets a flag to suppress snow. This behavior can
- be overridden by setting the IgnoreSnow% variable to a non-zero value. In
- that case the presence of a CGA is ignored and fast printing is used.
- XInit also sets the initial viewport to cover the entire screen (25x80),
- and sets the default colors to white on black. It puts the cursor in the
- first column of the row where it finds the cursor. The only display size
- supported by these routines is 25x80. (The 43/50 line options are not
- supported.)
-
- XPrint prints only strings. Numbers MUST be converted to strings before
- printing them (by using STR$ or a similar routine). XPrint uses the current
- colors defined by XColor. It prints at the current cursor position. When
- the variable NumScrolls% is set to 0, XPrint will behave like PRINT with a
- trailing semicolon, and the cursor will not be advanced beyond the space
- following the end of the printed string. When NumScrolls% is set to 1,
- Xprint will behave like PRINT with no semicolon, and the cursor will be
- advanced to the beginning of the next line. If NumScrolls% is greater than
- 1, the cursor will be advanced until that number of carriage returns and
- line feeds are performed, much like PRINT: PRINT: PRINT. Scrolling is
- automatic when printing on the last line of the viewport.
-
- XViewPort is similar to VIEW PRINT, except it allows column as well as row
- arguments. Screen coordinates follow BASIC convention, so that the upper
- left corner is 1,1 and the lower right is 25,80. If it is passed an illegal
- argument (for example a column or row less than 1 or a top row beneath the
- bottom row) then it defaults to a viewport consisting of the entire screen
- (25x80). When XViewPort is called and the cursor is detected outside the
- viewport's boundaries then the cursor will be brought into the viewport and
- placed at the top left corner, no matter where it was before.
-
- XLocate works a lot like LOCATE X%,Y%. You must always pass both the row
- and column arguments. When passed an illegal coordinate (outside the
- current viewport) XLocate will place the cursor as near to the requested
- position as it can, while keeping it within the viewport. IMPORTANT: Row
- and column arguments are numbered relative to the whole screen, so that the
- position 1,1 is ALWAYS the top left corner of the screen, which is NOT
- necessarily the top left corner of the current viewport. If the defined
- viewport does not include screen position 1,1 then those coordinates are
- illegal.
-
- XCursorOn turns the cursor on (when it is off) and controls its shape. It
- accepts one argument, telling it whether the cursor should appear as a
- block (non-zero value) or an underline (zero value). XCursorOff makes the
- cursor invisible, if it is visible.
-
- XColor sets the current foreground and background colors. It follows the
- QuickBASIC conventions: allowable background colors are 0-7. Foreground
- colors of 0-7 are normal, 8-15 are high intensity, and blinking is
- obtained by adding 16 to the desired foreground color (16-31).
-
- XCls clears the currently defined viewport to the current colors and puts
- the cursor in the top left corner.
-
- XCsrLin% returns the current cursor row, like CSRLIN. XPos% returns the
- current cursor column, like POS(0).
-
- end comment|
-
- .MODEL MEDIUM, BASIC
- .DATA
- ViewportTopRow DB 0 ; initial viewport is whole screen
- ViewportTopCol DB 0
- ViewportBotRow DB 24 ; 0-24 = 25 rows total
- ViewportBotCol DB 79 ; 0-79 = 80 columns total
- ColorAttr DB 7 ; default to white on black
- CursorRow DB 0 ; zero-based coordinate
- CursorCol DB 0 ; zero-based coordinate
- SnowFlag DB 0 ; default = no snow suppression
- VidPort DW 03BAh ; monochrome port default
- VidSeg DW 0B000h ; monochrome segment default
- VidOffset DW 0
- .CODE
- ; these variables are stored in code segment, rather than DGROUP
- CursorTopLine DB 0Bh ; monochrome default cursor
- CursorEndLine DB 0Ch ; monochrome default cursor
-
- XInit PROC FAR, IgnoreSnow:WORD
- Mov AX, 0500h ; set display page to 0
- Int 10h ; using the BIOS
- Xor BH, BH
- Mov AH, 03h ; discover current cursor row
- Int 10h ; using the BIOS
- Mov CursorRow, DH ; and save that row
- Call $SetVideoOffset ; and calculate new offset
- Xor AX, AX
- Mov ES, AX
- Mov AX, ES:[0463h] ; get the CRT port address
- Cmp AL, 0B4h ; and look at it
- Je GotMon ; it's mono, the default
- Mov VidSeg, 0B800h ; otherwise, set up for color monitor
- Mov VidPort, 03DAh ;
- Mov CS:CursorTopLine, 06h
- Mov CS:CursorEndLine, 07h
- Mov BL, 10h ; now let's look for EGA/VGA installed
- Mov AH, 12h ; using BIOS service 12
- Int 10h ; call BIOS
- Cmp BL, 10h ; if BL changes there's an EGA/VGA
- Jne GotMon ; and we assume EGA/VGA
- Mov BX, IgnoreSnow ; so, did the user abort snow suppresion?
- Mov AX, [BX] ; let's see!
- Or AX, AX ; were we passed a zero?
- Jz GotMon ; a non-zero means *don't* suppress snow
- Mov SnowFlag, 1 ; otherwise, assume snow problems
- GotMon:
- Ret
- XInit ENDP
-
- XPrint PROC FAR USES ES DI SI, String:WORD, NumScrolls:WORD
- Mov DI, String ; get address of descriptor
- Mov CX, [DI] ; get string's length in bytes
- Jcxz NullString ; String was null
- Mov SI, [DI+2] ;DS:SI points to String in memory
- Mov AX, VidSeg ; can't put VidSeg into ES directly
- Mov ES, AX ;ES = video segment
- Mov DI, VidOffset ;ES:DI points to current cursor position
- Mov AH, ColorAttr ; AL holds the character, AH the attribute
- Mov DX, VidPort ; We'll need this for snow suppression
- Mov BH, SnowFlag ; get snow flag
- Mov BL, CursorCol
- Cld ; clear direction flag for forward write
- WriteCharLoop:
- Or BH, BH ; check for snow flag
- Jz FastWrite
- WaitHere:
- In AL, DX ; get video status byte into AL
- Test AL, 1 ; test the retrace bit
- Jnz WaitHere ; wait until it zeros
- Cli ; disable interrupts
- WaitAgain:
- In AL, DX ; test again
- Test AL, 1
- Jz WaitAgain
- FastWrite:
- Lodsb ; loads char into AL
- Stosw ; put char+attribute into video buffer
- Sti ; enable interrupts again
- Inc BL ; keep track of cursor position
- Mov AL, ViewportBotCol ; AL is only temporarily available
- Cmp AL, BL ; is cursor inside viewport boundary
- Jae InBounds
- Call $ResetCursor ; reset cursor to first col, scroll if need be
- Mov DI, VidOffset ; reset DI to correct offset
- Mov BL, CursorCol ; reset BL to new CursorCol
- InBounds:
- Loop WriteCharLoop
- Mov CursorCol, BL ; save final cursor column
- NullString:
- Mov SI, NumScrolls ; take care of NumScrolls scrolling now
- Mov CX, [SI] ; get the value into CX
- Jcxz NoCRLF
- CRLoop:
- Call $ResetCursor ; let this PROC do the work
- Loop CRLoop ; however many times its needed
- NoCRLF:
- Call $SetCursorPosition ; set the cursor where desired
- Call $SetVideoOffset ; calculate offset where cursor ended up
- Ret
- XPrint ENDP
-
-
- XCsrLin PROC FAR
- Mov AL, CursorRow ; put the value in AL
- Inc AL ; revert to 1-based coordinates
- Cbw
- Ret
- XCsrLin ENDP
-
-
- Xpos PROC FAR
- Mov AL, CursorCol ; put the value in AL
- Inc AL ; return a 1-based coordinate
- Cbw
- Ret
- XPos ENDP
-
-
- XCls PROC FAR
- Xor AL, AL
- Call $ScrollWin ; sending zero in AL clears the screen
- Mov AL, ViewportTopRow
- Mov CursorRow, AL
- Mov AL, ViewportTopCol
- Mov CursorCol, AL
- Call $SetCursorPosition ; move cursor to top corner
- Call $SetVideoOffset ; recalculate video offset
- Ret
- XCls ENDP
-
-
- XLocate PROC, Row:WORD, Col:WORD
- Mov BX, Row
- Mov AL, Byte Ptr [BX]
- Dec AL ; convert to zero-based coordinates
- Cmp AL, ViewportTopRow
- Jl RowTooLow
- Cmp AL, ViewPortBotRow
- Jg RowTooHigh
- RowRight:
- Mov CursorRow, AL ; save row coordinate
- Mov BX, Col
- Mov AL, Byte Ptr [BX]
- Dec AL ; convert to zero-based coordinates
- Cmp AL, ViewportTopCol
- Jl ColTooLow
- Cmp AL, ViewportBotCol
- Jg ColTooHigh
- ColRight:
- Mov CursorCol, AL ; save column coordinate
- Call $SetCursorPosition ; move cursor into place
- Call $SetVideoOffset ; recalculate current offset
- Ret
- RowTooLow:
- Mov AL, ViewportTopRow ; keep row in viewport boundary
- Jmp SHORT RowRight
- RowTooHigh:
- Mov AL, ViewportBotRow ; keep row in viewport boundary
- Jmp SHORT RowRight
- ColTooLow:
- Mov AL, ViewportTopCol ; keep column in viewport boundary
- Jmp SHORT ColRight
- ColTooHigh:
- Mov AL, ViewportBotCol ; keep column in viewport boundary
- Jmp SHORT ColRight
- XLocate ENDP
-
-
- XColor PROC FAR, Fore:WORD, Back:WORD
- Xor DL, DL ; put a zero into DL
- Mov BX, Fore ; get address of Fore
- Mov AX, [BX] ; put FG color into bits 0-4 of AX
- Test AX, 10h ; is bit 4 set? (blinking requested?)
- Jnz SetBlink ; if it is, then go arrange for blink
- SetColor:
- Mov BX, Back
- Mov AH, Byte Ptr [BX] ; put BG color into AH
- And AH, 7 ; only keep bits 0-2
- Mov CL, 4
- Shl AH, CL ; shift bits 0-2 into bits 4-6
- Or AL, AH ; introduce BG value into bits 4-6 of AL
- Or AL, DL ; sets bit 7 of AL, if blinking requested
- Mov ColorAttr, AL ; save the result internally
- Ret
- SetBlink:
- And AL, 0Fh ; keep bits 0-3 of AL, discard 4-7
- Mov DL, 0F0h ; set bit 7 in DL
- Jmp SHORT SetColor
- XColor ENDP
-
-
- XViewPort PROC FAR, TopRow:WORD, TopCol:WORD, BotRow:WORD, BotCol:WORD
- Mov BX, TopRow ; get address
- Mov AL, Byte Ptr [BX] ; get value
- Dec AL ; convert to zero-based coordinates
- Cmp AL, 0
- Jl Abort ; signed comparisons throughout
- Cmp AL, 24
- Jg Abort
- Mov DL, AL ; DL = TopRow
- Mov BX, TopCol ; get address
- Mov AL, Byte Ptr [BX] ; get value
- Dec AL ; convert to zero-based coordinates
- Cmp AL, 0
- Jl Abort ; trap an illegal value
- Cmp AL, 79
- Jg Abort ; trap an illegal value
- Mov DH, AL ; DH = TopCol
- Mov BX, BotRow ; get address
- Mov AL, Byte Ptr [BX] ; get value
- Dec AL ; convert to zero-based coordinates
- Cmp AL, DL ; compare to TopRow
- Jl Abort ; trap an illegal value
- Cmp AL, 24
- Jg Abort ; trap an illegal value
- Mov CL, AL ; CL = BotRow
- Mov BX, BotCol ; get address
- Mov AL, Byte Ptr [BX] ; get value
- Dec AL ; convert to zero-based coordinates
- Cmp AL, DH ; compare to TopCol
- Jl Abort ; trap an illegal value
- Cmp AL, 79
- Jg Abort ; trap an illegal value
- Cmp CursorRow, DL ; is the cursor inside the viewport?
- Jb PutCursInside ; if not, move it in
- Cmp CursorRow, CL
- Ja PutCursInside ; if not, move it in
- Cmp CursorCol, DH
- Jb PutCursInside ; if not, move it in
- Cmp CursorCol, AL
- Ja PutCursInside ; if not, move it in
- SaveVars:
- Mov ViewportTopRow, DL
- Mov ViewportTopCol, DH
- Mov ViewportBotRow, CL
- Mov ViewportBotCol, AL
- Ret
- Abort:
- Xor DX, DX ; set top corner to 0, 0
- Mov CL, 24 ; set bottom corner to 24, 79
- Mov AL, 79
- Jmp SHORT SaveVars
- PutCursInside:
- Mov CursorRow, DL ; move the cursor to top left
- Mov CursorCol, DH
- Call $SetCursorPosition ; make it all official
- Call $SetVideoOffset
- Jmp SHORT SaveVars
- XViewPort ENDP
-
-
- XCursorOn PROC FAR, BigFlag:WORD
- Mov CL, CS:CursorEndLine
- Mov BX, BigFlag
- Mov AX, [BX]
- Or AX, AX
- Jnz Big
- Mov CH, CS:CursorTopLine ;makes an underline cursor
- Ready:
- Mov AH, 01h
- Int 10h
- Ret
- Big:
- Xor CH, CH ; change top line to zero
- Jmp SHORT Ready ; for a big cursor
- XCursorOn ENDP
-
-
- XCursorOff PROC FAR
- Mov CX, 2000h ; should force invisible cursor
- Mov AH, 01h
- Int 10h
- Ret
- XCursorOff ENDP
-
-
- $ResetCursor PROC NEAR
- Push AX ; preserve AX to free a working register
- Mov AL, CursorRow ; get what row we're in
- Mov AH, ViewportBotRow ; get the bottom row of text window
- Cmp AL, AH ; see if they match
- Je InBotRow ; if they do, we need to scroll a line
- Inc CursorRow ; if not, show we moved a row down
- ResumeReset:
- Mov AL, ViewportTopCol ; and adjust column to leftmost one
- Mov CursorCol, AL
- Call $SetVideoOffset ; recalculate VidOffset
- Pop AX ; restore AX to previous value
- Ret
- InBotRow:
- Mov AL, 1 ; ask for a one-line scroll
- Call $ScrollWin ; do it
- Jmp SHORT ResumeReset ; go back to do the rest
- $ResetCursor ENDP
-
-
- $ScrollWin PROC NEAR ;call with AL = lines to scroll (0 means clear it)
- Push AX
- Push BX
- Push CX
- Push DX
- Mov AH, 06h
- Mov BH, ColorAttr
- Mov CH, ViewPortTopRow
- Mov CL, ViewPortTopCol
- Mov DH, ViewPortBotRow
- Mov DL, ViewPortBotCol
- Int 10h
- Pop DX
- Pop CX
- Pop BX
- Pop AX
- Ret
- $ScrollWin ENDP
-
-
- $SetCursorPosition PROC NEAR ;call this with CursorRow/CursorCol set properly
- Push DX
- Push AX
- Xor BH, BH ; display page zero
- Mov DH, CursorRow
- Mov DL, CursorCol
- Mov AH, 02h
- Int 10h
- Pop AX
- Pop DX
- Ret
- $SetCursorPosition ENDP
-
-
- $SetVideoOffset PROC NEAR ;call with CursorRow/CursorCol set properly
- Push AX
- Push BX
- Push CX
- Xor AH, AH
- Xor BH, BH
- Mov AL, CursorRow ; what row are we at?
- Mov BL, AL ; make a second copy
- Mov CL, 5
- Shl AX, CL ; multiply row * 32 into AX
- Mov CL, 7
- Shl BX, CL ; multiply row * 128 into BX
- Add BX, AX ; BX = row * 160 bytes (each char is 2)
- Xor AH, AH
- Mov AL, CursorCol
- Shl AX, 1 ; AX = col * 2
- Add AX, BX ; AX = correct offset in video memory
- Mov VidOffset, AX ; save it
- Pop CX
- Pop BX
- Pop AX
- Ret
- $SetVideoOffset ENDP
- END
-