119304Speter/*-
219304Speter * Copyright (c) 1993, 1994
319304Speter *	The Regents of the University of California.  All rights reserved.
419304Speter * Copyright (c) 1993, 1994, 1995, 1996
519304Speter *	Keith Bostic.  All rights reserved.
619304Speter *
719304Speter * See the LICENSE file for redistribution information.
819304Speter */
919304Speter
1019304Speter#include "config.h"
1119304Speter
1219304Speter#ifndef lint
13254225Speterstatic const char sccsid[] = "$Id: cl_screen.c,v 10.56 2002/05/03 19:59:44 skimo Exp $";
1419304Speter#endif /* not lint */
1519304Speter
1619304Speter#include <sys/types.h>
1719304Speter#include <sys/queue.h>
18254225Speter#include <sys/time.h>
1919304Speter
2019304Speter#include <bitstring.h>
2119304Speter#include <errno.h>
2219304Speter#include <signal.h>
2319304Speter#include <stdio.h>
2419304Speter#include <stdlib.h>
2519304Speter#include <string.h>
26254225Speter#ifdef HAVE_TERM_H
27170371Srafan#include <term.h>
28254225Speter#endif
2919304Speter#include <termios.h>
3019304Speter#include <unistd.h>
3119304Speter
3219304Speter#include "../common/common.h"
3319304Speter#include "cl.h"
3419304Speter
3519304Speterstatic int	cl_ex_end __P((GS *));
3619304Speterstatic int	cl_ex_init __P((SCR *));
3719304Speterstatic void	cl_freecap __P((CL_PRIVATE *));
3819304Speterstatic int	cl_vi_end __P((GS *));
3919304Speterstatic int	cl_vi_init __P((SCR *));
4019304Speterstatic int	cl_putenv __P((char *, char *, u_long));
4119304Speter
4219304Speter/*
4319304Speter * cl_screen --
4419304Speter *	Switch screen types.
4519304Speter *
4619304Speter * PUBLIC: int cl_screen __P((SCR *, u_int32_t));
4719304Speter */
4819304Speterint
49254225Spetercl_screen(SCR *sp, u_int32_t flags)
5019304Speter{
5119304Speter	CL_PRIVATE *clp;
52254225Speter	WINDOW *win;
5319304Speter	GS *gp;
5419304Speter
5519304Speter	gp = sp->gp;
5619304Speter	clp = CLP(sp);
57254225Speter	win = CLSP(sp) ? CLSP(sp) : stdscr;
5819304Speter
5919304Speter	/* See if the current information is incorrect. */
6019304Speter	if (F_ISSET(gp, G_SRESTART)) {
61254225Speter		if (CLSP(sp)) {
62254225Speter		    delwin(CLSP(sp));
63254225Speter		    sp->cl_private = NULL;
64254225Speter		}
6519304Speter		if (cl_quit(gp))
6619304Speter			return (1);
6719304Speter		F_CLR(gp, G_SRESTART);
6819304Speter	}
6919304Speter
7019304Speter	/* See if we're already in the right mode. */
71254225Speter	if ((LF_ISSET(SC_EX) && F_ISSET(sp, SC_SCR_EX)) ||
72254225Speter	    (LF_ISSET(SC_VI) && F_ISSET(sp, SC_SCR_VI)))
7319304Speter		return (0);
7419304Speter
7519304Speter	/*
7619304Speter	 * Fake leaving ex mode.
7719304Speter	 *
7819304Speter	 * We don't actually exit ex or vi mode unless forced (e.g. by a window
7919304Speter	 * size change).  This is because many curses implementations can't be
8019304Speter	 * called twice in a single program.  Plus, it's faster.  If the editor
8119304Speter	 * "leaves" vi to enter ex, when it exits ex we'll just fall back into
8219304Speter	 * vi.
8319304Speter	 */
8419304Speter	if (F_ISSET(sp, SC_SCR_EX))
8519304Speter		F_CLR(sp, SC_SCR_EX);
8619304Speter
8719304Speter	/*
8819304Speter	 * Fake leaving vi mode.
8919304Speter	 *
9019304Speter	 * Clear out the rest of the screen if we're in the middle of a split
9119304Speter	 * screen.  Move to the last line in the current screen -- this makes
9219304Speter	 * terminal scrolling happen naturally.  Note: *don't* move past the
9319304Speter	 * end of the screen, as there are ex commands (e.g., :read ! cat file)
9419304Speter	 * that don't want to.  Don't clear the info line, its contents may be
9519304Speter	 * valid, e.g. :file|append.
9619304Speter	 */
9719304Speter	if (F_ISSET(sp, SC_SCR_VI)) {
9819304Speter		F_CLR(sp, SC_SCR_VI);
9919304Speter
100254225Speter		if (TAILQ_NEXT(sp, q) != NULL) {
101254225Speter			(void)wmove(win, RLNO(sp, sp->rows), 0);
102254225Speter			wclrtobot(win);
10319304Speter		}
104254225Speter		(void)wmove(win, RLNO(sp, sp->rows) - 1, 0);
105254225Speter		wrefresh(win);
10619304Speter	}
10719304Speter
10819304Speter	/* Enter the requested mode. */
10919304Speter	if (LF_ISSET(SC_EX)) {
11019304Speter		if (cl_ex_init(sp))
11119304Speter			return (1);
11219304Speter		F_SET(clp, CL_IN_EX | CL_SCR_EX_INIT);
11319304Speter
11419304Speter		/*
11519304Speter		 * If doing an ex screen for ex mode, move to the last line
11619304Speter		 * on the screen.
11719304Speter		 */
11819304Speter		if (F_ISSET(sp, SC_EX) && clp->cup != NULL)
11919304Speter			tputs(tgoto(clp->cup,
12019304Speter			    0, O_VAL(sp, O_LINES) - 1), 1, cl_putchar);
12119304Speter	} else {
12219304Speter		if (cl_vi_init(sp))
12319304Speter			return (1);
12419304Speter		F_CLR(clp, CL_IN_EX);
12519304Speter		F_SET(clp, CL_SCR_VI_INIT);
12619304Speter	}
12719304Speter	return (0);
12819304Speter}
12919304Speter
13019304Speter/*
13119304Speter * cl_quit --
13219304Speter *	Shutdown the screens.
13319304Speter *
13419304Speter * PUBLIC: int cl_quit __P((GS *));
13519304Speter */
13619304Speterint
137254225Spetercl_quit(GS *gp)
13819304Speter{
13919304Speter	CL_PRIVATE *clp;
14019304Speter	int rval;
14119304Speter
14219304Speter	rval = 0;
14319304Speter	clp = GCLP(gp);
14419304Speter
14519304Speter	/*
14619304Speter	 * If we weren't really running, ignore it.  This happens if the
14719304Speter	 * screen changes size before we've called curses.
14819304Speter	 */
14919304Speter	if (!F_ISSET(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT))
15019304Speter		return (0);
15119304Speter
15219304Speter	/* Clean up the terminal mappings. */
15319304Speter	if (cl_term_end(gp))
15419304Speter		rval = 1;
15519304Speter
15619304Speter	/* Really leave vi mode. */
15719304Speter	if (F_ISSET(clp, CL_STDIN_TTY) &&
15819304Speter	    F_ISSET(clp, CL_SCR_VI_INIT) && cl_vi_end(gp))
15919304Speter		rval = 1;
16019304Speter
16119304Speter	/* Really leave ex mode. */
16219304Speter	if (F_ISSET(clp, CL_STDIN_TTY) &&
16319304Speter	    F_ISSET(clp, CL_SCR_EX_INIT) && cl_ex_end(gp))
16419304Speter		rval = 1;
16519304Speter
16619304Speter	/*
16719304Speter	 * If we were running ex when we quit, or we're using an implementation
16819304Speter	 * of curses where endwin() doesn't get this right, restore the original
16919304Speter	 * terminal modes.
17019304Speter	 *
17119304Speter	 * XXX
17219304Speter	 * We always do this because it's too hard to figure out what curses
17319304Speter	 * implementations get it wrong.  It may discard type-ahead characters
17419304Speter	 * from the tty queue.
17519304Speter	 */
17619304Speter	(void)tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->orig);
17719304Speter
17819304Speter	F_CLR(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT);
17919304Speter	return (rval);
18019304Speter}
18119304Speter
18219304Speter/*
18319304Speter * cl_vi_init --
18419304Speter *	Initialize the curses vi screen.
18519304Speter */
18619304Speterstatic int
187254225Spetercl_vi_init(SCR *sp)
18819304Speter{
18919304Speter	CL_PRIVATE *clp;
19019304Speter	GS *gp;
19119304Speter	char *o_cols, *o_lines, *o_term, *ttype;
19219304Speter
19319304Speter	gp = sp->gp;
19419304Speter	clp = CLP(sp);
19519304Speter
19619304Speter	/* If already initialized, just set the terminal modes. */
19719304Speter	if (F_ISSET(clp, CL_SCR_VI_INIT))
19819304Speter		goto fast;
19919304Speter
20019304Speter	/* Curses vi always reads from (and writes to) a terminal. */
20119304Speter	if (!F_ISSET(clp, CL_STDIN_TTY) || !isatty(STDOUT_FILENO)) {
20219304Speter		msgq(sp, M_ERR,
20319304Speter		    "016|Vi's standard input and output must be a terminal");
20419304Speter		return (1);
20519304Speter	}
20619304Speter
20719304Speter	/* We'll need a terminal type. */
20819304Speter	if (opts_empty(sp, O_TERM, 0))
20919304Speter		return (1);
21019304Speter	ttype = O_STR(sp, O_TERM);
21119304Speter
21219304Speter	/*
21319304Speter	 * XXX
21419304Speter	 * Changing the row/column and terminal values is done by putting them
21519304Speter	 * into the environment, which is then read by curses.  What this loses
21619304Speter	 * in ugliness, it makes up for in stupidity.  We can't simply put the
21719304Speter	 * values into the environment ourselves, because in the presence of a
21819304Speter	 * kernel mechanism for returning the window size, entering values into
21919304Speter	 * the environment will screw up future screen resizing events, e.g. if
22019304Speter	 * the user enters a :shell command and then resizes their window.  So,
22119304Speter	 * if they weren't already in the environment, we make sure to delete
22219304Speter	 * them immediately after setting them.
22319304Speter	 *
22419304Speter	 * XXX
22519304Speter	 * Putting the TERM variable into the environment is necessary, even
22619304Speter	 * though we're using newterm() here.  We may be using initscr() as
22719304Speter	 * the underlying function.
22819304Speter	 */
22919304Speter	o_term = getenv("TERM");
23019304Speter	cl_putenv("TERM", ttype, 0);
23119304Speter	o_lines = getenv("LINES");
23219304Speter	cl_putenv("LINES", NULL, (u_long)O_VAL(sp, O_LINES));
23319304Speter	o_cols = getenv("COLUMNS");
23419304Speter	cl_putenv("COLUMNS", NULL, (u_long)O_VAL(sp, O_COLUMNS));
23519304Speter
23619304Speter	/*
23719304Speter	 * We don't care about the SCREEN reference returned by newterm, we
23819304Speter	 * never have more than one SCREEN at a time.
23919304Speter	 *
24019304Speter	 * XXX
24119304Speter	 * The SunOS initscr() can't be called twice.  Don't even think about
24219304Speter	 * using it.  It fails in subtle ways (e.g. select(2) on fileno(stdin)
24319304Speter	 * stops working).  (The SVID notes that applications should only call
24419304Speter	 * initscr() once.)
24519304Speter	 *
24619304Speter	 * XXX
24719304Speter	 * The HP/UX newterm doesn't support the NULL first argument, so we
24819304Speter	 * have to specify the terminal type.
24919304Speter	 */
250254225Speter	(void)del_curterm(cur_term);
25119304Speter	errno = 0;
25219304Speter	if (newterm(ttype, stdout, stdin) == NULL) {
25319304Speter		if (errno)
25419304Speter			msgq(sp, M_SYSERR, "%s", ttype);
25519304Speter		else
25619304Speter			msgq(sp, M_ERR, "%s: unknown terminal type", ttype);
25719304Speter		return (1);
25819304Speter	}
25919304Speter
26019304Speter	if (o_term == NULL)
26119304Speter		unsetenv("TERM");
26219304Speter	if (o_lines == NULL)
26319304Speter		unsetenv("LINES");
26419304Speter	if (o_cols == NULL)
26519304Speter		unsetenv("COLUMNS");
26619304Speter
26719304Speter	/*
26819304Speter	 * XXX
26919304Speter	 * Someone got let out alone without adult supervision -- the SunOS
27019304Speter	 * newterm resets the signal handlers.  There's a race, but it's not
27119304Speter	 * worth closing.
27219304Speter	 */
27319304Speter	(void)sig_init(sp->gp, sp);
27419304Speter
27519304Speter	/*
27619304Speter	 * We use raw mode.  What we want is 8-bit clean, however, signals
27719304Speter	 * and flow control should continue to work.  Admittedly, it sounds
27819304Speter	 * like cbreak, but it isn't.  Using cbreak() can get you additional
27919304Speter	 * things like IEXTEN, which turns on flags like DISCARD and LNEXT.
28019304Speter	 *
28119304Speter	 * !!!
28219304Speter	 * If raw isn't turning off echo and newlines, something's wrong.
28319304Speter	 * However, it shouldn't hurt.
28419304Speter	 */
28519304Speter	noecho();			/* No character echo. */
28619304Speter	nonl();				/* No CR/NL translation. */
28719304Speter	raw();				/* 8-bit clean. */
28819304Speter	idlok(stdscr, 1);		/* Use hardware insert/delete line. */
28919304Speter
29019304Speter	/* Put the cursor keys into application mode. */
29119304Speter	(void)keypad(stdscr, TRUE);
29219304Speter
29319304Speter	/*
29419304Speter	 * XXX
29519304Speter	 * The screen TI sequence just got sent.  See the comment in
29619304Speter	 * cl_funcs.c:cl_attr().
29719304Speter	 */
29819304Speter	clp->ti_te = TI_SENT;
29919304Speter
30019304Speter	/*
30119304Speter	 * XXX
30219304Speter	 * Historic implementations of curses handled SIGTSTP signals
30319304Speter	 * in one of three ways.  They either:
30419304Speter	 *
30519304Speter	 *	1: Set their own handler, regardless.
30619304Speter	 *	2: Did not set a handler if a handler was already installed.
30719304Speter	 *	3: Set their own handler, but then called any previously set
30819304Speter	 *	   handler after completing their own cleanup.
30919304Speter	 *
31019304Speter	 * We don't try and figure out which behavior is in place, we force
31119304Speter	 * it to SIG_DFL after initializing the curses interface, which means
31219304Speter	 * that curses isn't going to take the signal.  Since curses isn't
31319304Speter	 * reentrant (i.e., the whole curses SIGTSTP interface is a fantasy),
31419304Speter	 * we're doing The Right Thing.
31519304Speter	 */
31619304Speter	(void)signal(SIGTSTP, SIG_DFL);
31719304Speter
31819304Speter	/*
31919304Speter	 * If flow control was on, turn it back on.  Turn signals on.  ISIG
32019304Speter	 * turns on VINTR, VQUIT, VDSUSP and VSUSP.   The main curses code
32119304Speter	 * already installed a handler for VINTR.  We're going to disable the
32219304Speter	 * other three.
32319304Speter	 *
32419304Speter	 * XXX
32519304Speter	 * We want to use ^Y as a vi scrolling command.  If the user has the
32619304Speter	 * DSUSP character set to ^Y (common practice) clean it up.  As it's
32719304Speter	 * equally possible that the user has VDSUSP set to 'a', we disable
32819304Speter	 * it regardless.  It doesn't make much sense to suspend vi at read,
32919304Speter	 * so I don't think anyone will care.  Alternatively, we could look
33019304Speter	 * it up in the table of legal command characters and turn it off if
33119304Speter	 * it matches one.  VDSUSP wasn't in POSIX 1003.1-1990, so we test for
33219304Speter	 * it.
33319304Speter	 *
33419304Speter	 * XXX
33519304Speter	 * We don't check to see if the user had signals enabled originally.
33619304Speter	 * If they didn't, it's unclear what we're supposed to do here, but
33719304Speter	 * it's also pretty unlikely.
33819304Speter	 */
33919304Speter	if (tcgetattr(STDIN_FILENO, &clp->vi_enter)) {
34019304Speter		msgq(sp, M_SYSERR, "tcgetattr");
34119304Speter		goto err;
34219304Speter	}
34319304Speter	if (clp->orig.c_iflag & IXON)
34419304Speter		clp->vi_enter.c_iflag |= IXON;
34519304Speter	if (clp->orig.c_iflag & IXOFF)
34619304Speter		clp->vi_enter.c_iflag |= IXOFF;
34719304Speter
34819304Speter	clp->vi_enter.c_lflag |= ISIG;
34919304Speter#ifdef VDSUSP
35019304Speter	clp->vi_enter.c_cc[VDSUSP] = _POSIX_VDISABLE;
35119304Speter#endif
35219304Speter	clp->vi_enter.c_cc[VQUIT] = _POSIX_VDISABLE;
35319304Speter	clp->vi_enter.c_cc[VSUSP] = _POSIX_VDISABLE;
35419304Speter
35519304Speter	/*
35619304Speter	 * XXX
35719304Speter	 * OSF/1 doesn't turn off the <discard>, <literal-next> or <status>
35819304Speter	 * characters when curses switches into raw mode.  It should be OK
35919304Speter	 * to do it explicitly for everyone.
36019304Speter	 */
36119304Speter#ifdef VDISCARD
36219304Speter	clp->vi_enter.c_cc[VDISCARD] = _POSIX_VDISABLE;
36319304Speter#endif
36419304Speter#ifdef VLNEXT
36519304Speter	clp->vi_enter.c_cc[VLNEXT] = _POSIX_VDISABLE;
36619304Speter#endif
36719304Speter#ifdef VSTATUS
36819304Speter	clp->vi_enter.c_cc[VSTATUS] = _POSIX_VDISABLE;
36919304Speter#endif
37019304Speter
37119304Speter	/* Initialize terminal based information. */
37219304Speter	if (cl_term_init(sp))
37319304Speter		goto err;
37419304Speter
37519304Speterfast:	/* Set the terminal modes. */
37619304Speter	if (tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &clp->vi_enter)) {
37786201Srwatson		if (errno == EINTR)
37886201Srwatson			goto fast;
37919304Speter		msgq(sp, M_SYSERR, "tcsetattr");
38019304Spetererr:		(void)cl_vi_end(sp->gp);
38119304Speter		return (1);
38219304Speter	}
38319304Speter	return (0);
38419304Speter}
38519304Speter
38619304Speter/*
38719304Speter * cl_vi_end --
38819304Speter *	Shutdown the vi screen.
38919304Speter */
39019304Speterstatic int
391254225Spetercl_vi_end(GS *gp)
39219304Speter{
39319304Speter	CL_PRIVATE *clp;
39419304Speter
39519304Speter	clp = GCLP(gp);
39619304Speter
39719304Speter	/* Restore the cursor keys to normal mode. */
39819304Speter	(void)keypad(stdscr, FALSE);
39919304Speter
40019304Speter	/*
40119304Speter	 * If we were running vi when we quit, scroll the screen up a single
40219304Speter	 * line so we don't lose any information.
40319304Speter	 *
40419304Speter	 * Move to the bottom of the window (some endwin implementations don't
40519304Speter	 * do this for you).
40619304Speter	 */
40719304Speter	if (!F_ISSET(clp, CL_IN_EX)) {
40819304Speter		(void)move(0, 0);
40919304Speter		(void)deleteln();
41019304Speter		(void)move(LINES - 1, 0);
41119304Speter		(void)refresh();
41219304Speter	}
41319304Speter
41419304Speter	cl_freecap(clp);
41519304Speter
41619304Speter	/* End curses window. */
41719304Speter	(void)endwin();
41819304Speter
41919304Speter	/*
42019304Speter	 * XXX
42119304Speter	 * The screen TE sequence just got sent.  See the comment in
42219304Speter	 * cl_funcs.c:cl_attr().
42319304Speter	 */
42419304Speter	clp->ti_te = TE_SENT;
42519304Speter
42619304Speter	return (0);
42719304Speter}
42819304Speter
42919304Speter/*
43019304Speter * cl_ex_init --
43119304Speter *	Initialize the ex screen.
43219304Speter */
43319304Speterstatic int
434254225Spetercl_ex_init(SCR *sp)
43519304Speter{
43619304Speter	CL_PRIVATE *clp;
43719304Speter
43819304Speter	clp = CLP(sp);
43919304Speter
44019304Speter	/* If already initialized, just set the terminal modes. */
44119304Speter	if (F_ISSET(clp, CL_SCR_EX_INIT))
44219304Speter		goto fast;
44319304Speter
44419304Speter	/* If not reading from a file, we're done. */
44519304Speter	if (!F_ISSET(clp, CL_STDIN_TTY))
44619304Speter		return (0);
44719304Speter
44819304Speter	/* Get the ex termcap/terminfo strings. */
44919304Speter	(void)cl_getcap(sp, "cup", &clp->cup);
45019304Speter	(void)cl_getcap(sp, "smso", &clp->smso);
45119304Speter	(void)cl_getcap(sp, "rmso", &clp->rmso);
45219304Speter	(void)cl_getcap(sp, "el", &clp->el);
45319304Speter	(void)cl_getcap(sp, "cuu1", &clp->cuu1);
45419304Speter
45519304Speter	/* Enter_standout_mode and exit_standout_mode are paired. */
45619304Speter	if (clp->smso == NULL || clp->rmso == NULL) {
45719304Speter		if (clp->smso != NULL) {
45819304Speter			free(clp->smso);
45919304Speter			clp->smso = NULL;
46019304Speter		}
46119304Speter		if (clp->rmso != NULL) {
46219304Speter			free(clp->rmso);
46319304Speter			clp->rmso = NULL;
46419304Speter		}
46519304Speter	}
46619304Speter
46719304Speter	/*
46819304Speter	 * Turn on canonical mode, with normal input and output processing.
46919304Speter	 * Start with the original terminal settings as the user probably
47019304Speter	 * had them (including any local extensions) set correctly for the
47119304Speter	 * current terminal.
47219304Speter	 *
47319304Speter	 * !!!
47419304Speter	 * We can't get everything that we need portably; for example, ONLCR,
47519304Speter	 * mapping <newline> to <carriage-return> on output isn't required
47619304Speter	 * by POSIX 1003.1b-1993.  If this turns out to be a problem, then
47719304Speter	 * we'll either have to play some games on the mapping, or we'll have
47819304Speter	 * to make all ex printf's output \r\n instead of \n.
47919304Speter	 */
48019304Speter	clp->ex_enter = clp->orig;
48119304Speter	clp->ex_enter.c_lflag  |= ECHO | ECHOE | ECHOK | ICANON | IEXTEN | ISIG;
48219304Speter#ifdef ECHOCTL
48319304Speter	clp->ex_enter.c_lflag |= ECHOCTL;
48419304Speter#endif
48519304Speter#ifdef ECHOKE
48619304Speter	clp->ex_enter.c_lflag |= ECHOKE;
48719304Speter#endif
48819304Speter	clp->ex_enter.c_iflag |= ICRNL;
48919304Speter	clp->ex_enter.c_oflag |= OPOST;
49019304Speter#ifdef ONLCR
49119304Speter	clp->ex_enter.c_oflag |= ONLCR;
49219304Speter#endif
49319304Speter
49419304Speterfast:	if (tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->ex_enter)) {
49586201Srwatson		if (errno == EINTR)
49686201Srwatson			goto fast;
49719304Speter		msgq(sp, M_SYSERR, "tcsetattr");
49819304Speter		return (1);
49919304Speter	}
50019304Speter	return (0);
50119304Speter}
50219304Speter
50319304Speter/*
50419304Speter * cl_ex_end --
50519304Speter *	Shutdown the ex screen.
50619304Speter */
50719304Speterstatic int
508254225Spetercl_ex_end(GS *gp)
50919304Speter{
51019304Speter	CL_PRIVATE *clp;
51119304Speter
51219304Speter	clp = GCLP(gp);
51319304Speter
51419304Speter	cl_freecap(clp);
51519304Speter
51619304Speter	return (0);
51719304Speter}
51819304Speter
51919304Speter/*
52019304Speter * cl_getcap --
52119304Speter *	Retrieve termcap/terminfo strings.
52219304Speter *
52319304Speter * PUBLIC: int cl_getcap __P((SCR *, char *, char **));
52419304Speter */
52519304Speterint
526254225Spetercl_getcap(SCR *sp, char *name, char **elementp)
52719304Speter{
52819304Speter	size_t len;
52919304Speter	char *t;
53019304Speter
53119304Speter	if ((t = tigetstr(name)) != NULL &&
53219304Speter	    t != (char *)-1 && (len = strlen(t)) != 0) {
53319304Speter		MALLOC_RET(sp, *elementp, char *, len + 1);
53419304Speter		memmove(*elementp, t, len + 1);
53519304Speter	}
53619304Speter	return (0);
53719304Speter}
53819304Speter
53919304Speter/*
54019304Speter * cl_freecap --
54119304Speter *	Free any allocated termcap/terminfo strings.
54219304Speter */
54319304Speterstatic void
544254225Spetercl_freecap(CL_PRIVATE *clp)
54519304Speter{
54619304Speter	if (clp->el != NULL) {
54719304Speter		free(clp->el);
54819304Speter		clp->el = NULL;
54919304Speter	}
55019304Speter	if (clp->cup != NULL) {
55119304Speter		free(clp->cup);
55219304Speter		clp->cup = NULL;
55319304Speter	}
55419304Speter	if (clp->cuu1 != NULL) {
55519304Speter		free(clp->cuu1);
55619304Speter		clp->cuu1 = NULL;
55719304Speter	}
55819304Speter	if (clp->rmso != NULL) {
55919304Speter		free(clp->rmso);
56019304Speter		clp->rmso = NULL;
56119304Speter	}
56219304Speter	if (clp->smso != NULL) {
56319304Speter		free(clp->smso);
56419304Speter		clp->smso = NULL;
56519304Speter	}
566254225Speter	/* Required by libcursesw :) */
567254225Speter	if (clp->cw.bp1.c != NULL) {
568254225Speter		free(clp->cw.bp1.c);
569254225Speter		clp->cw.bp1.c = NULL;
570254225Speter		clp->cw.blen1 = 0;
571254225Speter	}
57219304Speter}
57319304Speter
57419304Speter/*
57519304Speter * cl_putenv --
57619304Speter *	Put a value into the environment.
57719304Speter */
57819304Speterstatic int
579254225Spetercl_putenv(char *name, char *str, u_long value)
58019304Speter{
58119304Speter	char buf[40];
58219304Speter
58319304Speter	if (str == NULL) {
58419304Speter		(void)snprintf(buf, sizeof(buf), "%lu", value);
58519304Speter		return (setenv(name, buf, 1));
58619304Speter	} else
58719304Speter		return (setenv(name, str, 1));
58819304Speter}
589