andrewt%watsnew.waterloo.edu@cunyvm.cuny.edu (12/16/89)
I don't know how to do it on the amiga, but here is a method which works on BSD, SunOS, Ultrix. I tried to reply by mail but it bounced. This code is guaranteed not at all. No claim is made to it either. Do what you will. ------------------- cbreak.c ----------------------- /* cbreak.c written by Andrew Thomas andrewt@watsnew.waterloo.edu If you have ideas on how to make this more portable, I am keen to hear them. I make no guarantees, no claims, no copyrights. */ #include <sgtty.h> #include <signal.h> #include <stdio.h> #include <sys/file.h> #include <sys/ioctl.h> /* WARNING: If this file is compiled with gcc (or any ansi compiler) you must privide the -traditional option, or modify the header files to adhere to ansi standard. */ /* The call you really want to use from here is the call to get_a_key(noecho,interrupt_status). If noecho is non-zero, then the keys will not be echoed as they are typed. Interrupt_status is explained in more detail later on. */ static int cbreak_on = 0; static int tty = 0; static int tty_set = 0; static int cbreak_int_status = 0; static struct sgttyb tty_desc; void cbreak(); void nocbreak(); void cbreak_ignoresignal () { } void cbreak_killsignal () { nocbreak (); exit (1); } void cbreak_stopsignal () { nocbreak (); kill (getpid(), SIGSTOP); if (cbreak_on) cbreak(cbreak_on-1); } /* interrupt_status tells the system what to do with SIGTSTP, SIGTERM and SIGINT interrupt status is one of 0, 1, or 2: 0: do nothing to alter the interrupts, or if interrupt status was changed before, make interrupts perform the default action. 1: make interrupts cause a clean exit, resetting the interrupt status on exit and reentry 2: ignore interrupts. */ void cbreak_open_tty (interrupt_status) int interrupt_status; { tty_set = 1; tty = fileno (stdin); if (ioctl (tty, TIOCGETP, &tty_desc) == -1) perror ("ioctl: TIOCGETP"); if (interrupt_status == 0 && cbreak_int_status != 0) { signal (SIGTSTP, SIG_DFL); signal (SIGTERM, SIG_DFL); signal (SIGINT, SIG_DFL); } else if (interrupt_status == 1) { signal (SIGTSTP, cbreak_stopsignal); signal (SIGTERM, cbreak_killsignal); signal (SIGINT, cbreak_killsignal); } else if (interrupt_status == 2) { signal (SIGTSTP, cbreak_ignoresignal); signal (SIGTERM, cbreak_ignoresignal); signal (SIGINT, cbreak_ignoresignal); } cbreak_int_status = interrupt_status; } /* noecho, if non-zero, causes the key stroke not to be echoed */ void cbreak (noecho, interrupt_status) int noecho, interrupt_status; { if (!tty_set || interrupt_status != cbreak_int_status) cbreak_open_tty (interrupt_status); tty_desc.sg_flags |= CBREAK; if (noecho) tty_desc.sg_flags &= ~ECHO; if (ioctl (tty, TIOCSETN, &tty_desc) == -1) perror ("cbreak: ioctl: TIOCSETN"); } void nocbreak () { if (!tty_set) cbreak_open_tty (cbreak_int_status); tty_desc.sg_flags &= ~CBREAK; tty_desc.sg_flags |= ECHO; if (ioctl (tty, TIOCSETN, &tty_desc) == -1) perror ("nocbreak: ioctl: TIOCSETN"); } /* get a keystroke in cbreak mode, echoed or not echoed, with actions on interrupts specified. Clear the stdin buffer first. This is a bit of a kluge. Suggestions welcome. */ char get_a_key (noecho, interrupt_status) int noecho, interrupt_status; { char x; while (stdin->_cnt > 0) if ((x=getchar()) != '\n') return (x); cbreak (noecho, interrupt_status); cbreak_on = 1+(noecho?1:0); x = getchar(); nocbreak (); cbreak_on = 0; return (x); } -------------------------------------------------- Hope this helps. -- Andrew Thomas andrewt@watsnew.waterloo.edu Systems Design Eng. University of Waterloo "If a million people do a stupid thing, it's still a stupid thing." - Opus