home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / ex / ex_vops.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  16KB  |  807 lines

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