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