xref: /titanic_51/usr/src/cmd/vi/port/ex_vput.c (revision f6db9f272f0061301cfaa1c0001b7d636eae31f4)
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 /*
23*f6db9f27Scf46844  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include "ex.h"
367c478bd9Sstevel@tonic-gate #include "ex_tty.h"
377c478bd9Sstevel@tonic-gate #include "ex_vis.h"
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate  * Deal with the screen, clearing, cursor positioning, putting characters
417c478bd9Sstevel@tonic-gate  * into the screen image, and deleting characters.
427c478bd9Sstevel@tonic-gate  * Really hard stuff here is utilizing insert character operations
437c478bd9Sstevel@tonic-gate  * on intelligent terminals which differs widely from terminal to terminal.
447c478bd9Sstevel@tonic-gate  */
45*f6db9f27Scf46844 void
46*f6db9f27Scf46844 vclear(void)
477c478bd9Sstevel@tonic-gate {
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #ifdef TRACE
507c478bd9Sstevel@tonic-gate 	if (trace)
517c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "------\nvclear, clear_screen '%s'\n", clear_screen);
527c478bd9Sstevel@tonic-gate #endif
537c478bd9Sstevel@tonic-gate 	tputs(clear_screen, lines, putch);
547c478bd9Sstevel@tonic-gate 	destcol = 0;
557c478bd9Sstevel@tonic-gate 	outcol = 0;
567c478bd9Sstevel@tonic-gate 	destline = 0;
577c478bd9Sstevel@tonic-gate 	outline = 0;
587c478bd9Sstevel@tonic-gate 	if (inopen)
597c478bd9Sstevel@tonic-gate 	vclrbyte(vtube0, WCOLS * (WECHO - ZERO + 1));
607c478bd9Sstevel@tonic-gate }
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate /*
637c478bd9Sstevel@tonic-gate  * Clear memory.
647c478bd9Sstevel@tonic-gate  */
65*f6db9f27Scf46844 void
66*f6db9f27Scf46844 vclrbyte(wchar_t *cp, int i)
677c478bd9Sstevel@tonic-gate {
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate 	if (i > 0)
707c478bd9Sstevel@tonic-gate 		do
717c478bd9Sstevel@tonic-gate 			*cp++ = 0;
727c478bd9Sstevel@tonic-gate 		while (--i != 0);
737c478bd9Sstevel@tonic-gate }
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate /*
767c478bd9Sstevel@tonic-gate  * Clear a physical display line, high level.
777c478bd9Sstevel@tonic-gate  */
78*f6db9f27Scf46844 void
79*f6db9f27Scf46844 vclrlin(int l, line *tp)
807c478bd9Sstevel@tonic-gate {
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 	vigoto(l, 0);
837c478bd9Sstevel@tonic-gate 	if ((hold & HOLDAT) == 0)
847c478bd9Sstevel@tonic-gate 		putchar(tp > dol ? ((UPPERCASE || tilde_glitch) ? '^' : '~') : '@');
857c478bd9Sstevel@tonic-gate 	if (state == HARDOPEN)
867c478bd9Sstevel@tonic-gate 		sethard();
877c478bd9Sstevel@tonic-gate 	vclreol();
887c478bd9Sstevel@tonic-gate }
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate /*
917c478bd9Sstevel@tonic-gate  * Clear to the end of the current physical line
927c478bd9Sstevel@tonic-gate  */
93*f6db9f27Scf46844 void
94*f6db9f27Scf46844 vclreol(void)
957c478bd9Sstevel@tonic-gate {
96*f6db9f27Scf46844 	int i;
97*f6db9f27Scf46844 	wchar_t *tp, j;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate #ifdef TRACE
1007c478bd9Sstevel@tonic-gate 	if (trace)
1017c478bd9Sstevel@tonic-gate 		fprintf(trace, "vclreol(), destcol %d, ateopr() %d\n", destcol, ateopr());
1027c478bd9Sstevel@tonic-gate #endif
1037c478bd9Sstevel@tonic-gate 	if (destcol == WCOLS)
1047c478bd9Sstevel@tonic-gate 		return;
1057c478bd9Sstevel@tonic-gate 	destline += destcol / WCOLS;
1067c478bd9Sstevel@tonic-gate 	destcol %= WCOLS;
1077c478bd9Sstevel@tonic-gate 	if (destline < 0 || destline > WECHO)
1087c478bd9Sstevel@tonic-gate 		error(gettext("Internal error: vclreol"));
1097c478bd9Sstevel@tonic-gate 	i = WCOLS - destcol;
1107c478bd9Sstevel@tonic-gate 	tp = vtube[destline] + destcol;
1117c478bd9Sstevel@tonic-gate 	if (clr_eol) {
1127c478bd9Sstevel@tonic-gate 		if (insert_null_glitch && *tp || !ateopr()) {
1137c478bd9Sstevel@tonic-gate 			vcsync();
1147c478bd9Sstevel@tonic-gate 			vputp(clr_eol, 1);
1157c478bd9Sstevel@tonic-gate 		}
1167c478bd9Sstevel@tonic-gate 		vclrbyte(tp, i);
1177c478bd9Sstevel@tonic-gate 		return;
1187c478bd9Sstevel@tonic-gate 	}
1197c478bd9Sstevel@tonic-gate 	if (*tp == 0)
1207c478bd9Sstevel@tonic-gate 		return;
1217c478bd9Sstevel@tonic-gate 	while (i > 0 && (j = *tp & (QUOTE|TRIM))) {
1227c478bd9Sstevel@tonic-gate 		if (j != ' ' && (j & QUOTE) == 0) {
1237c478bd9Sstevel@tonic-gate 			destcol = WCOLS - i;
124*f6db9f27Scf46844 			(void) vputchar(' ');
1257c478bd9Sstevel@tonic-gate 		}
1267c478bd9Sstevel@tonic-gate 		--i, *tp++ = 0;
1277c478bd9Sstevel@tonic-gate 	}
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate /*
1317c478bd9Sstevel@tonic-gate  * Clear the echo line.
1327c478bd9Sstevel@tonic-gate  * If didphys then its been cleared physically (as
1337c478bd9Sstevel@tonic-gate  * a side effect of a clear to end of display, e.g.)
1347c478bd9Sstevel@tonic-gate  * so just do it logically.
1357c478bd9Sstevel@tonic-gate  * If work here is being held off, just remember, in
1367c478bd9Sstevel@tonic-gate  * heldech, if work needs to be done, don't do anything.
1377c478bd9Sstevel@tonic-gate  */
138*f6db9f27Scf46844 void
1397c478bd9Sstevel@tonic-gate vclrech(didphys)
1407c478bd9Sstevel@tonic-gate 	bool didphys;
1417c478bd9Sstevel@tonic-gate {
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate #ifdef ADEBUG
1447c478bd9Sstevel@tonic-gate 	if (trace)
1457c478bd9Sstevel@tonic-gate 		fprintf(trace, "vclrech(%d), Peekkey %d, hold %o\n", didphys, Peekkey, hold);
1467c478bd9Sstevel@tonic-gate #endif
1477c478bd9Sstevel@tonic-gate 	if (Peekkey == ATTN)
1487c478bd9Sstevel@tonic-gate 		return;
1497c478bd9Sstevel@tonic-gate 	if (hold & HOLDECH) {
1507c478bd9Sstevel@tonic-gate 		heldech = !didphys;
1517c478bd9Sstevel@tonic-gate 		return;
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 	if (!didphys && (clr_eos || clr_eol)) {
1547c478bd9Sstevel@tonic-gate 		splitw++;
1557c478bd9Sstevel@tonic-gate 		/*
1567c478bd9Sstevel@tonic-gate 		 * If display is retained below, then MUST use clr_eos or
1577c478bd9Sstevel@tonic-gate 		 * clr_eol since we don't really know whats out there.
1587c478bd9Sstevel@tonic-gate 		 * Vigoto might decide (incorrectly) to do nothing.
1597c478bd9Sstevel@tonic-gate 		 */
1607c478bd9Sstevel@tonic-gate 		if (memory_below) {
1617c478bd9Sstevel@tonic-gate 			vgoto(WECHO, 0);
1627c478bd9Sstevel@tonic-gate 			/*
1637c478bd9Sstevel@tonic-gate 			 * This is tricky.  If clr_eos is as cheap we
1647c478bd9Sstevel@tonic-gate 			 * should use it, so we don't have extra junk
1657c478bd9Sstevel@tonic-gate 			 * floating around in memory below.  But if
1667c478bd9Sstevel@tonic-gate 			 * clr_eol costs less we should use it.  The real
1677c478bd9Sstevel@tonic-gate 			 * reason here is that clr_eos is incredibly
1687c478bd9Sstevel@tonic-gate 			 * expensive on the HP 2626 (1/2 second or more)
1697c478bd9Sstevel@tonic-gate 			 * which makes ^D scroll really slow.  But the
1707c478bd9Sstevel@tonic-gate 			 * 2621 has a bug that shows up if we use clr_eol
1717c478bd9Sstevel@tonic-gate 			 * instead of clr_eos, so we make sure the costs
1727c478bd9Sstevel@tonic-gate 			 * are equal so it will prefer clr_eol.
1737c478bd9Sstevel@tonic-gate 			 */
1747c478bd9Sstevel@tonic-gate 			if (costCE < costCD)
1757c478bd9Sstevel@tonic-gate 				vputp(clr_eol, 1);
1767c478bd9Sstevel@tonic-gate 			else
1777c478bd9Sstevel@tonic-gate 				vputp(clr_eos, 1);
1787c478bd9Sstevel@tonic-gate 		} else {
1797c478bd9Sstevel@tonic-gate 			if (teleray_glitch) {
1807c478bd9Sstevel@tonic-gate 				/* This code basically handles the t1061
1817c478bd9Sstevel@tonic-gate 				 * where positioning at (0, 0) won't work
1827c478bd9Sstevel@tonic-gate 				 * because the terminal won't let you put
1837c478bd9Sstevel@tonic-gate 				 * the cursor on it's magic cookie.
1847c478bd9Sstevel@tonic-gate 				 *
1857c478bd9Sstevel@tonic-gate 				 * Should probably be ceol_standout_glitch
1867c478bd9Sstevel@tonic-gate 				 * above, or even a
1877c478bd9Sstevel@tonic-gate 				 * new glitch, but right now t1061 is the
1887c478bd9Sstevel@tonic-gate 				 * only terminal with teleray_glitch.
1897c478bd9Sstevel@tonic-gate 				 */
1907c478bd9Sstevel@tonic-gate 				vgoto(WECHO, 0);
1917c478bd9Sstevel@tonic-gate 				vputp(delete_line, 1);
1927c478bd9Sstevel@tonic-gate 			} else {
1937c478bd9Sstevel@tonic-gate 				vigoto(WECHO, 0);
1947c478bd9Sstevel@tonic-gate 				vclreol();
1957c478bd9Sstevel@tonic-gate 			}
1967c478bd9Sstevel@tonic-gate 		}
1977c478bd9Sstevel@tonic-gate 		splitw = 0;
1987c478bd9Sstevel@tonic-gate 		didphys = 1;
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate 	if (didphys)
2017c478bd9Sstevel@tonic-gate 		vclrbyte(vtube[WECHO], WCOLS);
2027c478bd9Sstevel@tonic-gate 	heldech = 0;
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate /*
2067c478bd9Sstevel@tonic-gate  * Fix the echo area for use, setting
2077c478bd9Sstevel@tonic-gate  * the state variable splitw so we wont rollup
2087c478bd9Sstevel@tonic-gate  * when we move the cursor there.
2097c478bd9Sstevel@tonic-gate  */
210*f6db9f27Scf46844 void
211*f6db9f27Scf46844 fixech(void)
2127c478bd9Sstevel@tonic-gate {
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	splitw++;
2157c478bd9Sstevel@tonic-gate 	if (state != VISUAL && state != CRTOPEN) {
2167c478bd9Sstevel@tonic-gate 		vclean();
2177c478bd9Sstevel@tonic-gate 		vcnt = 0;
2187c478bd9Sstevel@tonic-gate 	}
2197c478bd9Sstevel@tonic-gate 	vgoto(WECHO, 0); flusho();
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate /*
2237c478bd9Sstevel@tonic-gate  * Put the cursor ``before'' cp.
2247c478bd9Sstevel@tonic-gate  */
225*f6db9f27Scf46844 void
226*f6db9f27Scf46844 vcursbef(unsigned char *cp)
2277c478bd9Sstevel@tonic-gate {
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	if (cp <= linebuf)
2307c478bd9Sstevel@tonic-gate 		vgotoCL(value(vi_NUMBER) << 3);
2317c478bd9Sstevel@tonic-gate 	else
2327c478bd9Sstevel@tonic-gate 		vgotoCL(lcolumn(cp)-1);
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate /*
2367c478bd9Sstevel@tonic-gate  * Put the cursor ``at'' cp.
2377c478bd9Sstevel@tonic-gate  */
238*f6db9f27Scf46844 void
239*f6db9f27Scf46844 vcursat(unsigned char *cp)
2407c478bd9Sstevel@tonic-gate {
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	if (cp <= linebuf && linebuf[0] == 0)
2437c478bd9Sstevel@tonic-gate 		vgotoCL(value(vi_NUMBER) << 3);
2447c478bd9Sstevel@tonic-gate 	else
2457c478bd9Sstevel@tonic-gate 		vgotoCL(lcolumn(cp));
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate /*
2497c478bd9Sstevel@tonic-gate  * Put the cursor ``after'' cp.
2507c478bd9Sstevel@tonic-gate  */
251*f6db9f27Scf46844 void
252*f6db9f27Scf46844 vcursaft(unsigned char *cp)
2537c478bd9Sstevel@tonic-gate {
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	vgotoCL(lcolumn(nextchr(cp)));
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate /*
2597c478bd9Sstevel@tonic-gate  * Fix the cursor to be positioned in the correct place
2607c478bd9Sstevel@tonic-gate  * to accept a command.
2617c478bd9Sstevel@tonic-gate  */
262*f6db9f27Scf46844 void
263*f6db9f27Scf46844 vfixcurs(void)
2647c478bd9Sstevel@tonic-gate {
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	vsetcurs(cursor);
2677c478bd9Sstevel@tonic-gate }
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate /*
2707c478bd9Sstevel@tonic-gate  * Compute the column position implied by the cursor at ``nc'',
2717c478bd9Sstevel@tonic-gate  * and move the cursor there.
2727c478bd9Sstevel@tonic-gate  */
273*f6db9f27Scf46844 void
274*f6db9f27Scf46844 vsetcurs(unsigned char *nc)
2757c478bd9Sstevel@tonic-gate {
276*f6db9f27Scf46844 	int col;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	col = column(nc);
2797c478bd9Sstevel@tonic-gate 	if (linebuf[0])
2807c478bd9Sstevel@tonic-gate 		col--;
2817c478bd9Sstevel@tonic-gate 	vgotoCL(col);
2827c478bd9Sstevel@tonic-gate 	cursor = nc;
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate /*
2867c478bd9Sstevel@tonic-gate  * Move the cursor invisibly, i.e. only remember to do it.
2877c478bd9Sstevel@tonic-gate  */
288*f6db9f27Scf46844 void
289*f6db9f27Scf46844 vigoto(int y, int x)
2907c478bd9Sstevel@tonic-gate {
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	destline = y;
2937c478bd9Sstevel@tonic-gate 	destcol = x;
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate /*
2977c478bd9Sstevel@tonic-gate  * Move the cursor to the position implied by any previous
2987c478bd9Sstevel@tonic-gate  * vigoto (or low level hacking with destcol/destline as in readecho).
2997c478bd9Sstevel@tonic-gate  */
300*f6db9f27Scf46844 void
301*f6db9f27Scf46844 vcsync(void)
3027c478bd9Sstevel@tonic-gate {
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	vgoto(destline, destcol);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate /*
3087c478bd9Sstevel@tonic-gate  * Goto column x of the current line.
3097c478bd9Sstevel@tonic-gate  */
310*f6db9f27Scf46844 void
311*f6db9f27Scf46844 vgotoCL(int x)
3127c478bd9Sstevel@tonic-gate {
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	if (splitw)
3157c478bd9Sstevel@tonic-gate 		vgoto(WECHO, x);
3167c478bd9Sstevel@tonic-gate 	else
3177c478bd9Sstevel@tonic-gate 		vgoto(LINE(vcline), x);
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate /*
3217c478bd9Sstevel@tonic-gate  * Invisible goto column x of current line.
3227c478bd9Sstevel@tonic-gate  */
323*f6db9f27Scf46844 void
324*f6db9f27Scf46844 vigotoCL(int x)
3257c478bd9Sstevel@tonic-gate {
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	if (splitw)
3287c478bd9Sstevel@tonic-gate 		vigoto(WECHO, x);
3297c478bd9Sstevel@tonic-gate 	else
3307c478bd9Sstevel@tonic-gate 		vigoto(LINE(vcline), x);
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate /*
3347c478bd9Sstevel@tonic-gate  * Show the current mode in the right hand part of the echo line,
3357c478bd9Sstevel@tonic-gate  * then return the cursor to where it is now.
3367c478bd9Sstevel@tonic-gate  */
337*f6db9f27Scf46844 void
338*f6db9f27Scf46844 vshowmode(unsigned char *msg)
3397c478bd9Sstevel@tonic-gate {
3407c478bd9Sstevel@tonic-gate 	int savecol, saveline, savesplit;
3417c478bd9Sstevel@tonic-gate 	unsigned char *p;
3427c478bd9Sstevel@tonic-gate 	wchar_t	wchar;
3437c478bd9Sstevel@tonic-gate 	int	length;
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	if (!value(vi_SHOWMODE))
3467c478bd9Sstevel@tonic-gate 		return;
3477c478bd9Sstevel@tonic-gate 	/* Don't alter mode message for macros (arrow keys) or yank/put */
3487c478bd9Sstevel@tonic-gate 	if (vmacp || vglobp)
3497c478bd9Sstevel@tonic-gate 		return;
3507c478bd9Sstevel@tonic-gate 	savecol = outcol; saveline = outline; savesplit = splitw;
3517c478bd9Sstevel@tonic-gate 	splitw = 1;	/* To avoid scrolling */
3527c478bd9Sstevel@tonic-gate 	vigoto(WECHO, WCOLS-20);
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	if (*msg) {
3557c478bd9Sstevel@tonic-gate 		vcsync();
3567c478bd9Sstevel@tonic-gate 		for (p = msg; *p;) {
3577c478bd9Sstevel@tonic-gate 			length = mbtowc(&wchar, (char *)p, MULTI_BYTE_MAX);
3587c478bd9Sstevel@tonic-gate 			if (length <= 0) {
3597c478bd9Sstevel@tonic-gate 				/*
3607c478bd9Sstevel@tonic-gate 				 * This should never happen, but
3617c478bd9Sstevel@tonic-gate 				 * if 'msg' doesn't make a valid string,
3627c478bd9Sstevel@tonic-gate 				 * treat this case as the same as the
3637c478bd9Sstevel@tonic-gate 				 * null string 'msg'.
3647c478bd9Sstevel@tonic-gate 				 */
3657c478bd9Sstevel@tonic-gate 				/*
3667c478bd9Sstevel@tonic-gate 				 * Going back to command mode - clear the message.
3677c478bd9Sstevel@tonic-gate 				 */
3687c478bd9Sstevel@tonic-gate 				vclreol();
3697c478bd9Sstevel@tonic-gate 				break;
3707c478bd9Sstevel@tonic-gate 			} else {
371*f6db9f27Scf46844 				(void) vputchar(wchar);
3727c478bd9Sstevel@tonic-gate 				p += length;
3737c478bd9Sstevel@tonic-gate 			}
3747c478bd9Sstevel@tonic-gate 		}
3757c478bd9Sstevel@tonic-gate 	} else {
3767c478bd9Sstevel@tonic-gate 		/*
3777c478bd9Sstevel@tonic-gate 		 * Going back to command mode - clear the message.
3787c478bd9Sstevel@tonic-gate 		 */
3797c478bd9Sstevel@tonic-gate 		vclreol();
3807c478bd9Sstevel@tonic-gate 	}
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	FLAGS(WECHO) |= VDIRT;
3837c478bd9Sstevel@tonic-gate 	vgoto(saveline, savecol);
3847c478bd9Sstevel@tonic-gate 	splitw = savesplit;
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate /*
3887c478bd9Sstevel@tonic-gate  * Move cursor to line y, column x, handling wraparound and scrolling.
3897c478bd9Sstevel@tonic-gate  */
390*f6db9f27Scf46844 void
391*f6db9f27Scf46844 vgoto(int y, int x)
3927c478bd9Sstevel@tonic-gate {
393*f6db9f27Scf46844 	wchar_t *tp;
394*f6db9f27Scf46844 	wchar_t c;
3957c478bd9Sstevel@tonic-gate 	int		 col;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	/*
3987c478bd9Sstevel@tonic-gate 	 * Fold the possibly too large value of x.
3997c478bd9Sstevel@tonic-gate 	 */
4007c478bd9Sstevel@tonic-gate 	if (x >= WCOLS) {
4017c478bd9Sstevel@tonic-gate 		y += x / WCOLS;
4027c478bd9Sstevel@tonic-gate 		x %= WCOLS;
4037c478bd9Sstevel@tonic-gate 	}
4047c478bd9Sstevel@tonic-gate 	if (y < 0) {
4057c478bd9Sstevel@tonic-gate 		error("Internal error: vgoto");
4067c478bd9Sstevel@tonic-gate 	}
4077c478bd9Sstevel@tonic-gate 	if (outcol >= WCOLS) {
4087c478bd9Sstevel@tonic-gate 		if (auto_right_margin) {
4097c478bd9Sstevel@tonic-gate 			outline += outcol / WCOLS;
4107c478bd9Sstevel@tonic-gate 			outcol %= WCOLS;
4117c478bd9Sstevel@tonic-gate 		} else
4127c478bd9Sstevel@tonic-gate 			outcol = WCOLS - 1;
4137c478bd9Sstevel@tonic-gate 	}
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	/*
4167c478bd9Sstevel@tonic-gate 	 * In a hardcopy or glass crt open, print the stuff
4177c478bd9Sstevel@tonic-gate 	 * implied by a motion, or backspace.
4187c478bd9Sstevel@tonic-gate 	 */
4197c478bd9Sstevel@tonic-gate 	if (state == HARDOPEN || state == ONEOPEN) {
4207c478bd9Sstevel@tonic-gate 		if (y != outline)
4217c478bd9Sstevel@tonic-gate 			error(gettext("Line too long for open"));
4227c478bd9Sstevel@tonic-gate 		if (x + 1 < outcol - x || (outcol > x && !cursor_left))
4237c478bd9Sstevel@tonic-gate 			destcol = 0, fgoto();
4247c478bd9Sstevel@tonic-gate 		tp = vtube[WBOT] + outcol;
4257c478bd9Sstevel@tonic-gate 		while (outcol != x)
4267c478bd9Sstevel@tonic-gate 			if (outcol < x) {
4277c478bd9Sstevel@tonic-gate 				int length;
4287c478bd9Sstevel@tonic-gate 				unsigned char multic[MULTI_BYTE_MAX];
4297c478bd9Sstevel@tonic-gate 				if (*tp == 0)
4307c478bd9Sstevel@tonic-gate 					*tp = ' ';
4317c478bd9Sstevel@tonic-gate 				c = *tp++ & TRIM;
4327c478bd9Sstevel@tonic-gate 				length = wctomb((char *)multic, c);
4337c478bd9Sstevel@tonic-gate 				if(length == 0)
4347c478bd9Sstevel@tonic-gate 					length = 1;
4357c478bd9Sstevel@tonic-gate 				while(length--)
436*f6db9f27Scf46844 					(void) vputc(c &&
437*f6db9f27Scf46844 					    (!over_strike || erase_overstrike)
438*f6db9f27Scf46844 					    ? c : ' ');
4397c478bd9Sstevel@tonic-gate 				if (c) {
4407c478bd9Sstevel@tonic-gate 					if ((col = wcwidth(c)) < 0)
4417c478bd9Sstevel@tonic-gate 						col = 0;
4427c478bd9Sstevel@tonic-gate 				} else
4437c478bd9Sstevel@tonic-gate 					col = 1;
4447c478bd9Sstevel@tonic-gate 				outcol += col;
4457c478bd9Sstevel@tonic-gate 			} else {
4467c478bd9Sstevel@tonic-gate 				vputp(cursor_left, 0);
4477c478bd9Sstevel@tonic-gate 				outcol--;
4487c478bd9Sstevel@tonic-gate 			}
4497c478bd9Sstevel@tonic-gate 		destcol = outcol = x;
4507c478bd9Sstevel@tonic-gate 		destline = outline;
4517c478bd9Sstevel@tonic-gate 		return;
4527c478bd9Sstevel@tonic-gate 	}
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	/*
4557c478bd9Sstevel@tonic-gate 	 * If the destination position implies a scroll, do it.
4567c478bd9Sstevel@tonic-gate 	 */
4577c478bd9Sstevel@tonic-gate 	destline = y;
4587c478bd9Sstevel@tonic-gate 	if (destline > WBOT && (!splitw || destline > WECHO)) {
4597c478bd9Sstevel@tonic-gate 		endim();
4607c478bd9Sstevel@tonic-gate 		vrollup(destline);
4617c478bd9Sstevel@tonic-gate 	}
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	/*
4647c478bd9Sstevel@tonic-gate 	 * If there really is a motion involved, do it.
4657c478bd9Sstevel@tonic-gate 	 * The check here is an optimization based on profiling.
4667c478bd9Sstevel@tonic-gate 	 */
4677c478bd9Sstevel@tonic-gate 	destcol = x;
4687c478bd9Sstevel@tonic-gate 	if ((destline - outline) * WCOLS != destcol - outcol) {
4697c478bd9Sstevel@tonic-gate 		if (!move_insert_mode)
4707c478bd9Sstevel@tonic-gate 			endim();
4717c478bd9Sstevel@tonic-gate 		fgoto();
4727c478bd9Sstevel@tonic-gate 	}
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate /*
4767c478bd9Sstevel@tonic-gate  * This is the hardest code in the editor, and deals with insert modes
4777c478bd9Sstevel@tonic-gate  * on different kinds of intelligent terminals.  The complexity is due
4787c478bd9Sstevel@tonic-gate  * to the cross product of three factors:
4797c478bd9Sstevel@tonic-gate  *
4807c478bd9Sstevel@tonic-gate  *	1. Lines may display as more than one segment on the screen.
4817c478bd9Sstevel@tonic-gate  *	2. There are 2 kinds of intelligent terminal insert modes.
4827c478bd9Sstevel@tonic-gate  *	3. Tabs squash when you insert characters in front of them,
4837c478bd9Sstevel@tonic-gate  *	   in a way in which current intelligent terminals don't handle.
4847c478bd9Sstevel@tonic-gate  *
4857c478bd9Sstevel@tonic-gate  * The two kinds of terminals are typified by the DM2500 or HP2645 for
4867c478bd9Sstevel@tonic-gate  * one and the CONCEPT-100 or the FOX for the other.
4877c478bd9Sstevel@tonic-gate  *
4887c478bd9Sstevel@tonic-gate  * The first (HP2645) kind has an insert mode where the characters
4897c478bd9Sstevel@tonic-gate  * fall off the end of the line and the screen is shifted rigidly
4907c478bd9Sstevel@tonic-gate  * no matter how the display came about.
4917c478bd9Sstevel@tonic-gate  *
4927c478bd9Sstevel@tonic-gate  * The second (CONCEPT-100) kind comes from terminals which are designed
4937c478bd9Sstevel@tonic-gate  * for forms editing and which distinguish between blanks and ``spaces''
4947c478bd9Sstevel@tonic-gate  * on the screen, spaces being like blank, but never having had
4957c478bd9Sstevel@tonic-gate  * and data typed into that screen position (since, e.g. a clear operation
4967c478bd9Sstevel@tonic-gate  * like clear screen).  On these terminals, when you insert a character,
4977c478bd9Sstevel@tonic-gate  * the characters from where you are to the end of the screen shift
4987c478bd9Sstevel@tonic-gate  * over till a ``space'' is found, and the null character there gets
4997c478bd9Sstevel@tonic-gate  * eaten up.
5007c478bd9Sstevel@tonic-gate  *
5017c478bd9Sstevel@tonic-gate  *
5027c478bd9Sstevel@tonic-gate  * The code here considers the line as consisting of several parts
5037c478bd9Sstevel@tonic-gate  * the first part is the ``doomed'' part, i.e. a part of the line
5047c478bd9Sstevel@tonic-gate  * which is being typed over.  Next comes some text up to the first
5057c478bd9Sstevel@tonic-gate  * following tab.  The tab is the next segment of the line, and finally
5067c478bd9Sstevel@tonic-gate  * text after the tab.
5077c478bd9Sstevel@tonic-gate  *
5087c478bd9Sstevel@tonic-gate  * We have to consider each of these segments and the effect of the
5097c478bd9Sstevel@tonic-gate  * insertion of a character on them.  On terminals like HP2645's we
5107c478bd9Sstevel@tonic-gate  * must simulate a multi-line insert mode using the primitive one
5117c478bd9Sstevel@tonic-gate  * line insert mode.  If we are inserting in front of a tab, we have
5127c478bd9Sstevel@tonic-gate  * to either delete characters from the tab or insert white space
5137c478bd9Sstevel@tonic-gate  * (when the tab reaches a new spot where it gets larger) before we
5147c478bd9Sstevel@tonic-gate  * insert the new character.
5157c478bd9Sstevel@tonic-gate  *
5167c478bd9Sstevel@tonic-gate  * On a terminal like a CONCEPT our strategy is to make all
5177c478bd9Sstevel@tonic-gate  * blanks be displayed, while trying to keep the screen having ``spaces''
5187c478bd9Sstevel@tonic-gate  * for portions of tabs.  In this way the terminal hardware does some
5197c478bd9Sstevel@tonic-gate  * of the hacking for compression of tabs, although this tends to
5207c478bd9Sstevel@tonic-gate  * disappear as you work on the line and spaces change into blanks.
5217c478bd9Sstevel@tonic-gate  *
5227c478bd9Sstevel@tonic-gate  * There are a number of boundary conditions (like typing just before
5237c478bd9Sstevel@tonic-gate  * the first following tab) where we can avoid a lot of work.  Most
5247c478bd9Sstevel@tonic-gate  * of them have to be dealt with explicitly because performance is
5257c478bd9Sstevel@tonic-gate  * much, much worse if we don't.
5267c478bd9Sstevel@tonic-gate  *
5277c478bd9Sstevel@tonic-gate  * A final thing which is hacked here is two flavors of insert mode.
5287c478bd9Sstevel@tonic-gate  * Datamedia's do this by an insert mode which you enter and leave
5297c478bd9Sstevel@tonic-gate  * and by having normal motion character operate differently in this
5307c478bd9Sstevel@tonic-gate  * mode, notably by having a newline insert a line on the screen in
5317c478bd9Sstevel@tonic-gate  * this mode.  This generally means it is unsafe to move around
5327c478bd9Sstevel@tonic-gate  * the screen ignoring the fact that we are in this mode.
5337c478bd9Sstevel@tonic-gate  * This is possible on some terminals, and wins big (e.g. HP), so
5347c478bd9Sstevel@tonic-gate  * we encode this as a ``can move in insert capability'' mi,
5357c478bd9Sstevel@tonic-gate  * and terminals which have it can do insert mode with much less
5367c478bd9Sstevel@tonic-gate  * work when tabs are present following the cursor on the current line.
5377c478bd9Sstevel@tonic-gate  */
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate /*
5407c478bd9Sstevel@tonic-gate  * Routine to expand a tab, calling the normal Outchar routine
5417c478bd9Sstevel@tonic-gate  * to put out each implied character.  Note that we call outchar
5427c478bd9Sstevel@tonic-gate  * with a QUOTE.  We use QUOTE internally to represent a position
5437c478bd9Sstevel@tonic-gate  * which is part of the expansion of a tab.
5447c478bd9Sstevel@tonic-gate  */
545*f6db9f27Scf46844 void
546*f6db9f27Scf46844 vgotab(void)
5477c478bd9Sstevel@tonic-gate {
548*f6db9f27Scf46844 	int i = tabcol(destcol, value(vi_TABSTOP)) - destcol;
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	do
5517c478bd9Sstevel@tonic-gate 		(*Outchar)(QUOTE);
5527c478bd9Sstevel@tonic-gate 	while (--i);
5537c478bd9Sstevel@tonic-gate }
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate /*
5567c478bd9Sstevel@tonic-gate  * Variables for insert mode.
5577c478bd9Sstevel@tonic-gate  */
5587c478bd9Sstevel@tonic-gate int	linend;			/* The column position of end of line */
5597c478bd9Sstevel@tonic-gate int	tabstart;		/* Column of start of first following tab */
5607c478bd9Sstevel@tonic-gate int	tabend;			/* Column of end of following tabs */
5617c478bd9Sstevel@tonic-gate int	tabsize;		/* Size of the following tabs */
5627c478bd9Sstevel@tonic-gate int	tabslack;		/* Number of ``spaces'' in following tabs */
5637c478bd9Sstevel@tonic-gate int	inssiz;			/* Number of characters to be inserted */
5647c478bd9Sstevel@tonic-gate int	inscol;			/* Column where insertion is taking place */
5657c478bd9Sstevel@tonic-gate int	shft;			/* Amount tab expansion shifted rest of line */
5667c478bd9Sstevel@tonic-gate int	slakused;		/* This much of tabslack will be used up */
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate /*
5697c478bd9Sstevel@tonic-gate  * This routine MUST be called before insert mode is run,
5707c478bd9Sstevel@tonic-gate  * and brings all segments of the current line to the top
5717c478bd9Sstevel@tonic-gate  * of the screen image buffer so it is easier for us to
5727c478bd9Sstevel@tonic-gate  * manipulate them.
5737c478bd9Sstevel@tonic-gate  */
574*f6db9f27Scf46844 void
575*f6db9f27Scf46844 vprepins(void)
5767c478bd9Sstevel@tonic-gate {
577*f6db9f27Scf46844 	int i;
578*f6db9f27Scf46844 	wchar_t *cp = vtube0;
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 	for (i = 0; i < DEPTH(vcline); i++) {
5817c478bd9Sstevel@tonic-gate 		vmaktop(LINE(vcline) + i, cp);
5827c478bd9Sstevel@tonic-gate 		cp += WCOLS;
5837c478bd9Sstevel@tonic-gate 	}
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate 
586*f6db9f27Scf46844 void
587*f6db9f27Scf46844 vmaktop(int p, wchar_t *cp)
5887c478bd9Sstevel@tonic-gate {
589*f6db9f27Scf46844 	int i;
5907c478bd9Sstevel@tonic-gate 	wchar_t temp[TUBECOLS];
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	if (p < 0 || vtube[p] == cp)
5937c478bd9Sstevel@tonic-gate 		return;
5947c478bd9Sstevel@tonic-gate 	for (i = ZERO; i <= WECHO; i++)
5957c478bd9Sstevel@tonic-gate 		if (vtube[i] == cp) {
5967c478bd9Sstevel@tonic-gate 			copy(temp, vtube[i], WCOLS * sizeof(wchar_t));
5977c478bd9Sstevel@tonic-gate 			copy(vtube[i], vtube[p], WCOLS * sizeof(wchar_t));
5987c478bd9Sstevel@tonic-gate 			copy(vtube[p], temp, WCOLS * sizeof(wchar_t));
5997c478bd9Sstevel@tonic-gate 			vtube[i] = vtube[p];
6007c478bd9Sstevel@tonic-gate 			vtube[p] = cp;
6017c478bd9Sstevel@tonic-gate 			return;
6027c478bd9Sstevel@tonic-gate 		}
6037c478bd9Sstevel@tonic-gate 	error(gettext("Line too long"));
6047c478bd9Sstevel@tonic-gate }
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate /*
6077c478bd9Sstevel@tonic-gate  * Insert character c at current cursor position.
6087c478bd9Sstevel@tonic-gate  * Multi-character inserts occur only as a result
6097c478bd9Sstevel@tonic-gate  * of expansion of tabs (i.e. inssize == 1 except
6107c478bd9Sstevel@tonic-gate  * for tabs or multibyte characters)
6117c478bd9Sstevel@tonic-gate  * and code assumes this in several place
6127c478bd9Sstevel@tonic-gate  * to make life simpler.
6137c478bd9Sstevel@tonic-gate  */
614*f6db9f27Scf46844 int
615*f6db9f27Scf46844 vinschar(wchar_t c)
6167c478bd9Sstevel@tonic-gate {
617*f6db9f27Scf46844 	int i;
618*f6db9f27Scf46844 	wchar_t *tp, wchar;
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 	if ((!enter_insert_mode || !exit_insert_mode) && ((hold & HOLDQIK) || !value(vi_REDRAW) || value(vi_SLOWOPEN))) {
6217c478bd9Sstevel@tonic-gate 		/*
6227c478bd9Sstevel@tonic-gate 		 * Don't want to try to use terminal
6237c478bd9Sstevel@tonic-gate 		 * insert mode, or to try to fake it.
6247c478bd9Sstevel@tonic-gate 		 * Just put the character out; the screen
6257c478bd9Sstevel@tonic-gate 		 * will probably be wrong but we will fix it later.
6267c478bd9Sstevel@tonic-gate 		 */
6277c478bd9Sstevel@tonic-gate 		if (c == '\t') {
6287c478bd9Sstevel@tonic-gate 			vgotab();
629*f6db9f27Scf46844 			return (0);
6307c478bd9Sstevel@tonic-gate 		}
631*f6db9f27Scf46844 		(void) vputchar(c);
6327c478bd9Sstevel@tonic-gate 		if (DEPTH(vcline) * WCOLS + !value(vi_REDRAW) >
6337c478bd9Sstevel@tonic-gate 		    (destline - LINE(vcline)) * WCOLS + destcol)
634*f6db9f27Scf46844 			return (0);
6357c478bd9Sstevel@tonic-gate 		/*
6367c478bd9Sstevel@tonic-gate 		 * The next line is about to be clobbered
6377c478bd9Sstevel@tonic-gate 		 * make space for another segment of this line
6387c478bd9Sstevel@tonic-gate 		 * (on an intelligent terminal) or just remember
6397c478bd9Sstevel@tonic-gate 		 * that next line was clobbered (on a dumb one
6407c478bd9Sstevel@tonic-gate 		 * if we don't care to redraw the tail.
6417c478bd9Sstevel@tonic-gate 		 */
6427c478bd9Sstevel@tonic-gate 		if (insert_line) {
6437c478bd9Sstevel@tonic-gate 			vnpins(0);
6447c478bd9Sstevel@tonic-gate 		} else {
6457c478bd9Sstevel@tonic-gate 			int i2 = LINE(vcline) + DEPTH(vcline);
6467c478bd9Sstevel@tonic-gate 			if (i2 < LINE(vcline + 1) || i2 > WBOT)
647*f6db9f27Scf46844 				return (0);
6487c478bd9Sstevel@tonic-gate 			i = destcol;
6497c478bd9Sstevel@tonic-gate 			vinslin(i2, 1, vcline);
6507c478bd9Sstevel@tonic-gate 			DEPTH(vcline)++;
6517c478bd9Sstevel@tonic-gate 			vigoto(i2, i);
6527c478bd9Sstevel@tonic-gate 			vprepins();
6537c478bd9Sstevel@tonic-gate 		}
654*f6db9f27Scf46844 		return (0);
6557c478bd9Sstevel@tonic-gate 	}
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	/*
6587c478bd9Sstevel@tonic-gate 	 * Compute the number of positions in the line image of the
6597c478bd9Sstevel@tonic-gate 	 * current line.  This is done from the physical image
6607c478bd9Sstevel@tonic-gate 	 * since that is faster.  Note that we have no memory
6617c478bd9Sstevel@tonic-gate 	 * from insertion to insertion so that routines which use
6627c478bd9Sstevel@tonic-gate 	 * us don't have to worry about moving the cursor around.
6637c478bd9Sstevel@tonic-gate 	 */
6647c478bd9Sstevel@tonic-gate 	if (*vtube0 == 0)
6657c478bd9Sstevel@tonic-gate 		linend = 0;
6667c478bd9Sstevel@tonic-gate 	else {
6677c478bd9Sstevel@tonic-gate 		/*
6687c478bd9Sstevel@tonic-gate 		 * Search backwards for a non-null character
6697c478bd9Sstevel@tonic-gate 		 * from the end of the displayed line.
6707c478bd9Sstevel@tonic-gate 		 */
6717c478bd9Sstevel@tonic-gate 		i = WCOLS * DEPTH(vcline);
6727c478bd9Sstevel@tonic-gate 		if (i == 0)
6737c478bd9Sstevel@tonic-gate 			i = WCOLS;
6747c478bd9Sstevel@tonic-gate 		tp = vtube0 + i;
6757c478bd9Sstevel@tonic-gate 		while (*--tp == 0)
6767c478bd9Sstevel@tonic-gate 			if (--i == 0)
6777c478bd9Sstevel@tonic-gate 				break;
6787c478bd9Sstevel@tonic-gate 		linend = i;
6797c478bd9Sstevel@tonic-gate 	}
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	/*
6827c478bd9Sstevel@tonic-gate 	 * We insert at a position based on the physical location
6837c478bd9Sstevel@tonic-gate 	 * of the output cursor.
6847c478bd9Sstevel@tonic-gate 	 */
6857c478bd9Sstevel@tonic-gate 	inscol = destcol + (destline - LINE(vcline)) * WCOLS;
6867c478bd9Sstevel@tonic-gate 	if (c == '\t') {
6877c478bd9Sstevel@tonic-gate 		/*
6887c478bd9Sstevel@tonic-gate 		 * Characters inserted from a tab must be
6897c478bd9Sstevel@tonic-gate 		 * remembered as being part of a tab, but we can't
6907c478bd9Sstevel@tonic-gate 		 * use QUOTE here since we really need to print blanks.
6917c478bd9Sstevel@tonic-gate 		 * QUOTE|' ' is the representation of this.
6927c478bd9Sstevel@tonic-gate 		 */
6937c478bd9Sstevel@tonic-gate 		inssiz = tabcol(inscol, value(vi_TABSTOP)) - inscol;
6947c478bd9Sstevel@tonic-gate 		c = ' ' | QUOTE;
6957c478bd9Sstevel@tonic-gate 	} else {
6967c478bd9Sstevel@tonic-gate 		if ((inssiz = wcwidth(c)) < 0)
6977c478bd9Sstevel@tonic-gate 			inssiz = 0;
6987c478bd9Sstevel@tonic-gate 	}
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	/*
7017c478bd9Sstevel@tonic-gate 	 * If the text to be inserted is less than the number
7027c478bd9Sstevel@tonic-gate 	 * of doomed positions, then we don't need insert mode,
7037c478bd9Sstevel@tonic-gate 	 * rather we can just typeover.
7047c478bd9Sstevel@tonic-gate 	 */
7057c478bd9Sstevel@tonic-gate 	if (inssiz <= doomed) {
7067c478bd9Sstevel@tonic-gate 		endim();
7077c478bd9Sstevel@tonic-gate 		if (inscol != linend)
7087c478bd9Sstevel@tonic-gate 			doomed -= inssiz;
7097c478bd9Sstevel@tonic-gate 		do {
710*f6db9f27Scf46844 			(void) vputchar(c);
7117c478bd9Sstevel@tonic-gate 			if(c & QUOTE)
7127c478bd9Sstevel@tonic-gate 				inssiz--;
7137c478bd9Sstevel@tonic-gate 			else
7147c478bd9Sstevel@tonic-gate 				break;
7157c478bd9Sstevel@tonic-gate 		} while (inssiz);
716*f6db9f27Scf46844 		return (0);
7177c478bd9Sstevel@tonic-gate 	}
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 	/*
7207c478bd9Sstevel@tonic-gate 	 * Have to really do some insertion, thus
7217c478bd9Sstevel@tonic-gate 	 * stake out the bounds of the first following
7227c478bd9Sstevel@tonic-gate 	 * group of tabs, computing starting position,
7237c478bd9Sstevel@tonic-gate 	 * ending position, and the number of ``spaces'' therein
7247c478bd9Sstevel@tonic-gate 	 * so we can tell how much it will squish.
7257c478bd9Sstevel@tonic-gate 	 */
7267c478bd9Sstevel@tonic-gate 	tp = vtube0 + inscol;
7277c478bd9Sstevel@tonic-gate 	for (i = inscol; i < linend; i++)
7287c478bd9Sstevel@tonic-gate 		if (*tp++ & QUOTE) {
7297c478bd9Sstevel@tonic-gate 			--tp;
7307c478bd9Sstevel@tonic-gate 			break;
7317c478bd9Sstevel@tonic-gate 		}
7327c478bd9Sstevel@tonic-gate 	tabstart = tabend = i;
7337c478bd9Sstevel@tonic-gate 	tabslack = 0;
7347c478bd9Sstevel@tonic-gate 	while (tabend < linend) {
7357c478bd9Sstevel@tonic-gate 		wchar = *tp++;
7367c478bd9Sstevel@tonic-gate 		if ((wchar & QUOTE) == 0)
7377c478bd9Sstevel@tonic-gate 			break;
7387c478bd9Sstevel@tonic-gate 		if ((wchar & TRIM) == 0)
7397c478bd9Sstevel@tonic-gate 			tabslack++;
7407c478bd9Sstevel@tonic-gate 		tabsize++;
7417c478bd9Sstevel@tonic-gate 		tabend++;
7427c478bd9Sstevel@tonic-gate 	}
7437c478bd9Sstevel@tonic-gate 	tabsize = tabend - tabstart;
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 	/*
7467c478bd9Sstevel@tonic-gate 	 * For HP's and DM's, e.g. tabslack has no meaning.
7477c478bd9Sstevel@tonic-gate 	 */
7487c478bd9Sstevel@tonic-gate 	if (!insert_null_glitch)
7497c478bd9Sstevel@tonic-gate 		tabslack = 0;
7507c478bd9Sstevel@tonic-gate #ifdef IDEBUG
7517c478bd9Sstevel@tonic-gate 	if (trace) {
7527c478bd9Sstevel@tonic-gate 		fprintf(trace, "inscol %d, inssiz %d, tabstart %d, ",
7537c478bd9Sstevel@tonic-gate 			inscol, inssiz, tabstart);
7547c478bd9Sstevel@tonic-gate 		fprintf(trace, "tabend %d, tabslack %d, linend %d\n",
7557c478bd9Sstevel@tonic-gate 			tabend, tabslack, linend);
7567c478bd9Sstevel@tonic-gate 	}
7577c478bd9Sstevel@tonic-gate #endif
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 	/*
7607c478bd9Sstevel@tonic-gate 	 * The real work begins.
7617c478bd9Sstevel@tonic-gate 	 */
7627c478bd9Sstevel@tonic-gate 	slakused = 0;
7637c478bd9Sstevel@tonic-gate 	shft = 0;
7647c478bd9Sstevel@tonic-gate 	if (tabsize) {
7657c478bd9Sstevel@tonic-gate 		/*
7667c478bd9Sstevel@tonic-gate 		 * There are tabs on this line.
7677c478bd9Sstevel@tonic-gate 		 * If they need to expand, then the rest of the line
7687c478bd9Sstevel@tonic-gate 		 * will have to be shifted over.  In this case,
7697c478bd9Sstevel@tonic-gate 		 * we will need to make sure there are no ``spaces''
7707c478bd9Sstevel@tonic-gate 		 * in the rest of the line (on e.g. CONCEPT-100)
7717c478bd9Sstevel@tonic-gate 		 * and then grab another segment on the screen if this
7727c478bd9Sstevel@tonic-gate 		 * line is now deeper.  We then do the shift
7737c478bd9Sstevel@tonic-gate 		 * implied by the insertion.
7747c478bd9Sstevel@tonic-gate 		 */
7757c478bd9Sstevel@tonic-gate 		if (inssiz >= doomed + tabcol(tabstart, value(vi_TABSTOP)) - tabstart) {
7767c478bd9Sstevel@tonic-gate 			if (insert_null_glitch)
7777c478bd9Sstevel@tonic-gate 				vrigid();
7787c478bd9Sstevel@tonic-gate 			vneedpos(value(vi_TABSTOP));
7797c478bd9Sstevel@tonic-gate 			vishft();
7807c478bd9Sstevel@tonic-gate 		}
7817c478bd9Sstevel@tonic-gate 	} else if (inssiz > doomed)
7827c478bd9Sstevel@tonic-gate 		/*
7837c478bd9Sstevel@tonic-gate 		 * No tabs, but line may still get deeper.
7847c478bd9Sstevel@tonic-gate 		 */
7857c478bd9Sstevel@tonic-gate 		vneedpos(inssiz - doomed);
7867c478bd9Sstevel@tonic-gate 	/*
7877c478bd9Sstevel@tonic-gate 	 * Now put in the inserted characters.
7887c478bd9Sstevel@tonic-gate 	 */
7897c478bd9Sstevel@tonic-gate 	viin(c);
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 	/*
7927c478bd9Sstevel@tonic-gate 	 * Now put the cursor in its final resting place.
7937c478bd9Sstevel@tonic-gate 	 */
7947c478bd9Sstevel@tonic-gate 	destline = LINE(vcline);
7957c478bd9Sstevel@tonic-gate 	destcol = inscol + inssiz;
7967c478bd9Sstevel@tonic-gate 	vcsync();
797*f6db9f27Scf46844 	return (0);
7987c478bd9Sstevel@tonic-gate }
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate /*
8017c478bd9Sstevel@tonic-gate  * Rigidify the rest of the line after the first
8027c478bd9Sstevel@tonic-gate  * group of following tabs, typing blanks over ``spaces''.
8037c478bd9Sstevel@tonic-gate  */
804*f6db9f27Scf46844 void
805*f6db9f27Scf46844 vrigid(void)
8067c478bd9Sstevel@tonic-gate {
807*f6db9f27Scf46844 	int col;
808*f6db9f27Scf46844 	wchar_t *tp = vtube0 + tabend;
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate 	for (col = tabend; col < linend; col++)
8117c478bd9Sstevel@tonic-gate 		if ((*tp++ & TRIM) == 0) {
8127c478bd9Sstevel@tonic-gate 			endim();
8137c478bd9Sstevel@tonic-gate 			vgotoCL(col);
814*f6db9f27Scf46844 			(void) vputchar(' ' | QUOTE);
8157c478bd9Sstevel@tonic-gate 		}
8167c478bd9Sstevel@tonic-gate }
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate /*
8197c478bd9Sstevel@tonic-gate  * We need cnt more positions on this line.
8207c478bd9Sstevel@tonic-gate  * Open up new space on the screen (this may in fact be a
8217c478bd9Sstevel@tonic-gate  * screen rollup).
8227c478bd9Sstevel@tonic-gate  *
8237c478bd9Sstevel@tonic-gate  * On a dumb terminal we may infact redisplay the rest of the
8247c478bd9Sstevel@tonic-gate  * screen here brute force to keep it pretty.
8257c478bd9Sstevel@tonic-gate  */
826*f6db9f27Scf46844 void
827*f6db9f27Scf46844 vneedpos(int cnt)
8287c478bd9Sstevel@tonic-gate {
829*f6db9f27Scf46844 	int d = DEPTH(vcline);
830*f6db9f27Scf46844 	int rmdr = d * WCOLS - linend;
8317c478bd9Sstevel@tonic-gate 	if (cnt <= rmdr - insert_null_glitch)
8327c478bd9Sstevel@tonic-gate 		return;
8337c478bd9Sstevel@tonic-gate 	endim();
8347c478bd9Sstevel@tonic-gate 	vnpins(1);
8357c478bd9Sstevel@tonic-gate }
8367c478bd9Sstevel@tonic-gate 
837*f6db9f27Scf46844 void
838*f6db9f27Scf46844 vnpins(int dosync)
8397c478bd9Sstevel@tonic-gate {
840*f6db9f27Scf46844 	int d = DEPTH(vcline);
841*f6db9f27Scf46844 	int e;
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 	e = LINE(vcline) + DEPTH(vcline);
8447c478bd9Sstevel@tonic-gate 	if (e < LINE(vcline + 1)) {
8457c478bd9Sstevel@tonic-gate 		vigoto(e, 0);
8467c478bd9Sstevel@tonic-gate 		vclreol();
8477c478bd9Sstevel@tonic-gate 		return;
8487c478bd9Sstevel@tonic-gate 	}
8497c478bd9Sstevel@tonic-gate 	DEPTH(vcline)++;
8507c478bd9Sstevel@tonic-gate 	if (e < WECHO) {
8517c478bd9Sstevel@tonic-gate 		e = vglitchup(vcline, d);
8527c478bd9Sstevel@tonic-gate 		vigoto(e, 0); vclreol();
8537c478bd9Sstevel@tonic-gate 		if (dosync) {
8547c478bd9Sstevel@tonic-gate 			int (*Ooutchar)() = Outchar;
8557c478bd9Sstevel@tonic-gate 			Outchar = vputchar;
8567c478bd9Sstevel@tonic-gate 			vsync(e + 1);
8577c478bd9Sstevel@tonic-gate 			Outchar = Ooutchar;
8587c478bd9Sstevel@tonic-gate 		}
8597c478bd9Sstevel@tonic-gate 	} else {
8607c478bd9Sstevel@tonic-gate 		vup1();
8617c478bd9Sstevel@tonic-gate 		vigoto(WBOT, 0);
8627c478bd9Sstevel@tonic-gate 		vclreol();
8637c478bd9Sstevel@tonic-gate 	}
8647c478bd9Sstevel@tonic-gate 	vprepins();
8657c478bd9Sstevel@tonic-gate }
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate /*
8687c478bd9Sstevel@tonic-gate  * Do the shift of the next tabstop implied by
8697c478bd9Sstevel@tonic-gate  * insertion so it expands.
8707c478bd9Sstevel@tonic-gate  */
871*f6db9f27Scf46844 void
872*f6db9f27Scf46844 vishft(void)
8737c478bd9Sstevel@tonic-gate {
8747c478bd9Sstevel@tonic-gate 	int tshft = 0;
8757c478bd9Sstevel@tonic-gate 	int j;
876*f6db9f27Scf46844 	int i;
877*f6db9f27Scf46844 	wchar_t *tp = vtube0;
878*f6db9f27Scf46844 	wchar_t *up, wchar;
8797c478bd9Sstevel@tonic-gate 	short oldhold = hold;
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate 	shft = value(vi_TABSTOP);
8827c478bd9Sstevel@tonic-gate 	hold |= HOLDPUPD;
8837c478bd9Sstevel@tonic-gate 	if (!enter_insert_mode && !exit_insert_mode) {
8847c478bd9Sstevel@tonic-gate 		/*
8857c478bd9Sstevel@tonic-gate 		 * Dumb terminals are easy, we just have
8867c478bd9Sstevel@tonic-gate 		 * to retype the text.
8877c478bd9Sstevel@tonic-gate 		 */
8887c478bd9Sstevel@tonic-gate 		vigotoCL(tabend + shft);
8897c478bd9Sstevel@tonic-gate 		up = tp + tabend;
8907c478bd9Sstevel@tonic-gate 		for (i = tabend; i < linend; i++)
8917c478bd9Sstevel@tonic-gate 			if((wchar = *up++) != FILLER)
892*f6db9f27Scf46844 				(void) vputchar(wchar);
8937c478bd9Sstevel@tonic-gate 	} else if (insert_null_glitch) {
8947c478bd9Sstevel@tonic-gate 		/*
8957c478bd9Sstevel@tonic-gate 		 * CONCEPT-like terminals do most of the work for us,
8967c478bd9Sstevel@tonic-gate 		 * we don't have to muck with simulation of multi-line
8977c478bd9Sstevel@tonic-gate 		 * insert mode.  Some of the shifting may come for free
8987c478bd9Sstevel@tonic-gate 		 * also if the tabs don't have enough slack to take up
8997c478bd9Sstevel@tonic-gate 		 * all the inserted characters.
9007c478bd9Sstevel@tonic-gate 		 */
9017c478bd9Sstevel@tonic-gate 		i = shft;
9027c478bd9Sstevel@tonic-gate 		slakused = inssiz - doomed;
9037c478bd9Sstevel@tonic-gate 		if (slakused > tabslack) {
9047c478bd9Sstevel@tonic-gate 			i -= slakused - tabslack;
9057c478bd9Sstevel@tonic-gate 			slakused -= tabslack;
9067c478bd9Sstevel@tonic-gate 		}
9077c478bd9Sstevel@tonic-gate 		if (i > 0 && tabend != linend) {
9087c478bd9Sstevel@tonic-gate 			tshft = i;
9097c478bd9Sstevel@tonic-gate 			vgotoCL(tabend);
9107c478bd9Sstevel@tonic-gate 			goim();
9117c478bd9Sstevel@tonic-gate 			do
912*f6db9f27Scf46844 				(void) vputchar(' ' | QUOTE);
9137c478bd9Sstevel@tonic-gate 			while (--i);
9147c478bd9Sstevel@tonic-gate 		}
9157c478bd9Sstevel@tonic-gate 	} else {
9167c478bd9Sstevel@tonic-gate 		/*
9177c478bd9Sstevel@tonic-gate 		 * HP and Datamedia type terminals have to have multi-line
9187c478bd9Sstevel@tonic-gate 		 * insert faked.  Hack each segment after where we are
9197c478bd9Sstevel@tonic-gate 		 * (going backwards to where we are.)  We then can
9207c478bd9Sstevel@tonic-gate 		 * hack the segment where the end of the first following
9217c478bd9Sstevel@tonic-gate 		 * tab group is.
9227c478bd9Sstevel@tonic-gate 		 */
9237c478bd9Sstevel@tonic-gate 		for (j = DEPTH(vcline) - 1; j > (tabend + shft) / WCOLS; j--) {
9247c478bd9Sstevel@tonic-gate 			vgotoCL(j * WCOLS);
9257c478bd9Sstevel@tonic-gate 			goim();
9267c478bd9Sstevel@tonic-gate 			up = tp + j * WCOLS - shft;
9277c478bd9Sstevel@tonic-gate 			i = shft;
9287c478bd9Sstevel@tonic-gate 			do {
9297c478bd9Sstevel@tonic-gate 				wchar_t wchar;
9307c478bd9Sstevel@tonic-gate 				if (wchar = *up) {
9317c478bd9Sstevel@tonic-gate 					if(wchar != FILLER)
932*f6db9f27Scf46844 						(void) vputchar(wchar);
9337c478bd9Sstevel@tonic-gate 					up++;
9347c478bd9Sstevel@tonic-gate 				} else
9357c478bd9Sstevel@tonic-gate 					break;
9367c478bd9Sstevel@tonic-gate 			} while (--i);
9377c478bd9Sstevel@tonic-gate 		}
9387c478bd9Sstevel@tonic-gate 		vigotoCL(tabstart);
9397c478bd9Sstevel@tonic-gate 		i = shft - (inssiz - doomed);
9407c478bd9Sstevel@tonic-gate 		if (i > 0) {
9417c478bd9Sstevel@tonic-gate 			tabslack = inssiz - doomed;
9427c478bd9Sstevel@tonic-gate 			vcsync();
9437c478bd9Sstevel@tonic-gate 			goim();
9447c478bd9Sstevel@tonic-gate 			do
945*f6db9f27Scf46844 				(void) vputchar(' ');
9467c478bd9Sstevel@tonic-gate 			while (--i);
9477c478bd9Sstevel@tonic-gate 		}
9487c478bd9Sstevel@tonic-gate 	}
9497c478bd9Sstevel@tonic-gate 	/*
9507c478bd9Sstevel@tonic-gate 	 * Now do the data moving in the internal screen
9517c478bd9Sstevel@tonic-gate 	 * image which is common to all three cases.
9527c478bd9Sstevel@tonic-gate 	 */
9537c478bd9Sstevel@tonic-gate 	tp += linend;
9547c478bd9Sstevel@tonic-gate 	up = tp + shft;
9557c478bd9Sstevel@tonic-gate 	i = linend - tabend;
9567c478bd9Sstevel@tonic-gate 	if (i > 0)
9577c478bd9Sstevel@tonic-gate 		do
9587c478bd9Sstevel@tonic-gate 			*--up = *--tp;
9597c478bd9Sstevel@tonic-gate 		while (--i);
9607c478bd9Sstevel@tonic-gate 	if (insert_null_glitch && tshft) {
9617c478bd9Sstevel@tonic-gate 		i = tshft;
9627c478bd9Sstevel@tonic-gate 		do
9637c478bd9Sstevel@tonic-gate 			*--up = ' ' | QUOTE;
9647c478bd9Sstevel@tonic-gate 		while (--i);
9657c478bd9Sstevel@tonic-gate 	}
9667c478bd9Sstevel@tonic-gate 	hold = oldhold;
9677c478bd9Sstevel@tonic-gate }
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate /*
9707c478bd9Sstevel@tonic-gate  * Now do the insert of the characters (finally).
9717c478bd9Sstevel@tonic-gate  */
972*f6db9f27Scf46844 void
973*f6db9f27Scf46844 viin(wchar_t c)
9747c478bd9Sstevel@tonic-gate {
975*f6db9f27Scf46844 	wchar_t *tp, *up;
976*f6db9f27Scf46844 	int i, j;
977*f6db9f27Scf46844 	bool noim = 0;
9787c478bd9Sstevel@tonic-gate 	int remdoom;
9797c478bd9Sstevel@tonic-gate 	short oldhold = hold;
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 	hold |= HOLDPUPD;
9827c478bd9Sstevel@tonic-gate 	if (tabsize && (enter_insert_mode && exit_insert_mode) && inssiz - doomed > tabslack)
9837c478bd9Sstevel@tonic-gate 		/*
9847c478bd9Sstevel@tonic-gate 		 * There is a tab out there which will be affected
9857c478bd9Sstevel@tonic-gate 		 * by the insertion since there aren't enough doomed
9867c478bd9Sstevel@tonic-gate 		 * characters to take up all the insertion and we do
9877c478bd9Sstevel@tonic-gate 		 * have insert mode capability.
9887c478bd9Sstevel@tonic-gate 		 */
9897c478bd9Sstevel@tonic-gate 		if (inscol + doomed == tabstart) {
9907c478bd9Sstevel@tonic-gate 			/*
9917c478bd9Sstevel@tonic-gate 			 * The end of the doomed characters sits right at the
9927c478bd9Sstevel@tonic-gate 			 * start of the tabs, then we don't need to use insert
9937c478bd9Sstevel@tonic-gate 			 * mode; unless the tab has already been expanded
9947c478bd9Sstevel@tonic-gate 			 * in which case we MUST use insert mode.
9957c478bd9Sstevel@tonic-gate 			 */
9967c478bd9Sstevel@tonic-gate 			slakused = 0;
9977c478bd9Sstevel@tonic-gate 			noim = !shft;
9987c478bd9Sstevel@tonic-gate 		} else {
9997c478bd9Sstevel@tonic-gate 			/*
10007c478bd9Sstevel@tonic-gate 			 * The last really special case to handle is case
10017c478bd9Sstevel@tonic-gate 			 * where the tab is just sitting there and doesn't
10027c478bd9Sstevel@tonic-gate 			 * have enough slack to let the insertion take
10037c478bd9Sstevel@tonic-gate 			 * place without shifting the rest of the line
10047c478bd9Sstevel@tonic-gate 			 * over.  In this case we have to go out and
10057c478bd9Sstevel@tonic-gate 			 * delete some characters of the tab before we start
10067c478bd9Sstevel@tonic-gate 			 * or the answer will be wrong, as the rest of the
10077c478bd9Sstevel@tonic-gate 			 * line will have been shifted.  This code means
10087c478bd9Sstevel@tonic-gate 			 * that terminals with only insert character (no
10097c478bd9Sstevel@tonic-gate 			 * delete character) won't work correctly.
10107c478bd9Sstevel@tonic-gate 			 */
10117c478bd9Sstevel@tonic-gate 			i = inssiz - doomed - tabslack - slakused;
10127c478bd9Sstevel@tonic-gate 			i %= value(vi_TABSTOP);
10137c478bd9Sstevel@tonic-gate 			if (i > 0) {
10147c478bd9Sstevel@tonic-gate 				vgotoCL(tabstart);
10157c478bd9Sstevel@tonic-gate 				godm();
10167c478bd9Sstevel@tonic-gate 				for (i = inssiz - doomed - tabslack; i > 0; i--)
10177c478bd9Sstevel@tonic-gate 					vputp(delete_character, DEPTH(vcline));
10187c478bd9Sstevel@tonic-gate 				enddm();
10197c478bd9Sstevel@tonic-gate 			}
10207c478bd9Sstevel@tonic-gate 		}
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate 	/*
10237c478bd9Sstevel@tonic-gate 	 * Now put out the characters of the actual insertion.
10247c478bd9Sstevel@tonic-gate 	 */
10257c478bd9Sstevel@tonic-gate 	vigotoCL(inscol);
10267c478bd9Sstevel@tonic-gate 	remdoom = doomed;
10277c478bd9Sstevel@tonic-gate 	for (i = inssiz; i > 0; i--) {
10287c478bd9Sstevel@tonic-gate 		if (remdoom > 0) {
10297c478bd9Sstevel@tonic-gate 			remdoom--;
10307c478bd9Sstevel@tonic-gate 			endim();
10317c478bd9Sstevel@tonic-gate 		} else if (noim)
10327c478bd9Sstevel@tonic-gate 			endim();
10337c478bd9Sstevel@tonic-gate 		else if (enter_insert_mode && exit_insert_mode) {
10347c478bd9Sstevel@tonic-gate 			vcsync();
10357c478bd9Sstevel@tonic-gate 			goim();
10367c478bd9Sstevel@tonic-gate 		}
1037*f6db9f27Scf46844 		(void) vputchar(c);
10387c478bd9Sstevel@tonic-gate 		if((c & QUOTE) == 0)
10397c478bd9Sstevel@tonic-gate 			break;
10407c478bd9Sstevel@tonic-gate 	}
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate 	if (!enter_insert_mode || !exit_insert_mode) {
10437c478bd9Sstevel@tonic-gate 		/*
10447c478bd9Sstevel@tonic-gate 		 * We are a dumb terminal; brute force update
10457c478bd9Sstevel@tonic-gate 		 * the rest of the line; this is very much an n^^2 process,
10467c478bd9Sstevel@tonic-gate 		 * and totally unreasonable at low speed.
10477c478bd9Sstevel@tonic-gate 		 *
10487c478bd9Sstevel@tonic-gate 		 * You asked for it, you get it.
10497c478bd9Sstevel@tonic-gate 		 */
10507c478bd9Sstevel@tonic-gate 		int width;
10517c478bd9Sstevel@tonic-gate 		tp = vtube0 + inscol + doomed;
10527c478bd9Sstevel@tonic-gate 		for (i = inscol + doomed; i < tabstart; i++) {
10537c478bd9Sstevel@tonic-gate 			if(*tp != FILLER)
1054*f6db9f27Scf46844 				(void) vputchar(*tp);
10557c478bd9Sstevel@tonic-gate 			tp++;
10567c478bd9Sstevel@tonic-gate 		}
10577c478bd9Sstevel@tonic-gate 		hold = oldhold;
10587c478bd9Sstevel@tonic-gate 		vigotoCL(tabstart + inssiz - doomed);
10597c478bd9Sstevel@tonic-gate 		for (i = tabsize - (inssiz - doomed) + shft; i > 0; i--)
1060*f6db9f27Scf46844 			(void) vputchar(' ' | QUOTE);
10617c478bd9Sstevel@tonic-gate 	} else {
10627c478bd9Sstevel@tonic-gate 		if (!insert_null_glitch) {
10637c478bd9Sstevel@tonic-gate 			/*
10647c478bd9Sstevel@tonic-gate 			 * On terminals without multi-line
10657c478bd9Sstevel@tonic-gate 			 * insert in the hardware, we must go fix the segments
10667c478bd9Sstevel@tonic-gate 			 * between the inserted text and the following
10677c478bd9Sstevel@tonic-gate 			 * tabs, if they are on different lines.
10687c478bd9Sstevel@tonic-gate 			 *
10697c478bd9Sstevel@tonic-gate 			 * Aaargh.
10707c478bd9Sstevel@tonic-gate 			 */
10717c478bd9Sstevel@tonic-gate 			tp = vtube0;
10727c478bd9Sstevel@tonic-gate 			for (j = (inscol + inssiz - 1) / WCOLS + 1;
10737c478bd9Sstevel@tonic-gate 			    j <= (tabstart + inssiz - doomed - 1) / WCOLS; j++) {
10747c478bd9Sstevel@tonic-gate 				vgotoCL(j * WCOLS);
10757c478bd9Sstevel@tonic-gate 				i = inssiz - doomed;
10767c478bd9Sstevel@tonic-gate 				up = tp + j * WCOLS - i;
10777c478bd9Sstevel@tonic-gate 				goim();
10787c478bd9Sstevel@tonic-gate 				do {
10797c478bd9Sstevel@tonic-gate 					wchar_t wchar;
10807c478bd9Sstevel@tonic-gate 					if((wchar = *up++) != FILLER)
1081*f6db9f27Scf46844 						(void) vputchar(wchar);
10827c478bd9Sstevel@tonic-gate 				} while (--i && *up);
10837c478bd9Sstevel@tonic-gate 			}
10847c478bd9Sstevel@tonic-gate 		} else {
10857c478bd9Sstevel@tonic-gate 			/*
10867c478bd9Sstevel@tonic-gate 			 * On terminals with multi line inserts,
10877c478bd9Sstevel@tonic-gate 			 * life is simpler, just reflect eating of
10887c478bd9Sstevel@tonic-gate 			 * the slack.
10897c478bd9Sstevel@tonic-gate 			 */
10907c478bd9Sstevel@tonic-gate 			tp = vtube0 + tabend;
10917c478bd9Sstevel@tonic-gate 			for (i = tabsize - (inssiz - doomed); i >= 0; i--) {
10927c478bd9Sstevel@tonic-gate 				if ((*--tp & (QUOTE|TRIM)) == QUOTE) {
10937c478bd9Sstevel@tonic-gate 					--tabslack;
10947c478bd9Sstevel@tonic-gate 					if (tabslack >= slakused)
10957c478bd9Sstevel@tonic-gate 						continue;
10967c478bd9Sstevel@tonic-gate 				}
10977c478bd9Sstevel@tonic-gate 				*tp = ' ' | QUOTE;
10987c478bd9Sstevel@tonic-gate 			}
10997c478bd9Sstevel@tonic-gate 		}
11007c478bd9Sstevel@tonic-gate 		/*
11017c478bd9Sstevel@tonic-gate 		 * Blank out the shifted positions to be tab positions.
11027c478bd9Sstevel@tonic-gate 		 */
11037c478bd9Sstevel@tonic-gate 		if (shft) {
11047c478bd9Sstevel@tonic-gate 			tp = vtube0 + tabend + shft;
11057c478bd9Sstevel@tonic-gate 			for (i = tabsize - (inssiz - doomed) + shft; i > 0; i--)
11067c478bd9Sstevel@tonic-gate 				if ((*--tp & QUOTE) == 0)
11077c478bd9Sstevel@tonic-gate 					*tp = ' ' | QUOTE;
11087c478bd9Sstevel@tonic-gate 		}
11097c478bd9Sstevel@tonic-gate 	}
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate 	/*
11127c478bd9Sstevel@tonic-gate 	 * Finally, complete the screen image update
11137c478bd9Sstevel@tonic-gate 	 * to reflect the insertion.
11147c478bd9Sstevel@tonic-gate 	 */
11157c478bd9Sstevel@tonic-gate 	hold = oldhold;
11167c478bd9Sstevel@tonic-gate 	tp = vtube0 + tabstart; up = tp + inssiz - doomed;
11177c478bd9Sstevel@tonic-gate 	for (i = tabstart; i > inscol + doomed; i--)
11187c478bd9Sstevel@tonic-gate 		*--up = *--tp;
11197c478bd9Sstevel@tonic-gate 	for (i = inssiz; i > 0; i--)
11207c478bd9Sstevel@tonic-gate 		if((c & QUOTE) == 0) {
11217c478bd9Sstevel@tonic-gate 			int width = wcwidth(c);
11227c478bd9Sstevel@tonic-gate 			if (width < 0)
11237c478bd9Sstevel@tonic-gate 				width = 0;
11247c478bd9Sstevel@tonic-gate 			up -= width;
11257c478bd9Sstevel@tonic-gate 			*up++ = c;
11267c478bd9Sstevel@tonic-gate 			if(width)
11277c478bd9Sstevel@tonic-gate 				while(--width)
11287c478bd9Sstevel@tonic-gate 					*up++ = FILLER;
11297c478bd9Sstevel@tonic-gate 			break;
11307c478bd9Sstevel@tonic-gate 		}
11317c478bd9Sstevel@tonic-gate 		else
11327c478bd9Sstevel@tonic-gate 			*--up = c;
11337c478bd9Sstevel@tonic-gate 	doomed = 0;
11347c478bd9Sstevel@tonic-gate }
11357c478bd9Sstevel@tonic-gate 
11367c478bd9Sstevel@tonic-gate /*
11377c478bd9Sstevel@tonic-gate  * Go into ``delete mode''.  If the
11387c478bd9Sstevel@tonic-gate  * sequence which goes into delete mode
11397c478bd9Sstevel@tonic-gate  * is the same as that which goes into insert
11407c478bd9Sstevel@tonic-gate  * mode, then we are in delete mode already.
11417c478bd9Sstevel@tonic-gate  */
1142*f6db9f27Scf46844 void
1143*f6db9f27Scf46844 godm(void)
11447c478bd9Sstevel@tonic-gate {
11457c478bd9Sstevel@tonic-gate 
11467c478bd9Sstevel@tonic-gate 	if (insmode) {
11477c478bd9Sstevel@tonic-gate 		if (eq(enter_delete_mode, enter_insert_mode))
11487c478bd9Sstevel@tonic-gate 			return;
11497c478bd9Sstevel@tonic-gate 		endim();
11507c478bd9Sstevel@tonic-gate 	}
11517c478bd9Sstevel@tonic-gate 	vputp(enter_delete_mode, 0);
11527c478bd9Sstevel@tonic-gate }
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate /*
11557c478bd9Sstevel@tonic-gate  * If we are coming out of delete mode, but
11567c478bd9Sstevel@tonic-gate  * delete and insert mode end with the same sequence,
11577c478bd9Sstevel@tonic-gate  * it wins to pretend we are now in insert mode,
11587c478bd9Sstevel@tonic-gate  * since we will likely want to be there again soon
11597c478bd9Sstevel@tonic-gate  * if we just moved over to delete space from part of
11607c478bd9Sstevel@tonic-gate  * a tab (above).
11617c478bd9Sstevel@tonic-gate  */
1162*f6db9f27Scf46844 void
1163*f6db9f27Scf46844 enddm(void)
11647c478bd9Sstevel@tonic-gate {
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate 	if (eq(enter_delete_mode, enter_insert_mode)) {
11677c478bd9Sstevel@tonic-gate 		insmode = 1;
11687c478bd9Sstevel@tonic-gate 		return;
11697c478bd9Sstevel@tonic-gate 	}
11707c478bd9Sstevel@tonic-gate 	vputp(exit_delete_mode, 0);
11717c478bd9Sstevel@tonic-gate }
11727c478bd9Sstevel@tonic-gate 
11737c478bd9Sstevel@tonic-gate /*
11747c478bd9Sstevel@tonic-gate  * In and out of insert mode.
11757c478bd9Sstevel@tonic-gate  * Note that the code here demands that there be
11767c478bd9Sstevel@tonic-gate  * a string for insert mode (the null string) even
11777c478bd9Sstevel@tonic-gate  * if the terminal does all insertions a single character
11787c478bd9Sstevel@tonic-gate  * at a time, since it branches based on whether enter_insert_mode is null.
11797c478bd9Sstevel@tonic-gate  */
1180*f6db9f27Scf46844 void
1181*f6db9f27Scf46844 goim(void)
11827c478bd9Sstevel@tonic-gate {
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate 	if (!insmode)
11857c478bd9Sstevel@tonic-gate 		vputp(enter_insert_mode, 0);
11867c478bd9Sstevel@tonic-gate 	insmode = 1;
11877c478bd9Sstevel@tonic-gate }
11887c478bd9Sstevel@tonic-gate 
1189*f6db9f27Scf46844 void
1190*f6db9f27Scf46844 endim(void)
11917c478bd9Sstevel@tonic-gate {
11927c478bd9Sstevel@tonic-gate 
11937c478bd9Sstevel@tonic-gate 	if (insmode) {
11947c478bd9Sstevel@tonic-gate 		vputp(exit_insert_mode, 0);
11957c478bd9Sstevel@tonic-gate 		insmode = 0;
11967c478bd9Sstevel@tonic-gate 	}
11977c478bd9Sstevel@tonic-gate }
11987c478bd9Sstevel@tonic-gate 
11997c478bd9Sstevel@tonic-gate /*
12007c478bd9Sstevel@tonic-gate  * Put the character c on the screen at the current cursor position.
12017c478bd9Sstevel@tonic-gate  * This routine handles wraparound and scrolling and understands not
12027c478bd9Sstevel@tonic-gate  * to roll when splitw is set, i.e. we are working in the echo area.
12037c478bd9Sstevel@tonic-gate  * There is a bunch of hacking here dealing with the difference between
12047c478bd9Sstevel@tonic-gate  * QUOTE, QUOTE|' ', and ' ' for CONCEPT-100 like terminals, and also
12057c478bd9Sstevel@tonic-gate  * code to deal with terminals which overstrike, including CRT's where
12067c478bd9Sstevel@tonic-gate  * you can erase overstrikes with some work.  CRT's which do underlining
12077c478bd9Sstevel@tonic-gate  * implicitly which has to be erased (like CONCEPTS) are also handled.
12087c478bd9Sstevel@tonic-gate  */
1209*f6db9f27Scf46844 int
1210*f6db9f27Scf46844 vputchar(wchar_t c)
12117c478bd9Sstevel@tonic-gate {
12127c478bd9Sstevel@tonic-gate 	unsigned char multic[MULTI_BYTE_MAX];
1213*f6db9f27Scf46844 	wchar_t *tp;
1214*f6db9f27Scf46844 	int d, length, length2, bytelength;
1215*f6db9f27Scf46844 	unsigned char *p;
12167c478bd9Sstevel@tonic-gate 	short oldhold = hold;
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 	c &= (QUOTE|TRIM);
12197c478bd9Sstevel@tonic-gate #ifdef TRACE
12207c478bd9Sstevel@tonic-gate 	if (trace) {
12217c478bd9Sstevel@tonic-gate 		tracec(c);
12227c478bd9Sstevel@tonic-gate 	}
12237c478bd9Sstevel@tonic-gate #endif
12247c478bd9Sstevel@tonic-gate 	if(c & QUOTE)
12257c478bd9Sstevel@tonic-gate 		length = 1;
12267c478bd9Sstevel@tonic-gate 	else
12277c478bd9Sstevel@tonic-gate 		if ((length = wcwidth(c)) < 0)
12287c478bd9Sstevel@tonic-gate 			length = 0;
12297c478bd9Sstevel@tonic-gate 	/* Fix problem of >79 chars on echo line. */
12307c478bd9Sstevel@tonic-gate 	if (destcol >= WCOLS-1 && splitw && destline == WECHO)
12317c478bd9Sstevel@tonic-gate 		pofix();
12327c478bd9Sstevel@tonic-gate 	if (destcol >= WCOLS) {
12337c478bd9Sstevel@tonic-gate 		destline += destcol / WCOLS;
12347c478bd9Sstevel@tonic-gate 		destcol %= WCOLS;
12357c478bd9Sstevel@tonic-gate 	}
12367c478bd9Sstevel@tonic-gate 	if (destline > WBOT && (!splitw || destline > WECHO))
12377c478bd9Sstevel@tonic-gate 		vrollup(destline);
12387c478bd9Sstevel@tonic-gate 	if (destline < 0)
12397c478bd9Sstevel@tonic-gate 		error(gettext("Line too long to fit on screen"));
12407c478bd9Sstevel@tonic-gate 	if(destcol + length - 1 >= WCOLS) {
12417c478bd9Sstevel@tonic-gate 		/* print out split multibyte character using '>' */
12427c478bd9Sstevel@tonic-gate 		hold |= HOLDPUPD;
12437c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC
12447c478bd9Sstevel@tonic-gate 		while(length--)
1245*f6db9f27Scf46844 			(void) vputchar('>');
12467c478bd9Sstevel@tonic-gate #else
12477c478bd9Sstevel@tonic-gate 		if (mc_wrap == 0)
12487c478bd9Sstevel@tonic-gate 			while(length--)
1249*f6db9f27Scf46844 				(void) vputchar(mc_filler);
12507c478bd9Sstevel@tonic-gate 		else {
12517c478bd9Sstevel@tonic-gate 			for (length = WCOLS - destcol; length; length--)
1252*f6db9f27Scf46844 				(void) vputchar(mc_filler);
12537c478bd9Sstevel@tonic-gate 			hold = oldhold;
12547c478bd9Sstevel@tonic-gate 			if ((length = wcwidth(c)) < 0)
12557c478bd9Sstevel@tonic-gate 				length = 0;
1256*f6db9f27Scf46844 			(void) vputchar(c);
12577c478bd9Sstevel@tonic-gate 		}
12587c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */
12597c478bd9Sstevel@tonic-gate 		hold = oldhold;
1260*f6db9f27Scf46844 		return (0);
12617c478bd9Sstevel@tonic-gate 	}
12627c478bd9Sstevel@tonic-gate 	tp = vtube[destline] + destcol;
12637c478bd9Sstevel@tonic-gate 	switch (c) {
12647c478bd9Sstevel@tonic-gate 
12657c478bd9Sstevel@tonic-gate 	case '\t':
12667c478bd9Sstevel@tonic-gate 		vgotab();
1267*f6db9f27Scf46844 		return (0);
12687c478bd9Sstevel@tonic-gate 
12697c478bd9Sstevel@tonic-gate 	case ' ':
12707c478bd9Sstevel@tonic-gate 		/*
12717c478bd9Sstevel@tonic-gate 		 * We can get away without printing a space in a number
12727c478bd9Sstevel@tonic-gate 		 * of cases, but not always.  We get away with doing nothing
12737c478bd9Sstevel@tonic-gate 		 * if we are not in insert mode, and not on a CONCEPT-100
12747c478bd9Sstevel@tonic-gate 		 * like terminal, and either not in hardcopy open or in hardcopy
12757c478bd9Sstevel@tonic-gate 		 * open on a terminal with no overstriking, provided,
12767c478bd9Sstevel@tonic-gate 		 * in all cases, that nothing has ever been displayed
12777c478bd9Sstevel@tonic-gate 		 * at this position.  Ugh.
12787c478bd9Sstevel@tonic-gate 		 */
12797c478bd9Sstevel@tonic-gate 		if (!insmode && !insert_null_glitch && (state != HARDOPEN || over_strike) && (*tp&TRIM) == 0) {
12807c478bd9Sstevel@tonic-gate 			*tp = ' ';
12817c478bd9Sstevel@tonic-gate 			destcol++;
1282*f6db9f27Scf46844 			return (0);
12837c478bd9Sstevel@tonic-gate 		}
12847c478bd9Sstevel@tonic-gate 		goto def;
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate 	case QUOTE:
12877c478bd9Sstevel@tonic-gate 		if (insmode) {
12887c478bd9Sstevel@tonic-gate 			/*
12897c478bd9Sstevel@tonic-gate 			 * When in insert mode, tabs have to expand
12907c478bd9Sstevel@tonic-gate 			 * to real, printed blanks.
12917c478bd9Sstevel@tonic-gate 			 */
12927c478bd9Sstevel@tonic-gate 			c = ' ' | QUOTE;
12937c478bd9Sstevel@tonic-gate 			goto def;
12947c478bd9Sstevel@tonic-gate 		}
12957c478bd9Sstevel@tonic-gate 		if (*tp == 0) {
12967c478bd9Sstevel@tonic-gate 			/*
12977c478bd9Sstevel@tonic-gate 			 * A ``space''.
12987c478bd9Sstevel@tonic-gate 			 */
12997c478bd9Sstevel@tonic-gate 			if ((hold & HOLDPUPD) == 0)
13007c478bd9Sstevel@tonic-gate 				*tp = QUOTE;
13017c478bd9Sstevel@tonic-gate 			destcol++;
1302*f6db9f27Scf46844 			return (0);
13037c478bd9Sstevel@tonic-gate 		}
13047c478bd9Sstevel@tonic-gate 		/*
13057c478bd9Sstevel@tonic-gate 		 * A ``space'' ontop of a part of a tab.
13067c478bd9Sstevel@tonic-gate 		 */
13077c478bd9Sstevel@tonic-gate 		if (*tp & QUOTE) {
13087c478bd9Sstevel@tonic-gate 			destcol++;
1309*f6db9f27Scf46844 			return (0);
13107c478bd9Sstevel@tonic-gate 		}
13117c478bd9Sstevel@tonic-gate 		c = ' ' | QUOTE;
13127c478bd9Sstevel@tonic-gate 		/* fall into ... */
13137c478bd9Sstevel@tonic-gate 
13147c478bd9Sstevel@tonic-gate def:
13157c478bd9Sstevel@tonic-gate 	default:
13167c478bd9Sstevel@tonic-gate 		d = *tp & TRIM;
13177c478bd9Sstevel@tonic-gate 		/*
13187c478bd9Sstevel@tonic-gate 		 * Now get away with doing nothing if the characters
13197c478bd9Sstevel@tonic-gate 		 * are the same, provided we are not in insert mode
13207c478bd9Sstevel@tonic-gate 		 * and if we are in hardopen, that the terminal has overstrike.
13217c478bd9Sstevel@tonic-gate 		 */
13227c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC
13237c478bd9Sstevel@tonic-gate 		if (rewrite == _OFF && d == (c & TRIM) && !insmode && (state != HARDOPEN || over_strike)) {
13247c478bd9Sstevel@tonic-gate #else
13257c478bd9Sstevel@tonic-gate 		if (rewrite == _OFF && d == (c & TRIM) && !insmode &&
13267c478bd9Sstevel@tonic-gate 		    (state != HARDOPEN || over_strike) && !multibyte) {
13277c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */
13287c478bd9Sstevel@tonic-gate 			if ((hold & HOLDPUPD) == 0) {
13297c478bd9Sstevel@tonic-gate 				*tp++ = c;
13307c478bd9Sstevel@tonic-gate 				if(length) {
13317c478bd9Sstevel@tonic-gate 					length2 = length;
13327c478bd9Sstevel@tonic-gate 					while(--length2)
13337c478bd9Sstevel@tonic-gate 						*tp++ = FILLER;
13347c478bd9Sstevel@tonic-gate 				}
13357c478bd9Sstevel@tonic-gate 			}
13367c478bd9Sstevel@tonic-gate 			destcol += length;
1337*f6db9f27Scf46844 			return (0);
13387c478bd9Sstevel@tonic-gate 		}
13397c478bd9Sstevel@tonic-gate 		/*
13407c478bd9Sstevel@tonic-gate 		 * Backwards looking optimization.
13417c478bd9Sstevel@tonic-gate 		 * The low level cursor motion routines will use
13427c478bd9Sstevel@tonic-gate 		 * a cursor motion right sequence to step 1 character
13437c478bd9Sstevel@tonic-gate 		 * right.  On, e.g., a DM3025A this is 2 characters
13447c478bd9Sstevel@tonic-gate 		 * and printing is noticeably slower at 300 baud.
13457c478bd9Sstevel@tonic-gate 		 * Since the low level routines are not allowed to use
13467c478bd9Sstevel@tonic-gate 		 * spaces for positioning, we discover the common
13477c478bd9Sstevel@tonic-gate 		 * case of a single space here and force a space
13487c478bd9Sstevel@tonic-gate 		 * to be printed.
13497c478bd9Sstevel@tonic-gate 		 */
13507c478bd9Sstevel@tonic-gate 		if (destcol == outcol + 1 && tp[-1] == ' ' && outline == destline) {
1351*f6db9f27Scf46844 			(void) vputc(' ');
13527c478bd9Sstevel@tonic-gate 			outcol++;
13537c478bd9Sstevel@tonic-gate 		}
13547c478bd9Sstevel@tonic-gate 
13557c478bd9Sstevel@tonic-gate 		/*
13567c478bd9Sstevel@tonic-gate 		 * This is an inline expansion a call to vcsync() dictated
13577c478bd9Sstevel@tonic-gate 		 * by high frequency in a profile.
13587c478bd9Sstevel@tonic-gate 		 */
13597c478bd9Sstevel@tonic-gate 		if (outcol != destcol || outline != destline)
13607c478bd9Sstevel@tonic-gate 			vgoto(destline, destcol);
13617c478bd9Sstevel@tonic-gate 
13627c478bd9Sstevel@tonic-gate 		/*
13637c478bd9Sstevel@tonic-gate 		 * Deal with terminals which have overstrike.
13647c478bd9Sstevel@tonic-gate 		 * We handle erasing general overstrikes, erasing
13657c478bd9Sstevel@tonic-gate 		 * underlines on terminals (such as CONCEPTS) which
13667c478bd9Sstevel@tonic-gate 		 * do underlining correctly automatically (e.g. on nroff
13677c478bd9Sstevel@tonic-gate 		 * output), and remembering, in hardcopy mode,
13687c478bd9Sstevel@tonic-gate 		 * that we have overstruct something.
13697c478bd9Sstevel@tonic-gate 		 */
13707c478bd9Sstevel@tonic-gate 		if (!insmode && d && d != ' ' && d != (c & TRIM)) {
13717c478bd9Sstevel@tonic-gate 			if (erase_overstrike && (over_strike || transparent_underline && (c == '_' || d == '_'))) {
1372*f6db9f27Scf46844 				(void) vputc(' ');
13737c478bd9Sstevel@tonic-gate 				outcol++, destcol++;
13747c478bd9Sstevel@tonic-gate 				back1();
13757c478bd9Sstevel@tonic-gate 			} else
13767c478bd9Sstevel@tonic-gate 				rubble = 1;
13777c478bd9Sstevel@tonic-gate 		}
13787c478bd9Sstevel@tonic-gate 
13797c478bd9Sstevel@tonic-gate 		/*
13807c478bd9Sstevel@tonic-gate 		 * Unless we are just bashing characters around for
13817c478bd9Sstevel@tonic-gate 		 * inner working of insert mode, update the display.
13827c478bd9Sstevel@tonic-gate 		 */
13837c478bd9Sstevel@tonic-gate 		if ((hold & HOLDPUPD) == 0) {
13847c478bd9Sstevel@tonic-gate 			*tp++ = c;
13857c478bd9Sstevel@tonic-gate 			length2 = length;
13867c478bd9Sstevel@tonic-gate 			/* put in filler characters */
13877c478bd9Sstevel@tonic-gate 			if(length)
13887c478bd9Sstevel@tonic-gate 				while(--length2)
13897c478bd9Sstevel@tonic-gate 					*tp++ = FILLER;
13907c478bd9Sstevel@tonic-gate 
13917c478bd9Sstevel@tonic-gate 		}
13927c478bd9Sstevel@tonic-gate 		/*
13937c478bd9Sstevel@tonic-gate 		 * In insert mode, put out the insert_character sequence, padded
13947c478bd9Sstevel@tonic-gate 		 * based on the depth of the current line.
13957c478bd9Sstevel@tonic-gate 		 * A terminal which had no real insert mode, rather
13967c478bd9Sstevel@tonic-gate 		 * opening a character position at a time could do this.
13977c478bd9Sstevel@tonic-gate 		 * Actually should use depth to end of current line
13987c478bd9Sstevel@tonic-gate 		 * but this rarely matters.
13997c478bd9Sstevel@tonic-gate 		 */
14007c478bd9Sstevel@tonic-gate 		if (insmode)
14017c478bd9Sstevel@tonic-gate 			vputp(insert_character, DEPTH(vcline));
14027c478bd9Sstevel@tonic-gate 		c &= TRIM;
14037c478bd9Sstevel@tonic-gate 		bytelength = wctomb((char *)multic, c);
14047c478bd9Sstevel@tonic-gate 		p = multic;
14057c478bd9Sstevel@tonic-gate 		while(bytelength--)
1406*f6db9f27Scf46844 			(void) vputc(*p++);
14077c478bd9Sstevel@tonic-gate 
14087c478bd9Sstevel@tonic-gate 		/*
14097c478bd9Sstevel@tonic-gate 		 * In insert mode, insert_padding is a post insert pad.
14107c478bd9Sstevel@tonic-gate 		 */
14117c478bd9Sstevel@tonic-gate 		if (insmode)
14127c478bd9Sstevel@tonic-gate 			vputp(insert_padding, DEPTH(vcline));
14137c478bd9Sstevel@tonic-gate 		destcol += length;
14147c478bd9Sstevel@tonic-gate 		outcol += length;
14157c478bd9Sstevel@tonic-gate 
14167c478bd9Sstevel@tonic-gate 		/*
14177c478bd9Sstevel@tonic-gate 		 * CONCEPT braindamage in early models:  after a wraparound
14187c478bd9Sstevel@tonic-gate 		 * the next newline is eaten.  It's hungry so we just
14197c478bd9Sstevel@tonic-gate 		 * feed it now rather than worrying about it.
14207c478bd9Sstevel@tonic-gate 		 * Fixed to use	return linefeed to work right
14217c478bd9Sstevel@tonic-gate 		 * on vt100/tab132 as well as concept.
14227c478bd9Sstevel@tonic-gate 		 */
14237c478bd9Sstevel@tonic-gate 		if (eat_newline_glitch && outcol % WCOLS == 0) {
1424*f6db9f27Scf46844 			(void) vputc('\r');
1425*f6db9f27Scf46844 			(void) vputc('\n');
14267c478bd9Sstevel@tonic-gate 		}
14277c478bd9Sstevel@tonic-gate 	}
1428*f6db9f27Scf46844 	return (0);
14297c478bd9Sstevel@tonic-gate }
14307c478bd9Sstevel@tonic-gate 
14317c478bd9Sstevel@tonic-gate /*
14327c478bd9Sstevel@tonic-gate  * Delete display positions stcol through endcol.
14337c478bd9Sstevel@tonic-gate  * Amount of use of special terminal features here is limited.
14347c478bd9Sstevel@tonic-gate  */
1435*f6db9f27Scf46844 void
1436*f6db9f27Scf46844 physdc(int stcol, int endcol)
14377c478bd9Sstevel@tonic-gate {
1438*f6db9f27Scf46844 	wchar_t *tp, *up;
14397c478bd9Sstevel@tonic-gate 	wchar_t *tpe;
1440*f6db9f27Scf46844 	int i;
1441*f6db9f27Scf46844 	int nc = endcol - stcol;
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate #ifdef IDEBUG
14447c478bd9Sstevel@tonic-gate 	if (trace)
14457c478bd9Sstevel@tonic-gate 		tfixnl(), fprintf(trace, "physdc(%d, %d)\n", stcol, endcol);
14467c478bd9Sstevel@tonic-gate #endif
14477c478bd9Sstevel@tonic-gate 	if (!delete_character || nc <= 0)
14487c478bd9Sstevel@tonic-gate 		return;
14497c478bd9Sstevel@tonic-gate 	if (insert_null_glitch) {
14507c478bd9Sstevel@tonic-gate 		/*
14517c478bd9Sstevel@tonic-gate 		 * CONCEPT-100 like terminal.
14527c478bd9Sstevel@tonic-gate 		 * If there are any ``spaces'' in the material to be
14537c478bd9Sstevel@tonic-gate 		 * deleted, then this is too hard, just retype.
14547c478bd9Sstevel@tonic-gate 		 */
14557c478bd9Sstevel@tonic-gate 		vprepins();
14567c478bd9Sstevel@tonic-gate 		up = vtube0 + stcol;
14577c478bd9Sstevel@tonic-gate 		i = nc;
14587c478bd9Sstevel@tonic-gate 		do
14597c478bd9Sstevel@tonic-gate 			if ((*up++ & (QUOTE|TRIM)) == QUOTE)
14607c478bd9Sstevel@tonic-gate 				return;
14617c478bd9Sstevel@tonic-gate 		while (--i);
14627c478bd9Sstevel@tonic-gate 		i = 2 * nc;
14637c478bd9Sstevel@tonic-gate 		do
14647c478bd9Sstevel@tonic-gate 			if (*up == 0 || (*up++ & QUOTE) == QUOTE)
14657c478bd9Sstevel@tonic-gate 				return;
14667c478bd9Sstevel@tonic-gate 		while (--i);
14677c478bd9Sstevel@tonic-gate 		vgotoCL(stcol);
14687c478bd9Sstevel@tonic-gate 	} else {
14697c478bd9Sstevel@tonic-gate 		/*
14707c478bd9Sstevel@tonic-gate 		 * HP like delete mode.
14717c478bd9Sstevel@tonic-gate 		 * Compute how much text we are moving over by deleting.
14727c478bd9Sstevel@tonic-gate 		 * If it appears to be faster to just retype
14737c478bd9Sstevel@tonic-gate 		 * the line, do nothing and that will be done later.
14747c478bd9Sstevel@tonic-gate 		 * We are assuming 2 output characters per deleted
14757c478bd9Sstevel@tonic-gate 		 * characters and that clear to end of line is available.
14767c478bd9Sstevel@tonic-gate 		 */
14777c478bd9Sstevel@tonic-gate 		i = stcol / WCOLS;
14787c478bd9Sstevel@tonic-gate 		if (i != endcol / WCOLS)
14797c478bd9Sstevel@tonic-gate 			return;
14807c478bd9Sstevel@tonic-gate 		i += LINE(vcline);
14817c478bd9Sstevel@tonic-gate 		stcol %= WCOLS;
14827c478bd9Sstevel@tonic-gate 		endcol %= WCOLS;
14837c478bd9Sstevel@tonic-gate 		up = vtube[i]; tp = up + endcol; tpe = up + WCOLS;
14847c478bd9Sstevel@tonic-gate 		while (tp < tpe && *tp)
14857c478bd9Sstevel@tonic-gate 			tp++;
14867c478bd9Sstevel@tonic-gate 		if (tp - (up + stcol) < 2 * nc)
14877c478bd9Sstevel@tonic-gate 			return;
14887c478bd9Sstevel@tonic-gate 		vgoto(i, stcol);
14897c478bd9Sstevel@tonic-gate 	}
14907c478bd9Sstevel@tonic-gate 
14917c478bd9Sstevel@tonic-gate 	/*
14927c478bd9Sstevel@tonic-gate 	 * Go into delete mode and do the actual delete.
14937c478bd9Sstevel@tonic-gate 	 * Padding is on delete_character itself.
14947c478bd9Sstevel@tonic-gate 	 */
14957c478bd9Sstevel@tonic-gate 	godm();
14967c478bd9Sstevel@tonic-gate 	for (i = nc; i > 0; i--)
14977c478bd9Sstevel@tonic-gate 		vputp(delete_character, DEPTH(vcline));
14987c478bd9Sstevel@tonic-gate 	vputp(exit_delete_mode, 0);
14997c478bd9Sstevel@tonic-gate 
15007c478bd9Sstevel@tonic-gate 	/*
15017c478bd9Sstevel@tonic-gate 	 * Straighten up.
15027c478bd9Sstevel@tonic-gate 	 * With CONCEPT like terminals, characters are pulled left
15037c478bd9Sstevel@tonic-gate 	 * from first following null.  HP like terminals shift rest of
15047c478bd9Sstevel@tonic-gate 	 * this (single physical) line rigidly.
15057c478bd9Sstevel@tonic-gate 	 */
15067c478bd9Sstevel@tonic-gate 	if (insert_null_glitch) {
15077c478bd9Sstevel@tonic-gate 		up = vtube0 + stcol;
15087c478bd9Sstevel@tonic-gate 		tp = vtube0 + endcol;
15097c478bd9Sstevel@tonic-gate 		while (i = *tp++) {
15107c478bd9Sstevel@tonic-gate 			if ((i & (QUOTE|TRIM)) == QUOTE)
15117c478bd9Sstevel@tonic-gate 				break;
15127c478bd9Sstevel@tonic-gate 			*up++ = i;
15137c478bd9Sstevel@tonic-gate 		}
15147c478bd9Sstevel@tonic-gate 		do
15157c478bd9Sstevel@tonic-gate 			*up++ = i;
15167c478bd9Sstevel@tonic-gate 		while (--nc);
15177c478bd9Sstevel@tonic-gate 	} else {
15187c478bd9Sstevel@tonic-gate 		copy(up + stcol, up + endcol, (WCOLS - endcol) * sizeof(wchar_t));
15197c478bd9Sstevel@tonic-gate 		vclrbyte(tpe - nc, nc);
15207c478bd9Sstevel@tonic-gate 	}
15217c478bd9Sstevel@tonic-gate }
15227c478bd9Sstevel@tonic-gate 
15237c478bd9Sstevel@tonic-gate #ifdef TRACE
15247c478bd9Sstevel@tonic-gate tfixnl()
15257c478bd9Sstevel@tonic-gate {
15267c478bd9Sstevel@tonic-gate 
15277c478bd9Sstevel@tonic-gate 	if (trubble || techoin)
15287c478bd9Sstevel@tonic-gate 		fprintf(trace, "\n");
15297c478bd9Sstevel@tonic-gate 	trubble = 0, techoin = 0;
15307c478bd9Sstevel@tonic-gate }
15317c478bd9Sstevel@tonic-gate 
15327c478bd9Sstevel@tonic-gate tvliny()
15337c478bd9Sstevel@tonic-gate {
1534*f6db9f27Scf46844 	int i;
15357c478bd9Sstevel@tonic-gate 
15367c478bd9Sstevel@tonic-gate 	if (!trace)
15377c478bd9Sstevel@tonic-gate 		return;
15387c478bd9Sstevel@tonic-gate 	tfixnl();
15397c478bd9Sstevel@tonic-gate 	fprintf(trace, "vcnt = %d, vcline = %d, vliny = ", vcnt, vcline);
15407c478bd9Sstevel@tonic-gate 	for (i = 0; i <= vcnt; i++) {
15417c478bd9Sstevel@tonic-gate 		fprintf(trace, "%d", LINE(i));
15427c478bd9Sstevel@tonic-gate 		if (FLAGS(i) & VDIRT)
15437c478bd9Sstevel@tonic-gate 			fprintf(trace, "*");
15447c478bd9Sstevel@tonic-gate 		if (DEPTH(i) != 1)
15457c478bd9Sstevel@tonic-gate 			fprintf(trace, "<%d>", DEPTH(i));
15467c478bd9Sstevel@tonic-gate 		if (i < vcnt)
15477c478bd9Sstevel@tonic-gate 			fprintf(trace, " ");
15487c478bd9Sstevel@tonic-gate 	}
15497c478bd9Sstevel@tonic-gate 	fprintf(trace, "\n");
15507c478bd9Sstevel@tonic-gate }
15517c478bd9Sstevel@tonic-gate 
15527c478bd9Sstevel@tonic-gate tracec(c)
15537c478bd9Sstevel@tonic-gate 	int c;		/* char --> int */
15547c478bd9Sstevel@tonic-gate {
15557c478bd9Sstevel@tonic-gate 
15567c478bd9Sstevel@tonic-gate 	if (!techoin)
15577c478bd9Sstevel@tonic-gate 		trubble = 1;
15587c478bd9Sstevel@tonic-gate 	if (c == ESCAPE)
15597c478bd9Sstevel@tonic-gate 		fprintf(trace, "$");
15607c478bd9Sstevel@tonic-gate 	else if (c & QUOTE)	/* for 3B (no sign extension) */
15617c478bd9Sstevel@tonic-gate 		fprintf(trace, "~%c", ctlof(c&TRIM));
15627c478bd9Sstevel@tonic-gate 	else if (c < ' ' || c == DELETE)
15637c478bd9Sstevel@tonic-gate 		fprintf(trace, "^%c", ctlof(c));
15647c478bd9Sstevel@tonic-gate 	else
15657c478bd9Sstevel@tonic-gate 		fprintf(trace, "%c", c);
15667c478bd9Sstevel@tonic-gate }
15677c478bd9Sstevel@tonic-gate #endif
15687c478bd9Sstevel@tonic-gate 
15697c478bd9Sstevel@tonic-gate /*
15707c478bd9Sstevel@tonic-gate  * Put a character with possible tracing.
15717c478bd9Sstevel@tonic-gate  */
15727c478bd9Sstevel@tonic-gate int
15737c478bd9Sstevel@tonic-gate vputch(char c)
15747c478bd9Sstevel@tonic-gate {
15757c478bd9Sstevel@tonic-gate 
15767c478bd9Sstevel@tonic-gate #ifdef TRACE
15777c478bd9Sstevel@tonic-gate 	if (trace) {
15787c478bd9Sstevel@tonic-gate 		tracec(c);
15797c478bd9Sstevel@tonic-gate 	}
15807c478bd9Sstevel@tonic-gate #endif
1581*f6db9f27Scf46844 	(void) vputc(c);
1582*f6db9f27Scf46844 	return (0);
15837c478bd9Sstevel@tonic-gate }
1584