📄 llcscn.asm
字号:
; modified by the LOCATE statement, is the one that is displayed
; for all but editing. When editing a line of input, either the
; Overwrite or Insert cursor will be used depending on whether
; we are overwriting or inserting characters. The Overwrite
; cursor is identical to the User Cursor, except that it can
; not be turned off with the LOCATE statement.
;
;
; Initially, the User Cursor and Overwrite cursors are a full
; block, and the insert cursor is a 1/2 block. Under DOS, the
; cursor has to be handled separately if we are in a graphics
; mode since the IBM BIOS does not support a cursor font in
; graphics mode. Note that none of this has anything to do with
; the graphics cursor, which is a one pixel location on the
; current graphics screen and is never displayed.
;
; NOTE: If you are supporting delayed screen initialization,
; B$SCNINIT has to be called before any changes are
; made.
;
;Algorithm:
;
; B$INSCSR - Turn insert cursor on and move to specified location
;
; B$OFFCSR - Turn cursor off and move invisible cursor to specified
; location
;
; B$USRCSR - Turn on user cursor if specified as being visible in
; the last call to B$CSRATR, otherwise do not display
; a cursor. Move (possibly invisible) cursor to specified
; location if the cursor is on. If the cursor is off,
; DO NOT move the cursor (for speed).
;
; B$OVWCSR - Turn overwrite cursor on and move to specified location.
; The overwrite cursor has the same specifications as the
; user cursor, but does not obey the visibility parameter
; specified in B$CSRATR.
;
;Entry:
; [DL] = new 1-relative line number
; [DH] = new 1-relative column number
; It is assumed that the values in DX are in range.
;
;Exit:
; None.
;
;Uses:
; Per Convention
;
;Preserves:
; BX,CX,DX
;
;Exceptions:
; None.
;****
;***
;B$CSRDSP - Change Cursor Type and Location
;
;Purpose:
; This routines display the specified cursor at a particular
; location as given by the input parameters. It may also
; request to not display a cursor. The text mode graphics cursor
; will be implemented as a full block for user cursor requests,
; and as a 1/2 block for insert modes. The graphics cursor will
; be handled separately (for DOS3) since the IBM BIOS does not
; support a cursor font in graphics mode.
;
; Entry points B$OFFCSR, B$OVWCSR, B$INSCSR, and B$USRCSR [16]
; exist to set AX to the appropriate value before falling through [16]
; into B$CSRDSP, in order to save code space. (Documented above)
;
;Algorithm:
;
; B$CSRDSP:
; if not OS/2
; if graphics request then
; if previous cursor valid
; if previous cursor is not an off cursor
; erase previous cursor using xor function on previous cursor
; and the screen.
;
; convert 1-relative row and col to 0-relative row and column
; swap row and col registers for bios call
; get active screen page number
; move cursor to desired location
; swap start and stop lines
; if text mode or OS/2
; if cursor type request != current cursor type
; change cursor to new type
; else (DOS3 graphics modes)
; if requested cursor is not for an off cursor
; display requested cursor using an xor function on requested cursor
; and the screen.
; store new cursor position and type
;
;Entry:
; b$CSRTYP = current cursor position
; [AX] = new cursor type
; [DL] = new 1-relative line number
; [DH] = new 1-relative column number
; It is assumed that the values in DX are in range.
;
;Exit:
; b$CSRTYP = current cursor type (start and stop lines)
;
;Modifies:
; None
;
;Preserves:
; BX,CX,DX
;
;Exceptions:
; None.
;****
CSRGRPH:
;here if screen mode graphics
PUSH AX ;save csr request for call
MOV AX,b$CSRTYP ; get previous cursor type
CMP AL,-1 ; unknown previous cursor type?
JZ NO_CURSOR ; brif so -- no cursor to erase
CALL GRPCSR ;erase previous cursor
NO_CURSOR:
POP AX ;restore csr request
JMP SHORT TXTCSR
labelNP <PUBLIC,B$SCNLOC> ; update cursor position variable
MOV b$CURSOR,DX ; and fall into SLOWUSRCSR.
labelNP <PUBLIC,B$SlowUsrCsr>
CMP [B$UsrCsrOn],0 ; should users cursor be displayed?
JZ B$OFFCSR ; brif not -- turn off cursor
USRCSR:
CMP b$ScreenMode,0 ; is screen mode graphics?
JNZ B$OFFCSR ; brif so -- use off cursor
labelNP <PUBLIC,B$OVWCSR> ; display overwrite cursor
MOV AX,b$UsrCsrTyp ; get user defined cursor
JMP SHORT B$CSRDSP ; and display it
labelNP <PUBLIC,B$INSCSR> ; display insert mode cursor
MOV AX,b$InsCsrTyp ; get insert mode cursor
JMP SHORT B$CSRDSP ; and display it
labelNP <PUBLIC,B$USRCSR> ; conditionally display user cursor
CMP [B$UsrCsrOn],0 ; should users cursor be displayed?
JNZ USRCSR ; brif so -- check for graphics mode
CMP b$CSRTYP,OffCsrTyp ; cursor already off?
JNE B$OFFCSR ; brif not -- turn it off now
RET ; otherwise, don't position or check type.
; check type.
; This REALLY speeds up print statements, but will usually NOT update the
; hardware cursor! To FORCE the cursor to get reset, invalidate the cursor
; type by moving -1 into b$CSRTYP.
labelNP <PUBLIC,B$OFFCSR> ; turn cursor off
MOV AX,OffCsrTyp ; get off cursor
cProc B$CSRDSP,<NEAR,PUBLIC>,<BX,CX>
cBegin
PUSH AX ; save registers
PUSH DX
CALL B$SCINIT ; make sure screen is initialized.
cmp b$ScreenMode,0 ;is screen mode graphics?
JNZ CSRGRPH ;br. if so
TXTCSR:
DEC DX ; DL = 0-relative row
XCHG DH,DL ;swap for BIOS call
DEC DX ; DL,DH = 0-relative column,row
MOV BH,b$ActPage ;get active page
PUSH AX ;save cursor type
SCNIOS vSetCursorPos ; issue BIOS call to move cursor
POP AX ;recover cursor type
cmp b$ScreenMode,0 ;Text mode ?
JNZ NOT_TEXT_MODE ; Brif not -- generate graphics cursor
CMP AX,b$CSRTYP ; (speed) need to change the cursor type?
JE DSPRET ; (speed) brif not -- just return
XCHG AX,CX ; CX = cursor type
; CH = start line, CL = stop line
SCNIOS vSetCursorType ; display requested cursor
; The bios does not set the cursor type right for IBM EGA cards
; when trying to get an underline cursor when not in 25-line mode. So
; we have to set it ourselves. We do the BIOS call beforehand to update
; the internal BIOS cursor type variable.
TEST CH,20H ; cursor off request?
JNZ NoChangeType ; brif so -- don't reset type
TEST b$Adapter,EGA ; EGA adapter?
JZ NoChangeType ; brif not -- don't reset type
CMP b$ScrHeight,25 ; 25-line mode?
JZ NoChangeType ; brif not -- don't reset type
MOV DX,03D4h ; EGA port
XCHG AX,CX ; AH = start line
MOV AL,0Ah ; select start line register
OutWord ; write correct value - macro for AT&T 6300
NoChangeType:
DSPRET:
POP DX ; restore new position and type
POP AX
MOV b$CSRTYP,AX ; store current cursor type
cEnd
NOT_TEXT_MODE:
CALL GRPCSR ; generate graphics cursor
JMP DSPRET ; exit
;***
; GRPCSR -- Toggle a generated graphics mode text cursor (DOS 3 only)
;
;Purpose:
;
;Entry:
; AX = cursor type
;
;Exit:
; None
;Uses:
; AX,BX,CX
;
;Preserves:
; DX
;
;Exceptions:
; None
;
;******************************************************************************
cProc GRPCSR,<NEAR>
cBegin
CMP AX,OffCsrTyp ; cursor off request?
JE GRPRET ; brif so -- return without doing anything
PUSH ES ; save ES
mov bl,[b$BiosMode] ; check BIOS mode
cmp bl,13h ; VGA mode 13h?
je Cursor13 ; go if so
XOR CX,CX ; CX = 0
MOV ES,CX ; ES = 0
CMP BL,40h ; Is it Olivetti 640x400 mode?
JNE NotCsr40h ; brif not
; The Olivetti VGA handles character fonts normally in mode 40h, but we
; special-case their CGA and EGA which use a MASTER TABLE POINTER at 40:84.
TEST [b$Adapter],CGA+EGA; Is it CGA or EGA Olivetti?
JZ NotCsr40h ; brif not (ie. Olivetti VGA)
;Note: B$OgaCsr requires ES = CX = 0 on entry
CALL [b$pOgaCsr] ; use Olivetti version of routine
JMP SHORT GrpRet2
NotCsr40h:
PUSH ES:CHREXT ;Save Old Char Extention Ptr
PUSH ES:CHREXT+2
MOV ES:WORD PTR CHREXT,OFFSET DGROUP:BLTLOT
MOV ES:CHREXT+2,DS ;Segment Addr of Box Char
CMP AX,b$InsCsrTyp ; is it an insert cursor?
PUSHF ; save check for insert mode
cmp b$BiosMode,8 ;Hercules graphics mode?
je UseEga ;use EGA code if so
CMP b$BiosMode,0Dh ;current screen mode EGA?
JB NotEga ;brif not Ega mode
UseEga:
MOV BL,b$ForeMapped ;use current color
OR BL,080H ;set XOR bit
MOV AL,0DCh ;half height block character for EGA
POPF ;insert mode?
JZ GRPCS2 ;brif insert cursor
DEC AL ;make overwrite cursor
JMP SHORT GRPCS2
NotEga:
POPF ;insert mode?
MOV AL,128 ;Char code for Box
JZ GRPCS1 ;brif it is insert cursor
INC AL ;Map to 128 or 129..
GRPCS1: ;Half Box (128) If INS_MODE
;Whole Box (129) for normal (NOT INS_MODE)
MOV BL,87H ;Select Invert (xor) Mode
;bit 7 of [BL] = 1 for XOR mode and
;low nibble =7, bcos we need low intensity white
GRPCS2:
MOV BH,b$ActPage ; Active Page
INC CX ; CX = 1 -- One Character
SCNIOS vWriteChar
POP ES:CHREXT+2
POP ES:CHREXT ;Restore Char Extention ptr
GrpRet2:
POP ES ;restore register
GRPRET:
cEnd
;
;BIOS mode 13H (SCREEN 13) does not perform XOR drawing of characters.
;We must therefore draw the cursor the hard way, XORing the 8x8 character
;cell with the desired cursor color.
;
Cursor13:
push dx ;preserve DX
push ax ;save cursor type
SCNIOS vReadCursorPos ;DH=cursor row, DL=column
xor ax,ax
xchg al,dh ;AX=row, DX=col
mov cl,3 ;*8
shl ax,cl ;AX=Y coordinate of character
shl dx,cl ;DX=X coordinate of character
mov cx,dx ;CX=X
mov dx,ax ;DX=Y
call [b$MapXYC] ;convert X,Y to buffer offset
mov al,b$ForeMapped ;get cursor color
mov ah,al ;replicate for 2 pixels
les bx,b$AddrC ;buffer address for character start
DbAssertRel ES,E,0A000H,RT_TEXT,<Buffer segment invalid in B$CSRDSP>
mov cx,8 ;8 raster lines down per character
pop dx ;restore cursor type
cmp dx,b$InsCsrTyp ;is it an insert cursor?
jne NextRaster ;go if not for full-block cursor
shr cx,1 ;half-block cursor
add bx,320*4 ;start 4 rasters down, do half as many
NextRaster:
push cx
mov cx,4 ;8 pixels (4 words) across per character
NextWord:
xor word ptr es:[bx],ax ;xor 2 pixels with color
inc bx ;to next word
inc bx
loop NextWord ;do all 8 pixels
pop cx
add bx,320-8 ;down to next raster and back to left
loop NextRaster
pop dx ;restore DX
jmp short GrpRet2
;***
;B$SCROLL - Scroll the screen by one line
;OEM-interface routine
;
;Purpose
; Scrolls up one line an area of the screen with a left,top corner of
; (1,b$WDOTOP), and a right,bottom corner of (b$CRTWIDTH,b$WDOBOT)
;
;Entry:
; b$WDOTOP, b$WDOBOT, b$CRTWIDTH set.
;
;Exit:
; None
;
;Uses:
; Per Convention
;
;Preserves:
; AX, BX, CX, DX
;
;Exceptions:
; None.
;****
cProc B$SCROLL,<PUBLIC,NEAR>,<AX,BX,CX,DX>
cBegin
XOR CX,CX ; CL = left column (0-relative)
MOV CH,b$WDOTOP ; CH = top row
DEC CH ; make it 0-relative
MOV BL,b$CRTWIDTH ; BL = right column
MOV BH,b$WDOBOT ; BH = bottom row
DEC BX ; make column 0-relative
DEC BH ; make row 0-relative
OLD_SCROLL: ; former entry point
; [BH] = Window bottom row (0-relative)
; [BL] = Right column of scroll window (0-relative)
; [CH] = Window top row (0-relative)
; [CL] = Left column of scroll window (0-relative)
cCALL B$SELAPG ; Active Visual Page
; Determine if scrolling is Horizontal or Vertical by comparing
; source line and destination line
; Source line will can be equal to destination line if VIEW PRINT n TO n
; is used.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -