* rltty.c: #if out some code if __GO32__.
[external/binutils.git] / readline / rltty.c
1 /* rltty.c -- functions to prepare and restore the terminal for readline's
2    use. */
3
4 /* Copyright (C) 1992 Free Software Foundation, Inc.
5
6    This file is part of the GNU Readline Library, a library for
7    reading lines of text with interactive input and history editing.
8
9    The GNU Readline Library is free software; you can redistribute it
10    and/or modify it under the terms of the GNU General Public License
11    as published by the Free Software Foundation; either version 1, or
12    (at your option) any later version.
13
14    The GNU Readline Library is distributed in the hope that it will be
15    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    The GNU General Public License is often shipped with GNU software, and
20    is generally kept in a file called COPYING or LICENSE.  If you do not
21    have a copy of the license, write to the Free Software Foundation,
22    675 Mass Ave, Cambridge, MA 02139, USA. */
23 #include <sys/types.h>
24 #include <signal.h>
25 #include <errno.h>
26 #include <stdio.h>
27
28 #if defined (HAVE_UNISTD_H)
29 #  include <unistd.h>
30 #endif /* HAVE_UNISTD_H */
31
32 #include "rldefs.h"
33 #include "readline.h"
34
35 #if !defined (errno)
36 extern int errno;
37 #endif /* !errno */
38
39 extern int readline_echoing_p;
40 extern int _rl_eof_char;
41
42 #if defined (_GO32_)
43 #  include <sys/pc.h>
44 #  undef HANDLE_SIGNALS
45 #endif /* _GO32_ */
46
47 /* **************************************************************** */
48 /*                                                                  */
49 /*                         Signal Management                        */
50 /*                                                                  */
51 /* **************************************************************** */
52
53 #if defined (HAVE_POSIX_SIGNALS)
54 static sigset_t sigint_set, sigint_oset;
55 #else /* !HAVE_POSIX_SIGNALS */
56 #  if defined (HAVE_BSD_SIGNALS)
57 static int sigint_oldmask;
58 #  endif /* HAVE_BSD_SIGNALS */
59 #endif /* !HAVE_POSIX_SIGNALS */
60
61 static int sigint_blocked = 0;
62
63 /* Cause SIGINT to not be delivered until the corresponding call to
64    release_sigint(). */
65 static void
66 block_sigint ()
67 {
68   if (sigint_blocked)
69     return;
70
71 #if defined (HAVE_POSIX_SIGNALS)
72   sigemptyset (&sigint_set);
73   sigemptyset (&sigint_oset);
74   sigaddset (&sigint_set, SIGINT);
75   sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset);
76 #else /* !HAVE_POSIX_SIGNALS */
77 #  if defined (HAVE_BSD_SIGNALS)
78   sigint_oldmask = sigblock (sigmask (SIGINT));
79 #  else /* !HAVE_BSD_SIGNALS */
80 #    if defined (HAVE_USG_SIGHOLD)
81   sighold (SIGINT);
82 #    endif /* HAVE_USG_SIGHOLD */
83 #  endif /* !HAVE_BSD_SIGNALS */
84 #endif /* !HAVE_POSIX_SIGNALS */
85   sigint_blocked = 1;
86 }
87
88 /* Allow SIGINT to be delivered. */
89 static void
90 release_sigint ()
91 {
92   if (!sigint_blocked)
93     return;
94
95 #if defined (HAVE_POSIX_SIGNALS)
96   sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL);
97 #else
98 #  if defined (HAVE_BSD_SIGNALS)
99   sigsetmask (sigint_oldmask);
100 #  else /* !HAVE_BSD_SIGNALS */
101 #    if defined (HAVE_USG_SIGHOLD)
102   sigrelse (SIGINT);
103 #    endif /* HAVE_USG_SIGHOLD */
104 #  endif /* !HAVE_BSD_SIGNALS */
105 #endif /* !HAVE_POSIX_SIGNALS */
106
107   sigint_blocked = 0;
108 }
109 \f
110 /* **************************************************************** */
111 /*                                                                  */
112 /*                    Controlling the Meta Key                      */
113 /*                                                                  */
114 /* **************************************************************** */
115
116 extern int term_has_meta;
117 extern char *term_mm;
118 extern char *term_mo;
119
120 static void
121 outchar (c)
122      int c;
123 {
124   putc (c, rl_outstream);
125 }
126
127 /* Turn on/off the meta key depending on ON. */
128 static void
129 control_meta_key (on)
130      int on;
131 {
132   if (term_has_meta)
133     {
134       if (on && term_mm)
135         tputs (term_mm, 1, outchar);
136       else if (!on && term_mo)
137         tputs (term_mo, 1, outchar);
138     }
139 }
140 \f
141 /* **************************************************************** */
142 /*                                                                  */
143 /*                    Saving and Restoring the TTY                  */
144 /*                                                                  */
145 /* **************************************************************** */
146
147 /* Non-zero means that the terminal is in a prepped state. */
148 static int terminal_prepped = 0;
149
150 /* If non-zero, means that this process has called tcflow(fd, TCOOFF)
151    and output is suspended. */
152 #if defined (__ksr1__)
153 static int ksrflow = 0;
154 #endif
155 #if defined (NEW_TTY_DRIVER)
156
157 /* Values for the `flags' field of a struct bsdtty.  This tells which
158    elements of the struct bsdtty have been fetched from the system and
159    are valid. */
160 #define SGTTY_SET       0x01
161 #define LFLAG_SET       0x02
162 #define TCHARS_SET      0x04
163 #define LTCHARS_SET     0x08
164
165 struct bsdtty {
166   struct sgttyb sgttyb; /* Basic BSD tty driver information. */
167   int lflag;            /* Local mode flags, like LPASS8. */
168 #if defined (TIOCGETC)
169   struct tchars tchars; /* Terminal special characters, including ^S and ^Q. */
170 #endif
171 #if defined (TIOCGLTC)
172   struct ltchars ltchars; /* 4.2 BSD editing characters */
173 #endif
174   int flags;            /* Bitmap saying which parts of the struct are valid. */
175 };
176
177 #define TIOTYPE struct bsdtty
178
179 static TIOTYPE otio;
180
181 static int
182 get_tty_settings (tty, tiop)
183      int tty;
184      TIOTYPE *tiop;
185 {
186   tiop->flags = tiop->lflag = 0;
187
188   ioctl (tty, TIOCGETP, &(tiop->sgttyb));
189   tiop->flags |= SGTTY_SET;
190
191 #if defined (TIOCLGET)
192   ioctl (tty, TIOCLGET, &(tiop->lflag));
193   tiop->flags |= LFLAG_SET;
194 #endif
195
196 #if defined (TIOCGETC)
197   ioctl (tty, TIOCGETC, &(tiop->tchars));
198   tiop->flags |= TCHARS_SET;
199 #endif
200
201 #if defined (TIOCGLTC)
202   ioctl (tty, TIOCGLTC, &(tiop->ltchars));
203   tiop->flags |= LTCHARS_SET;
204 #endif
205
206   return 0;
207 }
208
209 set_tty_settings (tty, tiop)
210      int tty;
211      TIOTYPE *tiop;
212 {
213   if (tiop->flags & SGTTY_SET)
214     {
215       ioctl (tty, TIOCSETN, &(tiop->sgttyb));
216       tiop->flags &= ~SGTTY_SET;
217     }
218   readline_echoing_p = 1;
219
220 #if defined (TIOCLSET)
221   if (tiop->flags & LFLAG_SET)
222     {
223       ioctl (tty, TIOCLSET, &(tiop->lflag));
224       tiop->flags &= ~LFLAG_SET;
225     }
226 #endif
227
228 #if defined (TIOCSETC)
229   if (tiop->flags & TCHARS_SET)
230     {
231       ioctl (tty, TIOCSETC, &(tiop->tchars));
232       tiop->flags &= ~TCHARS_SET;
233     }
234 #endif
235
236 #if defined (TIOCSLTC)
237   if (tiop->flags & LTCHARS_SET)
238     {
239       ioctl (tty, TIOCSLTC, &(tiop->ltchars));
240       tiop->flags &= ~LTCHARS_SET;
241     }
242 #endif
243
244   return 0;
245 }
246
247 static void
248 prepare_terminal_settings (meta_flag, otio, tiop)
249      int meta_flag;
250      TIOTYPE otio, *tiop;
251 {
252 #if !defined (_GO32_)
253   readline_echoing_p = (otio.sgttyb.sg_flags & ECHO);
254
255   /* Copy the original settings to the structure we're going to use for
256      our settings. */
257   tiop->sgttyb = otio.sgttyb;
258   tiop->lflag = otio.lflag;
259 #if defined (TIOCGETC)
260   tiop->tchars = otio.tchars;
261 #endif
262 #if defined (TIOCGLTC)
263   tiop->ltchars = otio.ltchars;
264 #endif
265   tiop->flags = otio.flags;
266
267   /* First, the basic settings to put us into character-at-a-time, no-echo
268      input mode. */
269   tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD);
270   tiop->sgttyb.sg_flags |= CBREAK;
271
272   /* If this terminal doesn't care how the 8th bit is used, then we can
273      use it for the meta-key.  If only one of even or odd parity is
274      specified, then the terminal is using parity, and we cannot. */
275 #if !defined (ANYP)
276 #  define ANYP (EVENP | ODDP)
277 #endif
278   if (((otio.sgttyb.sg_flags & ANYP) == ANYP) ||
279       ((otio.sgttyb.sg_flags & ANYP) == 0))
280     {
281       tiop->sgttyb.sg_flags |= ANYP;
282
283       /* Hack on local mode flags if we can. */
284 #if defined (TIOCLGET)
285 #  if defined (LPASS8)
286       tiop->lflag |= LPASS8;
287 #  endif /* LPASS8 */
288 #endif /* TIOCLGET */
289     }
290
291 #if defined (TIOCGETC)
292 #  if defined (USE_XON_XOFF)
293   /* Get rid of terminal output start and stop characters. */
294   tiop->tchars.t_stopc = -1; /* C-s */
295   tiop->tchars.t_startc = -1; /* C-q */
296
297   /* If there is an XON character, bind it to restart the output. */
298   if (otio.tchars.t_startc != -1)
299     rl_bind_key (otio.tchars.t_startc, rl_restart_output);
300 #  endif /* USE_XON_XOFF */
301
302   /* If there is an EOF char, bind _rl_eof_char to it. */
303   if (otio.tchars.t_eofc != -1)
304     _rl_eof_char = otio.tchars.t_eofc;
305
306 #  if defined (NO_KILL_INTR)
307   /* Get rid of terminal-generated SIGQUIT and SIGINT. */
308   tiop->tchars.t_quitc = -1; /* C-\ */
309   tiop->tchars.t_intrc = -1; /* C-c */
310 #  endif /* NO_KILL_INTR */
311 #endif /* TIOCGETC */
312
313 #if defined (TIOCGLTC)
314   /* Make the interrupt keys go away.  Just enough to make people happy. */
315   tiop->ltchars.t_dsuspc = -1;  /* C-y */
316   tiop->ltchars.t_lnextc = -1;  /* C-v */
317 #endif /* TIOCGLTC */
318 #endif /* !_GO32_ */
319 }
320 #endif /* defined (NEW_TTY_DRIVER) */
321
322 #if !defined (NEW_TTY_DRIVER) && !defined(_GO32_)
323
324 #if !defined (VMIN)
325 #  define VMIN VEOF
326 #endif
327
328 #if !defined (VTIME)
329 #  define VTIME VEOL
330 #endif
331
332 #if defined (TERMIOS_TTY_DRIVER)
333 #  define TIOTYPE struct termios
334 #  define DRAIN_OUTPUT(fd)      tcdrain (fd)
335 #  define GETATTR(tty, tiop)    (tcgetattr (tty, tiop))
336 #  define SETATTR(tty, tiop)    (tcsetattr (tty, TCSANOW, tiop))
337 #else
338 #  define TIOTYPE struct termio
339 #  define DRAIN_OUTPUT(fd)
340 #  define GETATTR(tty, tiop)    (ioctl (tty, TCGETA, tiop))
341 #  define SETATTR(tty, tiop)    (ioctl (tty, TCSETA, tiop))
342 #endif /* !TERMIOS_TTY_DRIVER */
343
344 static TIOTYPE otio;
345
346 static int
347 get_tty_settings (tty, tiop)
348      int tty;
349      TIOTYPE *tiop;
350 {
351   while (GETATTR (tty, tiop) < 0)
352     {
353       if (errno != EINTR)
354         return -1;
355       errno = 0;
356     }
357   return 0;
358 }
359
360 static int
361 set_tty_settings (tty, tiop)
362      int tty;
363      TIOTYPE *tiop;
364 {
365   while (SETATTR (tty, tiop) < 0)
366     {
367       if (errno != EINTR)
368         return -1;
369       errno = 0;
370     }
371
372 #if 0
373
374 #if defined (TERMIOS_TTY_DRIVER)
375 #  if defined (__ksr1__)
376   if (ksrflow)
377     {
378       ksrflow = 0;
379       tcflow (tty, TCOON);
380     }
381 #  else /* !ksr1 */
382   tcflow (tty, TCOON);          /* Simulate a ^Q. */
383 #  endif /* !ksr1 */
384 #else
385   ioctl (tty, TCXONC, 1);       /* Simulate a ^Q. */
386 #endif /* !TERMIOS_TTY_DRIVER */
387
388 #endif
389
390   return 0;
391 }
392
393 static void
394 prepare_terminal_settings (meta_flag, otio, tiop)
395      int meta_flag;
396      TIOTYPE otio, *tiop;
397 {
398   readline_echoing_p = (otio.c_lflag & ECHO);
399
400   tiop->c_lflag &= ~(ICANON | ECHO);
401
402   if ((unsigned char) otio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
403     _rl_eof_char = otio.c_cc[VEOF];
404
405 #if defined (USE_XON_XOFF)
406 #if defined (IXANY)
407   tiop->c_iflag &= ~(IXON | IXOFF | IXANY);
408 #else
409   /* `strict' Posix systems do not define IXANY. */
410   tiop->c_iflag &= ~(IXON | IXOFF);
411 #endif /* IXANY */
412 #endif /* USE_XON_XOFF */
413
414   /* Only turn this off if we are using all 8 bits. */
415   if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
416     tiop->c_iflag &= ~(ISTRIP | INPCK);
417
418   /* Make sure we differentiate between CR and NL on input. */
419   tiop->c_iflag &= ~(ICRNL | INLCR);
420
421 #if !defined (HANDLE_SIGNALS)
422   tiop->c_lflag &= ~ISIG;
423 #else
424   tiop->c_lflag |= ISIG;
425 #endif
426
427   tiop->c_cc[VMIN] = 1;
428   tiop->c_cc[VTIME] = 0;
429
430   /* Turn off characters that we need on Posix systems with job control,
431      just to be sure.  This includes ^Y and ^V.  This should not really
432      be necessary.  */
433 #if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE)
434
435 #if defined (VLNEXT)
436   tiop->c_cc[VLNEXT] = _POSIX_VDISABLE;
437 #endif
438
439 #if defined (VDSUSP)
440   tiop->c_cc[VDSUSP] = _POSIX_VDISABLE;
441 #endif
442
443 #endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */
444 }
445 #endif /* !defined (NEW_TTY_DRIVER) && !defined(_GO32_) */
446
447 /* Put the terminal in CBREAK mode so that we can detect key presses. */
448 void
449 rl_prep_terminal (meta_flag)
450      int meta_flag;
451 {
452 #if !defined (_GO32_)
453   int tty = fileno (rl_instream);
454   TIOTYPE tio;
455
456   if (terminal_prepped)
457     return;
458
459   /* Try to keep this function from being INTerrupted. */
460   block_sigint ();
461
462   if (get_tty_settings (tty, &tio) < 0)
463     {
464       release_sigint ();
465       return;
466     }
467
468   otio = tio;
469
470   prepare_terminal_settings (meta_flag, otio, &tio);
471
472   if (set_tty_settings (tty, &tio) < 0)
473     {
474       release_sigint ();
475       return;
476     }
477
478   control_meta_key (1);
479   terminal_prepped = 1;
480
481   release_sigint ();
482 #endif /* !_GO32_ */
483 }
484
485 /* Restore the terminal's normal settings and modes. */
486 void
487 rl_deprep_terminal ()
488 {
489 #if !defined (_GO32_)
490   int tty = fileno (rl_instream);
491
492   if (!terminal_prepped)
493     return;
494
495   /* Try to keep this function from being INTerrupted. */
496   block_sigint ();
497
498   if (set_tty_settings (tty, &otio) < 0)
499     {
500       release_sigint ();
501       return;
502     }
503
504   control_meta_key (0);
505   terminal_prepped = 0;
506
507   release_sigint ();
508 #endif /* !_GO32_ */
509 }
510 \f
511 /* **************************************************************** */
512 /*                                                                  */
513 /*                      Bogus Flow Control                          */
514 /*                                                                  */
515 /* **************************************************************** */
516
517 rl_restart_output (count, key)
518      int count, key;
519 {
520   int fildes = fileno (rl_outstream);
521 #if defined (TIOCSTART)
522 #if defined (apollo)
523   ioctl (&fildes, TIOCSTART, 0);
524 #else
525   ioctl (fildes, TIOCSTART, 0);
526 #endif /* apollo */
527
528 #else /* !TIOCSTART */
529 #  if defined (TERMIOS_TTY_DRIVER)
530 #    if defined (__ksr1__)
531   if (ksrflow)
532     {
533       ksrflow = 0;
534       tcflow (fildes, TCOON);
535     }
536 #    else /* !ksr1 */
537   tcflow (fildes, TCOON);               /* Simulate a ^Q. */
538 #    endif /* !ksr1 */
539 #  else /* !TERMIOS_TTY_DRIVER */
540 #    if defined (TCXONC)
541   ioctl (fildes, TCXONC, TCOON);
542 #    endif /* TCXONC */
543 #  endif /* !TERMIOS_TTY_DRIVER */
544 #endif /* !TIOCSTART */
545 }
546
547 rl_stop_output (count, key)
548      int count, key;
549 {
550   int fildes = fileno (rl_instream);
551
552 #if defined (TIOCSTOP)
553 # if defined (apollo)
554   ioctl (&fildes, TIOCSTOP, 0);
555 # else
556   ioctl (fildes, TIOCSTOP, 0);
557 # endif /* apollo */
558 #else /* !TIOCSTOP */
559 # if defined (TERMIOS_TTY_DRIVER)
560 #  if defined (__ksr1__)
561   ksrflow = 1;
562 #  endif /* ksr1 */
563   tcflow (fildes, TCOOFF);
564 # else
565 #   if defined (TCXONC)
566   ioctl (fildes, TCXONC, TCOON);
567 #   endif /* TCXONC */
568 # endif /* !TERMIOS_TTY_DRIVER */
569 #endif /* !TIOCSTOP */
570 }
571 \f
572 /* **************************************************************** */
573 /*                                                                  */
574 /*                      Default Key Bindings                        */
575 /*                                                                  */
576 /* **************************************************************** */
577 void
578 rltty_set_default_bindings (kmap)
579      Keymap kmap;
580 {
581   TIOTYPE ttybuff;
582   int tty = fileno (rl_instream);
583
584 #if defined (NEW_TTY_DRIVER)
585
586   if (get_tty_settings (tty, &ttybuff) == 0)
587     {
588       if (ttybuff.flags & SGTTY_SET)
589         {
590           int erase, kill;
591
592           erase = ttybuff.sgttyb.sg_erase;
593           kill  = ttybuff.sgttyb.sg_kill;
594
595           if (erase != -1 && kmap[erase].type == ISFUNC)
596             kmap[erase].function = rl_rubout;
597
598           if (kill != -1 && kmap[kill].type == ISFUNC)
599             kmap[kill].function = rl_unix_line_discard;
600         }
601
602 #  if defined (TIOCGLTC)
603
604       if (ttybuff.flags & LTCHARS_SET)
605         {
606           int werase, nextc;
607
608           werase = ttybuff.ltchars.t_werasc;
609           nextc = ttybuff.ltchars.t_lnextc;
610
611           if (werase != -1 && kmap[werase].type == ISFUNC)
612             kmap[werase].function = rl_unix_word_rubout;
613
614           if (nextc != -1 && kmap[nextc].type == ISFUNC)
615             kmap[nextc].function = rl_quoted_insert;
616         }
617     }
618 #  endif /* TIOCGLTC */
619
620 #else /* !NEW_TTY_DRIVER */
621
622   if (get_tty_settings (tty, &ttybuff) == 0)
623     {
624       unsigned char erase, kill;
625
626       erase = ttybuff.c_cc[VERASE];
627       kill = ttybuff.c_cc[VKILL];
628
629       if (erase != (unsigned char)_POSIX_VDISABLE &&
630           kmap[erase].type == ISFUNC)
631         kmap[erase].function = rl_rubout;
632
633       if (kill != (unsigned char)_POSIX_VDISABLE &&
634           kmap[kill].type == ISFUNC)
635         kmap[kill].function = rl_unix_line_discard;
636
637 #  if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
638       {
639         unsigned char nextc;
640
641         nextc = ttybuff.c_cc[VLNEXT];
642
643         if (nextc != (unsigned char)_POSIX_VDISABLE &&
644             kmap[nextc].type == ISFUNC)
645           kmap[nextc].function = rl_quoted_insert;
646       }
647 #  endif /* VLNEXT && TERMIOS_TTY_DRIVER */
648
649 #  if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
650       {
651         unsigned char werase;
652
653         werase = ttybuff.c_cc[VWERASE];
654
655         if (werase != (unsigned char)_POSIX_VDISABLE &&
656             kmap[werase].type == ISFUNC)
657           kmap[werase].function = rl_unix_word_rubout;
658       }
659 #  endif /* VWERASE && TERMIOS_TTY_DRIVER */
660     }
661 #endif /* !NEW_TTY_DRIVER */
662 }