17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
2367a4bb8fSGary Mills  * Copyright 2015 Gary Mills
247c478bd9Sstevel@tonic-gate  * Copyright (c) 1995, by Sun Microsystems, Inc.
257c478bd9Sstevel@tonic-gate  * All rights reserved.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * doupdate.c
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  * XCurses Library
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * Copyright 1990, 1995 by Mortice Kern Systems Inc.  All rights reserved.
347c478bd9Sstevel@tonic-gate  *
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #ifdef M_RCSID
387c478bd9Sstevel@tonic-gate #ifndef lint
397c478bd9Sstevel@tonic-gate static char const rcsID[] = "$Header: /rd/src/libc/xcurses/rcs/doupdate.c 1.9 1995/07/26 17:45:06 ant Exp $";
407c478bd9Sstevel@tonic-gate #endif
417c478bd9Sstevel@tonic-gate #endif
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #include <private.h>
447c478bd9Sstevel@tonic-gate #include <string.h>
457c478bd9Sstevel@tonic-gate #include <setjmp.h>
467c478bd9Sstevel@tonic-gate #include <signal.h>
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #undef SIGTSTP
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate  * Disable typeahead trapping because it slow down updated dramatically
527c478bd9Sstevel@tonic-gate  * on MPE/iX.
537c478bd9Sstevel@tonic-gate  */
547c478bd9Sstevel@tonic-gate #ifdef MPE_STUB
557c478bd9Sstevel@tonic-gate #undef M_CURSES_TYPEAHEAD
567c478bd9Sstevel@tonic-gate #endif
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate /*
59*55fea89dSDan Cross  * This value is the ideal length for the cursor addressing sequence
607c478bd9Sstevel@tonic-gate  * being four bytes long, ie. "<escape><cursor addressing code><row><col>".
617c478bd9Sstevel@tonic-gate  * eg. VT52 - "\EYrc" or ADM3A - "\E=rc"
627c478bd9Sstevel@tonic-gate  */
637c478bd9Sstevel@tonic-gate #define JUMP_SIZE	4
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate  * This value is the ideal length for the clear-to-eol sequence
677c478bd9Sstevel@tonic-gate  * being two bytes long, ie "<escape><clear eol code>".
687c478bd9Sstevel@tonic-gate  */
697c478bd9Sstevel@tonic-gate #define CEOL_SIZE	2
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate #define GOTO(r,c)	(__m_mvcur(curscr->_cury, curscr->_curx,r,c,__m_outc),\
727c478bd9Sstevel@tonic-gate 			curscr->_cury = r, curscr->_curx = c)
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate typedef struct cost_op {
757c478bd9Sstevel@tonic-gate 	short cost;
767c478bd9Sstevel@tonic-gate 	short op;
777c478bd9Sstevel@tonic-gate } lcost;
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate typedef void (*t_action)(int, int);
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate static jmp_buf breakout;
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate #define LC(i,j) 	(lc[(i) * (LINES + 1) + (j)])
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate static lcost *lc = (lcost *) 0;
867c478bd9Sstevel@tonic-gate static unsigned long *nhash = (unsigned long *) 0;
877c478bd9Sstevel@tonic-gate static t_action *del = (t_action *) 0;
887c478bd9Sstevel@tonic-gate static t_action *ins_rep = (t_action *) 0;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate static WINDOW *newscr;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate STATIC void erase_bottom(int);
937c478bd9Sstevel@tonic-gate STATIC void clear_bottom(int);
947c478bd9Sstevel@tonic-gate STATIC void complex(void);
957c478bd9Sstevel@tonic-gate STATIC int cost(int, int);
967c478bd9Sstevel@tonic-gate STATIC void lines_delete(int, int);
977c478bd9Sstevel@tonic-gate STATIC void lines_insert(int, int);
987c478bd9Sstevel@tonic-gate STATIC void lines_replace(int, int);
997c478bd9Sstevel@tonic-gate STATIC void script(int, int);
1007c478bd9Sstevel@tonic-gate STATIC int scroll_dn(int);
1017c478bd9Sstevel@tonic-gate STATIC int scroll_up(int);
1027c478bd9Sstevel@tonic-gate STATIC void simple(void);
1037c478bd9Sstevel@tonic-gate STATIC void text_replace(int);
1047c478bd9Sstevel@tonic-gate STATIC void block_over(int, int, int);
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate /*f
1077c478bd9Sstevel@tonic-gate  * Wrapper that streams Curses output.
108*55fea89dSDan Cross  *
1097c478bd9Sstevel@tonic-gate  * All escape sequences going to the screen come through here.
1107c478bd9Sstevel@tonic-gate  * All ordinary characters go to the screen via the putc in doupdate.c
1117c478bd9Sstevel@tonic-gate  */
1127c478bd9Sstevel@tonic-gate int
__m_outc(ch)1137c478bd9Sstevel@tonic-gate __m_outc(ch)
1147c478bd9Sstevel@tonic-gate int ch;
1157c478bd9Sstevel@tonic-gate {
1167c478bd9Sstevel@tonic-gate         return putc(ch, __m_screen->_of);
1177c478bd9Sstevel@tonic-gate }
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate /*
1207c478bd9Sstevel@tonic-gate  * Allocate or grow doupdate() structures.
1217c478bd9Sstevel@tonic-gate  */
1227c478bd9Sstevel@tonic-gate int
__m_doupdate_init()123*55fea89dSDan Cross __m_doupdate_init()
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate 	void *new;
1267c478bd9Sstevel@tonic-gate 	static short nlines = 0;
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	if (lines <= 0)
1297c478bd9Sstevel@tonic-gate 		return -1;
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	if (lines <= nlines)
1327c478bd9Sstevel@tonic-gate 		return 0;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	new = m_malloc((lines+1) * (lines+1) * sizeof *lc);
1357c478bd9Sstevel@tonic-gate 	if (new == (void *) 0)
1367c478bd9Sstevel@tonic-gate 		return -1;
1377c478bd9Sstevel@tonic-gate 	if (lc != (lcost *) 0)
1387c478bd9Sstevel@tonic-gate 		free(lc);
1397c478bd9Sstevel@tonic-gate 	lc = (lcost *) new;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	new = m_malloc((lines + lines) * sizeof *del);
1427c478bd9Sstevel@tonic-gate 	if (new == (void *) 0)
1437c478bd9Sstevel@tonic-gate 		return -1;
1447c478bd9Sstevel@tonic-gate 	if (del != (t_action *) 0)
1457c478bd9Sstevel@tonic-gate 		free(del);
1467c478bd9Sstevel@tonic-gate 	del = (t_action *) new;
1477c478bd9Sstevel@tonic-gate 	ins_rep = del + lines;
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	new = m_malloc(lines * sizeof *nhash);
1507c478bd9Sstevel@tonic-gate 	if (new == (void *) 0)
1517c478bd9Sstevel@tonic-gate 		return -1;
1527c478bd9Sstevel@tonic-gate 	if (nhash != (unsigned long *) 0)
1537c478bd9Sstevel@tonic-gate 		free(nhash);
1547c478bd9Sstevel@tonic-gate 	nhash = (unsigned long *) new;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	nlines = lines;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	return 0;
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate STATIC void
erase_bottom(y)1627c478bd9Sstevel@tonic-gate erase_bottom(y)
1637c478bd9Sstevel@tonic-gate int y;
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate 	int i;
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	for (i = y; i < LINES; ++i) {
1687c478bd9Sstevel@tonic-gate 		(void) __m_cc_erase(curscr, i, 0, i, curscr->_maxx-1);
1697c478bd9Sstevel@tonic-gate 		__m_cc_hash(curscr, __m_screen->_hash, i);
1707c478bd9Sstevel@tonic-gate 	}
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate /*f
1747c478bd9Sstevel@tonic-gate  *  Clear from the start of the current row to bottom of screen.
1757c478bd9Sstevel@tonic-gate  */
1767c478bd9Sstevel@tonic-gate STATIC void
clear_bottom(y)1777c478bd9Sstevel@tonic-gate clear_bottom(y)
1787c478bd9Sstevel@tonic-gate int y;
1797c478bd9Sstevel@tonic-gate {
1807c478bd9Sstevel@tonic-gate 	erase_bottom(y);
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	/* Restore default color pair before doing area clears. */
1837c478bd9Sstevel@tonic-gate 	if (back_color_erase)
1847c478bd9Sstevel@tonic-gate 		(void) vid_puts(WA_NORMAL, 0, (void *) 0, __m_outc);
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	if (y == 0 && clear_screen != (char *) 0) {
1877c478bd9Sstevel@tonic-gate 		(void) tputs(clear_screen, 1, __m_outc);
1887c478bd9Sstevel@tonic-gate 	} else {
1897c478bd9Sstevel@tonic-gate 		(void) __m_mvcur(-1, -1, y, 0, __m_outc);
1907c478bd9Sstevel@tonic-gate 		if (clr_eos != (char *) 0) {
1917c478bd9Sstevel@tonic-gate 			(void) tputs(clr_eos, 1, __m_outc);
1927c478bd9Sstevel@tonic-gate 		} else if (clr_eol != (char *) 0) {
1937c478bd9Sstevel@tonic-gate 			for (;;) {
1947c478bd9Sstevel@tonic-gate 				(void) tputs(clr_eol, 1, __m_outc);
1957c478bd9Sstevel@tonic-gate 				if (LINES <= y)
1967c478bd9Sstevel@tonic-gate 					break;
1977c478bd9Sstevel@tonic-gate 				(void) __m_mvcur(y, 0, y+1, 0, __m_outc);
1987c478bd9Sstevel@tonic-gate 				++y;
1997c478bd9Sstevel@tonic-gate 			}
2007c478bd9Sstevel@tonic-gate 		}
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	curscr->_cury = y;
2047c478bd9Sstevel@tonic-gate 	curscr->_curx = 0;
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate /*f
208*55fea89dSDan Cross  * Replace a line of text.
2097c478bd9Sstevel@tonic-gate  *
2107c478bd9Sstevel@tonic-gate  * The principal scheme is to overwrite the region of a line between
2117c478bd9Sstevel@tonic-gate  * the first and last differing characters.  A clear-eol is used to
2127c478bd9Sstevel@tonic-gate  * optimise an update region that consist largely of blanks.  This can
2137c478bd9Sstevel@tonic-gate  * happen fairly often in the case of scrolled lines or full redraws.
2147c478bd9Sstevel@tonic-gate  *
215*55fea89dSDan Cross  * Miller's line redraw algorithm, used in the 'S' editor [Mil87],
216*55fea89dSDan Cross  * should be re-investigated to see if it is simple and fast enough for
217*55fea89dSDan Cross  * our needs, and if it can be adapted to handle the ceol_standout_glitch
2187c478bd9Sstevel@tonic-gate  * (HP 2392A terminals) and multibyte character sequences.
2197c478bd9Sstevel@tonic-gate  *
2207c478bd9Sstevel@tonic-gate  * Very early versions of this code applied a Gosling algorithm column
2217c478bd9Sstevel@tonic-gate  * wise in addition to the row-wise used in complex().  It was removed
2227c478bd9Sstevel@tonic-gate  * in favour of both computation and transmission speed.  The assumption
2237c478bd9Sstevel@tonic-gate  * being that overwrites of a line region occured far more frequently
224*55fea89dSDan Cross  * than the need to insert/delete several isolated characters.
2257c478bd9Sstevel@tonic-gate  *
2267c478bd9Sstevel@tonic-gate  * References:
2277c478bd9Sstevel@tonic-gate  * [Mil87]	W. Miller, A Software Tools Sampler, Prentice-Hall, 1987
2287c478bd9Sstevel@tonic-gate  */
2297c478bd9Sstevel@tonic-gate STATIC void
text_replace(row)2307c478bd9Sstevel@tonic-gate text_replace(row)
2317c478bd9Sstevel@tonic-gate int row;
2327c478bd9Sstevel@tonic-gate {
2337c478bd9Sstevel@tonic-gate 	short npair;
234*55fea89dSDan Cross 	attr_t cookie, nattr;
2357c478bd9Sstevel@tonic-gate 	cchar_t *optr, *nptr;
2367c478bd9Sstevel@tonic-gate 	int col, last, tail, jump, count;
237*55fea89dSDan Cross 
2387c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TYPEAHEAD
2397c478bd9Sstevel@tonic-gate 	/* Before replacing a line of text, check for type-ahead. */
2407c478bd9Sstevel@tonic-gate 	if (__m_screen->_flags & S_ISATTY) {
2417c478bd9Sstevel@tonic-gate 		unsigned char cc;
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 		if (read(__m_screen->_kfd, &cc, sizeof cc) == sizeof cc) {
2447c478bd9Sstevel@tonic-gate 			(void) ungetch(cc);
2457c478bd9Sstevel@tonic-gate 			longjmp(breakout, 1);
2467c478bd9Sstevel@tonic-gate 		}
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate #endif /* M_CURSES_TYPEAHEAD */
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	col = newscr->_first[row];
2517c478bd9Sstevel@tonic-gate 	if (col < 0)
2527c478bd9Sstevel@tonic-gate 		col = 0;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	last = newscr->_last[row];
2557c478bd9Sstevel@tonic-gate 	if (COLS < last)
2567c478bd9Sstevel@tonic-gate 		last = COLS;
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	if (clr_eol != (char *) 0) {
2597c478bd9Sstevel@tonic-gate 		/* Find start of blank tail region. */
2607c478bd9Sstevel@tonic-gate 		nptr = &newscr->_line[row][COLS];
2617c478bd9Sstevel@tonic-gate 		for (tail = COLS; 0 < tail; --tail) {
2627c478bd9Sstevel@tonic-gate 			if (!__m_cc_compare(--nptr, &newscr->_bg, 1))
2637c478bd9Sstevel@tonic-gate 				break;
2647c478bd9Sstevel@tonic-gate 		}
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 		/* Only consider clear-to-end-of-line optimization if the
2677c478bd9Sstevel@tonic-gate 		 * blank tail falls within the end of the dirty region by
2687c478bd9Sstevel@tonic-gate 		 * more than ideal length of clear-to-end-of-line sequence.
2697c478bd9Sstevel@tonic-gate 		 * Else disable the check by forcing tail to be at the
2707c478bd9Sstevel@tonic-gate 		 * end-of-line.
2717c478bd9Sstevel@tonic-gate 		 */
2727c478bd9Sstevel@tonic-gate 		if (last < tail + CEOL_SIZE)
2737c478bd9Sstevel@tonic-gate 			tail = COLS;
2747c478bd9Sstevel@tonic-gate 	}
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	optr = &curscr->_line[row][col];
2777c478bd9Sstevel@tonic-gate 	nptr = &newscr->_line[row][col];
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	for (jump = -1; col < last; ) {
2807c478bd9Sstevel@tonic-gate 		/* Skip common regions. */
2817c478bd9Sstevel@tonic-gate 		for (count = 0; __m_cc_compare(optr, nptr, 1); ++count) {
2827c478bd9Sstevel@tonic-gate 			/* Advance before possible goto. */
2837c478bd9Sstevel@tonic-gate 			++optr;
2847c478bd9Sstevel@tonic-gate 			++nptr;
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 			if (last <= ++col)
2877c478bd9Sstevel@tonic-gate 				goto done;
2887c478bd9Sstevel@tonic-gate 		}
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate                 /* Move the cursor by redrawing characters or using
2917c478bd9Sstevel@tonic-gate                  * cursor motion commands.  The first time that we
2927c478bd9Sstevel@tonic-gate                  * address this row, jump equals -1, so that the cursor
2937c478bd9Sstevel@tonic-gate                  * will be forced to the correct screen line.  Once
2947c478bd9Sstevel@tonic-gate                  * there, we should be able to track the cursor motion
2957c478bd9Sstevel@tonic-gate                  * along the line and jump only when the cost of redrawing
2967c478bd9Sstevel@tonic-gate 		 * to column N is more expensive than a jump to column N.
2977c478bd9Sstevel@tonic-gate                  */
2987c478bd9Sstevel@tonic-gate                 if (jump < count) {
2997c478bd9Sstevel@tonic-gate 			/* First time addressing this row or cost of
3007c478bd9Sstevel@tonic-gate 			 * jumping cheaper than redrawing.
3017c478bd9Sstevel@tonic-gate 			 */
3027c478bd9Sstevel@tonic-gate                         jump = JUMP_SIZE;
3037c478bd9Sstevel@tonic-gate                         GOTO(row, col);
3047c478bd9Sstevel@tonic-gate 			count = 0;
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 			/* If attributes at start of field are different
3077c478bd9Sstevel@tonic-gate 			 * force an attribute cookie to be dropped.
3087c478bd9Sstevel@tonic-gate 			 */
309*55fea89dSDan Cross 			if (ceol_standout_glitch
3107c478bd9Sstevel@tonic-gate 			&& (optr->_at != nptr->_at || optr->_co != nptr->_co))
3117c478bd9Sstevel@tonic-gate 				ATTR_STATE |= WA_COOKIE;
3127c478bd9Sstevel@tonic-gate                 } else {
3137c478bd9Sstevel@tonic-gate                         /* Redraw to move short distance. */
3147c478bd9Sstevel@tonic-gate 			optr -= count;
3157c478bd9Sstevel@tonic-gate 			nptr -= count;
3167c478bd9Sstevel@tonic-gate 			col -= count;
3177c478bd9Sstevel@tonic-gate 		}
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 		/* Write difference region. */
320*55fea89dSDan Cross 		while (col < last
3217c478bd9Sstevel@tonic-gate 		&& (!__m_cc_compare(optr, nptr, 1) || 0 < count--)) {
3227c478bd9Sstevel@tonic-gate write_loop:
3237c478bd9Sstevel@tonic-gate 			/* Check for clear-to-end-of-line optimization. */
3247c478bd9Sstevel@tonic-gate 			if (clr_eol != (char *) 0 && tail <= col) {
3257c478bd9Sstevel@tonic-gate 				/* For HP terminals, only clear-to-end-of-line
3267c478bd9Sstevel@tonic-gate 				 * once the attributes have been turned off.
3277c478bd9Sstevel@tonic-gate 				 * Other terminals, we can proceed normally.
3287c478bd9Sstevel@tonic-gate 				 */
3297c478bd9Sstevel@tonic-gate 				if (!ceol_standout_glitch
3307c478bd9Sstevel@tonic-gate 				|| ATTR_STATE == WA_NORMAL) {
3317c478bd9Sstevel@tonic-gate 					curscr->_curx = col;
3327c478bd9Sstevel@tonic-gate 					goto done;
3337c478bd9Sstevel@tonic-gate 				}
3347c478bd9Sstevel@tonic-gate 			}
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 			++col;
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 			/* Make sure we don't scroll the screen by writing
339*55fea89dSDan Cross 			 * to the bottom right corner.
3407c478bd9Sstevel@tonic-gate 			 */
3417c478bd9Sstevel@tonic-gate 			if (COLS <= col && LINES-1 <= row
3427c478bd9Sstevel@tonic-gate 			&& auto_right_margin && !eat_newline_glitch) {
3437c478bd9Sstevel@tonic-gate 				/*** TODO
3447c478bd9Sstevel@tonic-gate 				 *** Insert character/auto_right_margin
3457c478bd9Sstevel@tonic-gate 				 *** hacks for writting into the last
3467c478bd9Sstevel@tonic-gate 				 *** column of the last line so as not
3477c478bd9Sstevel@tonic-gate 				 *** to scroll.
348*55fea89dSDan Cross 				 ***/
3497c478bd9Sstevel@tonic-gate 				curscr->_curx = col;
3507c478bd9Sstevel@tonic-gate 				goto done;
3517c478bd9Sstevel@tonic-gate 			}
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 			/* Remember any existing attribute cookie. */
3547c478bd9Sstevel@tonic-gate 			cookie = optr->_at & WA_COOKIE;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 			nattr = nptr->_at;
3577c478bd9Sstevel@tonic-gate 			npair = nptr->_co;
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 			/* Change attribute state.  On HP terminals we also
3607c478bd9Sstevel@tonic-gate 			 * have to check for attribute cookies that may need
3617c478bd9Sstevel@tonic-gate 			 * to be changed.
3627c478bd9Sstevel@tonic-gate 			 */
363*55fea89dSDan Cross 			if (ATTR_STATE != nattr
3647c478bd9Sstevel@tonic-gate 			|| optr->_at != nattr || optr->_co != npair) {
3657c478bd9Sstevel@tonic-gate 				(void) vid_puts(
3667c478bd9Sstevel@tonic-gate 					nattr, npair, (void *) 0, __m_outc
3677c478bd9Sstevel@tonic-gate 				);
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 				/* Remember new or existing cookie. */
3707c478bd9Sstevel@tonic-gate 				cookie = WA_COOKIE;
3717c478bd9Sstevel@tonic-gate 			}
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 			/* Don't display internal characters. */
374*55fea89dSDan Cross 			if (nptr->_f)
3757c478bd9Sstevel@tonic-gate 				(void) __m_cc_write(nptr);
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 			/* Update copy of screen image. */
3787c478bd9Sstevel@tonic-gate 			*optr++ = *nptr++;
3797c478bd9Sstevel@tonic-gate 			optr->_at |= cookie;
3807c478bd9Sstevel@tonic-gate 		}
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 		curscr->_curx = col;
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 		/* Check the attributes at the end of the field with
3857c478bd9Sstevel@tonic-gate 		 * those of start of the next common region.  If they
3867c478bd9Sstevel@tonic-gate 		 * differ, force another iteration of the write-loop
3877c478bd9Sstevel@tonic-gate 		 * that will change the attribute state.
388*55fea89dSDan Cross 		 */
389*55fea89dSDan Cross 		if (ceol_standout_glitch && col < COLS
3907c478bd9Sstevel@tonic-gate 		&& ATTR_STATE != (optr->_at & ~WA_COOKIE))
3917c478bd9Sstevel@tonic-gate 			goto write_loop;
3927c478bd9Sstevel@tonic-gate 	}
3937c478bd9Sstevel@tonic-gate done:
394*55fea89dSDan Cross 	/* Before leaving this line, check if we have to turn off
3957c478bd9Sstevel@tonic-gate 	 * attributes and record a cookie.
3967c478bd9Sstevel@tonic-gate 	 */
3977c478bd9Sstevel@tonic-gate 	if (!move_standout_mode && ATTR_STATE != WA_NORMAL) {
3987c478bd9Sstevel@tonic-gate 		/* ceol_standout_glitch, which affects HP terminals,
3997c478bd9Sstevel@tonic-gate 		 * drops hidden cookies on the screen where ever the
4007c478bd9Sstevel@tonic-gate 		 * cursor is, so disabling attributes before a cursor
4017c478bd9Sstevel@tonic-gate 		 * motion operation could disturb existing highlights.
4027c478bd9Sstevel@tonic-gate 		 */
4037c478bd9Sstevel@tonic-gate 		if (ceol_standout_glitch)
4047c478bd9Sstevel@tonic-gate 			/* Attributes on an HP terminal do not cross lines. */
4057c478bd9Sstevel@tonic-gate 			ATTR_STATE = A_NORMAL;
4067c478bd9Sstevel@tonic-gate 		else
4077c478bd9Sstevel@tonic-gate 			(void) vid_puts(WA_NORMAL, 0, (void *) 0, __m_outc);
4087c478bd9Sstevel@tonic-gate 	}
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	/* Re-check for clear to end-of-line optimization. */
4117c478bd9Sstevel@tonic-gate 	if (clr_eol != (char *) 0 && tail <= col && col < last) {
4127c478bd9Sstevel@tonic-gate 		/* Is the tail of the current screen image non-blank? */
4137c478bd9Sstevel@tonic-gate 		for (tail = col; tail < COLS; ++tail, ++optr)
4147c478bd9Sstevel@tonic-gate 			if (!__m_cc_compare(optr, &newscr->_bg, 1))
4157c478bd9Sstevel@tonic-gate 				break;
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 		/* If tail didn't reach the right margin of
4187c478bd9Sstevel@tonic-gate 		 * the current screen image, then we will
4197c478bd9Sstevel@tonic-gate 		 * make it look like the new image with a
4207c478bd9Sstevel@tonic-gate 		 * clear to end-of-line.
4217c478bd9Sstevel@tonic-gate 		 */
4227c478bd9Sstevel@tonic-gate 		if (tail < COLS) {
4237c478bd9Sstevel@tonic-gate 			/* Restore default color pair before area clear. */
4247c478bd9Sstevel@tonic-gate 			if (back_color_erase)
4257c478bd9Sstevel@tonic-gate 				(void) vid_puts(
4267c478bd9Sstevel@tonic-gate 					WA_NORMAL, 0, (void *) 0, __m_outc
4277c478bd9Sstevel@tonic-gate 				);
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 			(void) tputs(clr_eol, 1, __m_outc);
4307c478bd9Sstevel@tonic-gate 			__m_cc_erase(curscr, row, tail, row, COLS-1);
4317c478bd9Sstevel@tonic-gate 		}
432*55fea89dSDan Cross 	}
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	/* Line wrapping checks. */
4357c478bd9Sstevel@tonic-gate 	if (COLS <= curscr->_curx) {
4367c478bd9Sstevel@tonic-gate 		--curscr->_curx;
4377c478bd9Sstevel@tonic-gate 		if (auto_right_margin && row < LINES-1) {
4387c478bd9Sstevel@tonic-gate 			if (eat_newline_glitch) {
4397c478bd9Sstevel@tonic-gate 				__m_outc('\r');
4407c478bd9Sstevel@tonic-gate 				__m_outc('\n');
4417c478bd9Sstevel@tonic-gate 			}
4427c478bd9Sstevel@tonic-gate 			++curscr->_cury;
4437c478bd9Sstevel@tonic-gate 			curscr->_curx = 0;
4447c478bd9Sstevel@tonic-gate 		}
445*55fea89dSDan Cross 	}
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate /*f
4497c478bd9Sstevel@tonic-gate  * Replace a block of lines.
4507c478bd9Sstevel@tonic-gate  * Only ever used for complex().
4517c478bd9Sstevel@tonic-gate  */
452*55fea89dSDan Cross STATIC void
lines_replace(from,to_1)4537c478bd9Sstevel@tonic-gate lines_replace(from, to_1)
4547c478bd9Sstevel@tonic-gate int from, to_1;
4557c478bd9Sstevel@tonic-gate {
4567c478bd9Sstevel@tonic-gate 	for (; from < to_1; ++from)
4577c478bd9Sstevel@tonic-gate 		text_replace(from);
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate /*f
4617c478bd9Sstevel@tonic-gate  * Delete a block of lines.
4627c478bd9Sstevel@tonic-gate  * Only ever used for complex().
4637c478bd9Sstevel@tonic-gate  */
464*55fea89dSDan Cross STATIC void
lines_delete(from,to_1)4657c478bd9Sstevel@tonic-gate lines_delete(from, to_1)
4667c478bd9Sstevel@tonic-gate int from, to_1;
4677c478bd9Sstevel@tonic-gate {
4687c478bd9Sstevel@tonic-gate 	int count = to_1 - from;
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 	if (LINES <= to_1) {
4717c478bd9Sstevel@tonic-gate 		clear_bottom(from);
4727c478bd9Sstevel@tonic-gate 	} else {
4737c478bd9Sstevel@tonic-gate 		GOTO(from, 0);
4747c478bd9Sstevel@tonic-gate 		(void) winsdelln(curscr, -count);
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 		if (parm_delete_line != (char *) 0) {
477*55fea89dSDan Cross 			/* Assume that the sequence to delete more than one
478*55fea89dSDan Cross 			 * line is faster than repeated single delete_lines.
4797c478bd9Sstevel@tonic-gate 			 */
4807c478bd9Sstevel@tonic-gate 			(void) tputs(
4817c478bd9Sstevel@tonic-gate 				tparm(
4827c478bd9Sstevel@tonic-gate 					parm_delete_line, (long) count,
4837c478bd9Sstevel@tonic-gate 					0, 0, 0, 0, 0, 0, 0, 0
4847c478bd9Sstevel@tonic-gate 				), count, __m_outc
4857c478bd9Sstevel@tonic-gate 			);
4867c478bd9Sstevel@tonic-gate 		} else if (delete_line != (char *) 0) {
4877c478bd9Sstevel@tonic-gate 			while (from++ < to_1)
4887c478bd9Sstevel@tonic-gate 				(void) tputs(delete_line, 1, __m_outc);
4897c478bd9Sstevel@tonic-gate 		} else  {
4907c478bd9Sstevel@tonic-gate 			/* Error -- what to do. */
4917c478bd9Sstevel@tonic-gate 			return;
4927c478bd9Sstevel@tonic-gate 		}
4937c478bd9Sstevel@tonic-gate 	}
4947c478bd9Sstevel@tonic-gate }
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate /*f
4977c478bd9Sstevel@tonic-gate  * Insert a block of lines.
4987c478bd9Sstevel@tonic-gate  * Only ever used for complex().
4997c478bd9Sstevel@tonic-gate  *
500*55fea89dSDan Cross  * We must assume that insert_line and parm_insert_line reset the
5017c478bd9Sstevel@tonic-gate  * cursor column to zero.  Therefore it is text_replace() responsiblity
5027c478bd9Sstevel@tonic-gate  * to move the cursor to the correct column to begin the update.
5037c478bd9Sstevel@tonic-gate  */
504*55fea89dSDan Cross STATIC void
lines_insert(from,to_1)5057c478bd9Sstevel@tonic-gate lines_insert(from, to_1)
5067c478bd9Sstevel@tonic-gate int from, to_1;
5077c478bd9Sstevel@tonic-gate {
5087c478bd9Sstevel@tonic-gate 	int row, count = to_1 - from;
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 	/* Position the cursor and insert a block of lines into the screen
5117c478bd9Sstevel@tonic-gate 	 * image now, insert lines into the physical screen, then draw the
512*55fea89dSDan Cross 	 * new screen lines.
513*55fea89dSDan Cross 	 */
5147c478bd9Sstevel@tonic-gate 	GOTO(from, 0);
5157c478bd9Sstevel@tonic-gate 	(void) winsdelln(curscr, count);
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 	if (parm_insert_line != (char *) 0) {
5187c478bd9Sstevel@tonic-gate 		/* Assume that the sequence to insert more than one line is
519*55fea89dSDan Cross 		 * faster than repeated single insert_lines.
5207c478bd9Sstevel@tonic-gate 		 */
5217c478bd9Sstevel@tonic-gate 		(void) tputs(
5227c478bd9Sstevel@tonic-gate 			tparm(
5237c478bd9Sstevel@tonic-gate 				parm_insert_line, (long) count,
5247c478bd9Sstevel@tonic-gate 				0, 0, 0, 0, 0, 0, 0, 0
5257c478bd9Sstevel@tonic-gate 			), count, __m_outc
5267c478bd9Sstevel@tonic-gate 		);
5277c478bd9Sstevel@tonic-gate 	} else if (insert_line != (char *) 0) {
5287c478bd9Sstevel@tonic-gate 		/* For the single line insert we use to iterate moving
5297c478bd9Sstevel@tonic-gate 		 * the cursor, inserting, and then drawing a line.  That
5307c478bd9Sstevel@tonic-gate 		 * would appear to be slow but visually appealing.  However,
5317c478bd9Sstevel@tonic-gate 		 * people on slow terminals want speed and those on fast
5327c478bd9Sstevel@tonic-gate 		 * terminal won't see it.
5337c478bd9Sstevel@tonic-gate 		 */
5347c478bd9Sstevel@tonic-gate 		for (row = from; row < to_1; ++row)
5357c478bd9Sstevel@tonic-gate 			(void) tputs(insert_line, 1, __m_outc);
5367c478bd9Sstevel@tonic-gate 	} else {
5377c478bd9Sstevel@tonic-gate 		/* Error -- what to do. */
5387c478bd9Sstevel@tonic-gate 		return;
5397c478bd9Sstevel@tonic-gate 	}
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	for (row = from; row < to_1; ++row)
5427c478bd9Sstevel@tonic-gate 		text_replace(row);
5437c478bd9Sstevel@tonic-gate }
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate STATIC int
scroll_up(n)5467c478bd9Sstevel@tonic-gate scroll_up(n)
5477c478bd9Sstevel@tonic-gate int n;
5487c478bd9Sstevel@tonic-gate {
5497c478bd9Sstevel@tonic-gate 	int count = n;
5507c478bd9Sstevel@tonic-gate 	int start, finish, to, row;
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 	if (scroll_forward != (char *) 0) {
5537c478bd9Sstevel@tonic-gate 		GOTO(LINES-1, 0);
5547c478bd9Sstevel@tonic-gate 		while (0 < n--)
5557c478bd9Sstevel@tonic-gate 			(void) tputs(scroll_forward, 1, __m_outc);
5567c478bd9Sstevel@tonic-gate 	} else if (parm_delete_line != (char *) 0 && 1 < n) {
5577c478bd9Sstevel@tonic-gate 		GOTO(0, 0);
5587c478bd9Sstevel@tonic-gate 		(void) tputs(
5597c478bd9Sstevel@tonic-gate 			tparm(
560*55fea89dSDan Cross 				parm_delete_line, (long) n,
5617c478bd9Sstevel@tonic-gate 				0, 0, 0, 0, 0, 0, 0, 0
5627c478bd9Sstevel@tonic-gate 			), n, __m_outc
5637c478bd9Sstevel@tonic-gate 		);
5647c478bd9Sstevel@tonic-gate 	} else if (delete_line != (char *) 0) {
5657c478bd9Sstevel@tonic-gate 		GOTO(0, 0);
5667c478bd9Sstevel@tonic-gate 		while (0 < n--)
5677c478bd9Sstevel@tonic-gate 			(void) tputs(delete_line, 1, __m_outc);
5687c478bd9Sstevel@tonic-gate 	} else {
5697c478bd9Sstevel@tonic-gate 		return 0;
5707c478bd9Sstevel@tonic-gate 	}
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	/* Scroll recorded image. */
5737c478bd9Sstevel@tonic-gate 	start = 0;
5747c478bd9Sstevel@tonic-gate 	finish = count-1;
5757c478bd9Sstevel@tonic-gate 	to = lines;
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 	(void) __m_cc_erase(curscr, start, 0, finish, curscr->_maxx-1);
5787c478bd9Sstevel@tonic-gate 	(void) __m_ptr_move(
5797c478bd9Sstevel@tonic-gate 		(void **) curscr->_line, curscr->_maxy, start, finish, to
580*55fea89dSDan Cross 	);
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	simple();
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	return 1;
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate 
587*55fea89dSDan Cross STATIC int
scroll_dn(n)5887c478bd9Sstevel@tonic-gate scroll_dn(n)
5897c478bd9Sstevel@tonic-gate int n;
5907c478bd9Sstevel@tonic-gate {
5917c478bd9Sstevel@tonic-gate 	int count = n;
5927c478bd9Sstevel@tonic-gate 	int start, finish, to, row;
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	if (LINES < n)
5957c478bd9Sstevel@tonic-gate 		return 0;
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 	if (scroll_reverse != (char *) 0) {
5987c478bd9Sstevel@tonic-gate 		GOTO(0, 0);
5997c478bd9Sstevel@tonic-gate 		while (0 < n--)
6007c478bd9Sstevel@tonic-gate 			(void) tputs(scroll_reverse, 1, __m_outc);
6017c478bd9Sstevel@tonic-gate 	} else if (parm_insert_line != (char *) 0 && 1 < n) {
6027c478bd9Sstevel@tonic-gate 		GOTO(0, 0);
6037c478bd9Sstevel@tonic-gate 		(void) tputs(
6047c478bd9Sstevel@tonic-gate 			tparm(
605*55fea89dSDan Cross 				parm_insert_line, (long) n,
6067c478bd9Sstevel@tonic-gate 				0, 0, 0, 0, 0, 0, 0, 0
6077c478bd9Sstevel@tonic-gate 			), n, __m_outc
6087c478bd9Sstevel@tonic-gate 		);
6097c478bd9Sstevel@tonic-gate 	} else if (insert_line != (char *) 0) {
6107c478bd9Sstevel@tonic-gate 		GOTO(0, 0);
6117c478bd9Sstevel@tonic-gate 		while (0 < n--)
6127c478bd9Sstevel@tonic-gate 			(void) tputs(insert_line, 1, __m_outc);
6137c478bd9Sstevel@tonic-gate 	} else {
6147c478bd9Sstevel@tonic-gate 		return 0;
6157c478bd9Sstevel@tonic-gate 	}
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	/* Scroll recorded image. */
6187c478bd9Sstevel@tonic-gate 	start = lines - count;
6197c478bd9Sstevel@tonic-gate 	finish = lines - 1;
6207c478bd9Sstevel@tonic-gate 	to = 0;
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	(void) __m_cc_erase(curscr, start, 0, finish, curscr->_maxx-1);
6237c478bd9Sstevel@tonic-gate 	(void) __m_ptr_move(
6247c478bd9Sstevel@tonic-gate 		(void **) curscr->_line, curscr->_maxy, start, finish, to
625*55fea89dSDan Cross 	);
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	simple();
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 	return 1;
6307c478bd9Sstevel@tonic-gate }
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate #ifdef NEVER
6337c478bd9Sstevel@tonic-gate STATIC int
is_same_line(old,new,count)6347c478bd9Sstevel@tonic-gate is_same_line(old, new, count)
6357c478bd9Sstevel@tonic-gate cchar_t *old, *new;
6367c478bd9Sstevel@tonic-gate int count;
6377c478bd9Sstevel@tonic-gate {
6387c478bd9Sstevel@tonic-gate 	while (0 < count--)
6397c478bd9Sstevel@tonic-gate 		if (!__m_cc_compare(old, new, 1))
6407c478bd9Sstevel@tonic-gate 			return 0;
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 	return 1;
6437c478bd9Sstevel@tonic-gate }
6447c478bd9Sstevel@tonic-gate #endif /* NEVER */
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate /*f
6477c478bd9Sstevel@tonic-gate  * Dynamic programming algorithm for the string edit problem.
6487c478bd9Sstevel@tonic-gate  *
6497c478bd9Sstevel@tonic-gate  * This is a modified Gosling cost algorithm that takes into account
650*55fea89dSDan Cross  * null/move operations.
6517c478bd9Sstevel@tonic-gate  *
6527c478bd9Sstevel@tonic-gate  * Costs for move, delete, replace, and insert are 0, 1, 2, and 3
653*55fea89dSDan Cross  * repectively.
6547c478bd9Sstevel@tonic-gate  */
6557c478bd9Sstevel@tonic-gate STATIC int
cost(fr,lr)6567c478bd9Sstevel@tonic-gate cost(fr, lr)
6577c478bd9Sstevel@tonic-gate int fr, lr;
6587c478bd9Sstevel@tonic-gate {
6597c478bd9Sstevel@tonic-gate 	register lcost *lcp;
6607c478bd9Sstevel@tonic-gate 	register int or, nr, cc;
6617c478bd9Sstevel@tonic-gate 	register unsigned long *ohash = __m_screen->_hash;
6627c478bd9Sstevel@tonic-gate 	cchar_t **oline = curscr->_line;
6637c478bd9Sstevel@tonic-gate 	cchar_t **nline = newscr->_line;
6647c478bd9Sstevel@tonic-gate 	int linesz = COLS * sizeof **oline;
6657c478bd9Sstevel@tonic-gate 
666*55fea89dSDan Cross 	/* Prepare initial row and column of cost matrix.
6677c478bd9Sstevel@tonic-gate 	 *
6687c478bd9Sstevel@tonic-gate 	 *	0 3 6 9 ...
6697c478bd9Sstevel@tonic-gate 	 *	1
6707c478bd9Sstevel@tonic-gate 	 *	2
6717c478bd9Sstevel@tonic-gate 	 *	3
6727c478bd9Sstevel@tonic-gate 	 *	:
6737c478bd9Sstevel@tonic-gate 	 */
6747c478bd9Sstevel@tonic-gate 	LC(fr,fr).cost = 0;
6757c478bd9Sstevel@tonic-gate 	for (cc = 1, ++lr, nr = fr+1; nr <= lr; ++nr, ++cc) {
6767c478bd9Sstevel@tonic-gate 		/* Top row is 3, 6, 9, ... */
6777c478bd9Sstevel@tonic-gate 		LC(fr,nr).cost = cc * 3;
6787c478bd9Sstevel@tonic-gate 		LC(fr,nr).op = 'i';
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 		/* Left column is 1, 2, 3, ... */
681*55fea89dSDan Cross 		LC(nr,fr).cost = cc;
682*55fea89dSDan Cross 		LC(nr,fr).op = 'd';
6837c478bd9Sstevel@tonic-gate 	}
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 	for (--lr, or = fr; or <= lr; ++or) {
6867c478bd9Sstevel@tonic-gate 		for (nr = fr; nr <= lr; ++nr) {
6877c478bd9Sstevel@tonic-gate 			lcp = &LC(or+1,nr+1);
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate 			/* Assume move op. */
690*55fea89dSDan Cross 			lcp->cost = LC(or,nr).cost;
6917c478bd9Sstevel@tonic-gate 			lcp->op = 'm';
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 			if (ohash[or] != nhash[nr]
6947c478bd9Sstevel@tonic-gate #ifdef NEVER
6957c478bd9Sstevel@tonic-gate /* Should no longer require this code.  Using the POSIX 32-bit CRC to
696*55fea89dSDan Cross  * generate a hash value should be sufficient now, since text_replace()
6977c478bd9Sstevel@tonic-gate  * will compare the contents of a line and output only the dirty regions.
6987c478bd9Sstevel@tonic-gate  */
6997c478bd9Sstevel@tonic-gate 			|| !is_same_line(oline[or], nline[nr], linesz)
7007c478bd9Sstevel@tonic-gate #endif
7017c478bd9Sstevel@tonic-gate 			) {
7027c478bd9Sstevel@tonic-gate 				/* Lines are different, assume replace op. */
7037c478bd9Sstevel@tonic-gate 				lcp->cost += 2;
7047c478bd9Sstevel@tonic-gate 				lcp->op = 'r';
7057c478bd9Sstevel@tonic-gate 			}
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 			/* Compare insert op. */
7087c478bd9Sstevel@tonic-gate 			if ((cc = LC(or+1,nr).cost + 3) < lcp->cost) {
7097c478bd9Sstevel@tonic-gate 				lcp->cost = cc;
7107c478bd9Sstevel@tonic-gate 				lcp->op = 'i';
7117c478bd9Sstevel@tonic-gate 			}
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 			/* Compare delete op. */
7147c478bd9Sstevel@tonic-gate 			if ((cc = LC(or,nr+1).cost + 1) < lcp->cost) {
7157c478bd9Sstevel@tonic-gate 				lcp->cost = cc;
7167c478bd9Sstevel@tonic-gate 				lcp->op = 'd';
7177c478bd9Sstevel@tonic-gate 			}
7187c478bd9Sstevel@tonic-gate 		}
7197c478bd9Sstevel@tonic-gate 	}
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 	return LC(lr+1,lr+1).cost;
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate /*f
7257c478bd9Sstevel@tonic-gate  * Build edit script.
7267c478bd9Sstevel@tonic-gate  *
7277c478bd9Sstevel@tonic-gate  * Normally this would be a recursve routine doing the deletes, inserts,
7287c478bd9Sstevel@tonic-gate  * and replaces on individual lines. Instead we build the script so that
7297c478bd9Sstevel@tonic-gate  * we can later do the operations on a block basis.  For terminals with
7307c478bd9Sstevel@tonic-gate  * parm_delete or parm_insert strings this will be better in terms of the
7317c478bd9Sstevel@tonic-gate  * number of characters sent to delete and insert a block of lines.
7327c478bd9Sstevel@tonic-gate  *
7337c478bd9Sstevel@tonic-gate  * Also we can optimize the script so that tail inserts become replaces.
7347c478bd9Sstevel@tonic-gate  * This saves unnecessary inserts operations when the tail can just be
7357c478bd9Sstevel@tonic-gate  * overwritten.
7367c478bd9Sstevel@tonic-gate  */
7377c478bd9Sstevel@tonic-gate STATIC void
script(fr,lr)7387c478bd9Sstevel@tonic-gate script(fr, lr)
7397c478bd9Sstevel@tonic-gate int fr, lr;
7407c478bd9Sstevel@tonic-gate {
7417c478bd9Sstevel@tonic-gate 	int i, j;
7427c478bd9Sstevel@tonic-gate 	cchar_t *cp;
7437c478bd9Sstevel@tonic-gate 
744*55fea89dSDan Cross 	i = j = lr + 1;
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 	memset(del, 0, sizeof *del * LINES);
7477c478bd9Sstevel@tonic-gate 	memset(ins_rep, 0, sizeof *ins_rep * LINES);
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	do {
750*55fea89dSDan Cross 		/* We don't have to bounds check i or j becuase row fr and
751*55fea89dSDan Cross 		 * column fr of lc have been preset in order to guarantee the
7527c478bd9Sstevel@tonic-gate 		 * correct motion.
7537c478bd9Sstevel@tonic-gate 		 */
7547c478bd9Sstevel@tonic-gate 		switch (LC(i,j).op) {
7557c478bd9Sstevel@tonic-gate 		case 'i':
7567c478bd9Sstevel@tonic-gate 			--j;
7577c478bd9Sstevel@tonic-gate 			ins_rep[j] = lines_insert;
7587c478bd9Sstevel@tonic-gate 			break;
7597c478bd9Sstevel@tonic-gate 		case 'd':
7607c478bd9Sstevel@tonic-gate 			--i;
7617c478bd9Sstevel@tonic-gate 			del[i] = lines_delete;
7627c478bd9Sstevel@tonic-gate 			break;
7637c478bd9Sstevel@tonic-gate 		case 'm':
7647c478bd9Sstevel@tonic-gate 			--i;
7657c478bd9Sstevel@tonic-gate 			--j;
7667c478bd9Sstevel@tonic-gate 			break;
7677c478bd9Sstevel@tonic-gate 		case 'r':
7687c478bd9Sstevel@tonic-gate 			--i;
7697c478bd9Sstevel@tonic-gate 			--j;
7707c478bd9Sstevel@tonic-gate 			ins_rep[j] = lines_replace;
7717c478bd9Sstevel@tonic-gate 			break;
7727c478bd9Sstevel@tonic-gate 		}
7737c478bd9Sstevel@tonic-gate 	} while (fr < i || fr < j);
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 	/* Optimize Tail Inserts */
7767c478bd9Sstevel@tonic-gate 	for (i = LINES-1; 0 <= i && ins_rep[i] == lines_insert; --i) {
7777c478bd9Sstevel@tonic-gate 		/* Make each character in the screen line image invalid. */
7787c478bd9Sstevel@tonic-gate 		for (cp = curscr->_line[i], j = 0; j < COLS; ++j, ++cp)
7797c478bd9Sstevel@tonic-gate 			cp->_n = -1;
7807c478bd9Sstevel@tonic-gate 		ins_rep[i] = lines_replace;
7817c478bd9Sstevel@tonic-gate 	}
7827c478bd9Sstevel@tonic-gate }
783*55fea89dSDan Cross 
7847c478bd9Sstevel@tonic-gate /*f
7857c478bd9Sstevel@tonic-gate  * Complex update algorithm using insert/delete line operations.
7867c478bd9Sstevel@tonic-gate  *
7877c478bd9Sstevel@tonic-gate  * References:
788*55fea89dSDan Cross  * [MyM86]	E.W. Myers & W. Miller, Row Replacement Algorithms for
7897c478bd9Sstevel@tonic-gate  *		Screen Editors, TR 86-19, Dept. Computer Science, U. of Arizona
7907c478bd9Sstevel@tonic-gate  * [MyM87]	E.W. Myers & W. Miller, A Simple Row Replacement Method,
7917c478bd9Sstevel@tonic-gate  *		TR 86-28, Dept. Computer Science, U. of Arizona
7927c478bd9Sstevel@tonic-gate  * [Mil87]	W. Miller, A Software Tools Sampler, Prentice-Hall, 1987
793*55fea89dSDan Cross  * [Gos81]	James Gosling, A redisplay algorithm, Proceedings of the
794*55fea89dSDan Cross  *		ACM Symposium on Text Manipulation, SIGPLAN Notices,
7957c478bd9Sstevel@tonic-gate  *		16(6) June 1981, pg 123-129
7967c478bd9Sstevel@tonic-gate  *
7977c478bd9Sstevel@tonic-gate  * All the above were reviewed and experimented with.  Due to the nature of
7987c478bd9Sstevel@tonic-gate  * Curses' having to handling overlapping WINDOWs, the only suitable
7997c478bd9Sstevel@tonic-gate  * algorithum is [Gos81].  The others are better suited to editor type
8007c478bd9Sstevel@tonic-gate  * applications that have one window being the entire terminal screen.
8017c478bd9Sstevel@tonic-gate  *
8027c478bd9Sstevel@tonic-gate  */
8037c478bd9Sstevel@tonic-gate STATIC void
complex()8047c478bd9Sstevel@tonic-gate complex()
8057c478bd9Sstevel@tonic-gate {
8067c478bd9Sstevel@tonic-gate 	int fr = -1;
8077c478bd9Sstevel@tonic-gate 	int i, j, lr;
8087c478bd9Sstevel@tonic-gate 	t_action func;
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate 	/* Find block of lines to change */
8117c478bd9Sstevel@tonic-gate 	for (i = 0; i < LINES; ++i) {
8127c478bd9Sstevel@tonic-gate 		if (newscr->_first[i] < newscr->_last[i]) {
8137c478bd9Sstevel@tonic-gate 			/* Compute new hash. */
8147c478bd9Sstevel@tonic-gate 			__m_cc_hash(newscr, nhash, i);
8157c478bd9Sstevel@tonic-gate 			if (fr == -1)
8167c478bd9Sstevel@tonic-gate 				fr = i;
8177c478bd9Sstevel@tonic-gate 			lr = i;
8187c478bd9Sstevel@tonic-gate 		} else {
8197c478bd9Sstevel@tonic-gate 			/* Line not dirty so hash same as before. */
8207c478bd9Sstevel@tonic-gate 			nhash[i] = __m_screen->_hash[i];
8217c478bd9Sstevel@tonic-gate 		}
8227c478bd9Sstevel@tonic-gate 	}
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 	if (fr != -1) {
8257c478bd9Sstevel@tonic-gate 		/* Gosling */
8267c478bd9Sstevel@tonic-gate 		cost(fr, lr);
8277c478bd9Sstevel@tonic-gate 		script(fr, lr);
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 		/* Do deletes first in reverse order. */
8307c478bd9Sstevel@tonic-gate 		for (j = lr; fr <= j; --j) {
8317c478bd9Sstevel@tonic-gate 			if (del[j] != (t_action) 0) {
8327c478bd9Sstevel@tonic-gate 				for (i = j-1; fr <= i; --i)
8337c478bd9Sstevel@tonic-gate 					if (del[i] == (t_action) 0)
8347c478bd9Sstevel@tonic-gate 						break;
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 				lines_delete(i+1, j+1);
8377c478bd9Sstevel@tonic-gate 				j = i;
8387c478bd9Sstevel@tonic-gate 			}
8397c478bd9Sstevel@tonic-gate 		}
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 		/* Do insert/replace in forward order. */
8427c478bd9Sstevel@tonic-gate 		for (i = fr; i <= lr; ++i) {
8437c478bd9Sstevel@tonic-gate 			if ((func = ins_rep[i]) != (t_action) 0) {
8447c478bd9Sstevel@tonic-gate 				/* Find size of block */
8457c478bd9Sstevel@tonic-gate 				for (j = i; j <= lr && ins_rep[j] == func; ++j)
8467c478bd9Sstevel@tonic-gate 					;
8477c478bd9Sstevel@tonic-gate 				(*func)(i, j);
8487c478bd9Sstevel@tonic-gate 				i = j-1;
8497c478bd9Sstevel@tonic-gate 			}
8507c478bd9Sstevel@tonic-gate 		}
8517c478bd9Sstevel@tonic-gate record:
852*55fea89dSDan Cross 		/* _line[], which contains pointers to screen lines,
8537c478bd9Sstevel@tonic-gate 		 * may be shuffled.
8547c478bd9Sstevel@tonic-gate 		 */
8557c478bd9Sstevel@tonic-gate 		for (i = fr; i <= lr; ++i) {
8567c478bd9Sstevel@tonic-gate 			/* Save new hash for next update. */
8577c478bd9Sstevel@tonic-gate 			__m_screen->_hash[i] = nhash[i];
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 			/* Mark line as untouched. */
8607c478bd9Sstevel@tonic-gate 			newscr->_first[i] = newscr->_maxx;
8617c478bd9Sstevel@tonic-gate 			newscr->_last[i] = -1;
8627c478bd9Sstevel@tonic-gate 		}
8637c478bd9Sstevel@tonic-gate 	}
8647c478bd9Sstevel@tonic-gate }
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate /*f
8677c478bd9Sstevel@tonic-gate  * Simple screen update algorithm
8687c478bd9Sstevel@tonic-gate  *
869*55fea89dSDan Cross  * We perform a simple incremental update of the terminal screen.
870*55fea89dSDan Cross  * Only the segment of a line that was touched is replaced on the
8717c478bd9Sstevel@tonic-gate  * line.
8727c478bd9Sstevel@tonic-gate  */
8737c478bd9Sstevel@tonic-gate STATIC void
simple()8747c478bd9Sstevel@tonic-gate simple()
8757c478bd9Sstevel@tonic-gate {
8767c478bd9Sstevel@tonic-gate 	int row;
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate 	for (row = 0; row < LINES; ++row) {
8797c478bd9Sstevel@tonic-gate 		if (newscr->_first[row] < newscr->_last[row]) {
8807c478bd9Sstevel@tonic-gate 			text_replace(row);
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate 			/* Mark line as untouched. */
8837c478bd9Sstevel@tonic-gate 			newscr->_first[row] = newscr->_maxx;
8847c478bd9Sstevel@tonic-gate 			newscr->_last[row] = -1;
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 			if (__m_screen->_flags & S_INS_DEL_LINE)
8877c478bd9Sstevel@tonic-gate 				__m_cc_hash(newscr, nhash, row);
8887c478bd9Sstevel@tonic-gate 		}
8897c478bd9Sstevel@tonic-gate 	}
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 	newscr->_flags &= ~W_REDRAW_WINDOW;
8927c478bd9Sstevel@tonic-gate }
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate /*f
8957c478bd9Sstevel@tonic-gate  * Send all changes made to _newscr to the physical terminal.
8967c478bd9Sstevel@tonic-gate  *
8977c478bd9Sstevel@tonic-gate  * If idlok() is set TRUE then doupdate will try and use hardware insert
8987c478bd9Sstevel@tonic-gate  * and delete line sequences in an effort to optimize output.  idlok()
8997c478bd9Sstevel@tonic-gate  * should really only be used in applications that want a proper scrolling
9007c478bd9Sstevel@tonic-gate  * effect.
901*55fea89dSDan Cross  *
9027c478bd9Sstevel@tonic-gate  * Added scroll heuristic to handle special case where a full size window
9037c478bd9Sstevel@tonic-gate  * with full size scroll region, will scroll the window and replace dirty
9047c478bd9Sstevel@tonic-gate  * lines instead of performing usual cost/script operations.
9057c478bd9Sstevel@tonic-gate  */
906*55fea89dSDan Cross int
doupdate()9077c478bd9Sstevel@tonic-gate doupdate()
9087c478bd9Sstevel@tonic-gate {
9097c478bd9Sstevel@tonic-gate #ifdef SIGTSTP
9107c478bd9Sstevel@tonic-gate 	int (*oldsig)(int) = signal(SIGTSTP, SIG_IGN);
9117c478bd9Sstevel@tonic-gate #endif
9127c478bd9Sstevel@tonic-gate 
9137c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TYPEAHEAD
9147c478bd9Sstevel@tonic-gate 	unsigned char cc;
91567a4bb8fSGary Mills 	volatile int min, time, icanon;
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate 	if (__m_screen->_flags & S_ISATTY) {
9187c478bd9Sstevel@tonic-gate 		/* Set up non-blocking input for typeahead trapping. */
9197c478bd9Sstevel@tonic-gate 		min = cur_term->_prog.c_cc[VMIN];
9207c478bd9Sstevel@tonic-gate 		time = cur_term->_prog.c_cc[VTIME];
9217c478bd9Sstevel@tonic-gate 		icanon = cur_term->_prog.c_lflag & ICANON;
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 		cur_term->_prog.c_cc[VMIN] = 0;
9247c478bd9Sstevel@tonic-gate 		cur_term->_prog.c_cc[VTIME] = 0;
9257c478bd9Sstevel@tonic-gate 		cur_term->_prog.c_lflag &= ~ICANON;
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 		(void) tcsetattr(__m_screen->_kfd, TCSANOW, &cur_term->_prog);
9287c478bd9Sstevel@tonic-gate 	}
9297c478bd9Sstevel@tonic-gate #endif /* M_CURSES_TYPEAHEAD */
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
9327c478bd9Sstevel@tonic-gate 	__m_trace(
933*55fea89dSDan Cross 		"doupdate(void) using %s algorithm.",
9347c478bd9Sstevel@tonic-gate 		(__m_screen->_flags & S_INS_DEL_LINE) ? "complex" : "simple"
9357c478bd9Sstevel@tonic-gate 	);
9367c478bd9Sstevel@tonic-gate #endif
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate 	newscr = __m_screen->_newscr;
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 	if (__m_screen->_flags & S_ENDWIN) {
9417c478bd9Sstevel@tonic-gate 		/* Return from temporary escape done with endwin(). */
9427c478bd9Sstevel@tonic-gate 		__m_screen->_flags &= ~S_ENDWIN;
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 		(void) reset_prog_mode();
9457c478bd9Sstevel@tonic-gate 		if (enter_ca_mode != (char *) 0)
9467c478bd9Sstevel@tonic-gate 			(void) tputs(enter_ca_mode, 1, __m_outc);
9477c478bd9Sstevel@tonic-gate 		if (keypad_xmit != (char *) 0)
9487c478bd9Sstevel@tonic-gate 			(void) tputs(keypad_xmit, 1, __m_outc);
9497c478bd9Sstevel@tonic-gate 		if (ena_acs != (char *) 0)
9507c478bd9Sstevel@tonic-gate 			(void) tputs(ena_acs, 1, __m_outc);
9517c478bd9Sstevel@tonic-gate 
9527c478bd9Sstevel@tonic-gate 		/* Force redraw of screen. */
9537c478bd9Sstevel@tonic-gate 		newscr->_flags |= W_CLEAR_WINDOW;
9547c478bd9Sstevel@tonic-gate 	}
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TYPEAHEAD
9577c478bd9Sstevel@tonic-gate 	if (setjmp(breakout) == 0) {
9587c478bd9Sstevel@tonic-gate 		if ((__m_screen->_flags & S_ISATTY)
9597c478bd9Sstevel@tonic-gate 		&& read(__m_screen->_kfd, &cc, sizeof cc) == sizeof cc) {
9607c478bd9Sstevel@tonic-gate 			(void) ungetch(cc);
9617c478bd9Sstevel@tonic-gate 			longjmp(breakout, 1);
9627c478bd9Sstevel@tonic-gate 		}
9637c478bd9Sstevel@tonic-gate #endif /* M_CURSES_TYPEAHEAD */
9647c478bd9Sstevel@tonic-gate 
965*55fea89dSDan Cross 		/* When redrawwing a window, we not only assume that line
9667c478bd9Sstevel@tonic-gate 		 * noise may have lost characters, but line noise may have
9677c478bd9Sstevel@tonic-gate 		 * generated bogus characters on the screen outside the
9687c478bd9Sstevel@tonic-gate 		 * the window in question, in which case redraw the entire
9697c478bd9Sstevel@tonic-gate 		 * screen to be sure.
9707c478bd9Sstevel@tonic-gate 		 */
9717c478bd9Sstevel@tonic-gate 		if (newscr->_flags & (W_CLEAR_WINDOW | W_REDRAW_WINDOW)) {
9727c478bd9Sstevel@tonic-gate 			clear_bottom(0);
9737c478bd9Sstevel@tonic-gate 			newscr->_flags &= ~W_CLEAR_WINDOW;
9747c478bd9Sstevel@tonic-gate 			(void) wtouchln(newscr, 0, newscr->_maxy, 1);
9757c478bd9Sstevel@tonic-gate 		}
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 		if (newscr->_flags & W_REDRAW_WINDOW)
9787c478bd9Sstevel@tonic-gate 			simple();
9797c478bd9Sstevel@tonic-gate #if 0		/* This first expression, of undefined section, is useless
9807c478bd9Sstevel@tonic-gate 		 * since newscr->_scroll is unsigned and never LT zero.
9817c478bd9Sstevel@tonic-gate 		 */
9827c478bd9Sstevel@tonic-gate 		else if (newscr->_scroll < 0 && scroll_dn(-newscr->_scroll))
9837c478bd9Sstevel@tonic-gate #else
9847c478bd9Sstevel@tonic-gate 		else if (scroll_dn(-newscr->_scroll))
9857c478bd9Sstevel@tonic-gate #endif
9867c478bd9Sstevel@tonic-gate 			;
9877c478bd9Sstevel@tonic-gate 		else if (0 < newscr->_scroll && scroll_up(newscr->_scroll))
9887c478bd9Sstevel@tonic-gate 			;
9897c478bd9Sstevel@tonic-gate 		else if (__m_screen->_flags & S_INS_DEL_LINE)
9907c478bd9Sstevel@tonic-gate 			complex();
9917c478bd9Sstevel@tonic-gate 		else
9927c478bd9Sstevel@tonic-gate 			simple();
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 		if (!(newscr->_flags & W_LEAVE_CURSOR))
9957c478bd9Sstevel@tonic-gate 			GOTO(newscr->_cury, newscr->_curx);
9967c478bd9Sstevel@tonic-gate 
9977c478bd9Sstevel@tonic-gate 		if (!(curscr->_flags & W_FLUSH))
9987c478bd9Sstevel@tonic-gate 			(void) fflush(__m_screen->_of);
9997c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TYPEAHEAD
10007c478bd9Sstevel@tonic-gate 	}
10017c478bd9Sstevel@tonic-gate 
10027c478bd9Sstevel@tonic-gate 	if (__m_screen->_flags & S_ISATTY) {
10037c478bd9Sstevel@tonic-gate 		/* Restore previous input mode. */
10047c478bd9Sstevel@tonic-gate 		cur_term->_prog.c_cc[VMIN] = min;
10057c478bd9Sstevel@tonic-gate 		cur_term->_prog.c_cc[VTIME] = time;
10067c478bd9Sstevel@tonic-gate 		cur_term->_prog.c_lflag |= icanon;
10077c478bd9Sstevel@tonic-gate 
10087c478bd9Sstevel@tonic-gate 		(void) tcsetattr(__m_screen->_kfd,TCSANOW,&cur_term->_prog);
10097c478bd9Sstevel@tonic-gate 	}
10107c478bd9Sstevel@tonic-gate #endif /* M_CURSES_TYPEAHEAD */
10117c478bd9Sstevel@tonic-gate 
10127c478bd9Sstevel@tonic-gate 	newscr->_scroll = curscr->_scroll = 0;
10137c478bd9Sstevel@tonic-gate #ifdef SIGTSTP
10147c478bd9Sstevel@tonic-gate 	signal(SIGTSTP, oldsig);
10157c478bd9Sstevel@tonic-gate #endif
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 	return __m_return_code("doupdate", OK);
10187c478bd9Sstevel@tonic-gate }
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate /*
10217c478bd9Sstevel@tonic-gate  * If true, the implementation may use hardware insert and delete,
10227c478bd9Sstevel@tonic-gate  * character features of the terminal.  The window parameter
10237c478bd9Sstevel@tonic-gate  * is ignored.
10247c478bd9Sstevel@tonic-gate  */
10257c478bd9Sstevel@tonic-gate void
idcok(WINDOW * w,bool bf)10267c478bd9Sstevel@tonic-gate idcok(WINDOW *w, bool bf)
10277c478bd9Sstevel@tonic-gate {
10287c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
10297c478bd9Sstevel@tonic-gate 	__m_trace("idcok(%p, %d)", w, bf);
10307c478bd9Sstevel@tonic-gate #endif
1031*55fea89dSDan Cross 
10327c478bd9Sstevel@tonic-gate 	__m_screen->_flags &= ~S_INS_DEL_CHAR;
10337c478bd9Sstevel@tonic-gate 	if (bf)
10347c478bd9Sstevel@tonic-gate 		__m_screen->_flags |= S_INS_DEL_CHAR;
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 	__m_return_void("idcok");
10377c478bd9Sstevel@tonic-gate }
1038*55fea89dSDan Cross 
10397c478bd9Sstevel@tonic-gate /*
10407c478bd9Sstevel@tonic-gate  * If true, the implementation may use hardware insert, delete,
10417c478bd9Sstevel@tonic-gate  * and scroll line features of the terminal.  The window parameter
10427c478bd9Sstevel@tonic-gate  * is ignored.
10437c478bd9Sstevel@tonic-gate  */
10447c478bd9Sstevel@tonic-gate int
idlok(WINDOW * w,bool bf)10457c478bd9Sstevel@tonic-gate idlok(WINDOW *w, bool bf)
10467c478bd9Sstevel@tonic-gate {
10477c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
10487c478bd9Sstevel@tonic-gate 	__m_trace("idlok(%p, %d)", w, bf);
10497c478bd9Sstevel@tonic-gate #endif
10507c478bd9Sstevel@tonic-gate 
10517c478bd9Sstevel@tonic-gate 	__m_screen->_flags &= ~S_INS_DEL_LINE;
10527c478bd9Sstevel@tonic-gate 	if (bf && has_il())
10537c478bd9Sstevel@tonic-gate 		__m_screen->_flags |= S_INS_DEL_LINE;
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate 	return __m_return_code("idlok", OK);
10567c478bd9Sstevel@tonic-gate }
10577c478bd9Sstevel@tonic-gate 
10587c478bd9Sstevel@tonic-gate /*
1059*55fea89dSDan Cross  * Use the POSIX 32-bit CRC function to compute a hash value
10607c478bd9Sstevel@tonic-gate  * for the window line.
10617c478bd9Sstevel@tonic-gate  */
10627c478bd9Sstevel@tonic-gate void
__m_cc_hash(w,array,y)10637c478bd9Sstevel@tonic-gate __m_cc_hash(w, array, y)
10647c478bd9Sstevel@tonic-gate WINDOW *w;
10657c478bd9Sstevel@tonic-gate unsigned long *array;
10667c478bd9Sstevel@tonic-gate int y;
10677c478bd9Sstevel@tonic-gate {
10687c478bd9Sstevel@tonic-gate 	array[y] = 0;
10697c478bd9Sstevel@tonic-gate 	m_crcposix(
1070*55fea89dSDan Cross 		&array[y], (unsigned char *) w->_line[y],
10717c478bd9Sstevel@tonic-gate 		(size_t) (w->_maxx * sizeof **w->_line)
10727c478bd9Sstevel@tonic-gate 	);
10737c478bd9Sstevel@tonic-gate }
10747c478bd9Sstevel@tonic-gate 
10757c478bd9Sstevel@tonic-gate 
1076