; termio.z - subroutines for doing the terminal i/o part of qterm .incl "c:termcap" .incl "c:vars" .macro table byte,addr dw addr db byte .endm .extern procch procch: call kbdcc ; get a char if it's waiting or a jr z,lstmod ; skip if no character cp 'x' & 0x1f ; ctl x? jp z,canscr ; quit if so ld e,a ; save char in e ld a,(escval) ; get the escape value ld hl,pccs inc (hl) dec (hl) ; what state? jr z,pccs0 ; state zero - look for escape dec (hl) ; reset to 0 cp e ; escape twice? jr z,pccop ; yes - send one to modem ld a,e ; get char back cp ',' ; was it a ','? call z,hangup ; hang up if so cp '.' ; or a '.' call z,break ; do a break jr lstmod ; This is here for branch length reasons .extern modop modop: ; send a character to the modem, respecting ; half duplex etc. push af call modopc ; send it to the modem first pop hl ld a,(wflg) ; window mode? or a ld a,h ; get character back jr z,nowin push hl call winsnd ; go give it to window input code pop af ; char back cp '\r' ret nz ; returns get special processing ld a,(eflg) ; echo mode? or a ret z ; return if not ld a,'\n' ; throw a linefeed into the system jr modop nowin: ld a,(hflg) ; half duplex? or a ret z ld a,h ; get character again cp '\r' jr nz,ipchar ; pass non-return chars straight in ld a,(eflg) ; echo mode too? or a ld a,h ; get the '\r' back jr z,ipchar ; no echo mode, don't expand it call ipchar ; go send return to receive code ld a,'\n' jr ipmchr ; throw a newline into system as well pccs0: cp e ; did we see an escape? jr z,setesc ; yes, set the flag ld a,e pccop: call modop ; send char to modem db 0x3e ; ld a,xx opcode setesc: inc (hl) .extern lstmod lstmod: call wrtscn ; keep the printer going and check if a ; character is waiting at the modem port. ret c ; return if nothing arrived ld hl,ecval ; echo check needed? dec (hl) inc (hl) jr z,noec ; jump if not cp (hl) ; did we match? jr nz,noec ; no - leave value in place ld (hl),1 ; reset to say we got it noec: ld hl,bmask and (hl) ; mask if 7 bit mode scf ret z ; return on nulls as well ld hl,cscqfl inc (hl) dec (hl) ; ^S ^Q spotting enabled? jr z,nocscq bit 0,(hl) jr nz,nocs ; waiting for a ^Q? cp 's' & 0x1f ; ^S ? jr nz,nocscq ; nope, check status now set 0,(hl) ; flag that a ^S arrived scf ret nocs: cp 'q' & 0x1f ; was it a ^Q jr z,wascq cp 's' & 0x1f ; also let a second ^S toggle jr nz,nocscq ; not yet - pass this character wascq: res 0,(hl) ; clear the flag scf ret nocscq: ld hl,eflg inc (hl) dec (hl) ; echo mode? zipch: jr z,ipchar ; no, hand straight to input code cp '\r' ; return? jr nz,ipmchr ; no, echo and hand to input code call ipmchr ; otherwise process, ld a,'\n' ; and send a newline into the system as well ipmchr: push af call modopc ; send character to modem to echo it pop af .extern ipchar ; needed for sendcs in chat ipchar: ld c,a ; save char in c ld a,(jflg) or a ; junking control characters? ld a,c call nz,limitb ; if so it gets tested ret c ; and thrown if bad push af ; save the character call opchar pop af call oplst ; output to printer or a ; clear the carry ld hl,cflg bit 0,(hl) ; catch mode enabled ret z ; no - return ld hl,(cptr) ld (hl),a ; save char away inc hl ld (cptr),hl ; update pointer ld de,(endcbf) or a sbc hl,de ; buffer full? scf ccf ; clear carry w/o affecting zero ret nz ; no - keep going push af call flushc ; go flush data in catch buffer call ctlq pop af ret .extern savrng savrng: ; get a char and save in ring buffer call modist ; char available? ret z ; no. call modin ; get it ld de,(ringpw) ; pick up indices ld hl,(ringpr) inc de ; move write index res 2,d or a sbc hl,de ; buffer full? ret z ; return if so ld (ringpw),de ; save revised index ld hl,ring add hl,de ld (hl),a ret wrtscn: call wrtlst ; keep printer output rolling call savrng ; get any incoming characters ld de,(ringpr) ld hl,(ringpw) xor a sbc hl,de ; anything in the ring? scf ret z ; nope inc de res 2,d ld (ringpr),de ; save new index ld hl,ring add hl,de ; index into buffer ld a,(hl) ; get the char ret ; and return it .extern oplst ; put a character in the list ring buffer oplst: ld hl,oflg ; are we saving? bit 0,(hl) ret z ; return if not push bc ; save bc ld hl,(lstpr) ld de,(lstpw) ; get the list ring buffer indices inc de ; move the write pointer res 2,d ; wrap if it hits 1K or a sbc hl,de ; check for buffer full jr nz,notful push af ; save the character call ctls ; send an xoff and wait for things to cool mtloop: call wrtlst ; write a character if we can jr nc,mtloop ; keep writing if we're not done call ctlq ; OK - you can wake up again pop af ; restore char again notful: ld hl,(lstpw) inc hl res 2,h ld (lstpw),hl ; save the revised write pointer ld de,lstbuf ; address the list buffer add hl,de ld (hl),a ; and save the character pop bc ; get bc back. ret wrtlst: ld de,(lstpr) ; see if we can send a character to the lst ld hl,(lstpw) ; get the ring buffer indices or a sbc hl,de ; anything in the buffer scf ; set carry to say we're done ret z ; nope - nothing to do push de ld a,0x2d call cbios ; call to list status pop de ; get read pointer back or a ret z ; can't write - return now ld hl,lstbuf add hl,de ; index into buffer inc de res 2,d ; wrap if over 1K ld (lstpr),de ; save new index ld c,(hl) .extern lstout lstout: ld a,0x0f call cbios or a ; clear the carry ret .extern ctlq ctlq: ld a,(lxoff) ; get local xon / xoff status or a ret z ; send nothing if xoff sent from keyboard ld a,(cqchr) .extern modopc modopc: push af ; save character on stack modopl: call modost ; check if we can send jr z,modopl ; can't send - loop back pop af ; char back to a jp modout ; and away it goes .extern limitb limitb: ; like limitc, but includes backspace cp '\b' ret z .extern limitc limitc: cp 0x7f ; del or greater ccf ret c ; are invalid .extern iswa iswa: cp ' ' ; space to '~' ret nc ; are valid cp '\r' ret z ; return is valid cp '\n' ret z ; newline also cp '\t' ret z ; and tab scf ; rest are bad ret .var #where 0 .var #bot 1 .var #top 2 .var #col 6 .var #row 7 .var #lff 8 nocndo: call ilprt ; and finish the message db '\r\nW ignored - insufficient terminal capabilities\r\n\0' ret wend: ld hl,23 << 8 jp moveto .extern witog witog: ld a,(tcbits) ; check what terminal abilities we have cpl and b_delln | b_insln ld (wtflag),a ; save window type value jr z,cando ; got insert and delete - away we go ld a,(tcbits) and b_cleol ; alternatively check for clear to end-of-line jr z,nocndo ; missing it as well - can't do this cando: ld hl,wflg call togflg ; toggle the flag first of all jr z,wend ; disabled - so return & do nothing dec (hl) ; temporarily turn mode back off so prompt push hl ; works right call prompt db 'Window size (b / s)? \0' pop hl inc (hl) ; turn flag back on ld hl,ipbuf call byp or 0x20 xor 's' ; did they say 's'? ; we could probably optimise this even more, only two numbers actually change ld hl,sdat ; get small window data jr z,gotdat ; jump if so ld hl,bdat ; otherwise large window data gotdat: ld de,wrdat ld bc,6 ldir ; go install it ld h,d ld l,e inc de ld c,5 ld (hl),b ; clear the rest of the information ldir ld a,(wtflag) or a ; what sort of windowing jr nz,setrol ; rolling w/ clear to eol ld hl,(rbot) ; normal - get bottom row ld a,(sbot) ; and the other jr wsetsc ; and install them setrol: ld hl,(rtop) ; get top row ld a,(stop) ; and the other wsetsc: ld (srow),a ; save send window current row ld a,l ld (rrow),a ; and receive window ld (where),a ; and set where so we'll do a moveto call clear ld hl,(rtop - 1) ; get top of receive window dec h ; - 1 to move up a line ld l,0 ; and the first positon call moveto ; go there call dim ; dim mode ld bc,[80 << 8] + '-' dashes: push bc call scrout ; spit out 80 dashes pop bc djnz dashes jp bright ; set bright mode and we're done istab: ld c,' ' call opwc ld a,(iy + #col) and 7 jr nz,istab ret trybs: cp '\b' jr nz,trytab ld a,(iy + #col) or a ret z dec (iy + #col) call opbs ld c,' ' call scrout opbs: ld c,'\b' jp scrout trytab: cp '\t' jr z,istab nobs: cp '~' + 1 ret nc cp ' ' ret c opwc: push hl call scrout pop hl ld (iy + #lff),0 inc (iy + #col) ld a,(iy + #col) xor 80 jr z,scrl ret .extern winrec winrec: ld iy,wrdat jr winpc winsnd: ld iy,wsdat ld c,a winpc: ld hl,where ld a,(iy + #where) cp (hl) jr z,posok ld (hl),a push hl push bc ld l,(iy + #col) ld h,(iy + #row) call moveto pop bc pop hl posok: ld a,c cp '\n' jr z,scrl cp '\r' jr nz,trybs scrl: xor a cp (iy + #lff) ret nz ld (iy + #col),a ld (hl),h ld (iy + #lff),h ld a,(wtflag) or a jr nz,roll ld a,(iy + #top) ld h,(iy + #bot) ld l,22 ; rollit - scroll a region on the screen - this is made external so the VT100 ; code can get at it .extern rollit rollit: or a push hl jr nz,dell ld hl,23 << 8 call moveto ld c,'\n' call scrout jr dontop dell: ld l,0 ld h,a call moveto call dellin dontop: pop hl ld a,h cp l ret z ld l,0 call moveto jp inslin roll: ld a,(iy + #row) call incrow ld (iy + #row),a call incrow ld h,a ld l,0 call moveto jp cleol incrow: cp (iy + #bot) jr z,reload inc a ret reload: ld a,(iy + #top) ret .dseg .extern pccs pccs: db 0 ringpr: dw 0 ringpw: dw 0 lstpr: dw 0 lstpw: dw 0 .useg ring: ds 1024 lstbuf: ds 1024 wrdat: rwhere: ds 1 rbot: ds 1 rtop: ds 1 wsdat: swhere: ds 1 sbot: ds 1 stop: ds 1 rcol: ds 1 rrow: ds 1 rlff: ds 1 scol: ds 1 srow: ds 1 slff: ds 1 .extern where where: ds 1 wtflag: ds 1 .dseg sdat: db 0,22,12 db 1,10,0 bdat: db 0,22,5 db 1,3,0