| 1 |  |  | /*	$OpenBSD: cl_funcs.c,v 1.20 2016/05/27 09:18:11 martijn Exp $	*/ | 
    
    | 2 |  |  |  | 
    
    | 3 |  |  | /*- | 
    
    | 4 |  |  |  * Copyright (c) 1993, 1994 | 
    
    | 5 |  |  |  *	The Regents of the University of California.  All rights reserved. | 
    
    | 6 |  |  |  * Copyright (c) 1993, 1994, 1995, 1996 | 
    
    | 7 |  |  |  *	Keith Bostic.  All rights reserved. | 
    
    | 8 |  |  |  * | 
    
    | 9 |  |  |  * See the LICENSE file for redistribution information. | 
    
    | 10 |  |  |  */ | 
    
    | 11 |  |  |  | 
    
    | 12 |  |  | #include "config.h" | 
    
    | 13 |  |  |  | 
    
    | 14 |  |  | #include <sys/types.h> | 
    
    | 15 |  |  | #include <sys/queue.h> | 
    
    | 16 |  |  | #include <sys/time.h> | 
    
    | 17 |  |  |  | 
    
    | 18 |  |  | #include <bitstring.h> | 
    
    | 19 |  |  | #include <ctype.h> | 
    
    | 20 |  |  | #include <curses.h> | 
    
    | 21 |  |  | #include <signal.h> | 
    
    | 22 |  |  | #include <stdio.h> | 
    
    | 23 |  |  | #include <stdlib.h> | 
    
    | 24 |  |  | #include <string.h> | 
    
    | 25 |  |  | #include <term.h> | 
    
    | 26 |  |  | #include <termios.h> | 
    
    | 27 |  |  | #include <unistd.h> | 
    
    | 28 |  |  |  | 
    
    | 29 |  |  | #include "../common/common.h" | 
    
    | 30 |  |  | #include "../vi/vi.h" | 
    
    | 31 |  |  | #include "cl.h" | 
    
    | 32 |  |  |  | 
    
    | 33 |  |  | /* | 
    
    | 34 |  |  |  * cl_addstr -- | 
    
    | 35 |  |  |  *	Add len bytes from the string at the cursor, advancing the cursor. | 
    
    | 36 |  |  |  * | 
    
    | 37 |  |  |  * PUBLIC: int cl_addstr(SCR *, const char *, size_t); | 
    
    | 38 |  |  |  */ | 
    
    | 39 |  |  | int | 
    
    | 40 |  |  | cl_addstr(SCR *sp, const char *str, size_t len) | 
    
    | 41 |  |  | { | 
    
    | 42 |  |  | 	size_t oldy, oldx; | 
    
    | 43 |  |  | 	int iv; | 
    
    | 44 |  |  |  | 
    
    | 45 |  |  | 	/* | 
    
    | 46 |  |  | 	 * If ex isn't in control, it's the last line of the screen and | 
    
    | 47 |  |  | 	 * it's a split screen, use inverse video. | 
    
    | 48 |  |  | 	 */ | 
    
    | 49 |  |  | 	iv = 0; | 
    
    | 50 |  |  | 	getyx(stdscr, oldy, oldx); | 
    
    | 51 |  |  | 	if (!F_ISSET(sp, SC_SCR_EXWROTE) && | 
    
    | 52 |  |  | 	    oldy == RLNO(sp, LASTLINE(sp)) && IS_SPLIT(sp)) { | 
    
    | 53 |  |  | 		iv = 1; | 
    
    | 54 |  |  | 		(void)standout(); | 
    
    | 55 |  |  | 	} | 
    
    | 56 |  |  |  | 
    
    | 57 |  |  | 	if (addnstr(str, len) == ERR) | 
    
    | 58 |  |  | 		return (1); | 
    
    | 59 |  |  |  | 
    
    | 60 |  |  | 	if (iv) | 
    
    | 61 |  |  | 		(void)standend(); | 
    
    | 62 |  |  | 	return (0); | 
    
    | 63 |  |  | } | 
    
    | 64 |  |  |  | 
    
    | 65 |  |  | /* | 
    
    | 66 |  |  |  * cl_attr -- | 
    
    | 67 |  |  |  *	Toggle a screen attribute on/off. | 
    
    | 68 |  |  |  * | 
    
    | 69 |  |  |  * PUBLIC: int cl_attr(SCR *, scr_attr_t, int); | 
    
    | 70 |  |  |  */ | 
    
    | 71 |  |  | int | 
    
    | 72 |  |  | cl_attr(SCR *sp, scr_attr_t attribute, int on) | 
    
    | 73 |  |  | { | 
    
    | 74 |  |  | 	CL_PRIVATE *clp; | 
    
    | 75 |  |  |  | 
    
    | 76 |  |  | 	clp = CLP(sp); | 
    
    | 77 |  |  |  | 
    
    | 78 |  |  | 	switch (attribute) { | 
    
    | 79 |  |  | 	case SA_ALTERNATE: | 
    
    | 80 |  |  | 	/* | 
    
    | 81 |  |  | 	 * !!! | 
    
    | 82 |  |  | 	 * There's a major layering violation here.  The problem is that the | 
    
    | 83 |  |  | 	 * X11 xterm screen has what's known as an "alternate" screen.  Some | 
    
    | 84 |  |  | 	 * xterm termcap/terminfo entries include sequences to switch to/from | 
    
    | 85 |  |  | 	 * that alternate screen as part of the ti/te (smcup/rmcup) strings. | 
    
    | 86 |  |  | 	 * Vi runs in the alternate screen, so that you are returned to the | 
    
    | 87 |  |  | 	 * same screen contents on exit from vi that you had when you entered | 
    
    | 88 |  |  | 	 * vi.  Further, when you run :shell, or :!date or similar ex commands, | 
    
    | 89 |  |  | 	 * you also see the original screen contents.  This wasn't deliberate | 
    
    | 90 |  |  | 	 * on vi's part, it's just that it historically sent terminal init/end | 
    
    | 91 |  |  | 	 * sequences at those times, and the addition of the alternate screen | 
    
    | 92 |  |  | 	 * sequences to the strings changed the behavior of vi.  The problem | 
    
    | 93 |  |  | 	 * caused by this is that we don't want to switch back to the alternate | 
    
    | 94 |  |  | 	 * screen while getting a new command from the user, when the user is | 
    
    | 95 |  |  | 	 * continuing to enter ex commands, e.g.: | 
    
    | 96 |  |  | 	 * | 
    
    | 97 |  |  | 	 *	:!date				<<< switch to original screen | 
    
    | 98 |  |  | 	 *	[Hit return to continue]	<<< prompt user to continue | 
    
    | 99 |  |  | 	 *	:command			<<< get command from user | 
    
    | 100 |  |  | 	 * | 
    
    | 101 |  |  | 	 * Note that the :command input is a true vi input mode, e.g., input | 
    
    | 102 |  |  | 	 * maps and abbreviations are being done.  So, we need to be able to | 
    
    | 103 |  |  | 	 * switch back into the vi screen mode, without flashing the screen. | 
    
    | 104 |  |  | 	 * | 
    
    | 105 |  |  | 	 * To make matters worse, the curses initscr() and endwin() calls will | 
    
    | 106 |  |  | 	 * do this automatically -- so, this attribute isn't as controlled by | 
    
    | 107 |  |  | 	 * the higher level screen as closely as one might like. | 
    
    | 108 |  |  | 	 */ | 
    
    | 109 |  |  | 	if (on) { | 
    
    | 110 |  |  | 		if (clp->ti_te != TI_SENT) { | 
    
    | 111 |  |  | 			clp->ti_te = TI_SENT; | 
    
    | 112 |  |  | 			if (clp->smcup == NULL) | 
    
    | 113 |  |  | 				(void)cl_getcap(sp, "smcup", &clp->smcup); | 
    
    | 114 |  |  | 			if (clp->smcup != NULL) | 
    
    | 115 |  |  | 				(void)tputs(clp->smcup, 1, cl_putchar); | 
    
    | 116 |  |  | 		} | 
    
    | 117 |  |  | 	} else | 
    
    | 118 |  |  | 		if (clp->ti_te != TE_SENT) { | 
    
    | 119 |  |  | 			clp->ti_te = TE_SENT; | 
    
    | 120 |  |  | 			if (clp->rmcup == NULL) | 
    
    | 121 |  |  | 				(void)cl_getcap(sp, "rmcup", &clp->rmcup); | 
    
    | 122 |  |  | 			if (clp->rmcup != NULL) | 
    
    | 123 |  |  | 				(void)tputs(clp->rmcup, 1, cl_putchar); | 
    
    | 124 |  |  | 			(void)fflush(stdout); | 
    
    | 125 |  |  | 		} | 
    
    | 126 |  |  | 		(void)fflush(stdout); | 
    
    | 127 |  |  | 		break; | 
    
    | 128 |  |  | 	case SA_INVERSE: | 
    
    | 129 |  |  | 		if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE)) { | 
    
    | 130 |  |  | 			if (clp->smso == NULL) | 
    
    | 131 |  |  | 				return (1); | 
    
    | 132 |  |  | 			if (on) | 
    
    | 133 |  |  | 				(void)tputs(clp->smso, 1, cl_putchar); | 
    
    | 134 |  |  | 			else | 
    
    | 135 |  |  | 				(void)tputs(clp->rmso, 1, cl_putchar); | 
    
    | 136 |  |  | 			(void)fflush(stdout); | 
    
    | 137 |  |  | 		} else { | 
    
    | 138 |  |  | 			if (on) | 
    
    | 139 |  |  | 				(void)standout(); | 
    
    | 140 |  |  | 			else | 
    
    | 141 |  |  | 				(void)standend(); | 
    
    | 142 |  |  | 		} | 
    
    | 143 |  |  | 		break; | 
    
    | 144 |  |  | 	default: | 
    
    | 145 |  |  | 		abort(); | 
    
    | 146 |  |  | 	} | 
    
    | 147 |  |  | 	return (0); | 
    
    | 148 |  |  | } | 
    
    | 149 |  |  |  | 
    
    | 150 |  |  | /* | 
    
    | 151 |  |  |  * cl_baud -- | 
    
    | 152 |  |  |  *	Return the baud rate. | 
    
    | 153 |  |  |  * | 
    
    | 154 |  |  |  * PUBLIC: int cl_baud(SCR *, u_long *); | 
    
    | 155 |  |  |  */ | 
    
    | 156 |  |  | int | 
    
    | 157 |  |  | cl_baud(SCR *sp, u_long *ratep) | 
    
    | 158 |  |  | { | 
    
    | 159 |  |  | 	CL_PRIVATE *clp; | 
    
    | 160 |  |  |  | 
    
    | 161 |  |  | 	/* | 
    
    | 162 |  |  | 	 * XXX | 
    
    | 163 |  |  | 	 * There's no portable way to get a "baud rate" -- cfgetospeed(3) | 
    
    | 164 |  |  | 	 * returns the value associated with some #define, which we may | 
    
    | 165 |  |  | 	 * never have heard of, or which may be a purely local speed.  Vi | 
    
    | 166 |  |  | 	 * only cares if it's SLOW (w300), slow (w1200) or fast (w9600). | 
    
    | 167 |  |  | 	 * Try and detect the slow ones, and default to fast. | 
    
    | 168 |  |  | 	 */ | 
    
    | 169 |  |  | 	clp = CLP(sp); | 
    
    | 170 |  |  | 	switch (cfgetospeed(&clp->orig)) { | 
    
    | 171 |  |  | 	case B50: | 
    
    | 172 |  |  | 	case B75: | 
    
    | 173 |  |  | 	case B110: | 
    
    | 174 |  |  | 	case B134: | 
    
    | 175 |  |  | 	case B150: | 
    
    | 176 |  |  | 	case B200: | 
    
    | 177 |  |  | 	case B300: | 
    
    | 178 |  |  | 	case B600: | 
    
    | 179 |  |  | 		*ratep = 600; | 
    
    | 180 |  |  | 		break; | 
    
    | 181 |  |  | 	case B1200: | 
    
    | 182 |  |  | 		*ratep = 1200; | 
    
    | 183 |  |  | 		break; | 
    
    | 184 |  |  | 	default: | 
    
    | 185 |  |  | 		*ratep = 9600; | 
    
    | 186 |  |  | 		break; | 
    
    | 187 |  |  | 	} | 
    
    | 188 |  |  | 	return (0); | 
    
    | 189 |  |  | } | 
    
    | 190 |  |  |  | 
    
    | 191 |  |  | /* | 
    
    | 192 |  |  |  * cl_bell -- | 
    
    | 193 |  |  |  *	Ring the bell/flash the screen. | 
    
    | 194 |  |  |  * | 
    
    | 195 |  |  |  * PUBLIC: int cl_bell(SCR *); | 
    
    | 196 |  |  |  */ | 
    
    | 197 |  |  | int | 
    
    | 198 |  |  | cl_bell(SCR *sp) | 
    
    | 199 |  |  | { | 
    
    | 200 |  |  | 	if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE)) | 
    
    | 201 |  |  | 		(void)write(STDOUT_FILENO, "\07", 1);		/* \a */ | 
    
    | 202 |  |  | 	else { | 
    
    | 203 |  |  | 		/* | 
    
    | 204 |  |  | 		 * If the screen has not been setup we cannot call | 
    
    | 205 |  |  | 		 * curses routines yet. | 
    
    | 206 |  |  | 		 */ | 
    
    | 207 |  |  | 		if (F_ISSET(sp, SC_SCR_VI)) { | 
    
    | 208 |  |  | 			/* | 
    
    | 209 |  |  | 			 * Vi has an edit option which determines if the | 
    
    | 210 |  |  | 			 * terminal should be beeped or the screen flashed. | 
    
    | 211 |  |  | 			 */ | 
    
    | 212 |  |  | 			if (O_ISSET(sp, O_FLASH)) | 
    
    | 213 |  |  | 				(void)flash(); | 
    
    | 214 |  |  | 			else | 
    
    | 215 |  |  | 				(void)beep(); | 
    
    | 216 |  |  | 		} else if (!O_ISSET(sp, O_FLASH)) | 
    
    | 217 |  |  | 			(void)write(STDOUT_FILENO, "\07", 1); | 
    
    | 218 |  |  | 	} | 
    
    | 219 |  |  | 	return (0); | 
    
    | 220 |  |  | } | 
    
    | 221 |  |  |  | 
    
    | 222 |  |  | /* | 
    
    | 223 |  |  |  * cl_clrtoeol -- | 
    
    | 224 |  |  |  *	Clear from the current cursor to the end of the line. | 
    
    | 225 |  |  |  * | 
    
    | 226 |  |  |  * PUBLIC: int cl_clrtoeol(SCR *); | 
    
    | 227 |  |  |  */ | 
    
    | 228 |  |  | int | 
    
    | 229 |  |  | cl_clrtoeol(SCR *sp) | 
    
    | 230 |  |  | { | 
    
    | 231 |  |  | 	return (clrtoeol() == ERR); | 
    
    | 232 |  |  | } | 
    
    | 233 |  |  |  | 
    
    | 234 |  |  | /* | 
    
    | 235 |  |  |  * cl_cursor -- | 
    
    | 236 |  |  |  *	Return the current cursor position. | 
    
    | 237 |  |  |  * | 
    
    | 238 |  |  |  * PUBLIC: int cl_cursor(SCR *, size_t *, size_t *); | 
    
    | 239 |  |  |  */ | 
    
    | 240 |  |  | int | 
    
    | 241 |  |  | cl_cursor(SCR *sp, size_t *yp, size_t *xp) | 
    
    | 242 |  |  | { | 
    
    | 243 |  |  | 	/* | 
    
    | 244 |  |  | 	 * The curses screen support splits a single underlying curses screen | 
    
    | 245 |  |  | 	 * into multiple screens to support split screen semantics.  For this | 
    
    | 246 |  |  | 	 * reason the returned value must be adjusted to be relative to the | 
    
    | 247 |  |  | 	 * current screen, and not absolute.  Screens that implement the split | 
    
    | 248 |  |  | 	 * using physically distinct screens won't need this hack. | 
    
    | 249 |  |  | 	 */ | 
    
    | 250 |  |  | 	getyx(stdscr, *yp, *xp); | 
    
    | 251 |  |  | 	*yp -= sp->woff; | 
    
    | 252 |  |  | 	return (0); | 
    
    | 253 |  |  | } | 
    
    | 254 |  |  |  | 
    
    | 255 |  |  | /* | 
    
    | 256 |  |  |  * cl_deleteln -- | 
    
    | 257 |  |  |  *	Delete the current line, scrolling all lines below it. | 
    
    | 258 |  |  |  * | 
    
    | 259 |  |  |  * PUBLIC: int cl_deleteln(SCR *); | 
    
    | 260 |  |  |  */ | 
    
    | 261 |  |  | int | 
    
    | 262 |  |  | cl_deleteln(SCR *sp) | 
    
    | 263 |  |  | { | 
    
    | 264 |  |  | 	size_t oldy, oldx; | 
    
    | 265 |  |  |  | 
    
    | 266 |  |  | 	/* | 
    
    | 267 |  |  | 	 * This clause is required because the curses screen uses reverse | 
    
    | 268 |  |  | 	 * video to delimit split screens.  If the screen does not do this, | 
    
    | 269 |  |  | 	 * this code won't be necessary. | 
    
    | 270 |  |  | 	 * | 
    
    | 271 |  |  | 	 * If the bottom line was in reverse video, rewrite it in normal | 
    
    | 272 |  |  | 	 * video before it's scrolled. | 
    
    | 273 |  |  | 	 * | 
    
    | 274 |  |  | 	 * Check for the existence of a chgat function; XSI requires it, but | 
    
    | 275 |  |  | 	 * historic implementations of System V curses don't.   If it's not | 
    
    | 276 |  |  | 	 * a #define, we'll fall back to doing it by hand, which is slow but | 
    
    | 277 |  |  | 	 * acceptable. | 
    
    | 278 |  |  | 	 * | 
    
    | 279 |  |  | 	 * By hand means walking through the line, retrieving and rewriting | 
    
    | 280 |  |  | 	 * each character.  Curses has no EOL marker, so track strings of | 
    
    | 281 |  |  | 	 * spaces, and copy the trailing spaces only if there's a non-space | 
    
    | 282 |  |  | 	 * character following. | 
    
    | 283 |  |  | 	 */ | 
    
    | 284 |  |  | 	if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) { | 
    
    | 285 |  |  | 		getyx(stdscr, oldy, oldx); | 
    
    | 286 |  |  | 		mvchgat(RLNO(sp, LASTLINE(sp)), 0, -1, A_NORMAL, 0, NULL); | 
    
    | 287 |  |  | 		(void)move(oldy, oldx); | 
    
    | 288 |  |  | 	} | 
    
    | 289 |  |  |  | 
    
    | 290 |  |  | 	/* | 
    
    | 291 |  |  | 	 * The bottom line is expected to be blank after this operation, | 
    
    | 292 |  |  | 	 * and other screens must support that semantic. | 
    
    | 293 |  |  | 	 */ | 
    
    | 294 |  |  | 	return (deleteln() == ERR); | 
    
    | 295 |  |  | } | 
    
    | 296 |  |  |  | 
    
    | 297 |  |  | /* | 
    
    | 298 |  |  |  * cl_ex_adjust -- | 
    
    | 299 |  |  |  *	Adjust the screen for ex.  This routine is purely for standalone | 
    
    | 300 |  |  |  *	ex programs.  All special purpose, all special case. | 
    
    | 301 |  |  |  * | 
    
    | 302 |  |  |  * PUBLIC: int cl_ex_adjust(SCR *, exadj_t); | 
    
    | 303 |  |  |  */ | 
    
    | 304 |  |  | int | 
    
    | 305 |  |  | cl_ex_adjust(SCR *sp, exadj_t action) | 
    
    | 306 |  |  | { | 
    
    | 307 |  |  | 	CL_PRIVATE *clp; | 
    
    | 308 |  |  | 	int cnt; | 
    
    | 309 |  |  |  | 
    
    | 310 |  |  | 	clp = CLP(sp); | 
    
    | 311 |  |  | 	switch (action) { | 
    
    | 312 |  |  | 	case EX_TERM_SCROLL: | 
    
    | 313 |  |  | 		/* Move the cursor up one line if that's possible. */ | 
    
    | 314 |  |  | 		if (clp->cuu1 != NULL) | 
    
    | 315 |  |  | 			(void)tputs(clp->cuu1, 1, cl_putchar); | 
    
    | 316 |  |  | 		else if (clp->cup != NULL) | 
    
    | 317 |  |  | 			(void)tputs(tgoto(clp->cup, | 
    
    | 318 |  |  | 			    0, LINES - 2), 1, cl_putchar); | 
    
    | 319 |  |  | 		else | 
    
    | 320 |  |  | 			return (0); | 
    
    | 321 |  |  | 		/* FALLTHROUGH */ | 
    
    | 322 |  |  | 	case EX_TERM_CE: | 
    
    | 323 |  |  | 		/* Clear the line. */ | 
    
    | 324 |  |  | 		if (clp->el != NULL) { | 
    
    | 325 |  |  | 			(void)putchar('\r'); | 
    
    | 326 |  |  | 			(void)tputs(clp->el, 1, cl_putchar); | 
    
    | 327 |  |  | 		} else { | 
    
    | 328 |  |  | 			/* | 
    
    | 329 |  |  | 			 * Historically, ex didn't erase the line, so, if the | 
    
    | 330 |  |  | 			 * displayed line was only a single glyph, and <eof> | 
    
    | 331 |  |  | 			 * was more than one glyph, the output would not fully | 
    
    | 332 |  |  | 			 * overwrite the user's input.  To fix this, output | 
    
    | 333 |  |  | 			 * the maxiumum character number of spaces.  Note, | 
    
    | 334 |  |  | 			 * this won't help if the user entered extra prompt | 
    
    | 335 |  |  | 			 * or <blank> characters before the command character. | 
    
    | 336 |  |  | 			 * We'd have to do a lot of work to make that work, and | 
    
    | 337 |  |  | 			 * it's almost certainly not worth the effort. | 
    
    | 338 |  |  | 			 */ | 
    
    | 339 |  |  | 			for (cnt = 0; cnt < MAX_CHARACTER_COLUMNS; ++cnt) | 
    
    | 340 |  |  | 				(void)putchar('\b'); | 
    
    | 341 |  |  | 			for (cnt = 0; cnt < MAX_CHARACTER_COLUMNS; ++cnt) | 
    
    | 342 |  |  | 				(void)putchar(' '); | 
    
    | 343 |  |  | 			(void)putchar('\r'); | 
    
    | 344 |  |  | 			(void)fflush(stdout); | 
    
    | 345 |  |  | 		} | 
    
    | 346 |  |  | 		break; | 
    
    | 347 |  |  | 	default: | 
    
    | 348 |  |  | 		abort(); | 
    
    | 349 |  |  | 	} | 
    
    | 350 |  |  | 	return (0); | 
    
    | 351 |  |  | } | 
    
    | 352 |  |  |  | 
    
    | 353 |  |  | /* | 
    
    | 354 |  |  |  * cl_insertln -- | 
    
    | 355 |  |  |  *	Push down the current line, discarding the bottom line. | 
    
    | 356 |  |  |  * | 
    
    | 357 |  |  |  * PUBLIC: int cl_insertln(SCR *); | 
    
    | 358 |  |  |  */ | 
    
    | 359 |  |  | int | 
    
    | 360 |  |  | cl_insertln(SCR *sp) | 
    
    | 361 |  |  | { | 
    
    | 362 |  |  | 	/* | 
    
    | 363 |  |  | 	 * The current line is expected to be blank after this operation, | 
    
    | 364 |  |  | 	 * and the screen must support that semantic. | 
    
    | 365 |  |  | 	 */ | 
    
    | 366 |  |  | 	return (insertln() == ERR); | 
    
    | 367 |  |  | } | 
    
    | 368 |  |  |  | 
    
    | 369 |  |  | /* | 
    
    | 370 |  |  |  * cl_keyval -- | 
    
    | 371 |  |  |  *	Return the value for a special key. | 
    
    | 372 |  |  |  * | 
    
    | 373 |  |  |  * PUBLIC: int cl_keyval(SCR *, scr_keyval_t, CHAR_T *, int *); | 
    
    | 374 |  |  |  */ | 
    
    | 375 |  |  | int | 
    
    | 376 |  |  | cl_keyval(SCR *sp, scr_keyval_t val, CHAR_T *chp, int *dnep) | 
    
    | 377 |  |  | { | 
    
    | 378 |  |  | 	CL_PRIVATE *clp; | 
    
    | 379 |  |  |  | 
    
    | 380 |  |  | 	/* | 
    
    | 381 |  |  | 	 * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990, | 
    
    | 382 |  |  | 	 * VWERASE is a 4BSD extension. | 
    
    | 383 |  |  | 	 */ | 
    
    | 384 |  |  | 	clp = CLP(sp); | 
    
    | 385 |  |  | 	switch (val) { | 
    
    | 386 |  |  | 	case KEY_VEOF: | 
    
    | 387 |  |  | 		*dnep = (*chp = clp->orig.c_cc[VEOF]) == _POSIX_VDISABLE; | 
    
    | 388 |  |  | 		break; | 
    
    | 389 |  |  | 	case KEY_VERASE: | 
    
    | 390 |  |  | 		*dnep = (*chp = clp->orig.c_cc[VERASE]) == _POSIX_VDISABLE; | 
    
    | 391 |  |  | 		break; | 
    
    | 392 |  |  | 	case KEY_VKILL: | 
    
    | 393 |  |  | 		*dnep = (*chp = clp->orig.c_cc[VKILL]) == _POSIX_VDISABLE; | 
    
    | 394 |  |  | 		break; | 
    
    | 395 |  |  | 	case KEY_VWERASE: | 
    
    | 396 |  |  | 		*dnep = (*chp = clp->orig.c_cc[VWERASE]) == _POSIX_VDISABLE; | 
    
    | 397 |  |  | 		break; | 
    
    | 398 |  |  | 	default: | 
    
    | 399 |  |  | 		*dnep = 1; | 
    
    | 400 |  |  | 		break; | 
    
    | 401 |  |  | 	} | 
    
    | 402 |  |  | 	return (0); | 
    
    | 403 |  |  | } | 
    
    | 404 |  |  |  | 
    
    | 405 |  |  | /* | 
    
    | 406 |  |  |  * cl_move -- | 
    
    | 407 |  |  |  *	Move the cursor. | 
    
    | 408 |  |  |  * | 
    
    | 409 |  |  |  * PUBLIC: int cl_move(SCR *, size_t, size_t); | 
    
    | 410 |  |  |  */ | 
    
    | 411 |  |  | int | 
    
    | 412 |  |  | cl_move(SCR *sp, size_t lno, size_t cno) | 
    
    | 413 |  |  | { | 
    
    | 414 |  |  | 	/* See the comment in cl_cursor. */ | 
    
    | 415 |  |  | 	if (move(RLNO(sp, lno), cno) == ERR) { | 
    
    | 416 |  |  | 		msgq(sp, M_ERR, | 
    
    | 417 |  |  | 		    "Error: move: l(%u) c(%u) o(%u)", lno, cno, sp->woff); | 
    
    | 418 |  |  | 		return (1); | 
    
    | 419 |  |  | 	} | 
    
    | 420 |  |  | 	return (0); | 
    
    | 421 |  |  | } | 
    
    | 422 |  |  |  | 
    
    | 423 |  |  | /* | 
    
    | 424 |  |  |  * cl_refresh -- | 
    
    | 425 |  |  |  *	Refresh the screen. | 
    
    | 426 |  |  |  * | 
    
    | 427 |  |  |  * PUBLIC: int cl_refresh(SCR *, int); | 
    
    | 428 |  |  |  */ | 
    
    | 429 |  |  | int | 
    
    | 430 |  |  | cl_refresh(SCR *sp, int repaint) | 
    
    | 431 |  |  | { | 
    
    | 432 |  |  | 	CL_PRIVATE *clp; | 
    
    | 433 |  |  |  | 
    
    | 434 |  |  | 	clp = CLP(sp); | 
    
    | 435 |  |  |  | 
    
    | 436 |  |  | 	/* | 
    
    | 437 |  |  | 	 * If we received a killer signal, we're done, there's no point | 
    
    | 438 |  |  | 	 * in refreshing the screen. | 
    
    | 439 |  |  | 	 */ | 
    
    | 440 |  |  | 	if (clp->killersig) | 
    
    | 441 |  |  | 		return (0); | 
    
    | 442 |  |  |  | 
    
    | 443 |  |  | 	/* | 
    
    | 444 |  |  | 	 * If repaint is set, the editor is telling us that we don't know | 
    
    | 445 |  |  | 	 * what's on the screen, so we have to repaint from scratch. | 
    
    | 446 |  |  | 	 * | 
    
    | 447 |  |  | 	 * In the curses library, doing wrefresh(curscr) is okay, but the | 
    
    | 448 |  |  | 	 * screen flashes when we then apply the refresh() to bring it up | 
    
    | 449 |  |  | 	 * to date.  So, use clearok(). | 
    
    | 450 |  |  | 	 */ | 
    
    | 451 |  |  | 	if (repaint) | 
    
    | 452 |  |  | 		clearok(curscr, 1); | 
    
    | 453 |  |  | 	return (refresh() == ERR); | 
    
    | 454 |  |  | } | 
    
    | 455 |  |  |  | 
    
    | 456 |  |  | /* | 
    
    | 457 |  |  |  * cl_rename -- | 
    
    | 458 |  |  |  *	Rename the file. | 
    
    | 459 |  |  |  * | 
    
    | 460 |  |  |  * PUBLIC: int cl_rename(SCR *, char *, int); | 
    
    | 461 |  |  |  */ | 
    
    | 462 |  |  | int | 
    
    | 463 |  |  | cl_rename(SCR *sp, char *name, int on) | 
    
    | 464 |  |  | { | 
    
    | 465 |  |  | 	GS *gp; | 
    
    | 466 |  |  | 	CL_PRIVATE *clp; | 
    
    | 467 |  |  | 	char *ttype; | 
    
    | 468 |  |  |  | 
    
    | 469 |  |  | 	gp = sp->gp; | 
    
    | 470 |  |  | 	clp = CLP(sp); | 
    
    | 471 |  |  |  | 
    
    | 472 |  |  | 	ttype = OG_STR(gp, GO_TERM); | 
    
    | 473 |  |  |  | 
    
    | 474 |  |  | 	/* | 
    
    | 475 |  |  | 	 * XXX | 
    
    | 476 |  |  | 	 * We can only rename windows for xterm. | 
    
    | 477 |  |  | 	 */ | 
    
    | 478 |  |  | 	if (on) { | 
    
    | 479 |  |  | 		if (F_ISSET(clp, CL_RENAME_OK) && | 
    
    | 480 |  |  | 		    !strncmp(ttype, "xterm", sizeof("xterm") - 1)) { | 
    
    | 481 |  |  | 			F_SET(clp, CL_RENAME); | 
    
    | 482 |  |  | 			(void)printf(XTERM_RENAME, name); | 
    
    | 483 |  |  | 			(void)fflush(stdout); | 
    
    | 484 |  |  | 		} | 
    
    | 485 |  |  | 	} else | 
    
    | 486 |  |  | 		if (F_ISSET(clp, CL_RENAME)) { | 
    
    | 487 |  |  | 			F_CLR(clp, CL_RENAME); | 
    
    | 488 |  |  | 			(void)printf(XTERM_RENAME, ttype); | 
    
    | 489 |  |  | 			(void)fflush(stdout); | 
    
    | 490 |  |  | 		} | 
    
    | 491 |  |  | 	return (0); | 
    
    | 492 |  |  | } | 
    
    | 493 |  |  |  | 
    
    | 494 |  |  | /* | 
    
    | 495 |  |  |  * cl_suspend -- | 
    
    | 496 |  |  |  *	Suspend a screen. | 
    
    | 497 |  |  |  * | 
    
    | 498 |  |  |  * PUBLIC: int cl_suspend(SCR *, int *); | 
    
    | 499 |  |  |  */ | 
    
    | 500 |  |  | int | 
    
    | 501 |  |  | cl_suspend(SCR *sp, int *allowedp) | 
    
    | 502 |  |  | { | 
    
    | 503 |  |  | 	struct termios t; | 
    
    | 504 |  |  | 	CL_PRIVATE *clp; | 
    
    | 505 |  |  | 	size_t oldy, oldx; | 
    
    | 506 |  |  | 	int changed; | 
    
    | 507 |  |  |  | 
    
    | 508 |  |  | 	clp = CLP(sp); | 
    
    | 509 |  |  | 	*allowedp = 1; | 
    
    | 510 |  |  |  | 
    
    | 511 |  |  | 	/* | 
    
    | 512 |  |  | 	 * The ex implementation of this function isn't needed by screens not | 
    
    | 513 |  |  | 	 * supporting ex commands that require full terminal canonical mode | 
    
    | 514 |  |  | 	 * (e.g. :suspend). | 
    
    | 515 |  |  | 	 * | 
    
    | 516 |  |  | 	 * The vi implementation of this function isn't needed by screens not | 
    
    | 517 |  |  | 	 * supporting vi process suspension, i.e. any screen that isn't backed | 
    
    | 518 |  |  | 	 * by a UNIX shell. | 
    
    | 519 |  |  | 	 * | 
    
    | 520 |  |  | 	 * Setting allowedp to 0 will cause the editor to reject the command. | 
    
    | 521 |  |  | 	 */ | 
    
    | 522 |  |  | 	if (F_ISSET(sp, SC_EX)) { | 
    
    | 523 |  |  | 		/* Save the terminal settings, and restore the original ones. */ | 
    
    | 524 |  |  | 		if (F_ISSET(clp, CL_STDIN_TTY)) { | 
    
    | 525 |  |  | 			(void)tcgetattr(STDIN_FILENO, &t); | 
    
    | 526 |  |  | 			(void)tcsetattr(STDIN_FILENO, | 
    
    | 527 |  |  | 			    TCSASOFT | TCSADRAIN, &clp->orig); | 
    
    | 528 |  |  | 		} | 
    
    | 529 |  |  |  | 
    
    | 530 |  |  | 		/* Stop the process group. */ | 
    
    | 531 |  |  | 		(void)kill(0, SIGTSTP); | 
    
    | 532 |  |  |  | 
    
    | 533 |  |  | 		/* Time passes ... */ | 
    
    | 534 |  |  |  | 
    
    | 535 |  |  | 		/* Restore terminal settings. */ | 
    
    | 536 |  |  | 		if (F_ISSET(clp, CL_STDIN_TTY)) | 
    
    | 537 |  |  | 			(void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t); | 
    
    | 538 |  |  | 		return (0); | 
    
    | 539 |  |  | 	} | 
    
    | 540 |  |  |  | 
    
    | 541 |  |  | 	/* | 
    
    | 542 |  |  | 	 * Move to the lower left-hand corner of the screen. | 
    
    | 543 |  |  | 	 * | 
    
    | 544 |  |  | 	 * XXX | 
    
    | 545 |  |  | 	 * Not sure this is necessary in System V implementations, but it | 
    
    | 546 |  |  | 	 * shouldn't hurt. | 
    
    | 547 |  |  | 	 */ | 
    
    | 548 |  |  | 	getyx(stdscr, oldy, oldx); | 
    
    | 549 |  |  | 	(void)move(LINES - 1, 0); | 
    
    | 550 |  |  | 	(void)refresh(); | 
    
    | 551 |  |  |  | 
    
    | 552 |  |  | 	/* | 
    
    | 553 |  |  | 	 * Temporarily end the screen.  System V introduced a semantic where | 
    
    | 554 |  |  | 	 * endwin() could be restarted.  We use it because restarting curses | 
    
    | 555 |  |  | 	 * from scratch often fails in System V. | 
    
    | 556 |  |  | 	 */ | 
    
    | 557 |  |  |  | 
    
    | 558 |  |  | 	/* Restore the cursor keys to normal mode. */ | 
    
    | 559 |  |  | 	(void)keypad(stdscr, FALSE); | 
    
    | 560 |  |  |  | 
    
    | 561 |  |  | 	/* Restore the window name. */ | 
    
    | 562 |  |  | 	(void)cl_rename(sp, NULL, 0); | 
    
    | 563 |  |  |  | 
    
    | 564 |  |  | 	(void)endwin(); | 
    
    | 565 |  |  |  | 
    
    | 566 |  |  | 	/* | 
    
    | 567 |  |  | 	 * XXX | 
    
    | 568 |  |  | 	 * Restore the original terminal settings.  This is bad -- the | 
    
    | 569 |  |  | 	 * reset can cause character loss from the tty queue.  However, | 
    
    | 570 |  |  | 	 * we can't call endwin() in BSD curses implementations, and too | 
    
    | 571 |  |  | 	 * many System V curses implementations don't get it right. | 
    
    | 572 |  |  | 	 */ | 
    
    | 573 |  |  | 	(void)tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->orig); | 
    
    | 574 |  |  |  | 
    
    | 575 |  |  | 	/* Stop the process group. */ | 
    
    | 576 |  |  | 	(void)kill(0, SIGTSTP); | 
    
    | 577 |  |  |  | 
    
    | 578 |  |  | 	/* Time passes ... */ | 
    
    | 579 |  |  |  | 
    
    | 580 |  |  | 	/* | 
    
    | 581 |  |  | 	 * If we received a killer signal, we're done.  Leave everything | 
    
    | 582 |  |  | 	 * unchanged.  In addition, the terminal has already been reset | 
    
    | 583 |  |  | 	 * correctly, so leave it alone. | 
    
    | 584 |  |  | 	 */ | 
    
    | 585 |  |  | 	if (clp->killersig) { | 
    
    | 586 |  |  | 		F_CLR(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT); | 
    
    | 587 |  |  | 		return (0); | 
    
    | 588 |  |  | 	} | 
    
    | 589 |  |  |  | 
    
    | 590 |  |  | 	/* Set the window name. */ | 
    
    | 591 |  |  | 	(void)cl_rename(sp, sp->frp->name, 1); | 
    
    | 592 |  |  |  | 
    
    | 593 |  |  | 	/* Put the cursor keys into application mode. */ | 
    
    | 594 |  |  | 	(void)keypad(stdscr, TRUE); | 
    
    | 595 |  |  |  | 
    
    | 596 |  |  | 	/* Refresh and repaint the screen. */ | 
    
    | 597 |  |  | 	(void)move(oldy, oldx); | 
    
    | 598 |  |  | 	(void)cl_refresh(sp, 1); | 
    
    | 599 |  |  |  | 
    
    | 600 |  |  | 	/* If the screen changed size, set the SIGWINCH bit. */ | 
    
    | 601 |  |  | 	if (cl_ssize(sp, 1, NULL, NULL, &changed)) | 
    
    | 602 |  |  | 		return (1); | 
    
    | 603 |  |  | 	if (changed) | 
    
    | 604 |  |  | 		F_SET(CLP(sp), CL_SIGWINCH); | 
    
    | 605 |  |  |  | 
    
    | 606 |  |  | 	return (0); | 
    
    | 607 |  |  | } | 
    
    | 608 |  |  |  | 
    
    | 609 |  |  | /* | 
    
    | 610 |  |  |  * cl_usage -- | 
    
    | 611 |  |  |  *	Print out the curses usage messages. | 
    
    | 612 |  |  |  * | 
    
    | 613 |  |  |  * PUBLIC: void cl_usage(void); | 
    
    | 614 |  |  |  */ | 
    
    | 615 |  |  | void | 
    
    | 616 |  |  | cl_usage() | 
    
    | 617 |  |  | { | 
    
    | 618 |  |  | 	switch (pmode) { | 
    
    | 619 |  |  | 	case MODE_EX: | 
    
    | 620 |  |  | 		(void)fprintf(stderr, "usage: " | 
    
    | 621 |  |  | 		    "ex [-FRrSsv] [-c cmd] [-t tag] [-w size] [file ...]\n"); | 
    
    | 622 |  |  | 		break; | 
    
    | 623 |  |  | 	case MODE_VI: | 
    
    | 624 |  |  | 		(void)fprintf(stderr, "usage: " | 
    
    | 625 |  |  | 		    "vi [-eFRrS] [-c cmd] [-t tag] [-w size] [file ...]\n"); | 
    
    | 626 |  |  | 		break; | 
    
    | 627 |  |  | 	case MODE_VIEW: | 
    
    | 628 |  |  | 		(void)fprintf(stderr, "usage: " | 
    
    | 629 |  |  | 		    "view [-eFrS] [-c cmd] [-t tag] [-w size] [file ...]\n"); | 
    
    | 630 |  |  | 		break; | 
    
    | 631 |  |  | 	} | 
    
    | 632 |  |  | } | 
    
    | 633 |  |  |  | 
    
    | 634 |  |  | #ifdef DEBUG | 
    
    | 635 |  |  | /* | 
    
    | 636 |  |  |  * gdbrefresh -- | 
    
    | 637 |  |  |  *	Stub routine so can flush out curses screen changes using gdb. | 
    
    | 638 |  |  |  */ | 
    
    | 639 |  |  | int | 
    
    | 640 |  |  | gdbrefresh() | 
    
    | 641 |  |  | { | 
    
    | 642 |  |  | 	refresh(); | 
    
    | 643 |  |  | 	return (0);		/* XXX Convince gdb to run it. */ | 
    
    | 644 |  |  | } | 
    
    | 645 |  |  | #endif |