160786Sps/*
2240121Sdelphij * Copyright (C) 1984-2012  Mark Nudelman
360786Sps *
460786Sps * You may distribute under the terms of either the GNU General Public
560786Sps * License or the Less License, as specified in the README file.
660786Sps *
7240121Sdelphij * For more information, see the README file.
860786Sps */
960786Sps
1063120Sps/* $FreeBSD$ */
1160786Sps
1260786Sps/*
1360786Sps * Routines dealing with signals.
1460786Sps *
1560786Sps * A signal usually merely causes a bit to be set in the "signals" word.
1660786Sps * At some convenient time, the mainline code checks to see if any
1760786Sps * signals need processing by calling psignal().
1860786Sps * If we happen to be reading from a file [in iread()] at the time
1960786Sps * the signal is received, we call intread to interrupt the iread.
2060786Sps */
2160786Sps
2260786Sps#include "less.h"
2360786Sps#include <signal.h>
2460786Sps
2560786Sps/*
2660786Sps * "sigs" contains bits indicating signals which need to be processed.
2760786Sps */
2860786Spspublic int sigs;
2960786Sps
3060786Spsextern int sc_width, sc_height;
3160786Spsextern int screen_trashed;
3260786Spsextern int lnloop;
3360786Spsextern int linenums;
3460786Spsextern int wscroll;
3560786Spsextern int reading;
36161478Sdelphijextern int quit_on_intr;
37170259Sdelphijextern int less_is_more;
38170259Sdelphijextern long jump_sline_fraction;
3960786Sps
4060786Sps/*
4160786Sps * Interrupt signal handler.
4260786Sps */
4360786Sps	/* ARGSUSED*/
4460786Sps	static RETSIGTYPE
4560786Spsu_interrupt(type)
4660786Sps	int type;
4760786Sps{
48191930Sdelphij	bell();
4960786Sps#if OS2
5060786Sps	LSIGNAL(SIGINT, SIG_ACK);
5160786Sps#endif
5260786Sps	LSIGNAL(SIGINT, u_interrupt);
5360786Sps	sigs |= S_INTERRUPT;
5460786Sps#if MSDOS_COMPILER==DJGPPC
5560786Sps	/*
5660786Sps	 * If a keyboard has been hit, it must be Ctrl-C
5760786Sps	 * (as opposed to Ctrl-Break), so consume it.
5860786Sps	 * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.)
5960786Sps	 */
6060786Sps	if (kbhit())
6160786Sps		getkey();
6260786Sps#endif
63170259Sdelphij	if (less_is_more)
6463120Sps		quit(0);
6560786Sps	if (reading)
66191930Sdelphij		intread(); /* May longjmp */
6760786Sps}
6860786Sps
6960786Sps#ifdef SIGTSTP
7060786Sps/*
7160786Sps * "Stop" (^Z) signal handler.
7260786Sps */
7360786Sps	/* ARGSUSED*/
7460786Sps	static RETSIGTYPE
7560786Spsstop(type)
7660786Sps	int type;
7760786Sps{
7860786Sps	LSIGNAL(SIGTSTP, stop);
7960786Sps	sigs |= S_STOP;
8060786Sps	if (reading)
8160786Sps		intread();
8260786Sps}
8360786Sps#endif
8460786Sps
8560786Sps#ifdef SIGWINCH
8660786Sps/*
8760786Sps * "Window" change handler
8860786Sps */
8960786Sps	/* ARGSUSED*/
9060786Sps	public RETSIGTYPE
9160786Spswinch(type)
9260786Sps	int type;
9360786Sps{
9460786Sps	LSIGNAL(SIGWINCH, winch);
9560786Sps	sigs |= S_WINCH;
96172471Sdelphij	if (reading)
97172471Sdelphij		intread();
9860786Sps}
9960786Sps#else
10060786Sps#ifdef SIGWIND
10160786Sps/*
10260786Sps * "Window" change handler
10360786Sps */
10460786Sps	/* ARGSUSED*/
10560786Sps	public RETSIGTYPE
10660786Spswinch(type)
10760786Sps	int type;
10860786Sps{
10960786Sps	LSIGNAL(SIGWIND, winch);
11060786Sps	sigs |= S_WINCH;
11160786Sps	if (reading)
11260786Sps		intread();
11360786Sps}
11460786Sps#endif
11560786Sps#endif
11660786Sps
11760786Sps#if MSDOS_COMPILER==WIN32C
11860786Sps/*
11960786Sps * Handle CTRL-C and CTRL-BREAK keys.
12060786Sps */
12160786Sps#include "windows.h"
12260786Sps
12360786Sps	static BOOL WINAPI
12460786Spswbreak_handler(dwCtrlType)
12560786Sps	DWORD dwCtrlType;
12660786Sps{
12760786Sps	switch (dwCtrlType)
12860786Sps	{
12960786Sps	case CTRL_C_EVENT:
13060786Sps	case CTRL_BREAK_EVENT:
13160786Sps		sigs |= S_INTERRUPT;
13260786Sps		return (TRUE);
13360786Sps	default:
13460786Sps		break;
13560786Sps	}
13660786Sps	return (FALSE);
13760786Sps}
13860786Sps#endif
13960786Sps
14060786Sps/*
14160786Sps * Set up the signal handlers.
14260786Sps */
14360786Sps	public void
14460786Spsinit_signals(on)
14560786Sps	int on;
14660786Sps{
14760786Sps	if (on)
14860786Sps	{
14960786Sps		/*
15060786Sps		 * Set signal handlers.
15160786Sps		 */
15260786Sps		(void) LSIGNAL(SIGINT, u_interrupt);
15360786Sps#if MSDOS_COMPILER==WIN32C
15460786Sps		SetConsoleCtrlHandler(wbreak_handler, TRUE);
15560786Sps#endif
15660786Sps#ifdef SIGTSTP
15760786Sps		(void) LSIGNAL(SIGTSTP, stop);
15860786Sps#endif
15960786Sps#ifdef SIGWINCH
16060786Sps		(void) LSIGNAL(SIGWINCH, winch);
161170259Sdelphij#endif
16260786Sps#ifdef SIGWIND
16360786Sps		(void) LSIGNAL(SIGWIND, winch);
16460786Sps#endif
16560786Sps#ifdef SIGQUIT
16660786Sps		(void) LSIGNAL(SIGQUIT, SIG_IGN);
16760786Sps#endif
16860786Sps	} else
16960786Sps	{
17060786Sps		/*
17160786Sps		 * Restore signals to defaults.
17260786Sps		 */
17360786Sps		(void) LSIGNAL(SIGINT, SIG_DFL);
17460786Sps#if MSDOS_COMPILER==WIN32C
17560786Sps		SetConsoleCtrlHandler(wbreak_handler, FALSE);
17660786Sps#endif
17760786Sps#ifdef SIGTSTP
17860786Sps		(void) LSIGNAL(SIGTSTP, SIG_DFL);
17960786Sps#endif
18060786Sps#ifdef SIGWINCH
18160786Sps		(void) LSIGNAL(SIGWINCH, SIG_IGN);
18260786Sps#endif
18360786Sps#ifdef SIGWIND
18460786Sps		(void) LSIGNAL(SIGWIND, SIG_IGN);
18560786Sps#endif
18660786Sps#ifdef SIGQUIT
18760786Sps		(void) LSIGNAL(SIGQUIT, SIG_DFL);
18860786Sps#endif
18960786Sps	}
19060786Sps}
19160786Sps
19260786Sps/*
19360786Sps * Process any signals we have received.
19460786Sps * A received signal cause a bit to be set in "sigs".
19560786Sps */
19660786Sps	public void
19760786Spspsignals()
19860786Sps{
19960786Sps	register int tsignals;
20060786Sps
20160786Sps	if ((tsignals = sigs) == 0)
20260786Sps		return;
20360786Sps	sigs = 0;
20460786Sps
20560786Sps#ifdef SIGTSTP
20660786Sps	if (tsignals & S_STOP)
20760786Sps	{
20860786Sps		/*
20960786Sps		 * Clean up the terminal.
21060786Sps		 */
21160786Sps#ifdef SIGTTOU
21260786Sps		LSIGNAL(SIGTTOU, SIG_IGN);
21360786Sps#endif
21460786Sps		clear_bot();
21560786Sps		deinit();
21660786Sps		flush();
21760786Sps		raw_mode(0);
21860786Sps#ifdef SIGTTOU
21960786Sps		LSIGNAL(SIGTTOU, SIG_DFL);
22060786Sps#endif
22160786Sps		LSIGNAL(SIGTSTP, SIG_DFL);
22260786Sps		kill(getpid(), SIGTSTP);
22360786Sps		/*
22460786Sps		 * ... Bye bye. ...
22560786Sps		 * Hopefully we'll be back later and resume here...
22660786Sps		 * Reset the terminal and arrange to repaint the
22760786Sps		 * screen when we get back to the main command loop.
22860786Sps		 */
22960786Sps		LSIGNAL(SIGTSTP, stop);
23060786Sps		raw_mode(1);
23160786Sps		init();
23260786Sps		screen_trashed = 1;
23360786Sps		tsignals |= S_WINCH;
23460786Sps	}
23560786Sps#endif
23660786Sps#ifdef S_WINCH
23760786Sps	if (tsignals & S_WINCH)
23860786Sps	{
23960786Sps		int old_width, old_height;
24060786Sps		/*
24160786Sps		 * Re-execute scrsize() to read the new window size.
24260786Sps		 */
24360786Sps		old_width = sc_width;
24460786Sps		old_height = sc_height;
24560786Sps		get_term();
24660786Sps		if (sc_width != old_width || sc_height != old_height)
24760786Sps		{
24860786Sps			wscroll = (sc_height + 1) / 2;
249170259Sdelphij			calc_jump_sline();
250195941Sdelphij			calc_shift_count();
25160786Sps			screen_trashed = 1;
25260786Sps		}
25360786Sps	}
25460786Sps#endif
25560786Sps	if (tsignals & S_INTERRUPT)
25660786Sps	{
257161478Sdelphij		if (quit_on_intr)
258221715Sdelphij			quit(QUIT_INTERRUPT);
25960786Sps	}
26060786Sps}
261