1
0
Files
qterm/source/ODDS.Z
T
2020-10-05 14:03:34 +02:00

658 lines
14 KiB
Plaintext

; odds.z - code that has no place else to live
.incl "c:termcap"
.incl "c:vars"
.var slow 86 ; should we slow down outgoing string
.extern prompt ; print an inline prompt then get a buffer
prompt: ; full of data from the keyboard
ld a,(prmpfl) ; see if we're in a chat script or not
or a
jr z,nochat ; no - do normal input
push ix
pop hl ; get string address to hl
ld de,ipbuf
ld bc,116 ; reasonable amount to copy
ldir ; move it over, and we're done
skipze: pop hl ; get string address - we have to skip over it
skiplp: inc hl ; this relies on a non-empty string
ld a,(hl)
or a
jr nz,skiplp ; skip till we reach the end
jp (hl) ; and return to address in hl
nochat: call dim ; set dim mode
ld hl,crlfms
call prtslp ; send a newline
pop hl
call prtslp ; print the prompt
push hl
ld de,ipbuf - 2 ; point at where we'll read info
ld a,e
ld (de),a ; set count
ld c,buffin
call bdos ; read a line
ld hl,ipbuf - 1
ld e,(hl) ; get count actually input
ld d,h
add hl,de
inc hl ; turn into a buffer pointer
ld (hl),d ; and zero terminate input data
.extern crlf ; just print a newline
crlf:
call ilprt
crlfms: db '\r\n'
zero: db 0
ret
.extern ilprt
ilprt: call dim ; in line print - start by going dim
pop hl ; get string address
call prtslp ; out it goes
push hl ; restore return address - fall into bright
.extern bright
bright: ld a,(tcbits)
and b_brite ; do we have a bright string?
ret z
ld hl,bflag ; currently bright?
ld a,(hl)
dec a
ret nz ; yes, don't resend
ld (hl),a
ld hl,brites ; get address of bright string
jr prtslx ; and send it
.extern dim
dim: ld a,(tcbits)
and b_dim ; do we have a dim string?
ret z
ld hl,bflag ; currently dim?
ld a,(hl)
or a
ret nz ; yes, don't resend
inc (hl)
ld hl,dims ; get address of dim string
jr prtslx
.extern dellin
dellin:
ld hl,dlstr ; get address of dellin string
jr prtslx ; and send it
.extern inslin
inslin:
ld hl,ilstr ; get address of inslin string
jr prtslx ; and send it
.extern cleol
cleol:
ld hl,ceol ; get address of cleol string
jr prtslx ; and send it
.extern cleos
cleos:
ld hl,ceos ; get address of cleos string
jr prtslx ; and send it
.extern clear
clear: ld hl,clrs ; get address of clear string
prtslx: ld a,h
ld (optype),a
call prtslp
xor a
ld (optype),a
ret
.extern prtslp
prtslp:
call clrpcp
.extern prtsl1
prtsl1:
ld a,(hl)
or a
ret z
inc hl
push hl
call tabexp
pop hl
; for ^X to can a long directory, add a 'ret c' here
jr prtsl1
.extern tabexp
tabexp:
cp '\n'
jr nz,nonl
ld a,79
ld (pos),a
ld a,'\n'
nonl: cp '\r'
jr nz,nocr
ld a,0xff
ld (pos),a
ld a,'\r'
nocr: cp '\t'
jr z,tablp
call prtopc
jr chk80
tablp: ld a,' '
call prtopc
ld a,(pos)
and 7
jr nz,tablp
chk80: ld hl,pos
ld a,(hl)
xor 80
call z,newlin
ret
prtopc: ld c,a
ld a,(optype)
or a
ld a,c
jp nz,scrout
ld hl,mode
ld e,(hl)
push hl
push de
ld (hl),lf_bit
call opchar
pop de
pop hl
ld (hl),e
ld hl,pos
inc (hl)
ret
newlin: ld (hl),a ; set char count back to zero
inc hl ; point at line count
inc (hl) ; bump that too
ld a,(hl)
xor 23 ; 23 lines?
ret nz ; return if not
ld a,(pagerf)
or a
ret z ; and return if not paging
dec (hl) ; set back to 22 in case we get a return
ld hl,mmsg
.dseg
mmsg: db '[more]\0'
.cseg
call prtsl1 ; print more message
call kbdin ; get a character
ld hl,cmstr
.dseg
cmstr: db '\r \r\0'
.cseg
cp (hl) ; return?
jr z,clrmor ; yes - just remove '[more]', linec is set
xor 'x' & 0x1f
jr z,retcx ; special exit on a ^X
xor a
ld (linec),a ; else clear linc for a full page
clrmor: jp prtsl1 ; and remove the more message
retcx: call prtsl1 ; come here after a ^X - we remove the message
scf ; and return carry to flag the exit
ret
.extern clrpsp
clrpsp:
db 0x3e ; makes a ld a,xx
.extern clrpcp
clrpcp:
xor a
ld (pagerf),a
push hl
ld hl,0
ld (pos),hl
pop hl
ret
.extern mtprt ; a call to this is followed by inline coords.
mtprt: ; and a string to be printed at the coords
pop hl
ld e,(hl)
inc hl
ld d,(hl) ; get moveto coordinates
inc hl
push hl ; save address of string
ex de,hl ; coords to hl
call moveto ; move to wherever
pop hl ; restore string to hl
call prtslp ; print it
jp (hl) ; and return
.extern decob ; print number in l, by zeroing h
decob:
ld h,0 ; clear h and fall through
.extern decout ; print number in hl in decimal
decout:
push de ; save running total
push bc ; save char count
ld bc,-10
ld de,-1
decou2: add hl,bc
inc de
jr c,decou2 ; divide hl by 10
sbc hl,bc ; reset because of overflow
ex de,hl ; remainder to e, answer to hl
ld a,h
or l
pop bc ; restore char count for next call
call nz,decout ; answer non-zero: print recursively
ld a,e ; get remainder
add a,'0'
ld c,a
push bc
call scrout ; print to screen as a digit
pop bc
dec b ; keep count of printed chars in b
pop de ; restore total
ret
.extern break
break:
call tenth ; wait a while before beginning
call sbreak ; start the break
call tenth3 ; idle for 3/10 of a second
jp ebreak ; finish off by ending the break
.extern hangup
hangup:
ld hl,#dtroff
ld a,(hl)
cp 0xc9 ; return at dtroff => no code
jr z,strhup ; so send a string instead
call dtroff ; drop dtr - should make modem hang up
call tenth3
call tenth3 ; wait a (long) while
jp dtron ; dtr back on
strhup: ld ix,hangup - slow
inc hl
ld b,(hl) ; get the string length
inc hl
jp sendcs ; and out it goes
tenth3: call tenth
call tenth
.extern tenth ; delay for 1/10 of a second, but continue to
tenth: ; save incoming chars
ld de,100
call setspd ; get speed constant to hl
tnthlp: ld b,60
tnthl1: djnz tnthl1 ; idle a while
push hl
call savrng ; check incoming chars, but only as far as
pop hl ; the ring buffer
dec hl ; count main timer
ld a,h
or l
jr nz,tnthlp
ret
.extern tnthip ; delay for 1/10 of a second, but continue to
tnthip: ; check the modem for incoming chars
ld de,100
.extern msip ; delay for de msec, but continue to
msip: ; check the modem for incoming chars
ld a,d
or e ; anything in de?
ret z ; nope - return right now
call setspd ; get speed constant to hl
msil: ld b,60
msl2: djnz msl2 ; idle a while
push hl
call lstmod ; process incoming chars and printer output
pop hl
dec hl ; count main timer
ld a,h
or l
jr nz,msil
ret
.extern setspd ; take 1MHz value in de, get correct value in
setspd: ; hl based on cpu speed
ld hl,0
ld a,(speed)
ld b,a ; get cpu speed to b
spdok: add hl,de ; multiply de by b
djnz spdok
ret
.extern help
help:
call crlf ; start off with a new line
call dim ; and dim
call presc ; print the escape character
or a ; test the flag
ld c,' '
call z,scrout ; print a space if no '^'
call ilprt ; and finish off
db ' - Transmit escape character\t '
db '? - Print this help\r\n'
db '. - Send a break\t\t\t'
db ', - Hang up modem\r\n'
db 'B - Change baud rate and mode\t\t'
db 'C - Open an input catch file\r\n'
db 'D - Display local directory\t\t'
db 'E - Toggle remote echo\r\n'
db 'H - Toggle half duplex\t\t'
db 'I - Print settings information\r\n'
db 'J - Junk control characters\t\t'
db 'K - Load a function key\r\n'
db 'L - Toggle linefeed transmit for \'P\'\t'
db 'M - Toggle bit 7 mask\r\n'
db 'N - Select new default drive / user\t'
db 'O - Toggle output to printer\r\n'
db 'P - Print a file to remote\t\t'
db 'Q - Quit\r\n'
db 'R - Receive a file using protocol\t'
db 'S - Send a file using protocol\r\n'
db 'T - Type a local file\t\t\t'
db 'U - Invoke user function\r\n'
db 'V - Toggle VT100 Emulation\t\t'
db 'W - Toggle split window mode\r\n'
db 'X - Activate a chat script\t\t'
db 'Y - Put catch file on hold\r\n'
db 'Z - Close catch file\t\t\t'
db '0-9 - Send function key string\r\n'
db 0
ret
.extern info ; print current settings
info:
call ilprt
db '\r\nEscape character:\t\0'
call dim
call presc ; print the escape character
call ilprt
db '\r\nCurrent drive / user:\t\0'
call dim
ld hl,(curusr) ; get the current drive & user
ld a,h
add a,'A' ; convert drive to a letter
ld c,a
push hl
call scrout ; print the drive
pop hl
call decob ; and print the user in l
call ilprt
db ':\r\n\0'
ld a,(rate)
cp ' '
jr z,norate
call ilprt
db 'Baud rate:\t\t\0'
call dim
ld hl,rate
call prtslp
norate: ld a,(modsav)
cp ' '
jr z,nomode
call ilprt
db 'Communication Mode:\t\0'
call dim
ld hl,modsav
call prtslp
nomode: call ilprt
db '^S delay:\t\t\0'
call dim
ld hl,(csdely) ; get the delay count
call decob ; out it goes
call ilprt
db ' second(s)\r\nHalf duplex:\t\t\0'
ld a,(hflg)
call onoff ; say whether HDX is on or off
call ilprt
db 'Local echo:\t\t\0'
ld a,(eflg)
call onoff ; say what local echo is up to
call ilprt
db 'Control char. discard:\t\0'
ld a,(jflg)
call onoff ; say what local echo is up to
call ilprt
db 'Linefeed in \'P\':\t\0'
ld a,(lflg)
call onoff ; line feed in print
call ilprt
db 'Character delay:\t\0'
call dim
ld hl,(chd) ; get the character delay
call decob ; out it goes
call ilprt
db ' msec. \0'
ld a,(ecflg)
or a
jr z,noeci
call ilprt
db '\techo check\0'
noeci: call ilprt
db '\r\nNew line delay:\t\t\0'
call dim
ld hl,(nld) ; new line delay is a word
call decout
call ilprt
db ' msec. \0'
ld a,(lfecho)
or a
jr z,nolfe
push af
call ilprt
db '\tnewline echo: \'\0'
call dim
pop af
ld c,a
call scrout
ld c,'\''
call scrout
nolfe: call ilprt
db '\r\nBit 7 masking:\t\t\0'
ld a,(bmask)
inc a
call onoff ; say what bit 7 masking is up to
call ilprt
db 'VT100 emulation:\t\0'
ld a,(vflg)
call onoff ; and vt100 emulation
call ilprt
db 'Printer output:\t\t\0'
ld a,(oflg)
call onoff ; and printer output
ld a,(cflg)
or a
jr nz,isctch ; catch file active?
call ilprt ; if not then say so
db 'Not catching\r\n\0'
ret
isctch: call ilprt
db 'Current catch file:\t\0'
call dim
ld hl,cfcb
call prtfl ; otherwise print the filename
ld a,(cflg)
dec a
jp z,crlf ; if active we're done
call ilprt ; else say it's on hold
db ' (on hold)\r\n\0'
ret
onoff: or a ; is the flag active
jr z,proff ; jump if not
call ilprt
db 'on\r\n\0' ; say it's on
ret
proff: call ilprt
db 'off\r\n\0' ; or say it's off
ret
.extern presc
presc:
ld b,0
ld a,(escval) ; get the escape character
cp ' '
jr c,prthat ; it's a control char - print the ^
cp 0x7f
jr nz,nohat ; also do that for deletes
prthat: ld c,'^'
push af ; save the escape val
call scrout ; print the ^
pop af
ld b,64 ; flag we printed the ^
xor b ; and "uncontrollify" the char
nohat: ld c,a
push bc ; save flag
call scrout ; print the char
pop af ; flag back to a
ret
.extern quit
quit:
call cclose ; close catch file if open
ld hl,23 * 256 ; blh corner of screen
call moveto ; go there
call exit ; call custom unwind code
rst 0 ; exit to cp/m
.extern conin ; get char from function key or keyboard
conin:
ld a,(fkdely) ; check if we need to delay
or a
call nz,tnthip ; idle a while if we do
ld hl,(fkptr)
ld a,(hl) ; get the next char
inc hl
ld (fkptr),hl ; save revised pointer
ret ; char is in a
.extern ctls
ctls:
ld a,(lxoff) ; get local xon / xoff status
or a
ld a,(cschr)
call nz,modopc ; send the xoff if needed
ld a,(csdely)
or a
ret z ; if it's zero, return right now
ld b,a ; get the delay value
add a,a
add a,a
add a,b
add a,a ; * 10
ld b,a ; to b
waitlp: push bc
call tenth ; wait a while
pop bc
djnz waitlp
ret
.extern gotxon ; flag that an xon was sent from the kbd,
gotxon: ; so we don't re-send
ld (lxoff),a ; set the local xoff flag
ret
.extern gotxof ; flag that an xof was sent: this just clears
gotxof: ; the flag set in gotxon
ld hl,lxoff
ld (hl),0
ret
.extern areabp ; areabp used in chat scripts: point at first
areabp: ; non-white in text of a '!' command
ld hl,area - 1 ; point at chat parse area and fall into byp
.extern incbyp
incbyp: ; inc hl, and then byp
inc hl
.extern byp ; step over spaces in string pointed to by hl
byp:
ld a,(hl)
cp ' '
ret nz ; return on the first char that is NOT a space
inc hl
jr byp
.extern ldfnk ; this will prompt and then use the string
ldfnk: ; to program one of the 10 function keys
ld hl,zero ; point the readback pointer at a zero
ld (fkptr),hl ; in case we change the string under it
call prompt
db 'Key value: \0' ; get the string
ld hl,ipbuf
call byp ; strip spaces
or a
ret z ; skip if nothing to do
cp '\e'
ret z ; or if an escape typed
ld c,0 ; clear c (will become slow/fast flag)
sub '0'
cp 10
jr c,fast ; 0-9: is a fast, key index in a
ld c,a ; non-digit: save a non-zero in c
inc hl
ld a,(hl) ; get the next character
sub '0' ; and turn it into an index
fast: cp 10
jr c,fnkok ; check it's ok
call ilprt ; complain and return if not
db 'Invalid function key number\r\n\0'
ret
fnkok: inc hl ; point at string to be parsed
push hl ; save input string address
add a,a
add a,a
add a,a
add a,a ; turn index into table offset
ld e,a
ld d,0 ; goes in de
ld hl,fktbl
add hl,de ; get table entry address
ld (hl),c ; save speed flag
inc hl
ex de,hl ; string target address to de
pop hl ; text back to hl
ld bc,14 << 8 ; 14 chars, zero byte delimits
jp parst ; go parse the string, and we're done
.extern cbios ; call the entry point in the bios witn number
cbios: ; in a, saving ix and iy as we go
push ix
push iy
call #bios
pop iy
pop iy
ret
#bios: ; offset is in a
ld hl,(1) ; get the warm boot value to hl
ld l,a ; modify with function number
jp (hl) ; go do the code
.dseg
optype: db 0
bflag: db 0
.extern lxoff
lxoff: db 1
.extern prmpfl
prmpfl: db 0
.extern fkptr
fkptr: dw zero
.useg
pos: ds 1
linec: ds 1
pagerf: ds 1
.extern fkdely
fkdely: ds 1
.extern fktbl
fktbl: ds 16 * 10