cameron@runx.ips.oz (James Cameron) (05/04/88)
I have a program which allows users to control their local printer queue. It uses the SMG$ Run-Time Library routines for screen control, the $GETQUI system service for obtaining the queue contents, and the $SNDJBC system service for controlling the queue (and jobs). Commands are typed as single keystrokes - S to stop the queue, G to go, etc. There is a VAX MACRO routine that issues the $QIO to read a single character from SYS$INPUT. The $QIO call specifies an AST routine that will handle the character (it does the $SNDJBC according to what was typed). The AST routine requeues the $QIO so as to catch the next character. This is the $QIO used to read the first and next character; $QIO_S chan=channel, func=#io$_readvblk!io$m_noecho, - iosb=iosb, astadr=vq_command_ast, astprm=#buffer, - p1=buffer, p2=#1 ; one character length There's the background - the problem is the PF4 key. It causes the AST routine to be called once for each character of the se- quence <ESC>OS, which causes the queue to be stopped, since nei- ther <ESC> nor O are valid commands. The PF4 key is used in most of our systems as a get-out key. Users are accidently stopping their queues. I've tried adding the function modifier IO$M_ESCAPE to the $QIO, but that simply causes a %SYSTEM-F, Partial Escape status in the IOSB. I've tried enlarging the buffer so that the escape se- quence can fit into it, but that causes the I/O to wait until the buffer is filled before declaring the I/O complete (have to type SSSS or S followed by RETURN). I know I could probably kludge it so that the AST routine would parse the escape sequence - but I'd rather do it some other way. I thought that I could use an unsolicited data mailbox. When the program receives the unsolicited data message, it would issue the $QIO to the terminal with a timeout value of zero, thus catching either a single character that the user typed or the escape se- quence. But I have a worry about that - if the terminal line is low speed, or a multiplexor causes the subsequent characters of an escape sequence to arrive a bit later, will this cause the I/O to only pick up the first few characters of the sequence? Does a read with timeout of zero only read the type-ahead buffer? Or does it wait to see an entire escape sequence if it has noticed an escape character? I would appreciate any comments or help. Please reply by MAIL. I may eventually summarise the response. James Cameron, Kilpatrick Green Pty. Ltd., P.O. Box N366, Sydney 2000 Australia Internet: cameron@runx.ips.oz.au UUCP: uunet!runx.ips.oz.au!cameron
u3369429@ucsvc.unimelb.edu.au (Michael Bednarek) (05/09/88)
In article <1501@runx.ips.oz>, cameron@runx.ips.oz (James Cameron) writes: > > I have a program which allows users to control their local > printer queue. It uses the SMG$ Run-Time Library routines for > screen control, the $GETQUI system service for obtaining the > queue contents, and the $SNDJBC system service for controlling > the queue (and jobs). > > Commands are typed as single keystrokes - S to stop the queue, G > to go, etc. There is a VAX MACRO routine that issues the $QIO to > read a single character from SYS$INPUT. [...] The best thing would probably be to use SMG$ to read the keyboard. Using only QIOs, here are three small Fortran programs. o Sense_Type_Ahead ! Sense Type-Ahead-Buffer o Inkey0 ! Read one character without echo from SYS$COMMAND ! with a time-out value of zero o TInkey0 ! Demonstrate usage of `Sense_Type_Ahead' and `Inkey0' -- Michael Bednarek, Institute of Applied Economic and Social Research (IAESR) // Melbourne University,Parkville 3052, AUSTRALIA, Phone:+61 3 344 5744 \X/ Domain:u3369429@{murdu.oz.au | ucsvc.dn.mu.oz.au} | mb@munnari.oz.au "bang":...UUNET!munnari!murdu!u3369429 PSI%23343000301::U3369429 "POST NO BILLS." >>> Options /Extend_Source Integer Function Sense_Type_Ahead(First) Implicit NONE C** Sense Type-Ahead-Buffer from SYS$COMMAND Michael Bednarek Integer Status,Func,Channel,SYS$Assign,SYS$QIOW,SYS$DASSGN Character First Include '($IODEF)/List' Parameter (Func=IO$_SenseMode.or.IO$M_TypeAhdCnt) Structure /Sense_Mode_Buffer/ Integer*2 Number Character First Byte %FILL(5) End Structure Record /Sense_Mode_Buffer/ P1 C** assign a channel to the terminal Status=SYS$Assign('SYS$COMMAND',Channel,,) If (.not.Status) Call LIB$Signal(%VAL(Status)) C** Sense Type-Ahead-Buffer Status=SYS$QIOW(,%VAL(Channel), 1 %VAL(Func),,,, 1 P1,%VAL(8),,,,) If (.not.Status) Call LIB$Signal(%VAL(Status)) Sense_Type_Ahead=P1.Number First=P1.First c** deassign the i/o channel Status=SYS$DASSGN(%VAL(Channel)) If (.not.Status) Call LIB$Signal(%VAL(Status)) Return End >>> Options /Extend_Source Integer Function INKEY0 (c) C** Read one character without echo from SYS$COMMAND Michael Bednarek C with a time-out value of zero C Usage: Status=INKEY0(c) C Returns character in `c', and QIOW's Status. If no character was read, C Status is set to zero and `c' remains unchanged. C Note: If function or arrow keys are pressed, each character of the C transmitted code is returned in successive calls. C E.g. pressing UP-ARROW will send the three characters `<ESC>[A'. Implicit NONE Integer Func,Status,Channel,SYS$Assign,SYS$QIOW,SYS$DASSGN Character c Include '($SSDEF)/List' Include '($IODEF)/List' Parameter (Func=IO$_READVBLK.or.IO$M_NOECHO 1 .or.IO$M_NOFILTR.or.IO$M_TIMED) Structure /IOSB/ Integer*2 Value Integer*2 Count Integer*4 Dev_Spec End Structure Record /IOSB/ IOSB C** assign a channel to the terminal Status=SYS$Assign('SYS$COMMAND',Channel,,) If (.not.Status) Call LIB$Signal(%VAL(Status)) C** read 1 character Status=SYS$QIOW(,%VAL(Channel),%VAL(Func),IOSB,,, 2 %REF(c),%VAL(1),%VAL(0),,,) If (.not.Status) Call LIB$Signal(%VAL(Status)) If (IOSB.Value.eq.SS$_TIMEOUT) then INKEY0=0 else INKEY0=Status End If c** deassign the i/o channel Status=SYS$DASSGN(%VAL(Channel)) If (.not.Status) Call LIB$Signal(%VAL(Status)) Return End >>> Options /Extend_Source Program TInkey0 ! Demonstrate usage of `Sense_Type_Ahead' and 'Inkey0': Implicit Integer (A-z) Character c Do while (1) l=Sense_Type_Ahead(c) If (l.gt.0) then Write (*,*) 'Sensed',l,' characters. First: >',c,'<',ICHAR(c) Do i=1,l Status=Inkey0(c) If (Status.ne.0) Write (*,*) 'INKEY0 returns >',c,'<',ICHAR(c) End Do End If End Do End
rrk@byuvax.bitnet (05/10/88)
An easy solution to your problem was included in a recent (somewhere between 4.0 and 4.4) revision of the operating system. I don't remember the exact names of the codes. Please refer to your I/O reference manual. This much I do remember. You have to revise the form of your terminal QIO to use the terminal QIO extended itemlist. You can do this without changing the basic way your QIO works--it is just a different way of passing parameters because they ran out of parameter/qualifier space in the $QIO with only six parameters. Anyway, there is a code you can include to reserve N characters of the buffer for receiving the rest of an escape sequence. If you specify a buffer size of 20 and an escape overflow of 19, this will cause any keystroke from the terminal to terminate the I/O, but if the key generated an escape sequence, the entire sequence (up to 20 characters including the escape) will be placed in your buffer. I hope this helps. AMMON::RAY