17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bdstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bdstevel@tonic-gate * (the "License").  You may not use this file except in compliance
77c478bdstevel@tonic-gate * with the License.
87c478bdstevel@tonic-gate *
97c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bdstevel@tonic-gate * See the License for the specific language governing permissions
127c478bdstevel@tonic-gate * and limitations under the License.
137c478bdstevel@tonic-gate *
147c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bdstevel@tonic-gate *
207c478bdstevel@tonic-gate * CDDL HEADER END
217c478bdstevel@tonic-gate */
227c478bdstevel@tonic-gate/*
237c478bdstevel@tonic-gate * Copyright (c) 1995-1999 by Sun Microsystems, Inc.
247c478bdstevel@tonic-gate * All rights reserved.
257c478bdstevel@tonic-gate */
267c478bdstevel@tonic-gate
277c478bdstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bdstevel@tonic-gate
297c478bdstevel@tonic-gate/* LINTLIBRARY */
307c478bdstevel@tonic-gate
317c478bdstevel@tonic-gate/*
327c478bdstevel@tonic-gate * doupdate.c
337c478bdstevel@tonic-gate *
347c478bdstevel@tonic-gate * XCurses Library
357c478bdstevel@tonic-gate *
367c478bdstevel@tonic-gate * Copyright 1990, 1995 by Mortice Kern Systems Inc.  All rights reserved.
377c478bdstevel@tonic-gate *
387c478bdstevel@tonic-gate */
397c478bdstevel@tonic-gate
407c478bdstevel@tonic-gate#ifdef M_RCSID
417c478bdstevel@tonic-gate#ifndef lint
427c478bdstevel@tonic-gatestatic char const rcsID[] =
437c478bdstevel@tonic-gate"$Header: /team/ps/sun_xcurses/archive/local_changes/xcurses/src/lib/"
447c478bdstevel@tonic-gate"libxcurses/src/libc/xcurses/rcs/doupdate.c 1.22 1998/06/04 12:13:38 "
457c478bdstevel@tonic-gate"cbates Exp $";
467c478bdstevel@tonic-gate#endif
477c478bdstevel@tonic-gate#endif
487c478bdstevel@tonic-gate
497c478bdstevel@tonic-gate#include <sys/isa_defs.h>
507c478bdstevel@tonic-gate#include <private.h>
517c478bdstevel@tonic-gate#include <string.h>
527c478bdstevel@tonic-gate#include <signal.h>
537c478bdstevel@tonic-gate
547c478bdstevel@tonic-gate#undef SIGTSTP
557c478bdstevel@tonic-gate
567c478bdstevel@tonic-gate/*
577c478bdstevel@tonic-gate * This value is the ideal length for the cursor addressing sequence
587c478bdstevel@tonic-gate * being four bytes long, ie. "<escape><cursor addressing code><row><col>".
597c478bdstevel@tonic-gate * eg. VT52 - "\EYrc" or ADM3A - "\E=rc"
607c478bdstevel@tonic-gate */
617c478bdstevel@tonic-gate#define	JUMP_SIZE	4
627c478bdstevel@tonic-gate
637c478bdstevel@tonic-gate/*
647c478bdstevel@tonic-gate * This value is the ideal length for the clear-to-eol sequence
657c478bdstevel@tonic-gate * being two bytes long, ie "<escape><clear eol code>".
667c478bdstevel@tonic-gate */
677c478bdstevel@tonic-gate#define	CEOL_SIZE	2
687c478bdstevel@tonic-gate
697c478bdstevel@tonic-gate#define	GOTO(r, c)	((void) __m_mvcur(curscr->_cury, curscr->_curx,\
707c478bdstevel@tonic-gate	r, c, __m_outc), curscr->_cury = r, curscr->_curx = c)
717c478bdstevel@tonic-gate
727c478bdstevel@tonic-gatetypedef struct cost_op {
737c478bdstevel@tonic-gate	short	cost;
747c478bdstevel@tonic-gate	short	op;
757c478bdstevel@tonic-gate} lcost;
767c478bdstevel@tonic-gate
777c478bdstevel@tonic-gatetypedef void (*t_action)(int, int);
787c478bdstevel@tonic-gate
797c478bdstevel@tonic-gate
807c478bdstevel@tonic-gate#define	LC(i, j) 	(lc[(i) * (LINES + 1) + (j)])
817c478bdstevel@tonic-gate
827c478bdstevel@tonic-gatestatic lcost *lc = NULL;
837c478bdstevel@tonic-gate#if defined(_LP64)
847c478bdstevel@tonic-gatestatic unsigned int	*nhash = NULL;
857c478bdstevel@tonic-gate#else
867c478bdstevel@tonic-gatestatic unsigned long	*nhash = NULL;
877c478bdstevel@tonic-gate#endif
887c478bdstevel@tonic-gatestatic t_action *del = NULL;
897c478bdstevel@tonic-gatestatic t_action *ins_rep = NULL;
907c478bdstevel@tonic-gate
917c478bdstevel@tonic-gatestatic WINDOW	*newscr;
927c478bdstevel@tonic-gate
937c478bdstevel@tonic-gatestatic void erase_bottom(int, int);
947c478bdstevel@tonic-gatestatic void clear_bottom(int);
957c478bdstevel@tonic-gatestatic void complex(void);
967c478bdstevel@tonic-gatestatic int cost(int, int);
977c478bdstevel@tonic-gatestatic void lines_delete(int, int);
987c478bdstevel@tonic-gatestatic void lines_insert(int, int);
997c478bdstevel@tonic-gatestatic void lines_replace(int, int);
1007c478bdstevel@tonic-gatestatic void script(int, int);
1017c478bdstevel@tonic-gatestatic int scroll_up(int);
1027c478bdstevel@tonic-gatestatic void simple(void);
1037c478bdstevel@tonic-gatestatic void text_replace(int);
1047c478bdstevel@tonic-gate#if 0
1057c478bdstevel@tonic-gatestatic int scroll_dn(int);
1067c478bdstevel@tonic-gate#endif
1077c478bdstevel@tonic-gate
1087c478bdstevel@tonic-gate
1097c478bdstevel@tonic-gate/*
1107c478bdstevel@tonic-gate * Wrapper that streams Curses output.
1117c478bdstevel@tonic-gate *
1127c478bdstevel@tonic-gate * All escape sequences going to the screen come through here.
1137c478bdstevel@tonic-gate * All ordinary characters go to the screen via the putc in doupdate.c
1147c478bdstevel@tonic-gate */
1157c478bdstevel@tonic-gateint
1167c478bdstevel@tonic-gate__m_outc(int ch)
1177c478bdstevel@tonic-gate{
1187c478bdstevel@tonic-gate	return (putc(ch, __m_screen->_of));
1197c478bdstevel@tonic-gate}
1207c478bdstevel@tonic-gate
1217c478bdstevel@tonic-gate/*
1227c478bdstevel@tonic-gate * Allocate or grow doupdate() structures.
1237c478bdstevel@tonic-gate */
1247c478bdstevel@tonic-gateint
1257c478bdstevel@tonic-gate__m_doupdate_init(void)
1267c478bdstevel@tonic-gate{
1277c478bdstevel@tonic-gate	void	*new;
1287c478bdstevel@tonic-gate	static short	nlines = 0;
1297c478bdstevel@tonic-gate
1307c478bdstevel@tonic-gate	if (lines <= 0)
1317c478bdstevel@tonic-gate		return (-1);
1327c478bdstevel@tonic-gate
1337c478bdstevel@tonic-gate	if (lines <= nlines)
1347c478bdstevel@tonic-gate		return (0);
1357c478bdstevel@tonic-gate
1367c478bdstevel@tonic-gate	new = malloc((lines + 1) * (lines + 1) * sizeof (*lc));
1377c478bdstevel@tonic-gate	if (new == NULL)
1387c478bdstevel@tonic-gate		return (-1);
1397c478bdstevel@tonic-gate	if (lc != NULL)
1407c478bdstevel@tonic-gate		free(lc);
1417c478bdstevel@tonic-gate	lc = (lcost *) new;
1427c478bdstevel@tonic-gate
1437c478bdstevel@tonic-gate	new = malloc((lines + lines) * sizeof (*del));
1447c478bdstevel@tonic-gate	if (new == NULL)
1457c478bdstevel@tonic-gate		return (-1);
1467c478bdstevel@tonic-gate	if (del != NULL)
1477c478bdstevel@tonic-gate		free(del);
1487c478bdstevel@tonic-gate	del = (t_action *) new;
1497c478bdstevel@tonic-gate	ins_rep = del + lines;
1507c478bdstevel@tonic-gate
1517c478bdstevel@tonic-gate	new = malloc(lines * sizeof (*nhash));
1527c478bdstevel@tonic-gate	if (new == NULL)
1537c478bdstevel@tonic-gate		return (-1);
1547c478bdstevel@tonic-gate	if (nhash != NULL)
1557c478bdstevel@tonic-gate		free(nhash);
1567c478bdstevel@tonic-gate#if defined(_LP64)
1577c478bdstevel@tonic-gate	nhash = (unsigned int *) new;
1587c478bdstevel@tonic-gate#else
1597c478bdstevel@tonic-gate	nhash = (unsigned long *) new;
1607c478bdstevel@tonic-gate#endif
1617c478bdstevel@tonic-gate
1627c478bdstevel@tonic-gate	nlines = lines;
1637c478bdstevel@tonic-gate
1647c478bdstevel@tonic-gate	return (0);
1657c478bdstevel@tonic-gate}
1667c478bdstevel@tonic-gate
1677c478bdstevel@tonic-gatestatic void
1687c478bdstevel@tonic-gateerase_bottom(int start, int end)
1697c478bdstevel@tonic-gate{
1707c478bdstevel@tonic-gate	int i;
1717c478bdstevel@tonic-gate
1727c478bdstevel@tonic-gate	for (i = start; i < end; ++i) {
1737c478bdstevel@tonic-gate		(void) __m_cc_erase(curscr, i, 0, i, curscr->_maxx - 1);
1747c478bdstevel@tonic-gate		__m_cc_hash(curscr, __m_screen->_hash, i);
1757c478bdstevel@tonic-gate	}
1767c478bdstevel@tonic-gate}
1777c478bdstevel@tonic-gate
1787c478bdstevel@tonic-gate/*
1797c478bdstevel@tonic-gate *  Clear from the start of the current row to bottom of screen.
1807c478bdstevel@tonic-gate */
1817c478bdstevel@tonic-gatestatic void
1827c478bdstevel@tonic-gateclear_bottom(int y)
1837c478bdstevel@tonic-gate{
1847c478bdstevel@tonic-gate	/* Restore default color pair before doing area clears. */
1857c478bdstevel@tonic-gate	if (back_color_erase)
1867c478bdstevel@tonic-gate		(void) vid_puts(WA_NORMAL, 0, (void *) 0, __m_outc);
1877c478bdstevel@tonic-gate
1887c478bdstevel@tonic-gate	if (y == 0 && clear_screen != NULL) {
1897c478bdstevel@tonic-gate		(void) TPUTS(clear_screen, 1, __m_outc);
1907c478bdstevel@tonic-gate	} else {
1917c478bdstevel@tonic-gate		(void) __m_mvcur(-1, -1, y, 0, __m_outc);
1927c478bdstevel@tonic-gate		if (clr_eos != NULL) {
1937c478bdstevel@tonic-gate			(void) TPUTS(clr_eos, 1, __m_outc);
1947c478bdstevel@tonic-gate		} else if (clr_eol != NULL) {
1957c478bdstevel@tonic-gate			for (;;) {
1967c478bdstevel@tonic-gate				(void) TPUTS(clr_eol, 1, __m_outc);
1977c478bdstevel@tonic-gate				if (LINES <= y)
1987c478bdstevel@tonic-gate					break;
1997c478bdstevel@tonic-gate				(void) __m_mvcur(y, 0, y + 1, 0, __m_outc);
2007c478bdstevel@tonic-gate				++y;
2017c478bdstevel@tonic-gate			}
2027c478bdstevel@tonic-gate		}
2037c478bdstevel@tonic-gate	}
2047c478bdstevel@tonic-gate
2057c478bdstevel@tonic-gate	curscr->_cury = y;
2067c478bdstevel@tonic-gate	curscr->_curx = 0;
2077c478bdstevel@tonic-gate}
2087c478bdstevel@tonic-gate
2097c478bdstevel@tonic-gate
2107c478bdstevel@tonic-gate
2117c478bdstevel@tonic-gate/*
2127c478bdstevel@tonic-gate * Rewrite of text_replace() implementation by C. Bates of MKS
2137c478bdstevel@tonic-gate *
2147c478bdstevel@tonic-gate * This code creates a list of 'regions' for each test line which
2157c478bdstevel@tonic-gate * is to be replaced. Each region describes a portion of the line.
2167c478bdstevel@tonic-gate * Logic is performed on the list of regions, then the regions
2177c478bdstevel@tonic-gate * are used to generate output.
2187c478bdstevel@tonic-gate */
2197c478bdstevel@tonic-gatetypedef	struct LineRegion {
2207c478bdstevel@tonic-gate	int	col;	/* Starting column of region */
2217c478bdstevel@tonic-gate	int	size;	/* Size of region */
2227c478bdstevel@tonic-gate	/* 0: Difference Region, 1: Common Region, 2: Delete Region */
2237c478bdstevel@tonic-gate	int	type;
2247c478bdstevel@tonic-gate} LineRegion;
2257c478bdstevel@tonic-gate#define	REGION_DIFFERENT	0
2267c478bdstevel@tonic-gate#define	REGION_COMMON		1
2277c478bdstevel@tonic-gate#define	REGION_DELETE		2
2287c478bdstevel@tonic-gate
2297c478bdstevel@tonic-gate#define	DELETE_SEARCH_LIMIT	4
2307c478bdstevel@tonic-gate#define	DELETE_THRESHOLD	10
2317c478bdstevel@tonic-gate
2327c478bdstevel@tonic-gatestatic LineRegion	regions[1024];
2337c478bdstevel@tonic-gateint	nRegions = 0;
2347c478bdstevel@tonic-gate
2357c478bdstevel@tonic-gate/*
2367c478bdstevel@tonic-gate * Return the first column of the completely blank End-of-line
2377c478bdstevel@tonic-gate */
2387c478bdstevel@tonic-gatestatic int
2397c478bdstevel@tonic-gate_find_blank_tail(int row)
2407c478bdstevel@tonic-gate{
2417c478bdstevel@tonic-gate	cchar_t	*nptr;
2427c478bdstevel@tonic-gate	int	tail = COLS;
2437c478bdstevel@tonic-gate
2447c478bdstevel@tonic-gate	if (!clr_eol)
2457c478bdstevel@tonic-gate		return (COLS);
2467c478bdstevel@tonic-gate	/*
2477c478bdstevel@tonic-gate	 * Find start of blank tail region.
2487c478bdstevel@tonic-gate	 */
2497c478bdstevel@tonic-gate	nptr = &newscr->_line[row][COLS];
2507c478bdstevel@tonic-gate	for (; 0 < tail; --tail) {
2517c478bdstevel@tonic-gate		if (!__m_cc_compare(--nptr, &newscr->_bg, 1))
2527c478bdstevel@tonic-gate			break;
2537c478bdstevel@tonic-gate	}
2547c478bdstevel@tonic-gate	return (tail);
2557c478bdstevel@tonic-gate}
2567c478bdstevel@tonic-gate
2577c478bdstevel@tonic-gate/*
2587c478bdstevel@tonic-gate * Send all the characters in the region to the terminal
2597c478bdstevel@tonic-gate */
2607c478bdstevel@tonic-gatestatic void
2617c478bdstevel@tonic-gate_writeRegion(int row, LineRegion region)
2627c478bdstevel@tonic-gate{
2637c478bdstevel@tonic-gate	short	npair;
2647c478bdstevel@tonic-gate	attr_t	nattr;
2657c478bdstevel@tonic-gate	int	i;
2667c478bdstevel@tonic-gate	cchar_t	*optr = &curscr->_line[row][region.col];
2677c478bdstevel@tonic-gate	cchar_t	*nptr = &newscr->_line[row][region.col];
2687c478bdstevel@tonic-gate
2697c478bdstevel@tonic-gate	for (i = 0; i < region.size; i++, nptr++, optr++) {
2707c478bdstevel@tonic-gate		nattr = nptr->_at;
2717c478bdstevel@tonic-gate		npair = nptr->_co;
2727c478bdstevel@tonic-gate
2737c478bdstevel@tonic-gate		/*
2747c478bdstevel@tonic-gate		 * Change attribute state.
2757c478bdstevel@tonic-gate		 */
2767c478bdstevel@tonic-gate		if ((ATTR_STATE != nattr) || (optr->_at != nattr) ||
2777c478bdstevel@tonic-gate			(cur_term->_co != npair)) {
2787c478bdstevel@tonic-gate			(void) vid_puts(nattr, npair, NULL, __m_outc);
2797c478bdstevel@tonic-gate		}
2807c478bdstevel@tonic-gate		/*
2817c478bdstevel@tonic-gate		 * Don't display internal characters.
2827c478bdstevel@tonic-gate		 */
2837c478bdstevel@tonic-gate		if (nptr->_f)
2847c478bdstevel@tonic-gate			(void) __m_cc_write(nptr);
2857c478bdstevel@tonic-gate
2867c478bdstevel@tonic-gate		/*
2877c478bdstevel@tonic-gate		 * Update copy of screen image.
2887c478bdstevel@tonic-gate		 */
2897c478bdstevel@tonic-gate		*optr = *nptr;
2907c478bdstevel@tonic-gate		curscr->_curx = region.col + i + 1;
2917c478bdstevel@tonic-gate	}
2927c478bdstevel@tonic-gate}
2937c478bdstevel@tonic-gate
2947c478bdstevel@tonic-gate/*
2957c478bdstevel@tonic-gate * Delete some characters from the terminal for this region
2967c478bdstevel@tonic-gate */
2977c478bdstevel@tonic-gatestatic void
2987c478bdstevel@tonic-gate_deleteRegion(int row, LineRegion region)
2997c478bdstevel@tonic-gate{
3007c478bdstevel@tonic-gate	int	i;
3017c478bdstevel@tonic-gate	cchar_t	*optr = &curscr->_line[row][region.col];
3027c478bdstevel@tonic-gate
3037c478bdstevel@tonic-gate	if ((region.size <= 1) || !parm_dch) {
3047c478bdstevel@tonic-gate		for (i = 0; i < region.size; i++)
3057c478bdstevel@tonic-gate			(void) TPUTS(delete_character, 1, __m_outc);
3067c478bdstevel@tonic-gate	} else {
3077c478bdstevel@tonic-gate		(void) TPUTS(tparm(parm_dch, (long)region.size,
3087c478bdstevel@tonic-gate			0, 0, 0, 0, 0, 0, 0, 0), region.size, __m_outc);
3097c478bdstevel@tonic-gate	}
3107c478bdstevel@tonic-gate	for (i = region.col; i < COLS - region.size; i++) {
3117c478bdstevel@tonic-gate		/*
3127c478bdstevel@tonic-gate		 * Delete the chars in the image of the real screen
3137c478bdstevel@tonic-gate		 */
3147c478bdstevel@tonic-gate		*optr = *(optr + region.size);
3157c478bdstevel@tonic-gate		optr++;
3167c478bdstevel@tonic-gate	}
3177c478bdstevel@tonic-gate}
3187c478bdstevel@tonic-gate
3197c478bdstevel@tonic-gate/*
3207c478bdstevel@tonic-gate * Use clr_eol control if possible
3217c478bdstevel@tonic-gate */
3227c478bdstevel@tonic-gatestatic void
3237c478bdstevel@tonic-gate_clearToEOL(int row, int tail)
3247c478bdstevel@tonic-gate{
3257c478bdstevel@tonic-gate	if (tail < COLS) {
3267c478bdstevel@tonic-gate		GOTO(row, tail);
3277c478bdstevel@tonic-gate		/*
3287c478bdstevel@tonic-gate		 * Restore default color pair before area clear.
3297c478bdstevel@tonic-gate		 */
3307c478bdstevel@tonic-gate		if (back_color_erase)
3317c478bdstevel@tonic-gate			(void) vid_puts(WA_NORMAL, 0, NULL, __m_outc);
3327c478bdstevel@tonic-gate
3337c478bdstevel@tonic-gate		(void) TPUTS(clr_eol, 1, __m_outc);
3347c478bdstevel@tonic-gate		(void) __m_cc_erase(curscr, row, tail, row, COLS - 1);
3357c478bdstevel@tonic-gate	}
3367c478bdstevel@tonic-gate}
3377c478bdstevel@tonic-gate
3387c478bdstevel@tonic-gate/*
3397c478bdstevel@tonic-gate * Delete leading common region
3407c478bdstevel@tonic-gate */
3417c478bdstevel@tonic-gatestatic void
3427c478bdstevel@tonic-gate_normalizeRegions1(void)
3437c478bdstevel@tonic-gate{
3447c478bdstevel@tonic-gate	int	iRegion;
3457c478bdstevel@tonic-gate
3467c478bdstevel@tonic-gate	/*
3477c478bdstevel@tonic-gate	 * Delete leading common region
3487c478bdstevel@tonic-gate	 */
3497c478bdstevel@tonic-gate	if (regions[0].type == REGION_COMMON) {
3507c478bdstevel@tonic-gate		nRegions--;
3517c478bdstevel@tonic-gate		for (iRegion = 0; iRegion < nRegions; iRegion++) {
3527c478bdstevel@tonic-gate			regions[iRegion] = regions[iRegion + 1];
3537c478bdstevel@tonic-gate		}
3547c478bdstevel@tonic-gate	}
3557c478bdstevel@tonic-gate}
3567c478bdstevel@tonic-gate
3577c478bdstevel@tonic-gate/*
3587c478bdstevel@tonic-gate * Give each region a size, then delete all trailing common regions
3597c478bdstevel@tonic-gate */
3607c478bdstevel@tonic-gatestatic void
3617c478bdstevel@tonic-gate_normalizeRegions2(void)
3627c478bdstevel@tonic-gate{
3637c478bdstevel@tonic-gate	int	iRegion;
3647c478bdstevel@tonic-gate
3657c478bdstevel@tonic-gate	for (iRegion = 0; iRegion < nRegions - 1; iRegion++) {
3667c478bdstevel@tonic-gate		regions[iRegion].size = regions[iRegion + 1].col -
3677c478bdstevel@tonic-gate			regions[iRegion].col;
3687c478bdstevel@tonic-gate	}
3697c478bdstevel@tonic-gate	regions[nRegions - 1].size = COLS - regions[nRegions - 1].col;
3707c478bdstevel@tonic-gate
3717c478bdstevel@tonic-gate	/*
3727c478bdstevel@tonic-gate	 * Delete trailing common regions
3737c478bdstevel@tonic-gate	 */
3747c478bdstevel@tonic-gate	while (regions[nRegions - 1].type == REGION_COMMON)
3757c478bdstevel@tonic-gate		nRegions--;
3767c478bdstevel@tonic-gate}
3777c478bdstevel@tonic-gate
3787c478bdstevel@tonic-gate/*
3797c478bdstevel@tonic-gate * Tiny common regions are merged into adjacent difference regions
3807c478bdstevel@tonic-gate */
3817c478bdstevel@tonic-gatestatic void
3827c478bdstevel@tonic-gate_mergeTinyRegions(void)
3837c478bdstevel@tonic-gate{
3847c478bdstevel@tonic-gate	int	from;
3857c478bdstevel@tonic-gate	int	to;
3867c478bdstevel@tonic-gate	for (from = 1, to = 1; from < nRegions; ) {
3877c478bdstevel@tonic-gate		if ((regions[from].type == REGION_COMMON) &&
3887c478bdstevel@tonic-gate			(regions[from].size < JUMP_SIZE)) {
3897c478bdstevel@tonic-gate			/*
3907c478bdstevel@tonic-gate			 * Merge out tiny common regions
3917c478bdstevel@tonic-gate			 */
3927c478bdstevel@tonic-gate			regions[to - 1].size += regions[from].size;
3937c478bdstevel@tonic-gate			/*
3947c478bdstevel@tonic-gate			 * Now join adjacent non-common regions
3957c478bdstevel@tonic-gate			 */
3967c478bdstevel@tonic-gate			if (++from < nRegions)
3977c478bdstevel@tonic-gate				regions[to - 1].size += regions[from++].size;
3987c478bdstevel@tonic-gate		} else {
3997c478bdstevel@tonic-gate			regions[to++] = regions[from++];
4007c478bdstevel@tonic-gate		}
4017c478bdstevel@tonic-gate	}
4027c478bdstevel@tonic-gate	nRegions = to;
4037c478bdstevel@tonic-gate}
4047c478bdstevel@tonic-gate
4057c478bdstevel@tonic-gate/*
4067c478bdstevel@tonic-gate * Create the initial list of regions for this row
4077c478bdstevel@tonic-gate */
4087c478bdstevel@tonic-gatestatic int
4097c478bdstevel@tonic-gate_findRegions(int row)
4107c478bdstevel@tonic-gate{
4117c478bdstevel@tonic-gate	int	cmp;
4127c478bdstevel@tonic-gate	int	old_cmp;
4137c478bdstevel@tonic-gate	int	col;
4147c478bdstevel@tonic-gate	int	bestDeleteCount;
4157c478bdstevel@tonic-gate	cchar_t	*nptr = &newscr->_line[row][0];
4167c478bdstevel@tonic-gate	cchar_t	*optr = &curscr->_line[row][0];
4177c478bdstevel@tonic-gate
4187c478bdstevel@tonic-gate	col = 0;
4197c478bdstevel@tonic-gate	nRegions = 0;
4207c478bdstevel@tonic-gate	bestDeleteCount = 0;
4217c478bdstevel@tonic-gate	if ((__m_screen->_flags & S_INS_DEL_CHAR) &&
4227c478bdstevel@tonic-gate		(parm_dch || delete_character)) {
4237c478bdstevel@tonic-gate		int	bestFit = 0;
4247c478bdstevel@tonic-gate		int	deletePoint;
4257c478bdstevel@tonic-gate		int	deleteCount;
4267c478bdstevel@tonic-gate		int	matches;
4277c478bdstevel@tonic-gate
4287c478bdstevel@tonic-gate		/*
4297c478bdstevel@tonic-gate		 * Skip to first difference
4307c478bdstevel@tonic-gate		 */
4317c478bdstevel@tonic-gate		for (col = 0; col < COLS; col++) {
4327c478bdstevel@tonic-gate			if (!__m_cc_compare(&optr[col], &nptr[col], 1))
4337c478bdstevel@tonic-gate				break;
4347c478bdstevel@tonic-gate		}
4357c478bdstevel@tonic-gate		deletePoint = col;
4367c478bdstevel@tonic-gate		for (deleteCount = 1; deleteCount < DELETE_SEARCH_LIMIT;
4377c478bdstevel@tonic-gate			deleteCount++) {
4387c478bdstevel@tonic-gate			matches = 0;
4397c478bdstevel@tonic-gate			for (col = deletePoint; col < COLS - deleteCount;
4407c478bdstevel@tonic-gate				col++) {
4417c478bdstevel@tonic-gate				if (__m_cc_compare(&optr[col + deleteCount],
4427c478bdstevel@tonic-gate					&nptr[col], 1))
4437c478bdstevel@tonic-gate					matches++;
4447c478bdstevel@tonic-gate				else
4457c478bdstevel@tonic-gate					break;
4467c478bdstevel@tonic-gate			}
4477c478bdstevel@tonic-gate			if (matches > bestFit) {
4487c478bdstevel@tonic-gate				bestFit = matches;
4497c478bdstevel@tonic-gate				bestDeleteCount = deleteCount;
4507c478bdstevel@tonic-gate			}
4517c478bdstevel@tonic-gate		}
4527c478bdstevel@tonic-gate		if (bestFit > DELETE_THRESHOLD) {
4537c478bdstevel@tonic-gate			regions[nRegions].type = REGION_DELETE;
4547c478bdstevel@tonic-gate			regions[nRegions].col = deletePoint;
4557c478bdstevel@tonic-gate			regions[nRegions].size = bestDeleteCount;
4567c478bdstevel@tonic-gate			nRegions++;
4577c478bdstevel@tonic-gate			col = deletePoint + bestDeleteCount;
4587c478bdstevel@tonic-gate		} else {
4597c478bdstevel@tonic-gate			col = 0;
4607c478bdstevel@tonic-gate			nRegions = 0;
4617c478bdstevel@tonic-gate			/* Forget trying to use character delete */
4627c478bdstevel@tonic-gate			bestDeleteCount = 0;
4637c478bdstevel@tonic-gate		}
4647c478bdstevel@tonic-gate	}
4657c478bdstevel@tonic-gate	for (old_cmp = -1; col + bestDeleteCount < COLS; col++) {
4667c478bdstevel@tonic-gate		cmp = __m_cc_compare(&optr[col + bestDeleteCount],
4677c478bdstevel@tonic-gate			&nptr[col], 1);
4687c478bdstevel@tonic-gate		if (cmp != old_cmp) {
4697c478bdstevel@tonic-gate			regions[nRegions].type = cmp ? REGION_COMMON :
4707c478bdstevel@tonic-gate				REGION_DIFFERENT;
4717c478bdstevel@tonic-gate			regions[nRegions].col = col;
4727c478bdstevel@tonic-gate			regions[nRegions].size = 0;	/* Determine later */
4737c478bdstevel@tonic-gate			nRegions++;
4747c478bdstevel@tonic-gate			old_cmp = cmp;
4757c478bdstevel@tonic-gate		}
4767c478bdstevel@tonic-gate	}
4777c478bdstevel@tonic-gate	if (bestDeleteCount) {
4787c478bdstevel@tonic-gate		/*
4797c478bdstevel@tonic-gate		 * Force update of end-of-line if delete is to be used
4807c478bdstevel@tonic-gate		 */
4817c478bdstevel@tonic-gate		regions[nRegions].type = REGION_DIFFERENT;
4827c478bdstevel@tonic-gate		regions[nRegions].col = col;
4837c478bdstevel@tonic-gate		regions[nRegions].size = 0;	/* Determine later */
4847c478bdstevel@tonic-gate		nRegions++;
4857c478bdstevel@tonic-gate	}
4867c478bdstevel@tonic-gate	_normalizeRegions1();
4877c478bdstevel@tonic-gate	if (nRegions == 0)
4887c478bdstevel@tonic-gate		return (0);		/* No difference regions */
4897c478bdstevel@tonic-gate
4907c478bdstevel@tonic-gate	_normalizeRegions2();
4917c478bdstevel@tonic-gate	return (1);
4927c478bdstevel@tonic-gate}
4937c478bdstevel@tonic-gate
4947c478bdstevel@tonic-gate/*
4957c478bdstevel@tonic-gate * Determine if Clr-EOL optimization can be used, and
4967c478bdstevel@tonic-gate * adjust regions accordingly
4977c478bdstevel@tonic-gate */
4987c478bdstevel@tonic-gatestatic int
4997c478bdstevel@tonic-gate_ceolAdjustRegions(int row)
5007c478bdstevel@tonic-gate{
5017c478bdstevel@tonic-gate	int	iRegion;
5027c478bdstevel@tonic-gate	int	blankEolStart = _find_blank_tail(row);
5037c478bdstevel@tonic-gate
5047c478bdstevel@tonic-gate	for (iRegion = 0; iRegion < nRegions; iRegion++) {
5057c478bdstevel@tonic-gate		switch (regions[iRegion].type) {
5067c478bdstevel@tonic-gate		case REGION_DIFFERENT:
5077c478bdstevel@tonic-gate			if (regions[iRegion].col >= blankEolStart) {
5087c478bdstevel@tonic-gate				/*
5097c478bdstevel@tonic-gate				 * Delete this and all following regions
5107c478bdstevel@tonic-gate				 */
5117c478bdstevel@tonic-gate				nRegions = iRegion;
5127c478bdstevel@tonic-gate				return (blankEolStart);
5137c478bdstevel@tonic-gate			}
5147c478bdstevel@tonic-gate			if (regions[iRegion].col + regions[iRegion].size >
5157c478bdstevel@tonic-gate				blankEolStart) {
5167c478bdstevel@tonic-gate				/*
5177c478bdstevel@tonic-gate				 * Truncate this region to end
5187c478bdstevel@tonic-gate				 * where blank EOL starts
5197c478bdstevel@tonic-gate				 */
5207c478bdstevel@tonic-gate				regions[iRegion].size = blankEolStart -
5217c478bdstevel@tonic-gate					regions[iRegion].col;
5227c478bdstevel@tonic-gate				/*
5237c478bdstevel@tonic-gate				 * Delete all following regions
5247c478bdstevel@tonic-gate				 */
5257c478bdstevel@tonic-gate				nRegions = iRegion + 1;
5267c478bdstevel@tonic-gate				return (blankEolStart);
5277c478bdstevel@tonic-gate			}
5287c478bdstevel@tonic-gate			break;
5297c478bdstevel@tonic-gate		case REGION_COMMON:
5307c478bdstevel@tonic-gate			break;
5317c478bdstevel@tonic-gate		case REGION_DELETE:		/* Scrap the whole thing */
5327c478bdstevel@tonic-gate			return (COLS);
5337c478bdstevel@tonic-gate		}
5347c478bdstevel@tonic-gate	}
5357c478bdstevel@tonic-gate	return (COLS);	/* Couldn't use Clear EOL optimization */
5367c478bdstevel@tonic-gate}
5377c478bdstevel@tonic-gate
5387c478bdstevel@tonic-gate/*
5397c478bdstevel@tonic-gate * Generate output, based on region list
5407c478bdstevel@tonic-gate */
5417c478bdstevel@tonic-gatestatic void
5427c478bdstevel@tonic-gate_updateRegions(int row)
5437c478bdstevel@tonic-gate{
5447c478bdstevel@tonic-gate	int	ceolStart;
5457c478bdstevel@tonic-gate	int	iRegion;
5467c478bdstevel@tonic-gate
5477c478bdstevel@tonic-gate	ceolStart = _ceolAdjustRegions(row);
5487c478bdstevel@tonic-gate
5497c478bdstevel@tonic-gate	/*
5507c478bdstevel@tonic-gate	 * regions are guaranteed to start with a non-common region.
5517c478bdstevel@tonic-gate	 * tiny common regions have also been merged into
5527c478bdstevel@tonic-gate	 * bracketting common-regions.
5537c478bdstevel@tonic-gate	 */
5547c478bdstevel@tonic-gate	if (nRegions) {
5557c478bdstevel@tonic-gate		for (iRegion = 0; iRegion < nRegions; iRegion++) {
5567c478bdstevel@tonic-gate			switch (regions[iRegion].type) {
5577c478bdstevel@tonic-gate			case REGION_COMMON:
5587c478bdstevel@tonic-gate				break;
5597c478bdstevel@tonic-gate			case REGION_DELETE:
5607c478bdstevel@tonic-gate				/*
5617c478bdstevel@tonic-gate				 * Start of non-common region
5627c478bdstevel@tonic-gate				 */
5637c478bdstevel@tonic-gate				GOTO(row, regions[iRegion].col);
5647c478bdstevel@tonic-gate				_deleteRegion(row, regions[iRegion]);
5657c478bdstevel@tonic-gate				break;
5667c478bdstevel@tonic-gate			case REGION_DIFFERENT:
5677c478bdstevel@tonic-gate				/*
5687c478bdstevel@tonic-gate				 * Star of non-common region
5697c478bdstevel@tonic-gate				 */
5707c478bdstevel@tonic-gate				GOTO(row, regions[iRegion].col);
5717c478bdstevel@tonic-gate				_writeRegion(row, regions[iRegion]);
5727c478bdstevel@tonic-gate				break;
5737c478bdstevel@tonic-gate			}
5747c478bdstevel@tonic-gate		}
5757c478bdstevel@tonic-gate	}
5767c478bdstevel@tonic-gate	if (ceolStart != COLS) {
5777c478bdstevel@tonic-gate		_clearToEOL(row, ceolStart);
5787c478bdstevel@tonic-gate	}
5797c478bdstevel@tonic-gate}
5807c478bdstevel@tonic-gate
5817c478bdstevel@tonic-gate/*
5827c478bdstevel@tonic-gate * The new text_replace algorithm, which uses regions
5837c478bdstevel@tonic-gate */
5847c478bdstevel@tonic-gatestatic void
5857c478bdstevel@tonic-gatetext_replace(int row)
5867c478bdstevel@tonic-gate{
5877c478bdstevel@tonic-gate	if (!_findRegions(row))
5887c478bdstevel@tonic-gate		return;
5897c478bdstevel@tonic-gate	_mergeTinyRegions();
5907c478bdstevel@tonic-gate	_updateRegions(row);
5917c478bdstevel@tonic-gate
5927c478bdstevel@tonic-gate	/*
5937c478bdstevel@tonic-gate	 * Line wrapping checks.
5947c478bdstevel@tonic-gate	 */
5957c478bdstevel@tonic-gate	if (COLS <= curscr->_curx) {
5967c478bdstevel@tonic-gate		--curscr->_curx;
5977c478bdstevel@tonic-gate		if (auto_right_margin && (row < LINES - 1)) {
5987c478bdstevel@tonic-gate			if (eat_newline_glitch) {
5997c478bdstevel@tonic-gate				(void) __m_outc('\r');
6007c478bdstevel@tonic-gate				(void) __m_outc('\n');
6017c478bdstevel@tonic-gate			}
6027c478bdstevel@tonic-gate			++curscr->_cury;
6037c478bdstevel@tonic-gate			curscr->_curx = 0;
6047c478bdstevel@tonic-gate		}
6057c478bdstevel@tonic-gate	}
6067c478bdstevel@tonic-gate}
6077c478bdstevel@tonic-gate
6087c478bdstevel@tonic-gate/*
6097c478bdstevel@tonic-gate * Replace a block of lines.
6107c478bdstevel@tonic-gate * Only ever used for complex().
6117c478bdstevel@tonic-gate */
6127c478bdstevel@tonic-gatestatic void
6137c478bdstevel@tonic-gatelines_replace(int from, int to_1)
6147c478bdstevel@tonic-gate{
6157c478bdstevel@tonic-gate	for (; from < to_1; ++from)
6167c478bdstevel@tonic-gate		text_replace(from);
6177c478bdstevel@tonic-gate}
6187c478bdstevel@tonic-gate
6197c478bdstevel@tonic-gate/*
6207c478bdstevel@tonic-gate * Delete a block of lines.
6217c478bdstevel@tonic-gate * Only ever used for complex().
6227c478bdstevel@tonic-gate */
6237c478bdstevel@tonic-gatestatic void
6247c478bdstevel@tonic-gatelines_delete(int from, int to_1)
6257c478bdstevel@tonic-gate{
6267c478bdstevel@tonic-gate	int count = to_1 - from;
6277c478bdstevel@tonic-gate
6287c478bdstevel@tonic-gate	if (LINES <= to_1) {
6297c478bdstevel@tonic-gate		erase_bottom(from, LINES);
6307c478bdstevel@tonic-gate		clear_bottom(from);
6317c478bdstevel@tonic-gate	} else {
6327c478bdstevel@tonic-gate		GOTO(from, 0);
6337c478bdstevel@tonic-gate		(void) winsdelln(curscr, -count);
6347c478bdstevel@tonic-gate
6357c478bdstevel@tonic-gate		if (parm_delete_line != NULL) {
6367c478bdstevel@tonic-gate			/*
6377c478bdstevel@tonic-gate			 * Assume that the sequence to delete more than one
6387c478bdstevel@tonic-gate			 * line is faster than repeated single delete_lines.
6397c478bdstevel@tonic-gate			 */
6407c478bdstevel@tonic-gate			(void) TPUTS(tparm(parm_delete_line, (long)count,
6417c478bdstevel@tonic-gate				0, 0, 0, 0, 0, 0, 0, 0), count, __m_outc);
6427c478bdstevel@tonic-gate		} else if (delete_line != NULL) {
6437c478bdstevel@tonic-gate			while (from++ < to_1)
6447c478bdstevel@tonic-gate				(void) TPUTS(delete_line, 1, __m_outc);
6457c478bdstevel@tonic-gate		} else  {
6467c478bdstevel@tonic-gate			/* Error -- what to do. */
6477c478bdstevel@tonic-gate			return;
6487c478bdstevel@tonic-gate		}
6497c478bdstevel@tonic-gate	}
6507c478bdstevel@tonic-gate}
6517c478bdstevel@tonic-gate
6527c478bdstevel@tonic-gate/*
6537c478bdstevel@tonic-gate * Insert a block of lines.
6547c478bdstevel@tonic-gate * Only ever used for complex().
6557c478bdstevel@tonic-gate *
6567c478bdstevel@tonic-gate * We must assume that insert_line and parm_insert_line reset the
6577c478bdstevel@tonic-gate * cursor column to zero.  Therefore it is text_replace() responsiblity
6587c478bdstevel@tonic-gate * to move the cursor to the correct column to begin the update.
6597c478bdstevel@tonic-gate */
6607c478bdstevel@tonic-gatestatic void
6617c478bdstevel@tonic-gatelines_insert(int from, int to_1)
6627c478bdstevel@tonic-gate{
6637c478bdstevel@tonic-gate	int	row;
6647c478bdstevel@tonic-gate	int	count = to_1 - from;
6657c478bdstevel@tonic-gate
6667c478bdstevel@tonic-gate	/*
6677c478bdstevel@tonic-gate	 * Position the cursor and insert a block of lines into the screen
6687c478bdstevel@tonic-gate	 * image now, insert lines into the physical screen, then draw the
6697c478bdstevel@tonic-gate	 * new screen lines.
6707c478bdstevel@tonic-gate	 */
6717c478bdstevel@tonic-gate	GOTO(from, 0);
6727c478bdstevel@tonic-gate	(void) winsdelln(curscr, count);
6737c478bdstevel@tonic-gate
6747c478bdstevel@tonic-gate	if (parm_insert_line != NULL) {
6757c478bdstevel@tonic-gate		/*
6767c478bdstevel@tonic-gate		 * Assume that the sequence to insert more than one line is
6777c478bdstevel@tonic-gate		 * faster than repeated single insert_lines.
6787c478bdstevel@tonic-gate		 */
6797c478bdstevel@tonic-gate		(void) TPUTS(tparm(parm_insert_line, (long)count,
6807c478bdstevel@tonic-gate			0, 0, 0, 0, 0, 0, 0, 0), count, __m_outc);
6817c478bdstevel@tonic-gate	} else if (insert_line != NULL) {
6827c478bdstevel@tonic-gate		/*
6837c478bdstevel@tonic-gate		 * For the single line insert we use to iterate moving
6847c478bdstevel@tonic-gate		 * the cursor, inserting, and then drawing a line.  That
6857c478bdstevel@tonic-gate		 * would appear to be slow but visually appealing.  However,
6867c478bdstevel@tonic-gate		 * people on slow terminals want speed and those on fast
6877c478bdstevel@tonic-gate		 * terminal won't see it.
6887c478bdstevel@tonic-gate		 */
6897c478bdstevel@tonic-gate		for (row = from; row < to_1; ++row)
6907c478bdstevel@tonic-gate			(void) TPUTS(insert_line, 1, __m_outc);
6917c478bdstevel@tonic-gate	} else {
6927c478bdstevel@tonic-gate		/* Error -- what to do. */
6937c478bdstevel@tonic-gate		return;
6947c478bdstevel@tonic-gate	}
6957c478bdstevel@tonic-gate
6967c478bdstevel@tonic-gate	for (row = from; row < to_1; ++row)
6977c478bdstevel@tonic-gate		text_replace(row);
6987c478bdstevel@tonic-gate}
6997c478bdstevel@tonic-gate
7007c478bdstevel@tonic-gatestatic int
7017c478bdstevel@tonic-gatescroll_up(int n)
7027c478bdstevel@tonic-gate{
7037c478bdstevel@tonic-gate	int	count = n;
7047c478bdstevel@tonic-gate	int	start, finish, to;
7057c478bdstevel@tonic-gate
7067c478bdstevel@tonic-gate	if (scroll_forward != NULL) {
7077c478bdstevel@tonic-gate		GOTO(LINES-1, 0);
7087c478bdstevel@tonic-gate		while (0 < n--)
7097c478bdstevel@tonic-gate			(void) TPUTS(scroll_forward, 1, __m_outc);
7107c478bdstevel@tonic-gate	} else if (parm_delete_line != NULL && 1 < n) {
7117c478bdstevel@tonic-gate		GOTO(0, 0);
7127c478bdstevel@tonic-gate		(void) TPUTS(tparm(parm_delete_line, (long)n,
7137c478bdstevel@tonic-gate			0, 0, 0, 0, 0, 0, 0, 0), n, __m_outc);
7147c478bdstevel@tonic-gate	} else if (delete_line != NULL) {
7157c478bdstevel@tonic-gate		GOTO(0, 0);
7167c478bdstevel@tonic-gate		while (0 < n--)
7177c478bdstevel@tonic-gate			(void) TPUTS(delete_line, 1, __m_outc);
7187c478bdstevel@tonic-gate	} else {
7197c478bdstevel@tonic-gate		return (0);
7207c478bdstevel@tonic-gate	}
7217c478bdstevel@tonic-gate
7227c478bdstevel@tonic-gate	/* Scroll recorded image. */
7237c478bdstevel@tonic-gate	start = 0;
7247c478bdstevel@tonic-gate	finish = count-1;
7257c478bdstevel@tonic-gate	to = lines;
7267c478bdstevel@tonic-gate
7277c478bdstevel@tonic-gate	(void) __m_cc_erase(curscr, start, 0, finish, curscr->_maxx-1);
7287c478bdstevel@tonic-gate	(void) __m_ptr_move((void **) curscr->_line,
7297c478bdstevel@tonic-gate		curscr->_maxy, start, finish, to);
7307c478bdstevel@tonic-gate
7317c478bdstevel@tonic-gate	simple();
7327c478bdstevel@tonic-gate
7337c478bdstevel@tonic-gate	return (1);
7347c478bdstevel@tonic-gate}
7357c478bdstevel@tonic-gate
7367c478bdstevel@tonic-gate#if 0
7377c478bdstevel@tonic-gatestatic int
7387c478bdstevel@tonic-gatescroll_dn(int n)
7397c478bdstevel@tonic-gate{
7407c478bdstevel@tonic-gate	int	count = n;
7417c478bdstevel@tonic-gate	int	start, finish, to;
7427c478bdstevel@tonic-gate
7437c478bdstevel@tonic-gate	if (LINES < n)
7447c478bdstevel@tonic-gate		return (0);
7457c478bdstevel@tonic-gate
7467c478bdstevel@tonic-gate	if (scroll_reverse != NULL) {
7477c478bdstevel@tonic-gate		GOTO(0, 0);
7487c478bdstevel@tonic-gate		while (0 < n--)
7497c478bdstevel@tonic-gate			(void) TPUTS(scroll_reverse, 1, __m_outc);
7507c478bdstevel@tonic-gate	} else if (parm_insert_line != NULL && 1 < n) {
7517c478bdstevel@tonic-gate		GOTO(0, 0);
7527c478bdstevel@tonic-gate		(void) TPUTS(tparm(parm_insert_line, (long)n,
7537c478bdstevel@tonic-gate			0, 0, 0, 0, 0, 0, 0, 0), n, __m_outc);
7547c478bdstevel@tonic-gate	} else if (insert_line != NULL) {
7557c478bdstevel@tonic-gate		GOTO(0, 0);
7567c478bdstevel@tonic-gate		while (0 < n--)
7577c478bdstevel@tonic-gate			(void) TPUTS(insert_line, 1, __m_outc);
7587c478bdstevel@tonic-gate	} else {
7597c478bdstevel@tonic-gate		return (0);
7607c478bdstevel@tonic-gate	}
7617c478bdstevel@tonic-gate
7627c478bdstevel@tonic-gate	/* Scroll recorded image. */
7637c478bdstevel@tonic-gate	start = lines - count;
7647c478bdstevel@tonic-gate	finish = lines - 1;
7657c478bdstevel@tonic-gate	to = 0;
7667c478bdstevel@tonic-gate
7677c478bdstevel@tonic-gate	(void) __m_cc_erase(curscr, start, 0, finish, curscr->_maxx-1);
7687c478bdstevel@tonic-gate	(void) __m_ptr_move((void **) curscr->_line,
7697c478bdstevel@tonic-gate		curscr->_maxy, start, finish, to);
7707c478bdstevel@tonic-gate
7717c478bdstevel@tonic-gate	simple();
7727c478bdstevel@tonic-gate
7737c478bdstevel@tonic-gate	return (1);
7747c478bdstevel@tonic-gate}
7757c478bdstevel@tonic-gate#endif
7767c478bdstevel@tonic-gate
7777c478bdstevel@tonic-gate/*
7787c478bdstevel@tonic-gate * Dynamic programming algorithm for the string edit problem.
7797c478bdstevel@tonic-gate *
7807c478bdstevel@tonic-gate * This is a modified Gosling cost algorithm that takes into account
7817c478bdstevel@tonic-gate * null/move operations.
7827c478bdstevel@tonic-gate *
7837c478bdstevel@tonic-gate * Costs for move, delete, replace, and insert are 0, 1, 2, and 3
7847c478bdstevel@tonic-gate * repectively.
7857c478bdstevel@tonic-gate */
7867c478bdstevel@tonic-gate#define	MOVE_COST	0
7877c478bdstevel@tonic-gate#define	REPLACE_COST	10
7887c478bdstevel@tonic-gate#define	INSERT_COST	12
7897c478bdstevel@tonic-gate#define	DELETE_COST	1
7907c478bdstevel@tonic-gate
7917c478bdstevel@tonic-gatestatic int
7927c478bdstevel@tonic-gatecost(int fr, int lr)
7937c478bdstevel@tonic-gate{
7947c478bdstevel@tonic-gate	lcost	*lcp;
7957c478bdstevel@tonic-gate	int	or, nr, cc;
7967c478bdstevel@tonic-gate#if defined(_LP64)
7977c478bdstevel@tonic-gate	unsigned int	*ohash = __m_screen->_hash;
7987c478bdstevel@tonic-gate#else
7997c478bdstevel@tonic-gate	unsigned long	*ohash = __m_screen->_hash;
8007c478bdstevel@tonic-gate#endif
8017c478bdstevel@tonic-gate
8027c478bdstevel@tonic-gate	/*
8037c478bdstevel@tonic-gate	 * Prepare initial row and column of cost matrix.
8047c478bdstevel@tonic-gate	 *
8057c478bdstevel@tonic-gate	 *	0 3 6 9 ...
8067c478bdstevel@tonic-gate	 *	1
8077c478bdstevel@tonic-gate	 *	2
8087c478bdstevel@tonic-gate	 *	3
8097c478bdstevel@tonic-gate	 *	:
8107c478bdstevel@tonic-gate	 */
8117c478bdstevel@tonic-gate	LC(fr, fr).cost = MOVE_COST;
8127c478bdstevel@tonic-gate	for (cc = 1, ++lr, nr = fr+1; nr <= lr; ++nr, ++cc) {
8137c478bdstevel@tonic-gate		/* Top row is 3, 6, 9, ... */
8147c478bdstevel@tonic-gate		LC(fr, nr).cost = cc * INSERT_COST;
8157c478bdstevel@tonic-gate		LC(fr, nr).op = 'i';
8167c478bdstevel@tonic-gate
8177c478bdstevel@tonic-gate		/* Left column is 1, 2, 3, ... */
8187c478bdstevel@tonic-gate		LC(nr, fr).cost = cc * DELETE_COST;
8197c478bdstevel@tonic-gate		LC(nr, fr).op = 'd';
8207c478bdstevel@tonic-gate	}
8217c478bdstevel@tonic-gate
8227c478bdstevel@tonic-gate	for (--lr, or = fr; or <= lr; ++or) {
8237c478bdstevel@tonic-gate		for (nr = fr; nr <= lr; ++nr) {
8247c478bdstevel@tonic-gate			lcp = &LC(or + 1, nr + 1);
8257c478bdstevel@tonic-gate
8267c478bdstevel@tonic-gate			/* Assume move op. */
8277c478bdstevel@tonic-gate			lcp->cost = LC(or, nr).cost;
8287c478bdstevel@tonic-gate			lcp->op = 'm';
8297c478bdstevel@tonic-gate
8307c478bdstevel@tonic-gate			if (ohash[or] != nhash[nr]) {
8317c478bdstevel@tonic-gate				/* Lines are different, assume replace op. */
8327c478bdstevel@tonic-gate				lcp->cost += REPLACE_COST;
8337c478bdstevel@tonic-gate				lcp->op = 'r';
8347c478bdstevel@tonic-gate			}
8357c478bdstevel@tonic-gate
8367c478bdstevel@tonic-gate			/* Compare insert op. */
8377c478bdstevel@tonic-gate			if ((cc = LC(or + 1, nr).cost + INSERT_COST) <
8387c478bdstevel@tonic-gate				lcp->cost) {
8397c478bdstevel@tonic-gate				lcp->cost = cc;
8407c478bdstevel@tonic-gate				lcp->op = 'i';
8417c478bdstevel@tonic-gate			}
8427c478bdstevel@tonic-gate
8437c478bdstevel@tonic-gate			/* Compare delete op. */
8447c478bdstevel@tonic-gate			if ((cc = LC(or, nr + 1).cost + DELETE_COST) <
8457c478bdstevel@tonic-gate				lcp->cost) {
8467c478bdstevel@tonic-gate				lcp->cost = cc;
8477c478bdstevel@tonic-gate				lcp->op = 'd';
8487c478bdstevel@tonic-gate			}
8497c478bdstevel@tonic-gate		}
8507c478bdstevel@tonic-gate	}
8517c478bdstevel@tonic-gate
8527c478bdstevel@tonic-gate	return (LC(lr + 1, lr + 1).cost);
8537c478bdstevel@tonic-gate}
8547c478bdstevel@tonic-gate
8557c478bdstevel@tonic-gate/*
8567c478bdstevel@tonic-gate * Build edit script.
8577c478bdstevel@tonic-gate *
8587c478bdstevel@tonic-gate * Normally this would be a recursve routine doing the deletes, inserts,
8597c478bdstevel@tonic-gate * and replaces on individual lines. Instead we build the script so that
8607c478bdstevel@tonic-gate * we can later do the operations on a block basis.  For terminals with
8617c478bdstevel@tonic-gate * parm_delete or parm_insert strings this will be better in terms of the
8627c478bdstevel@tonic-gate * number of characters sent to delete and insert a block of lines.
8637c478bdstevel@tonic-gate *
8647c478bdstevel@tonic-gate * Also we can optimize the script so that tail inserts become replaces.
8657c478bdstevel@tonic-gate * This saves unnecessary inserts operations when the tail can just be
8667c478bdstevel@tonic-gate * overwritten.
8677c478bdstevel@tonic-gate */
8687c478bdstevel@tonic-gatestatic void
8697c478bdstevel@tonic-gatescript(int fr, int lr)
8707c478bdstevel@tonic-gate{
8717c478bdstevel@tonic-gate	int	i, j;
8727c478bdstevel@tonic-gate	cchar_t	*cp;
8737c478bdstevel@tonic-gate
8747c478bdstevel@tonic-gate	i = j = lr + 1;
8757c478bdstevel@tonic-gate
8767c478bdstevel@tonic-gate	(void) memset(del, 0, sizeof (*del) * LINES);
8777c478bdstevel@tonic-gate	(void) memset(ins_rep, 0, sizeof (*ins_rep) * LINES);
8787c478bdstevel@tonic-gate
8797c478bdstevel@tonic-gate	do {
8807c478bdstevel@tonic-gate		/*
8817c478bdstevel@tonic-gate		 * We don't have to bounds check i or j becuase row fr and
8827c478bdstevel@tonic-gate		 * column fr of lc have been preset in order to guarantee the
8837c478bdstevel@tonic-gate		 * correct motion.
8847c478bdstevel@tonic-gate		 */
8857c478bdstevel@tonic-gate		switch (LC(i, j).op) {
8867c478bdstevel@tonic-gate		case 'i':
8877c478bdstevel@tonic-gate			--j;
8887c478bdstevel@tonic-gate			ins_rep[j] = lines_insert;
8897c478bdstevel@tonic-gate			break;
8907c478bdstevel@tonic-gate		case 'd':
8917c478bdstevel@tonic-gate			--i;
8927c478bdstevel@tonic-gate			del[i] = lines_delete;
8937c478bdstevel@tonic-gate			break;
8947c478bdstevel@tonic-gate		case 'm':
8957c478bdstevel@tonic-gate			--i;
8967c478bdstevel@tonic-gate			--j;
8977c478bdstevel@tonic-gate			break;
8987c478bdstevel@tonic-gate		case 'r':
8997c478bdstevel@tonic-gate			--i;
9007c478bdstevel@tonic-gate			--j;
9017c478bdstevel@tonic-gate			ins_rep[j] = lines_replace;
9027c478bdstevel@tonic-gate			break;
9037c478bdstevel@tonic-gate		}
9047c478bdstevel@tonic-gate	} while (fr < i || fr < j);
9057c478bdstevel@tonic-gate
9067c478bdstevel@tonic-gate	/* Optimize Tail Inserts */
9077c478bdstevel@tonic-gate	for (i = LINES-1; 0 <= i && ins_rep[i] == lines_insert; --i) {
9087c478bdstevel@tonic-gate		/* Make each character in the screen line image invalid. */
9097c478bdstevel@tonic-gate		for (cp = curscr->_line[i], j = 0; j < COLS; ++j, ++cp)
9107c478bdstevel@tonic-gate			cp->_n = -1;
9117c478bdstevel@tonic-gate		ins_rep[i] = lines_replace;
9127c478bdstevel@tonic-gate	}
9137c478bdstevel@tonic-gate}
9147c478bdstevel@tonic-gate
9157c478bdstevel@tonic-gate/*
9167c478bdstevel@tonic-gate * Complex update algorithm using insert/delete line operations.
9177c478bdstevel@tonic-gate *
9187c478bdstevel@tonic-gate * References:
9197c478bdstevel@tonic-gate * [MyM86]	E.W. Myers & W. Miller, Row Replacement Algorithms for
9207c478bdstevel@tonic-gate *		Screen Editors, TR 86-19, Dept. Computer Science, U. of Arizona
9217c478bdstevel@tonic-gate * [MyM87]	E.W. Myers & W. Miller, A Simple Row Replacement Method,
9227c478bdstevel@tonic-gate *		TR 86-28, Dept. Computer Science, U. of Arizona
9237c478bdstevel@tonic-gate * [Mil87]	W. Miller, A Software Tools Sampler, Prentice-Hall, 1987
9247c478bdstevel@tonic-gate * [Gos81]	James Gosling, A redisplay algorithm, Proceedings of the
9257c478bdstevel@tonic-gate *		ACM Symposium on Text Manipulation, SIGPLAN Notices,
9267c478bdstevel@tonic-gate *		16(6) June 1981, pg 123-129
9277c478bdstevel@tonic-gate *
9287c478bdstevel@tonic-gate * All the above were reviewed and experimented with.  Due to the nature of
9297c478bdstevel@tonic-gate * Curses' having to handling overlapping WINDOWs, the only suitable
9307c478bdstevel@tonic-gate * algorithum is [Gos81].  The others are better suited to editor type
9317c478bdstevel@tonic-gate * applications that have one window being the entire terminal screen.
9327c478bdstevel@tonic-gate *
9337c478bdstevel@tonic-gate */
9347c478bdstevel@tonic-gatestatic void
9357c478bdstevel@tonic-gatecomplex(void)
9367c478bdstevel@tonic-gate{
9377c478bdstevel@tonic-gate	int	fr = -1;
9387c478bdstevel@tonic-gate	int	i, j, lr;
9397c478bdstevel@tonic-gate	t_action	func;
9407c478bdstevel@tonic-gate
9417c478bdstevel@tonic-gate	/* Find block of lines to change */
9427c478bdstevel@tonic-gate	for (i = 0; i < LINES; ++i) {
9437c478bdstevel@tonic-gate		if (newscr->_first[i] < newscr->_last[i]) {
9447c478bdstevel@tonic-gate			/* Compute new hash. */
9457c478bdstevel@tonic-gate			__m_cc_hash(newscr, nhash, i);
9467c478bdstevel@tonic-gate			if (fr == -1)
9477c478bdstevel@tonic-gate				fr = i;
9487c478bdstevel@tonic-gate			lr = i;
9497c478bdstevel@tonic-gate		} else {
9507c478bdstevel@tonic-gate			/* Line not dirty so hash same as before. */
9517c478bdstevel@tonic-gate			nhash[i] = __m_screen->_hash[i];
9527c478bdstevel@tonic-gate		}
9537c478bdstevel@tonic-gate	}
9547c478bdstevel@tonic-gate
9557c478bdstevel@tonic-gate	if (fr != -1) {
9567c478bdstevel@tonic-gate		/* Gosling */
9577c478bdstevel@tonic-gate		(void) cost(fr, lr);
9587c478bdstevel@tonic-gate		script(fr, lr);
9597c478bdstevel@tonic-gate
9607c478bdstevel@tonic-gate		/* Do deletes first in reverse order. */
9617c478bdstevel@tonic-gate		for (j = lr; fr <= j; --j) {
9627c478bdstevel@tonic-gate			if (del[j] != (t_action) 0) {
9637c478bdstevel@tonic-gate				for (i = j-1; fr <= i; --i)
9647c478bdstevel@tonic-gate					if (del[i] == (t_action) 0)
9657c478bdstevel@tonic-gate						break;
9667c478bdstevel@tonic-gate
9677c478bdstevel@tonic-gate				lines_delete(i+1, j+1);
9687c478bdstevel@tonic-gate				j = i;
9697c478bdstevel@tonic-gate			}
9707c478bdstevel@tonic-gate		}
9717c478bdstevel@tonic-gate
9727c478bdstevel@tonic-gate		/* Do insert/replace in forward order. */
9737c478bdstevel@tonic-gate		for (i = fr; i <= lr; ++i) {
9747c478bdstevel@tonic-gate			if ((func = ins_rep[i]) != (t_action) 0) {
9757c478bdstevel@tonic-gate				/* Find size of block */
9767c478bdstevel@tonic-gate				for (j = i; j <= lr && ins_rep[j] == func; ++j)
9777c478bdstevel@tonic-gate					;
9787c478bdstevel@tonic-gate				(*func)(i, j);
9797c478bdstevel@tonic-gate				i = j - 1;
9807c478bdstevel@tonic-gate			}
9817c478bdstevel@tonic-gate		}
9827c478bdstevel@tonic-gate		/*
9837c478bdstevel@tonic-gate		 * _line[], which contains pointers to screen lines,
9847c478bdstevel@tonic-gate		 * may be shuffled.
9857c478bdstevel@tonic-gate		 */
9867c478bdstevel@tonic-gate		for (i = fr; i <= lr; ++i) {
9877c478bdstevel@tonic-gate			/* Save new hash for next update. */
9887c478bdstevel@tonic-gate			__m_screen->_hash[i] = nhash[i];
9897c478bdstevel@tonic-gate
9907c478bdstevel@tonic-gate			/* Mark line as untouched. */
9917c478bdstevel@tonic-gate			newscr->_first[i] = newscr->_maxx;
9927c478bdstevel@tonic-gate			newscr->_last[i] = -1;
9937c478bdstevel@tonic-gate		}
9947c478bdstevel@tonic-gate	}
9957c478bdstevel@tonic-gate}
9967c478bdstevel@tonic-gate
9977c478bdstevel@tonic-gate/*
9987c478bdstevel@tonic-gate * Simple screen update algorithm
9997c478bdstevel@tonic-gate *
10007c478bdstevel@tonic-gate * We perform a simple incremental update of the terminal screen.
10017c478bdstevel@tonic-gate * Only the segment of a line that was touched is replaced on the
10027c478bdstevel@tonic-gate * line.
10037c478bdstevel@tonic-gate */
10047c478bdstevel@tonic-gatestatic void
10057c478bdstevel@tonic-gatesimple(void)
10067c478bdstevel@tonic-gate{
10077c478bdstevel@tonic-gate	int row;
10087c478bdstevel@tonic-gate
10097c478bdstevel@tonic-gate	for (row = 0; row < newscr->_maxy; ++row) {
10107c478bdstevel@tonic-gate		if (newscr->_first[row] < newscr->_last[row]) {
10117c478bdstevel@tonic-gate			text_replace(row);
10127c478bdstevel@tonic-gate
10137c478bdstevel@tonic-gate			/* Mark line as untouched. */
10147c478bdstevel@tonic-gate			newscr->_first[row] = newscr->_maxx;
10157c478bdstevel@tonic-gate			newscr->_last[row] = -1;
10167c478bdstevel@tonic-gate			__m_cc_hash(curscr, __m_screen->_hash, row);
10177c478bdstevel@tonic-gate		}
10187c478bdstevel@tonic-gate	}
10197c478bdstevel@tonic-gate
10207c478bdstevel@tonic-gate	newscr->_flags &= ~W_REDRAW_WINDOW;
10217c478bdstevel@tonic-gate}
10227c478bdstevel@tonic-gate
10237c478bdstevel@tonic-gatevoid
10247c478bdstevel@tonic-gatewtouchln_hard(WINDOW *w, int y, int n)
10257c478bdstevel@tonic-gate{
10267c478bdstevel@tonic-gate	int	last;
10277c478bdstevel@tonic-gate
10287c478bdstevel@tonic-gate	last = w->_maxx;
10297c478bdstevel@tonic-gate
10307c478bdstevel@tonic-gate	for (; (y < w->_maxy) && (0 < n); ++y, --n) {
10317c478bdstevel@tonic-gate		/*
10327c478bdstevel@tonic-gate		 * Force compare in doupdate to fail.
10337c478bdstevel@tonic-gate		 * Touch should be unconditional
10347c478bdstevel@tonic-gate		 */
10357c478bdstevel@tonic-gate(void) memset(&__m_screen->_curscr->_line[w->_begy + y][w->_begx],
10367c478bdstevel@tonic-gate	0xff, last * sizeof (cchar_t));
10377c478bdstevel@tonic-gate	}
10387c478bdstevel@tonic-gate}
10397c478bdstevel@tonic-gate/*
10407c478bdstevel@tonic-gate * Send all changes made to _newscr to the physical terminal.
10417c478bdstevel@tonic-gate *
10427c478bdstevel@tonic-gate * If idlok() is set TRUE then doupdate will try and use hardware insert
10437c478bdstevel@tonic-gate * and delete line sequences in an effort to optimize output.  idlok()
10447c478bdstevel@tonic-gate * should really only be used in applications that want a proper scrolling
10457c478bdstevel@tonic-gate * effect.
10467c478bdstevel@tonic-gate *
10477c478bdstevel@tonic-gate * Added scroll heuristic to handle special case where a full size window
10487c478bdstevel@tonic-gate * with full size scroll region, will scroll the window and replace dirty
10497c478bdstevel@tonic-gate * lines instead of performing usual cost/script operations.
10507c478bdstevel@tonic-gate */
10517c478bdstevel@tonic-gateint
10527c478bdstevel@tonic-gatedoupdate(void)
10537c478bdstevel@tonic-gate{
10547c478bdstevel@tonic-gate#ifdef SIGTSTP
10557c478bdstevel@tonic-gate	int (*oldsig)(int) = signal(SIGTSTP, SIG_IGN);
10567c478bdstevel@tonic-gate#endif
10577c478bdstevel@tonic-gate
10587c478bdstevel@tonic-gate	if (pollTypeahead()) {
10597c478bdstevel@tonic-gate		return (OK);
10607c478bdstevel@tonic-gate	}
10617c478bdstevel@tonic-gate	newscr = __m_screen->_newscr;
10627c478bdstevel@tonic-gate
10637c478bdstevel@tonic-gate	if (__m_screen->_flags & S_ENDWIN) {
10647c478bdstevel@tonic-gate		/* Return from temporary escape done with endwin(). */
10657c478bdstevel@tonic-gate		__m_screen->_flags &= ~S_ENDWIN;
10667c478bdstevel@tonic-gate
10677c478bdstevel@tonic-gate		(void) reset_prog_mode();
10687c478bdstevel@tonic-gate		if (enter_ca_mode != NULL)
10697c478bdstevel@tonic-gate			(void) TPUTS(enter_ca_mode, 1, __m_outc);
10707c478bdstevel@tonic-gate		if (keypad_xmit != NULL)
10717c478bdstevel@tonic-gate			(void) TPUTS(keypad_xmit, 1, __m_outc);
10727c478bdstevel@tonic-gate		if (ena_acs != NULL)
10737c478bdstevel@tonic-gate			(void) TPUTS(ena_acs, 1, __m_outc);
10747c478bdstevel@tonic-gate
10757c478bdstevel@tonic-gate		/* Force redraw of screen. */
10767c478bdstevel@tonic-gate		newscr->_flags |= W_CLEAR_WINDOW;
10777c478bdstevel@tonic-gate	}
10787c478bdstevel@tonic-gate	/*
10797c478bdstevel@tonic-gate	 * When redrawwing a window, we not only assume that line
10807c478bdstevel@tonic-gate	 * noise may have lost characters, but line noise may have
10817c478bdstevel@tonic-gate	 * generated bogus characters on the screen outside the
10827c478bdstevel@tonic-gate	 * the window in question, in which case redraw the entire
10837c478bdstevel@tonic-gate	 * screen to be sure.
10847c478bdstevel@tonic-gate	 */
10857c478bdstevel@tonic-gate	if ((newscr->_flags & (W_CLEAR_WINDOW | W_REDRAW_WINDOW)) ||
10867c478bdstevel@tonic-gate		(curscr->_flags & W_CLEAR_WINDOW)) {
10877c478bdstevel@tonic-gate		erase_bottom(0, newscr->_maxy);
10887c478bdstevel@tonic-gate		clear_bottom(0);
10897c478bdstevel@tonic-gate		(void) wtouchln(newscr, 0, newscr->_maxy, 1);
10907c478bdstevel@tonic-gate		newscr->_flags &= ~W_CLEAR_WINDOW;
10917c478bdstevel@tonic-gate		curscr->_flags &= ~W_CLEAR_WINDOW;
10927c478bdstevel@tonic-gate	}
10937c478bdstevel@tonic-gate
10947c478bdstevel@tonic-gate	/*
10957c478bdstevel@tonic-gate	 * Scrolling heuristic should only be used if lines being
10967c478bdstevel@tonic-gate	 * scrolled are clean because scrolling overrides updates
10977c478bdstevel@tonic-gate	 *
10987c478bdstevel@tonic-gate	 * Right now, the following code should always turn off
10997c478bdstevel@tonic-gate	 * scrolling, because the internal scroll touches the
11007c478bdstevel@tonic-gate	 * scrolled lines. This thing requires a lot more care
11017c478bdstevel@tonic-gate	 * than I have right now...
11027c478bdstevel@tonic-gate	 */
11037c478bdstevel@tonic-gate	if (newscr->_scroll) {
11047c478bdstevel@tonic-gate		int	y;
11057c478bdstevel@tonic-gate		for (y = 0; y < newscr->_maxy; ++y) {
11067c478bdstevel@tonic-gate			if (0 <= newscr->_last[y]) {
11077c478bdstevel@tonic-gate				newscr->_scroll = 0;
11087c478bdstevel@tonic-gate			}
11097c478bdstevel@tonic-gate		}
11107c478bdstevel@tonic-gate		newscr->_scroll = 0;	/* Just fudge it for now ... */
11117c478bdstevel@tonic-gate	}
11127c478bdstevel@tonic-gate	if (newscr->_flags & W_REDRAW_WINDOW) {
11137c478bdstevel@tonic-gate		simple();
11147c478bdstevel@tonic-gate	} else {
11157c478bdstevel@tonic-gate		if (newscr->_scroll == 0) {
11167c478bdstevel@tonic-gate			if (__m_screen->_flags & S_INS_DEL_LINE) {
11177c478bdstevel@tonic-gate				complex();
11187c478bdstevel@tonic-gate			} else {
11197c478bdstevel@tonic-gate				simple();
11207c478bdstevel@tonic-gate			}
11217c478bdstevel@tonic-gate		} else {
11227c478bdstevel@tonic-gate			if (!scroll_up(newscr->_scroll)) {
11237c478bdstevel@tonic-gate				if (__m_screen->_flags & S_INS_DEL_LINE) {
11247c478bdstevel@tonic-gate					complex();
11257c478bdstevel@tonic-gate				} else {
11267c478bdstevel@tonic-gate					simple();
11277c478bdstevel@tonic-gate				}
11287c478bdstevel@tonic-gate			}
11297c478bdstevel@tonic-gate		}
11307c478bdstevel@tonic-gate	}
11317c478bdstevel@tonic-gate
11327c478bdstevel@tonic-gate	if (!(newscr->_flags & W_LEAVE_CURSOR))	{
11337c478bdstevel@tonic-gate		GOTO(newscr->_cury, newscr->_curx);
11347c478bdstevel@tonic-gate	}
11357c478bdstevel@tonic-gate
11367c478bdstevel@tonic-gate	if (!(curscr->_flags & W_FLUSH)) {
11377c478bdstevel@tonic-gate		(void) fflush(__m_screen->_of);
11387c478bdstevel@tonic-gate	}
11397c478bdstevel@tonic-gate
11407c478bdstevel@tonic-gate	newscr->_scroll = curscr->_scroll = 0;
11417c478bdstevel@tonic-gate
11427c478bdstevel@tonic-gate	/* Send labels to terminal that supports them. */
11437c478bdstevel@tonic-gate	__m_slk_doupdate();
11447c478bdstevel@tonic-gate#ifdef SIGTSTP
11457c478bdstevel@tonic-gate	signal(SIGTSTP, oldsig);
11467c478bdstevel@tonic-gate#endif
11477c478bdstevel@tonic-gate
11487c478bdstevel@tonic-gate	return (OK);
11497c478bdstevel@tonic-gate}
11507c478bdstevel@tonic-gate
11517c478bdstevel@tonic-gate/*
11527c478bdstevel@tonic-gate * If true, the implementation may use hardware insert and delete,
11537c478bdstevel@tonic-gate * character features of the terminal.  The window parameter
11547c478bdstevel@tonic-gate * is ignored.
11557c478bdstevel@tonic-gate */
11567c478bdstevel@tonic-gate/* ARGSUSED */
11577c478bdstevel@tonic-gatevoid
11587c478bdstevel@tonic-gateidcok(WINDOW *w, bool bf)
11597c478bdstevel@tonic-gate{
11607c478bdstevel@tonic-gate	__m_screen->_flags &= ~S_INS_DEL_CHAR;
11617c478bdstevel@tonic-gate	if (bf)
11627c478bdstevel@tonic-gate		__m_screen->_flags |= S_INS_DEL_CHAR;
11637c478bdstevel@tonic-gate}
11647c478bdstevel@tonic-gate
11657c478bdstevel@tonic-gate/*
11667c478bdstevel@tonic-gate * If true, the implementation may use hardware insert, delete,
11677c478bdstevel@tonic-gate * and scroll line features of the terminal.  The window parameter
11687c478bdstevel@tonic-gate * is ignored.
11697c478bdstevel@tonic-gate */
11707c478bdstevel@tonic-gate/* ARGSUSED */
11717c478bdstevel@tonic-gateint
11727c478bdstevel@tonic-gateidlok(WINDOW *w, bool bf)
11737c478bdstevel@tonic-gate{
11747c478bdstevel@tonic-gate	__m_screen->_flags &= ~S_INS_DEL_LINE;
11757c478bdstevel@tonic-gate	if (bf && has_il())
11767c478bdstevel@tonic-gate		__m_screen->_flags |= S_INS_DEL_LINE;
11777c478bdstevel@tonic-gate
11787c478bdstevel@tonic-gate	return (OK);
11797c478bdstevel@tonic-gate}
11807c478bdstevel@tonic-gate
11817c478bdstevel@tonic-gate/*
11827c478bdstevel@tonic-gate * Use the POSIX 32-bit CRC function to compute a hash value
11837c478bdstevel@tonic-gate * for the window line.
11847c478bdstevel@tonic-gate */
11857c478bdstevel@tonic-gatevoid
11867c478bdstevel@tonic-gate#if defined(_LP64)
11877c478bdstevel@tonic-gate__m_cc_hash(WINDOW *w, unsigned int *array, int y)
11887c478bdstevel@tonic-gate#else
11897c478bdstevel@tonic-gate__m_cc_hash(WINDOW *w, unsigned long *array, int y)
11907c478bdstevel@tonic-gate#endif
11917c478bdstevel@tonic-gate{
11927c478bdstevel@tonic-gate	array[y] = 0;
11937c478bdstevel@tonic-gate	m_crcposix(&array[y], (unsigned char *) w->_line[y],
11947c478bdstevel@tonic-gate		(size_t)(w->_maxx * sizeof (**w->_line)));
11957c478bdstevel@tonic-gate}
1196