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