summaryrefslogtreecommitdiff
path: root/src/vi/ex-070224/ex_vput.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vi/ex-070224/ex_vput.c')
-rw-r--r--src/vi/ex-070224/ex_vput.c1630
1 files changed, 0 insertions, 1630 deletions
diff --git a/src/vi/ex-070224/ex_vput.c b/src/vi/ex-070224/ex_vput.c
deleted file mode 100644
index 1851b67..0000000
--- a/src/vi/ex-070224/ex_vput.c
+++ /dev/null
@@ -1,1630 +0,0 @@
-/*
- * This code contains changes by
- * Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
- *
- * Conditions 1, 2, and 4 and the no-warranty notice below apply
- * to these changes.
- *
- *
- * Copyright (c) 1980, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *
- * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * Redistributions of source code and documentation must retain the
- * above copyright notice, this list of conditions and the following
- * disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed or owned by Caldera
- * International, Inc.
- * Neither the name of Caldera International, Inc. nor the names of
- * other contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
- * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
- * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef lint
-#ifdef DOSCCS
-static char sccsid[] = "@(#)ex_vput.c 1.52 (gritter) 12/25/06";
-#endif
-#endif
-
-/* from ex_vput.c 7.4.1 (2.11BSD GTE) 12/9/94 */
-
-#include "ex.h"
-#include "ex_tty.h"
-#include "ex_vis.h"
-
-/*
- * Deal with the screen, clearing, cursor positioning, putting characters
- * into the screen image, and deleting characters.
- * Really hard stuff here is utilizing insert character operations
- * on intelligent terminals which differs widely from terminal to terminal.
- */
-void
-vclear(void)
-{
-
-#ifdef ADEBUG
- if (trace)
- tfixnl(), fprintf(trace, "------\nvclear\n");
-#endif
- tputs(CL, TLINES, putch);
- destcol = 0;
- outcol = 0;
- destline = 0;
- outline = 0;
- if (inopen)
- vclrcell(vtube0, WCOLS * (WECHO - ZERO + 1));
-}
-
-/*
- * Clear memory.
- */
-void
-vclrcell(register cell *cp, register int i)
-{
- if (i > 0)
- do
- *cp++ = 0;
- while (--i != 0);
-}
-
-/*
- * Clear a physical display line, high level.
- */
-void
-vclrlin(int l, line *tp)
-{
-
- vigoto(l, 0);
- if ((hold & HOLDAT) == 0)
-#ifndef UCVISUAL
- putchar(tp > dol ? '~' : '@');
-#else
- putchar(tp > dol ? ((UPPERCASE || xHZ) ? '^' : '~') : '@');
-#endif
- if (state == HARDOPEN)
- sethard();
- vclreol();
-}
-
-/*
- * 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;
- }
-}
-
-/*
- * 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 && vtube)
- vclrcell(vtube[WECHO], WCOLS);
- heldech = 0;
-}
-
-/*
- * Fix the echo area for use, setting
- * the state variable splitw so we wont rollup
- * when we move the cursor there.
- */
-void
-fixech(void)
-{
-
- splitw++;
- if (state != VISUAL && state != CRTOPEN) {
- vclean();
- vcnt = 0;
- }
- vgoto(WECHO, 0); flusho();
-}
-
-/*
- * Put the cursor ``before'' cp.
- */
-void
-vcursbef(register char *cp)
-{
-
- if (cp <= linebuf)
- vgotoCL(value(NUMBER) << 3);
- else
- vgotoCL(column(cp - 1) - 1);
-}
-
-/*
- * Put the cursor ``at'' cp.
- */
-void
-vcursat(register char *cp)
-{
-
- if (cp <= linebuf && linebuf[0] == 0)
- vgotoCL(value(NUMBER) << 3);
- else
- vgotoCL(column(cp + skipleft(linebuf, cp)));
-}
-
-/*
- * Put the cursor ``after'' cp.
- */
-void
-vcursaft(register char *cp)
-{
-
- vgotoCL(column(cp));
-}
-
-/*
- * Fix the cursor to be positioned in the correct place
- * to accept a command.
- */
-void
-vfixcurs(void)
-{
-
- vsetcurs(cursor);
-}
-
-/*
- * Compute the column position implied by the cursor at ``nc'',
- * and move the cursor there.
- */
-void
-vsetcurs(register char *nc)
-{
- register int col;
-
- col = column(nc);
- if (linebuf[0])
- col--;
- vgotoCL(col);
- cursor = vcolbp;
-}
-
-/*
- * Move the cursor invisibly, i.e. only remember to do it.
- */
-void
-vigoto(int y, int x)
-{
-
- destline = y;
- destcol = x;
-}
-
-/*
- * Move the cursor to the position implied by any previous
- * vigoto (or low level hacking with destcol/destline as in readecho).
- */
-void
-vcsync(void)
-{
-
- vgoto(destline, destcol);
-}
-
-/*
- * Goto column x of the current line.
- */
-void
-vgotoCL(register int x)
-{
-
- if (splitw)
- vgoto(WECHO, x);
- else
- vgoto(LINE(vcline), x);
-}
-
-/*
- * Invisible goto column x of current line.
- */
-void
-vigotoCL(register int x)
-{
-
- if (splitw)
- vigoto(WECHO, x);
- else
- vigoto(LINE(vcline), x);
-}
-
-/*
- * 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();
- }
-}
-
-/*
- * This is the hardest code in the editor, and deals with insert modes
- * on different kinds of intelligent terminals. The complexity is due
- * to the cross product of three factors:
- *
- * 1. Lines may display as more than one segment on the screen.
- * 2. There are 2 kinds of intelligent terminal insert modes.
- * 3. Tabs squash when you insert characters in front of them,
- * in a way in which current intelligent terminals don't handle.
- *
- * The two kinds of terminals are typified by the DM2500 or HP2645 for
- * one and the CONCEPT-100 or the FOX for the other.
- *
- * The first (HP2645) kind has an insert mode where the characters
- * fall off the end of the line and the screen is shifted rigidly
- * no matter how the display came about.
- *
- * The second (CONCEPT-100) kind comes from terminals which are designed
- * for forms editing and which distinguish between blanks and ``spaces''
- * on the screen, spaces being like blank, but never having had
- * and data typed into that screen position (since, e.g. a clear operation
- * like clear screen). On these terminals, when you insert a character,
- * the characters from where you are to the end of the screen shift
- * over till a ``space'' is found, and the null character there gets
- * eaten up.
- *
- *
- * The code here considers the line as consisting of several parts
- * the first part is the ``doomed'' part, i.e. a part of the line
- * which is being typed over. Next comes some text up to the first
- * following tab. The tab is the next segment of the line, and finally
- * text after the tab.
- *
- * We have to consider each of these segments and the effect of the
- * insertion of a character on them. On terminals like HP2645's we
- * must simulate a multi-line insert mode using the primitive one
- * line insert mode. If we are inserting in front of a tab, we have
- * to either delete characters from the tab or insert white space
- * (when the tab reaches a new spot where it gets larger) before we
- * insert the new character.
- *
- * On a terminal like a CONCEPT our strategy is to make all
- * blanks be displayed, while trying to keep the screen having ``spaces''
- * for portions of tabs. In this way the terminal hardward does some
- * of the hacking for compression of tabs, although this tends to
- * disappear as you work on the line and spaces change into blanks.
- *
- * There are a number of boundary conditions (like typing just before
- * the first following tab) where we can avoid a lot of work. Most
- * of them have to be dealt with explicitly because performance is
- * much, much worse if we don't.
- *
- * A final thing which is hacked here is two flavors of insert mode.
- * Datamedia's do this by an insert mode which you enter and leave
- * and by having normal motion character operate differently in this
- * mode, notably by having a newline insert a line on the screen in
- * this mode. This generally means it is unsafe to move around
- * the screen ignoring the fact that we are in this mode.
- * This is possible on some terminals, and wins big (e.g. HP), so
- * we encode this as a ``can move in insert capability'' mi,
- * and terminals which have it can do insert mode with much less
- * work when tabs are present following the cursor on the current line.
- */
-
-/*
- * Routine to expand a tab, calling the normal Outchar routine
- * to put out each implied character. Note that we call outchar
- * with a QUOTE. We use QUOTE internally to represent a position
- * which is part of the expansion of a tab.
- */
-void
-vgotab(void)
-{
- register int i = tabcol(destcol, value(TABSTOP)) - destcol;
-
- do
- (*Outchar)(QUOTE);
- while (--i);
-}
-
-/*
- * Variables for insert mode.
- */
-int linend; /* The column position of end of line */
-int tabstart; /* Column of start of first following tab */
-int tabend; /* Column of end of following tabs */
-int tabsize; /* Size of the following tabs */
-int tabslack; /* Number of ``spaces'' in following tabs */
-int inssiz; /* Number of characters to be inserted */
-int inscol; /* Column where insertion is taking place */
-int insmc0; /* Multi-column character before insertion */
-int insmc1; /* Multi-column character at insertion */
-int shft; /* Amount tab expansion shifted rest of line */
-int slakused; /* This much of tabslack will be used up */
-
-/*
- * This routine MUST be called before insert mode is run,
- * and brings all segments of the current line to the top
- * of the screen image buffer so it is easier for us to
- * maniuplate them.
- */
-void
-vprepins(void)
-{
- register int i;
- register cell *cp = vtube0;
-
- for (i = 0; i < DEPTH(vcline); i++) {
- vmaktop(LINE(vcline) + i, cp);
- cp += WCOLS;
- }
-}
-
-void
-vmaktop(register int p, cell *cp)
-{
- register int i;
- cell temp[TUBECOLS];
-
- if (p < 0 || vtube[p] == cp)
- return;
- for (i = ZERO; i <= WECHO; i++)
- if (vtube[i] == cp) {
- copy(temp, vtube[i], WCOLS * sizeof *temp);
- copy(vtube[i], vtube[p], WCOLS * sizeof *temp);
- copy(vtube[p], temp, WCOLS * sizeof *temp);
- vtube[i] = vtube[p];
- vtube[p] = cp;
- return;
- }
- error(catgets(catd, 1, 240, "Line too long"));
-}
-
-/*
- * Insert character c at current cursor position.
- * Multi-character inserts occur only as a result
- * of expansion of tabs (i.e. inssize == 1 except
- * for tabs) and code assumes this in several place
- * to make life simpler.
- */
-int
-vinschar(int c)
-/* int c; /\* mjm: char --> int */
-{
- register int i;
- register cell *tp;
- char *OIM;
- bool OXN;
- int noim, filler = 0;
-
- insmc1 = colsc(c) - 1;
- if ((!IM || !EI) && ((hold & HOLDQIK) || !value(REDRAW) || value(SLOWOPEN))) {
- /*
- * Don't want to try to use terminal
- * insert mode, or to try to fake it.
- * Just put the character out; the screen
- * will probably be wrong but we will fix it later.
- */
- if (c == '\t') {
- vgotab();
- return c;
- }
- vputchar(c);
-#ifdef MB
- if (insmc1 == 0 && (vtube0[destcol]&(TRIM|MULTICOL))==MULTICOL)
- vtube0[destcol] = INVBIT;
-#endif /* MB */
- if (DEPTH(vcline) * WCOLS + !value(REDRAW) >
- (destline - LINE(vcline)) * WCOLS + destcol)
- return c;
- /*
- * The next line is about to be clobbered
- * make space for another segment of this line
- * (on an intelligent terminal) or just remember
- * that next line was clobbered (on a dumb one
- * if we don't care to redraw the tail.
- */
- if (AL) {
- vnpins(0);
- } else {
- c = LINE(vcline) + DEPTH(vcline);
- if (c < LINE(vcline + 1) || c > WBOT)
- return c;
- i = destcol;
- vinslin(c, 1, vcline);
- DEPTH(vcline)++;
- vigoto(c, i);
- vprepins();
- }
- return c;
- }
- /*
- * Compute the number of positions in the line image of the
- * current line. This is done from the physical image
- * since that is faster. Note that we have no memory
- * from insertion to insertion so that routines which use
- * us don't have to worry about moving the cursor around.
- */
- if (*vtube0 == 0)
- linend = 0;
- else {
- /*
- * Search backwards for a non-null character
- * from the end of the displayed line.
- */
- i = WCOLS * DEPTH(vcline);
- if (i == 0)
- i = WCOLS;
- tp = vtube0 + i;
- while (*--tp == 0)
- if (--i == 0)
- break;
- linend = i + insmc1;
- }
-
- /*
- * We insert at a position based on the physical location
- * of the output cursor.
- */
- inscol = destcol + (destline - LINE(vcline)) * WCOLS;
- insmc0 = 0;
-#ifdef MB
- i = 0;
- while (inscol+i < LBSIZE && vtube0[inscol+i]&MULTICOL &&
- (vtube0[inscol+insmc0+i]&(MULTICOL|TRIM)) != MULTICOL)
- i++;
- while (inscol+insmc0+i < LBSIZE &&
- (vtube0[inscol+insmc0+i]&(MULTICOL|TRIM)) == MULTICOL)
- insmc0++;
-#endif /* MB */
- if (c == '\t') {
- /*
- * Characters inserted from a tab must be
- * remembered as being part of a tab, but we can't
- * use QUOTE here since we really need to print blanks.
- * QUOTE|' ' is the representation of this.
- */
- inssiz = tabcol(inscol+insmc0, value(TABSTOP)) - inscol - insmc0;
- c = ' ' | QUOTE;
- } else
- inssiz = 1;
-
- /*
- * If the text to be inserted is less than the number
- * of doomed positions, then we don't need insert mode,
- * rather we can just typeover.
- */
- if (inssiz + insmc1 <= doomed) {
- endim();
- if (inscol + insmc0 != linend)
- doomed -= inssiz + insmc1;
-#ifdef MB
- if (insmc1 == 0 && c != '\t' &&
- vtube0[inscol+insmc0] & MULTICOL)
- vtube0[inscol+insmc0] = INVBIT;
-#endif /* MB */
- do
- vputchar(c);
- while (--inssiz);
- return c;
- }
-
- /*
- * Have to really do some insertion, thus
- * stake out the bounds of the first following
- * group of tabs, computing starting position,
- * ending position, and the number of ``spaces'' therein
- * so we can tell how much it will squish.
- */
- tp = vtube0 + inscol + insmc0;
- for (i = inscol + insmc0; i < linend; i++) {
- if (*tp++ & QUOTE) {
- --tp;
- break;
- }
- }
- tabstart = tabend = i;
- tabslack = 0;
- while (tabend < linend) {
- i = *tp++;
- if ((i & QUOTE) == 0)
- break;
- if ((i & (TRIM|MULTICOL)) == 0)
- tabslack++;
- tabsize++;
- tabend++;
- }
- tabsize = tabend - tabstart;
-
- /*
- * For HP's and DM's, e.g. tabslack has no meaning.
- */
- if (!IN)
- tabslack = 0;
-#ifdef IDEBUG
- if (trace) {
- fprintf(trace, "inscol %d, inssiz %d, tabstart %d, ",
- inscol, inssiz, tabstart);
- fprintf(trace, "tabend %d, tabslack %d, linend %d\n",
- tabend, tabslack, linend);
- }
-#endif
- OIM = IM;
- OXN = XN;
- noim = 0;
-#ifdef MB
- if (mb_cur_max > 1) {
- if (destcol + 1 + insmc1 == WCOLS + 1) {
- noim = 1;
- if (insmc1 == 1 && insmc0 == 0)
- filler = 1;
- }
- for (i = inscol; vtube0[i]; i++)
- if (i + 1 >= WCOLS && vtube0[i] & MULTICOL) {
- noim = 1;
- break;
- }
- }
-#endif /* MB */
- if (noim) {
- endim();
- IM = 0;
- XN = 0;
- }
-
- /*
- * The real work begins.
- */
- slakused = 0;
- shft = 0;
- if (tabsize) {
- /*
- * There are tabs on this line.
- * If they need to expand, then the rest of the line
- * will have to be shifted over. In this case,
- * we will need to make sure there are no ``spaces''
- * in the rest of the line (on e.g. CONCEPT-100)
- * and then grab another segment on the screen if this
- * line is now deeper. We then do the shift
- * implied by the insertion.
- */
- if (inssiz >= doomed + tabcol(tabstart, value(TABSTOP)) - tabstart) {
- if (IN)
- vrigid();
- vneedpos(value(TABSTOP));
- vishft();
- }
- } else if (inssiz + insmc1 > doomed)
- /*
- * No tabs, but line may still get deeper.
- */
- vneedpos(inssiz + insmc1 - doomed);
- /*
- * Now put in the inserted characters.
- */
- viin(c);
-
- /*
- * Now put the cursor in its final resting place.
- */
- destline = LINE(vcline);
- destcol = inscol + inssiz + insmc1 + filler;
- vcsync();
- if (IM != OIM) {
- IM = OIM;
- XN = OXN;
- }
- return c;
-}
-
-/*
- * Rigidify the rest of the line after the first
- * group of following tabs, typing blanks over ``spaces''.
- */
-void
-vrigid(void)
-{
- register int col;
- register cell *tp = vtube0 + tabend;
-
- for (col = tabend; col < linend; col++) {
- if ((*tp++ & TRIM) == 0) {
- endim();
- vgotoCL(col);
- vputchar(' ' | QUOTE);
- }
- }
-}
-
-/*
- * 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);
-}
-
-void
-vnpins(int dosync)
-{
- register int d = DEPTH(vcline);
- register int e;
-
- e = LINE(vcline) + DEPTH(vcline);
- if (e < LINE(vcline + 1)) {
- vigoto(e, 0);
- vclreol();
- return;
- }
- DEPTH(vcline)++;
- if (e < WECHO) {
- e = vglitchup(vcline, d);
- vigoto(e, 0); vclreol();
- if (dosync) {
- int (*Ooutchar)(int) = Outchar;
- Outchar = vputchar;
- vsync(e + 1);
- Outchar = Ooutchar;
- }
- } else {
- vup1();
- vigoto(WBOT, 0);
- vclreol();
- }
- vprepins();
-}
-
-/*
- * Do the shift of the next tabstop implied by
- * insertion so it expands.
- */
-void
-vishft(void)
-{
- int tshft = 0;
- int j;
- register int i;
- register cell *tp = vtube0;
- register cell *up;
- short oldhold = hold;
-
- shft = value(TABSTOP);
- hold |= HOLDPUPD;
- if (!IM && !EI) {
- /*
- * Dumb terminals are easy, we just have
- * to retype the text.
- */
- vigotoCL(tabend + shft);
- up = tp + tabend;
- for (i = tabend; i < linend; i++)
- vputchar(*up++);
- } else if (IN) {
- /*
- * CONCEPT-like terminals do most of the work for us,
- * we don't have to muck with simulation of multi-line
- * insert mode. Some of the shifting may come for free
- * also if the tabs don't have enough slack to take up
- * all the inserted characters.
- */
- i = shft;
- slakused = inssiz - doomed;
- if (slakused > tabslack) {
- i -= slakused - tabslack;
- slakused -= tabslack;
- }
- if (i > 0 && tabend != linend) {
- tshft = i;
- vgotoCL(tabend);
- goim();
- do
- vputchar(' ' | QUOTE);
- while (--i);
- }
- } else {
- /*
- * HP and Datamedia type terminals have to have multi-line
- * insert faked. Hack each segment after where we are
- * (going backwards to where we are.) We then can
- * hack the segment where the end of the first following
- * tab group is.
- */
- for (j = DEPTH(vcline) - 1; j > (tabend + shft) / WCOLS; j--) {
- vgotoCL(j * WCOLS);
- goim();
- up = tp + j * WCOLS - shft;
- i = shft;
- do {
- if (*up)
- vputchar(*up++);
- else
- break;
- } while (--i);
- }
- vigotoCL(tabstart);
- i = shft - (inssiz - doomed);
- if (i > 0) {
- tabslack = inssiz - doomed;
- vcsync();
- goim();
- do
- vputchar(' ');
- while (--i);
- }
- }
- /*
- * Now do the data moving in the internal screen
- * image which is common to all three cases.
- */
- tp += linend;
- up = tp + shft;
- i = linend - tabend;
- if (i > 0)
- do
- *--up = *--tp;
- while (--i);
- if (IN && tshft) {
- i = tshft;
- do
- *--up = ' ' | QUOTE;
- while (--i);
- }
- hold = oldhold;
-}
-
-/*
- * 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;
-}
-
-/*
- * 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);
-}
-
-/*
- * 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);
-}
-
-/*
- * 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;
-}
-
-void
-endim(void)
-{
-
- if (insmode) {
- vputp(EI, 0);
- insmode = 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) {
- if ((d = colsc(c&TRIM&~MULTICOL)) > 1) {
- if ((hold & HOLDPUPD) == 0)
- *tp |= MULTICOL;
- while (--d) {
- if ((hold & HOLDPUPD) == 0)
- *++tp = MULTICOL;
- destcol++;
- outcol++;
- }
- } else if (d == 0) {
- destcol--;
- outcol--;
- }
- }
-#endif /* MB */
- return c;
-}
-
-/*
- * 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);
- }
-}
-
-#ifdef TRACE
-void
-tfixnl(void)
-{
-
- if (trubble || techoin)
- fprintf(trace, "\n");
- trubble = 0, techoin = 0;
-}
-
-void
-tvliny(void)
-{
- register int i;
-
- if (!trace)
- return;
- tfixnl();
- fprintf(trace, "vcnt = %d, vcline = %d, vliny = ", vcnt, vcline);
- for (i = 0; i <= vcnt; i++) {
- fprintf(trace, "%d", LINE(i));
- if (FLAGS(i) & VDIRT)
- fprintf(trace, "*");
- if (DEPTH(i) != 1)
- fprintf(trace, "<%d>", DEPTH(i));
- if (i < vcnt)
- fprintf(trace, " ");
- }
- fprintf(trace, "\n");
-}
-
-void
-tracec(int c)
-/* int c; /\* mjm: char --> int */
-{
-
- if (!techoin)
- trubble = 1;
- if (c == ESCAPE)
- fprintf(trace, "$");
- else if (c & QUOTE) /* mjm: for 3B (no sign extension) */
- fprintf(trace, "~%c", ctlof(c&TRIM));
- else if (c < ' ' || c == DELETE)
- fprintf(trace, "^%c", ctlof(c));
- else
- fprintf(trace, "%c", c);
-}
-#endif
-
-/*
- * Put a character with possible tracing.
- */
-int
-vputch(int c)
-{
-
-#ifdef TRACE
- if (trace)
- tracec(c);
-#endif
- return vputc(c);
-}