Path: utzoo!mnetor!uunet!munnari!murdu!ucsvc!u3369429
From: u3369429@ucsvc.unimelb.edu.au (Michael Bednarek)
Newsgroups: comp.os.vms
Subject: Re: Reading single keystrokes - how do I cope with PF keys?
Message-ID: <242@ucsvc.unimelb.edu.au>
Date: 9 May 88 13:53:37 GMT
References: <1501@runx.ips.oz>
Organization: I.A.E.S.R., Melbourne University
Lines: 136

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 `[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