|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char *sccsid = "@(#)ex_vops.c 7.8 (Berkeley) 3/9/87";
9: #endif not lint
10:
11: #include "ex.h"
12: #include "ex_tty.h"
13: #include "ex_vis.h"
14:
15: /*
16: * This file defines the operation sequences which interface the
17: * logical changes to the file buffer with the internal and external
18: * display representations.
19: */
20:
21: /*
22: * Undo.
23: *
24: * Undo is accomplished in two ways. We often for small changes in the
25: * current line know how (in terms of a change operator) how the change
26: * occurred. Thus on an intelligent terminal we can undo the operation
27: * by another such operation, using insert and delete character
28: * stuff. The pointers vU[AD][12] index the buffer vutmp when this
29: * is possible and provide the necessary information.
30: *
31: * The other case is that the change involved multiple lines or that
32: * we have moved away from the line or forgotten how the change was
33: * accomplished. In this case we do a redisplay and hope that the
34: * low level optimization routines (which don't look for winning
35: * via insert/delete character) will not lose too badly.
36: */
37: char *vUA1, *vUA2;
38: char *vUD1, *vUD2;
39:
40: ex_vUndo()
41: {
42:
43: /*
44: * Avoid UU which clobbers ability to do u.
45: */
46: if (vundkind == VCAPU || vUNDdot != dot) {
47: beep();
48: return;
49: }
50: CP(vutmp, linebuf);
51: vUD1 = linebuf; vUD2 = strend(linebuf);
52: putmk1(dot, vUNDsav);
53: getDOT();
54: vUA1 = linebuf; vUA2 = strend(linebuf);
55: vundkind = VCAPU;
56: if (state == ONEOPEN || state == HARDOPEN) {
57: vjumpto(dot, vUNDcurs, 0);
58: return;
59: }
60: vdirty(vcline, 1);
61: vsyncCL();
62: cursor = linebuf;
63: vfixcurs();
64: }
65:
66: vundo(show)
67: bool show; /* if true update the screen */
68: {
69: register int cnt;
70: register line *addr;
71: register char *cp;
72: char temp[LBSIZE];
73: bool savenote;
74: int (*OO)();
75: short oldhold = hold;
76:
77: switch (vundkind) {
78:
79: case VMANYINS:
80: wcursor = 0;
81: addr1 = undap1;
82: addr2 = undap2 - 1;
83: vsave();
84: YANKreg('1');
85: notecnt = 0;
86: /* fall into ... */
87:
88: case VMANY:
89: case VMCHNG:
90: vsave();
91: addr = dot - vcline;
92: notecnt = 1;
93: if (undkind == UNDPUT && undap1 == undap2) {
94: beep();
95: break;
96: }
97: /*
98: * Undo() call below basically replaces undap1 to undap2-1
99: * with dol through unddol-1. Hack screen image to
100: * reflect this replacement.
101: */
102: if (show)
103: if (undkind == UNDMOVE)
104: vdirty(0, LINES);
105: else
106: vreplace(undap1 - addr, undap2 - undap1,
107: undkind == UNDPUT ? 0 : unddol - dol);
108: savenote = notecnt;
109: undo(1);
110: if (show && (vundkind != VMCHNG || addr != dot))
111: killU();
112: vundkind = VMANY;
113: cnt = dot - addr;
114: if (cnt < 0 || cnt > vcnt || state != VISUAL) {
115: if (show)
116: vjumpto(dot, NOSTR, '.');
117: break;
118: }
119: if (!savenote)
120: notecnt = 0;
121: if (show) {
122: vcline = cnt;
123: vrepaint(vmcurs);
124: }
125: vmcurs = 0;
126: break;
127:
128: case VCHNG:
129: case VCAPU:
130: vundkind = VCHNG;
131: strcpy(temp, vutmp);
132: strcpy(vutmp, linebuf);
133: doomed = column(vUA2 - 1) - column(vUA1 - 1);
134: strcLIN(temp);
135: cp = vUA1; vUA1 = vUD1; vUD1 = cp;
136: cp = vUA2; vUA2 = vUD2; vUD2 = cp;
137: if (!show)
138: break;
139: cursor = vUD1;
140: if (state == HARDOPEN) {
141: doomed = 0;
142: vsave();
143: vopen(dot, WBOT);
144: vnline(cursor);
145: break;
146: }
147: /*
148: * Pseudo insert command.
149: */
150: vcursat(cursor);
151: OO = Outchar; Outchar = vinschar; hold |= HOLDQIK;
152: vprepins();
153: temp[vUA2 - linebuf] = 0;
154: for (cp = &temp[vUA1 - linebuf]; *cp;)
155: ex_putchar(*cp++);
156: Outchar = OO; hold = oldhold;
157: endim();
158: physdc(cindent(), cindent() + doomed);
159: doomed = 0;
160: vdirty(vcline, 1);
161: vsyncCL();
162: if (cursor > linebuf && cursor >= strend(linebuf))
163: cursor--;
164: vfixcurs();
165: break;
166:
167: case VNONE:
168: beep();
169: break;
170: }
171: }
172:
173: /*
174: * Routine to handle a change inside a macro.
175: * Fromvis is true if we were called from a visual command (as
176: * opposed to an ex command). This has nothing to do with being
177: * in open/visual mode as :s/foo/bar is not fromvis.
178: */
179: vmacchng(fromvis)
180: bool fromvis;
181: {
182: line *savedot, *savedol;
183: char *savecursor;
184: char savelb[LBSIZE];
185: int nlines, more;
186: int copyw(), copywR();
187:
188: if (!inopen)
189: return;
190: if (!vmacp)
191: vch_mac = VC_NOTINMAC;
192: #ifdef TRACE
193: if (trace)
194: fprintf(trace, "vmacchng, vch_mac=%d, linebuf='%s', *dot=%o\n", vch_mac, linebuf, *dot);
195: #endif
196: if (vmacp && fromvis)
197: vsave();
198: #ifdef TRACE
199: if (trace)
200: fprintf(trace, "after vsave, linebuf='%s', *dot=%o\n", linebuf, *dot);
201: #endif
202: switch(vch_mac) {
203: case VC_NOCHANGE:
204: vch_mac = VC_ONECHANGE;
205: break;
206: case VC_ONECHANGE:
207: /* Save current state somewhere */
208: #ifdef TRACE
209: vudump("before vmacchng hairy case");
210: #endif
211: savedot = dot; savedol = dol; savecursor = cursor;
212: CP(savelb, linebuf);
213: nlines = dol - zero;
214: while ((line *) endcore - truedol < nlines)
215: if (morelines() < 0) {
216: dot = savedot;
217: dol = savedol;
218: cursor = savecursor;
219: CP(linebuf, savelb);
220: error("Out of memory@- too many lines to undo");
221: }
222: copyw(truedol+1, zero+1, nlines);
223: truedol += nlines;
224:
225: #ifdef TRACE
226: visdump("before vundo");
227: #endif
228: /* Restore state as it was at beginning of macro */
229: vundo(0);
230: #ifdef TRACE
231: visdump("after vundo");
232: vudump("after vundo");
233: #endif
234:
235: /* Do the saveall we should have done then */
236: saveall();
237: #ifdef TRACE
238: vudump("after saveall");
239: #endif
240:
241: /* Restore current state from where saved */
242: more = savedol - dol; /* amount we shift everything by */
243: if (more)
244: (*(more>0 ? copywR : copyw))(savedol+1, dol+1, truedol-dol);
245: unddol += more; truedol += more; undap2 += more;
246:
247: truedol -= nlines;
248: copyw(zero+1, truedol+1, nlines);
249: dot = savedot; dol = savedol ; cursor = savecursor;
250: CP(linebuf, savelb);
251: vch_mac = VC_MANYCHANGE;
252:
253: /* Arrange that no further undo saving happens within macro */
254: otchng = tchng; /* Copied this line blindly - bug? */
255: inopen = -1; /* no need to save since it had to be 1 or -1 before */
256: vundkind = VMANY;
257: #ifdef TRACE
258: vudump("after vmacchng");
259: #endif
260: break;
261: case VC_NOTINMAC:
262: case VC_MANYCHANGE:
263: /* Nothing to do for various reasons. */
264: break;
265: }
266: }
267:
268: /*
269: * Initialize undo information before an append.
270: */
271: vnoapp()
272: {
273:
274: vUD1 = vUD2 = cursor;
275: }
276:
277: /*
278: * All the rest of the motion sequences have one or more
279: * cases to deal with. In the case wdot == 0, operation
280: * is totally within current line, from cursor to wcursor.
281: * If wdot is given, but wcursor is 0, then operation affects
282: * the inclusive line range. The hardest case is when both wdot
283: * and wcursor are given, then operation affects from line dot at
284: * cursor to line wdot at wcursor.
285: */
286:
287: /*
288: * Move is simple, except for moving onto new lines in hardcopy open mode.
289: */
290: vmove()
291: {
292: register int cnt;
293:
294: if (wdot) {
295: if (wdot < one || wdot > dol) {
296: beep();
297: return;
298: }
299: cnt = wdot - dot;
300: wdot = NOLINE;
301: if (cnt)
302: killU();
303: vupdown(cnt, wcursor);
304: return;
305: }
306:
307: /*
308: * When we move onto a new line, save information for U undo.
309: */
310: if (vUNDdot != dot) {
311: vUNDsav = *dot;
312: vUNDcurs = wcursor;
313: vUNDdot = dot;
314: }
315:
316: /*
317: * In hardcopy open, type characters to left of cursor
318: * on new line, or back cursor up if its to left of where we are.
319: * In any case if the current line is ``rubbled'' i.e. has trashy
320: * looking overstrikes on it or \'s from deletes, we reprint
321: * so it is more comprehensible (and also because we can't work
322: * if we let it get more out of sync since column() won't work right.
323: */
324: if (state == HARDOPEN) {
325: register char *cp;
326: if (rubble) {
327: register int c;
328: int oldhold = hold;
329:
330: sethard();
331: cp = wcursor;
332: c = *cp;
333: *cp = 0;
334: hold |= HOLDDOL;
335: ignore(vreopen(WTOP, lineDOT(), vcline));
336: hold = oldhold;
337: *cp = c;
338: } else if (wcursor > cursor) {
339: vfixcurs();
340: for (cp = cursor; *cp && cp < wcursor;) {
341: register int c = *cp++ & TRIM;
342:
343: ex_putchar(c ? c : ' ');
344: }
345: }
346: }
347: vsetcurs(wcursor);
348: }
349:
350: /*
351: * Delete operator.
352: *
353: * Hard case of deleting a range where both wcursor and wdot
354: * are specified is treated as a special case of change and handled
355: * by vchange (although vchange may pass it back if it degenerates
356: * to a full line range delete.)
357: */
358: vdelete(c)
359: char c;
360: {
361: register char *cp;
362: register int i;
363:
364: if (wdot) {
365: if (wcursor) {
366: vchange('d');
367: return;
368: }
369: if ((i = xdw()) < 0)
370: return;
371: if (state != VISUAL) {
372: vgoto(LINE(0), 0);
373: vputchar('@');
374: }
375: wdot = dot;
376: vremote(i, ex_delete, 0);
377: notenam = "delete";
378: DEL[0] = 0;
379: killU();
380: vreplace(vcline, i, 0);
381: if (wdot > dol)
382: vcline--;
383: vrepaint(NOSTR);
384: return;
385: }
386: if (wcursor < linebuf)
387: wcursor = linebuf;
388: if (cursor == wcursor) {
389: beep();
390: return;
391: }
392: i = vdcMID();
393: cp = cursor;
394: setDEL();
395: CP(cp, wcursor);
396: if (cp > linebuf && (cp[0] == 0 || c == '#'))
397: cp--;
398: if (state == HARDOPEN) {
399: bleep(i, cp);
400: cursor = cp;
401: return;
402: }
403: physdc(column(cursor - 1), i);
404: DEPTH(vcline) = 0;
405: ignore(vreopen(LINE(vcline), lineDOT(), vcline));
406: vsyncCL();
407: vsetcurs(cp);
408: }
409:
410: /*
411: * Change operator.
412: *
413: * In a single line we mark the end of the changed area with '$'.
414: * On multiple whole lines, we clear the lines first.
415: * Across lines with both wcursor and wdot given, we delete
416: * and sync then append (but one operation for undo).
417: */
418: vchange(c)
419: char c;
420: {
421: register char *cp;
422: register int i, ind, cnt;
423: line *addr;
424:
425: if (wdot) {
426: /*
427: * Change/delete of lines or across line boundaries.
428: */
429: if ((cnt = xdw()) < 0)
430: return;
431: getDOT();
432: if (wcursor && cnt == 1) {
433: /*
434: * Not really.
435: */
436: wdot = 0;
437: if (c == 'd') {
438: vdelete(c);
439: return;
440: }
441: goto smallchange;
442: }
443: if (cursor && wcursor) {
444: /*
445: * Across line boundaries, but not
446: * necessarily whole lines.
447: * Construct what will be left.
448: */
449: *cursor = 0;
450: strcpy(genbuf, linebuf);
451: getline(*wdot);
452: if (strlen(genbuf) + strlen(wcursor) > LBSIZE - 2) {
453: getDOT();
454: beep();
455: return;
456: }
457: strcat(genbuf, wcursor);
458: if (c == 'd' && *vpastwh(genbuf) == 0) {
459: /*
460: * Although this is a delete
461: * spanning line boundaries, what
462: * would be left is all white space,
463: * so take it all away.
464: */
465: wcursor = 0;
466: getDOT();
467: op = 0;
468: notpart(lastreg);
469: notpart('1');
470: vdelete(c);
471: return;
472: }
473: ind = -1;
474: } else if (c == 'd' && wcursor == 0) {
475: vdelete(c);
476: return;
477: } else
478: #ifdef LISPCODE
479: /*
480: * We are just substituting text for whole lines,
481: * so determine the first autoindent.
482: */
483: if (value(LISP) && value(AUTOINDENT))
484: ind = lindent(dot);
485: else
486: #endif
487: ind = whitecnt(linebuf);
488: i = vcline >= 0 ? LINE(vcline) : WTOP;
489:
490: /*
491: * Delete the lines from the buffer,
492: * and remember how the partial stuff came about in
493: * case we are told to put.
494: */
495: addr = dot;
496: vremote(cnt, ex_delete, 0);
497: setpk();
498: notenam = "delete";
499: if (c != 'd')
500: notenam = "change";
501: /*
502: * If DEL[0] were nonzero, put would put it back
503: * rather than the deleted lines.
504: */
505: DEL[0] = 0;
506: if (cnt > 1)
507: killU();
508:
509: /*
510: * Now hack the screen image coordination.
511: */
512: vreplace(vcline, cnt, 0);
513: wdot = NOLINE;
514: ignore(noteit(0));
515: vcline--;
516: if (addr <= dol)
517: dot--;
518:
519: /*
520: * If this is a across line delete/change,
521: * cursor stays where it is; just splice together the pieces
522: * of the new line. Otherwise generate a autoindent
523: * after a S command.
524: */
525: if (ind >= 0) {
526: *genindent(ind) = 0;
527: vdoappend(genbuf);
528: } else {
529: vmcurs = cursor;
530: strcLIN(genbuf);
531: vdoappend(linebuf);
532: }
533:
534: /*
535: * Indicate a change on hardcopies by
536: * erasing the current line.
537: */
538: if (c != 'd' && state != VISUAL && state != HARDOPEN) {
539: int oldhold = hold;
540:
541: hold |= HOLDAT, vclrlin(i, dot), hold = oldhold;
542: }
543:
544: /*
545: * Open the line (logically) on the screen, and
546: * update the screen tail. Unless we are really a delete
547: * go off and gather up inserted characters.
548: */
549: vcline++;
550: if (vcline < 0)
551: vcline = 0;
552: vopen(dot, i);
553: vsyncCL();
554: ignore(noteit(1));
555: if (c != 'd') {
556: if (ind >= 0) {
557: cursor = linebuf;
558: linebuf[0] = 0;
559: vfixcurs();
560: } else {
561: ind = 0;
562: vcursat(cursor);
563: }
564: vappend('x', 1, ind);
565: return;
566: }
567: if (*cursor == 0 && cursor > linebuf)
568: cursor--;
569: vrepaint(cursor);
570: return;
571: }
572:
573: smallchange:
574: /*
575: * The rest of this is just low level hacking on changes
576: * of small numbers of characters.
577: */
578: if (wcursor < linebuf)
579: wcursor = linebuf;
580: if (cursor == wcursor) {
581: beep();
582: return;
583: }
584: i = vdcMID();
585: cp = cursor;
586: if (state != HARDOPEN)
587: vfixcurs();
588:
589: /*
590: * Put out the \\'s indicating changed text in hardcopy,
591: * or mark the end of the change with $ if not hardcopy.
592: */
593: if (state == HARDOPEN)
594: bleep(i, cp);
595: else {
596: vcursbef(wcursor);
597: ex_putchar('$');
598: i = cindent();
599: }
600:
601: /*
602: * Remember the deleted text for possible put,
603: * and then prepare and execute the input portion of the change.
604: */
605: cursor = cp;
606: setDEL();
607: CP(cursor, wcursor);
608: if (state != HARDOPEN) {
609: vcursaft(cursor - 1);
610: doomed = i - cindent();
611: } else {
612: /*
613: sethard();
614: wcursor = cursor;
615: cursor = linebuf;
616: vgoto(outline, value(NUMBER) << 3);
617: vmove();
618: */
619: doomed = 0;
620: }
621: prepapp();
622: vappend('c', 1, 0);
623: }
624:
625: /*
626: * Open new lines.
627: *
628: * Tricky thing here is slowopen. This causes display updating
629: * to be held off so that 300 baud dumb terminals don't lose badly.
630: * This also suppressed counts, which otherwise say how many blank
631: * space to open up. Counts are also suppressed on intelligent terminals.
632: * Actually counts are obsoleted, since if your terminal is slow
633: * you are better off with slowopen.
634: */
635: voOpen(c, cnt)
636: int c; /* mjm: char --> int */
637: register int cnt;
638: {
639: register int ind = 0, i;
640: short oldhold = hold;
641: #ifdef SIGWINCH
642: int oldmask;
643: #endif
644:
645: if (value(SLOWOPEN) || value(REDRAW) && AL && DL)
646: cnt = 1;
647: #ifdef SIGWINCH
648: oldmask = sigblock(sigmask(SIGWINCH));
649: #endif
650: vsave();
651: setLAST();
652: if (value(AUTOINDENT))
653: ind = whitecnt(linebuf);
654: if (c == 'O') {
655: vcline--;
656: dot--;
657: if (dot > zero)
658: getDOT();
659: }
660: if (value(AUTOINDENT)) {
661: #ifdef LISPCODE
662: if (value(LISP))
663: ind = lindent(dot + 1);
664: #endif
665: }
666: killU();
667: prepapp();
668: if (FIXUNDO)
669: vundkind = VMANY;
670: if (state != VISUAL)
671: c = WBOT + 1;
672: else {
673: c = vcline < 0 ? WTOP - cnt : LINE(vcline) + DEPTH(vcline);
674: if (c < ex_ZERO)
675: c = ex_ZERO;
676: i = LINE(vcline + 1) - c;
677: if (i < cnt && c <= WBOT && (!AL || !DL))
678: vinslin(c, cnt - i, vcline);
679: }
680: *genindent(ind) = 0;
681: vdoappend(genbuf);
682: vcline++;
683: oldhold = hold;
684: hold |= HOLDROL;
685: vopen(dot, c);
686: hold = oldhold;
687: if (value(SLOWOPEN))
688: /*
689: * Oh, so lazy!
690: */
691: vscrap();
692: else
693: vsync1(LINE(vcline));
694: cursor = linebuf;
695: linebuf[0] = 0;
696: vappend('o', 1, ind);
697: #ifdef SIGWINCH
698: (void)sigsetmask(oldmask);
699: #endif
700: }
701:
702: /*
703: * > < and = shift operators.
704: *
705: * Note that =, which aligns lisp, is just a ragged sort of shift,
706: * since it never distributes text between lines.
707: */
708: char vshnam[2] = { 'x', 0 };
709:
710: vshftop()
711: {
712: register line *addr;
713: register int cnt;
714:
715: if ((cnt = xdw()) < 0)
716: return;
717: addr = dot;
718: vremote(cnt, vshift, 0);
719: vshnam[0] = op;
720: notenam = vshnam;
721: dot = addr;
722: vreplace(vcline, cnt, cnt);
723: if (state == HARDOPEN)
724: vcnt = 0;
725: vrepaint(NOSTR);
726: }
727:
728: /*
729: * !.
730: *
731: * Filter portions of the buffer through unix commands.
732: */
733: vfilter()
734: {
735: register line *addr;
736: register int cnt;
737: char *oglobp;
738: short d;
739:
740: if ((cnt = xdw()) < 0)
741: return;
742: if (vglobp)
743: vglobp = uxb;
744: if (readecho('!'))
745: return;
746: oglobp = globp; globp = genbuf + 1;
747: d = peekc; ungetchar(0);
748: CATCH
749: fixech();
750: unix0(0);
751: ONERR
752: splitw = 0;
753: ungetchar(d);
754: vrepaint(cursor);
755: globp = oglobp;
756: return;
757: ENDCATCH
758: ungetchar(d); globp = oglobp;
759: addr = dot;
760: CATCH
761: vgoto(WECHO, 0); flusho();
762: vremote(cnt, filter, 2);
763: ONERR
764: vdirty(0, LINES);
765: ENDCATCH
766: if (dot == zero && dol > zero)
767: dot = one;
768: splitw = 0;
769: notenam = "";
770: /*
771: * BUG: we shouldn't be depending on what undap2 and undap1 are,
772: * since we may be inside a macro. What's really wanted is the
773: * number of lines we read from the filter. However, the mistake
774: * will be an overestimate so it only results in extra work,
775: * it shouldn't cause any real screwups.
776: */
777: vreplace(vcline, cnt, undap2 - undap1);
778: dot = addr;
779: if (dot > dol) {
780: dot--;
781: vcline--;
782: }
783: vrepaint(NOSTR);
784: }
785:
786: /*
787: * Xdw exchanges dot and wdot if appropriate and also checks
788: * that wdot is reasonable. Its name comes from
789: * xchange dotand wdot
790: */
791: xdw()
792: {
793: register char *cp;
794: register int cnt;
795: /*
796: register int notp = 0;
797: */
798:
799: if (wdot == NOLINE || wdot < one || wdot > dol) {
800: beep();
801: return (-1);
802: }
803: vsave();
804: setLAST();
805: if (dot > wdot || (dot == wdot && wcursor != 0 && cursor > wcursor)) {
806: register line *addr;
807:
808: vcline -= dot - wdot;
809: addr = dot; dot = wdot; wdot = addr;
810: cp = cursor; cursor = wcursor; wcursor = cp;
811: }
812: /*
813: * If a region is specified but wcursor is at the begining
814: * of the last line, then we move it to be the end of the
815: * previous line (actually off the end).
816: */
817: if (cursor && wcursor == linebuf && wdot > dot) {
818: wdot--;
819: getDOT();
820: if (vpastwh(linebuf) >= cursor)
821: wcursor = 0;
822: else {
823: getline(*wdot);
824: wcursor = strend(linebuf);
825: getDOT();
826: }
827: /*
828: * Should prepare in caller for possible dot == wdot.
829: */
830: }
831: cnt = wdot - dot + 1;
832: if (vreg) {
833: vremote(cnt, YANKreg, vreg);
834: /*
835: if (notp)
836: notpart(vreg);
837: */
838: }
839:
840: /*
841: * Kill buffer code. If delete operator is c or d, then save
842: * the region in numbered buffers.
843: *
844: * BUG: This may be somewhat inefficient due
845: * to the way named buffer are implemented,
846: * necessitating some optimization.
847: */
848: vreg = 0;
849: if (any(op, "cd")) {
850: vremote(cnt, YANKreg, '1');
851: /*
852: if (notp)
853: notpart('1');
854: */
855: }
856: return (cnt);
857: }
858:
859: /*
860: * Routine for vremote to call to implement shifts.
861: */
862: vshift()
863: {
864:
865: shift(op, 1);
866: }
867:
868: /*
869: * Replace a single character with the next input character.
870: * A funny kind of insert.
871: */
872: vrep(cnt)
873: register int cnt;
874: {
875: register int i, c;
876:
877: if (cnt > strlen(cursor)) {
878: beep();
879: return;
880: }
881: i = column(cursor + cnt - 1);
882: vcursat(cursor);
883: doomed = i - cindent();
884: if (!vglobp) {
885: c = getesc();
886: if (c == 0) {
887: vfixcurs();
888: return;
889: }
890: ungetkey(c);
891: }
892: CP(vutmp, linebuf);
893: if (FIXUNDO)
894: vundkind = VCHNG;
895: wcursor = cursor + cnt;
896: vUD1 = cursor; vUD2 = wcursor;
897: CP(cursor, wcursor);
898: prepapp();
899: vappend('r', cnt, 0);
900: *lastcp++ = INS[0];
901: setLAST();
902: }
903:
904: /*
905: * Yank.
906: *
907: * Yanking to string registers occurs for free (essentially)
908: * in the routine xdw().
909: */
910: vyankit()
911: {
912: register int cnt;
913:
914: if (wdot) {
915: if ((cnt = xdw()) < 0)
916: return;
917: vremote(cnt, yank, 0);
918: setpk();
919: notenam = "yank";
920: if (FIXUNDO)
921: vundkind = VNONE;
922: DEL[0] = 0;
923: wdot = NOLINE;
924: if (notecnt <= vcnt - vcline && notecnt < value(REPORT))
925: notecnt = 0;
926: vrepaint(cursor);
927: return;
928: }
929: takeout(DEL);
930: }
931:
932: /*
933: * Set pkill variables so a put can
934: * know how to put back partial text.
935: * This is necessary because undo needs the complete
936: * line images to be saved, while a put wants to trim
937: * the first and last lines. The compromise
938: * is for put to be more clever.
939: */
940: setpk()
941: {
942:
943: if (wcursor) {
944: pkill[0] = cursor;
945: pkill[1] = wcursor;
946: }
947: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.