0fbaf7e6fdd04a32fa7342add5117c259c420b57
[dragonfly.git] / contrib / less / signal.c
1 /*
2  * Copyright (C) 1984-2011  Mark Nudelman
3  *
4  * You may distribute under the terms of either the GNU General Public
5  * License or the Less License, as specified in the README file.
6  *
7  * For more information about less, or for information on how to 
8  * contact the author, see the README file.
9  */
10
11
12 /*
13  * Routines dealing with signals.
14  *
15  * A signal usually merely causes a bit to be set in the "signals" word.
16  * At some convenient time, the mainline code checks to see if any
17  * signals need processing by calling psignal().
18  * If we happen to be reading from a file [in iread()] at the time
19  * the signal is received, we call intread to interrupt the iread.
20  */
21
22 #include "less.h"
23 #include <signal.h>
24
25 /*
26  * "sigs" contains bits indicating signals which need to be processed.
27  */
28 public int sigs;
29
30 extern int sc_width, sc_height;
31 extern int screen_trashed;
32 extern int lnloop;
33 extern int linenums;
34 extern int wscroll;
35 extern int reading;
36 extern int quit_on_intr;
37 extern long jump_sline_fraction;
38
39 /*
40  * Interrupt signal handler.
41  */
42         /* ARGSUSED*/
43         static RETSIGTYPE
44 u_interrupt(type)
45         int type;
46 {
47         bell();
48 #if OS2
49         LSIGNAL(SIGINT, SIG_ACK);
50 #endif
51         LSIGNAL(SIGINT, u_interrupt);
52         sigs |= S_INTERRUPT;
53 #if MSDOS_COMPILER==DJGPPC
54         /*
55          * If a keyboard has been hit, it must be Ctrl-C
56          * (as opposed to Ctrl-Break), so consume it.
57          * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.)
58          */
59         if (kbhit())
60                 getkey();
61 #endif
62         if (reading)
63                 intread(); /* May longjmp */
64 }
65
66 #ifdef SIGTSTP
67 /*
68  * "Stop" (^Z) signal handler.
69  */
70         /* ARGSUSED*/
71         static RETSIGTYPE
72 stop(type)
73         int type;
74 {
75         LSIGNAL(SIGTSTP, stop);
76         sigs |= S_STOP;
77         if (reading)
78                 intread();
79 }
80 #endif
81
82 #ifdef SIGWINCH
83 /*
84  * "Window" change handler
85  */
86         /* ARGSUSED*/
87         public RETSIGTYPE
88 winch(type)
89         int type;
90 {
91         LSIGNAL(SIGWINCH, winch);
92         sigs |= S_WINCH;
93         if (reading)
94                 intread();
95 }
96 #else
97 #ifdef SIGWIND
98 /*
99  * "Window" change handler
100  */
101         /* ARGSUSED*/
102         public RETSIGTYPE
103 winch(type)
104         int type;
105 {
106         LSIGNAL(SIGWIND, winch);
107         sigs |= S_WINCH;
108         if (reading)
109                 intread();
110 }
111 #endif
112 #endif
113
114 #if MSDOS_COMPILER==WIN32C
115 /*
116  * Handle CTRL-C and CTRL-BREAK keys.
117  */
118 #include "windows.h"
119
120         static BOOL WINAPI 
121 wbreak_handler(dwCtrlType)
122         DWORD dwCtrlType;
123 {
124         switch (dwCtrlType)
125         {
126         case CTRL_C_EVENT:
127         case CTRL_BREAK_EVENT:
128                 sigs |= S_INTERRUPT;
129                 return (TRUE);
130         default:
131                 break;
132         }
133         return (FALSE);
134 }
135 #endif
136
137 /*
138  * Set up the signal handlers.
139  */
140         public void
141 init_signals(on)
142         int on;
143 {
144         if (on)
145         {
146                 /*
147                  * Set signal handlers.
148                  */
149                 (void) LSIGNAL(SIGINT, u_interrupt);
150 #if MSDOS_COMPILER==WIN32C
151                 SetConsoleCtrlHandler(wbreak_handler, TRUE);
152 #endif
153 #ifdef SIGTSTP
154                 (void) LSIGNAL(SIGTSTP, stop);
155 #endif
156 #ifdef SIGWINCH
157                 (void) LSIGNAL(SIGWINCH, winch);
158 #endif
159 #ifdef SIGWIND
160                 (void) LSIGNAL(SIGWIND, winch);
161 #endif
162 #ifdef SIGQUIT
163                 (void) LSIGNAL(SIGQUIT, SIG_IGN);
164 #endif
165         } else
166         {
167                 /*
168                  * Restore signals to defaults.
169                  */
170                 (void) LSIGNAL(SIGINT, SIG_DFL);
171 #if MSDOS_COMPILER==WIN32C
172                 SetConsoleCtrlHandler(wbreak_handler, FALSE);
173 #endif
174 #ifdef SIGTSTP
175                 (void) LSIGNAL(SIGTSTP, SIG_DFL);
176 #endif
177 #ifdef SIGWINCH
178                 (void) LSIGNAL(SIGWINCH, SIG_IGN);
179 #endif
180 #ifdef SIGWIND
181                 (void) LSIGNAL(SIGWIND, SIG_IGN);
182 #endif
183 #ifdef SIGQUIT
184                 (void) LSIGNAL(SIGQUIT, SIG_DFL);
185 #endif
186         }
187 }
188
189 /*
190  * Process any signals we have received.
191  * A received signal cause a bit to be set in "sigs".
192  */
193         public void
194 psignals()
195 {
196         register int tsignals;
197
198         if ((tsignals = sigs) == 0)
199                 return;
200         sigs = 0;
201
202 #ifdef SIGTSTP
203         if (tsignals & S_STOP)
204         {
205                 /*
206                  * Clean up the terminal.
207                  */
208 #ifdef SIGTTOU
209                 LSIGNAL(SIGTTOU, SIG_IGN);
210 #endif
211                 clear_bot();
212                 deinit();
213                 flush();
214                 raw_mode(0);
215 #ifdef SIGTTOU
216                 LSIGNAL(SIGTTOU, SIG_DFL);
217 #endif
218                 LSIGNAL(SIGTSTP, SIG_DFL);
219                 kill(getpid(), SIGTSTP);
220                 /*
221                  * ... Bye bye. ...
222                  * Hopefully we'll be back later and resume here...
223                  * Reset the terminal and arrange to repaint the
224                  * screen when we get back to the main command loop.
225                  */
226                 LSIGNAL(SIGTSTP, stop);
227                 raw_mode(1);
228                 init();
229                 screen_trashed = 1;
230                 tsignals |= S_WINCH;
231         }
232 #endif
233 #ifdef S_WINCH
234         if (tsignals & S_WINCH)
235         {
236                 int old_width, old_height;
237                 /*
238                  * Re-execute scrsize() to read the new window size.
239                  */
240                 old_width = sc_width;
241                 old_height = sc_height;
242                 get_term();
243                 if (sc_width != old_width || sc_height != old_height)
244                 {
245                         wscroll = (sc_height + 1) / 2;
246                         calc_jump_sline();
247                         calc_shift_count();
248                         screen_trashed = 1;
249                 }
250         }
251 #endif
252         if (tsignals & S_INTERRUPT)
253         {
254                 if (quit_on_intr)
255                         quit(QUIT_INTERRUPT);
256         }
257 }