]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/less/signal.c
This commit was generated by cvs2svn to compensate for changes in r165009,
[FreeBSD/FreeBSD.git] / contrib / less / 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 /* $FreeBSD$ */
12
13 /*
14  * Routines dealing with signals.
15  *
16  * A signal usually merely causes a bit to be set in the "signals" word.
17  * At some convenient time, the mainline code checks to see if any
18  * signals need processing by calling psignal().
19  * If we happen to be reading from a file [in iread()] at the time
20  * the signal is received, we call intread to interrupt the iread.
21  */
22
23 #include "less.h"
24 #include <signal.h>
25
26 /*
27  * "sigs" contains bits indicating signals which need to be processed.
28  */
29 public int sigs;
30
31 extern int sc_width, sc_height;
32 extern int screen_trashed;
33 extern int lnloop;
34 extern int linenums;
35 extern int wscroll;
36 extern int reading;
37 extern int quit_on_intr;
38 extern int more_mode;
39
40 /*
41  * Interrupt signal handler.
42  */
43         /* ARGSUSED*/
44         static RETSIGTYPE
45 u_interrupt(type)
46         int type;
47 {
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 (more_mode)
63                 quit(0);
64         if (reading)
65                 intread();
66 }
67
68 #ifdef SIGTSTP
69 /*
70  * "Stop" (^Z) signal handler.
71  */
72         /* ARGSUSED*/
73         static RETSIGTYPE
74 stop(type)
75         int type;
76 {
77         LSIGNAL(SIGTSTP, stop);
78         sigs |= S_STOP;
79         if (reading)
80                 intread();
81 }
82 #endif
83
84 #ifdef SIGWINCH
85 /*
86  * "Window" change handler
87  */
88         /* ARGSUSED*/
89         public RETSIGTYPE
90 winch(type)
91         int type;
92 {
93         LSIGNAL(SIGWINCH, winch);
94         sigs |= S_WINCH;
95         if (reading)
96                 intread();
97 }
98 #else
99 #ifdef SIGWIND
100 /*
101  * "Window" change handler
102  */
103         /* ARGSUSED*/
104         public RETSIGTYPE
105 winch(type)
106         int type;
107 {
108         LSIGNAL(SIGWIND, winch);
109         sigs |= S_WINCH;
110         if (reading)
111                 intread();
112 }
113 #endif
114 #endif
115
116 #if MSDOS_COMPILER==WIN32C
117 /*
118  * Handle CTRL-C and CTRL-BREAK keys.
119  */
120 #include "windows.h"
121
122         static BOOL WINAPI 
123 wbreak_handler(dwCtrlType)
124         DWORD dwCtrlType;
125 {
126         switch (dwCtrlType)
127         {
128         case CTRL_C_EVENT:
129         case CTRL_BREAK_EVENT:
130                 sigs |= S_INTERRUPT;
131                 return (TRUE);
132         default:
133                 break;
134         }
135         return (FALSE);
136 }
137 #endif
138
139 /*
140  * Set up the signal handlers.
141  */
142         public void
143 init_signals(on)
144         int on;
145 {
146         if (on)
147         {
148                 /*
149                  * Set signal handlers.
150                  */
151                 (void) LSIGNAL(SIGINT, u_interrupt);
152 #if MSDOS_COMPILER==WIN32C
153                 SetConsoleCtrlHandler(wbreak_handler, TRUE);
154 #endif
155 #ifdef SIGTSTP
156                 (void) LSIGNAL(SIGTSTP, stop);
157 #endif
158 #ifdef SIGWINCH
159                 (void) LSIGNAL(SIGWINCH, winch);
160 #else
161 #ifdef SIGWIND
162                 (void) LSIGNAL(SIGWIND, winch);
163 #endif
164 #ifdef SIGQUIT
165                 (void) LSIGNAL(SIGQUIT, SIG_IGN);
166 #endif
167 #endif
168         } else
169         {
170                 /*
171                  * Restore signals to defaults.
172                  */
173                 (void) LSIGNAL(SIGINT, SIG_DFL);
174 #if MSDOS_COMPILER==WIN32C
175                 SetConsoleCtrlHandler(wbreak_handler, FALSE);
176 #endif
177 #ifdef SIGTSTP
178                 (void) LSIGNAL(SIGTSTP, SIG_DFL);
179 #endif
180 #ifdef SIGWINCH
181                 (void) LSIGNAL(SIGWINCH, SIG_IGN);
182 #endif
183 #ifdef SIGWIND
184                 (void) LSIGNAL(SIGWIND, SIG_IGN);
185 #endif
186 #ifdef SIGQUIT
187                 (void) LSIGNAL(SIGQUIT, SIG_DFL);
188 #endif
189         }
190 }
191
192 /*
193  * Process any signals we have received.
194  * A received signal cause a bit to be set in "sigs".
195  */
196         public void
197 psignals()
198 {
199         register int tsignals;
200
201         if ((tsignals = sigs) == 0)
202                 return;
203         sigs = 0;
204
205 #ifdef SIGTSTP
206         if (tsignals & S_STOP)
207         {
208                 /*
209                  * Clean up the terminal.
210                  */
211 #ifdef SIGTTOU
212                 LSIGNAL(SIGTTOU, SIG_IGN);
213 #endif
214                 clear_bot();
215                 deinit();
216                 flush();
217                 raw_mode(0);
218 #ifdef SIGTTOU
219                 LSIGNAL(SIGTTOU, SIG_DFL);
220 #endif
221                 LSIGNAL(SIGTSTP, SIG_DFL);
222                 kill(getpid(), SIGTSTP);
223                 /*
224                  * ... Bye bye. ...
225                  * Hopefully we'll be back later and resume here...
226                  * Reset the terminal and arrange to repaint the
227                  * screen when we get back to the main command loop.
228                  */
229                 LSIGNAL(SIGTSTP, stop);
230                 raw_mode(1);
231                 init();
232                 screen_trashed = 1;
233                 tsignals |= S_WINCH;
234         }
235 #endif
236 #ifdef S_WINCH
237         if (tsignals & S_WINCH)
238         {
239                 int old_width, old_height;
240                 /*
241                  * Re-execute scrsize() to read the new window size.
242                  */
243                 old_width = sc_width;
244                 old_height = sc_height;
245                 get_term();
246                 if (sc_width != old_width || sc_height != old_height)
247                 {
248                         wscroll = (sc_height + 1) / 2;
249                         screen_trashed = 1;
250                 }
251         }
252 #endif
253         if (tsignals & S_INTERRUPT)
254         {
255                 if (quit_on_intr)
256                         quit(QUIT_OK);
257                 bell();
258                 /*
259                  * {{ You may wish to replace the bell() with 
260                  *    error("Interrupt", NULL_PARG); }}
261                  */
262
263                 /*
264                  * If we were interrupted while in the "calculating 
265                  * line numbers" loop, turn off line numbers.
266                  */
267                 if (lnloop)
268                 {
269                         lnloop = 0;
270                         if (linenums == 2)
271                                 screen_trashed = 1;
272                         linenums = 0;
273                         error("Line numbers turned off", NULL_PARG);
274                 }
275
276         }
277 }