10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 23500Sceastha * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 280Sstevel@tonic-gate /* All Rights Reserved */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate 310Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */ 320Sstevel@tonic-gate 330Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 340Sstevel@tonic-gate 350Sstevel@tonic-gate #include "ex.h" 360Sstevel@tonic-gate #include "ex_tty.h" 370Sstevel@tonic-gate #include "ex_vis.h" 380Sstevel@tonic-gate 390Sstevel@tonic-gate /* 400Sstevel@tonic-gate * This file defines the operation sequences which interface the 410Sstevel@tonic-gate * logical changes to the file buffer with the internal and external 420Sstevel@tonic-gate * display representations. 430Sstevel@tonic-gate */ 440Sstevel@tonic-gate 450Sstevel@tonic-gate /* 460Sstevel@tonic-gate * Undo. 470Sstevel@tonic-gate * 480Sstevel@tonic-gate * Undo is accomplished in two ways. We often for small changes in the 490Sstevel@tonic-gate * current line know how (in terms of a change operator) how the change 500Sstevel@tonic-gate * occurred. Thus on an intelligent terminal we can undo the operation 510Sstevel@tonic-gate * by another such operation, using insert and delete character 520Sstevel@tonic-gate * stuff. The pointers vU[AD][12] index the buffer vutmp when this 530Sstevel@tonic-gate * is possible and provide the necessary information. 540Sstevel@tonic-gate * 550Sstevel@tonic-gate * The other case is that the change involved multiple lines or that 560Sstevel@tonic-gate * we have moved away from the line or forgotten how the change was 570Sstevel@tonic-gate * accomplished. In this case we do a redisplay and hope that the 580Sstevel@tonic-gate * low level optimization routines (which don't look for winning 590Sstevel@tonic-gate * via insert/delete character) will not lose too badly. 600Sstevel@tonic-gate */ 610Sstevel@tonic-gate unsigned char *vUA1, *vUA2; 620Sstevel@tonic-gate unsigned char *vUD1, *vUD2; 630Sstevel@tonic-gate 64*802Scf46844 void 65*802Scf46844 vUndo(void) 660Sstevel@tonic-gate { 670Sstevel@tonic-gate 680Sstevel@tonic-gate /* 690Sstevel@tonic-gate * Avoid UU which clobbers ability to do u. 700Sstevel@tonic-gate */ 710Sstevel@tonic-gate if (vundkind == VNONE || vundkind == VCAPU || vUNDdot != dot) { 72*802Scf46844 (void) beep(); 730Sstevel@tonic-gate return; 740Sstevel@tonic-gate } 750Sstevel@tonic-gate CP(vutmp, linebuf); 760Sstevel@tonic-gate vUD1 = linebuf; vUD2 = strend(linebuf); 770Sstevel@tonic-gate putmk1(dot, vUNDsav); 780Sstevel@tonic-gate getDOT(); 790Sstevel@tonic-gate vUA1 = linebuf; vUA2 = strend(linebuf); 800Sstevel@tonic-gate vundkind = VCAPU; 810Sstevel@tonic-gate if (state == ONEOPEN || state == HARDOPEN) { 820Sstevel@tonic-gate vjumpto(dot, vUNDcurs, 0); 830Sstevel@tonic-gate return; 840Sstevel@tonic-gate } 850Sstevel@tonic-gate vdirty(vcline, 1); 860Sstevel@tonic-gate if(MB_CUR_MAX > 1) 870Sstevel@tonic-gate rewrite = _ON; 880Sstevel@tonic-gate vsyncCL(); 890Sstevel@tonic-gate if(MB_CUR_MAX > 1) 900Sstevel@tonic-gate rewrite = _OFF; 910Sstevel@tonic-gate cursor = linebuf; 920Sstevel@tonic-gate vfixcurs(); 930Sstevel@tonic-gate } 940Sstevel@tonic-gate 95*802Scf46844 void 960Sstevel@tonic-gate vundo(show) 970Sstevel@tonic-gate bool show; /* if true update the screen */ 980Sstevel@tonic-gate { 99*802Scf46844 int cnt; 100*802Scf46844 line *addr; 101*802Scf46844 unsigned char *cp; 1020Sstevel@tonic-gate unsigned char temp[LBSIZE]; 1030Sstevel@tonic-gate bool savenote; 1040Sstevel@tonic-gate int (*OO)(); 1050Sstevel@tonic-gate short oldhold = hold; 1060Sstevel@tonic-gate unsigned multic[MULTI_BYTE_MAX]; 1070Sstevel@tonic-gate int length; 1080Sstevel@tonic-gate wchar_t wchar; 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate switch (vundkind) { 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate case VMANYINS: 1130Sstevel@tonic-gate wcursor = 0; 1140Sstevel@tonic-gate addr1 = undap1; 1150Sstevel@tonic-gate addr2 = undap2 - 1; 1160Sstevel@tonic-gate vsave(); 117*802Scf46844 (void) YANKreg('1'); 1180Sstevel@tonic-gate notecnt = 0; 1190Sstevel@tonic-gate /* fall into ... */ 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate case VMANY: 1220Sstevel@tonic-gate case VMCHNG: 1230Sstevel@tonic-gate vsave(); 1240Sstevel@tonic-gate addr = dot - vcline; 1250Sstevel@tonic-gate notecnt = 1; 1260Sstevel@tonic-gate if (undkind == UNDPUT && undap1 == undap2) { 127*802Scf46844 (void) beep(); 1280Sstevel@tonic-gate break; 1290Sstevel@tonic-gate } 1300Sstevel@tonic-gate /* 1310Sstevel@tonic-gate * Undo() call below basically replaces undap1 to undap2-1 1320Sstevel@tonic-gate * with dol through unddol-1. Hack screen image to 1330Sstevel@tonic-gate * reflect this replacement. 1340Sstevel@tonic-gate */ 1350Sstevel@tonic-gate if (show) 1360Sstevel@tonic-gate if (undkind == UNDMOVE) 1370Sstevel@tonic-gate vdirty(0, lines); 1380Sstevel@tonic-gate else 1390Sstevel@tonic-gate vreplace(undap1 - addr, undap2 - undap1, 1400Sstevel@tonic-gate undkind == UNDPUT ? 0 : unddol - dol); 1410Sstevel@tonic-gate savenote = notecnt; 1420Sstevel@tonic-gate undo(1); 1430Sstevel@tonic-gate if (show && (vundkind != VMCHNG || addr != dot)) 1440Sstevel@tonic-gate killU(); 1450Sstevel@tonic-gate vundkind = VMANY; 1460Sstevel@tonic-gate cnt = dot - addr; 1470Sstevel@tonic-gate if (cnt < 0 || cnt > vcnt || state != VISUAL) { 1480Sstevel@tonic-gate if (show) 149*802Scf46844 vjumpto(dot, (unsigned char *)NOSTR, '.'); 1500Sstevel@tonic-gate break; 1510Sstevel@tonic-gate } 1520Sstevel@tonic-gate if (!savenote) 1530Sstevel@tonic-gate notecnt = 0; 1540Sstevel@tonic-gate if (show) { 1550Sstevel@tonic-gate vcline = cnt; 1560Sstevel@tonic-gate if(MB_CUR_MAX > 1) 1570Sstevel@tonic-gate rewrite = _ON; 1580Sstevel@tonic-gate vrepaint(vmcurs); 1590Sstevel@tonic-gate if(MB_CUR_MAX > 1) 1600Sstevel@tonic-gate rewrite = _OFF; 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate vmcurs = 0; 1630Sstevel@tonic-gate break; 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate case VCHNG: 1660Sstevel@tonic-gate case VCAPU: 1670Sstevel@tonic-gate vundkind = VCHNG; 1680Sstevel@tonic-gate strcpy(temp, vutmp); 1690Sstevel@tonic-gate strcpy(vutmp, linebuf); 1700Sstevel@tonic-gate doomed = lcolumn(vUA2) - lcolumn(vUA1); 1710Sstevel@tonic-gate strcLIN(temp); 1720Sstevel@tonic-gate cp = vUA1; vUA1 = vUD1; vUD1 = cp; 1730Sstevel@tonic-gate cp = vUA2; vUA2 = vUD2; vUD2 = cp; 1740Sstevel@tonic-gate if (!show) 1750Sstevel@tonic-gate break; 1760Sstevel@tonic-gate cursor = vUD1; 1770Sstevel@tonic-gate if (state == HARDOPEN) { 1780Sstevel@tonic-gate doomed = 0; 1790Sstevel@tonic-gate vsave(); 1800Sstevel@tonic-gate vopen(dot, WBOT); 1810Sstevel@tonic-gate vnline(cursor); 1820Sstevel@tonic-gate break; 1830Sstevel@tonic-gate } 1840Sstevel@tonic-gate /* 1850Sstevel@tonic-gate * Pseudo insert command. 1860Sstevel@tonic-gate */ 1870Sstevel@tonic-gate vcursat(cursor); 1880Sstevel@tonic-gate OO = Outchar; Outchar = vinschar; hold |= HOLDQIK; 1890Sstevel@tonic-gate vprepins(); 1900Sstevel@tonic-gate temp[vUA2 - linebuf] = 0; 1910Sstevel@tonic-gate for (cp = &temp[vUA1 - linebuf]; *cp;) { 1920Sstevel@tonic-gate length = mbtowc(&wchar, (char *)cp, MULTI_BYTE_MAX); 1930Sstevel@tonic-gate if(length < 0) { 1940Sstevel@tonic-gate putoctal = 1; 1950Sstevel@tonic-gate putchar(*cp++); 1960Sstevel@tonic-gate putoctal = 0; 1970Sstevel@tonic-gate } else { 1980Sstevel@tonic-gate putchar(wchar); 1990Sstevel@tonic-gate cp += length; 2000Sstevel@tonic-gate } 2010Sstevel@tonic-gate } 2020Sstevel@tonic-gate Outchar = OO; hold = oldhold; 2030Sstevel@tonic-gate endim(); 2040Sstevel@tonic-gate physdc(cindent(), cindent() + doomed); 2050Sstevel@tonic-gate doomed = 0; 2060Sstevel@tonic-gate vdirty(vcline, 1); 2070Sstevel@tonic-gate if(MB_CUR_MAX > 1) 2080Sstevel@tonic-gate rewrite = _ON; 2090Sstevel@tonic-gate vsyncCL(); 2100Sstevel@tonic-gate if(MB_CUR_MAX > 1) 2110Sstevel@tonic-gate rewrite = _OFF; 2120Sstevel@tonic-gate if (cursor > linebuf && cursor >= strend(linebuf)) 2130Sstevel@tonic-gate cursor = lastchr(linebuf, cursor); 2140Sstevel@tonic-gate vfixcurs(); 2150Sstevel@tonic-gate break; 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate case VNONE: 218*802Scf46844 (void) beep(); 2190Sstevel@tonic-gate break; 2200Sstevel@tonic-gate } 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate /* 2240Sstevel@tonic-gate * Routine to handle a change inside a macro. 2250Sstevel@tonic-gate * Fromvis is true if we were called from a visual command (as 2260Sstevel@tonic-gate * opposed to an ex command). This has nothing to do with being 2270Sstevel@tonic-gate * in open/visual mode as :s/foo/bar is not fromvis. 2280Sstevel@tonic-gate */ 229*802Scf46844 void 2300Sstevel@tonic-gate vmacchng(fromvis) 2310Sstevel@tonic-gate bool fromvis; 2320Sstevel@tonic-gate { 2330Sstevel@tonic-gate line *savedot, *savedol; 2340Sstevel@tonic-gate unsigned char *savecursor; 2350Sstevel@tonic-gate unsigned char savelb[LBSIZE]; 2360Sstevel@tonic-gate int nlines, more; 237*802Scf46844 line *a1, *a2; 2380Sstevel@tonic-gate unsigned char ch; /* DEBUG */ 2390Sstevel@tonic-gate int copyw(), copywR(); 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate if (!inopen) 2420Sstevel@tonic-gate return; 2430Sstevel@tonic-gate if (!vmacp) 2440Sstevel@tonic-gate vch_mac = VC_NOTINMAC; 2450Sstevel@tonic-gate #ifdef UNDOTRACE 2460Sstevel@tonic-gate if (trace) 2470Sstevel@tonic-gate fprintf(trace, "vmacchng, vch_mac=%d, linebuf='%s', *dot=%o\n", vch_mac, linebuf, *dot); 2480Sstevel@tonic-gate #endif 2490Sstevel@tonic-gate if (vmacp && fromvis) 2500Sstevel@tonic-gate vsave(); 2510Sstevel@tonic-gate #ifdef UNDOTRACE 2520Sstevel@tonic-gate if (trace) 2530Sstevel@tonic-gate fprintf(trace, "after vsave, linebuf='%s', *dot=%o\n", linebuf, *dot); 2540Sstevel@tonic-gate #endif 2550Sstevel@tonic-gate switch(vch_mac) { 2560Sstevel@tonic-gate case VC_NOCHANGE: 2570Sstevel@tonic-gate vch_mac = VC_ONECHANGE; 2580Sstevel@tonic-gate break; 2590Sstevel@tonic-gate case VC_ONECHANGE: 2600Sstevel@tonic-gate /* Save current state somewhere */ 2610Sstevel@tonic-gate #ifdef UNDOTRACE 2620Sstevel@tonic-gate vudump("before vmacchng hairy case"); 2630Sstevel@tonic-gate #endif 2640Sstevel@tonic-gate savedot = dot; savedol = dol; savecursor = cursor; 2650Sstevel@tonic-gate CP(savelb, linebuf); 2660Sstevel@tonic-gate nlines = dol - zero; 2670Sstevel@tonic-gate while ((line *) endcore - truedol < nlines) 2680Sstevel@tonic-gate if (morelines() < 0) 2690Sstevel@tonic-gate return; /* or could be fatal error */ 2700Sstevel@tonic-gate copyw(truedol+1, zero+1, nlines); 2710Sstevel@tonic-gate truedol += nlines; 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate #ifdef UNDOTRACE 2740Sstevel@tonic-gate visdump("before vundo"); 2750Sstevel@tonic-gate #endif 2760Sstevel@tonic-gate /* Restore state as it was at beginning of macro */ 2770Sstevel@tonic-gate vundo(0); 2780Sstevel@tonic-gate #ifdef UNDOTRACE 2790Sstevel@tonic-gate visdump("after vundo"); 2800Sstevel@tonic-gate vudump("after vundo"); 2810Sstevel@tonic-gate #endif 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate /* Do the saveall we should have done then */ 2840Sstevel@tonic-gate saveall(); 2850Sstevel@tonic-gate #ifdef UNDOTRACE 2860Sstevel@tonic-gate vudump("after saveall"); 2870Sstevel@tonic-gate #endif 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate /* Restore current state from where saved */ 2900Sstevel@tonic-gate more = savedol - dol; /* amount we shift everything by */ 2910Sstevel@tonic-gate if (more) 2920Sstevel@tonic-gate (*(more>0 ? copywR : copyw))(savedol+1, dol+1, truedol-dol); 2930Sstevel@tonic-gate unddol += more; truedol += more; undap2 += more; 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate truedol -= nlines; 2960Sstevel@tonic-gate copyw(zero+1, truedol+1, nlines); 2970Sstevel@tonic-gate dot = savedot; dol = savedol ; cursor = savecursor; 2980Sstevel@tonic-gate CP(linebuf, savelb); 2990Sstevel@tonic-gate vch_mac = VC_MANYCHANGE; 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate /* Arrange that no further undo saving happens within macro */ 3020Sstevel@tonic-gate otchng = tchng; /* Copied this line blindly - bug? */ 3030Sstevel@tonic-gate inopen = -1; /* no need to save since it had to be 1 or -1 before */ 3040Sstevel@tonic-gate vundkind = VMANY; 3050Sstevel@tonic-gate #ifdef UNDOTRACE 3060Sstevel@tonic-gate vudump("after vmacchng"); 3070Sstevel@tonic-gate #endif 3080Sstevel@tonic-gate break; 3090Sstevel@tonic-gate case VC_NOTINMAC: 3100Sstevel@tonic-gate case VC_MANYCHANGE: 3110Sstevel@tonic-gate /* Nothing to do for various reasons. */ 3120Sstevel@tonic-gate break; 3130Sstevel@tonic-gate } 3140Sstevel@tonic-gate } 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate /* 3170Sstevel@tonic-gate * Initialize undo information before an append. 3180Sstevel@tonic-gate */ 319*802Scf46844 void 320*802Scf46844 vnoapp(void) 3210Sstevel@tonic-gate { 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate vUD1 = vUD2 = cursor; 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate /* 3270Sstevel@tonic-gate * All the rest of the motion sequences have one or more 3280Sstevel@tonic-gate * cases to deal with. In the case wdot == 0, operation 3290Sstevel@tonic-gate * is totally within current line, from cursor to wcursor. 3300Sstevel@tonic-gate * If wdot is given, but wcursor is 0, then operation affects 3310Sstevel@tonic-gate * the inclusive line range. The hardest case is when both wdot 3320Sstevel@tonic-gate * and wcursor are given, then operation affects from line dot at 3330Sstevel@tonic-gate * cursor to line wdot at wcursor. 3340Sstevel@tonic-gate */ 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate /* 3370Sstevel@tonic-gate * Move is simple, except for moving onto new lines in hardcopy open mode. 3380Sstevel@tonic-gate */ 339*802Scf46844 int 340*802Scf46844 vmove(void) 3410Sstevel@tonic-gate { 342*802Scf46844 int cnt; 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate if (wdot) { 3450Sstevel@tonic-gate if (wdot < one || wdot > dol) { 346*802Scf46844 (void) beep(); 347*802Scf46844 return (0); 3480Sstevel@tonic-gate } 3490Sstevel@tonic-gate cnt = wdot - dot; 3500Sstevel@tonic-gate wdot = NOLINE; 3510Sstevel@tonic-gate if (cnt) 3520Sstevel@tonic-gate killU(); 3530Sstevel@tonic-gate vupdown(cnt, wcursor); 354*802Scf46844 return (0); 3550Sstevel@tonic-gate } 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate /* 3580Sstevel@tonic-gate * When we move onto a new line, save information for U undo. 3590Sstevel@tonic-gate */ 3600Sstevel@tonic-gate if (vUNDdot != dot) { 3610Sstevel@tonic-gate vUNDsav = *dot; 3620Sstevel@tonic-gate vUNDcurs = wcursor; 3630Sstevel@tonic-gate vUNDdot = dot; 3640Sstevel@tonic-gate } 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate /* 3670Sstevel@tonic-gate * In hardcopy open, type characters to left of cursor 3680Sstevel@tonic-gate * on new line, or back cursor up if its to left of where we are. 3690Sstevel@tonic-gate * In any case if the current line is ``rubbled'' i.e. has trashy 3700Sstevel@tonic-gate * looking overstrikes on it or \'s from deletes, we reprint 3710Sstevel@tonic-gate * so it is more comprehensible (and also because we can't work 3720Sstevel@tonic-gate * if we let it get more out of sync since column() won't work right. 3730Sstevel@tonic-gate */ 3740Sstevel@tonic-gate if (state == HARDOPEN) { 375*802Scf46844 unsigned char *cp; 3760Sstevel@tonic-gate if (rubble) { 377*802Scf46844 int c; 3780Sstevel@tonic-gate int oldhold = hold; 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate sethard(); 3810Sstevel@tonic-gate cp = wcursor; 3820Sstevel@tonic-gate c = *cp; 3830Sstevel@tonic-gate *cp = 0; 3840Sstevel@tonic-gate hold |= HOLDDOL; 385*802Scf46844 (void) vreopen(WTOP, lineDOT(), vcline); 3860Sstevel@tonic-gate hold = oldhold; 3870Sstevel@tonic-gate *cp = c; 3880Sstevel@tonic-gate } else if (wcursor > cursor) { 389*802Scf46844 int length; 3900Sstevel@tonic-gate char multic[MULTI_BYTE_MAX]; 3910Sstevel@tonic-gate wchar_t wchar; 3920Sstevel@tonic-gate vfixcurs(); 3930Sstevel@tonic-gate for (cp = cursor; *cp && cp < wcursor;) { 3940Sstevel@tonic-gate length = mbtowc(&wchar, (char *)cp, MULTI_BYTE_MAX); 3950Sstevel@tonic-gate if(length == 0) 3960Sstevel@tonic-gate putchar(' '); 3970Sstevel@tonic-gate else if(length < 0) { 3980Sstevel@tonic-gate putoctal = 1; 3990Sstevel@tonic-gate putchar(*cp++); 4000Sstevel@tonic-gate putoctal = 0; 4010Sstevel@tonic-gate } else { 4020Sstevel@tonic-gate cp += length; 4030Sstevel@tonic-gate putchar(wchar); 4040Sstevel@tonic-gate } 4050Sstevel@tonic-gate } 4060Sstevel@tonic-gate } 4070Sstevel@tonic-gate } 4080Sstevel@tonic-gate vsetcurs(wcursor); 409*802Scf46844 return (0); 4100Sstevel@tonic-gate } 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate /* 4130Sstevel@tonic-gate * Delete operator. 4140Sstevel@tonic-gate * 4150Sstevel@tonic-gate * Hard case of deleting a range where both wcursor and wdot 4160Sstevel@tonic-gate * are specified is treated as a special case of change and handled 4170Sstevel@tonic-gate * by vchange (although vchange may pass it back if it degenerates 4180Sstevel@tonic-gate * to a full line range delete.) 4190Sstevel@tonic-gate */ 420*802Scf46844 int 421*802Scf46844 vdelete(unsigned char c) 4220Sstevel@tonic-gate { 423*802Scf46844 unsigned char *cp; 424*802Scf46844 int i; 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate if (wdot) { 4270Sstevel@tonic-gate if (wcursor) { 428*802Scf46844 (void) vchange('d'); 429*802Scf46844 return (0); 4300Sstevel@tonic-gate } 4310Sstevel@tonic-gate if ((i = xdw()) < 0) 432*802Scf46844 return (0); 4330Sstevel@tonic-gate if (state != VISUAL) { 4340Sstevel@tonic-gate vgoto(LINE(0), 0); 435*802Scf46844 (void) vputchar('@'); 4360Sstevel@tonic-gate } 4370Sstevel@tonic-gate wdot = dot; 4380Sstevel@tonic-gate vremote(i, delete, 0); 4390Sstevel@tonic-gate notenam = (unsigned char *)"delete"; 4400Sstevel@tonic-gate DEL[0] = 0; 4410Sstevel@tonic-gate killU(); 4420Sstevel@tonic-gate vreplace(vcline, i, 0); 4430Sstevel@tonic-gate if (wdot > dol) 4440Sstevel@tonic-gate vcline--; 4450Sstevel@tonic-gate vrepaint(NOSTR); 446*802Scf46844 return (0); 4470Sstevel@tonic-gate } 4480Sstevel@tonic-gate if (wcursor < linebuf) 4490Sstevel@tonic-gate wcursor = linebuf; 4500Sstevel@tonic-gate if (cursor == wcursor) { 451*802Scf46844 (void) beep(); 452*802Scf46844 return (0); 4530Sstevel@tonic-gate } 4540Sstevel@tonic-gate i = vdcMID(); 4550Sstevel@tonic-gate cp = cursor; 4560Sstevel@tonic-gate setDEL(); 4570Sstevel@tonic-gate CP(cp, wcursor); 4580Sstevel@tonic-gate if (cp > linebuf && (cp[0] == 0 || c == '#')) 4590Sstevel@tonic-gate cp = lastchr(linebuf, cp); 4600Sstevel@tonic-gate if (state == HARDOPEN) { 4610Sstevel@tonic-gate bleep(i, cp); 4620Sstevel@tonic-gate cursor = cp; 463*802Scf46844 return (0); 4640Sstevel@tonic-gate } 4650Sstevel@tonic-gate physdc(lcolumn(cursor), i); 4660Sstevel@tonic-gate DEPTH(vcline) = 0; 4670Sstevel@tonic-gate if(MB_CUR_MAX > 1) 4680Sstevel@tonic-gate rewrite = _ON; 469*802Scf46844 (void) vreopen(LINE(vcline), lineDOT(), vcline); 4700Sstevel@tonic-gate if(MB_CUR_MAX > 1) 4710Sstevel@tonic-gate rewrite = _OFF; 4720Sstevel@tonic-gate vsyncCL(); 4730Sstevel@tonic-gate vsetcurs(cp); 474*802Scf46844 return (0); 4750Sstevel@tonic-gate } 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate /* 4780Sstevel@tonic-gate * Change operator. 4790Sstevel@tonic-gate * 4800Sstevel@tonic-gate * In a single line we mark the end of the changed area with '$'. 4810Sstevel@tonic-gate * On multiple whole lines, we clear the lines first. 4820Sstevel@tonic-gate * Across lines with both wcursor and wdot given, we delete 4830Sstevel@tonic-gate * and sync then append (but one operation for undo). 4840Sstevel@tonic-gate */ 485*802Scf46844 int 486*802Scf46844 vchange(unsigned char c) 4870Sstevel@tonic-gate { 488*802Scf46844 unsigned char *cp; 489*802Scf46844 int i, ind, cnt; 4900Sstevel@tonic-gate line *addr; 4910Sstevel@tonic-gate 4920Sstevel@tonic-gate if (wdot) { 4930Sstevel@tonic-gate /* 4940Sstevel@tonic-gate * Change/delete of lines or across line boundaries. 4950Sstevel@tonic-gate */ 4960Sstevel@tonic-gate if ((cnt = xdw()) < 0) 497*802Scf46844 return (0); 4980Sstevel@tonic-gate getDOT(); 4990Sstevel@tonic-gate if (wcursor && cnt == 1) { 5000Sstevel@tonic-gate /* 5010Sstevel@tonic-gate * Not really. 5020Sstevel@tonic-gate */ 5030Sstevel@tonic-gate wdot = 0; 5040Sstevel@tonic-gate if (c == 'd') { 505*802Scf46844 (void) vdelete(c); 506*802Scf46844 return (0); 5070Sstevel@tonic-gate } 5080Sstevel@tonic-gate goto smallchange; 5090Sstevel@tonic-gate } 5100Sstevel@tonic-gate if (cursor && wcursor) { 5110Sstevel@tonic-gate /* 5120Sstevel@tonic-gate * Across line boundaries, but not 5130Sstevel@tonic-gate * necessarily whole lines. 5140Sstevel@tonic-gate * Construct what will be left. 5150Sstevel@tonic-gate */ 5160Sstevel@tonic-gate *cursor = 0; 5170Sstevel@tonic-gate strcpy(genbuf, linebuf); 5180Sstevel@tonic-gate getline(*wdot); 5190Sstevel@tonic-gate if (strlen(genbuf) + strlen(wcursor) > LBSIZE - 2) { 5200Sstevel@tonic-gate getDOT(); 521*802Scf46844 (void) beep(); 522*802Scf46844 return (0); 5230Sstevel@tonic-gate } 5240Sstevel@tonic-gate strcat(genbuf, wcursor); 5250Sstevel@tonic-gate if (c == 'd' && *vpastwh(genbuf) == 0) { 5260Sstevel@tonic-gate /* 5270Sstevel@tonic-gate * Although this is a delete 5280Sstevel@tonic-gate * spanning line boundaries, what 5290Sstevel@tonic-gate * would be left is all white space, 5300Sstevel@tonic-gate * so take it all away. 5310Sstevel@tonic-gate */ 5320Sstevel@tonic-gate wcursor = 0; 5330Sstevel@tonic-gate getDOT(); 5340Sstevel@tonic-gate op = 0; 5350Sstevel@tonic-gate notpart(lastreg); 5360Sstevel@tonic-gate notpart('1'); 537*802Scf46844 (void) vdelete(c); 538*802Scf46844 return (0); 5390Sstevel@tonic-gate } 5400Sstevel@tonic-gate ind = -1; 5410Sstevel@tonic-gate } else if (c == 'd' && wcursor == 0) { 542*802Scf46844 (void) vdelete(c); 543*802Scf46844 return (0); 5440Sstevel@tonic-gate } else 5450Sstevel@tonic-gate /* 5460Sstevel@tonic-gate * We are just substituting text for whole lines, 5470Sstevel@tonic-gate * so determine the first autoindent. 5480Sstevel@tonic-gate */ 5490Sstevel@tonic-gate if (value(vi_LISP) && value(vi_AUTOINDENT)) 5500Sstevel@tonic-gate ind = lindent(dot); 5510Sstevel@tonic-gate else 5520Sstevel@tonic-gate ind = whitecnt(linebuf); 5530Sstevel@tonic-gate i = vcline >= 0 ? LINE(vcline) : WTOP; 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate /* 5560Sstevel@tonic-gate * Delete the lines from the buffer, 5570Sstevel@tonic-gate * and remember how the partial stuff came about in 5580Sstevel@tonic-gate * case we are told to put. 5590Sstevel@tonic-gate */ 5600Sstevel@tonic-gate addr = dot; 5610Sstevel@tonic-gate vremote(cnt, delete, 0); 5620Sstevel@tonic-gate setpk(); 5630Sstevel@tonic-gate notenam = (unsigned char *)"delete"; 5640Sstevel@tonic-gate if (c != 'd') 5650Sstevel@tonic-gate notenam = (unsigned char *)"change"; 5660Sstevel@tonic-gate /* 5670Sstevel@tonic-gate * If DEL[0] were nonzero, put would put it back 5680Sstevel@tonic-gate * rather than the deleted lines. 5690Sstevel@tonic-gate */ 5700Sstevel@tonic-gate DEL[0] = 0; 5710Sstevel@tonic-gate if (cnt > 1) 5720Sstevel@tonic-gate killU(); 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate /* 5750Sstevel@tonic-gate * Now hack the screen image coordination. 5760Sstevel@tonic-gate */ 5770Sstevel@tonic-gate vreplace(vcline, cnt, 0); 5780Sstevel@tonic-gate wdot = NOLINE; 5790Sstevel@tonic-gate noteit(0); 5800Sstevel@tonic-gate vcline--; 5810Sstevel@tonic-gate if (addr <= dol) 5820Sstevel@tonic-gate dot--; 5830Sstevel@tonic-gate 5840Sstevel@tonic-gate /* 5850Sstevel@tonic-gate * If this is a across line delete/change, 5860Sstevel@tonic-gate * cursor stays where it is; just splice together the pieces 5870Sstevel@tonic-gate * of the new line. Otherwise generate a autoindent 5880Sstevel@tonic-gate * after a S command. 5890Sstevel@tonic-gate */ 5900Sstevel@tonic-gate if (ind >= 0) { 5910Sstevel@tonic-gate *genindent(ind) = 0; 5920Sstevel@tonic-gate vdoappend(genbuf); 5930Sstevel@tonic-gate } else { 5940Sstevel@tonic-gate vmcurs = cursor; 5950Sstevel@tonic-gate strcLIN(genbuf); 5960Sstevel@tonic-gate vdoappend(linebuf); 5970Sstevel@tonic-gate } 5980Sstevel@tonic-gate 5990Sstevel@tonic-gate /* 6000Sstevel@tonic-gate * Indicate a change on hardcopies by 6010Sstevel@tonic-gate * erasing the current line. 6020Sstevel@tonic-gate */ 6030Sstevel@tonic-gate if (c != 'd' && state != VISUAL && state != HARDOPEN) { 6040Sstevel@tonic-gate int oldhold = hold; 6050Sstevel@tonic-gate 6060Sstevel@tonic-gate hold |= HOLDAT, vclrlin(i, dot), hold = oldhold; 6070Sstevel@tonic-gate } 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate /* 6100Sstevel@tonic-gate * Open the line (logically) on the screen, and 6110Sstevel@tonic-gate * update the screen tail. Unless we are really a delete 6120Sstevel@tonic-gate * go off and gather up inserted characters. 6130Sstevel@tonic-gate */ 6140Sstevel@tonic-gate vcline++; 6150Sstevel@tonic-gate if (vcline < 0) 6160Sstevel@tonic-gate vcline = 0; 6170Sstevel@tonic-gate vopen(dot, i); 6180Sstevel@tonic-gate vsyncCL(); 6190Sstevel@tonic-gate noteit(1); 6200Sstevel@tonic-gate if (c != 'd') { 6210Sstevel@tonic-gate if (ind >= 0) { 6220Sstevel@tonic-gate cursor = linebuf; 6230Sstevel@tonic-gate linebuf[0] = 0; 6240Sstevel@tonic-gate vfixcurs(); 6250Sstevel@tonic-gate } else { 6260Sstevel@tonic-gate ind = 0; 6270Sstevel@tonic-gate vcursat(cursor); 6280Sstevel@tonic-gate } 6290Sstevel@tonic-gate vappend('x', 1, ind); 630*802Scf46844 return (0); 6310Sstevel@tonic-gate } 6320Sstevel@tonic-gate if (*cursor == 0 && cursor > linebuf) 6330Sstevel@tonic-gate cursor = lastchr(linebuf, cursor); 6340Sstevel@tonic-gate vrepaint(cursor); 635*802Scf46844 return (0); 6360Sstevel@tonic-gate } 6370Sstevel@tonic-gate 6380Sstevel@tonic-gate smallchange: 6390Sstevel@tonic-gate /* 6400Sstevel@tonic-gate * The rest of this is just low level hacking on changes 6410Sstevel@tonic-gate * of small numbers of characters. 6420Sstevel@tonic-gate */ 6430Sstevel@tonic-gate if (wcursor < linebuf) 6440Sstevel@tonic-gate wcursor = linebuf; 6450Sstevel@tonic-gate if (cursor == wcursor) { 646*802Scf46844 (void) beep(); 647*802Scf46844 return (0); 6480Sstevel@tonic-gate } 6490Sstevel@tonic-gate i = vdcMID(); 6500Sstevel@tonic-gate cp = cursor; 6510Sstevel@tonic-gate if (state != HARDOPEN) 6520Sstevel@tonic-gate vfixcurs(); 6530Sstevel@tonic-gate 6540Sstevel@tonic-gate /* 6550Sstevel@tonic-gate * Put out the \\'s indicating changed text in hardcopy, 6560Sstevel@tonic-gate * or mark the end of the change with $ if not hardcopy. 6570Sstevel@tonic-gate */ 6580Sstevel@tonic-gate if (state == HARDOPEN) 6590Sstevel@tonic-gate bleep(i, cp); 6600Sstevel@tonic-gate else { 6610Sstevel@tonic-gate vcursbef(wcursor); 6620Sstevel@tonic-gate putchar('$'); 6630Sstevel@tonic-gate i = cindent(); 6640Sstevel@tonic-gate } 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate /* 6670Sstevel@tonic-gate * Remember the deleted text for possible put, 6680Sstevel@tonic-gate * and then prepare and execute the input portion of the change. 6690Sstevel@tonic-gate */ 6700Sstevel@tonic-gate cursor = cp; 6710Sstevel@tonic-gate setDEL(); 6720Sstevel@tonic-gate CP(cursor, wcursor); 6730Sstevel@tonic-gate if (state != HARDOPEN) { 6740Sstevel@tonic-gate /* place cursor at beginning of changing text */ 6750Sstevel@tonic-gate vgotoCL(lcolumn(cp)); 6760Sstevel@tonic-gate doomed = i - cindent(); 6770Sstevel@tonic-gate } else { 6780Sstevel@tonic-gate /* 6790Sstevel@tonic-gate sethard(); 6800Sstevel@tonic-gate wcursor = cursor; 6810Sstevel@tonic-gate cursor = linebuf; 6820Sstevel@tonic-gate vgoto(outline, value(vi_NUMBER) << 3); 6830Sstevel@tonic-gate vmove(); 6840Sstevel@tonic-gate */ 6850Sstevel@tonic-gate doomed = 0; 6860Sstevel@tonic-gate } 6870Sstevel@tonic-gate prepapp(); 6880Sstevel@tonic-gate vappend('c', 1, 0); 689*802Scf46844 return (0); 6900Sstevel@tonic-gate } 6910Sstevel@tonic-gate 6920Sstevel@tonic-gate /* 6930Sstevel@tonic-gate * Open new lines. 6940Sstevel@tonic-gate * 6950Sstevel@tonic-gate * Tricky thing here is slowopen. This causes display updating 6960Sstevel@tonic-gate * to be held off so that 300 baud dumb terminals don't lose badly. 6970Sstevel@tonic-gate * This also suppressed counts, which otherwise say how many blank 6980Sstevel@tonic-gate * space to open up. Counts are also suppressed on intelligent terminals. 6990Sstevel@tonic-gate * Actually counts are obsoleted, since if your terminal is slow 7000Sstevel@tonic-gate * you are better off with slowopen. 7010Sstevel@tonic-gate */ 702*802Scf46844 void 703*802Scf46844 voOpen(int c, int cnt) 7040Sstevel@tonic-gate { 705*802Scf46844 int ind = 0, i; 7060Sstevel@tonic-gate short oldhold = hold; 7070Sstevel@tonic-gate 7080Sstevel@tonic-gate if (value(vi_SLOWOPEN) || value(vi_REDRAW) && insert_line && delete_line) 7090Sstevel@tonic-gate cnt = 1; 7100Sstevel@tonic-gate vsave(); 7110Sstevel@tonic-gate setLAST(); 7120Sstevel@tonic-gate if (value(vi_AUTOINDENT)) 7130Sstevel@tonic-gate ind = whitecnt(linebuf); 7140Sstevel@tonic-gate if (c == 'O') { 7150Sstevel@tonic-gate vcline--; 7160Sstevel@tonic-gate dot--; 7170Sstevel@tonic-gate if (dot > zero) 7180Sstevel@tonic-gate getDOT(); 7190Sstevel@tonic-gate } 7200Sstevel@tonic-gate if (value(vi_AUTOINDENT)) { 7210Sstevel@tonic-gate if (value(vi_LISP)) 7220Sstevel@tonic-gate ind = lindent(dot + 1); 7230Sstevel@tonic-gate } 7240Sstevel@tonic-gate killU(); 7250Sstevel@tonic-gate prepapp(); 7260Sstevel@tonic-gate if (FIXUNDO) 7270Sstevel@tonic-gate vundkind = VMANY; 7280Sstevel@tonic-gate if (state != VISUAL) 7290Sstevel@tonic-gate c = WBOT + 1; 7300Sstevel@tonic-gate else { 7310Sstevel@tonic-gate c = vcline < 0 ? WTOP - cnt : LINE(vcline) + DEPTH(vcline); 7320Sstevel@tonic-gate if (c < ZERO) 7330Sstevel@tonic-gate c = ZERO; 7340Sstevel@tonic-gate i = LINE(vcline + 1) - c; 7350Sstevel@tonic-gate if (i < cnt && c <= WBOT && (!insert_line || !delete_line)) 7360Sstevel@tonic-gate vinslin(c, cnt - i, vcline); 7370Sstevel@tonic-gate } 7380Sstevel@tonic-gate *genindent(ind) = 0; 7390Sstevel@tonic-gate vdoappend(genbuf); 7400Sstevel@tonic-gate vcline++; 7410Sstevel@tonic-gate oldhold = hold; 7420Sstevel@tonic-gate hold |= HOLDROL; 7430Sstevel@tonic-gate vopen(dot, c); 7440Sstevel@tonic-gate hold = oldhold; 7450Sstevel@tonic-gate if (value(vi_SLOWOPEN)) 7460Sstevel@tonic-gate /* 7470Sstevel@tonic-gate * Oh, so lazy! 7480Sstevel@tonic-gate */ 7490Sstevel@tonic-gate vscrap(); 7500Sstevel@tonic-gate else 7510Sstevel@tonic-gate vsync1(LINE(vcline)); 7520Sstevel@tonic-gate cursor = linebuf; 7530Sstevel@tonic-gate linebuf[0] = 0; 7540Sstevel@tonic-gate vappend('o', 1, ind); 7550Sstevel@tonic-gate } 7560Sstevel@tonic-gate 7570Sstevel@tonic-gate /* 7580Sstevel@tonic-gate * > < and = shift operators. 7590Sstevel@tonic-gate * 7600Sstevel@tonic-gate * Note that =, which aligns lisp, is just a ragged sort of shift, 7610Sstevel@tonic-gate * since it never distributes text between lines. 7620Sstevel@tonic-gate */ 7630Sstevel@tonic-gate unsigned char vshnam[2] = { 'x', 0 }; 7640Sstevel@tonic-gate 765*802Scf46844 int 766*802Scf46844 vshftop(void) 7670Sstevel@tonic-gate { 768*802Scf46844 line *addr; 769*802Scf46844 int cnt; 7700Sstevel@tonic-gate 7710Sstevel@tonic-gate if ((cnt = xdw()) < 0) 772*802Scf46844 return (0); 7730Sstevel@tonic-gate addr = dot; 7740Sstevel@tonic-gate vremote(cnt, vshift, 0); 7750Sstevel@tonic-gate vshnam[0] = op; 7760Sstevel@tonic-gate notenam = vshnam; 7770Sstevel@tonic-gate dot = addr; 7780Sstevel@tonic-gate vreplace(vcline, cnt, cnt); 7790Sstevel@tonic-gate if (state == HARDOPEN) 7800Sstevel@tonic-gate vcnt = 0; 7810Sstevel@tonic-gate vrepaint(NOSTR); 782*802Scf46844 return (0); 7830Sstevel@tonic-gate } 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate /* 7860Sstevel@tonic-gate * !. 7870Sstevel@tonic-gate * 7880Sstevel@tonic-gate * Filter portions of the buffer through unix commands. 7890Sstevel@tonic-gate */ 790*802Scf46844 int 791*802Scf46844 vfilter(void) 7920Sstevel@tonic-gate { 793*802Scf46844 line *addr; 794*802Scf46844 int cnt; 7950Sstevel@tonic-gate unsigned char *oglobp; 7960Sstevel@tonic-gate short d; 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate if ((cnt = xdw()) < 0) 799*802Scf46844 return (0); 8000Sstevel@tonic-gate if (vglobp) 8010Sstevel@tonic-gate vglobp = (unsigned char *)uxb; 8020Sstevel@tonic-gate if (readecho('!')) 803*802Scf46844 return (0); 8040Sstevel@tonic-gate oglobp = globp; globp = genbuf + 1; 8050Sstevel@tonic-gate d = peekc; ungetchar(0); 8060Sstevel@tonic-gate CATCH 8070Sstevel@tonic-gate fixech(); 808500Sceastha unix0(0, 0); 8090Sstevel@tonic-gate ONERR 8100Sstevel@tonic-gate splitw = 0; 8110Sstevel@tonic-gate ungetchar(d); 8120Sstevel@tonic-gate vrepaint(cursor); 8130Sstevel@tonic-gate globp = oglobp; 814*802Scf46844 return (0); 8150Sstevel@tonic-gate ENDCATCH 8160Sstevel@tonic-gate ungetchar(d); globp = oglobp; 8170Sstevel@tonic-gate addr = dot; 8180Sstevel@tonic-gate CATCH 8190Sstevel@tonic-gate vgoto(WECHO, 0); flusho(); 8200Sstevel@tonic-gate vremote(cnt, vi_filter, 2); 8210Sstevel@tonic-gate ONERR 8220Sstevel@tonic-gate vdirty(0, lines); 8230Sstevel@tonic-gate ENDCATCH 8240Sstevel@tonic-gate if (dot == zero && dol > zero) 8250Sstevel@tonic-gate dot = one; 8260Sstevel@tonic-gate splitw = 0; 8270Sstevel@tonic-gate notenam = (unsigned char *)""; 8280Sstevel@tonic-gate /* 8290Sstevel@tonic-gate * BUG: we shouldn't be depending on what undap2 and undap1 are, 8300Sstevel@tonic-gate * since we may be inside a macro. What's really wanted is the 8310Sstevel@tonic-gate * number of lines we read from the filter. However, the mistake 8320Sstevel@tonic-gate * will be an overestimate so it only results in extra work, 8330Sstevel@tonic-gate * it shouldn't cause any real mess-ups. 8340Sstevel@tonic-gate */ 8350Sstevel@tonic-gate vreplace(vcline, cnt, undap2 - undap1); 8360Sstevel@tonic-gate dot = addr; 8370Sstevel@tonic-gate if (dot > dol) { 8380Sstevel@tonic-gate dot--; 8390Sstevel@tonic-gate vcline--; 8400Sstevel@tonic-gate } 8410Sstevel@tonic-gate vrepaint(NOSTR); 842*802Scf46844 return (0); 8430Sstevel@tonic-gate } 8440Sstevel@tonic-gate 8450Sstevel@tonic-gate /* 8460Sstevel@tonic-gate * Xdw exchanges dot and wdot if appropriate and also checks 8470Sstevel@tonic-gate * that wdot is reasonable. Its name comes from 8480Sstevel@tonic-gate * xchange dotand wdot 8490Sstevel@tonic-gate */ 850*802Scf46844 int 851*802Scf46844 xdw(void) 8520Sstevel@tonic-gate { 853*802Scf46844 unsigned char *cp; 854*802Scf46844 int cnt; 8550Sstevel@tonic-gate /* 8560Sstevel@tonic-gate register int notp = 0; 8570Sstevel@tonic-gate */ 8580Sstevel@tonic-gate 8590Sstevel@tonic-gate if (wdot == NOLINE || wdot < one || wdot > dol) { 860*802Scf46844 (void) beep(); 8610Sstevel@tonic-gate return (-1); 8620Sstevel@tonic-gate } 8630Sstevel@tonic-gate vsave(); 8640Sstevel@tonic-gate setLAST(); 8650Sstevel@tonic-gate if (dot > wdot || (dot == wdot && wcursor != 0 && cursor > wcursor)) { 866*802Scf46844 line *addr; 8670Sstevel@tonic-gate 8680Sstevel@tonic-gate vcline -= dot - wdot; 8690Sstevel@tonic-gate addr = dot; dot = wdot; wdot = addr; 8700Sstevel@tonic-gate cp = cursor; cursor = wcursor; wcursor = cp; 8710Sstevel@tonic-gate } 8720Sstevel@tonic-gate /* 8730Sstevel@tonic-gate * If a region is specified but wcursor is at the beginning 8740Sstevel@tonic-gate * of the last line, then we move it to be the end of the 8750Sstevel@tonic-gate * previous line (actually off the end). 8760Sstevel@tonic-gate */ 8770Sstevel@tonic-gate if (cursor && wcursor == linebuf && wdot > dot) { 8780Sstevel@tonic-gate wdot--; 8790Sstevel@tonic-gate getDOT(); 8800Sstevel@tonic-gate if (vpastwh(linebuf) >= cursor) 8810Sstevel@tonic-gate wcursor = 0; 8820Sstevel@tonic-gate else { 8830Sstevel@tonic-gate getline(*wdot); 8840Sstevel@tonic-gate wcursor = strend(linebuf); 8850Sstevel@tonic-gate getDOT(); 8860Sstevel@tonic-gate } 8870Sstevel@tonic-gate /* 8880Sstevel@tonic-gate * Should prepare in caller for possible dot == wdot. 8890Sstevel@tonic-gate */ 8900Sstevel@tonic-gate } 8910Sstevel@tonic-gate cnt = wdot - dot + 1; 8920Sstevel@tonic-gate if (vreg) { 8930Sstevel@tonic-gate vremote(cnt, YANKreg, vreg); 8940Sstevel@tonic-gate /* 8950Sstevel@tonic-gate if (notp) 8960Sstevel@tonic-gate notpart(vreg); 8970Sstevel@tonic-gate */ 8980Sstevel@tonic-gate } 8990Sstevel@tonic-gate 9000Sstevel@tonic-gate /* 9010Sstevel@tonic-gate * Kill buffer code. If delete operator is c or d, then save 9020Sstevel@tonic-gate * the region in numbered buffers. 9030Sstevel@tonic-gate * 9040Sstevel@tonic-gate * BUG: This may be somewhat inefficient due 9050Sstevel@tonic-gate * to the way named buffer are implemented, 9060Sstevel@tonic-gate * necessitating some optimization. 9070Sstevel@tonic-gate */ 9080Sstevel@tonic-gate vreg = 0; 9090Sstevel@tonic-gate if (any(op, "cd")) { 9100Sstevel@tonic-gate vremote(cnt, YANKreg, '1'); 9110Sstevel@tonic-gate /* 9120Sstevel@tonic-gate if (notp) 9130Sstevel@tonic-gate notpart('1'); 9140Sstevel@tonic-gate */ 9150Sstevel@tonic-gate } 9160Sstevel@tonic-gate return (cnt); 9170Sstevel@tonic-gate } 9180Sstevel@tonic-gate 9190Sstevel@tonic-gate /* 9200Sstevel@tonic-gate * Routine for vremote to call to implement shifts. 9210Sstevel@tonic-gate */ 922*802Scf46844 int 923*802Scf46844 vshift(void) 9240Sstevel@tonic-gate { 9250Sstevel@tonic-gate 9260Sstevel@tonic-gate shift(op, 1); 927*802Scf46844 return (0); 9280Sstevel@tonic-gate } 9290Sstevel@tonic-gate 9300Sstevel@tonic-gate /* 9310Sstevel@tonic-gate * Replace a single character with the next input character. 9320Sstevel@tonic-gate * A funny kind of insert. 9330Sstevel@tonic-gate */ 934*802Scf46844 void 935*802Scf46844 vrep(int cnt) 9360Sstevel@tonic-gate { 937*802Scf46844 int i, c; 938*802Scf46844 unsigned char *endcurs; 9390Sstevel@tonic-gate endcurs = cursor; 9400Sstevel@tonic-gate for(i = 1; i <= cnt; i++) { 9410Sstevel@tonic-gate if(!*endcurs) { 942*802Scf46844 (void) beep(); 9430Sstevel@tonic-gate return; 9440Sstevel@tonic-gate } 9450Sstevel@tonic-gate endcurs = nextchr(endcurs); 9460Sstevel@tonic-gate } 9470Sstevel@tonic-gate i = lcolumn(endcurs); 9480Sstevel@tonic-gate vcursat(cursor); 9490Sstevel@tonic-gate doomed = i - cindent(); 9500Sstevel@tonic-gate /* 9510Sstevel@tonic-gate * TRANSLATION_NOTE 9520Sstevel@tonic-gate * "r" is a terse mode message that corresponds to 9530Sstevel@tonic-gate * "REPLACE 1 CHAR". 9540Sstevel@tonic-gate * Translated message of "r" must be 1 character (not byte). 9550Sstevel@tonic-gate * Or, just leave it. 9560Sstevel@tonic-gate */ 9570Sstevel@tonic-gate if(value(vi_TERSE)) 9580Sstevel@tonic-gate vshowmode(gettext("r")); 9590Sstevel@tonic-gate else 9600Sstevel@tonic-gate vshowmode(gettext("REPLACE 1 CHAR")); 9610Sstevel@tonic-gate if (!vglobp) { 9620Sstevel@tonic-gate c = getesc(); 9630Sstevel@tonic-gate if (c == 0) { 9640Sstevel@tonic-gate vshowmode(""); 9650Sstevel@tonic-gate vfixcurs(); 9660Sstevel@tonic-gate return; 9670Sstevel@tonic-gate } 9680Sstevel@tonic-gate ungetkey(c); 9690Sstevel@tonic-gate } 9700Sstevel@tonic-gate CP(vutmp, linebuf); 9710Sstevel@tonic-gate if (FIXUNDO) 9720Sstevel@tonic-gate vundkind = VCHNG; 9730Sstevel@tonic-gate wcursor = endcurs; 9740Sstevel@tonic-gate vUD1 = cursor; vUD2 = wcursor; 9750Sstevel@tonic-gate CP(cursor, wcursor); 9760Sstevel@tonic-gate prepapp(); 9770Sstevel@tonic-gate vappend('r', cnt, 0); 9780Sstevel@tonic-gate *lastcp++ = INS[0]; 9790Sstevel@tonic-gate setLAST(); 9800Sstevel@tonic-gate } 9810Sstevel@tonic-gate 9820Sstevel@tonic-gate /* 9830Sstevel@tonic-gate * Yank. 9840Sstevel@tonic-gate * 9850Sstevel@tonic-gate * Yanking to string registers occurs for free (essentially) 9860Sstevel@tonic-gate * in the routine xdw(). 9870Sstevel@tonic-gate */ 988*802Scf46844 int 989*802Scf46844 vyankit(void) 9900Sstevel@tonic-gate { 991*802Scf46844 int cnt; 9920Sstevel@tonic-gate 9930Sstevel@tonic-gate if (wdot) { 9940Sstevel@tonic-gate if ((cnt = xdw()) < 0) 995*802Scf46844 return (0); 9960Sstevel@tonic-gate vremote(cnt, yank, 0); 9970Sstevel@tonic-gate setpk(); 9980Sstevel@tonic-gate notenam = (unsigned char *)"yank"; 9990Sstevel@tonic-gate if (FIXUNDO) 10000Sstevel@tonic-gate vundkind = VNONE; 10010Sstevel@tonic-gate DEL[0] = 0; 10020Sstevel@tonic-gate wdot = NOLINE; 10030Sstevel@tonic-gate if (notecnt <= vcnt - vcline && notecnt < value(vi_REPORT)) 10040Sstevel@tonic-gate notecnt = 0; 10050Sstevel@tonic-gate vrepaint(cursor); 1006*802Scf46844 return (0); 10070Sstevel@tonic-gate } 10080Sstevel@tonic-gate takeout(DEL); 1009*802Scf46844 return (0); 1010*802Scf46844 10110Sstevel@tonic-gate } 10120Sstevel@tonic-gate 10130Sstevel@tonic-gate /* 10140Sstevel@tonic-gate * Set pkill variables so a put can 10150Sstevel@tonic-gate * know how to put back partial text. 10160Sstevel@tonic-gate * This is necessary because undo needs the complete 10170Sstevel@tonic-gate * line images to be saved, while a put wants to trim 10180Sstevel@tonic-gate * the first and last lines. The compromise 10190Sstevel@tonic-gate * is for put to be more clever. 10200Sstevel@tonic-gate */ 1021*802Scf46844 void 1022*802Scf46844 setpk(void) 10230Sstevel@tonic-gate { 10240Sstevel@tonic-gate 10250Sstevel@tonic-gate if (wcursor) { 10260Sstevel@tonic-gate pkill[0] = cursor; 10270Sstevel@tonic-gate pkill[1] = wcursor; 10280Sstevel@tonic-gate } 10290Sstevel@tonic-gate } 1030