Ejemplo n.º 1
0
/*
 * Clear to the end of the current physical line
 */
void
vclreol(void)
{
	register int i, j;
	register cell *tp;

	if (destcol == WCOLS)
		return;
	destline += destcol / WCOLS;
	destcol %= WCOLS;
	if (destline < 0 || destline > WECHO)
		error(catgets(catd, 1, 237, "Internal error: vclreol"));
	i = WCOLS - destcol;
	tp = vtube[destline] + destcol;
	if (CE) {
		if (IN && *tp || !ateopr()) {
			vcsync();
			vputp(CE, 1);
		}
		vclrcell(tp, i);
		return;
	}
	if (*tp == 0)
		return;
	while (i > 0 && (j = *tp & (QUOTE|TRIM|MULTICOL))) {
		if ((j != ' ' && (j & QUOTE) == 0)) {
			destcol = WCOLS - i;
			vputchar(' ');
		}
		--i, *tp++ = 0;
	}
}
Ejemplo n.º 2
0
/*
 * Scroll the screen up cnt lines physically.
 * If doclr is true, do a clear eol if the terminal
 * has standout (to prevent it from scrolling up)
 */
void 
vmoveitup(register int cnt, int doclr)
{

	if (cnt == 0)
		return;
#ifdef ADEBUG
	if (trace)
		tfixnl(), fprintf(trace, "vmoveitup(%d)\n", cnt);
#endif
	if (doclr && (SO || SE))
		vclrech(0);
	if (SF) {
		destline = WECHO;
		destcol = (NONL ? 0 : outcol % WCOLS);
		fgoto();
		while (cnt > 0)
			vputp(SF, 0), cnt--;
		return;
	}
	destline = WECHO + cnt;
	destcol = (NONL ? 0 : outcol % WCOLS);
	fgoto();
	if (state == ONEOPEN || state == HARDOPEN) {
		outline = destline = 0;
		vclrcell(vtube[0], WCOLS);
	}
}
Ejemplo n.º 3
0
/*
 * Clear the echo line.
 * If didphys then its been cleared physically (as
 * a side effect of a clear to end of display, e.g.)
 * so just do it logically.
 * If work here is being held off, just remember, in
 * heldech, if work needs to be done, don't do anything.
 */
void
vclrech(bool didphys)
{

	if (Peekkey == ATTN)
		return;
	if (hold & HOLDECH) {
		heldech = !didphys;
		return;
	}
	if (!didphys && (CD || CE)) {
		splitw++;
		/*
		 * If display is retained below, then MUST use CD or CE
		 * since we don't really know whats out there.
		 * Vigoto might decide (incorrectly) to do nothing.
		 */
		if (DB) {
			vgoto(WECHO, 0);
			vputp(CD ? CD : CE, 1);
		} else {
			if (XT) {
				/*
				 * This code basically handles the t1061
				 * where positioning at (0, 0) won't work
				 * because the terminal won't let you put
				 * the cursor on it's magic cookie.
				 *
				 * Should probably be XS above, or even a
				 * new X? glitch, but right now t1061 is the
				 * only terminal with XT.
				 */
				vgoto(WECHO, 0);
				vputp(DL, 1);
			} else {
				vigoto(WECHO, 0);
				vclreol();
			}
		}
		splitw = 0;
		didphys = 1;
	}
	if (didphys)
		vclrcell(vtube[WECHO], WCOLS);
	heldech = 0;
}
Ejemplo n.º 4
0
/*
 * In and out of insert mode.
 * Note that the code here demands that there be
 * a string for insert mode (the null string) even
 * if the terminal does all insertions a single character
 * at a time, since it branches based on whether IM is null.
 */
void
goim(void)
{

	if (!insmode)
		vputp(IM, 0);
	insmode = 1;
}
Ejemplo n.º 5
0
/*
 * Rrrrringgggggg.
 * If possible, use flash (VB).
 */
void
beep(void)
{

	if (VB)
		vputp(VB, 0);
	else
		vputc(CTRL('g'));
}
Ejemplo n.º 6
0
void
endim(void)
{

	if (insmode) {
		vputp(EI, 0);
		insmode = 0;
	}
}
Ejemplo n.º 7
0
/*
 * If we are coming out of delete mode, but
 * delete and insert mode end with the same sequence,
 * it wins to pretend we are now in insert mode,
 * since we will likely want to be there again soon
 * if we just moved over to delete space from part of
 * a tab (above).
 */
void
enddm(void)
{

	if (eq(DM, IM)) {
		insmode = 1;
		return;
	}
	vputp(ED, 0);
}
Ejemplo n.º 8
0
/*
 * Go into ``delete mode''.  If the
 * sequence which goes into delete mode
 * is the same as that which goes into insert
 * mode, then we are in delete mode already.
 */
void
godm(void)
{

	if (insmode) {
		if (eq(DM, IM))
			return;
		endim();
	}
	vputp(DM, 0);
}
Ejemplo n.º 9
0
/*
 * We need cnt more positions on this line.
 * Open up new space on the screen (this may in fact be a
 * screen rollup).
 *
 * On a dumb terminal we may infact redisplay the rest of the
 * screen here brute force to keep it pretty.
 */
void
vneedpos(int npcnt)
{
	register int d = DEPTH(vcline);
	register int rmdr = d * WCOLS - linend;

	/*
	 * Delete the showmode string on wraparound to last line. Cannot use
	 * vclrech() since the mode string is printed on the echo area, but
	 * not actually a part of it.
	 */
	if (value(SHOWMODE) && (value(REDRAW) || (IM && EI)) &&
			npcnt == rmdr - IN && LINE(vcline) + d == WECHO) {
		int sdc, sdl;
		char *ocurs;

		endim();
		sdc = destcol, sdl = destline, ocurs = cursor;
		splitw++;
		vgoto(WECHO, 0);
		if (CD) {
			vputp(CD, 1);
		} else if (CE) {
			vputp(CE, 1);
		} else {
			int i;

			for (i = 1; i < WCOLS; i++)
				vputchar(' ');
		}
		destcol = sdc, destline = sdl; cursor = ocurs;
		splitw = 0;
	}
	if (npcnt <= rmdr - IN)
		return;
	endim();
	vnpins(1);
}
Ejemplo n.º 10
0
/*
 * Do the real work in deleting cnt lines starting at line p from
 * the display.  First affected line is line l.
 */
void 
vdellin(int p, int cnt, int l)
{
	register int i;

	if (cnt == 0)
		return;
	if (DL == NOSTR || cnt < 0) {
		/*
		 * Can't do it; just remember that line l is munged.
		 */
		FLAGS(l) |= VDIRT;
		return;
	}
#ifdef ADEBUG
	if (trace)
		tfixnl(), fprintf(trace, "vdellin(%d, %d, %d)\n", p, cnt, l);
#endif
	/*
	 * Send the deletes to the screen and then adjust logical
	 * and physical internal data structures.
	 */
	vgoto(p, 0);
	if (DL_PARM && (cnt>1 || *DL==0)) {
		vputp(tgoto(DL_PARM, p, cnt), WECHO-p);
	}
	else if (xCS && *DL==0) {
		/* vt100: fake DL by changing scrolling region */
		vputp(SC, 1);	/* Save since xCS homes stupid cursor */
		vputp(tgoto(xCS, TLINES-1, p), 1);
		vputp(tgoto(CM, 0, TLINES-1), 1);/* Go to lower left corner */
		for (i=0; i<cnt; i++)		/* .. and scroll cnt times */
			putch('\n');		/* should check NL too */
		vputp(tgoto(xCS, TLINES-1, 0), 1);/* restore scrolling region */
		vputp(RC, 1);			/* put cursor back */
	}
	else {
		for (i = 0; i < cnt; i++)
			vputp(DL, WECHO - p);
	}
	vadjDL(p, cnt);
	vcloseup(l, cnt);
}
Ejemplo n.º 11
0
/*
 * Clear to the end of the current physical line
 */
void
vclreol(void)
{
	int i;
	wchar_t *tp, j;

#ifdef TRACE
	if (trace)
		fprintf(trace, "vclreol(), destcol %d, ateopr() %d\n", destcol, ateopr());
#endif
	if (destcol == WCOLS)
		return;
	destline += destcol / WCOLS;
	destcol %= WCOLS;
	if (destline < 0 || destline > WECHO)
		error(gettext("Internal error: vclreol"));
	i = WCOLS - destcol;
	tp = vtube[destline] + destcol;
	if (clr_eol) {
		if (insert_null_glitch && *tp || !ateopr()) {
			vcsync();
			vputp(clr_eol, 1);
		}
		vclrbyte(tp, i);
		return;
	}
	if (*tp == 0)
		return;
	while (i > 0 && (j = *tp & (QUOTE|TRIM))) {
		if (j != ' ' && (j & QUOTE) == 0) {
			destcol = WCOLS - i;
			(void) vputchar(' ');
		}
		--i, *tp++ = 0;
	}
}
Ejemplo n.º 12
0
/*
 * Insert cnt blank lines before line p,
 * logically and (if supported) physically.
 */
void 
vinslin(register int p, register int cnt, int l)
{
	register int i;
	bool could = 1;

#ifdef ADEBUG
	if (trace)
		tfixnl(), fprintf(trace, "vinslin(%d, %d, %d)\n", p, cnt, l);
#endif
	if (p + cnt > WBOT && CD) {
		/*
		 * Really quick -- clear to end of screen.
		 */
		cnt = WECHO + 1 - p;
		vgoto(p, 0), vputp(CD, cnt);
		vclrech(1);
		vadjAL(p, cnt);
	} else if (SR && p == WTOP && costSR < costAL) {
		/*
		 * Use reverse scroll mode of the terminal, at
		 * the top of the window.  Reverse linefeed works
		 * too, since we only use it from line WTOP.
		 */
		for (i = cnt; i > 0; i--) {
			vgoto(p, 0), vputp(SR, 0);
			if (i > 1 && (hold & HOLDAT) == 0)
				putchar('@');
			/*
			 * If we are at the top of the screen, and the
			 * terminal retains display above, then we
			 * should try to clear to end of line.
			 * Have to use CE since we don't remember what is
			 * actually on the line.
			 */
			if (CE && (DA || p != 0))
				vputp(CE, 1);
		}
		vadjAL(p, cnt);
	} else if (AL) {
		/*
		 * Use insert line.
		 */
		vgoto(p, 0);
		if (AL_PARM && (cnt>1 || *AL==0)) {
			/* insert cnt lines.  Should do @'s too. */
			vputp(tgoto(AL_PARM, p, cnt), WECHO+1-p);
		}
		else if (xCS && *AL==0) {
			/* vt100 change scrolling region to fake AL */
			vputp(SC, 1);
			vputp(tgoto(xCS, TLINES-1,p), 1);
			vputp(RC, 1);	/* xCS homes stupid cursor */
			for (i=cnt; i>0; i--)
				vputp(SR, 1);	/* should do @'s */
			vputp(tgoto(xCS, TLINES-1,0), 1);
			vputp(RC, 1);	/* Once again put it back */
		}
		else {
			vputp(AL, WECHO + 1 - p);
			for (i = cnt - 1; i > 0; i--) {
				vgoto(outline+1, 0);
				vputp(AL, WECHO + 1 - outline);
				if ((hold & HOLDAT) == 0)
					putchar('@');
			}
		}
		vadjAL(p, cnt);
	} else
		could = 0;
	vopenup(cnt, could, l);
}
Ejemplo n.º 13
0
/*
 * Move cursor to line y, column x, handling wraparound and scrolling.
 */
void
vgoto(register int y, register int x)
{
	register cell *tp;
	register int c;

	/*
	 * Fold the possibly too large value of x.
	 */
	if (x >= WCOLS) {
		y += x / WCOLS;
		x %= WCOLS;
	}
#ifdef	MB
	if (y >= 0 && y <= WLINES && mb_cur_max > 1 && !insmode) {
		while (x > 0 && (vtube[y][x]&(MULTICOL|TRIM)) == MULTICOL &&
				vtube[y][x-1] & MULTICOL &&
				(vtube[y][x-1]&(MULTICOL|TRIM)) != MULTICOL)
			x--;
	}
#endif	/* MB */
	if (y < 0)
		error(catgets(catd, 1, 238, "Internal error: vgoto"));
	if (outcol >= WCOLS) {
		if (AM) {
			outline += outcol / WCOLS;
			outcol %= WCOLS;
		} else
			outcol = WCOLS - 1;
	}

	/*
	 * In a hardcopy or glass crt open, print the stuff
	 * implied by a motion, or backspace.
	 */
	if (state == HARDOPEN || state == ONEOPEN) {
		if (y != outline)
			error(catgets(catd, 1, 239, "Line too long for open"));
		if (x + 1 < outcol - x || (outcol > x && !BS))
			destcol = 0, fgoto();
		tp = vtube[WBOT] + outcol;
		while (outcol != x)
			if (outcol < x) {
				if (*tp == 0)
					*tp = ' ';
				c = *tp++ & TRIM;
				vputc(c && (!OS || EO) ? c : ' ');
				outcol++;
			} else {
				if (BC)
					vputp(BC, 0);
				else
					vputc('\b');
				outcol--;
			}
		destcol = outcol = x;
		destline = outline;
		return;
	}

	/*
	 * If the destination position implies a scroll, do it.
	 */
	destline = y;
	if (destline > WBOT && (!splitw || destline > WECHO)) {
		endim();
		vrollup(destline);
	}

	/*
	 * If there really is a motion involved, do it.
	 * The check here is an optimization based on profiling.
	 */
	destcol = x;
	if ((destline - outline) * WCOLS != destcol - outcol) {
		if (!MI)
			endim();
		fgoto();
	}
}
Ejemplo n.º 14
0
/*
 * Delete display positions stcol through endcol.
 * Amount of use of special terminal features here is limited.
 */
void
physdc(int stcol, int endcol)
{
	register cell *tp, *up;
	cell *tpe = NULL;
	register int i;
	register int nc = endcol - stcol;

#ifdef IDEBUG
	if (trace)
		tfixnl(), fprintf(trace, "physdc(%d, %d)\n", stcol, endcol);
#endif
	if (!DC || nc <= 0)
		return;
	if (IN) {
		/*
		 * CONCEPT-100 like terminal.
		 * If there are any ``spaces'' in the material to be
		 * deleted, then this is too hard, just retype.
		 */
		vprepins();
		up = vtube0 + stcol;
		i = nc;
		do {
			if ((*up++ & (QUOTE|TRIM)) == QUOTE)
				return;
		} while (--i);
		i = 2 * nc;
		do {
			if (*up == 0 || (*up++ & QUOTE) == QUOTE)
				return;
		} while (--i);
		vgotoCL(stcol);
	} else {
		/*
		 * HP like delete mode.
		 * Compute how much text we are moving over by deleting.
		 * If it appears to be faster to just retype
		 * the line, do nothing and that will be done later.
		 * We are assuming 2 output characters per deleted
		 * characters and that clear to end of line is available.
		 */
		i = stcol / WCOLS;
		if (i != endcol / WCOLS)
			return;
		i += LINE(vcline);
		stcol %= WCOLS;
		endcol %= WCOLS;
		up = vtube[i]; tp = up + endcol; tpe = up + WCOLS;
		while (tp < tpe && *tp)
			tp++;
		if (tp - (up + stcol) < 2 * nc)
			return;
		vgoto(i, stcol);
	}

	/*
	 * Go into delete mode and do the actual delete.
	 * Padding is on DC itself.
	 */
	godm();
	for (i = nc; i > 0; i--)
		vputp(DC, DEPTH(vcline));
	vputp(ED, 0);

	/*
	 * Straighten up.
	 * With CONCEPT like terminals, characters are pulled left
	 * from first following null.  HP like terminals shift rest of
	 * this (single physical) line rigidly.
	 */
	if (IN) {
		up = vtube0 + stcol;
		tp = vtube0 + endcol;
		while (i = *tp++) {
			if ((i & (QUOTE|TRIM)) == QUOTE)
				break;
			*up++ = i;
		}
		do
			*up++ = i;
		while (--nc);
	} else {
		copy(up + stcol, up + endcol,
				(WCOLS - endcol) * sizeof *up);
		vclrcell(tpe - nc, nc);
	}
}
Ejemplo n.º 15
0
/*
 * Put the character c on the screen at the current cursor position.
 * This routine handles wraparound and scrolling and understands not
 * to roll when splitw is set, i.e. we are working in the echo area.
 * There is a bunch of hacking here dealing with the difference between
 * QUOTE, QUOTE|' ', and ' ' for CONCEPT-100 like terminals, and also
 * code to deal with terminals which overstrike, including CRT's where
 * you can erase overstrikes with some work.  CRT's which do underlining
 * implicitly which has to be erased (like CONCEPTS) are also handled.
 */
int
vputchar(register int c)
{
	register cell *tp;
	register int d, m, n;

#ifndef	BIT8
	c &= (QUOTE|TRIM);
#endif
#ifdef TRACE
	if (trace)
		tracec(c);
#endif
	/* Fix problem of >79 chars on echo line. */
	if (destcol >= WCOLS-1 && splitw && destline == WECHO)
		pofix();
#ifdef	MB
	if (mb_cur_max > 1) {
		if (c == MULTICOL)
			return c;
		/*
		 * If a multicolumn character extends beyond the screen
		 * width, it must be put on the next line. A tilde is
		 * printed as an indicator but must disappear when the
		 * text is moved at a later time.
		 */
		if (c == ('~'|INVBIT|QUOTE))
			c = '~'|INVBIT;
		else if (c == ('~'|INVBIT))
			return c;
		else if (destcol < WCOLS && destcol +
				colsc(c==QUOTE ? ' ' : c&TRIM&~MULTICOL) - 1
				>= WCOLS)
			vputchar('~'|INVBIT|QUOTE);
	}
#endif	/* MB */
	if (destcol >= WCOLS) {
		destline += destcol / WCOLS;
		destcol %= WCOLS;
	}
	if (destline > WBOT && (!splitw || destline > WECHO))
		vrollup(destline);
	tp = vtube[destline] + destcol;
	if (c == QUOTE) {
		if (insmode) {
			/*
			 * When in insert mode, tabs have to expand
			 * to real, printed blanks.
			 */
			c = ' ' | QUOTE;
			goto def;
		}
		if (*tp == 0) {
			/*
			 * A ``space''.
			 */
			if ((hold & HOLDPUPD) == 0)
				*tp = QUOTE;
			destcol++;
			return c;
		}
		/*
		 * A ``space'' ontop of a part of a tab.
		 */
		if (*tp & QUOTE) {
			destcol++;
			return c;
		}
		c = ' ' | QUOTE;
		goto def;
	}

#ifdef	notdef
#ifdef	BIT8
	if (c == ' ' | QUOTE) {
		c = ' ';
		goto def;
	}
#endif
#endif
	switch (c) {

	case '\t':
		vgotab();
		return c;

	case ' ':
		/*
		 * We can get away without printing a space in a number
		 * of cases, but not always.  We get away with doing nothing
		 * if we are not in insert mode, and not on a CONCEPT-100
		 * like terminal, and either not in hardcopy open or in hardcopy
		 * open on a terminal with no overstriking, provided,
		 * in all cases, that nothing has ever been displayed
		 * at this position.  Ugh.
		 */
		if (!insmode && !IN && (state != HARDOPEN || OS)
		&& (*tp&QUOTE)) {
			*tp = ' ';
			destcol++;
			return c;
		}
		goto def;

def:
	default:
		d = *tp & TRIM;
		/*
		 * Now get away with doing nothing if the characters
		 * are the same, provided we are not in insert mode
		 * and if we are in hardopen, that the terminal has overstrike.
		 */
		if ((d & ~MULTICOL) == (c & TRIM & ~MULTICOL) && !insmode &&
				(state != HARDOPEN || OS) && c != MULTICOL) {
			n = colsc(d);
			for (m = 1; m < n; m++)
				if ((tp[m] & (MULTICOL|TRIM)) != MULTICOL)
					break;
			if (m == n) {
				if ((hold & HOLDPUPD) == 0)
					*tp = c | (n > 1 ? MULTICOL : 0);
				destcol += n;
				return c;
			}
		}
		/*
		 * Backwards looking optimization.
		 * The low level cursor motion routines will use
		 * a cursor motion right sequence to step 1 character
		 * right.  On, e.g., a DM3025A this is 2 characters
		 * and printing is noticeably slower at 300 baud.
		 * Since the low level routines are not allowed to use
		 * spaces for positioning, we discover the common
		 * case of a single space here and force a space
		 * to be printed.
		 */
		if (destcol == outcol + 1 && tp[-1] == ' ' && outline == destline) {
			vputc(' ');
			outcol++;
		}

		/*
		 * This is an inline expansion a call to vcsync() dictated
		 * by high frequency in a profile.
		 */
		if (outcol != destcol || outline != destline)
			vgoto(destline, destcol);

		/*
		 * Deal with terminals which have overstrike.
		 * We handle erasing general overstrikes, erasing
		 * underlines on terminals (such as CONCEPTS) which
		 * do underlining correctly automatically (e.g. on nroff
		 * output), and remembering, in hardcopy mode,
		 * that we have overstruct something.
		 */
		if (!insmode && d && d != ' ' && d != (c & TRIM)) {
			if (EO && (OS || UL && (c == '_' || d == '_'))) {
				vputc(' ');
				outcol++, destcol++;
				back1();
			} else
				rubble = 1;
		}

		/*
		 * Unless we are just bashing characters around for
		 * inner working of insert mode, update the display.
		 */
		if ((hold & HOLDPUPD) == 0)
			*tp = c;

		/*
		 * In insert mode, put out the IC sequence, padded
		 * based on the depth of the current line.
		 * A terminal which had no real insert mode, rather
		 * opening a character position at a time could do this.
		 * Actually should use depth to end of current line
		 * but this rarely matters.
		 */
#ifdef	notdef
		if (insmode)
#else
		/*
		 * It seems today's termcap writers consider this
		 * an either-or situation; if both im and ic
		 * are used vi puts out additional spaces.
		 *
		 * SVR4 ex does not include this change. If it hits
		 * your terminal, change back to the old way and
		 * mail me a description.
		 *
		 * GR July 2000
		 */
		if (insmode && (!IM || !*IM))
#endif	/* !notdef */
		{
			n = colsc(c&TRIM);
			for (m = 0; m < n; m++)
				vputp(IC, DEPTH(vcline));
		}
		vputc(c & TRIM);

		/*
		 * In insert mode, IP is a post insert pad.
		 */
		if (insmode)
			vputp(IP, DEPTH(vcline));
		destcol++, outcol++;

		/*
		 * CONCEPT braindamage in early models:  after a wraparound
		 * the next newline is eaten.  It's hungry so we just
		 * feed it now rather than worrying about it.
		 * Fixed to use	return linefeed to work right
		 * on vt100/tab132 as well as concept.
		 */
		if (XN && outcol % WCOLS == 0) {
			vputc('\r');
			vputc('\n');
		}
	}
#ifdef	MB
	if (mb_cur_max > 1 && (d = colsc(c&TRIM&~MULTICOL)) > 1) {
		if ((hold & HOLDPUPD) == 0)
			*tp |= MULTICOL;
		while (--d) {
			if ((hold & HOLDPUPD) == 0)
				*++tp = MULTICOL;
			destcol++;
			outcol++;
		}
	}
#endif	/* MB */
	return c;
}
Ejemplo n.º 16
0
/*
 * Now do the insert of the characters (finally).
 */
void
viin(int c)
/*	int c;		/\* mjm: char --> int */
{
	register cell *tp, *up;
	register int i, j;
	register bool noim = 0;
	int remdoom;
	short oldhold = hold;

	hold |= HOLDPUPD;
	if (tabsize && (IM && EI) && inssiz - doomed > tabslack)
		/*
		 * There is a tab out there which will be affected
		 * by the insertion since there aren't enough doomed
		 * characters to take up all the insertion and we do
		 * have insert mode capability.
		 */
		if (inscol + insmc0 + doomed == tabstart) {
			/*
			 * The end of the doomed characters sits right at the
			 * start of the tabs, then we don't need to use insert
			 * mode; unless the tab has already been expanded
			 * in which case we MUST use insert mode.
			 */
			slakused = 0;
			noim = !shft;
		} else {
			/*
			 * The last really special case to handle is case
			 * where the tab is just sitting there and doesn't
			 * have enough slack to let the insertion take
			 * place without shifting the rest of the line
			 * over.  In this case we have to go out and
			 * delete some characters of the tab before we start
			 * or the answer will be wrong, as the rest of the
			 * line will have been shifted.  This code means
			 * that terminals with only insert chracter (no
			 * delete character) won't work correctly.
			 */
			i = inssiz - doomed - tabslack - slakused;
			i %= value(TABSTOP);
			if (i > 0) {
				vgotoCL(tabstart);
				godm();
				for (i = inssiz - doomed - tabslack; i > 0; i--)
					vputp(DC, DEPTH(vcline));
				enddm();
			}
		}

	/* 
	 * Now put out the characters of the actual insertion.
	 */
	vigotoCL(inscol);
	remdoom = doomed;
	for (i = inssiz; i > 0; i--) {
		if (remdoom > insmc1) {
			remdoom--;
			endim();
		} else if (noim || insmc1 && remdoom == insmc1)
			endim();
		else if (IM && EI) {
			vcsync();
			goim();
		}
		vputchar(c);
	}

	if (!IM || !EI || remdoom && remdoom == insmc1) {
		/*
		 * We are a dumb terminal; brute force update
		 * the rest of the line; this is very much an n^^2 process,
		 * and totally unreasonable at low speed.
		 *
		 * You asked for it, you get it.
		 */
		tp = vtube0 + inscol + doomed;
		for (i = inscol + doomed; i < tabstart; i++)
			vputchar(*tp++);
		hold = oldhold;
		vigotoCL(tabstart + inssiz + insmc0 - doomed);
		for (i = tabsize - (inssiz - insmc0 - doomed) + shft;
				i > 0; i--)
			vputchar(' ' | QUOTE);
	} else {
		if (!IN) {
			/*
			 * On terminals without multi-line
			 * insert in the hardware, we must go fix the segments
			 * between the inserted text and the following
			 * tabs, if they are on different lines.
			 *
			 * Aaargh.
			 */
			tp = vtube0;
			for (j = (inscol + insmc0 + inssiz - 1) / WCOLS + 1;
			    j <= (tabstart + inssiz - doomed - 1) / WCOLS; j++) {
				vgotoCL(j * WCOLS);
				i = inssiz - doomed + insmc1;
				up = tp + j * WCOLS - i;
				goim();
				do
					vputchar(*up++);
				while (--i && *up);
			}
		} else {
			/*
			 * On terminals with multi line inserts,
			 * life is simpler, just reflect eating of
			 * the slack.
			 */
			tp = vtube0 + tabend;
			for (i = tabsize - (inssiz + insmc1 - doomed); i >= 0; i--) {
				if ((*--tp & (QUOTE|TRIM)) == QUOTE) {
					--tabslack;
					if (tabslack >= slakused)
						continue;
				}
				*tp = ' ' | QUOTE;
			}
		}
		/*
		 * Blank out the shifted positions to be tab positions.
		 */
		if (shft) {
			tp = vtube0 + tabend + shft;
			for (i = tabsize - (inssiz - doomed) + shft; i > 0; i--)
				if ((*--tp & QUOTE) == 0)
					*tp = ' ' | QUOTE;
		}
	}

	/*
	 * Finally, complete the screen image update
	 * to reflect the insertion.
	 */
	hold = oldhold;
	tp = vtube0 + tabstart;
	up = tp + insmc1 + inssiz - doomed;
	for (i = tabstart; i > inscol + doomed; i--)
		*--up = *--tp;
#ifdef	MB
	for (i = insmc1; i > 0; i--)
		*--up = MULTICOL;
#endif
	for (i = inssiz; i > 0; i--)
		*--up = c | (insmc1 ? MULTICOL : 0);
	doomed = 0;
}