home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / EDITOR / NVI179B / NVI179B.ZIP / ex / ex_move.c < prev    next >
C/C++ Source or Header  |  1996-09-24  |  5KB  |  199 lines

  1. /*-
  2.  * Copyright (c) 1992, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  * Copyright (c) 1992, 1993, 1994, 1995, 1996
  5.  *    Keith Bostic.  All rights reserved.
  6.  *
  7.  * See the LICENSE file for redistribution information.
  8.  */
  9.  
  10. #include "config.h"
  11.  
  12. #ifndef lint
  13. static const char sccsid[] = "@(#)ex_move.c    10.10 (Berkeley) 9/15/96";
  14. #endif /* not lint */
  15.  
  16. #include <sys/types.h>
  17. #include <sys/queue.h>
  18.  
  19. #include <bitstring.h>
  20. #include <limits.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24.  
  25. #include "../common/common.h"
  26.  
  27. /*
  28.  * ex_copy -- :[line [,line]] co[py] line [flags]
  29.  *    Copy selected lines.
  30.  *
  31.  * PUBLIC: int ex_copy __P((SCR *, EXCMD *));
  32.  */
  33. int
  34. ex_copy(sp, cmdp)
  35.     SCR *sp;
  36.     EXCMD *cmdp;
  37. {
  38.     CB cb;
  39.     MARK fm1, fm2, m, tm;
  40.     recno_t cnt;
  41.     int rval;
  42.  
  43.     rval = 0;
  44.  
  45.     NEEDFILE(sp, cmdp);
  46.  
  47.     /*
  48.      * It's possible to copy things into the area that's being
  49.      * copied, e.g. "2,5copy3" is legitimate.  Save the text to
  50.      * a cut buffer.
  51.      */
  52.     fm1 = cmdp->addr1;
  53.     fm2 = cmdp->addr2;
  54.     memset(&cb, 0, sizeof(cb));
  55.     CIRCLEQ_INIT(&cb.textq);
  56.     for (cnt = fm1.lno; cnt <= fm2.lno; ++cnt)
  57.         if (cut_line(sp, cnt, 0, 0, &cb)) {
  58.             rval = 1;
  59.             goto err;
  60.         }
  61.     cb.flags |= CB_LMODE;
  62.  
  63.     /* Put the text into place. */
  64.     tm.lno = cmdp->lineno;
  65.     tm.cno = 0;
  66.     if (put(sp, &cb, NULL, &tm, &m, 1))
  67.         rval = 1;
  68.     else {
  69.         /*
  70.          * Copy puts the cursor on the last line copied.  The cursor
  71.          * returned by the put routine is the first line put, not the
  72.          * last, because that's the historic semantic of vi.
  73.          */
  74.         cnt = (fm2.lno - fm1.lno) + 1;
  75.         sp->lno = m.lno + (cnt - 1);
  76.         sp->cno = 0;
  77.     }
  78. err:    text_lfree(&cb.textq);
  79.     return (rval);
  80. }
  81.  
  82. /*
  83.  * ex_move -- :[line [,line]] mo[ve] line
  84.  *    Move selected lines.
  85.  *
  86.  * PUBLIC: int ex_move __P((SCR *, EXCMD *));
  87.  */
  88. int
  89. ex_move(sp, cmdp)
  90.     SCR *sp;
  91.     EXCMD *cmdp;
  92. {
  93.     LMARK *lmp;
  94.     MARK fm1, fm2;
  95.     recno_t cnt, diff, fl, tl, mfl, mtl;
  96.     size_t blen, len;
  97.     int mark_reset;
  98.     char *bp, *p;
  99.  
  100.     NEEDFILE(sp, cmdp);
  101.  
  102.     /*
  103.      * It's not possible to move things into the area that's being
  104.      * moved.
  105.      */
  106.     fm1 = cmdp->addr1;
  107.     fm2 = cmdp->addr2;
  108.     if (cmdp->lineno >= fm1.lno && cmdp->lineno <= fm2.lno) {
  109.         msgq(sp, M_ERR, "139|Destination line is inside move range");
  110.         return (1);
  111.     }
  112.  
  113.     /*
  114.      * Log the positions of any marks in the to-be-deleted lines.  This
  115.      * has to work with the logging code.  What happens is that we log
  116.      * the old mark positions, make the changes, then log the new mark
  117.      * positions.  Then the marks end up in the right positions no matter
  118.      * which way the log is traversed.
  119.      *
  120.      * XXX
  121.      * Reset the MARK_USERSET flag so that the log can undo the mark.
  122.      * This isn't very clean, and should probably be fixed.
  123.      */
  124.     fl = fm1.lno;
  125.     tl = cmdp->lineno;
  126.  
  127.     /* Log the old positions of the marks. */
  128.     mark_reset = 0;
  129.     for (lmp = sp->ep->marks.lh_first; lmp != NULL; lmp = lmp->q.le_next)
  130.         if (lmp->name != ABSMARK1 &&
  131.             lmp->lno >= fl && lmp->lno <= tl) {
  132.             mark_reset = 1;
  133.             F_CLR(lmp, MARK_USERSET);
  134.             (void)log_mark(sp, lmp);
  135.         }
  136.  
  137.     /* Get memory for the copy. */
  138.     GET_SPACE_RET(sp, bp, blen, 256);
  139.  
  140.     /* Move the lines. */
  141.     diff = (fm2.lno - fm1.lno) + 1;
  142.     if (tl > fl) {                /* Destination > source. */
  143.         mfl = tl - diff;
  144.         mtl = tl;
  145.         for (cnt = diff; cnt--;) {
  146.             if (db_get(sp, fl, DBG_FATAL, &p, &len))
  147.                 return (1);
  148.             BINC_RET(sp, bp, blen, len);
  149.             memcpy(bp, p, len);
  150.             if (db_append(sp, 1, tl, bp, len))
  151.                 return (1);
  152.             if (mark_reset)
  153.                 for (lmp = sp->ep->marks.lh_first;
  154.                     lmp != NULL; lmp = lmp->q.le_next)
  155.                     if (lmp->name != ABSMARK1 &&
  156.                         lmp->lno == fl)
  157.                         lmp->lno = tl + 1;
  158.             if (db_delete(sp, fl))
  159.                 return (1);
  160.         }
  161.     } else {                /* Destination < source. */
  162.         mfl = tl;
  163.         mtl = tl + diff;
  164.         for (cnt = diff; cnt--;) {
  165.             if (db_get(sp, fl, DBG_FATAL, &p, &len))
  166.                 return (1);
  167.             BINC_RET(sp, bp, blen, len);
  168.             memcpy(bp, p, len);
  169.             if (db_append(sp, 1, tl++, bp, len))
  170.                 return (1);
  171.             if (mark_reset)
  172.                 for (lmp = sp->ep->marks.lh_first;
  173.                     lmp != NULL; lmp = lmp->q.le_next)
  174.                     if (lmp->name != ABSMARK1 &&
  175.                         lmp->lno == fl)
  176.                         lmp->lno = tl;
  177.             ++fl;
  178.             if (db_delete(sp, fl))
  179.                 return (1);
  180.         }
  181.     }
  182.     FREE_SPACE(sp, bp, blen);
  183.  
  184.     sp->lno = tl;                /* Last line moved. */
  185.     sp->cno = 0;
  186.  
  187.     /* Log the new positions of the marks. */
  188.     if (mark_reset)
  189.         for (lmp = sp->ep->marks.lh_first;
  190.             lmp != NULL; lmp = lmp->q.le_next)
  191.             if (lmp->name != ABSMARK1 &&
  192.                 lmp->lno >= mfl && lmp->lno <= mtl)
  193.                 (void)log_mark(sp, lmp);
  194.  
  195.  
  196.     sp->rptlines[L_MOVED] += diff;
  197.     return (0);
  198. }
  199.