Merge from vendor branch LIBSTDC++:
[dragonfly.git] / contrib / texinfo / info / signals.c
1 /* signals.c -- install and maintain Info signal handlers.
2    $Id: signals.c,v 1.6 1998/12/06 22:00:04 karl Exp $
3    $FreeBSD: src/contrib/texinfo/info/signals.c,v 1.6 2000/01/17 10:46:55 ru Exp $
4    $DragonFly: src/contrib/texinfo/info/Attic/signals.c,v 1.2 2003/06/17 04:24:07 dillon Exp $
5
6    Copyright (C) 1993, 94, 95, 98 Free Software Foundation, Inc.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2, or (at your option)
11    any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22    Written by Brian Fox (bfox@ai.mit.edu). */
23
24 #include "info.h"
25 #include "signals.h"
26
27 /* **************************************************************** */
28 /*                                                                  */
29 /*              Pretending That We Have POSIX Signals               */
30 /*                                                                  */
31 /* **************************************************************** */
32
33 /* Non-zero when our signal handler has been called to handle SIGWINCH. */
34 static int in_sigwinch = 0;
35
36 #if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK)
37 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
38 static void
39 sigprocmask (operation, newset, oldset)
40      int operation, *newset, *oldset;
41 {
42   switch (operation)
43     {
44     case SIG_UNBLOCK:
45       sigsetmask (sigblock (0) & ~(*newset));
46       break;
47
48     case SIG_BLOCK:
49       *oldset = sigblock (*newset);
50       break;
51
52     case SIG_SETMASK:
53       sigsetmask (*newset);
54       break;
55
56     default:
57       abort ();
58     }
59 }
60 #endif /* !HAVE_SIGPROCMASK && HAVE_SIGSETMASK */
61
62 /* **************************************************************** */
63 /*                                                                  */
64 /*                  Signal Handling for Info                        */
65 /*                                                                  */
66 /* **************************************************************** */
67
68 typedef RETSIGTYPE signal_handler ();
69
70 static RETSIGTYPE info_signal_handler ();
71 static signal_handler *old_TSTP, *old_TTOU, *old_TTIN;
72 static signal_handler *old_WINCH, *old_INT, *old_USR1, *old_CONT;
73
74 void
75 initialize_info_signal_handler ()
76 {
77 #if defined (SIGTSTP)
78   old_TSTP = (signal_handler *) signal (SIGTSTP, info_signal_handler);
79   old_TTOU = (signal_handler *) signal (SIGTTOU, info_signal_handler);
80   old_TTIN = (signal_handler *) signal (SIGTTIN, info_signal_handler);
81 #endif /* SIGTSTP */
82
83 #if defined (SIGWINCH)
84   old_WINCH = (signal_handler *) signal (SIGWINCH, info_signal_handler);
85 #if defined (SIGCONT)
86   old_CONT = (signal_handler *) signal (SIGCONT, info_signal_handler);
87 #endif
88 #endif
89
90 #if defined (SIGINT)
91   old_INT = (signal_handler *) signal (SIGINT, info_signal_handler);
92 #endif
93
94 #if defined (SIGUSR1)
95   /* Used by DJGPP to simulate SIGTSTP on Ctrl-Z.  */
96   old_USR1 = (signal_handler *) signal (SIGUSR1, info_signal_handler);
97 #endif
98 }
99
100 static void
101 redisplay_after_signal ()
102 {
103   terminal_clear_screen ();
104   display_clear_display (the_display);
105   window_mark_chain (windows, W_UpdateWindow);
106   display_update_display (windows);
107   display_cursor_at_point (active_window);
108   fflush (stdout);
109 }
110
111 static void
112 reset_info_window_sizes ()
113 {
114   terminal_goto_xy (0, 0);
115   fflush (stdout);
116   terminal_unprep_terminal ();
117   terminal_get_screen_size ();
118   terminal_prep_terminal ();
119   display_initialize_display (screenwidth, screenheight);
120   window_new_screen_size (screenwidth, screenheight, NULL);
121   redisplay_after_signal ();
122 }
123
124 static RETSIGTYPE
125 info_signal_handler (sig)
126      int sig;
127 {
128   signal_handler **old_signal_handler;
129
130   switch (sig)
131     {
132 #if defined (SIGTSTP)
133     case SIGTSTP:
134     case SIGTTOU:
135     case SIGTTIN:
136 #endif
137 #if defined (SIGINT)
138     case SIGINT:
139 #endif
140       {
141 #if defined (SIGTSTP)
142         if (sig == SIGTSTP)
143           old_signal_handler = &old_TSTP;
144         if (sig == SIGTTOU)
145           old_signal_handler = &old_TTOU;
146         if (sig == SIGTTIN)
147           old_signal_handler = &old_TTIN;
148 #endif /* SIGTSTP */
149         if (sig == SIGINT)
150           old_signal_handler = &old_INT;
151
152         /* For stop signals, restore the terminal IO, leave the cursor
153            at the bottom of the window, and stop us. */
154         terminal_goto_xy (0, screenheight - 1);
155         terminal_clear_to_eol ();
156         fflush (stdout);
157         terminal_unprep_terminal ();
158         signal (sig, *old_signal_handler);
159         UNBLOCK_SIGNAL (sig);
160         kill (getpid (), sig);
161
162         /* The program is returning now.  Restore our signal handler,
163            turn on terminal handling, redraw the screen, and place the
164            cursor where it belongs. */
165         terminal_prep_terminal ();
166         *old_signal_handler = (signal_handler *) signal (sig, info_signal_handler);
167         redisplay_after_signal ();
168         fflush (stdout);
169       }
170       break;
171
172 #if defined (SIGWINCH) || defined (SIGUSR1)
173 #ifdef SIGWINCH
174 #ifdef SIGCONT
175     case SIGCONT:
176       /* pretend a SIGWINCH in case the terminal window size has changed
177          while we've been asleep */
178       /* FALLTHROUGH */
179 #endif
180     case SIGWINCH:
181 #endif
182 #ifdef SIGUSR1
183     case SIGUSR1:
184 #endif
185       {
186         if (!in_sigwinch) {
187           in_sigwinch++;
188           
189           /* Turn off terminal IO, tell our parent that the window has changed,
190              then reinitialize the terminal and rebuild our windows. */
191 #ifdef SIGWINCH
192           if (sig == SIGWINCH)
193             old_signal_handler = &old_WINCH;
194 #ifdef SIGCONT
195           else if (sig == SIGCONT)
196             old_signal_handler = &old_CONT;
197 #endif
198 #endif
199 #ifdef SIGUSR1
200           if (sig == SIGUSR1)
201             old_signal_handler = &old_USR1;
202 #endif
203           terminal_goto_xy (0, 0);
204           fflush (stdout);
205           terminal_unprep_terminal ();
206           signal (sig, *old_signal_handler);
207           UNBLOCK_SIGNAL (sig);
208           kill (getpid (), sig);
209
210           /* After our old signal handler returns... */
211           *old_signal_handler
212             = (signal_handler *) signal (sig, info_signal_handler);
213           terminal_prep_terminal ();
214           reset_info_window_sizes ();
215           in_sigwinch--;
216         }
217       }
218       break;
219 #endif /* SIGWINCH || SIGUSR1 */
220     }
221 }