xref: /minix3/external/bsd/nvi/dist/ex/ex_move.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: ex_move.c,v 1.4 2014/01/26 21:43:45 christos Exp $ */
284d9c625SLionel Sambuc /*-
384d9c625SLionel Sambuc  * Copyright (c) 1992, 1993, 1994
484d9c625SLionel Sambuc  *	The Regents of the University of California.  All rights reserved.
584d9c625SLionel Sambuc  * Copyright (c) 1992, 1993, 1994, 1995, 1996
684d9c625SLionel Sambuc  *	Keith Bostic.  All rights reserved.
784d9c625SLionel Sambuc  *
884d9c625SLionel Sambuc  * See the LICENSE file for redistribution information.
984d9c625SLionel Sambuc  */
1084d9c625SLionel Sambuc 
1184d9c625SLionel Sambuc #include "config.h"
1284d9c625SLionel Sambuc 
13*0a6a1f1dSLionel Sambuc #include <sys/cdefs.h>
14*0a6a1f1dSLionel Sambuc #if 0
1584d9c625SLionel Sambuc #ifndef lint
1684d9c625SLionel Sambuc static const char sccsid[] = "Id: ex_move.c,v 10.15 2001/06/25 15:19:17 skimo Exp  (Berkeley) Date: 2001/06/25 15:19:17 ";
1784d9c625SLionel Sambuc #endif /* not lint */
18*0a6a1f1dSLionel Sambuc #else
19*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: ex_move.c,v 1.4 2014/01/26 21:43:45 christos Exp $");
20*0a6a1f1dSLionel Sambuc #endif
2184d9c625SLionel Sambuc 
2284d9c625SLionel Sambuc #include <sys/types.h>
2384d9c625SLionel Sambuc #include <sys/queue.h>
2484d9c625SLionel Sambuc 
2584d9c625SLionel Sambuc #include <bitstring.h>
2684d9c625SLionel Sambuc #include <limits.h>
2784d9c625SLionel Sambuc #include <stdio.h>
2884d9c625SLionel Sambuc #include <stdlib.h>
2984d9c625SLionel Sambuc #include <string.h>
3084d9c625SLionel Sambuc 
3184d9c625SLionel Sambuc #include "../common/common.h"
3284d9c625SLionel Sambuc 
3384d9c625SLionel Sambuc /*
3484d9c625SLionel Sambuc  * ex_copy -- :[line [,line]] co[py] line [flags]
3584d9c625SLionel Sambuc  *	Copy selected lines.
3684d9c625SLionel Sambuc  *
3784d9c625SLionel Sambuc  * PUBLIC: int ex_copy __P((SCR *, EXCMD *));
3884d9c625SLionel Sambuc  */
3984d9c625SLionel Sambuc int
ex_copy(SCR * sp,EXCMD * cmdp)4084d9c625SLionel Sambuc ex_copy(SCR *sp, EXCMD *cmdp)
4184d9c625SLionel Sambuc {
4284d9c625SLionel Sambuc 	CB cb;
4384d9c625SLionel Sambuc 	MARK fm1, fm2, m, tm;
4484d9c625SLionel Sambuc 	db_recno_t cnt;
4584d9c625SLionel Sambuc 	int rval;
4684d9c625SLionel Sambuc 
4784d9c625SLionel Sambuc 	rval = 0;
4884d9c625SLionel Sambuc 
4984d9c625SLionel Sambuc 	NEEDFILE(sp, cmdp);
5084d9c625SLionel Sambuc 
5184d9c625SLionel Sambuc 	/*
5284d9c625SLionel Sambuc 	 * It's possible to copy things into the area that's being
5384d9c625SLionel Sambuc 	 * copied, e.g. "2,5copy3" is legitimate.  Save the text to
5484d9c625SLionel Sambuc 	 * a cut buffer.
5584d9c625SLionel Sambuc 	 */
5684d9c625SLionel Sambuc 	fm1 = cmdp->addr1;
5784d9c625SLionel Sambuc 	fm2 = cmdp->addr2;
5884d9c625SLionel Sambuc 	memset(&cb, 0, sizeof(cb));
5984d9c625SLionel Sambuc 	TAILQ_INIT(&cb.textq);
6084d9c625SLionel Sambuc 	for (cnt = fm1.lno; cnt <= fm2.lno; ++cnt)
6184d9c625SLionel Sambuc 		if (cut_line(sp, cnt, 0, ENTIRE_LINE, &cb)) {
6284d9c625SLionel Sambuc 			rval = 1;
6384d9c625SLionel Sambuc 			goto err;
6484d9c625SLionel Sambuc 		}
6584d9c625SLionel Sambuc 	cb.flags |= CB_LMODE;
6684d9c625SLionel Sambuc 
6784d9c625SLionel Sambuc 	/* Put the text into place. */
6884d9c625SLionel Sambuc 	tm.lno = cmdp->lineno;
6984d9c625SLionel Sambuc 	tm.cno = 0;
7084d9c625SLionel Sambuc 	if (put(sp, &cb, NULL, &tm, &m, 1))
7184d9c625SLionel Sambuc 		rval = 1;
7284d9c625SLionel Sambuc 	else {
7384d9c625SLionel Sambuc 		/*
7484d9c625SLionel Sambuc 		 * Copy puts the cursor on the last line copied.  The cursor
7584d9c625SLionel Sambuc 		 * returned by the put routine is the first line put, not the
7684d9c625SLionel Sambuc 		 * last, because that's the historic semantic of vi.
7784d9c625SLionel Sambuc 		 */
7884d9c625SLionel Sambuc 		cnt = (fm2.lno - fm1.lno) + 1;
7984d9c625SLionel Sambuc 		sp->lno = m.lno + (cnt - 1);
8084d9c625SLionel Sambuc 		sp->cno = 0;
8184d9c625SLionel Sambuc 	}
8284d9c625SLionel Sambuc err:	text_lfree(&cb.textq);
8384d9c625SLionel Sambuc 	return (rval);
8484d9c625SLionel Sambuc }
8584d9c625SLionel Sambuc 
8684d9c625SLionel Sambuc /*
8784d9c625SLionel Sambuc  * ex_move -- :[line [,line]] mo[ve] line
8884d9c625SLionel Sambuc  *	Move selected lines.
8984d9c625SLionel Sambuc  *
9084d9c625SLionel Sambuc  * PUBLIC: int ex_move __P((SCR *, EXCMD *));
9184d9c625SLionel Sambuc  */
9284d9c625SLionel Sambuc int
ex_move(SCR * sp,EXCMD * cmdp)9384d9c625SLionel Sambuc ex_move(SCR *sp, EXCMD *cmdp)
9484d9c625SLionel Sambuc {
9584d9c625SLionel Sambuc 	LMARK *lmp;
9684d9c625SLionel Sambuc 	MARK fm1, fm2;
9784d9c625SLionel Sambuc 	db_recno_t cnt, diff, fl, tl, mfl, mtl;
9884d9c625SLionel Sambuc 	size_t blen, len;
9984d9c625SLionel Sambuc 	int mark_reset;
10084d9c625SLionel Sambuc 	CHAR_T *bp;
10184d9c625SLionel Sambuc 	CHAR_T *p;
10284d9c625SLionel Sambuc 
10384d9c625SLionel Sambuc 	NEEDFILE(sp, cmdp);
10484d9c625SLionel Sambuc 
10584d9c625SLionel Sambuc 	/*
10684d9c625SLionel Sambuc 	 * It's not possible to move things into the area that's being
10784d9c625SLionel Sambuc 	 * moved.
10884d9c625SLionel Sambuc 	 */
10984d9c625SLionel Sambuc 	fm1 = cmdp->addr1;
11084d9c625SLionel Sambuc 	fm2 = cmdp->addr2;
11184d9c625SLionel Sambuc 	if (cmdp->lineno >= fm1.lno && cmdp->lineno <= fm2.lno) {
11284d9c625SLionel Sambuc 		msgq(sp, M_ERR, "139|Destination line is inside move range");
11384d9c625SLionel Sambuc 		return (1);
11484d9c625SLionel Sambuc 	}
11584d9c625SLionel Sambuc 
11684d9c625SLionel Sambuc 	/*
11784d9c625SLionel Sambuc 	 * Log the positions of any marks in the to-be-deleted lines.  This
11884d9c625SLionel Sambuc 	 * has to work with the logging code.  What happens is that we log
11984d9c625SLionel Sambuc 	 * the old mark positions, make the changes, then log the new mark
12084d9c625SLionel Sambuc 	 * positions.  Then the marks end up in the right positions no matter
12184d9c625SLionel Sambuc 	 * which way the log is traversed.
12284d9c625SLionel Sambuc 	 *
12384d9c625SLionel Sambuc 	 * XXX
12484d9c625SLionel Sambuc 	 * Reset the MARK_USERSET flag so that the log can undo the mark.
12584d9c625SLionel Sambuc 	 * This isn't very clean, and should probably be fixed.
12684d9c625SLionel Sambuc 	 */
12784d9c625SLionel Sambuc 	fl = fm1.lno;
12884d9c625SLionel Sambuc 	tl = cmdp->lineno;
12984d9c625SLionel Sambuc 
13084d9c625SLionel Sambuc 	/* Log the old positions of the marks. */
13184d9c625SLionel Sambuc 	mark_reset = 0;
13284d9c625SLionel Sambuc 	LIST_FOREACH(lmp, &sp->ep->marks, q)
13384d9c625SLionel Sambuc 		if (lmp->name != ABSMARK1 &&
13484d9c625SLionel Sambuc 		    lmp->lno >= fl && lmp->lno <= tl) {
13584d9c625SLionel Sambuc 			mark_reset = 1;
13684d9c625SLionel Sambuc 			F_CLR(lmp, MARK_USERSET);
13784d9c625SLionel Sambuc 			(void)log_mark(sp, lmp);
13884d9c625SLionel Sambuc 		}
13984d9c625SLionel Sambuc 
14084d9c625SLionel Sambuc 	/* Get memory for the copy. */
14184d9c625SLionel Sambuc 	GET_SPACE_RETW(sp, bp, blen, 256);
14284d9c625SLionel Sambuc 
14384d9c625SLionel Sambuc 	/* Move the lines. */
14484d9c625SLionel Sambuc 	diff = (fm2.lno - fm1.lno) + 1;
14584d9c625SLionel Sambuc 	if (tl > fl) {				/* Destination > source. */
14684d9c625SLionel Sambuc 		mfl = tl - diff;
14784d9c625SLionel Sambuc 		mtl = tl;
14884d9c625SLionel Sambuc 		for (cnt = diff; cnt--;) {
14984d9c625SLionel Sambuc 			if (db_get(sp, fl, DBG_FATAL, &p, &len))
15084d9c625SLionel Sambuc 				return (1);
15184d9c625SLionel Sambuc 			BINC_RETW(sp, bp, blen, len);
15284d9c625SLionel Sambuc 			MEMCPYW(bp, p, len);
15384d9c625SLionel Sambuc 			if (db_append(sp, 1, tl, bp, len))
15484d9c625SLionel Sambuc 				return (1);
15584d9c625SLionel Sambuc 			if (mark_reset)
15684d9c625SLionel Sambuc 				LIST_FOREACH(lmp, &sp->ep->marks, q)
15784d9c625SLionel Sambuc 					if (lmp->name != ABSMARK1 &&
15884d9c625SLionel Sambuc 					    lmp->lno == fl)
15984d9c625SLionel Sambuc 						lmp->lno = tl + 1;
16084d9c625SLionel Sambuc 			if (db_delete(sp, fl))
16184d9c625SLionel Sambuc 				return (1);
16284d9c625SLionel Sambuc 		}
16384d9c625SLionel Sambuc 	} else {				/* Destination < source. */
16484d9c625SLionel Sambuc 		mfl = tl;
16584d9c625SLionel Sambuc 		mtl = tl + diff;
16684d9c625SLionel Sambuc 		for (cnt = diff; cnt--;) {
16784d9c625SLionel Sambuc 			if (db_get(sp, fl, DBG_FATAL, &p, &len))
16884d9c625SLionel Sambuc 				return (1);
16984d9c625SLionel Sambuc 			BINC_RETW(sp, bp, blen, len);
17084d9c625SLionel Sambuc 			MEMCPYW(bp, p, len);
17184d9c625SLionel Sambuc 			if (db_append(sp, 1, tl++, bp, len))
17284d9c625SLionel Sambuc 				return (1);
17384d9c625SLionel Sambuc 			if (mark_reset)
17484d9c625SLionel Sambuc 				LIST_FOREACH(lmp, &sp->ep->marks, q)
17584d9c625SLionel Sambuc 					if (lmp->name != ABSMARK1 &&
17684d9c625SLionel Sambuc 					    lmp->lno == fl)
17784d9c625SLionel Sambuc 						lmp->lno = tl;
17884d9c625SLionel Sambuc 			++fl;
17984d9c625SLionel Sambuc 			if (db_delete(sp, fl))
18084d9c625SLionel Sambuc 				return (1);
18184d9c625SLionel Sambuc 		}
18284d9c625SLionel Sambuc 	}
18384d9c625SLionel Sambuc 	FREE_SPACEW(sp, bp, blen);
18484d9c625SLionel Sambuc 
18584d9c625SLionel Sambuc 	sp->lno = tl;				/* Last line moved. */
18684d9c625SLionel Sambuc 	sp->cno = 0;
18784d9c625SLionel Sambuc 
18884d9c625SLionel Sambuc 	/* Log the new positions of the marks. */
18984d9c625SLionel Sambuc 	if (mark_reset)
19084d9c625SLionel Sambuc 		LIST_FOREACH(lmp, &sp->ep->marks, q)
19184d9c625SLionel Sambuc 			if (lmp->name != ABSMARK1 &&
19284d9c625SLionel Sambuc 			    lmp->lno >= mfl && lmp->lno <= mtl)
19384d9c625SLionel Sambuc 				(void)log_mark(sp, lmp);
19484d9c625SLionel Sambuc 
19584d9c625SLionel Sambuc 
19684d9c625SLionel Sambuc 	sp->rptlines[L_MOVED] += diff;
19784d9c625SLionel Sambuc 	return (0);
19884d9c625SLionel Sambuc }
199