/* Applications Plus ******************************************************************************* PROJECT NAME: GTE OLTS MODULE NAME : one_esc.c DESCRIPTION : This module provides a routine to insert into the keyloop function so that vermont views will work correctly with terminals without requiring that the user press twice to generate the code for an escape key yet still allows the arrow and function keys to work properly. AUTHOR : John K. Harris (214) 541-1771 This computer software was written by Applications Plus, Inc. 122 W. Carpenter Fwy. Suite 535, Lockbox 28 Irving, TX 75039 DATE : 09-05-90 ******************************************************************************* */ #include #include #include /* or - my addition (bc) */ #include #include int one_esc(); /* prototype for internal use as a function pointer */ void Usleep(); /* prototype for internal use as an alarm vector */ int one_esc(counter) int counter; { int rv; /* return value */ int i; /* general purpose variable */ unsigned char c[2]; /* character storage buffer */ int kbsave; /* save for file control flags */ rv=0; /* init. return value to zero */ if(counter == KL_INIT) /* called by ki() before any other */ /* processing */ { kbsave=_kb_flags; /* save vv keyboard (stdin) flags */ _kb_flags &= ~O_NDELAY; /* make sure next read will wait */ if(_kb_flags != kbsave) /* if any changes... */ fcntl(0,F_SETFL,_kb_flags);/* modify the opened stdin stream*/ i=_ki_get(SAVE); /* get 1st char with wait */ *c=(unsigned char)i; if(*c != 27) /* if not an escape... */ { if(_kb_flags != kbsave) /* restore terminal settings... */ { _kb_flags = kbsave;/* restore original stdin setting */ fcntl(0,F_SETFL,_kb_flags); } return(rv); /* and return with what we have so far */ } _pb_buf=0; /* first character was an escape */ Usleep(-20000); /* sleep for 20 milliseconds */ _kb_flags |= O_NDELAY; /* make sure next read will NOT wait */ fcntl(0,F_SETFL,_kb_flags); /* write changed kb flags to stdin */ /****************************************************************/ /* The first read with wait has now completed. Attempt a 2nd */ /* read without wait after the allowed timeout period. If */ /* there is a 2nd character available, then we want to be as */ /* if we never read either the first or second characters. We */ /* do this by pushing back the second into stdin using ungetc. */ /* Then, we place the first one into _pb_buf, which is the */ /* Vermont Views internal pushback buffer (1-byte). The next */ /* byte read from stdin using _ki_get will see the value we */ /* put into _pb_buf. */ /* If there is not a second character, then this was probably a*/ /* single keystroke entry, and */ /* we should use just the first and only key as the single */ /* keycode. We do this by just returning with the value. */ /****************************************************************/ i=getchar(); /* attempt to get 2nd char (no wait) */ c[1]=(unsigned char) i; /* cast to character */ if (i==EOF) /* if nothing after timeout... */ rv=c[0]; /* return the one and only character */ else /* second one received */ { if(c[0] == c[1] && c[0] == 27) /* BOTH chars were esc's */ { rv=27; /* TWO ESC's = one ESC */ ungetc((int) c[1],stdin); /* push back last only */ } else /* not two ESC's in a row */ { ungetc((int) c[1],stdin); /* psh bck most recent read */ _pb_buf=c[0]; /* push back (undo) first read */ } } if(_kb_flags != kbsave) { _kb_flags = kbsave; /* restore original stdin settings */ fcntl(0,F_SETFL,_kb_flags); } } return(rv); } /* end one_esc() */ /* * Sleep for the given number of microseconds (specified as a negative long). * This function installs its own address as the signal service routine * for the required alarm call. It sets the alarm value only if the * argument passed to here is negative. Positive values are passed to * here which represent the signal value which caused the call. * */ void Usleep(arg) long int arg; /* specify negative value of microseconds to delay */ { struct itimerval itv[1]; struct itimerval otv[1]; (void) signal(SIGALRM,(void (*)())Usleep); /* recursive call (w/positive argument) */ if((arg = -arg) > 0) /* set timer */ { long whole_seconds; whole_seconds = arg / 1000000; itv->it_value.tv_sec = whole_seconds; itv->it_value.tv_usec = arg - (whole_seconds * 1000000); itv->it_interval.tv_sec = 0; itv->it_interval.tv_usec = 0; (void) setitimer(ITIMER_REAL,itv,otv); (void) sigpause(0); } }/* end Usleep() */