.enabl lsb .title ttin Terminal input .ident "V02.00" ;+ ; Index Terminal input ; ; Usage ; ; length = ttise(buffer, size); ; int length; /* Number of bytes read */ ; char *buffer; /* Address of input buffer */ ; int size; /* size of input buffer */ ; ; ; length = ttisne(buffer, size); ; int length; /* Number of bytes read */ ; char *buffer; /* Address of input buffer */ ; int size; /* size of input buffer */ ; ; ; extern char ttice(); ; ch = ttice(); ; char ch; /* returned character */ ; ; ; extern char tticne(); ; ch = tticne(); ; char ch; /* returned character */ ; ; ; Description ; ; ttise() reads a maximum of "size" characters into "buffer" ; echoing them on the terminal, and appends a null (see the ; NOTE below!) to the end of the just read string. ; ; ttisne() reads a maximum of "size" characters into "buffer" ; without echoing them on the terminal, and appends a null ; (see the NOTE below!) to the end of the just read string. ; ; Both ttise() and ttisne() return the number of characters ; read (excluding the terminator such as ) or 0 if ; there was an error. ; ; NOTE: The string in the buffer is null terminated, so be ; sure there is room for the null ( i.e. the actual size of ; the buffer must be at least 1 byte larger than the size ; passed to the routine). If the string read completes because ; the buffer filled (as far as the QIO was concerned), there ; MUST be room for the terminating null! ; ; ttice() reads one character echoing it on on the terminal. ; The actual character read is returned with the hi byte ; cleared, or a 0 is returned if there was an error. ; ; tticne() reads one character without echoing it on the terminal. ; The actual character read is returned with the hi byte ; cleared, or a 0 is returned if there was an error. ; ; The ttice() and tticne() routines do NOT clear bit 7 (usually ; the parity bit). ; ; The single character input routines ttice() and tticne() ; use the IO.RAL function, so that any 8-bit character may be ; read without trapping and interpretation by the terminal ; driver. The exceptions to this are ^S and ^Q, which ; are trapped by the ttic(n)e() routine(s) and used to manually ; synchronize the terminal driver. ; ; It is possible to get into a lockup or overrun condition with ; terminals which automatically generate ^S and ^Q to ; synchronize with the host computer when using the IO.RAL, ; since both of these characters are passed to the program. ; ; For instance, suppose the program sends something which ; causes the terminal to send back a ^S, and then posts an ; IO.RAL. If the ^S arrives before the RAL gets queued to ; the terminal driver, the ^S will cause terminal output to ; be suspended, since the terminal driver has no reason to ; do anything special with the ^S. Now the RAL arrives and ; shortly thereafter the terminal sends a ^Q, expecting ; terminal output to be resumed. But instead, the terminal ; driver faithfully passes the ^Q to the program. Meanwhile, ; the terminal driver still has output suspended, and the ; terminal is never going to generate another ^Q on it's own. ; The terminal will appear to have mysteriously locked up. ; ; This and other scenarios make it wise to trap ^S and ^Q ; within the CS library character input routines and issue ; the appropriate SF.SMC function to suspend or resume terminal ; output. The effect is to make the IO.RAL look like "read pass ; almost all" (except for ^S and ^Q). After processing the ; ^S or ^Q, the routine issues another read without returning ; to the caller. ; ;- ; Edit History ; V02.00 19-Oct-82 TTC Rework of CS library ; .psect c$data ch.spn: .byte TC.CTS,1 ; SF.SMC char to suspend TIO ch.rsm: .byte TC.CTS,0 ; SF.SMC char to resume TIO char: .byte 0 ; Character buffer .even .psect c$code ttice:: mov #IO.RAL,ttqio+q.iofn ; Function: IO.RAL mov #ttice,-(sp) ; Remember for ^S/^Q code br readch ; Branch to common char read code ttise:: mov #IO.RLB,ttqio+q.iofn ; Function: IO.RLB clr -(sp) ; Fake for consistency br readst ; Branch to common string read code tticne:: mov #IO.RAL!TF.RNE,ttqio+q.iofn ; Function: IO.RAL mov #tticne,-(sp) ; Remember for ^S/^Q code br readch ; Branch to common char read code ttisne:: mov #IO.RLB!TF.RNE,ttqio+q.iofn ; Function: IO.RLB clr -(sp) ; Fake for consistency ; ; Falls through to common string read code ; readst: ; Common string read code mov #ttqio+q.iopl,r0 ; r0 --> qio param list for prmclr call prmclr ; Clear qiow parameters mov 4(sp),ttqio+q.iopl ; Parameter #1: Buffer addr. mov 6(sp),ttqio+q.iopl+2 ; Parameter #2: Buffer size br common ; Branch to common read code readch: ; Common character read code mov #ttqio+q.iopl,r0 ; r0 --> qio param list for prmclr call prmclr ; Clear qiow parameters mov #char,ttqio+q.iopl ; Parameter #1: Character buffer mov #1,ttqio+q.iopl+2 ; Parameter #2: Buffer size (1) ; ; Falls through to common read code ; common: ; Common read code mov #ttqio,r0 ; Put qio address in r0 for .xqiow call .xqiow ; Execute qiow cmp $dsw,#is.suc ; How'd things go? bne 20$ ; Bad cmpb t.iosb,#is.suc bne 20$ mov ttqio+q.iopl,r1 ; r1 --> char or string buffer cmp #char,r1 ; Character read? beq 10$ ; (Yes) mov t.iosb+2,r0 ; (No), r0 = # of bytes read add r0,r1 ; r1 --> end of string clrb (r1) ; Tag on NULL br 25$ ; Return 10$: cmpb char,#21 ; ^Q ? beq rsum ; (yes, resume terminal output) cmpb char,#23 ; ^S ? beq spnd ; (yes, suspend terminal output) clr r0 ; Copy character without sign extend bisb char,r0 ; (the efficient way) br 25$ ; Return 20$: clr r0 ; Error, r0 = 0 25$: tst (sp)+ ; Clean off the stack return ; Retrun rsum: mov #ch.rsm,r1 ; Resume terminal output br smc spnd: mov #ch.spn,r1 smc: mov #ttqio+q.iopl,r0 ; r0 --> qio param list for prmclr call prmclr ; Clear qiow parameters mov r1,ttqio+q.iopl ; Buffer addr = characteristic pair mov #2,ttqio+q.iopl+2 ; Buffer size = 2 bytes mov #SF.SMC,ttqio+q.iofn ; Function: SF.SMC mov #ttqio,r0 ; Put qio address in r0 for .xqiow call .xqiow ; Execute qiow (tough if fails) jmp @(sp)+ ; Jump back for another try .end