📄 window.asm
字号:
*
* Low level IBM/PC console keyboard/window interface routines
* for use with the DDS MICRO-C compiler.
*
* Copyright 1989-2000 Dave Dunfield
* All rights reserved.
*
* Permission granted for personal (non-commercial) use only.
*
?CBASE EQU $B800 ; Color video screen segment
?MBASE EQU $B000 ; Monochrome video screen segment
*
* Initialized variables & tables
*
W_BASE DW ?CBASE ; Mono=B000, Cga=B800
W_PAGE DB 0 ; Current video page
W_OPEN DW 0 ; Last opened window
* Special key table - General keys
?W_KEYS DW $4800 ; KUA (Up arrow)
DW $5000 ; KDA (Down arrow)
DW $4B00 ; KLA (Left arrow)
DW $4D00 ; KRA (Right arrow)
DW $4900 ; KPU (PgUp)
DW $5100 ; KPD (PgDn)
DW $4700 ; KHO (Home)
DW $4F00 ; KEN (End)
DW $4E2B ; KKP (Keypad '+')
DW $4A2D ; KKM (Keypad '-')
DW $5200 ; KIN (Ins)
DW $5300 ; KDL (Del)
DW $0E08 ; KBS (Backspace)
* Function keys
DW $3B00 ; K1 (F1)
DW $3C00 ; K2 (F2)
DW $3D00 ; K3 (F3)
DW $3E00 ; K4 (F4)
DW $3F00 ; K5 (F5)
DW $4000 ; K6 (F6)
DW $4100 ; K7 (F7)
DW $4200 ; K8 (F8)
DW $4300 ; K9 (F9)
DW $4400 ; K10 (F10)
* Special control keys
DW $8400 ; CPU (CTRL-PgUp)
DW $7600 ; CPD (CTRL-PgDn)
DW $7700 ; CHO (CTRL-Home)
DW $7500 ; CEN (CTRL-End)
DW 0
* BOX character table
?BOXTAB DB $C4,$B3,$DA,$BF,$C0,$D9
DB $CD,$BA,$C9,$BB,$C8,$BC
DB $CD,$B3,$D5,$B8,$D4,$BE
*
* Open a window: w_open(px, py, sx, sy, flags)
*
wopen PUSH BP ; Save callers stack frame
MOV BP,SP ; Address parameters
PUSH ES ; Save ES
* Set up video mode
MOV AH,#$0F ; Get video mode
INT $10 ; Call BIOS
MOV W_PAGE,BH ; Save video page
MOV BX,#?CBASE ; Assume COLOR address
CMP AL,#$07 ; Monochrome?
JNZ ?oinit1 ; No, assumption correct
MOV BX,#?MBASE ; Get MONOCHROME address
?oinit1 MOV W_BASE,BX ; Set video base address
MOV ES,BX ; Set up segment
* Allocate a window buffer
XOR AH,AH ; zero high
MOV AL,5[BP] ; Get video flags
AND AL,#$80 ; Do we save screen
JZ ?oinit2 ; No, do not
MOV AL,6[BP] ; Get 'Y' size
MOV BL,8[BP] ; Get 'X' size
MUL BL ; Calculate total size
SHL AX,1 ; X2 for attributes
?oinit2 ADD AX,#14 ; Include overhead
PUSH AX ; Pass as parameter
CALL malloc ; Allocate the buffer
MOV SI,AX ; Set up pointer
POP DX ; Clean up stack
AND SI,SI ; Did we get it?
JNZ ?oinit3 ; Yes, proceed
* Couldn't allocate, return with bad news
POP ES ; Restore extra set
POP BP ; Restore caller
RET
* Fill in window parameter block
?oinit3 MOV DL,12[BP] ; Get 'X' position
MOV DH,10[BP] ; Get 'Y' position
MOV 2[SI],DX ; Save it
MOV DL,8[BP] ; Get 'X' size
MOV DH,6[BP] ; Get 'Y' size
MOV 4[SI],DX ; Save size
MOV BX,4[BP] ; Get window flags
MOV [SI],BX ; Save attributes & flags
MOV DX,W_OPEN ; Get last opened window
MOV 8[SI],DX ; Save in buffer
XOR DX,DX ; Reset cursor position
MOV 6[SI],DX ; Save initial cursor position
* Save window contents if required
TEST BH,#$80 ; Do we save it?
JZ ?oinit5 ; No we don't
* ... Set up pointers to screen & save area
CALL ?xyaddr ; Get base address
MOV DX,4[SI] ; Get 'X' and 'Y' sizes
LEA DI,14[SI] ; Offset to data area
PUSH SI ; Save SI
MOV SI,BX ; Get base window address
* ... Save one line at a time
PUSH ES ; Stack ES
PUSH DS ; And DS
POP ES ; For swap
POP DS ; ES <> DS
?oinit4 PUSH SI ; Save source
MOV CL,DL ; Get 'X' size
XOR CH,CH ; Zero high size
REP
MOVSW ; Move one line
POP SI ; Restore it
ADD SI,#160 ; Offset to next line
DEC DH ; Reduce count
JNZ ?oinit4 ; And proceed
* ... Restore registers and continue
PUSH ES ; Stack ES
PUSH DS ; And DS
POP ES ; For swap
POP DS ; ES <> DS
POP SI ; Restore SI
XOR DX,DX ; Reset cursor position
MOV BH,5[BP] ; Get flags back
* Draw box if required
?oinit5 MOV BP,#?BOXTAB ; Point to BOX table
MOV CX,4[SI] ; Get size of box
SUB CH,#2 ; Adjust for bar
DEC CL ; Adjust for bar
AND BH,#$60 ; Draw BOX?
JZ ?oinit8 ; No we don't
* ... Select box type
CMP BH,#$40 ; Box1?
JZ ?oinit6 ; Use this one
ADD BP,#6 ; Offset to next
CMP BH,#$20 ; Box2?
JZ ?oinit6 ; Use this one
ADD BP,#6 ; Offset to next
?oinit6 PUSH CX ; Save size
CALL ?xyaddr ; Get address
* ... Draw the top (With corners)
MOV AH,[SI] ; Get attribute
MOV AL,2[BP] ; Top left corner
MOV ES:[BX],AX ; Write top corner
LEA DI,2[BX] ; Get value
XOR CH,CH ; Zero high
DEC CL ; Adjust for bar
MOV AL,0[BP] ; Horizontal line
REP
STOSW ; Draw the line
MOV AL,3[BP] ; Top right hand corner
MOV ES:[DI],AX ; Write it
POP CX ; Restore position
* ... Draw the box sides
?oinit7 INC DH ; Advance
MOV AL,1[BP] ; Box side
CALL ?xyaddr ; Get position
MOV ES:[BX],AX ; Write it
ADD DL,CL ; Offset
CALL ?xyaddr ; Get position
MOV ES:[BX],AX ; Write it
SUB DL,CL ; Backup
DEC CH ; Reduce count
JNZ ?oinit7 ; Do them all
* ... Draw the bottom (With corners)
INC DH ; Advance to bottom
CALL ?xyaddr ; get address
MOV AL,4[BP] ; Lower left corner
MOV ES:[BX],AX ; Write it
LEA DI,2[BX] ; Position to line
DEC CL ; Adjust for bar
MOV AL,0[BP] ; Horizontal line
REP
STOSW ; Write it out
MOV AL,5[BP] ; Lower right corner
MOV ES:[DI],AX ; Write it out
* ... Reduce size of active region
MOV AX,2[SI] ; Get position
INC AL ; Advance 'X'
INC AH ; Advance 'Y'
MOV 2[SI],AX ; Resave
MOV AX,4[SI] ; Get size
SUB AH,#2 ; Chop out bars
SUB AL,#2 ; Chop out bars
MOV 4[SI],AX ; And resave
XOR DX,DX ; Reset cursor position
* Clear screen if required
?oinit8 MOV BH,1[SI] ; Get flags back
TEST BH,#$10 ; Clear screen?
JZ ?oinit9 ; No, its ok
CALL ?cleos ; Clear one line
* Save cursor information
?oinit9 MOV BH,W_PAGE ; Get video page
MOV AH,#$03 ; Get cursor info
INT $10 ; Get cursor
MOV 10[SI],CX ; Save shape
MOV 12[SI],DX ; Save position
MOV AX,SI ; Get buffer address
MOV W_OPEN,AX ; Save this window pointer
POP ES ; Restore ES
POP BP ; Restore callers stack frame
RET
*
* Close current window: wclose()
*
wclose CALL ?xsetup ; Get last window
JMP <?wclos0 ; And proceed
*
* Close a window: w_close(window)
*
w_close CALL ?wsetup ; Get parameters
?wclos0 XOR DX,DX ; Zero position
MOV BH,1[SI] ; Get open flags
* If window was BOXed, adjust sizes first
TEST BH,#$60 ; Was it BOXed
JZ ?wclos1 ; No, don't adjust
MOV AX,2[SI] ; Get position
DEC AL ; Expand 'X'
DEC AH ; Expand 'Y'
MOV 2[SI],AX ; Resave
MOV AX,4[SI] ; Get size
ADD AH,#2 ; Adjust for bars
ADD AL,#2 ; Adjust for bars
MOV 4[SI],AX ; Resave
* Clear window if requested
?wclos1 TEST BH,#$08 ; Clear window?
JZ ?wclos2 ; No, try next
CALL ?cleos ; Clear the window
MOV BH,1[SI] ; Get flags back
* Restore previous contents if saved
?wclos2 TEST BH,#$80 ; Do we restore it
JZ ?wclos4 ; No, just clear
* ... Set up pointers to screen & save area
CALL ?xyaddr ; Calculate base address
MOV DX,4[SI] ; Get 'X' and 'Y' sizes
PUSH SI ; Save SI
LEA SI,14[SI] ; Offset to data area
MOV DI,BX ; Get base window address
* ... Restore one line at a time
?wclos3 PUSH DI ; Save source
MOV CL,DL ; Get 'X' size
XOR CH,CH ; Zero high size
REP
MOVSW ; Move one line
POP DI ; Restore it
ADD DI,#160 ; Offset to next line
DEC DH ; Reduce count
JNZ ?wclos3 ; And proceed
POP SI ; Restore SI
MOV BH,1[SI] ; Get flags back
* Restore the cursor
?wclos4 MOV CX,10[SI] ; Get cursor shape
MOV AH,#$01 ; Set shape
INT $10 ; Call BIOS
MOV DX,12[SI] ; Get position
MOV BH,W_PAGE ; Get display page
MOV AH,#$02 ; Set position
INT $10 ; Call BIOS
* If this is the active window, switch to previously open
CMP SI,W_OPEN ; Is this it?
JNZ ?wclos5 ; No, don't reset
MOV AX,8[SI] ; Get last free
MOV W_OPEN,AX ; Save it
* Release the buffer contents
?wclos5 PUSH SI ; Save address of buffer
CALL free ; Release it
POP SI ; Fixup stack
POP ES ; Restore ES
POP BP ; Restore BP
RET
*
* Write character into current window: wputc(int c)
*
wputc CALL ?xsetup ; Get last open window
MOV AX,4[BP] ; Get character
JMP <?tstbel ; And proceed
*
* Write a character to the video display: w_putc(int c, window)
*
w_putc CALL ?wsetup ; Set up video addresses
MOV AX,6[BP] ; Get character to display
* Handle BELL
?tstbel CMP AX,#'G'-$40 ; BELL code?
JNZ ?tstcr ; No, try next
MOV AX,#$0E07 ; Write BELL code
XOR BX,BX ; Write to page 0
INT $10 ; Call BIOS
JMP <?vedit ; and exit
* Handle CARRIAGE RETURN
?tstcr CMP AX,#'M'-$40 ; Is it carriage return
JNZ ?tstbs ; No, try next
XOR DL,DL ; Reset 'X' position
JMP <?vedit ; and proceed
* Handle BACKSPACE
?tstbs CMP AX,#'H'-$40 ; Is it backspace
JNZ ?tstnl ; No, try line-feed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -