xref: /minix3/external/bsd/nvi/dist/cl/cl_term.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: cl_term.c,v 1.4 2014/01/26 21:43:45 christos Exp $ */
284d9c625SLionel Sambuc /*-
384d9c625SLionel Sambuc  * Copyright (c) 1993, 1994
484d9c625SLionel Sambuc  *	The Regents of the University of California.  All rights reserved.
584d9c625SLionel Sambuc  * Copyright (c) 1993, 1994, 1995, 1996
684d9c625SLionel Sambuc  *	Keith Bostic.  All rights reserved.
784d9c625SLionel Sambuc  *
884d9c625SLionel Sambuc  * See the LICENSE file for redistribution information.
984d9c625SLionel Sambuc  */
1084d9c625SLionel Sambuc 
1184d9c625SLionel Sambuc #include "config.h"
1284d9c625SLionel Sambuc 
13*0a6a1f1dSLionel Sambuc #include <sys/cdefs.h>
14*0a6a1f1dSLionel Sambuc #if 0
1584d9c625SLionel Sambuc #ifndef lint
1684d9c625SLionel Sambuc static const char sccsid[] = "Id: cl_term.c,v 10.31 2001/07/08 13:06:56 skimo Exp  (Berkeley) Date: 2001/07/08 13:06:56 ";
1784d9c625SLionel Sambuc #endif /* not lint */
18*0a6a1f1dSLionel Sambuc #else
19*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: cl_term.c,v 1.4 2014/01/26 21:43:45 christos Exp $");
20*0a6a1f1dSLionel Sambuc #endif
2184d9c625SLionel Sambuc 
2284d9c625SLionel Sambuc #include <sys/types.h>
2384d9c625SLionel Sambuc #include <sys/ioctl.h>
2484d9c625SLionel Sambuc #include <sys/queue.h>
2584d9c625SLionel Sambuc #include <sys/stat.h>
2684d9c625SLionel Sambuc 
2784d9c625SLionel Sambuc #include <bitstring.h>
2884d9c625SLionel Sambuc #include <errno.h>
2984d9c625SLionel Sambuc #include <limits.h>
3084d9c625SLionel Sambuc #include <signal.h>
3184d9c625SLionel Sambuc #include <stdio.h>
3284d9c625SLionel Sambuc #include <stdlib.h>
3384d9c625SLionel Sambuc #include <string.h>
3484d9c625SLionel Sambuc #include <termios.h>
3584d9c625SLionel Sambuc #include <unistd.h>
3684d9c625SLionel Sambuc 
3784d9c625SLionel Sambuc #include "../common/common.h"
3884d9c625SLionel Sambuc #include "cl.h"
3984d9c625SLionel Sambuc 
4084d9c625SLionel Sambuc static int cl_pfmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
4184d9c625SLionel Sambuc 
4284d9c625SLionel Sambuc /*
4384d9c625SLionel Sambuc  * XXX
4484d9c625SLionel Sambuc  * THIS REQUIRES THAT ALL SCREENS SHARE A TERMINAL TYPE.
4584d9c625SLionel Sambuc  */
4684d9c625SLionel Sambuc typedef struct _tklist {
4784d9c625SLionel Sambuc 	const char	*ts;		/* Key's termcap string. */
4884d9c625SLionel Sambuc 	const char	*output;	/* Corresponding vi command. */
4984d9c625SLionel Sambuc 	const char	*name;		/* Name. */
5084d9c625SLionel Sambuc 	u_char	 value;			/* Special value (for lookup). */
5184d9c625SLionel Sambuc } TKLIST;
5284d9c625SLionel Sambuc 
5384d9c625SLionel Sambuc #define TKINIT(a, b, c) { a, b, c, 0 }
5484d9c625SLionel Sambuc 
5584d9c625SLionel Sambuc static TKLIST const c_tklist[] = {	/* Command mappings. */
5684d9c625SLionel Sambuc 	TKINIT("kil1",	"O",	"insert line"),
5784d9c625SLionel Sambuc 	TKINIT("kdch1",	"x",	"delete character"),
5884d9c625SLionel Sambuc 	TKINIT("kcud1",	"j",	"cursor down"),
5984d9c625SLionel Sambuc 	TKINIT("kel",	"D",	"delete to eol"),
6084d9c625SLionel Sambuc 	TKINIT("kind",  "\004",	"scroll down"),			/* ^D */
6184d9c625SLionel Sambuc 	TKINIT("kll",	"$",	"go to eol"),
6284d9c625SLionel Sambuc 	TKINIT("kend",	"$",	"go to eol"),
6384d9c625SLionel Sambuc 	TKINIT("khome",	"^",	"go to sol"),
6484d9c625SLionel Sambuc 	TKINIT("kich1",	"i",	"insert at cursor"),
6584d9c625SLionel Sambuc 	TKINIT("kdl1",  "dd",	"delete line"),
6684d9c625SLionel Sambuc 	TKINIT("kcub1",	"h",	"cursor left"),
6784d9c625SLionel Sambuc 	TKINIT("knp",	"\006",	"page down"),			/* ^F */
6884d9c625SLionel Sambuc 	TKINIT("kpp",	"\002",	"page up"),			/* ^B */
6984d9c625SLionel Sambuc 	TKINIT("kri",	"\025",	"scroll up"),			/* ^U */
7084d9c625SLionel Sambuc 	TKINIT("ked",	"dG",	"delete to end of screen"),
7184d9c625SLionel Sambuc 	TKINIT("kcuf1",	"l",	"cursor right"),
7284d9c625SLionel Sambuc 	TKINIT("kcuu1",	"k",	"cursor up"),
7384d9c625SLionel Sambuc 	TKINIT(NULL, NULL, NULL),
7484d9c625SLionel Sambuc };
7584d9c625SLionel Sambuc static TKLIST const m1_tklist[] = {	/* Input mappings (lookup). */
7684d9c625SLionel Sambuc 	TKINIT(NULL, NULL, NULL),
7784d9c625SLionel Sambuc };
7884d9c625SLionel Sambuc static TKLIST const m2_tklist[] = {	/* Input mappings (set or delete). */
7984d9c625SLionel Sambuc 	TKINIT("kcud1",  "\033ja",	"cursor down"),		/* ^[ja */
8084d9c625SLionel Sambuc 	TKINIT("kcub1",  "\033ha",	"cursor left"),		/* ^[ha */
8184d9c625SLionel Sambuc 	TKINIT("kcuu1",  "\033ka",	"cursor up"),		/* ^[ka */
8284d9c625SLionel Sambuc 	TKINIT("kcuf1",  "\033la",	"cursor right"),	/* ^[la */
8384d9c625SLionel Sambuc 	TKINIT(NULL, NULL, NULL),
8484d9c625SLionel Sambuc };
8584d9c625SLionel Sambuc 
8684d9c625SLionel Sambuc /*
8784d9c625SLionel Sambuc  * cl_term_init --
8884d9c625SLionel Sambuc  *	Initialize the special keys defined by the termcap/terminfo entry.
8984d9c625SLionel Sambuc  *
9084d9c625SLionel Sambuc  * PUBLIC: int cl_term_init __P((SCR *));
9184d9c625SLionel Sambuc  */
9284d9c625SLionel Sambuc int
cl_term_init(SCR * sp)9384d9c625SLionel Sambuc cl_term_init(SCR *sp)
9484d9c625SLionel Sambuc {
9584d9c625SLionel Sambuc 	KEYLIST *kp;
9684d9c625SLionel Sambuc 	SEQ *qp;
9784d9c625SLionel Sambuc 	TKLIST const *tkp;
9884d9c625SLionel Sambuc 	char *t;
9984d9c625SLionel Sambuc 	CHAR_T name[60];
10084d9c625SLionel Sambuc 	CHAR_T output[5];
10184d9c625SLionel Sambuc 	CHAR_T ts[20];
10284d9c625SLionel Sambuc 	const CHAR_T *wp;
10384d9c625SLionel Sambuc 	size_t wlen;
10484d9c625SLionel Sambuc 
10584d9c625SLionel Sambuc 	/* Command mappings. */
10684d9c625SLionel Sambuc 	for (tkp = c_tklist; tkp->name != NULL; ++tkp) {
10784d9c625SLionel Sambuc 		if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
10884d9c625SLionel Sambuc 			continue;
10984d9c625SLionel Sambuc 		CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
11084d9c625SLionel Sambuc 		MEMCPYW(name, wp, wlen);
11184d9c625SLionel Sambuc 		CHAR2INT(sp, t, strlen(t), wp, wlen);
11284d9c625SLionel Sambuc 		MEMCPYW(ts, wp, wlen);
11384d9c625SLionel Sambuc 		CHAR2INT(sp, tkp->output, strlen(tkp->output), wp, wlen);
11484d9c625SLionel Sambuc 		MEMCPYW(output, wp, wlen);
11584d9c625SLionel Sambuc 		if (seq_set(sp, name, strlen(tkp->name), ts, strlen(t),
11684d9c625SLionel Sambuc 		    output, strlen(tkp->output), SEQ_COMMAND,
11784d9c625SLionel Sambuc 		    SEQ_NOOVERWRITE | SEQ_SCREEN))
11884d9c625SLionel Sambuc 			return (1);
11984d9c625SLionel Sambuc 	}
12084d9c625SLionel Sambuc 
12184d9c625SLionel Sambuc 	/* Input mappings needing to be looked up. */
12284d9c625SLionel Sambuc 	for (tkp = m1_tklist; tkp->name != NULL; ++tkp) {
12384d9c625SLionel Sambuc 		if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
12484d9c625SLionel Sambuc 			continue;
12584d9c625SLionel Sambuc 		for (kp = keylist;; ++kp)
12684d9c625SLionel Sambuc 			if (kp->value == tkp->value)
12784d9c625SLionel Sambuc 				break;
12884d9c625SLionel Sambuc 		if (kp == NULL)
12984d9c625SLionel Sambuc 			continue;
13084d9c625SLionel Sambuc 		CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
13184d9c625SLionel Sambuc 		MEMCPYW(name, wp, wlen);
13284d9c625SLionel Sambuc 		CHAR2INT(sp, t, strlen(t), wp, wlen);
13384d9c625SLionel Sambuc 		MEMCPYW(ts, wp, wlen);
13484d9c625SLionel Sambuc 		output[0] = (UCHAR_T)kp->ch;
13584d9c625SLionel Sambuc 		if (seq_set(sp, name, strlen(tkp->name), ts, strlen(t),
13684d9c625SLionel Sambuc 		    output, 1, SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
13784d9c625SLionel Sambuc 			return (1);
13884d9c625SLionel Sambuc 	}
13984d9c625SLionel Sambuc 
14084d9c625SLionel Sambuc 	/* Input mappings that are already set or are text deletions. */
14184d9c625SLionel Sambuc 	for (tkp = m2_tklist; tkp->name != NULL; ++tkp) {
14284d9c625SLionel Sambuc 		if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
14384d9c625SLionel Sambuc 			continue;
14484d9c625SLionel Sambuc 		/*
14584d9c625SLionel Sambuc 		 * !!!
14684d9c625SLionel Sambuc 		 * Some terminals' <cursor_left> keys send single <backspace>
14784d9c625SLionel Sambuc 		 * characters.  This is okay in command mapping, but not okay
14884d9c625SLionel Sambuc 		 * in input mapping.  That combination is the only one we'll
14984d9c625SLionel Sambuc 		 * ever see, hopefully, so kluge it here for now.
15084d9c625SLionel Sambuc 		 */
15184d9c625SLionel Sambuc 		if (!strcmp(t, "\b"))
15284d9c625SLionel Sambuc 			continue;
15384d9c625SLionel Sambuc 		if (tkp->output == NULL) {
15484d9c625SLionel Sambuc 			CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
15584d9c625SLionel Sambuc 			MEMCPYW(name, wp, wlen);
15684d9c625SLionel Sambuc 			CHAR2INT(sp, t, strlen(t), wp, wlen);
15784d9c625SLionel Sambuc 			MEMCPYW(ts, wp, wlen);
15884d9c625SLionel Sambuc 			if (seq_set(sp, name, strlen(tkp->name),
15984d9c625SLionel Sambuc 			    ts, strlen(t), NULL, 0,
16084d9c625SLionel Sambuc 			    SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
16184d9c625SLionel Sambuc 				return (1);
16284d9c625SLionel Sambuc 		} else {
16384d9c625SLionel Sambuc 			CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
16484d9c625SLionel Sambuc 			MEMCPYW(name, wp, wlen);
16584d9c625SLionel Sambuc 			CHAR2INT(sp, t, strlen(t), wp, wlen);
16684d9c625SLionel Sambuc 			MEMCPYW(ts, wp, wlen);
16784d9c625SLionel Sambuc 			CHAR2INT(sp, tkp->output, strlen(tkp->output), wp, wlen);
16884d9c625SLionel Sambuc 			MEMCPYW(output, wp, wlen);
16984d9c625SLionel Sambuc 			if (seq_set(sp, name, strlen(tkp->name),
17084d9c625SLionel Sambuc 			    ts, strlen(t), output, strlen(tkp->output),
17184d9c625SLionel Sambuc 			    SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
17284d9c625SLionel Sambuc 				return (1);
17384d9c625SLionel Sambuc 		}
17484d9c625SLionel Sambuc 	}
17584d9c625SLionel Sambuc 
17684d9c625SLionel Sambuc 	/*
17784d9c625SLionel Sambuc 	 * Rework any function key mappings that were set before the
17884d9c625SLionel Sambuc 	 * screen was initialized.
17984d9c625SLionel Sambuc 	 */
18084d9c625SLionel Sambuc 	LIST_FOREACH(qp, &sp->gp->seqq, q)
18184d9c625SLionel Sambuc 		if (F_ISSET(qp, SEQ_FUNCMAP))
18284d9c625SLionel Sambuc 			(void)cl_pfmap(sp, qp->stype,
18384d9c625SLionel Sambuc 			    qp->input, qp->ilen, qp->output, qp->olen);
18484d9c625SLionel Sambuc 	return (0);
18584d9c625SLionel Sambuc }
18684d9c625SLionel Sambuc 
18784d9c625SLionel Sambuc /*
18884d9c625SLionel Sambuc  * cl_term_end --
18984d9c625SLionel Sambuc  *	End the special keys defined by the termcap/terminfo entry.
19084d9c625SLionel Sambuc  *
19184d9c625SLionel Sambuc  * PUBLIC: int cl_term_end __P((GS *));
19284d9c625SLionel Sambuc  */
19384d9c625SLionel Sambuc int
cl_term_end(GS * gp)19484d9c625SLionel Sambuc cl_term_end(GS *gp)
19584d9c625SLionel Sambuc {
19684d9c625SLionel Sambuc 	SEQ *qp, *nqp;
19784d9c625SLionel Sambuc 
19884d9c625SLionel Sambuc 	/* Delete screen specific mappings. */
19984d9c625SLionel Sambuc 	LIST_FOREACH_SAFE(qp, &gp->seqq, q, nqp)
20084d9c625SLionel Sambuc 		if (F_ISSET(qp, SEQ_SCREEN))
20184d9c625SLionel Sambuc 			(void)seq_mdel(qp);
20284d9c625SLionel Sambuc 	return (0);
20384d9c625SLionel Sambuc }
20484d9c625SLionel Sambuc 
20584d9c625SLionel Sambuc /*
20684d9c625SLionel Sambuc  * cl_fmap --
20784d9c625SLionel Sambuc  *	Map a function key.
20884d9c625SLionel Sambuc  *
20984d9c625SLionel Sambuc  * PUBLIC: int cl_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t));
21084d9c625SLionel Sambuc  */
21184d9c625SLionel Sambuc int
cl_fmap(SCR * sp,seq_t stype,CHAR_T * from,size_t flen,CHAR_T * to,size_t tlen)21284d9c625SLionel Sambuc cl_fmap(SCR *sp, seq_t stype, CHAR_T *from, size_t flen, CHAR_T *to, size_t tlen)
21384d9c625SLionel Sambuc {
21484d9c625SLionel Sambuc 	/* Ignore until the screen is running, do the real work then. */
21584d9c625SLionel Sambuc 	if (F_ISSET(sp, SC_VI) && !F_ISSET(sp, SC_SCR_VI))
21684d9c625SLionel Sambuc 		return (0);
21784d9c625SLionel Sambuc 	if (F_ISSET(sp, SC_EX) && !F_ISSET(sp, SC_SCR_EX))
21884d9c625SLionel Sambuc 		return (0);
21984d9c625SLionel Sambuc 
22084d9c625SLionel Sambuc 	return (cl_pfmap(sp, stype, from, flen, to, tlen));
22184d9c625SLionel Sambuc }
22284d9c625SLionel Sambuc 
22384d9c625SLionel Sambuc /*
22484d9c625SLionel Sambuc  * cl_pfmap --
22584d9c625SLionel Sambuc  *	Map a function key (private version).
22684d9c625SLionel Sambuc  */
22784d9c625SLionel Sambuc static int
cl_pfmap(SCR * sp,seq_t stype,CHAR_T * from,size_t flen,CHAR_T * to,size_t tlen)22884d9c625SLionel Sambuc cl_pfmap(SCR *sp, seq_t stype, CHAR_T *from, size_t flen, CHAR_T *to, size_t tlen)
22984d9c625SLionel Sambuc {
23084d9c625SLionel Sambuc 	size_t nlen;
23184d9c625SLionel Sambuc 	char *p;
23284d9c625SLionel Sambuc 	char name[64];
23384d9c625SLionel Sambuc 	CHAR_T mykeyname[64];
23484d9c625SLionel Sambuc 	CHAR_T ts[20];
23584d9c625SLionel Sambuc 	const CHAR_T *wp;
23684d9c625SLionel Sambuc 	size_t wlen;
23784d9c625SLionel Sambuc 
23884d9c625SLionel Sambuc 	(void)snprintf(name, sizeof(name), "kf%d",
23984d9c625SLionel Sambuc 			(int)STRTOL(from+1,NULL,10));
24084d9c625SLionel Sambuc 	if ((p = tigetstr(name)) == NULL ||
24184d9c625SLionel Sambuc 	    p == (char *)-1 || strlen(p) == 0)
24284d9c625SLionel Sambuc 		p = NULL;
24384d9c625SLionel Sambuc 	if (p == NULL) {
24484d9c625SLionel Sambuc 		msgq_wstr(sp, M_ERR, from, "233|This terminal has no %s key");
24584d9c625SLionel Sambuc 		return (1);
24684d9c625SLionel Sambuc 	}
24784d9c625SLionel Sambuc 
24884d9c625SLionel Sambuc 	nlen = SPRINTF(mykeyname,
24984d9c625SLionel Sambuc 	    SIZE(mykeyname), L("function key %d"),
25084d9c625SLionel Sambuc 			(int)STRTOL(from+1,NULL,10));
25184d9c625SLionel Sambuc 	CHAR2INT(sp, p, strlen(p), wp, wlen);
25284d9c625SLionel Sambuc 	MEMCPYW(ts, wp, wlen);
25384d9c625SLionel Sambuc 	return (seq_set(sp, mykeyname, nlen,
25484d9c625SLionel Sambuc 	    ts, strlen(p), to, tlen, stype, SEQ_NOOVERWRITE | SEQ_SCREEN));
25584d9c625SLionel Sambuc }
25684d9c625SLionel Sambuc 
25784d9c625SLionel Sambuc /*
25884d9c625SLionel Sambuc  * cl_optchange --
25984d9c625SLionel Sambuc  *	Curses screen specific "option changed" routine.
26084d9c625SLionel Sambuc  *
26184d9c625SLionel Sambuc  * PUBLIC: int cl_optchange __P((SCR *, int, const char *, u_long *));
26284d9c625SLionel Sambuc  */
26384d9c625SLionel Sambuc int
cl_optchange(SCR * sp,int opt,const char * str,u_long * valp)26484d9c625SLionel Sambuc cl_optchange(SCR *sp, int opt, const char *str, u_long *valp)
26584d9c625SLionel Sambuc {
26684d9c625SLionel Sambuc 	CL_PRIVATE *clp;
26784d9c625SLionel Sambuc 
26884d9c625SLionel Sambuc 	clp = CLP(sp);
26984d9c625SLionel Sambuc 
27084d9c625SLionel Sambuc 	switch (opt) {
27184d9c625SLionel Sambuc 	case O_COLUMNS:
27284d9c625SLionel Sambuc 	case O_LINES:
27384d9c625SLionel Sambuc 	case O_TERM:
27484d9c625SLionel Sambuc 		/*
27584d9c625SLionel Sambuc 		 * Changing the columns, lines or terminal require that
27684d9c625SLionel Sambuc 		 * we restart the screen.
27784d9c625SLionel Sambuc 		 */
27884d9c625SLionel Sambuc 		F_SET(sp->gp, G_SRESTART);
27984d9c625SLionel Sambuc 		F_CLR(sp, SC_SCR_EX | SC_SCR_VI);
28084d9c625SLionel Sambuc 		break;
28184d9c625SLionel Sambuc 	case O_MESG:
28284d9c625SLionel Sambuc 		(void)cl_omesg(sp, clp, *valp);
28384d9c625SLionel Sambuc 		break;
28484d9c625SLionel Sambuc 	case O_WINDOWNAME:
28584d9c625SLionel Sambuc 		if (*valp) {
28684d9c625SLionel Sambuc 			F_SET(clp, CL_RENAME_OK);
28784d9c625SLionel Sambuc 
28884d9c625SLionel Sambuc 			/*
28984d9c625SLionel Sambuc 			 * If the screen is live, i.e. we're not reading the
29084d9c625SLionel Sambuc 			 * .exrc file, update the window.
29184d9c625SLionel Sambuc 			 */
29284d9c625SLionel Sambuc 			if (sp->frp != NULL && sp->frp->name != NULL)
29384d9c625SLionel Sambuc 				(void)cl_rename(sp, sp->frp->name, 1);
29484d9c625SLionel Sambuc 		} else {
29584d9c625SLionel Sambuc 			F_CLR(clp, CL_RENAME_OK);
29684d9c625SLionel Sambuc 
29784d9c625SLionel Sambuc 			(void)cl_rename(sp, NULL, 0);
29884d9c625SLionel Sambuc 		}
29984d9c625SLionel Sambuc 		break;
30084d9c625SLionel Sambuc 	}
30184d9c625SLionel Sambuc 	return (0);
30284d9c625SLionel Sambuc }
30384d9c625SLionel Sambuc 
30484d9c625SLionel Sambuc /*
30584d9c625SLionel Sambuc  * cl_omesg --
30684d9c625SLionel Sambuc  *	Turn the tty write permission on or off.
30784d9c625SLionel Sambuc  *
30884d9c625SLionel Sambuc  * PUBLIC: int cl_omesg __P((SCR *, CL_PRIVATE *, int));
30984d9c625SLionel Sambuc  */
31084d9c625SLionel Sambuc int
cl_omesg(SCR * sp,CL_PRIVATE * clp,int on)31184d9c625SLionel Sambuc cl_omesg(SCR *sp, CL_PRIVATE *clp, int on)
31284d9c625SLionel Sambuc {
31384d9c625SLionel Sambuc 	struct stat sb;
31484d9c625SLionel Sambuc 	char *tty;
31584d9c625SLionel Sambuc 
31684d9c625SLionel Sambuc 	/* Find the tty, get the current permissions. */
31784d9c625SLionel Sambuc 	if ((tty = ttyname(STDERR_FILENO)) == NULL) {
31884d9c625SLionel Sambuc 		if (sp != NULL)
31984d9c625SLionel Sambuc 			msgq(sp, M_SYSERR, "stderr");
32084d9c625SLionel Sambuc 		return (1);
32184d9c625SLionel Sambuc 	}
32284d9c625SLionel Sambuc 	if (stat(tty, &sb) < 0) {
32384d9c625SLionel Sambuc 		if (sp != NULL)
32484d9c625SLionel Sambuc 			msgq(sp, M_SYSERR, "%s", tty);
32584d9c625SLionel Sambuc 		return (1);
32684d9c625SLionel Sambuc 	}
32784d9c625SLionel Sambuc 
32884d9c625SLionel Sambuc 	/* Save the original status if it's unknown. */
32984d9c625SLionel Sambuc 	if (clp->tgw == TGW_UNKNOWN)
33084d9c625SLionel Sambuc 		clp->tgw = sb.st_mode & S_IWGRP ? TGW_SET : TGW_UNSET;
33184d9c625SLionel Sambuc 
33284d9c625SLionel Sambuc 	/* Toggle the permissions. */
33384d9c625SLionel Sambuc 	if (on) {
33484d9c625SLionel Sambuc 		if (chmod(tty, sb.st_mode | S_IWGRP) < 0) {
33584d9c625SLionel Sambuc 			if (sp != NULL)
33684d9c625SLionel Sambuc 				msgq(sp, M_SYSERR,
33784d9c625SLionel Sambuc 				    "046|messages not turned on: %s", tty);
33884d9c625SLionel Sambuc 			return (1);
33984d9c625SLionel Sambuc 		}
34084d9c625SLionel Sambuc 	} else
34184d9c625SLionel Sambuc 		if (chmod(tty, sb.st_mode & ~S_IWGRP) < 0) {
34284d9c625SLionel Sambuc 			if (sp != NULL)
34384d9c625SLionel Sambuc 				msgq(sp, M_SYSERR,
34484d9c625SLionel Sambuc 				    "045|messages not turned off: %s", tty);
34584d9c625SLionel Sambuc 			return (1);
34684d9c625SLionel Sambuc 		}
34784d9c625SLionel Sambuc 	return (0);
34884d9c625SLionel Sambuc }
34984d9c625SLionel Sambuc 
35084d9c625SLionel Sambuc /*
35184d9c625SLionel Sambuc  * cl_ssize --
35284d9c625SLionel Sambuc  *	Return the terminal size.
35384d9c625SLionel Sambuc  *
35484d9c625SLionel Sambuc  * PUBLIC: int cl_ssize __P((SCR *, int, size_t *, size_t *, int *));
35584d9c625SLionel Sambuc  */
35684d9c625SLionel Sambuc int
cl_ssize(SCR * sp,int sigwinch,size_t * rowp,size_t * colp,int * changedp)35784d9c625SLionel Sambuc cl_ssize(SCR *sp, int sigwinch, size_t *rowp, size_t *colp, int *changedp)
35884d9c625SLionel Sambuc {
35984d9c625SLionel Sambuc #ifdef TIOCGWINSZ
36084d9c625SLionel Sambuc 	struct winsize win;
36184d9c625SLionel Sambuc #endif
36284d9c625SLionel Sambuc 	size_t col, row;
36384d9c625SLionel Sambuc 	int rval;
36484d9c625SLionel Sambuc 	char *p;
36584d9c625SLionel Sambuc 
36684d9c625SLionel Sambuc 	/* Assume it's changed. */
36784d9c625SLionel Sambuc 	if (changedp != NULL)
36884d9c625SLionel Sambuc 		*changedp = 1;
36984d9c625SLionel Sambuc 
37084d9c625SLionel Sambuc 	/*
37184d9c625SLionel Sambuc 	 * !!!
37284d9c625SLionel Sambuc 	 * sp may be NULL.
37384d9c625SLionel Sambuc 	 *
37484d9c625SLionel Sambuc 	 * Get the screen rows and columns.  If the values are wrong, it's
37584d9c625SLionel Sambuc 	 * not a big deal -- as soon as the user sets them explicitly the
37684d9c625SLionel Sambuc 	 * environment will be set and the screen package will use the new
37784d9c625SLionel Sambuc 	 * values.
37884d9c625SLionel Sambuc 	 *
37984d9c625SLionel Sambuc 	 * Try TIOCGWINSZ.
38084d9c625SLionel Sambuc 	 */
38184d9c625SLionel Sambuc 	row = col = 0;
38284d9c625SLionel Sambuc #ifdef TIOCGWINSZ
38384d9c625SLionel Sambuc 	if (ioctl(STDERR_FILENO, TIOCGWINSZ, &win) != -1) {
38484d9c625SLionel Sambuc 		row = win.ws_row;
38584d9c625SLionel Sambuc 		col = win.ws_col;
38684d9c625SLionel Sambuc 	}
38784d9c625SLionel Sambuc #endif
38884d9c625SLionel Sambuc 	/* If here because of suspend or a signal, only trust TIOCGWINSZ. */
38984d9c625SLionel Sambuc 	if (sigwinch) {
39084d9c625SLionel Sambuc 		/*
39184d9c625SLionel Sambuc 		 * Somebody didn't get TIOCGWINSZ right, or has suspend
39284d9c625SLionel Sambuc 		 * without window resizing support.  The user just lost,
39384d9c625SLionel Sambuc 		 * but there's nothing we can do.
39484d9c625SLionel Sambuc 		 */
39584d9c625SLionel Sambuc 		if (row == 0 || col == 0) {
39684d9c625SLionel Sambuc 			if (changedp != NULL)
39784d9c625SLionel Sambuc 				*changedp = 0;
39884d9c625SLionel Sambuc 			return (0);
39984d9c625SLionel Sambuc 		}
40084d9c625SLionel Sambuc 
40184d9c625SLionel Sambuc 		/*
40284d9c625SLionel Sambuc 		 * SunOS systems deliver SIGWINCH when windows are uncovered
40384d9c625SLionel Sambuc 		 * as well as when they change size.  In addition, we call
40484d9c625SLionel Sambuc 		 * here when continuing after being suspended since the window
40584d9c625SLionel Sambuc 		 * may have changed size.  Since we don't want to background
40684d9c625SLionel Sambuc 		 * all of the screens just because the window was uncovered,
40784d9c625SLionel Sambuc 		 * ignore the signal if there's no change.
40884d9c625SLionel Sambuc 		 */
40984d9c625SLionel Sambuc 		if (sp != NULL &&
41084d9c625SLionel Sambuc 		    row == O_VAL(sp, O_LINES) && col == O_VAL(sp, O_COLUMNS)) {
41184d9c625SLionel Sambuc 			if (changedp != NULL)
41284d9c625SLionel Sambuc 				*changedp = 0;
41384d9c625SLionel Sambuc 			return (0);
41484d9c625SLionel Sambuc 		}
41584d9c625SLionel Sambuc 
41684d9c625SLionel Sambuc 		if (rowp != NULL)
41784d9c625SLionel Sambuc 			*rowp = row;
41884d9c625SLionel Sambuc 		if (colp != NULL)
41984d9c625SLionel Sambuc 			*colp = col;
42084d9c625SLionel Sambuc 		resizeterm(row, col);
42184d9c625SLionel Sambuc 		return (0);
42284d9c625SLionel Sambuc 	}
42384d9c625SLionel Sambuc 
42484d9c625SLionel Sambuc 	/*
42584d9c625SLionel Sambuc 	 * !!!
42684d9c625SLionel Sambuc 	 * If TIOCGWINSZ failed, or had entries of 0, try termcap.  This
42784d9c625SLionel Sambuc 	 * routine is called before any termcap or terminal information
42884d9c625SLionel Sambuc 	 * has been set up.  If there's no TERM environmental variable set,
42984d9c625SLionel Sambuc 	 * let it go, at least ex can run.
43084d9c625SLionel Sambuc 	 */
43184d9c625SLionel Sambuc 	if (row == 0 || col == 0) {
43284d9c625SLionel Sambuc 		if ((p = getenv("TERM")) == NULL)
43384d9c625SLionel Sambuc 			goto noterm;
43484d9c625SLionel Sambuc 		if (row == 0) {
43584d9c625SLionel Sambuc 			if ((rval = tigetnum("lines")) < 0)
43684d9c625SLionel Sambuc 				msgq(sp, M_SYSERR, "tigetnum: lines");
43784d9c625SLionel Sambuc 			else
43884d9c625SLionel Sambuc 				row = rval;
43984d9c625SLionel Sambuc 		}
44084d9c625SLionel Sambuc 		if (col == 0) {
44184d9c625SLionel Sambuc 			if ((rval = tigetnum("cols")) < 0)
44284d9c625SLionel Sambuc 				msgq(sp, M_SYSERR, "tigetnum: cols");
44384d9c625SLionel Sambuc 			else
44484d9c625SLionel Sambuc 				col = rval;
44584d9c625SLionel Sambuc 		}
44684d9c625SLionel Sambuc 	}
44784d9c625SLionel Sambuc 
44884d9c625SLionel Sambuc 	/* If nothing else, well, it's probably a VT100. */
44984d9c625SLionel Sambuc noterm:	if (row == 0)
45084d9c625SLionel Sambuc 		row = 24;
45184d9c625SLionel Sambuc 	if (col == 0)
45284d9c625SLionel Sambuc 		col = 80;
45384d9c625SLionel Sambuc 
45484d9c625SLionel Sambuc 	/*
45584d9c625SLionel Sambuc 	 * !!!
45684d9c625SLionel Sambuc 	 * POSIX 1003.2 requires the environment to override everything.
45784d9c625SLionel Sambuc 	 * Often, people can get nvi to stop messing up their screen by
45884d9c625SLionel Sambuc 	 * deleting the LINES and COLUMNS environment variables from their
45984d9c625SLionel Sambuc 	 * dot-files.
46084d9c625SLionel Sambuc 	 */
46184d9c625SLionel Sambuc 	if ((p = getenv("LINES")) != NULL)
46284d9c625SLionel Sambuc 		row = strtol(p, NULL, 10);
46384d9c625SLionel Sambuc 	if ((p = getenv("COLUMNS")) != NULL)
46484d9c625SLionel Sambuc 		col = strtol(p, NULL, 10);
46584d9c625SLionel Sambuc 
46684d9c625SLionel Sambuc 	if (rowp != NULL)
46784d9c625SLionel Sambuc 		*rowp = row;
46884d9c625SLionel Sambuc 	if (colp != NULL)
46984d9c625SLionel Sambuc 		*colp = col;
47084d9c625SLionel Sambuc 	return (0);
47184d9c625SLionel Sambuc }
47284d9c625SLionel Sambuc 
47384d9c625SLionel Sambuc /*
47484d9c625SLionel Sambuc  * cl_putchar --
47584d9c625SLionel Sambuc  *	Function version of putchar, for tputs.
47684d9c625SLionel Sambuc  *
47784d9c625SLionel Sambuc  * PUBLIC: int cl_putchar __P((int));
47884d9c625SLionel Sambuc  */
47984d9c625SLionel Sambuc int
cl_putchar(int ch)48084d9c625SLionel Sambuc cl_putchar(int ch)
48184d9c625SLionel Sambuc {
48284d9c625SLionel Sambuc 	return (putchar(ch));
48384d9c625SLionel Sambuc }
484