ncurses 4.1
[ncurses.git] / ncurses / lib_raw.c
1
2 /***************************************************************************
3 *                            COPYRIGHT NOTICE                              *
4 ****************************************************************************
5 *                ncurses is copyright (C) 1992-1995                        *
6 *                          Zeyd M. Ben-Halim                               *
7 *                          zmbenhal@netcom.com                             *
8 *                          Eric S. Raymond                                 *
9 *                          esr@snark.thyrsus.com                           *
10 *                                                                          *
11 *        Permission is hereby granted to reproduce and distribute ncurses  *
12 *        by any means and for any fee, whether alone or as part of a       *
13 *        larger distribution, in source or in binary form, PROVIDED        *
14 *        this notice is included with any such distribution, and is not    *
15 *        removed from any of its header files. Mention of ncurses in any   *
16 *        applications linked with it is highly appreciated.                *
17 *                                                                          *
18 *        ncurses comes AS IS with no warranty, implied or expressed.       *
19 *                                                                          *
20 ***************************************************************************/
21
22
23 /*
24  *      raw.c
25  *
26  *      Routines:
27  *              raw()
28  *              echo()
29  *              nl()
30  *              cbreak()
31  *              noraw()
32  *              noecho()
33  *              nonl()
34  *              nocbreak()
35  *              qiflush()
36  *              noqiflush()
37  *              intrflush()
38  *
39  */
40
41 #include <curses.priv.h>
42 #include <term.h>       /* cur_term */
43
44 MODULE_ID("$Id: lib_raw.c,v 1.16 1997/02/02 00:02:32 tom Exp $")
45
46 #ifdef SVR4_TERMIO
47 #define _POSIX_SOURCE
48 #endif
49
50 #if HAVE_SYS_TERMIO_H
51 #include <sys/termio.h> /* needed for ISC */
52 #endif
53
54 /* may be undefined if we're using termio.h */
55 #ifndef TOSTOP
56 #define TOSTOP 0
57 #endif
58 #ifndef IEXTEN
59 #define IEXTEN 0
60 #endif
61
62 #define COOKED_INPUT    (IXON|BRKINT|PARMRK)
63
64 #ifdef TRACE
65 char *_tracebits(void)
66 /* describe the state of the terminal control bits exactly */
67 {
68 static char     buf[BUFSIZ];
69 static const    struct {unsigned int val; const char *name;}
70
71 #ifdef TERMIOS
72 iflags[] =
73     {
74         {BRKINT,        "BRKINT"},
75         {IGNBRK,        "IGNBRK"},
76         {IGNPAR,        "IGNPAR"},
77         {PARMRK,        "PARMRK"},
78         {INPCK,         "INPCK"},
79         {ISTRIP,        "ISTRIP"},
80         {INLCR,         "INLCR"},
81         {IGNCR,         "IGNC"},
82         {ICRNL,         "ICRNL"},
83         {IXON,          "IXON"},
84         {IXOFF,         "IXOFF"},
85         {0,             NULL}
86 #define ALLIN   (BRKINT|IGNBRK|IGNPAR|PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF)
87     },
88 oflags[] =
89     {
90         {OPOST,         "OPOST"},
91         {0,             NULL}
92 #define ALLOUT  (OPOST)
93     },
94 cflags[] =
95     {
96         {CLOCAL,        "CLOCAL"},
97         {CREAD,         "CREAD"},
98         {CSIZE,         "CSIZE"},
99         {CSTOPB,        "CSTOPB"},
100         {HUPCL,         "HUPCL"},
101         {PARENB,        "PARENB"},
102         {PARODD|PARENB, "PARODD"},      /* concession to readability */
103         {0,             NULL}
104 #define ALLCTRL (CLOCAL|CREAD|CSIZE|CSTOPB|HUPCL|PARENB|PARODD)
105     },
106 lflags[] =
107     {
108         {ECHO,          "ECHO"},
109         {ECHOE|ECHO,    "ECHOE"},       /* concession to readability */
110         {ECHOK|ECHO,    "ECHOK"},       /* concession to readability */
111         {ECHONL,        "ECHONL"},
112         {ICANON,        "ICANON"},
113         {ISIG,          "ISIG"},
114         {NOFLSH,        "NOFLSH"},
115 #if TOSTOP != 0
116         {TOSTOP,        "TOSTOP"},
117 #endif
118 #if IEXTEN != 0
119         {IEXTEN,        "IEXTEN"},
120 #endif
121         {0,             NULL}
122 #define ALLLOCAL        (ECHO|ECHONL|ICANON|ISIG|NOFLSH|TOSTOP|IEXTEN)
123     },
124     *sp;
125
126     if (cur_term->Nttyb.c_iflag & ALLIN)
127     {
128         (void) strcpy(buf, "iflags: {");
129         for (sp = iflags; sp->val; sp++)
130             if ((cur_term->Nttyb.c_iflag & sp->val) == sp->val)
131             {
132                 (void) strcat(buf, sp->name);
133                 (void) strcat(buf, ", ");
134             }
135         if (buf[strlen(buf) - 2] == ',')
136             buf[strlen(buf) - 2] = '\0';
137         (void) strcat(buf,"} ");
138     }
139
140     if (cur_term->Nttyb.c_oflag & ALLOUT)
141     {
142         (void) strcat(buf, "oflags: {");
143         for (sp = oflags; sp->val; sp++)
144             if ((cur_term->Nttyb.c_oflag & sp->val) == sp->val)
145             {
146                 (void) strcat(buf, sp->name);
147                 (void) strcat(buf, ", ");
148             }
149         if (buf[strlen(buf) - 2] == ',')
150             buf[strlen(buf) - 2] = '\0';
151         (void) strcat(buf,"} ");
152     }
153
154     if (cur_term->Nttyb.c_cflag & ALLCTRL)
155     {
156         (void) strcat(buf, "cflags: {");
157         for (sp = cflags; sp->val; sp++)
158             if ((cur_term->Nttyb.c_cflag & sp->val) == sp->val)
159             {
160                 (void) strcat(buf, sp->name);
161                 (void) strcat(buf, ", ");
162             }
163         if (buf[strlen(buf) - 2] == ',')
164             buf[strlen(buf) - 2] = '\0';
165         (void) strcat(buf,"} ");
166     }
167
168     if (cur_term->Nttyb.c_lflag & ALLLOCAL)
169     {
170         (void) strcat(buf, "lflags: {");
171         for (sp = lflags; sp->val; sp++)
172             if ((cur_term->Nttyb.c_lflag & sp->val) == sp->val)
173             {
174                 (void) strcat(buf, sp->name);
175                 (void) strcat(buf, ", ");
176             }
177         if (buf[strlen(buf) - 2] == ',')
178             buf[strlen(buf) - 2] = '\0';
179         (void) strcat(buf,"} ");
180     }
181
182 #else
183     /* reference: ttcompat(4M) on SunOS 4.1 */
184 #ifndef EVENP
185 #define EVENP 0
186 #endif
187 #ifndef LCASE
188 #define LCASE 0
189 #endif
190 #ifndef LLITOUT
191 #define LLITOUT 0
192 #endif
193 #ifndef ODDP
194 #define ODDP 0
195 #endif
196 #ifndef TANDEM
197 #define TANDEM 0
198 #endif
199
200 cflags[] =
201     {
202         {CBREAK,        "CBREAK"},
203         {CRMOD,         "CRMOD"},
204         {ECHO,          "ECHO"},
205         {EVENP,         "EVENP"},
206         {LCASE,         "LCASE"},
207         {LLITOUT,       "LLITOUT"},
208         {ODDP,          "ODDP"},
209         {RAW,           "RAW"},
210         {TANDEM,        "TANDEM"},
211         {XTABS,         "XTABS"},
212         {0,             NULL}
213 #define ALLCTRL (CBREAK|CRMOD|ECHO|EVENP|LCASE|LLITOUT|ODDP|RAW|TANDEM|XTABS)
214     },
215     *sp;
216
217     if (cur_term->Nttyb.sg_flags & ALLCTRL)
218     {
219         (void) strcat(buf, "cflags: {");
220         for (sp = cflags; sp->val; sp++)
221             if ((cur_term->Nttyb.sg_flags & sp->val) == sp->val)
222             {
223                 (void) strcat(buf, sp->name);
224                 (void) strcat(buf, ", ");
225             }
226         if (buf[strlen(buf) - 2] == ',')
227             buf[strlen(buf) - 2] = '\0';
228         (void) strcat(buf,"} ");
229     }
230
231 #endif
232     return(buf);
233 }
234
235 #define BEFORE(N)       if (_nc_tracing&TRACE_BITS) _tracef("%s before bits: %s", N, _tracebits())
236 #define AFTER(N)        if (_nc_tracing&TRACE_BITS) _tracef("%s after bits: %s", N, _tracebits())
237 #else
238 #define BEFORE(s)
239 #define AFTER(s)
240 #endif /* TRACE */
241
242 int raw(void)
243 {
244         T((T_CALLED("raw()")));
245
246         SP->_raw = TRUE;
247         SP->_cbreak = TRUE;
248
249 #ifdef TERMIOS
250         BEFORE("raw");
251         cur_term->Nttyb.c_lflag &= ~(ICANON|ISIG);
252         cur_term->Nttyb.c_iflag &= ~(COOKED_INPUT);
253         cur_term->Nttyb.c_cc[VMIN] = 1;
254         cur_term->Nttyb.c_cc[VTIME] = 0;
255         AFTER("raw");
256 #else
257         cur_term->Nttyb.sg_flags |= RAW;
258 #endif
259         if ((SET_TTY(cur_term->Filedes, &cur_term->Nttyb)) == -1)
260                 returnCode(ERR);
261         returnCode(OK);
262 }
263
264 int cbreak(void)
265 {
266         T((T_CALLED("cbreak()")));
267
268         SP->_cbreak = TRUE;
269
270 #ifdef TERMIOS
271         BEFORE("cbreak");
272         cur_term->Nttyb.c_lflag &= ~ICANON;
273         cur_term->Nttyb.c_iflag &= ~ICRNL;
274         cur_term->Nttyb.c_lflag |= ISIG;
275         cur_term->Nttyb.c_cc[VMIN] = 1;
276         cur_term->Nttyb.c_cc[VTIME] = 0;
277         AFTER("cbreak");
278 #else
279         cur_term->Nttyb.sg_flags |= CBREAK;
280 #endif
281         if ((SET_TTY(cur_term->Filedes, &cur_term->Nttyb)) == -1)
282                 returnCode(ERR);
283         returnCode(OK);
284 }
285
286 int echo(void)
287 {
288         T((T_CALLED("echo()")));
289
290         SP->_echo = TRUE;
291
292         returnCode(OK);
293 }
294
295
296 int nl(void)
297 {
298         T((T_CALLED("nl()")));
299
300         SP->_nl = TRUE;
301
302         returnCode(OK);
303 }
304
305
306 int qiflush(void)
307 {
308         T((T_CALLED("qiflush()")));
309
310         /*
311          * Note: this implementation may be wrong.  See the comment under
312          * intrflush().
313          */
314
315 #ifdef TERMIOS
316         BEFORE("qiflush");
317         cur_term->Nttyb.c_lflag &= ~(NOFLSH);
318         AFTER("qiflush");
319         if ((SET_TTY(cur_term->Filedes, &cur_term->Nttyb)) == -1)
320                 returnCode(ERR);
321         else
322                 returnCode(OK);
323 #else
324         returnCode(ERR);
325 #endif
326 }
327
328
329 int noraw(void)
330 {
331         T((T_CALLED("noraw()")));
332
333         SP->_raw = FALSE;
334         SP->_cbreak = FALSE;
335
336 #ifdef TERMIOS
337         BEFORE("noraw");
338         cur_term->Nttyb.c_lflag |= ISIG|ICANON;
339         cur_term->Nttyb.c_iflag |= COOKED_INPUT;
340         AFTER("noraw");
341 #else
342         cur_term->Nttyb.sg_flags &= ~(RAW|CBREAK);
343 #endif
344         if ((SET_TTY(cur_term->Filedes, &cur_term->Nttyb)) == -1)
345                 returnCode(ERR);
346         returnCode(OK);
347 }
348
349
350 int nocbreak(void)
351 {
352         T((T_CALLED("nocbreak()")));
353
354         SP->_cbreak = 0;
355
356 #ifdef TERMIOS
357         BEFORE("nocbreak");
358         cur_term->Nttyb.c_lflag |= ICANON;
359         cur_term->Nttyb.c_iflag |= ICRNL;
360         AFTER("nocbreak");
361 #else
362         cur_term->Nttyb.sg_flags &= ~CBREAK;
363 #endif
364         if ((SET_TTY(cur_term->Filedes, &cur_term->Nttyb)) == -1)
365                 returnCode(ERR);
366         returnCode(OK);
367 }
368
369 int noecho(void)
370 {
371         T((T_CALLED("noecho()")));
372         SP->_echo = FALSE;
373         returnCode(OK);
374 }
375
376
377 int nonl(void)
378 {
379         T((T_CALLED("nonl()")));
380
381         SP->_nl = FALSE;
382
383         returnCode(OK);
384 }
385
386 int noqiflush(void)
387 {
388         T((T_CALLED("noqiflush()")));
389
390         /*
391          * Note: this implementation may be wrong.  See the comment under
392          * intrflush().
393          */
394
395 #ifdef TERMIOS
396         BEFORE("noqiflush");
397         cur_term->Nttyb.c_lflag |= NOFLSH;
398         AFTER("noqiflush");
399         if ((SET_TTY(cur_term->Filedes, &cur_term->Nttyb)) == -1)
400                 returnCode(ERR);
401         else
402                 returnCode(OK);
403 #else
404         returnCode(ERR);
405 #endif
406 }
407
408 int intrflush(WINDOW *win GCC_UNUSED, bool flag)
409 {
410         T((T_CALLED("intrflush(%d)"), flag));
411
412         /*
413          * This call does the same thing as the qiflush()/noqiflush()
414          * pair.  We know for certain that SVr3 intrflush() tweaks the
415          * NOFLSH bit; on the other hand, the match (in the SVr4 man
416          * pages) between the language describing NOFLSH in termio(7)
417          * and the language describing qiflush()/noqiflush() in
418          * curs_inopts(3x) is too exact to be coincidence.
419          */
420
421 #ifdef TERMIOS
422         BEFORE("intrflush");
423         if (flag)
424                 cur_term->Nttyb.c_lflag &= ~(NOFLSH);
425         else
426                 cur_term->Nttyb.c_lflag |= (NOFLSH);
427         AFTER("intrflush");
428         if ((SET_TTY(cur_term->Filedes, &cur_term->Nttyb)) == -1)
429                 returnCode(ERR);
430         else
431                 returnCode(OK);
432 #else
433         returnCode(ERR);
434 #endif
435 }