|
|
1.1 root 1: /*
2: conwrap.c -- To give DOS's getch() function to Linux for use in Synchronet
3: Casey Martin 2000
4: */
5:
6: /* $Id: conwrap.c,v 1.2 2000/11/02 13:21:24 rswindell Exp $ */
7:
8: /* @format.tab-size 4, @format.use-tabs true */
9:
10: #ifdef __unix__
11:
12: #include <stdlib.h>
13: #include <unistd.h>
14: #include <termios.h>
15: #include <sys/kd.h>
16: #include <sys/time.h>
17: #include <sys/types.h>
18: #include <signal.h>
19:
20: #include "conwrap.h" // Verify prototypes
21:
22: struct termios current; // our current term settings
23: struct termios original; // old termios settings
24: struct timeval timeout = {0, 0}; // passed in select() call
25: fd_set inp; // ditto
26: int beensetup = 0; // has _termios_setup() been called?
27:
28: /*
29: I'm using a variable function here simply for the sake of speed. The
30: termios functions must be called before a kbhit() can be successful, so
31: on the first call, we just set up the terminal, point to variable function
32: to kbhit_norm(), and then call the new function. Otherwise, testing would
33: be required on every call to determine if termios has already been setup.
34:
35: Maybe I'm being way too anal, though.
36: */
37:
38: /* Resets the termios to its previous state */
39: void _termios_reset(void)
40: {
41: tcsetattr(0, TCSANOW, &original);
42: }
43:
44: /************************************************
45: This pair of functions handles Ctrl-Z presses
46: ************************************************/
47:
48: void _sighandler_stop(int sig)
49: {
50: // clean up the terminal
51: _termios_reset();
52:
53: // ... and stop
54: kill(getpid(), SIGSTOP);
55: }
56:
57: void _sighandler_cont(int sig)
58: {
59: // restore terminal
60: tcsetattr(0, TCSANOW, ¤t);
61: }
62:
63:
64: /* Prepares termios for non-blocking action */
65: void _termios_setup(void)
66: {
67: beensetup = 1;
68:
69: tcgetattr(0, &original);
70:
71: memcpy(¤t, &original, sizeof(struct termios));
72: current.c_cc[VMIN] = 1; // read() will return with one char
73: current.c_cc[VTIME] = 0; // read() blocks forever
74: current.c_lflag &= ~ICANON; // character mode
75: current.c_lflag &= ~ECHO; // turn off echoing
76: tcsetattr(0, TCSANOW, ¤t);
77:
78: // Let's install an exit function, also. This way, we can reset
79: // the termios silently
80: atexit(_termios_reset);
81:
82: // install the Ctrl-Z handler
83: signal(SIGSTOP, _sighandler_stop);
84: signal(SIGCONT, _sighandler_cont);
85: }
86:
87:
88: int kbhit(void)
89: {
90: // set up select() args
91: FD_ZERO(&inp);
92: FD_SET(0, &inp);
93:
94: return select(1, &inp, NULL, NULL, &timeout);
95: }
96:
97: int getch(void)
98: {
99: char c;
100:
101: if (!beensetup)
102: // I hate to test for this every time, but this shouldn't be
103: // called that often anyway...
104: _termios_setup();
105:
106: // get a char out of stdin
107: read(0, &c, 1);
108:
109: return c;
110: }
111:
112: #endif // __unix__
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.