[comp.lang.c] Question on implementing "repeat...until keypress"?

maw@auc.UUCP (Michael A. Walker) (02/01/87)

I have some experience in using Apple Pascal(using the UCSD Pascal) and I have
used a loop that will continue until either a defined key or any key is pressed
on the keyboard.  

Now, I am writing a program that I would like to simulate this feature in C. I
would like to use it something like this:

                 do {
                  .
                  .
                  .  }
                 until keypress();

I haven't been programming in C that long but I am rather familiar with the
language.  I am programming on an AT&T 3B5 computer running SYSTEM V UNIX.  I
was thinking that I might have to use something in termcap, terminfo, stty,
or even curses or raw I/O to do this, but I am just getting into that level 
of C programming.

If there is anyone out there who can give me some information as to how 
I can implement this function, PLEASE do so as soon as possible.

Thanks in advanced.

----- mike

P.S.   HELP!!!!!!!!!!!!!!!!

<----------------------------------------------------------------------------->
<      Michael A. Walker      | Operator |      AUC Computational Center      > 
<   gatech!gt-cmmsr!auc!maw   | <<<<>>>> |  "There is strength is diversity." >
<----------------------------------------------------------------------------->

plocher@puff.UUCP (02/02/87)

Question asked about implementing above loop on a 3bx w/SV:

  You mentioned curses.  If you are already using it, there is a 
  function called nodelay(win, flag) which causes getch() to
  return -1 if no input is ready.
   
       #include <curses.h>
	 ...
	 int ch;
	 ...
	 initscr();
	 ...
	 nodelay(curscr, TRUE);
	 while ( (ch = getch()) == -1) {
	     /* do this while waiting for a character */
         }
         /* at this point, ch contains char typed */
  
  If you are not using curses (no reason to use it just for the above!)
  then you might look at the termio(7) man pages where they describe
  ioctl()s which set character count/timeout periods for input.  (This
  is what nodelay() does internally)

  The following was posted to the net a while back; I've used the
  ideas in a few of my programs, and they work ok.
	   Have fun!
	     John


-------- NOT A SHAR ---------

/*
 * In article <30896@arizona.UUCP>, sbw@arizona.UUCP (stephen wampler) writes:
 * > What is the preferred way to determine if a key has been pressed
 * > on the keyboard when running UNIX Sys V?  I know that some UN*X ...
 * -- 
 * Stuart D. Gathman	<..!seismo!{vrdxhq|dgis}!BMS-AT!stuart>
 */

#include <sys/termio.h>

{
  struct termio tty, save;
  char c;

  ioctl(0,TCGETA,&tty);
  save = tty;				/* save current tty definitions */
  tty.c_lflag &= ~(ECHO|ICANON);	/* enter raw mode */
  tty.c_cc[VMIN]=0;		/* wait for at least VMIN chars on read */
  tty.c_cc[VTIME]=0;		/* wait at least VTIME seconds/10 on read   ioctl(0,TCSETA,&tty);

  saved = read(0,&c,1);
  if (saved)
    printf("You typed a '%c'.\n",c);
  else
    printf("You haven't typed anything yet.\n");

/*
  Note, you will have to save 'c' yourself if you need it!
  Perhaps stdio would work (using ungetc()).
*/

/* restore tty state */

  ioctl(0,TCSETA,&save);
}

robert@arizona.UUCP (02/03/87)

In article <32100@auc.UUCP>, maw@auc.UUCP (Michael A. Walker) writes:
> I have some experience in using Apple Pascal(using the UCSD Pascal) and I
> have used a loop that will continue until either a defined key or any
> key is pressed on the keyboard.  
> 

The following works under Berkeley 4.3; detects any key press.  To
have it detect a particular key, it could do a get character and
see if that's the one of interest.

#include	<stdio.h>
#include	<sgtty.h>
#include	<sys/time.h>

typedef	char	bool;
#define TRUE	1
#define	FALSE	0


main()
{
  int i = 0;

  flip(); /* first call puts terminal in raw/noecho mode */

  do {

    printf("Hello <%d>\r\n", i++);  /* just to have something to do here */

  } while (!keypressed());

  flip(); /* second call puts terminal back in original mode */

}  /* main */


/* flip
     Simple routine to switch back and forth between raw and
     regular modes.
*/
flip()
{
  struct sgttyb ttyb;

  ioctl(0, TIOCGETP, &ttyb);
  ttyb.sg_flags ^= (RAW | ECHO);
  ioctl(0, TIOCSETP, &ttyb);

}  /* flip */


/* keypressed
     Returns TRUE if any key is pressed.  Assumes terminal is
     in raw/no echo mode.
*/
bool keypressed()
{
  static struct timeval timeout = {0, 0};
  static int rfd, wfd, efd;

  rfd = 1 << 0; /* this zero refers to device 0 (stdin) */
  wfd = efd = 0;

  return select(32, &rfd, &wfd, &efd, &timeout);

}  /* keypressed */

maw@auc.UUCP (02/09/87)

Awile back, I posted a question pertaining to implementing "repeat...until
keypress".  Well, first I want to thank you those of you who gave me some
help.  I really needed it to complete that phase of my project.

And now for the completion of the next phase:

I need some way to spawn a child process from a C program.  I want it execute
another program, and then, once the child process is ABORTED, the control goes
back to the mother process at the point of spawning.

I would appreciate it it someone can again help me.  I am not trying to get 
everyone to write my programs.  It's just that on these two points that my
knowledge, and experience, is lacking.

Thanks in advanced.

----- mike

-- 
<----------------------------------------------------------------------------->
<      Michael A. Walker      | Operator |      AUC Computational Center      > 
<   gatech!gt-cmmsr!auc!maw   | <<<<>>>> |  "There is strength is diversity." >
<----------------------------------------------------------------------------->

guy@gorodish.UUCP (02/09/87)

(This is NOT a C question, it's an operating system question.  C
doesn't know anything about modes for reading lines vs.  modes for
reading characters, which is as it should be.  I'm redirecting this
to comp.unix.questions, where it belongs.)

>  ioctl(0, TIOCGETP, &ttyb);
>  ttyb.sg_flags ^= (RAW | ECHO);
>  ioctl(0, TIOCSETP, &ttyb);

Is there some reason why this example requires that you:

	1) turn off parity checking and generation?

	2) disable XON/XOFF flow control?

	3) disable the user's interrupt and quit characters?

	4) disable all special output processing (such as mapping
	   newlines to CR/LF)?

If not, then you should be going into CBREAK mode, not RAW mode.
(Two advantages of the S3/S5 terminal driver interface:  1) it
doesn't have CBREAK or RAW mode, so you have to think about what you
want to change, and 2) it's different from the older ones, so you
can't just work from mistaken impressions about what RAW mode really
is.)

RAW mode was intended for binary data transfer, as is used for
up/down loading terminals and the like, UUCP, etc..  (Yes, I know
EMACS uses it, but that's just because the only way to guarantee no
special input processing whatsoever with the older V7-style interface
is to turn RAW mode on.)

The original poster said they were running under S5, so V7/BSD
solutions don't help much.  John Plocher's solution is a correct one
for those systems.

maw@auc.UUCP (02/09/87)

We are experiences some problems with our postnews software. Just in case you 
did not receive a path to me, here is my .signature file which contains 
the path to reply to my recent message.

----- mike

<----------------------------------------------------------------------------->
<      Michael A. Walker      | Operator |      AUC Computational Center      > 
<   gatech!gt-cmmsr!auc!maw   | <<<<>>>> |  "There is strength is diversity." >
<----------------------------------------------------------------------------->

P.S. You will probably get something at the end of this message that will
look like the beginning of the above.
-- 
<----------------------------------------------------------------------------->
<      Michael A. Walker      | Operator |      AUC Computational Center      > 
<   gatech!gt-cmmsr!auc!maw   | <<<<>>>> |  "There is strength is diversity." >
<----------------------------------------------------------------------------->