signals.c revision 21495
1/* signals.c -- Install and maintain Info signal handlers. */
2
3/* This file is part of GNU Info, a program for reading online documentation
4   stored in Info format.
5
6   Copyright (C) 1993, 1994, 1995 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#if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK)
34/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
35static void
36sigprocmask (operation, newset, oldset)
37     int operation, *newset, *oldset;
38{
39  switch (operation)
40    {
41    case SIG_UNBLOCK:
42      sigsetmask (sigblock (0) & ~(*newset));
43      break;
44
45    case SIG_BLOCK:
46      *oldset = sigblock (*newset);
47      break;
48
49    case SIG_SETMASK:
50      sigsetmask (*newset);
51      break;
52
53    default:
54      abort ();
55    }
56}
57#endif /* !HAVE_SIGPROCMASK && HAVE_SIGSETMASK */
58
59/* **************************************************************** */
60/*								    */
61/*		    Signal Handling for Info			    */
62/*								    */
63/* **************************************************************** */
64
65typedef void SigHandlerType;
66typedef SigHandlerType SigHandler ();
67
68static SigHandlerType info_signal_handler ();
69static SigHandler *old_TSTP, *old_TTOU, *old_TTIN;
70static SigHandler *old_WINCH, *old_INT;
71
72void
73initialize_info_signal_handler ()
74{
75#if defined (SIGTSTP)
76  old_TSTP = (SigHandler *) signal (SIGTSTP, info_signal_handler);
77  old_TTOU = (SigHandler *) signal (SIGTTOU, info_signal_handler);
78  old_TTIN = (SigHandler *) signal (SIGTTIN, info_signal_handler);
79#endif /* SIGTSTP */
80
81#if defined (SIGWINCH)
82  old_WINCH = (SigHandler *) signal (SIGWINCH, info_signal_handler);
83#endif
84
85#if defined (SIGINT)
86  old_INT = (SigHandler *) signal (SIGINT, info_signal_handler);
87#endif
88}
89
90static void
91redisplay_after_signal ()
92{
93  terminal_clear_screen ();
94  display_clear_display (the_display);
95  window_mark_chain (windows, W_UpdateWindow);
96  display_update_display (windows);
97  display_cursor_at_point (active_window);
98  fflush (stdout);
99}
100
101static SigHandlerType
102info_signal_handler (sig)
103     int sig;
104{
105  SigHandler **old_signal_handler;
106
107  switch (sig)
108    {
109#if defined (SIGTSTP)
110    case SIGTSTP:
111    case SIGTTOU:
112    case SIGTTIN:
113#endif
114#if defined (SIGINT)
115    case SIGINT:
116#endif
117      {
118#if defined (SIGTSTP)
119	if (sig == SIGTSTP)
120	  old_signal_handler = &old_TSTP;
121	if (sig == SIGTTOU)
122	  old_signal_handler = &old_TTOU;
123	if (sig == SIGTTIN)
124	  old_signal_handler = &old_TTIN;
125#endif /* SIGTSTP */
126	if (sig == SIGINT)
127	  old_signal_handler = &old_INT;
128
129	/* For stop signals, restore the terminal IO, leave the cursor
130	   at the bottom of the window, and stop us. */
131	terminal_goto_xy (0, screenheight - 1);
132	terminal_clear_to_eol ();
133	fflush (stdout);
134	terminal_unprep_terminal ();
135	signal (sig, *old_signal_handler);
136 	UNBLOCK_SIGNAL (sig);
137	kill (getpid (), sig);
138
139	/* The program is returning now.  Restore our signal handler,
140	   turn on terminal handling, redraw the screen, and place the
141	   cursor where it belongs. */
142	terminal_prep_terminal ();
143	*old_signal_handler = (SigHandler *) signal (sig, info_signal_handler);
144	redisplay_after_signal ();
145	fflush (stdout);
146      }
147      break;
148
149#if defined (SIGWINCH)
150    case SIGWINCH:
151      {
152	/* Turn off terminal IO, tell our parent that the window has changed,
153	   then reinitialize the terminal and rebuild our windows. */
154	old_signal_handler = &old_WINCH;
155	terminal_goto_xy (0, 0);
156	fflush (stdout);
157	terminal_unprep_terminal ();
158	signal (sig, *old_signal_handler);
159 	UNBLOCK_SIGNAL (sig);
160	kill (getpid (), sig);
161
162	/* After our old signal handler returns... */
163	terminal_get_screen_size ();
164	terminal_prep_terminal ();
165	display_initialize_display (screenwidth, screenheight);
166	window_new_screen_size (screenwidth, screenheight, (VFunction *)NULL);
167	*old_signal_handler = (SigHandler *) signal (sig, info_signal_handler);
168	redisplay_after_signal ();
169      }
170      break;
171#endif /* SIGWINCH */
172    }
173}
174