Updated italian translation
[midnight-commander.git] / slang / slutty.c
blob8c037542cfc077f4e696c66d196d546b6b30ccd6
1 /* slutty.c --- Unix Low level terminal (tty) functions for S-Lang */
2 /* Copyright (c) 1992, 1999, 2001, 2002, 2003 John E. Davis
3 * This file is part of the S-Lang library.
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Perl Artistic License.
7 */
9 #include "slinclud.h"
11 #include <signal.h>
12 /* sequent support thanks to Kenneth Lorber <keni@oasys.dt.navy.mil> */
13 /* SYSV (SYSV ISC R3.2 v3.0) provided by iain.lea@erlm.siemens.de */
15 #if defined (_AIX) && !defined (_ALL_SOURCE)
16 # define _ALL_SOURCE /* so NBBY is defined in <sys/types.h> */
17 #endif
19 #include <sys/time.h>
20 #include <sys/types.h>
22 #ifdef SYSV
23 # include <fcntl.h>
24 # ifndef CRAY
25 # include <sys/termio.h>
26 # include <sys/stream.h>
27 # include <sys/ptem.h>
28 # include <sys/tty.h>
29 # endif
30 #endif
32 #ifdef __BEOS__
33 /* Prototype for select */
34 # include <net/socket.h>
35 #endif
37 #include <sys/file.h>
39 #ifndef sun
40 # include <sys/ioctl.h>
41 #endif
43 #ifdef __QNX__
44 # include <sys/select.h>
45 #endif
47 #include <sys/stat.h>
48 #include <errno.h>
50 #if defined (_AIX) && !defined (FD_SET)
51 # include <sys/select.h> /* for FD_ISSET, FD_SET, FD_ZERO */
52 #endif
54 #ifndef O_RDWR
55 # include <fcntl.h>
56 #endif
58 #include "slang.h"
59 #include "_slang.h"
61 int SLang_TT_Read_FD = -1;
62 int SLang_TT_Baud_Rate;
64 #ifdef HAVE_TERMIOS_H
65 # if !defined(HAVE_TCGETATTR) || !defined(HAVE_TCSETATTR)
66 # undef HAVE_TERMIOS_H
67 # endif
68 #endif
70 #ifndef HAVE_TERMIOS_H
72 # if !defined(CBREAK) && defined(sun)
73 # ifndef BSD_COMP
74 # define BSD_COMP 1
75 # endif
76 # include <sys/ioctl.h>
77 # endif
79 typedef struct
81 struct tchars t;
82 struct ltchars lt;
83 struct sgttyb s;
85 TTY_Termio_Type;
86 #else
87 # include <termios.h>
88 typedef struct termios TTY_Termio_Type;
89 #endif
91 static TTY_Termio_Type Old_TTY;
93 #ifdef HAVE_TERMIOS_H
94 typedef const struct
96 unsigned int key;
97 unsigned int value;
98 } Baud_Rate_Type;
100 static Baud_Rate_Type Baud_Rates [] =
102 #ifdef B0
103 {B0, 0},
104 #endif
105 #ifdef B50
106 {B50, 50},
107 #endif
108 #ifdef B75
109 {B75, 75},
110 #endif
111 #ifdef B110
112 {B110, 110},
113 #endif
114 #ifdef B134
115 {B134, 134},
116 #endif
117 #ifdef B150
118 {B150, 150},
119 #endif
120 #ifdef B200
121 {B200, 200},
122 #endif
123 #ifdef B300
124 {B300, 300},
125 #endif
126 #ifdef B600
127 {B600, 600},
128 #endif
129 #ifdef B1200
130 {B1200, 1200},
131 #endif
132 #ifdef B1800
133 {B1800, 1800},
134 #endif
135 #ifdef B2400
136 {B2400, 2400},
137 #endif
138 #ifdef B4800
139 {B4800, 4800},
140 #endif
141 #ifdef B9600
142 {B9600, 9600},
143 #endif
144 #ifdef B19200
145 {B19200, 19200},
146 #endif
147 #ifdef B38400
148 {B38400, 38400},
149 #endif
150 #ifdef B57600
151 {B57600, 57600},
152 #endif
153 #ifdef B115200
154 {B115200, 115200},
155 #endif
156 #ifdef B230400
157 {B230400, 230400},
158 #endif
159 {0, 0}
162 static void
163 set_baud_rate (TTY_Termio_Type *tty)
165 #ifdef HAVE_CFGETOSPEED
166 unsigned int speed;
167 Baud_Rate_Type *b, *bmax;
169 if (SLang_TT_Baud_Rate)
170 return; /* already set */
172 speed = (unsigned int) cfgetospeed (tty);
174 b = Baud_Rates;
175 bmax = b + (sizeof (Baud_Rates)/sizeof(Baud_Rates[0]));
176 while (b < bmax)
178 if (b->key == speed)
180 SLang_TT_Baud_Rate = b->value;
181 return;
183 b++;
185 #else
186 (void) tty;
187 #endif
190 #endif /* HAVE_TERMIOS_H */
192 #ifdef HAVE_TERMIOS_H
193 # define GET_TERMIOS(fd, x) tcgetattr(fd, x)
194 # define SET_TERMIOS(fd, x) tcsetattr(fd, TCSADRAIN, x)
195 #else
196 # ifdef TCGETS
197 # define GET_TERMIOS(fd, x) ioctl(fd, TCGETS, x)
198 # define SET_TERMIOS(fd, x) ioctl(fd, TCSETS, x)
199 # else
200 # define X(x,m) &(((TTY_Termio_Type *)(x))->m)
201 # define GET_TERMIOS(fd, x) \
202 ((ioctl(fd, TIOCGETC, X(x,t)) || \
203 ioctl(fd, TIOCGLTC, X(x,lt)) || \
204 ioctl(fd, TIOCGETP, X(x,s))) ? -1 : 0)
205 # define SET_TERMIOS(fd, x) \
206 ((ioctl(fd, TIOCSETC, X(x,t)) ||\
207 ioctl(fd, TIOCSLTC, X(x,lt)) || \
208 ioctl(fd, TIOCSETP, X(x,s))) ? -1 : 0)
209 # endif
210 #endif
212 static int TTY_Inited = 0;
213 static int TTY_Open = 0;
215 #ifdef ultrix /* Ultrix gets _POSIX_VDISABLE wrong! */
216 # define NULL_VALUE -1
217 #else
218 # ifdef _POSIX_VDISABLE
219 # define NULL_VALUE _POSIX_VDISABLE
220 # else
221 # define NULL_VALUE 255
222 # endif
223 #endif
225 int SLang_init_tty (int abort_char, int no_flow_control, int opost)
227 TTY_Termio_Type newtty;
229 SLsig_block_signals ();
231 if (TTY_Inited)
233 SLsig_unblock_signals ();
234 return 0;
237 TTY_Open = 0;
239 if ((SLang_TT_Read_FD == -1)
240 || (1 != isatty (SLang_TT_Read_FD)))
242 #ifdef O_RDWR
243 # if !defined(__BEOS__) && !defined(__APPLE__)
244 /* I have been told that BEOS will HANG if passed /dev/tty */
245 if ((SLang_TT_Read_FD = open("/dev/tty", O_RDWR)) >= 0)
247 TTY_Open = 1;
249 # endif
250 #endif
251 if (TTY_Open == 0)
253 SLang_TT_Read_FD = fileno (stderr);
254 if (1 != isatty (SLang_TT_Read_FD))
256 SLang_TT_Read_FD = fileno (stdin);
257 if (1 != isatty (SLang_TT_Read_FD))
259 fprintf (stderr, "Failed to open terminal.");
260 return -1;
266 SLang_Abort_Char = abort_char;
268 /* Some systems may not permit signals to be blocked. As a result, the
269 * return code must be checked.
271 while (-1 == GET_TERMIOS(SLang_TT_Read_FD, &Old_TTY))
273 if (errno != EINTR)
275 SLsig_unblock_signals ();
276 return -1;
280 while (-1 == GET_TERMIOS(SLang_TT_Read_FD, &newtty))
282 if (errno != EINTR)
284 SLsig_unblock_signals ();
285 return -1;
289 #ifndef HAVE_TERMIOS_H
290 (void) opost;
291 (void) no_flow_control;
292 newtty.s.sg_flags &= ~(ECHO);
293 newtty.s.sg_flags &= ~(CRMOD);
294 /* if (Flow_Control == 0) newtty.s.sg_flags &= ~IXON; */
295 newtty.t.t_eofc = 1;
296 if (abort_char == -1) SLang_Abort_Char = newtty.t.t_intrc;
297 newtty.t.t_intrc = SLang_Abort_Char; /* ^G */
298 newtty.t.t_quitc = 255;
299 newtty.lt.t_suspc = 255; /* to ignore ^Z */
300 newtty.lt.t_dsuspc = 255; /* to ignore ^Y */
301 newtty.lt.t_lnextc = 255;
302 newtty.s.sg_flags |= CBREAK; /* do I want cbreak or raw????? */
303 #else
305 /* get baud rate */
307 newtty.c_iflag &= ~(ECHO | INLCR | ICRNL);
308 #ifdef ISTRIP
309 /* newtty.c_iflag &= ~ISTRIP; */
310 #endif
311 if (opost == 0) newtty.c_oflag &= ~OPOST;
313 set_baud_rate (&newtty);
315 if (no_flow_control) newtty.c_iflag &= ~IXON; else newtty.c_iflag |= IXON;
317 newtty.c_cc[VEOF] = 1;
318 newtty.c_cc[VMIN] = 1;
319 newtty.c_cc[VTIME] = 0;
320 newtty.c_lflag = ISIG | NOFLSH;
321 if (abort_char == -1) SLang_Abort_Char = newtty.c_cc[VINTR];
322 newtty.c_cc[VINTR] = SLang_Abort_Char; /* ^G */
323 newtty.c_cc[VQUIT] = NULL_VALUE;
324 newtty.c_cc[VSUSP] = NULL_VALUE; /* to ignore ^Z */
325 #ifdef VDSUSP
326 newtty.c_cc[VDSUSP] = NULL_VALUE; /* to ignore ^Y */
327 #endif
328 #ifdef VLNEXT
329 newtty.c_cc[VLNEXT] = NULL_VALUE; /* to ignore ^V ? */
330 #endif
331 #ifdef VSWTCH
332 newtty.c_cc[VSWTCH] = NULL_VALUE; /* to ignore who knows what */
333 #endif
334 #endif /* NOT HAVE_TERMIOS_H */
336 while (-1 == SET_TERMIOS(SLang_TT_Read_FD, &newtty))
338 if (errno != EINTR)
340 SLsig_unblock_signals ();
341 return -1;
345 TTY_Inited = 1;
346 SLsig_unblock_signals ();
347 return 0;
350 void SLtty_set_suspend_state (int mode)
352 TTY_Termio_Type newtty;
354 SLsig_block_signals ();
356 if (TTY_Inited == 0)
358 SLsig_unblock_signals ();
359 return;
362 while ((-1 == GET_TERMIOS (SLang_TT_Read_FD, &newtty))
363 && (errno == EINTR))
366 #ifndef HAVE_TERMIOS_H
367 /* I do not know if all systems define the t_dsuspc field */
368 if (mode == 0)
370 newtty.lt.t_suspc = 255;
371 newtty.lt.t_dsuspc = 255;
373 else
375 newtty.lt.t_suspc = Old_TTY.lt.t_suspc;
376 newtty.lt.t_dsuspc = Old_TTY.lt.t_dsuspc;
378 #else
379 if (mode == 0)
381 newtty.c_cc[VSUSP] = NULL_VALUE;
382 #ifdef VDSUSP
383 newtty.c_cc[VDSUSP] = NULL_VALUE;
384 #endif
386 else
388 newtty.c_cc[VSUSP] = Old_TTY.c_cc[VSUSP];
389 #ifdef VDSUSP
390 newtty.c_cc[VDSUSP] = Old_TTY.c_cc[VDSUSP];
391 #endif
393 #endif
395 while ((-1 == SET_TERMIOS (SLang_TT_Read_FD, &newtty))
396 && (errno == EINTR))
399 SLsig_unblock_signals ();
402 void SLang_reset_tty (void)
404 SLsig_block_signals ();
406 if (TTY_Inited == 0)
408 SLsig_unblock_signals ();
409 return;
412 while ((-1 == SET_TERMIOS(SLang_TT_Read_FD, &Old_TTY))
413 && (errno == EINTR))
416 if (TTY_Open)
418 while ((-1 == close (SLang_TT_Read_FD))
419 && (errno == EINTR))
422 TTY_Open = 0;
423 SLang_TT_Read_FD = -1;
426 TTY_Inited = 0;
427 SLsig_unblock_signals ();
430 static void default_sigint (int sig)
432 sig = errno; /* use parameter */
434 SLKeyBoard_Quit = 1;
435 if (SLang_Ignore_User_Abort == 0) SLang_Error = SL_USER_BREAK;
436 SLsignal_intr (SIGINT, default_sigint);
437 errno = sig;
440 int SLang_set_abort_signal (void (*hand)(int))
442 int save_errno = errno;
443 SLSig_Fun_Type *f;
445 if (hand == NULL) hand = default_sigint;
446 f = SLsignal_intr (SIGINT, hand);
448 errno = save_errno;
450 if (f == (SLSig_Fun_Type *) SIG_ERR)
451 return -1;
453 return 0;
456 #ifndef FD_SET
457 #define FD_SET(fd, tthis) *(tthis) = 1 << (fd)
458 #define FD_ZERO(tthis) *(tthis) = 0
459 #define FD_ISSET(fd, tthis) (*(tthis) & (1 << fd))
460 typedef int fd_set;
461 #endif
463 static fd_set Read_FD_Set;
465 /* HACK: If > 0, use 1/10 seconds. If < 0, use 1/1000 seconds */
467 int _SLsys_input_pending(int tsecs)
469 struct timeval wait;
470 long usecs, secs;
472 if ((TTY_Inited == 0)
473 || (SLang_TT_Read_FD < 0))
475 errno = EBADF;
476 return -1;
479 if (tsecs >= 0)
481 secs = tsecs / 10;
482 usecs = (tsecs % 10) * 100000;
484 else
486 tsecs = -tsecs;
487 secs = tsecs / 1000;
488 usecs = (tsecs % 1000) * 1000;
491 wait.tv_sec = secs;
492 wait.tv_usec = usecs;
494 FD_ZERO(&Read_FD_Set);
495 FD_SET(SLang_TT_Read_FD, &Read_FD_Set);
497 return select(SLang_TT_Read_FD + 1, &Read_FD_Set, NULL, NULL, &wait);
500 int (*SLang_getkey_intr_hook) (void);
502 static int handle_interrupt (void)
504 if (SLang_getkey_intr_hook != NULL)
506 int save_tty_fd = SLang_TT_Read_FD;
508 if (-1 == (*SLang_getkey_intr_hook) ())
509 return -1;
511 if (save_tty_fd != SLang_TT_Read_FD)
512 return -1;
515 return 0;
518 unsigned int _SLsys_getkey (void)
520 unsigned char c;
522 if (TTY_Inited == 0)
524 int ic = fgetc (stdin);
525 if (ic == EOF) return SLANG_GETKEY_ERROR;
526 return (unsigned int) ic;
529 while (1)
531 int ret;
533 if (SLKeyBoard_Quit)
534 return SLang_Abort_Char;
536 if (0 == (ret = _SLsys_input_pending (100)))
537 continue;
539 if (ret != -1)
540 break;
542 if (SLKeyBoard_Quit)
543 return SLang_Abort_Char;
545 if (errno == EINTR)
547 if (-1 == handle_interrupt ())
548 return SLANG_GETKEY_ERROR;
550 continue;
553 break; /* let read handle it */
556 while (1)
558 int status = read(SLang_TT_Read_FD, (char *) &c, 1);
560 if (status > 0)
561 break;
563 if (status == 0)
565 /* We are at the end of a file. Let application handle it. */
566 return SLANG_GETKEY_ERROR;
569 if (errno == EINTR)
571 if (-1 == handle_interrupt ())
572 return SLANG_GETKEY_ERROR;
574 if (SLKeyBoard_Quit)
575 return SLang_Abort_Char;
577 continue;
579 #ifdef EAGAIN
580 if (errno == EAGAIN)
582 sleep (1);
583 continue;
585 #endif
586 #ifdef EWOULDBLOCK
587 if (errno == EWOULDBLOCK)
589 sleep (1);
590 continue;
592 #endif
593 #ifdef EIO
594 if (errno == EIO)
596 SLang_exit_error ("_SLsys_getkey: EIO error.");
598 #endif
599 return SLANG_GETKEY_ERROR;
602 return((unsigned int) c);