Upgrade to less version 403.
[dragonfly.git] / contrib / less-394 / signal.c
1 /*
2  * Copyright (C) 1984-2004  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
38 /*
39  * Interrupt signal handler.
40  */
41         /* ARGSUSED*/
42         static RETSIGTYPE
43 u_interrupt(type)
44         int type;
45 {
46 #if OS2
47         LSIGNAL(SIGINT, SIG_ACK);
48 #endif
49         LSIGNAL(SIGINT, u_interrupt);
50         sigs |= S_INTERRUPT;
51 #if MSDOS_COMPILER==DJGPPC
52         /*
53          * If a keyboard has been hit, it must be Ctrl-C
54          * (as opposed to Ctrl-Break), so consume it.
55          * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.)
56          */
57         if (kbhit())
58                 getkey();
59 #endif
60         if (reading)
61                 intread();
62 }
63
64 #ifdef SIGTSTP
65 /*
66  * "Stop" (^Z) signal handler.
67  */
68         /* ARGSUSED*/
69         static RETSIGTYPE
70 stop(type)
71         int type;
72 {
73         LSIGNAL(SIGTSTP, stop);
74         sigs |= S_STOP;
75         if (reading)
76                 intread();
77 }
78 #endif
79
80 #ifdef SIGWINCH
81 /*
82  * "Window" change handler
83  */
84         /* ARGSUSED*/
85         public RETSIGTYPE
86 winch(type)
87         int type;
88 {
89         LSIGNAL(SIGWINCH, winch);
90         sigs |= S_WINCH;
91         if (reading)
92                 intread();
93 }
94 #else
95 #ifdef SIGWIND
96 /*
97  * "Window" change handler
98  */
99         /* ARGSUSED*/
100         public RETSIGTYPE
101 winch(type)
102         int type;
103 {
104         LSIGNAL(SIGWIND, winch);
105         sigs |= S_WINCH;
106         if (reading)
107                 intread();
108 }
109 #endif
110 #endif
111
112 #if MSDOS_COMPILER==WIN32C
113 /*
114  * Handle CTRL-C and CTRL-BREAK keys.
115  */
116 #include "windows.h"
117
118         static BOOL WINAPI 
119 wbreak_handler(dwCtrlType)
120         DWORD dwCtrlType;
121 {
122         switch (dwCtrlType)
123         {
124         case CTRL_C_EVENT:
125         case CTRL_BREAK_EVENT:
126                 sigs |= S_INTERRUPT;
127                 return (TRUE);
128         default:
129                 break;
130         }
131         return (FALSE);
132 }
133 #endif
134
135 /*
136  * Set up the signal handlers.
137  */
138         public void
139 init_signals(on)
140         int on;
141 {
142         if (on)
143         {
144                 /*
145                  * Set signal handlers.
146                  */
147                 (void) LSIGNAL(SIGINT, u_interrupt);
148 #if MSDOS_COMPILER==WIN32C
149                 SetConsoleCtrlHandler(wbreak_handler, TRUE);
150 #endif
151 #ifdef SIGTSTP
152                 (void) LSIGNAL(SIGTSTP, stop);
153 #endif
154 #ifdef SIGWINCH
155                 (void) LSIGNAL(SIGWINCH, winch);
156 #else
157 #ifdef SIGWIND
158                 (void) LSIGNAL(SIGWIND, winch);
159 #endif
160 #ifdef SIGQUIT
161                 (void) LSIGNAL(SIGQUIT, SIG_IGN);
162 #endif
163 #endif
164         } else
165         {
166                 /*
167                  * Restore signals to defaults.
168                  */
169                 (void) LSIGNAL(SIGINT, SIG_DFL);
170 #if MSDOS_COMPILER==WIN32C
171                 SetConsoleCtrlHandler(wbreak_handler, FALSE);
172 #endif
173 #ifdef SIGTSTP
174                 (void) LSIGNAL(SIGTSTP, SIG_DFL);
175 #endif
176 #ifdef SIGWINCH
177                 (void) LSIGNAL(SIGWINCH, SIG_IGN);
178 #endif
179 #ifdef SIGWIND
180                 (void) LSIGNAL(SIGWIND, SIG_IGN);
181 #endif
182 #ifdef SIGQUIT
183                 (void) LSIGNAL(SIGQUIT, SIG_DFL);
184 #endif
185         }
186 }
187
188 /*
189  * Process any signals we have received.
190  * A received signal cause a bit to be set in "sigs".
191  */
192         public void
193 psignals()
194 {
195         register int tsignals;
196
197         if ((tsignals = sigs) == 0)
198                 return;
199         sigs = 0;
200
201 #ifdef SIGTSTP
202         if (tsignals & S_STOP)
203         {
204                 /*
205                  * Clean up the terminal.
206                  */
207 #ifdef SIGTTOU
208                 LSIGNAL(SIGTTOU, SIG_IGN);
209 #endif
210                 clear_bot();
211                 deinit();
212                 flush();
213                 raw_mode(0);
214 #ifdef SIGTTOU
215                 LSIGNAL(SIGTTOU, SIG_DFL);
216 #endif
217                 LSIGNAL(SIGTSTP, SIG_DFL);
218                 kill(getpid(), SIGTSTP);
219                 /*
220                  * ... Bye bye. ...
221                  * Hopefully we'll be back later and resume here...
222                  * Reset the terminal and arrange to repaint the
223                  * screen when we get back to the main command loop.
224                  */
225                 LSIGNAL(SIGTSTP, stop);
226                 raw_mode(1);
227                 init();
228                 screen_trashed = 1;
229                 tsignals |= S_WINCH;
230         }
231 #endif
232 #ifdef S_WINCH
233         if (tsignals & S_WINCH)
234         {
235                 int old_width, old_height;
236                 /*
237                  * Re-execute scrsize() to read the new window size.
238                  */
239                 old_width = sc_width;
240                 old_height = sc_height;
241                 get_term();
242                 if (sc_width != old_width || sc_height != old_height)
243                 {
244                         wscroll = (sc_height + 1) / 2;
245                         screen_trashed = 1;
246                 }
247         }
248 #endif
249         if (tsignals & S_INTERRUPT)
250         {
251                 if (quit_on_intr)
252                         quit(QUIT_OK);
253                 bell();
254                 /*
255                  * {{ You may wish to replace the bell() with 
256                  *    error("Interrupt", NULL_PARG); }}
257                  */
258
259                 /*
260                  * If we were interrupted while in the "calculating 
261                  * line numbers" loop, turn off line numbers.
262                  */
263                 if (lnloop)
264                 {
265                         lnloop = 0;
266                         if (linenums == 2)
267                                 screen_trashed = 1;
268                         linenums = 0;
269                         error("Line numbers turned off", NULL_PARG);
270                 }
271
272         }
273 }