home *** CD-ROM | disk | FTP | other *** search
- ;------ zavt_k.asm ----------------------------------------------
- ; Zephyr Avatar terminal driver.
- ; Copyright (C) 1989-1990, Luns Tee, Toronto ON.
- ; Based on original code by Charles Petzold
- ;
- ; Revision History:
- ;------------------------------------------------------------------------
- ; Luns Tee, Toronto, Ontario
- ; 28 Feb 1990; Personal hack of DOS-EDIT taken and modified for use
- ; in ZAVT.
- ;
- ; 12 May 1990; Pseudocursor support extended here
- ;------------------------------------------------------------------------
-
- include zavt_d.asm ; get equates
-
-
- ; to zavt.asm
- public getchar, peekchar
-
- ; from zavt.asm
-
- if fullscreen ; nothing needed if no full-screen ed.
- extrn scrnbuf:keybuf, linebufend:abs, linebuf:abs
- extrn max_x:byte, cur_coords:word
- extrn cur_x:byte, cur_y:byte
- extrn gmode_flag:byte
- extrn cur_attrib:byte
- extrn pseudo_flag:byte
- endif
- extrn fnkey:keybuf, fnkeybuf:byte
- if xlate
- extrn xlatseq:keybuf
- extrn redef_end:abs, param_end:word
- endif
-
- code segment byte public 'CODE'
- assume cs:code, ds:code, es:code
-
-
- if fullscreen ; nothing needed if no full-screen ed.
-
- ; All Data
- ; --------
-
- InsertOn db 0 ; Insert mode flag
- KeyRoutine dw Home,Up,PgUp,Dummy,Left,Dummy,Right
- dw Dummy,End,Down,PgDn,Insert,Delete
- endif
-
- ;---- lookup -----------------------------------------------
- ; Called by getchar, peekchar, and key to see if a given key has
- ; been redefined.
- ; Sets AH to zero if AL is not zero (i.e. if AX is not a function key).
- ; Returns with Z cleared if no redefinition; otherwise,
- ; Z is set, SI points to redefinition string, CX is its length.
- ; Preseves AL, all but CX and SI.
- ; Redefinition table organization:
- ; redef_end points to the last word used by the redef table.
- ; the highest word is the length of the string sans header;
- ; the word following is the character to be replaced;
- ; the string follows with the last character highest;
- ; param_end points to the last byte used by the parameter buffer.
-
- if xlate
- public lookup
-
- lookup proc near
- mov si, redef_end ; Start at end of table, move down.
- or al, al
- jz lu_lp
- xor ah, ah ; clear extraneous scan code
- lu_lp: cmp si, param_end
- jbe lu_notfound ; If below redef table, exit.
- mov cx, [si]
- cmp ax, [si-2] ; are you my mommy?
- jz lu_gotit
- sub si, 4
- sub si, cx ; point to next header
- jmp lu_lp
- lu_notfound:
- or si, si ; clear Z
- ret
-
- lu_gotit:
- sub si, 3 ; point to last char of string
- cmp al, al ; set Z
- ret
- lookup endp
-
- endif
-
- ;---- searchbuf --------------------------------------------
- ; Called by getchar and peekchar to see if any characters are
- ; waiting to be gotten from sources other than BIOS.
- ; Returns with Z set if no chars found, BX=keybuf & SI=keybuf.len otherwise.
- assume ds:code
- searchbuf proc near
- ; Search the stuffahead buffers.
- mov cx,3 - fullscreen - xlate ; number of buffers to check for chars
- mov bx,offset fnkey - 4
- sbloop: add bx,4 ; point to next buffer record
- mov si,[bx].len
- or si,si ; empty?
- loopz sbloop ; if so, loop.
- ret
- searchbuf endp
-
-
- ;---- peekchar -----------------------------------------------
- ; Returns Z if no character ready, AL=char otherwise.
- ; Trashes AX, BX, CX, SI.
- peekchar proc near
- call searchbuf
- jz pc_trykbd ; No chars? Try the keyboard.
- ; A nonempty buffer was found.
- dec si
- pcdone: neg si
- add si, [bx].adr ; get pointer to string
- lodsb ; get the char
- ret
-
- pc_brk: int 16h ; get rid of control-break in buffer
-
- pc_trykbd:
- mov ah,1
- int 16h ; BIOS returns with char in AX
- jz pcexit
- or ax,ax
- jz pc_brk ; If ctl-brk, it's already been taken care of- kill it.
-
- if xlate
- ; Look in the reassignment table to see if it needs translation.
- call lookup ; Z=found; CX=length; SI=ptr
- jnz pcexit ; Nope; just return the char.
- ; Okay; get the first code to be returned.
- sub si,cx
- inc si
- lodsb
- endif
-
- pcexit: ret ; with character in AL, Z true if no char waiting.
- peekchar endp
-
- ;---- getchar -----------------------------------------------
- ; Returns AL = next char.
- ; Trashes AX, BX, CX, SI.
-
- getchar proc near
- ; See if any chars are waiting in stuffahead buffers.
- call searchbuf
- jz gc_trykbd ; No chars? Try the keyboard.
- ; A nonempty buffer was found.
- dec si
- mov [bx].len,si
-
- if xlate
- neg si
- mov bp, [bx].adr ; get pointer to string
- mov ax, ds:[bp][si] ; get the char
- ; Recognize function key sequences, move them to highest priority
- ; queue.
- or al, al
- jnz gcdone ; nonzero first byte -> not fnkey.
- or si,si ; set Z if si=0
- jz gcdone ; no chars left -> nothing to protect.
- dec [bx].len
-
- if fullscreen
- or ax,ax ; full-screen routine wanted?
- jz screenedit ; yes? no?
- endif
-
- ; Valid char from buffer in AL. Return with it through
- ; code shared with peekchar
- else
- jmp short pcdone
- endif
-
- gc_fnkey: ; yep, special treatment
- mov fnkey.len, 1
- mov fnkeybuf, ah ; save it.
-
- gcdone: ret ; with character in AL.
-
- gc_trykbd:
- xor ah,ah
- int 16h ; BIOS returns with char in AX
- ; If it's Ctrl-Break, it has already been taken care of.
- or ax,ax
- jz gc_trykbd
-
- gcbark:
- if xlate
- ; Look in the reassignment table to see if it needs translation.
- call lookup ; Z=found; CX=length; SI=ptr
- jnz gc_noredef
- ; Okay; set up the reassignment, and run thru the translation code.
- mov xlatseq.len, cx
- mov xlatseq.adr, si
- jmp getchar
- endif
- gc_noredef:
- or al,al ; Is it a function key?
- jnz gcdone
-
- if fullscreen and not xlate
- cmp ah,84h ; Check if up cursor
- jnz gc_fnkey ; If so, get something from screen
- else
- jmp gc_fnkey
- endif
- getchar endp
-
- if fullscreen ; nothing needed if no full-screen ed.
-
- ; Full Screen Routine
- ; -------------------
-
- ScreenEdit proc near
- push es
- push di
-
- push cs ; Set ax to this segment
- pop es ; And es is also
-
- mov ah,0Fh ; Get Video State
- int 10h ; through BIOS
- dec ah ; Number of columns on screen
- mov [max_x],ah ; Save maximum column
-
- cbw
- cmp al,4
- jb text_mode
- cmp al,7
- jz text_mode
- not ah
-
- text_mode: mov gmode_flag,ah ; BH = Page Number throughout
- mov ah, 3 ; Get cursor in dx
- int 10h ; through BIOS
- mov [cur_coords],dx ; And save the cursor position
-
- call cursor ; delete old pseudocursor
- call Up ; Move cursor up
-
- MainLoop: cmp dh,[cur_y] ; If at line
- jz TermFullScreen ; we started from, terminate
-
- GetKeyboard: call cursor ; redraw pseudocursor
- mov ah,ch ; Get the next key
- int 16h
-
- push ax
- call cursor ; delete pseudocursor
- pop ax
-
- mov bl,[cur_attrib]
-
- or ah,ah ; Alt-<num> input?
- jz PutOnScreen
-
- cmp al,1Bh ; See if Escape key
- jz TermFullScreen ; If so, terminate full screen
-
- ; Back Space
- ; ----------
-
- cmp al,08h ; See if back space
- jnz NotBackSpace ; If not, continue test
-
- or dl,dl ; Check if cursor at left
- jz MainLoop ; If so, do nothing
-
- dec dx ; Otherwise, move cursor back
- call ShiftLeft ; And shift line to the left
-
- jmp MainLoop ; And continue for next key
-
- ; Carriage Return
- ; ---------------
-
- NotBackSpace: cmp al,0Dh ; See if Carriage Return
- jnz PutOnScreen ; If not, continue test
-
- call TransferLine ; Move line into buffer
-
- inc scrnbuf.len ; Put trailing CR into
- inc scrnbuf.adr ; buffer as well
-
- ; Terminate Full Screen Movement
- ; ------------------------------
-
- TermFullScreen: mov dx,[cur_coords] ; Set cursor to original
- call cursor ; draw pseudocursor
-
- pop di
- pop es
-
- jmp getchar
-
- ; Normal Character
- ; ----------------
-
- PutOnScreen: or al,al ; See if normal character
- jz NotNormalChar ; If not, continue test
-
- mov ah,0Ah ; By calling BIOS
- add ah,gmode_flag
-
- cmp [InsertOn],ch ; Check for Insert mode
- jz OverWrite ; If not, overwrite
-
- call ShiftRight ; Shift line right for insert
- jmp Short NormalCharEnd ; And get ready to print
-
- OverWrite: int 10h
-
- NormalCharEnd: mov ax,4d00h ; stuff in a cursor-right
- ; and fall through
-
- ; Cursor Key, Insert, or Delete Subroutine
- ; ----------------------------------------
-
- NotNormalChar: xchg al,ah ; Put extended code in al
- sub al,71 ; See if it's a cursor key
- jc GetKeyboard ; If not, no good
-
- cmp al,12 ; Another check for cursor
- ja GetKeyboard ; If not, skip it
-
- shl ax,1 ; Double for index
- mov di,ax ; into vector table
-
- call [KeyRoutine + di] ; Do the routine
-
- jmp MainLoop ; Back for another key
-
-
- ; Cursor Movement
- ; ---------------
-
- End: call TransferLine ; Move line to buffer
- mov dh,[cur_y] ; Set cursor to original
-
- PgUp: mov dl,[cur_x] ; Move cursor to
- ret ; to original column
-
- Left: sub dl,cl ; Check if cursor at far left
- jc GoNorth ; If so, move it up
- ret
-
- GoNorth: or dh,dh ; Top of screen?
- jz UpEnd ; then don't move
- mov dl,[max_x] ; Move cursor to right margin
-
- Up: sub dh,cl ; Decrement row (CX=1)
- adc dh,ch ; if carry, restore to zero
- ret
-
- Right: cmp dl,[max_x] ; Check if cursor at far right
- jae GoSouth ; If not, move it right
- UpEnd: inc dl
- ret
-
- Home: dec dh ; Move cursor up a row
-
- GoSouth: mov dl,ch ; Set cursor to left of screen
-
- Down: inc dh ; Move cursor down one row
- ret
-
- PgDn: mov cl,[max_x] ; Get last column on screen
- sub cl,dl ; Subtract current column
- inc cx ; Kick it up by one
- mov ax,' '+0Ah*256 ; Write blanks to screen
- int 10h ; through BIOS
- Dummy: ret
-
- ; Insert and Delete
- ; -----------------
-
- Insert: not [InsertOn] ; Toggle the InsertOn flag
- ret ; and return
-
- Delete: ; fall through to ShiftLeft routine
-
-
- ; Shift Line One Space Left (For Delete)
- ; --------------------------------------
-
- ShiftLeft: mov di,0020h ; Blank at end
- mov bl,0Ah ; first write is char. only
- mov cl,[max_x] ; How far to go to
- sub cl,dl ; from where
- inc cx
- add dl,cl ; And put cursor at EOL
- ShiftLeftLoop: dec dx ; Kick down cursor column
- call ReadAndWrite ; Copy a character
- loop ShiftLeftLoop ; And repeat as necessary
- ret
-
-
- ; Shift Line One Space Right (For Insert, called like Int 10h)
- ; ------------------------------------------------------------
-
- ShiftRight: push dx ; Save original cursor
- xchg bl,ah ; Write character and attribute
-
- mov di,ax ; Character to insert
- mov cl,[max_x]
- sub cl,dl
- inc cx
-
- ShiftRightLoop: call ReadAndWrite ; Read character and write
- inc dx ; Kick up cursor column
- loop ShiftRightLoop
-
- pop dx ; Get back original cursor
- ret ; And return from routine
-
- ; Read and Write Character for Line Shifts
- ; ----------------------------------------
-
- ReadAndWrite: push cx
- mov ah,2 ; Set Cursor from dx
- int 10h ; through BIOS
-
- mov ah,8 ; Read Character and Attribute
- int 10h ; through BIOS
-
- xchg ax,di ; Switch with previous char
-
- mov cl,1 ; One character to write
- xchg bl,ah ; Write character and attribute
- int 10h ; through BIOS
- mov bl,9 ; next write is with attribute
- pop cx
- ret ; Return from Routine
-
- ; Transfer Line on Screen to Keyboard Buffer
- ; ------------------------------------------
-
- TransferLine: mov cl,ch ; Count characters in line
- mov di, linebuf ; Place to store 'em
-
- GetCharLoop: mov ah,02h ; Set Cursor at dx
- int 10h ; through BIOS
-
- mov ah,08h ; Read Character & Attribute
- int 10h ; through BIOS
- or al,al ; Space in graphics mode?
- jnz StashIt ; if no, save it
- mov al,' ' ; else use a space
- StashIt: stosb ; Save the character
-
- inc cx ; Increment the counter
- inc dx ; Increment the cursor column
- cmp dl,[max_x] ; See if at end of line yet
- jbe GetCharLoop ; If not, continue
-
- sub dx,cx ; go home
-
- dec di ; Points to end of string
- mov al,' ' ; Character to search through
- std ; Searching backwards
- repz scasb ; Search for first non-blank
- cld
- jz SetBufferCount ; If all blanks, skip down
-
- inc cx
- inc di ; At last character
-
- SetBufferCount: mov scrnbuf.adr, di ; save pointer to last char in string
- mov scrnbuf.len,cx ; pass info to the getchar routine
- mov al,13
- inc di ; After last character
- stosb ; send a carriage return, too
-
- ret ; Return from routine
-
- ; Draw or erase pseudocursor in graphics mode or set text mode cursor
- ; -------------------------------------------------------------------
-
- Cursor: mov ah,2
- int 10h
- mov cx,1 ; just one
- cmp gmode_flag,ch ; if we're in text mode
- jz Set_Text
- cmp pseudo_flag,ch ; or don't want a pseudocursor
- jz Set_Text ; don't draw it
-
- mov ax,0916h ; write a ^V
- mov bl,8fh ; XOR mode
- int 10h
-
- Set_Text: ret
-
- ScreenEdit endp
-
- endif
-
- code ends
- end ; of zavt_k.asm