Import less-436.
[dragonfly.git] / contrib / less / signal.c
CommitLineData
131ccf9c 1/*
a9adbba3 2 * Copyright (C) 1984-2009 Mark Nudelman
131ccf9c
PA
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 */
28public int sigs;
29
30extern int sc_width, sc_height;
31extern int screen_trashed;
32extern int lnloop;
33extern int linenums;
34extern int wscroll;
35extern int reading;
36extern int quit_on_intr;
37extern long jump_sline_fraction;
38
39/*
40 * Interrupt signal handler.
41 */
42 /* ARGSUSED*/
43 static RETSIGTYPE
44u_interrupt(type)
45 int type;
46{
8be36e5b 47 bell();
131ccf9c
PA
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)
8be36e5b 63 intread(); /* May longjmp */
131ccf9c
PA
64}
65
66#ifdef SIGTSTP
67/*
68 * "Stop" (^Z) signal handler.
69 */
70 /* ARGSUSED*/
71 static RETSIGTYPE
72stop(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
88winch(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
103winch(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
121wbreak_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
141init_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
194psignals()
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();
a9adbba3 247 calc_shift_count();
131ccf9c
PA
248 screen_trashed = 1;
249 }
250 }
251#endif
252 if (tsignals & S_INTERRUPT)
253 {
254 if (quit_on_intr)
255 quit(QUIT_OK);
131ccf9c
PA
256 }
257}