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