Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / miscellany / less-177 / signal.c
1 /*
2  * Routines dealing with signals.
3  *
4  * A signal usually merely causes a bit to be set in the "signals" word.
5  * At some convenient time, the mainline code checks to see if any
6  * signals need processing by calling psignal().
7  * If we happen to be reading from a file [in iread()] at the time
8  * the signal is received, we call intread to interrupt the iread.
9  */
10
11 #include "less.h"
12 #include <signal.h>
13
14 /*
15  * "sigs" contains bits indicating signals which need to be processed.
16  */
17 public int sigs;
18
19 #define S_INTERRUPT     01
20 #ifdef SIGTSTP
21 #define S_STOP          02
22 #endif
23 #if defined(SIGWINCH) || defined(SIGWIND)
24 #define S_WINCH         04
25 #endif
26
27 extern int sc_width, sc_height;
28 extern int swindow;
29 extern int screen_trashed;
30 extern int lnloop;
31 extern int linenums;
32 extern int scroll;
33 extern int reading;
34
35 /*
36  * Interrupt signal handler.
37  */
38         /* ARGSUSED*/
39         static HANDLER
40 u_interrupt(type)
41         int type;
42 {
43         SIGNAL(SIGINT, u_interrupt);
44         sigs |= S_INTERRUPT;
45         if (reading)
46                 intread();
47 }
48
49         public void
50 fake_interrupt()
51 {
52         sigs |= S_INTERRUPT;
53 }
54
55 #ifdef SIGTSTP
56 /*
57  * "Stop" (^Z) signal handler.
58  */
59         /* ARGSUSED*/
60         static HANDLER
61 stop(type)
62         int type;
63 {
64         SIGNAL(SIGTSTP, stop);
65         sigs |= S_STOP;
66         if (reading)
67                 intread();
68 }
69 #endif
70
71 #ifdef SIGWINCH
72 /*
73  * "Window" change handler
74  */
75         /* ARGSUSED*/
76         public HANDLER
77 winch(type)
78         int type;
79 {
80         SIGNAL(SIGWINCH, winch);
81         sigs |= S_WINCH;
82         if (reading)
83                 intread();
84 }
85 #else
86 #ifdef SIGWIND
87 /*
88  * "Window" change handler
89  */
90         /* ARGSUSED*/
91         public HANDLER
92 winch(type)
93         int type;
94 {
95         SIGNAL(SIGWIND, winch);
96         sigs |= S_WINCH;
97         if (reading)
98                 intread();
99 }
100 #endif
101 #endif
102
103 /*
104  * Set up the signal handlers.
105  */
106         public void
107 init_signals(on)
108         int on;
109 {
110         if (on)
111         {
112                 /*
113                  * Set signal handlers.
114                  */
115                 (void) SIGNAL(SIGINT, u_interrupt);
116 #ifdef SIGTSTP
117                 (void) SIGNAL(SIGTSTP, stop);
118 #endif
119 #ifdef SIGWINCH
120                 (void) SIGNAL(SIGWINCH, winch);
121 #else
122 #ifdef SIGWIND
123                 (void) SIGNAL(SIGWIND, winch);
124 #endif
125 #endif
126         } else
127         {
128                 /*
129                  * Restore signals to defaults.
130                  */
131                 (void) SIGNAL(SIGINT, SIG_DFL);
132 #ifdef SIGTSTP
133                 (void) SIGNAL(SIGTSTP, SIG_DFL);
134 #endif
135 #ifdef SIGWINCH
136                 (void) SIGNAL(SIGWINCH, SIG_IGN);
137 #endif
138 #ifdef SIGWIND
139                 (void) SIGNAL(SIGWIND, SIG_IGN);
140 #endif
141         }
142 }
143
144 /*
145  * Process any signals we have received.
146  * A received signal cause a bit to be set in "sigs".
147  */
148         public void
149 psignals()
150 {
151         register int tsignals;
152
153         if ((tsignals = sigs) == 0)
154                 return;
155         sigs = 0;
156
157 #ifdef S_WINCH
158         if (tsignals & S_WINCH)
159         {
160                 int old_width, old_height;
161                 /*
162                  * Re-execute get_term() to read the new window size.
163                  */
164                 old_width = sc_width;
165                 old_height = sc_height;
166                 swindow = -1;
167                 get_term();
168                 if (sc_width != old_width || sc_height != old_height)
169                 {
170                         scroll = (sc_height + 1) / 2;
171                         screen_trashed = 1;
172                 }
173         }
174 #endif
175 #ifdef SIGTSTP
176         if (tsignals & S_STOP)
177         {
178                 /*
179                  * Clean up the terminal.
180                  */
181 #ifdef SIGTTOU
182                 SIGNAL(SIGTTOU, SIG_IGN);
183 #endif
184                 lower_left();
185                 clear_eol();
186                 deinit();
187                 flush();
188                 raw_mode(0);
189 #ifdef SIGTTOU
190                 SIGNAL(SIGTTOU, SIG_DFL);
191 #endif
192                 SIGNAL(SIGTSTP, SIG_DFL);
193                 kill(getpid(), SIGTSTP);
194                 /*
195                  * ... Bye bye. ...
196                  * Hopefully we'll be back later and resume here...
197                  * Reset the terminal and arrange to repaint the
198                  * screen when we get back to the main command loop.
199                  */
200                 SIGNAL(SIGTSTP, stop);
201                 raw_mode(1);
202                 init();
203                 screen_trashed = 1;
204         }
205 #endif
206         if (tsignals & S_INTERRUPT)
207         {
208                 bell();
209                 /*
210                  * {{ You may wish to replace the bell() with 
211                  *    error("Interrupt", NULL_PARG); }}
212                  */
213
214                 /*
215                  * If we were interrupted while in the "calculating 
216                  * line numbers" loop, turn off line numbers.
217                  */
218                 if (lnloop)
219                 {
220                         lnloop = 0;
221                         if (linenums == 2)
222                                 screen_trashed = 1;
223                         linenums = 0;
224                         error("Line numbers turned off", NULL_PARG);
225                 }
226
227         }
228 }