From 15bd7946cc838a3151c357e4b0bc1ab85eecda62 Mon Sep 17 00:00:00 2001 From: Thomas Ulmer Date: Mon, 23 Feb 2026 16:54:28 -0800 Subject: add musl and vi --- ex_vops.c | 1071 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1071 insertions(+) create mode 100644 ex_vops.c (limited to 'ex_vops.c') diff --git a/ex_vops.c b/ex_vops.c new file mode 100644 index 0000000..f9a7aa5 --- /dev/null +++ b/ex_vops.c @@ -0,0 +1,1071 @@ +/* + * 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_vops.c 1.28 (gritter) 8/4/05"; +#endif +#endif + +/* from ex_vops.c 7.7 (Berkeley) 6/7/85 */ + +#include "ex.h" +#include "ex_tty.h" +#include "ex_vis.h" + +/* + * This file defines the operation sequences which interface the + * logical changes to the file buffer with the internal and external + * display representations. + */ + +/* + * Undo. + * + * Undo is accomplished in two ways. We often for small changes in the + * current line know how (in terms of a change operator) how the change + * occurred. Thus on an intelligent terminal we can undo the operation + * by another such operation, using insert and delete character + * stuff. The pointers vU[AD][12] index the buffer vutmp when this + * is possible and provide the necessary information. + * + * The other case is that the change involved multiple lines or that + * we have moved away from the line or forgotten how the change was + * accomplished. In this case we do a redisplay and hope that the + * low level optimization routines (which don't look for winning + * via insert/delete character) will not lose too badly. + */ +char *vUA1, *vUA2; +char *vUD1, *vUD2; + +void +vUndo(void) +{ + + /* + * Avoid UU which clobbers ability to do u. + */ + if (vundkind == VCAPU || vUNDdot != dot) { + beep(); + return; + } + CP(vutmp, linebuf); + vUD1 = linebuf; vUD2 = strend(linebuf); + putmk1(dot, vUNDsav); + getDOT(); + vUA1 = linebuf; vUA2 = strend(linebuf); + vundkind = VCAPU; + if (state == ONEOPEN || state == HARDOPEN) { + vjumpto(dot, vUNDcurs, 0); + return; + } + vdirty(vcline, 1); + vsyncCL(); + cursor = linebuf; + vfixcurs(); +} + +void +vundo ( + int show /* if true update the screen */ +) +{ + register int cnt; + register line *addr; + register char *cp; + char *temp = smalloc(LBSIZE); + bool savenote; + int (*OO)(int); + short oldhold = hold; + + switch (vundkind) { + + case VMANYINS: + wcursor = 0; + addr1 = undap1; + addr2 = undap2 - 1; + vsave(); + YANKreg('1'); + notecnt = 0; + /* fall into ... */ + + case VMANY: + case VMCHNG: + vsave(); + addr = dot - vcline; + notecnt = 1; + if (undkind == UNDPUT && undap1 == undap2) { + beep(); + break; + } + /* + * Undo() call below basically replaces undap1 to undap2-1 + * with dol through unddol-1. Hack screen image to + * reflect this replacement. + */ + if (show) + if (undkind == UNDMOVE) + vdirty(0, TLINES); + else + vreplace(undap1 - addr, undap2 - undap1, + undkind == UNDPUT ? 0 : unddol - dol); + savenote = notecnt; + undo(1); + if (show && (vundkind != VMCHNG || addr != dot)) + killU(); + vundkind = VMANY; + cnt = dot - addr; + if (cnt < 0 || cnt > vcnt || state != VISUAL) { + if (show) + vjumpto(dot, NOSTR, '.'); + break; + } + if (!savenote) + notecnt = 0; + if (show) { + vcline = cnt; + vrepaint(vmcurs); + } + vmcurs = 0; + break; + + case VCHNG: + case VCAPU: + vundkind = VCHNG; + CP(temp, vutmp); + CP(vutmp, linebuf); + doomed = column(vUA2 - 1) - column(vUA1 - 1); + strcLIN(temp); + cp = vUA1; vUA1 = vUD1; vUD1 = cp; + cp = vUA2; vUA2 = vUD2; vUD2 = cp; + if (!show) + break; + cursor = vUD1; + if (state == HARDOPEN) { + doomed = 0; + vsave(); + vopen(dot, WBOT); + vnline(cursor); + break; + } + /* + * Pseudo insert command. + */ + vcursat(cursor); + OO = Outchar; Outchar = vinschar; hold |= HOLDQIK; + vprepins(); + temp[vUA2 - linebuf] = 0; + for (cp = &temp[vUA1 - linebuf]; *cp;) { + int c, n; + nextc(c, cp, n); + cp += n; + putchar(c); + } + Outchar = OO; hold = oldhold; + endim(); + physdc(cindent(), cindent() + doomed); + doomed = 0; + vdirty(vcline, 1); + vsyncCL(); + if (cursor > linebuf && cursor >= strend(linebuf)) + cursor += skipleft(linebuf, cursor); + vfixcurs(); + break; + + case VNONE: + beep(); + break; + } + free(temp); +} + +/* + * Routine to handle a change inside a macro. + * Fromvis is true if we were called from a visual command (as + * opposed to an ex command). This has nothing to do with being + * in open/visual mode as :s/foo/bar is not fromvis. + */ +void +vmacchng(int fromvis) +{ + line *savedot, *savedol; + char *savecursor; + char *savelb; + int nlines, more; + /* register line *a1, *a2; */ + /* char ch; */ /* DEBUG */ + + if (!inopen) + return; + if (!vmacp) + vch_mac = VC_NOTINMAC; +#ifdef TRACE + if (trace) + fprintf(trace, "vmacchng, vch_mac=%d, linebuf='%s', *dot=%o\n", vch_mac, linebuf, *dot); +#endif + if (vmacp && fromvis) + vsave(); +#ifdef TRACE + if (trace) + fprintf(trace, "after vsave, linebuf='%s', *dot=%o\n", linebuf, *dot); +#endif + switch(vch_mac) { + case VC_NOCHANGE: + vch_mac = VC_ONECHANGE; + break; + case VC_ONECHANGE: + savelb = smalloc(LBSIZE); + /* Save current state somewhere */ +#ifdef TRACE + vudump("before vmacchng hairy case"); +#endif + savedot = dot; savedol = dol; savecursor = cursor; + CP(savelb, linebuf); + nlines = dol - zero; + while ((line *) endcore - truedol < nlines) + morelines(); + copyw(truedol+1, zero+1, nlines); + truedol += nlines; + +#ifdef TRACE + visdump("before vundo"); +#endif + /* Restore state as it was at beginning of macro */ + vundo(0); +#ifdef TRACE + visdump("after vundo"); + vudump("after vundo"); +#endif + + /* Do the saveall we should have done then */ + saveall(); +#ifdef TRACE + vudump("after saveall"); +#endif + + /* Restore current state from where saved */ + more = savedol - dol; /* amount we shift everything by */ + if (more) + (*(more>0 ? copywR : copyw))(savedol+1, dol+1, truedol-dol); + unddol += more; truedol += more; undap2 += more; + + truedol -= nlines; + copyw(zero+1, truedol+1, nlines); + dot = savedot; dol = savedol ; cursor = savecursor; + CP(linebuf, savelb); + vch_mac = VC_MANYCHANGE; + + /* Arrange that no further undo saving happens within macro */ + otchng = tchng; /* Copied this line blindly - bug? */ + inopen = -1; /* no need to save since it had to be 1 or -1 before */ + vundkind = VMANY; +#ifdef TRACE + vudump("after vmacchng"); +#endif + free(savelb); + break; + case VC_NOTINMAC: + case VC_MANYCHANGE: + /* Nothing to do for various reasons. */ + break; + } +} + +/* + * Initialize undo information before an append. + */ +void +vnoapp(void) +{ + + vUD1 = vUD2 = cursor; +} + +/* + * All the rest of the motion sequences have one or more + * cases to deal with. In the case wdot == 0, operation + * is totally within current line, from cursor to wcursor. + * If wdot is given, but wcursor is 0, then operation affects + * the inclusive line range. The hardest case is when both wdot + * and wcursor are given, then operation affects from line dot at + * cursor to line wdot at wcursor. + */ + +/* + * Move is simple, except for moving onto new lines in hardcopy open mode. + */ +/*ARGSUSED*/ +void +vmove(int unused) +{ + register int cnt; + + if (wdot) { + if (wdot < one || wdot > dol) { + beep(); + return; + } + cnt = wdot - dot; + wdot = NOLINE; + if (cnt) + killU(); + vupdown(cnt, wcursor); + return; + } + + /* + * When we move onto a new line, save information for U undo. + */ + if (vUNDdot != dot) { + vUNDsav = *dot; + vUNDcurs = wcursor; + vUNDdot = dot; + } + + /* + * In hardcopy open, type characters to left of cursor + * on new line, or back cursor up if its to left of where we are. + * In any case if the current line is ``rubbled'' i.e. has trashy + * looking overstrikes on it or \'s from deletes, we reprint + * so it is more comprehensible (and also because we can't work + * if we let it get more out of sync since column() won't work right. + */ + if (state == HARDOPEN) { + register char *cp; + if (rubble) { + register int c; + int oldhold = hold; + + sethard(); + cp = wcursor; + c = *cp; + *cp = 0; + hold |= HOLDDOL; + vreopen(WTOP, lineDOT(), vcline); + hold = oldhold; + *cp = c; + } else if (wcursor > cursor) { + vfixcurs(); + for (cp = cursor; *cp && cp < wcursor;) { + int c, n; + nextc(c, cp, n); + cp += n; + c &= TRIM; + putchar(c ? c : ' '); + } + } + } + vsetcurs(wcursor); +} + +/* + * Delete operator. + * + * Hard case of deleting a range where both wcursor and wdot + * are specified is treated as a special case of change and handled + * by vchange (although vchange may pass it back if it degenerates + * to a full line range delete.) + */ +void +vdelete(int c) +{ + register char *cp; + register int i; + + if (wdot) { + if (wcursor) { + vchange(EOF); + return; + } + if ((i = xdw()) < 0) + return; + if (state != VISUAL) { + vgoto(LINE(0), 0); + vputchar('@'); + } + wdot = dot; + vremote(i, delete, 0); + notenam = "delete"; + DEL[0] = 0; + killU(); + vreplace(vcline, i, 0); + if (wdot > dol) + vcline--; + vrepaint(NOSTR); + return; + } + if (wcursor < linebuf) + wcursor = linebuf; + if (cursor == wcursor) { + beep(); + return; + } + i = vdcMID(); + cp = cursor; + setDEL(); + CP(cp, wcursor); + if (cp > linebuf && (cp[0] == 0 || c == '#')) + cp--; + if (state == HARDOPEN) { + bleep(i, cp); + cursor = cp; + return; + } + physdc(column(cursor + skipleft(linebuf, cursor)), i); + DEPTH(vcline) = 0; + vreopen(LINE(vcline), lineDOT(), vcline); + vsyncCL(); + vsetcurs(cp); +} + +/* + * Change operator. + * + * In a single line we mark the end of the changed area with '$'. + * On multiple whole lines, we clear the lines first. + * Across lines with both wcursor and wdot given, we delete + * and sync then append (but one operation for undo). + */ +void +vchange(int c) +{ + register char *cp; + register int i, ind, cnt; + line *addr; + + if (wdot) { + /* + * Change/delete of lines or across line boundaries. + */ + if ((cnt = xdw()) < 0) + return; + getDOT(); + if (wcursor && cnt == 1) { + /* + * Not really. + */ + wdot = 0; + if (c == EOF) { + vdelete(c); + return; + } + goto smallchange; + } + if (cursor && wcursor) { + /* + * Across line boundaries, but not + * necessarily whole lines. + * Construct what will be left. + */ + *cursor = 0; + strcpy(genbuf, linebuf); + getline(*wdot); + if (strlen(genbuf) + strlen(wcursor) > LBSIZE - 2) { + getDOT(); + beep(); + return; + } + strcat(genbuf, wcursor); + if (c == EOF && *vpastwh(genbuf) == 0) { + /* + * Although this is a delete + * spanning line boundaries, what + * would be left is all white space, + * so take it all away. + */ + wcursor = 0; + getDOT(); + op = 0; + notpart(lastreg); + notpart('1'); + vdelete(c); + return; + } + ind = -1; + } else if (c == EOF && wcursor == 0) { + vdelete(c); + return; + } else +#ifdef LISPCODE + /* + * We are just substituting text for whole lines, + * so determine the first autoindent. + */ + if (value(LISP) && value(AUTOINDENT)) + ind = lindent(dot); + else +#endif + ind = whitecnt(linebuf); + i = vcline >= 0 ? LINE(vcline) : WTOP; + + /* + * Delete the lines from the buffer, + * and remember how the partial stuff came about in + * case we are told to put. + */ + addr = dot; + vremote(cnt, delete, 0); + setpk(); + notenam = "delete"; + if (c != EOF) + notenam = "change"; + /* + * If DEL[0] were nonzero, put would put it back + * rather than the deleted lines. + */ + DEL[0] = 0; + if (cnt > 1) + killU(); + + /* + * Now hack the screen image coordination. + */ + vreplace(vcline, cnt, 0); + wdot = NOLINE; + noteit(0); + vcline--; + if (addr <= dol) + dot--; + + /* + * If this is a across line delete/change, + * cursor stays where it is; just splice together the pieces + * of the new line. Otherwise generate a autoindent + * after a S command. + */ + if (ind >= 0) { + *genindent(ind) = 0; + vdoappend(genbuf); + } else { + vmcurs = cursor; + strcLIN(genbuf); + vdoappend(linebuf); + } + + /* + * Indicate a change on hardcopies by + * erasing the current line. + */ + if (c != EOF && state != VISUAL && state != HARDOPEN) { + int oldhold = hold; + + hold |= HOLDAT, vclrlin(i, dot), hold = oldhold; + } + + /* + * Open the line (logically) on the screen, and + * update the screen tail. Unless we are really a delete + * go off and gather up inserted characters. + */ + vcline++; + if (vcline < 0) + vcline = 0; + vopen(dot, i); + vsyncCL(); + noteit(1); + if (c != EOF) { + if (ind >= 0) { + cursor = linebuf; + linebuf[0] = 0; + vfixcurs(); + } else { + ind = 0; + vcursat(cursor); + } + vappend('x', 1, ind); + return; + } + if (*cursor == 0 && cursor > linebuf) + cursor += skipleft(linebuf, cursor); + vrepaint(cursor); + return; + } + +smallchange: + /* + * The rest of this is just low level hacking on changes + * of small numbers of characters. + */ + if (wcursor < linebuf) + wcursor = linebuf; + if (cursor == wcursor) { + beep(); + return; + } + i = vdcMID(); + cp = cursor; + if (state != HARDOPEN) + vfixcurs(); + + /* + * Put out the \\'s indicating changed text in hardcopy, + * or mark the end of the change with $ if not hardcopy. + */ + if (state == HARDOPEN) + bleep(i, cp); + else { + int c, d, n; + vcursbef(wcursor); + d = skipleft(linebuf, wcursor); + nextc(c, &wcursor[d], n); + if (colsc(c) > 1) + putchar(' '); + putchar('$'); + i = cindent(); + } + + /* + * Remember the deleted text for possible put, + * and then prepare and execute the input portion of the change. + */ + cursor = cp; + setDEL(); + CP(cursor, wcursor); + if (state != HARDOPEN) { + vcursaft(cursor - 1); + doomed = i - cindent(); + } else { +/* + sethard(); + wcursor = cursor; + cursor = linebuf; + vgoto(outline, value(NUMBER) << 3); + vmove(); +*/ + doomed = 0; + } + prepapp(); + vappend('c', 1, 0); +} + +/* + * Open new lines. + * + * Tricky thing here is slowopen. This causes display updating + * to be held off so that 300 baud dumb terminals don't lose badly. + * This also suppressed counts, which otherwise say how many blank + * space to open up. Counts are also suppressed on intelligent terminals. + * Actually counts are obsoleted, since if your terminal is slow + * you are better off with slowopen. + */ +void +voOpen ( + int c, /* mjm: char --> int */ + register int cnt +) +{ + register int ind = 0, i; + short oldhold = hold; +#ifdef SIGWINCH + sigset_t set, oset; +#endif + + if (value(SLOWOPEN) || value(REDRAW) && AL && DL) + cnt = 1; +#ifdef SIGWINCH + sigemptyset(&set); + sigaddset(&set, SIGWINCH); + sigprocmask(SIG_BLOCK, &set, &oset); +#endif + vsave(); + setLAST(); + if (value(AUTOINDENT)) + ind = whitecnt(linebuf); + if (c == 'O') { + vcline--; + dot--; + if (dot > zero) + getDOT(); + } + if (value(AUTOINDENT)) { +#ifdef LISPCODE + if (value(LISP)) + ind = lindent(dot + 1); +#endif + } + killU(); + prepapp(); + if (FIXUNDO) + vundkind = VMANY; + if (state != VISUAL) + c = WBOT + 1; + else { + c = vcline < 0 ? WTOP - cnt : LINE(vcline) + DEPTH(vcline); + if (c < ZERO) + c = ZERO; + i = LINE(vcline + 1) - c; + if (i < cnt && c <= WBOT && (!AL || !DL)) + vinslin(c, cnt - i, vcline); + } + *genindent(ind) = 0; + vdoappend(genbuf); + vcline++; + oldhold = hold; + hold |= HOLDROL; + vopen(dot, c); + hold = oldhold; + if (value(SLOWOPEN)) + /* + * Oh, so lazy! + */ + vscrap(); + else + vsync1(LINE(vcline)); + cursor = linebuf; + linebuf[0] = 0; + vappend('o', 1, ind); +#ifdef SIGWINCH + sigprocmask(SIG_SETMASK, &oset, NULL); +#endif +} + +/* + * > < and = shift operators. + * + * Note that =, which aligns lisp, is just a ragged sort of shift, + * since it never distributes text between lines. + */ +char vshnam[2] = { 'x', 0 }; + +/*ARGSUSED*/ +void +vshftop(int unused) +{ + register line *addr; + register int cnt; + + if ((cnt = xdw()) < 0) + return; + addr = dot; + vremote(cnt, vshift, 0); + vshnam[0] = op; + notenam = vshnam; + dot = addr; + vreplace(vcline, cnt, cnt); + if (state == HARDOPEN) + vcnt = 0; + vrepaint(NOSTR); +} + +/* + * !. + * + * Filter portions of the buffer through unix commands. + */ +/*ARGSUSED*/ +void +vfilter(int unused) +{ + register line *addr; + register int cnt; + char *oglobp; + short d; +#ifdef BIT8 + cell cuxb[UXBSIZE + 2]; +#endif + + if ((cnt = xdw()) < 0) + return; + if (vglobp) +#ifdef BIT8 + vglobp = cuxb; +#else + vglobp = uxb; +#endif + if (readecho('!')) + return; + oglobp = globp; globp = genbuf + 1; + d = peekc; ungetchar(0); + CATCH + fixech(); + unix0(0); +#ifdef BIT8 + str2cell(cuxb, uxb); +#endif + ONERR + splitw = 0; + ungetchar(d); + vrepaint(cursor); + globp = oglobp; + return; + ENDCATCH + ungetchar(d); globp = oglobp; + addr = dot; + CATCH + vgoto(WECHO, 0); flusho(); + vremote(cnt, filter, 2); + ONERR + vdirty(0, TLINES); + ENDCATCH + if (dot == zero && dol > zero) + dot = one; + splitw = 0; + notenam = ""; + /* + * BUG: we shouldn't be depending on what undap2 and undap1 are, + * since we may be inside a macro. What's really wanted is the + * number of lines we read from the filter. However, the mistake + * will be an overestimate so it only results in extra work, + * it shouldn't cause any real screwups. + */ + vreplace(vcline, cnt, undap2 - undap1); + dot = addr; + if (dot > dol) { + dot--; + vcline--; + } + vrepaint(NOSTR); +} + +/* + * Xdw exchanges dot and wdot if appropriate and also checks + * that wdot is reasonable. Its name comes from + * xchange dotand wdot + */ +int +xdw(void) +{ + register char *cp; + register int cnt; +/* + register int notp = 0; + */ + + if (wdot == NOLINE || wdot < one || wdot > dol) { + beep(); + return (-1); + } + vsave(); + setLAST(); + if (dot > wdot || (dot == wdot && wcursor != 0 && cursor > wcursor)) { + register line *addr; + + vcline -= dot - wdot; + addr = dot; dot = wdot; wdot = addr; + cp = cursor; cursor = wcursor; wcursor = cp; + } + /* + * If a region is specified but wcursor is at the begining + * of the last line, then we move it to be the end of the + * previous line (actually off the end). + */ + if (cursor && wcursor == linebuf && wdot > dot) { + wdot--; + getDOT(); + if (vpastwh(linebuf) >= cursor) + wcursor = 0; + else { + getline(*wdot); + wcursor = strend(linebuf); + getDOT(); + } + /* + * Should prepare in caller for possible dot == wdot. + */ + } + cnt = wdot - dot + 1; + if (vreg) { + vremote(cnt, YANKreg, vreg); +/* + if (notp) + notpart(vreg); + */ + } + + /* + * Kill buffer code. If delete operator is c or d, then save + * the region in numbered buffers. + * + * BUG: This may be somewhat inefficient due + * to the way named buffer are implemented, + * necessitating some optimization. + */ + vreg = 0; + if (any(op, "cd")) { + vremote(cnt, YANKreg, '1'); +/* + if (notp) + notpart('1'); + */ + } + return (cnt); +} + +/* + * Routine for vremote to call to implement shifts. + */ +/*ARGSUSED*/ +void +vshift(int unused) +{ + + shift(op, 1); +} + +/* + * Replace a single character with the next input character. + * A funny kind of insert. + */ +void +vrep(register int cnt) +{ + register int i, c; + + if (cnt > strlen(cursor)) { + beep(); + return; + } + showmode('r'); + i = column(cursor + cnt - 1); + vcursat(cursor); + doomed = i - cindent(); + if (!vglobp) { + c = getesc(); + if (c == 0) { + showmode(0); + vfixcurs(); + return; + } + ungetkey(c); + } + CP(vutmp, linebuf); + if (FIXUNDO) + vundkind = VCHNG; + wcursor = cursor; + for (i = 0; i < cnt; i++) + wcursor += skipright(cursor, wcursor); + vUD1 = cursor; vUD2 = wcursor; + CP(cursor, wcursor); + prepapp(); + vappend('r', cnt, 0); + *lastcp++ = INS[0]; + setLAST(); +} + +/* + * Yank. + * + * Yanking to string registers occurs for free (essentially) + * in the routine xdw(). + */ +/*ARGSUSED*/ +void +vyankit(int unused) +{ + register int cnt; + + if (wdot) { + if ((cnt = xdw()) < 0) + return; + vremote(cnt, yank, 0); + setpk(); + notenam = "yank"; + if (FIXUNDO) + vundkind = VNONE; + DEL[0] = 0; + wdot = NOLINE; + if (notecnt <= vcnt - vcline && notecnt < value(REPORT)) + notecnt = 0; + vrepaint(cursor); + return; + } + takeout(DEL); +} + +/* + * Set pkill variables so a put can + * know how to put back partial text. + * This is necessary because undo needs the complete + * line images to be saved, while a put wants to trim + * the first and last lines. The compromise + * is for put to be more clever. + */ +void +setpk(void) +{ + + if (wcursor) { + pkill[0] = cursor; + pkill[1] = wcursor; + } +} + +/* + * Kill the last deleted part of a line so that "p" does not put it back. + * This is to be called from ex commands that delete some text. + */ +void +vkillDEL(void) +{ + DEL[0] = 0; +} -- cgit v1.2.3