home *** CD-ROM | disk | FTP | other *** search
-
- title term
-
- public term, gss ; entry points
- include msdefs.h
-
- ; some character definitions
-
- chesc equ 27
- bel equ 7
-
- print_out equ 05h ; dos function to print to printer
- pbout equ 02h ; dos function to print a character
- prscan equ 72h ; print-screen scan code...
- upscan equ 49h ; up page
- dnscan equ 51h ; down page
- ctlup equ 84h ; ctl-up page
- ctldn equ 76h ; ctl-down page
- homscn equ 47h ; home screen
- endscn equ 4fh ; end of screen
- screen equ 10h ; bios screen call
- kb equ 16h ; keyboard interrupt
- alt_shift equ 8H ; alt shift key down
- ctl_shift equ 4H ; ctl key down
- left_shift equ 2H ; left shift key down
- right_shift equ 1H ; right shift key down
-
- timer equ 40h ; timer port
- bel_prt equ 61h ; speaker control
-
- crt_status equ 3dah ; crt status port
- disp_enb equ 8 ; display enable bit
-
- uparr equ 48h ; scan codes for arrow keys
- dnarr equ 50h
- lftarr equ 4bh
- rgtarr equ 4dh
-
-
- modfrm struc ; format of mode line
- db 'Esc chr: '
- m_echr db 2 dup (?)
- db ', Port: '
- m_prt db 1 dup (?)
- db ', Speed: '
- m_baud db 4 dup (?)
- db ', Parity: '
- m_par db 4 dup (?)
- db ', Echo: '
- m_echo db 3 dup (?)
- db ', Type '
- m_hlp db 2 dup (?)
- db '? for Help'
- modfrm ends
-
- datas segment public 'datas'
- waste db 100h dup (?) ;*** need this junk because assembler
- ;*** generates non-relocatable offsets
- ;*** for things like
- ;*** "sub di,offset foo"
- ;*** if offset foo < 100H
- ; stuff for screen routines
- flags db ? ; status flags...
- flags1 db 0 ; internal flags.
- prtscr equ 80h ; print screen pressed
- lnwrap equ 40h ; line wrap enabled.
- inited equ 08h ; been here before...
- cursor dw ?
- esc_ch db ?
- argadr dw ? ; address of arg blk
- ckeys db 0,prscan,dnscan,upscan,endscn,homscn,ctlup,ctldn
- db uparr,dnarr,lftarr,rgtarr
- lckeys equ $-ckeys
- ; ckacts must parallel ckeys above...
- ckacts dw trnbrk,trnprs,upwpg,dnwpg,endwnd,homwnd,dnwind,upwind
- dw trnupw,trndnw,trnlfw,trnrgw
-
- uptrn db esc,'A'
- dntrn db esc,'B'
- rgtrn db esc,'C'
- lftrn db esc,'D'
-
- spctab db chesc,cr,lf,bs,tab,bel
- lspctab equ $-spctab
- spcjmp dw outesc,outcr,outlf,outbs,outtab,outbel ; must match spctab
- esctab db 'YABCDEFGHIJKLM'
- db 'NOZ@[pq<vw'
- lesctab equ $-esctab
- ; escjmp must parallel esctab above
- escjmp dw movcur,curup,curdwn,currt,outbs,clrscr,outign,outign,curhom
- dw revind,clreow,clreol,inslin,dellin,delchr,noins
- dw vtident,entins,doansi
- dw invvid,nrmvid,outign,dowrap,nowrap
- vtidstr db chesc,'/K'
- lvtidst equ $-vtidstr
- coord dw ?
- insmod db ?
- wcoord dw ?
- ttstate dw outtt0
- curattr db ? ; current attribute
- ansarg db ? ; ansi argument value
- igncnt db ? ; # of chars to ignore
- beldiv dw 2dch ; 550 hz?
- crt_mode db ?
- crt_cols db ?
- crt_lins db ?
- low_rgt dw ? ; lower right corner of window
- ; key redefinitions
- ktrntab dw ? ; address of translation table
- krpltab dw ? ; address of replacement table
- tmptab db 0eh,3bh ; scan code for bs, f1
- ktlen dw ?
- modbuf modfrm <> ; mode line buffer
- ; routine to call for captured output
- captrtn dw ?
- ; some static data for mode line
- unkbaud db 'Unk ' ; must be 4 chars...
- baudn db '45.5'
- db ' 50'
- db ' 75'
- db ' 110'
- db ' 135'
- db ' 150'
- db ' 300'
- db ' 600'
- db '1200'
- db '1800'
- db '2000'
- db '2400'
- db '4800'
- db '9600'
- baudnsiz equ 14 ; # of baud rates known (tbl size / 4)
- parnams db 'Even'
- db 'Mark'
- db 'None'
- db 'Odd ' ; must be 4 chars
- db 'Spc '
- offmsg db 'Off'
- onmsg db 'On '
- lclmsg db 'Lcl'
- remmsg db 'Rem'
- ; storage for multi-window stuff
- swidth equ 80
- slen equ 24
- npgs equ 5 ; # of pages on each side
- bsize equ swidth*slen*npgs*2
- scrsav dw swidth*slen dup (0700H) ; a blank screen
-
- ; circular buffer. To work properly, the buffer size should be an exact
- ; multiple of swidth*2
- cbuf struc
- pp dw ? ; place ptr in buffer
- bend dw ? ; end of buffer
- orig dw ? ; buffer origin
- lcnt dw 0 ; # of lines in buffer.
- cbuf ends
-
- topbuf db bsize dup (?)
- botbuf db bsize dup (?) ; top and bottom windows
- tlbuf db swidth*2 dup (?)
- blbuf db swidth*2 dup (?)
- twnd cbuf <topbuf,topbuf+bsize-1,topbuf,0>
- bwnd cbuf <botbuf,botbuf+bsize-1,botbuf,0>
- portno db ?
- prton db 'Printer: on'
- prtnlen equ $-prton
- prtoff db 'Printer: off'
- prtflen equ $-prtoff
- datas ends
-
- code segment public ; code segment
- extrn prtchr:near,outchr:near,sendbr:near
- assume cs:code,ds:datas,es:datas
-
- scrini proc near ; init screen stuff
- mov ah,15 ; read video state...
- int screen
- mov crt_mode,al ; save crt mode
- cmp ah,crt_cols ; is real # of cols < passed?
- jge scrin1 ; no
- mov crt_cols,ah ; yes, save # of cols
- scrin1: mov dl,crt_cols ; # of cols again
- mov dh,crt_lins ; and # of rows
- dec dl
- dec dh
- mov low_rgt,dx ; save away window address
- mov insmod,0 ; not in insert mode
- mov dx,cursor ; assume old cursor
- test flags1,inited ; have we been here before?
- jnz scrin4 ; yes, use old cursor
- mov curattr,07 ; else set nice screen attribute
- mov ttstate,offset outtt0 ; normal screen state
- mov ah,3 ; figure out where cursor is
- xor bh,bh ; page 0
- int screen ; read cursor position
- cmp dh,crt_lins ; past logical end of screen?
- jb scrin2 ; no, keep going
- mov dh,byte ptr low_rgt+1 ; yes, just use lower right corner
- scrin2: cmp dl,crt_cols ; maybe past right margin
- jb scrin3 ; no, use the way it is
- mov dl,byte ptr low_rgt
- scrin3: mov cursor,dx ; init cursor
- scrin4: mov ah,2
- xor bh,bh
- int screen ; set cursor in case it moved
- ret
- scrini endp
-
- argini proc near ; read passed arguments
- mov bx,argadr ; base of argument block
- mov al,[bx].flgs ; get flags
- and al,capt+emheath+havtt+trnctl+lclecho+modoff
- mov flags,al ; mask for allowable and save
- and flags1,not (prtscr) ; these are allowable
- ; (others remain).
- mov al,[bx].prt
- cmp al,portno ; using same port?
- je argin1 ; yes, go on
- and flags1,not inited ; else re-init stuff
- argin1: mov portno,al ; update port number
- mov al,[bx].cols
- mov crt_cols,al
- mov al,[bx].rows
- mov crt_lins,al ; init # of rows and cols
- mov ax,[bx].captr
- mov captrtn,ax ; buffer capture routine
- mov ax,[bx].belld
- mov beldiv,ax ; bell divisor
- mov ax,[bx].klen
- mov ktlen,ax ; length of key redef tbl
- mov ax,[bx].ktab
- mov ktrntab,ax ; save key translation table
- mov ax,[bx].krpl
- mov krpltab,ax
- mov al,[bx].escc
- mov esc_ch,al
- ret ; that's it
- argini endp
-
- modlin proc near ; turn on mode line
- mov al,esc_ch
- mov modbuf.m_echr,' ' ; first char is initial space
- mov modbuf.m_hlp,' ' ; goes here too.
- cmp al,32 ; printable?
- jnb modl1 ; yes, keep going
- add al,40h ; made printable
- mov modbuf.m_echr,'^' ; note control char
- mov modbuf.m_hlp,'^'
- modl1: mov modbuf.m_echr+1,al ; fill in character
- mov modbuf.m_hlp+1,al
- mov bx,argadr ; get argument block
- mov al,[bx].baudb ; get baud bits
- mov si,offset unkbaud ; assume unknown baud
- cmp al,baudnsiz ; too big?
- jnb modl2 ; yes, use default
- mov cl,2 ; each is 4 bytes long
- shl al,cl
- mov ah,0
- add ax,offset baudn
- mov si,ax
- modl2: mov cx,size m_baud ; length of baud space
- mov di,offset modbuf.m_baud
- rep movsb ; copy in baud rate
- mov al,[bx].parity ; get parity code
- mov cl,2 ; each is 4 bytes long...
- shl al,cl
- mov ah,0
- add ax,offset parnams ; names of parity settings
- mov si,ax
- mov cx,4 ; each is 4 long
- mov di,offset modbuf.m_par
- rep movsb
- mov si,offset lclmsg ; assume remote echoing
- test flags,lclecho ; echoing?
- jz modl4 ; no, keep going
- mov si,offset remmsg
- modl4: mov cx,3 ; size of on/off
- mov di,offset modbuf.m_echo
- rep movsb
- mov al,'1'
- cmp portno,1 ; port 1?
- je modl5 ; yes, keep going
- mov al,'2'
- modl5: mov modbuf.m_prt,al ; fill in port number
- mov cx,size modfrm ; this is size of mode line
- mov si,offset modbuf ; mode line image
- ; alternate entry to write an alternate mode line
- modwrt: push cx
- push si ; save mode line and size
- mov dx,24 * 100h ; 25th line for mode line
- push word ptr curattr ; save current attributes
- mov curattr,70h ; want inverse video
- call clreol ; clear to end of line...
- pop word ptr curattr ; restore attributes
- mov dx,24 * 100h
- mov bh,0
- mov ah,2 ; set cursor position
- int screen
- pop si
- pop cx ; restore these
- modl6: lodsb ; get a byte
- mov ah,14 ; write to terminal
- mov bh,0 ; page 0
- int screen
- loop modl6 ; write out entire mode line
- mov dx,cursor
- mov ah,2
- mov bh,0
- int screen ; put cursor back where it belongs
- ret ; and return
- modlin endp
-
- clrmod proc near ; clear mode line
- mov ax,600h ; blank window
- mov cx,24 * 100h ; beginning of window
- mov dx,24 * 100h + 79 ; end of window
- mov bh,07 ; nice attribute
- int screen ; clear mode line
- ret ; and return
- clrmod endp
-
- term proc near ; terminal emulator entry point
-
- mov argadr,ax ; save argument ptr
- push es ; save caller's extra segment address
- mov ax,seg datas
- mov es,ax
-
- call argini ; init options from arg address
-
- call scrini ; init screen stuff
-
- test flags1,inited ; have we run yet?
- jz term1 ; no, forget this part
- call restscr ; restore screen
- term1: or flags1,inited ; remember we've run already.
-
- call clrmod ; empty mode line
- test flags,modoff ; is mode line disabled?
- jnz lp ; yes, skip it
- call modlin ; turn on mode line
-
- lp: call portchr ; char at port?
- jnc chkinp ; no, keep going
- call outtty ; print on terminal
-
- chkinp: mov ah,1
- int kb
- jz lp ; nothing available...
- xor ah,ah
- int kb ; get the char from the buffer
- push ax ; save character temporarily
- call gss ; get shift state into al
- mov bl,al ; save shift state
- pop ax
-
- cmp al,esc_ch ; escape character?
- je quit ; yes, stop here
-
- call trnout ; translate if nec., output to prt
- jmp chkinp ; and keep going
-
- quit: call clrmod ; erase mode line
- call savescr ; save screen
-
- mov al,flags
- mov bx,argadr
- mov [bx].flgs,al ; update flags in arg block
- pop es ; restore segment register
- ret ; and return to caller
-
- term endp
-
- ; get shift state into al. We only care about shift, ctl, and alt keys.
- ; right shift is collapsed into left shift.
- gss proc near
- mov ah,2
- int kb ; get current shift state
- mov bl,al ; copy for a moment
- and bl,right_shift ; mask out all but right shift
- shl bl,1 ; move right shift to left shift pos
- or al,bl ; collapse shift bits
- and al,(left_shift + alt_shift + ctl_shift)
- ret
- gss endp
-
- ; save the screen so we can restore it
- ; maybe save cursor also.
- savescr proc near
- push ds
- mov si,0
- mov di,offset scrsav ; place to put screen
- mov cx,80*24 ; # of words on screen
- call scrseg
- push ax ; save screen segment
- call scrwait ; wait for screen to be ready
- pop ds ; address screen
- rep movsw ; save the screen
- pop ds ; restore this
- ret ; and return
- savescr endp
-
- ; restore screen from scrsav buffer
- restscr proc near
- push es
- mov si,offset scrsav ; source
- mov di,0
- mov cx,80*24
- call scrseg
- mov es,ax
- call scrwait
- rep movsw ; restore it
- pop es
- ret
- restscr endp
-
- ; send the character in al out to the serial port
- ; handle echoing also...
- outprt proc near
- test flags,lclecho ; echoing?
- jz outpr1 ; no, forget it
- push ax ; save char
- call outtty ; print it
- pop ax ; restore
- outpr1: mov ah,al ; this is where outchr expects it
- call outchr ; output to the port
- nop
- nop
- nop ; skip returns...
- ret
- outprt endp
-
- ; returns with carry on if a character is available
-
- portchr proc near
- call prtchr ; character at port?
- jmp short portc1 ; yes, go handle
- nop ; skip return is stupid...
- clc ; no carry -> no character
- ret ; and return...
- portc1: and al,7fh ; we don't worry about parity here
- stc ; have a character
- ret ; and return
- portchr endp
-
-
- ; translate the scan code in ah according to the translate table
- ; given in ktrntab/krpltab, output to port. If no translation,
- ; use ascii char in al. (should probably include shift state
- ; somewhere). Shift state is in bl.
- trnout proc near
- cmp ah,4eh ;*** plus key thing?
- je trnmod ; yes, go toggle mode line
- trnou1: test flags,havtt ; translate table given?
- jz trnou3 ; no, just output character
- push ax ; save original value
- mov al,ah ; put scan code into ah
- mov ah,bl ; shift state into top half.
- mov di,ktrntab ; pick up translate tbl
- mov cx,ktlen ; length of tbl
- repne scasw ; look for our key
- pop ax ; recover character
- jne trnou3 ; not found, forget it
- sub di,ktrntab ; get index into tbl
- sub di,2 ; (minus 2 for pre-increment)
- mov bx,krpltab ; get replacement table
- mov si,[bx][di] ; and addr of replacement
- mov cl,[si] ; get first byte (length)
- xor ch,ch ; clear high-order byte
- inc si ; point to translation string
- trnou2: lodsb ; get a byte
- push si
- push cx ; save important registers
- call outprt ; s
- pop cx
- pop si
- loop trnou2
- ret
- trnou3: cmp al,0
- jnz trnou4
- mov al,ah
- mov cx,lckeys ; length of table
- mov di,offset ckeys ; table address
- repne scasb
- mov al,0 ; ascii code was 0...
- jne trnou4 ; not found, keep going
- sub di,offset ckeys+1 ; get table offset
- shl di,1 ; shift for word offset
- jmp ckacts[di] ; jump to appropriate routine
- trnou4: call outprt ; just output single char
- ret ; and return
-
- trnmod: test flags,modoff ; mode line already off?
- jnz trnm1 ; yes, go turn on
- call clrmod ; no, clear mode line here
- or flags,modoff ; turn on flag
- ret ; and return
- trnm1: call modlin ; turn on mode line
- and flags,not modoff ; clear flag
- ret ; and return
-
- trnbrk: mov ah,dconio
- mov dl,0ffH
- int dos ; read the bogus ^C DOS gets.
- call sendbr
- ret
- trnprs: xor flags1,prtscr ; flip the flag
- and flags,not modoff ; turn on mode line
- mov si,offset prton
- mov cx,prtnlen
- test flags1,prtscr ; did it go on?
- jnz trnpr1 ; yes, say so
- mov si,offset prtoff
- mov cx,prtflen
- trnpr1: call modwrt ; write into mode line
- ret ; and return
-
- ; common entry for arrow keys
- trnarr: mov cx,2 ; length is always 2
- jmp trnou2 ; go send definition
-
- trnupw: mov si,offset uptrn
- jmp trnarr
-
- trndnw: mov si,offset dntrn
- jmp trnarr
-
- trnlfw: mov si,offset lftrn
- jmp trnarr
-
- trnrgw: mov si,offset rgtrn
- jmp trnarr
-
- trnout endp
-
- ; move viewing window up (screen moves down).
- ; alternate entry upwin2 doesn't beep if invalid.
- upwind proc near
- mov ax,offset tlbuf ; place to put line temporarily
- mov bx,offset twnd ; where to get lines from
- call getcirc ; try to get a line
- jnc upwin3 ; have a line, go show it
- call outbel ; else ring bel
- ret ; and return
- upwin2: mov ax,offset tlbuf
- mov bx,offset twnd
- call getcirc
- jnc upwin3
- ret ; this just rets if no line avail.
- upwin3: mov ax,offset blbuf ; place for bottom line
- call getbot ; fetch bottom line
- mov ax,offset blbuf
- mov bx,offset bwnd
- call putcirc ; save in circular buffer
- mov ax,701h ; scroll down one line
- xor cx,cx ; from top
- mov dx,low_rgt ; to bottom
- mov bh,curattr
- int screen ; scroll it down
- mov di,0 ; offset for destination
- mov si,offset tlbuf ; where to get line from
- mov cx,swidth ; length of line
- push es
- call scrseg
- push ax
- call scrwait
- pop es
- rep movsw ; copy the line in
- pop es ; restore this
- ret ; and return
- upwind endp
-
-
- ; move viewing window down a line (screen scrolls up)
- ; entry dwin2 does same w/out checking to see if scroll is legal
- dnwind proc near
- mov ax,offset blbuf ; place to put line temporarily
- mov bx,offset bwnd ; where to get lines from
- call getcirc ; try to get a line
- jnc dnwin3 ; have a line, go show it
- call outbel ; else ring bel
- ret ; and return
- dnwin2: mov ax,offset blbuf
- mov bx,offset bwnd
- call getcirc
- jnc dnwin3
- ret ; this just rets if no line avail.
- dnwin3: call scrprep ; save top line
- mov ax,601h ; scroll up one line
- xor cx,cx ; from top
- mov dx,low_rgt ; to bottom
- mov bh,curattr
- int screen ; scroll it down
- mov dx,low_rgt
- mov dl,0 ; get addr of last line
- call scrloc
- mov di,ax ; this is offset in dest
- mov si,offset blbuf ; where to get line from
- mov cx,swidth ; length of line
- push es
- call scrseg
- push ax
- call scrwait
- pop es
- rep movsw ; copy the line in
- pop es ; restore this
- ret ; and return
- dnwind endp
-
- ; move viewing window down as much as possible...
- endwnd proc near
- mov cx,1000 ; large number of lines
- jmp dnwp1 ; and enter dwnpg
- endwnd endp
-
- ; scroll viewing window down (contents move up) crt_lins times...
- dnwpg proc near
- mov cl,crt_lins
- mov ch,0
- dnwp1: push cx ; save this
- call dnwin2
- pop cx
- loop dnwp1
- ret ; and return
- dnwpg endp
-
- ; home viewing window
- homwnd proc near
- mov cx,1000 ; large # of lines
- jmp upwp1 ; join upwpg
- homwnd endp
-
- ; scroll viewing window up (screen moves down) a page
- upwpg proc near
- mov cl,crt_lins
- mov ch,0
- upwp1: push cx
- call upwin2
- pop cx
- loop upwp1
- ret ; and return
- upwpg endp
-
- ; get the bottom line into the buffer pointed to by ax.
- getbot proc near
- push ds
- mov di,ax ; save dest
- mov cx,swidth
- mov dx,low_rgt
- mov dl,0
- call scrloc
- mov si,ax
- call scrseg
- push ax
- call scrwait
- pop ds
- rep movsw
- pop ds
- ret
- getbot endp
-
- ; put a line into the circular buffer. Pass the buffer structure
- ; in bx, the pointer to the line in ax.
- putcirc proc near
- push si
- push di
- push cx
- push dx
- mov di,[bx].pp ; pick up buffer ptr
- add di,2*swidth ; increment to next avail slot
- cmp di,[bx].bend ; past end?
- jb putci1 ; no, leave alone
- mov di,[bx].orig ; else start at beginning
- putci1: mov [bx].pp,di ; update ptr
- mov si,ax ; this is source
- mov cx,swidth
- rep movsw ; copy into buffer
- cmp [bx].lcnt,npgs*slen ; can we increment it?
- jae putci2 ; no, keep going
- inc [bx].lcnt ; else count this line
- putci2: pop dx
- pop cx
- pop di
- pop si ; restore registers
- ret
- putcirc endp
-
- ; get a line from the circular buffer, removing it from the buffer.
- ; returns with carry on if the buffer is empty.
- ; pass the buffer structure in bx, the buffer to copy the line into
- ; in ax.
- getcirc proc near
- push si
- push di
- push cx
- push dx
- cmp [bx].lcnt,0 ; any lines in buffer?
- jne getci1 ; yes, ok to take one out.
- stc ; else set carry
- jmp short getcir3 ; and return
- getci1: mov si,[bx].pp ; this is source
- mov di,ax ; this is dest
- mov cx,swidth ; # of chars to copy
- rep movsw
- mov si,[bx].pp ; get ptr again
- sub si,2*swidth ; move back
- cmp si,[bx].orig ; compare to origin
- jae getcir2 ; still in range, continue
- mov si,[bx].bend ; else use end of buffer
- sub si,2*swidth-1 ; minus length of a piece
- getcir2:mov [bx].pp,si ; update ptr
- dec [bx].lcnt ; decrement # of lines in buffer
- clc ; make sure no carry
- getcir3:pop dx
- pop cx
- pop di
- pop si
- ret
- getcirc endp
-
- ; call before scrolling to save top line...
- scrprep proc near
- push ds
- mov si,0 ; offset of top line
- mov cx,swidth ; length of line
- mov di,offset tlbuf ; place to put line temporarily
- call scrseg
- push ax
- call scrwait
- pop ds
- rep movsw ; copy the line
- pop ds ; restore this
- mov ax,offset tlbuf
- mov bx,offset twnd ; this is where it goes
- call putcirc ; put into buffer
- ret ; and return
- scrprep endp
-
-
- ; put the character in al to the screen
- outtty proc near
- test flags,capt ; capturing output?
- jz outnoc ; no, forget this part
- push ax ; save char
- call captrtn ; give it captured character
- pop ax ; restore character and keep going
-
- outnoc: test flags1,prtscr ; should we be printing?
- jz outnop ; no, keep going
- push ax
- mov ah,print_out
- mov dl,al ; put character here for dos...
- int dos
- pop ax
-
- outnop: test flags,emheath ; emulating heath?
- jnz outnop1 ; yup, go do something smart
- mov dl,al
- mov ah,pbout
- int dos ; else let dos print char
- ret ; and return
-
- outnop1:mov dx,cursor ; these may need cursor...
- jmp ttstate ; jump according to current state
-
- outtt0:
- cmp al,32 ; special character?
- jb outtt1 ; yes, handle specially...
-
- cmp insmod,0 ; in insert mode?
- je outnrm ; no, output normal
- push ax ; save character
- call inschr ; insert a character
- pop ax
- outnrm: xor bh,bh ; current page
- mov cx,1 ; only one char
- mov bl,curattr ; with current attribute
- mov ah,9
- int screen ; put onto screen
- mov dx,cursor ; get cursor pos
- currt: inc dl ; bump col
- cmp dl,crt_cols ; see if in range
- jb setcur ; in range, go set cursor
- test flags1,lnwrap ; in wrap mode?
- jz outign ; no, just return w/out updating cursor
- xor dl,dl
- inc dh ; handle wrap
- setcur: cmp dh,crt_lins
- jb setc1 ; not off end, keep going
- push dx ; save row/col
- call scrprep ; save top line in window buf
- mov ax,0601h ; scroll up one line
- xor cx,cx ; from 0,0
- mov dx,low_rgt ; to 24,80
- mov bh,curattr ; nice attribute
- int screen ; do the scroll
- pop dx
- mov dh,crt_lins ; go to bottom line again...
- dec dh
- setc1: xor bh,bh ; page is 0
- mov cursor,dx ; save cursor pos
- mov ah,2
- int screen ; set cursor
- outign: ret ; and return
- ; special character (in al)
- outtt1: mov di,offset spctab ; special char table
- mov cx,lspctab ; length of tbl
- repne scasb ; look for char in tbl
- jz outtt2 ; found, go do something with it
- test flags,trnctl ; are we allowed to print carets?
- jz outign ; no, just ignore it.
- push ax ; save char
- mov al,'^'
- call outtty ; print caret
- pop ax
- add al,'A'-1 ; make printable
- jmp outtty ; print, then return
-
- outtt2: mov dx,cursor ; might need cursor pos
- sub di,offset spctab+1 ; get index of char
- shl di,1 ; double for word offset
- jmp spcjmp[di] ; and go handle
-
- ; special char routines. cursor is in dx, char in al
-
- outlf: inc dh ; bump row
- jmp setcur
-
- outcr: xor dl,dl ; set col to 0
- jmp setcur
-
- outbs: or dl,dl
- jle setcur ; col 0, can't back up
- dec dl ; back up col
- jmp setcur ; and use if reasonable
-
- outtab: mov dl,byte ptr cursor ; get initial column
- outta1: mov dh,dl ; save column ptr
- push dx
- mov al,' ' ; output a space
- call outtty ; convenient, huh?
- pop dx
- mov dl,byte ptr cursor
- cmp dh,dl ; is it moving?
- je outta2 ; no, forget this
- test dl,7 ; is it a multiple of 8?
- jnz outta1 ; no, keep going
- outta2: ret ; else return
-
- ; stolen from bios
- outbel: mov al,10110110b ; timer initialization
- out timer+3,al
- mov ax,beldiv ; bel divisor
- out timer+2,al
- mov al,ah
- out timer+2,al ; output divisor
- in al,bel_prt
- mov ah,al ; remember original value
- or al,3 ; turn speaker on
- out bel_prt,al
- mov cx,8888h
- outbe1: loop outbe1 ; wait a while
- mov al,ah
- out bel_prt,al ; turn bell off
- ret ; and return
-
- outesc: mov ttstate,offset escseq ; expect escape sequence.
- ret ; and return
-
- ; escape-char handling routines
- escseq: mov ttstate,offset outtt0 ; put state back to normal
- mov di,offset esctab ; escape char tbl
- mov cx,lesctab ; length of tbl
- repne scasb ; look for it in tbl
- jz escsq1 ; found, go use it
- jmp outtty ; not there, just print it
- escsq1: sub di,offset esctab+1 ; get offset into tbl
- shl di,1 ; convert to word offset
- jmp escjmp[di] ; and go dispatch on it
-
- ; escape dispatch routines
- revind: cmp dh,0
- jle revin1
- dec dh ; back up a row
- jmp setcur ; and go set cursor
- revin1: push dx ; save cursor pos
- mov ax,701h ; scroll down one line
- xor cx,cx ; from top
- mov dx,low_rgt ; to bottom
- mov bh,curattr
- int screen ; scroll it down
- pop dx ; restore cursor.
- mov dh,0 ; set row back to 0
- jmp setcur
-
- curup: cmp dh,0 ; w/in range?
- jle curu1 ; no, skip this
- dec dh ; else back up
- curu1: jmp setcur ; and go set position
-
- curdwn: inc dh
- jmp setcur ; increment row (setcur can scroll!)
-
- ; currt is above
-
- clrscr: call curhom ; go home cursor
- jmp clreow ; then clear to end of window
-
- curhom: xor dx,dx ; move to 0,0
- jmp setcur
-
- clreow: cmp dl,0 ; at beginning of line?
- jz clrw1 ; yes, skip this part...
- push dx ; remember cursor pos
- call clreol ; clear to end of this line
- pop dx
- inc dh ; bump row
- xor dl,dl ; start from col 0
- clrw1: cmp dh,crt_lins ; last line on screen
- jnb clrw2 ; if not in range, forget it
- mov ax,700h ; clear whole window
- mov cx,dx ; this is beginning
- mov dx,low_rgt
- ; mov dx,174fh ; this is lower right corner
- mov bh,curattr ; default attribute
- int screen ; go clear it
- clrw2: ret ; and return
-
- clreol: push es
- mov cl,crt_cols ; last col + 1
- sub cl,dl ; this is # of chars to move
- xor ch,ch
- jcxz clrl1
- call scrloc ; compute screen location (to ax)
- mov di,ax
- call scrseg
- mov es,ax ; address screen segment
- call scrwait ; wait for retrace
- mov ah,curattr ; current attribute
- mov al,' ' ; fill char
- rep stosw ; fill line with spaces
- clrl1: pop es
- ret ; and return
-
- inslin: mov al,1 ; scroll one line
- ; alternate entry if inserting more then one line
- inslin1:mov ch,dh ; start at current row
- xor cl,cl ; column 0
- mov dx,low_rgt
- ; mov dx,174fh ; to bottom of screen
- mov ah,7h ; scroll down.
- mov bh,curattr ; attribute
- int screen
- ret
-
- dellin: mov al,1 ; scroll 1 line
- ; alternate entry if deleting more than one line
- dellin1:mov ch,dh ; start at current row
- xor cl,cl ; column 0
- mov dx,low_rgt
- ; mov dx,174fh ; to bottom of screen
- mov ah,6h ; scroll up.
- mov bh,curattr ; attribute
- int screen
- ret
-
- delchr: push ds
- push es
- pushf ; these may get changed...
- mov cl,crt_cols
- dec cl
- sub cl,dl ; from what we're fiddling)
- xor ch,ch
- jcxz delch1 ; none to move, forget it
- call scrloc ; compute location
- mov di,ax
- mov si,ax
- add si,2 ; source is next position over
- call scrseg ; pick up screen segment
- push ax ; put screen segment onto stack
- mov es,ax ; and in destination segment
- call scrwait ; wait for retrace
- pop ds ; address screen segment
- rep movsw ; delete it
- mov byte ptr [di],' ' ; kill char at end of line
- delch1: popf
- pop es
- pop ds
- ret
-
- inschr: push ds
- push es ; save these as well
- pushf ; might as well save flags...
- mov dx,cursor ; this is place to do it
- mov cl,crt_cols
- dec cl
- ; mov cl,79 ; this is last col to move, +1 for length
- sub cl,dl ; compute distance to end
- xor ch,ch ; clear top half of offset
- jcxz insch1 ; nothing to move...
- mov dl,crt_cols
- sub dl,2 ; last col to move
- ; mov dl,78 ; this is address of last col to move
- call scrloc ; compute pos
- mov si,ax
- mov di,ax
- add di,2 ; destination is one byte over...
- std ; remember to move us backwards
- call scrseg ; find screen segment
- mov es,ax
- push ax ; save screen seg on stack
- call scrwait ; w
- pop ds
- rep movsw ; move each char and attribute
- insch1: popf
- pop es
- pop ds
- ret ; and return
-
- noins: mov insmod,0 ; turn off insert mode
- ret ; and return
-
- movcur: mov wcoord,2 ; want two coordinates...
- mov ttstate,offset getcoord
- ret ; and return
-
- vtident: mov si,offset vtidstr
- mov cx,lvtidst
- vtid1: lodsb ; get a byte from the string
- push si ; have to save from outprt
- push cx
- call outprt ; send to serial port
- pop cx
- pop si
- loop vtid1 ; go thru all chars
- ret ; and return
-
- entins: mov insmod,0ffh ; enter insert mode...
- ret ; and return
-
- doansi: mov ansarg,0 ; ansi argument is 0 (default)
- mov ttstate,offset getaarg ; state is get ansi argument
- ret
-
- getaarg:cmp al,'0'
- jb getaa1 ; in range for digit?
- cmp al,'9'
- ja getaa1
- sub al,'0' ; convert to binary
- mov dl,al ; tuck away
- mov al,ansarg
- mov dh,10
- mul dh ; shift sum
- add al,dl ; add in this digit (what about ovfl?)
- mov ansarg,al
- ret ; and return
-
- getaa1: cmp al,'?' ; the dreaded question mark?
- jne getaa2
- mov ttstate,offset ignn ; we ignore these...
- mov igncnt,2 ; this is how many chars come after him
- ret
-
- getaa2: mov ttstate,offset outtt0 ; reset state
- mov dx,cursor ; this needs cursor position
- mov bl,ansarg
- xchg al,bl ; put argument in nice place
- cmp bl,'L' ; insert line?
- jne getaa3
- jmp inslin1 ; and go do it
-
- getaa3: cmp bl,'M' ; maybe delete line?
- jne getaa4
- jmp dellin1
-
- getaa4: ret ; ignore.
-
- invvid: mov curattr,70h ; attribute for inverse video
- ret
-
- nrmvid: mov curattr,07h ; attribute for normal video
- ret
-
- dowrap: or flags1,lnwrap ; turn on wrap mode
- ret ; and return
-
- nowrap: and flags1,not lnwrap ; turn off wrap mode
- ret ; and return
-
- ; get a coordinate.
- getcoord:
- sub al,32 ; coordinates offset by 32
- mov si,wcoord
- dec si
- mov byte ptr coord[si],al ; fill in appropriate coordinate
- mov wcoord,si ; update flag
- jnz getco1 ; more needed, can't do anything yet
- mov ttstate,offset outtt0 ; reset state
- mov dx,coord ; get coordinates
- jmp setcur ; and go jump there
- getco1: ret
-
- ; ignore following igncnt characters
- ignn: dec igncnt ; decrement count
- jnz ignn1
- mov ttstate,offset outtt0 ; put state back to normal if done
- ignn1: ret
-
- outtty endp
-
- ; computes screen location to ax, given row and col in dx.
- ; trashes ax,bx
- scrloc proc near
- mov al,dh ; get row
- mov bl,crt_cols ;** row size
- mul bl ; multiply by row size
- xor dh,dh ; clear col
- add ax,dx ; this is current position
- sal ax,1 ; double for attributes
- ret
- scrloc endp
-
- ; puts current screen segment in ax
- scrseg proc near
- mov ax,0b000h ; assume bw for now
- cmp crt_mode,7 ; 7 is bw (***)
- je scrse1
- mov ax,0b800h ; color card
- scrse1: ret
- scrseg endp
-
- ; wait for retrace so can write to screen memory
- scrwait proc near
- cmp crt_mode,7 ; bw mode?
- je scrwa3 ; yes, no waiting
- push dx
- mov dx,crt_status
- scrwa1: in al,dx
- test al,disp_enb ; display enable?
- jnz scrwa1 ; yes, keep waiting
- scrwa2: in al,dx
- test al,disp_enb ; now wait for it to go off
- jz scrwa2 ; so can have whole cycle
- pop dx
- scrwa3: ret
- scrwait endp
-
- code ends
- end
-