[comp.lang.c] Ah, so THAT'S how you trap a single keystroke in VMS C!

andersen@vaxr.llnl.gov (07/28/90)

Hey, Gang --

I asked how to trap a single keystroke in VMS C earlier this week.  I've since
been told that this is really not the proper forum for such a question, since
it is more a VMS question than a C one.  But I've had a few e-mail messages
asking me to post whatever solutions I received, so at the risk of your 
disapproval, here is a program that combines the two general types of 
solutions that were sent to me.

The SMG way is dead-simple to code, and was sent to me by Robert J. Drabek from
Arizona.  The QIO way was sent to me by Russ Evans and Phil Wild from the
British Geological Survery, and is less obvious; but once it works, it works
well.

The difference is that the QIO way will buffer up extra keystrokes (if,
for example, you hit an arrow key, it will trap the entire escape sequence
one character at a time).  It also allows for timeouts (though the SMG way
might as well -- I didn't explore it.)

This program demonstrates both methods, but it is not crash-proofed or dolled
up very much, and if it's bad or wrong or ugly, it's because I screwed up 
Robert's and Russ' and Phil's examples.

So, thanks to all of you who responded with you solutions and ideas.  I'll
try to make my next question (if any) more C-specific.

-- Roger Andersen
	LLNL


		----------------- CUT HERE -------------------------
/*  ======================================================================  */
/*  File:	    keytraps.c						    */
/*  Author:	    Roger W. Andersen					    */
/*		    Laser Controls Group    L-572	2-2176		    */
/*  Abstract:								    */
/*	This program demonstrates two methods of trapping a single	    */
/*	keystroke in VMS C.  The two solutions were suggested by many folks */
/*	in USENETs alt.lang.c, and complete working examples came from:	    */
/*									    */
/*	QIO type:   Russ Evans and Phil Wild				    */
/*		    British Geological Survey - Seismology Reseach Group    */
/*		    							    */
/*	SMG type:   Robert J. Drabek -- somewhere in Arizona		    */
/*									    */
/*									    */
/*	Both methods still allow ^Y and ^C to kill the process.		    */
/*									    */
/*	This is just a combiantion  of their code, and if it is wrong or    */
/*	ugly it is simply because I mucked it up.			    */
/*									    */
/*	So there.							    */
/*									    */
/*									    */
/*  Modification History:						    */
/*  ==================================================================	    */
/*  Date	Author	    Modification				    */
/*  ==================================================================	    */
/*  07-27-90	RWA	    Initial key-in				    */
/*									    */
/*  ======================================================================  */

#include <stdio.h>
#define then


/*  ======================================================================  */
/* for the SMG method: */
static unsigned int kb;


/*  ======================================================================  */
/* for the QIO method: */
#include <iodef>
#include <ssdef>
#include <descrip>

static int  qioch_in = 0;
static int  stat_in;
static int  IO_function =
    IO$_READVBLK | IO$M_NOECHO | IO$M_TRMNOECHO | IO$M_NOFILTR;
static int  delay = 0;


$DESCRIPTOR (input_stream, "SYS$INPUT");

typedef struct {
	short 	cond_code;
	short 	count;
	int     info;
	} io_status_block;

typedef struct {
	int	type;
	int	mask;
	} io_mask;





/* =======================================================================  */
/* PREP_SMG_KEYTRAPPER							    */
/* =======================================================================  */
void prep_SMG_keytrapper( )
{
  smg$create_virtual_keyboard(&kb);
}





/* =======================================================================  */
/* PREP_QIO_KEYTRAPPER							    */
/* =======================================================================  */
void prep_QIO_keytrapper( )
{
int	answer;

    if (qioch_in == 0) { 
	if ((stat_in = SYS$ASSIGN(&input_stream, 
				  &qioch_in, 
				  0, 
				  0)) 	
			!= SS$_NORMAL) {
		printf("Can't open connection\n");
		LIB$STOP(stat_in);
		}
	}

    printf("Enter (0) for normal trap, (1) for timeout : ");
    scanf("%d", &answer );
    if ( answer ) then
    {
	IO_function |= IO$M_TIMED;
	printf("Enter timeout value in seconds: " );
	scanf("%d", &delay );
    }
}





/* =======================================================================  */
/* TRAP_KEYSTROKE_USING_SMG						    */
/* =======================================================================  */
static int trap_keystroke_using_SMG( )
{
  short key;

  smg$read_keystroke(&kb, &key);
  return (int)key;
}


/* =======================================================================  */
/* TRAP_KEYSTROKE_USING_QIO						    */
/*	 Remove comments to make this wait 1 second, then return -1 if	    */
/*	 no keystroke detected.						    */
/* =======================================================================  */
int trap_keystroke_using_QIO( )
{
    char		c;
    io_mask		mask = {0, 0};
    io_status_block	iosb;

    if ((stat_in = SYS$QIOW(0,
			    qioch_in,
			    IO_function,
			    &iosb,
			    0,
			    0,
			    &c,
			    1,
			    delay,
			    &mask,
			    0,
			    0))	
		    != SS$_NORMAL) {
	    LIB$SIGNAL(stat_in);
	    }

        return (  (iosb.count == 0) ? -1 : (int)c);
}	

/* =======================================================================  */
/* =======================================================================  */
main( )
{
int	ch;
int	which;

    printf("Which method do you want to use? (0 = SMG, 1 = QIO) : ");
    scanf("%d", &which );
    
    if ( which )
	then prep_QIO_keytrapper( );
	else prep_SMG_keytrapper( );

    while ( 1 )
    {
	printf("Hit key to be trapped : ");

	if ( which )
	    then ch = trap_keystroke_using_QIO( );
	    else ch = trap_keystroke_using_SMG( );

	printf("Key is <%c>; its ASCII value is <%d>\n", ch, ch);
    }	
}