; ; 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