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