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); } }