1
0
mirror of https://github.com/openbsd/src.git synced 2026-04-29 00:27:11 +00:00

vi: fix 'p' command with a count

This moves the count support from v_put() to put().  Previously,
v_put() would call put() "count" times.  Because put() also updates
the cursor position, this resulted in the text being pasted in the
wrong place after the first call to put().  Moving the "count" loop
into put() itself means the cursor position is only updated once.

From Walter Alejandro Iglesias
This commit is contained in:
millert
2025-08-23 21:02:10 +00:00
parent b2576f5c9a
commit 9279bdd4d7
5 changed files with 47 additions and 42 deletions

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: put.c,v 1.16 2016/05/27 09:18:11 martijn Exp $ */
/* $OpenBSD: put.c,v 1.17 2025/08/23 21:02:10 millert Exp $ */
/*-
* Copyright (c) 1992, 1993, 1994
@@ -27,16 +27,16 @@
* put --
* Put text buffer contents into the file.
*
* PUBLIC: int put(SCR *, CB *, CHAR_T *, MARK *, MARK *, int);
* PUBLIC: int put(SCR *, CB *, CHAR_T *, MARK *, MARK *, int, int);
*/
int
put(SCR *sp, CB *cbp, CHAR_T *namep, MARK *cp, MARK *rp, int append)
put(SCR *sp, CB *cbp, CHAR_T *namep, MARK *cp, MARK *rp, int append, int cnt)
{
CHAR_T name;
TEXT *ltp, *tp;
recno_t lno;
size_t blen, clen, len;
int rval;
int rval, i, isempty;
char *bp, *p, *t;
if (cbp == NULL) {
@@ -77,11 +77,15 @@ put(SCR *sp, CB *cbp, CHAR_T *namep, MARK *cp, MARK *rp, int append)
if (cp->lno == 1) {
if (db_last(sp, &lno))
return (1);
if (lno == 0) {
for (; tp; ++lno, ++sp->rptlines[L_ADDED],
tp = TAILQ_NEXT(tp, q))
if (db_append(sp, 1, lno, tp->lb, tp->len))
return (1);
if (lno == 0 && F_ISSET(cbp, CB_LMODE)) {
for (i = cnt; i > 0; i--) {
for (; tp; ++lno, ++sp->rptlines[L_ADDED],
tp = TAILQ_NEXT(tp, q))
if (db_append(sp, 1, lno, tp->lb,
tp->len))
return (1);
tp = TAILQ_FIRST(&cbp->textq);
}
rp->lno = 1;
rp->cno = 0;
return (0);
@@ -92,10 +96,14 @@ put(SCR *sp, CB *cbp, CHAR_T *namep, MARK *cp, MARK *rp, int append)
if (F_ISSET(cbp, CB_LMODE)) {
lno = append ? cp->lno : cp->lno - 1;
rp->lno = lno + 1;
for (; tp;
++lno, ++sp->rptlines[L_ADDED], tp = TAILQ_NEXT(tp, q))
if (db_append(sp, 1, lno, tp->lb, tp->len))
return (1);
for (i = cnt; i > 0; i--) {
for (; tp;
++lno, ++sp->rptlines[L_ADDED],
tp = TAILQ_NEXT(tp, q))
if (db_append(sp, 1, lno, tp->lb, tp->len))
return (1);
tp = TAILQ_FIRST(&cbp->textq);
}
rp->cno = 0;
(void)nonblank(sp, rp->lno, &rp->cno);
return (0);
@@ -111,8 +119,11 @@ put(SCR *sp, CB *cbp, CHAR_T *namep, MARK *cp, MARK *rp, int append)
* Get the first line.
*/
lno = cp->lno;
if (db_get(sp, lno, DBG_FATAL, &p, &len))
return (1);
if (db_eget(sp, lno, &p, &len, &isempty)) {
if (!isempty)
return (1);
len = 0;
}
GET_SPACE_RET(sp, bp, blen, tp->len + len + 1);
t = bp;
@@ -126,8 +137,10 @@ put(SCR *sp, CB *cbp, CHAR_T *namep, MARK *cp, MARK *rp, int append)
/* First line from the CB. */
if (tp->len != 0) {
memcpy(t, tp->lb, tp->len);
t += tp->len;
for (i = cnt; i > 0; i--) {
memcpy(t, tp->lb, tp->len);
t += tp->len;
}
}
/* Calculate length left in the original line. */

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: ex_move.c,v 1.11 2016/01/06 22:28:52 millert Exp $ */
/* $OpenBSD: ex_move.c,v 1.12 2025/08/23 21:02:10 millert Exp $ */
/*-
* Copyright (c) 1992, 1993, 1994
@@ -59,7 +59,7 @@ ex_copy(SCR *sp, EXCMD *cmdp)
/* Put the text into place. */
tm.lno = cmdp->lineno;
tm.cno = 0;
if (put(sp, &cb, NULL, &tm, &m, 1))
if (put(sp, &cb, NULL, &tm, &m, 1, 1))
rval = 1;
else {
/*

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: ex_put.c,v 1.6 2014/11/12 04:28:41 bentley Exp $ */
/* $OpenBSD: ex_put.c,v 1.7 2025/08/23 21:02:10 millert Exp $ */
/*-
* Copyright (c) 1992, 1993, 1994
@@ -39,7 +39,7 @@ ex_put(SCR *sp, EXCMD *cmdp)
m.cno = sp->cno;
if (put(sp, NULL,
FL_ISSET(cmdp->iflags, E_C_BUFFER) ? &cmdp->buffer : NULL,
&cmdp->addr1, &m, 1))
&cmdp->addr1, &m, 1, 1))
return (1);
sp->lno = m.lno;
sp->cno = m.cno;

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: com_extern.h,v 1.16 2019/05/21 09:24:58 martijn Exp $ */
/* $OpenBSD: com_extern.h,v 1.17 2025/08/23 21:02:10 millert Exp $ */
int cut(SCR *, CHAR_T *, MARK *, MARK *, int);
int cut_line(SCR *, recno_t, size_t, size_t, CB *);
@@ -81,7 +81,7 @@ int f_w300(SCR *, OPTION *, char *, u_long *);
int f_w1200(SCR *, OPTION *, char *, u_long *);
int f_w9600(SCR *, OPTION *, char *, u_long *);
int f_window(SCR *, OPTION *, char *, u_long *);
int put(SCR *, CB *, CHAR_T *, MARK *, MARK *, int);
int put(SCR *, CB *, CHAR_T *, MARK *, MARK *, int, int);
int rcv_tmp(SCR *, EXF *, char *);
int rcv_init(SCR *);
int rcv_sync(SCR *, u_int);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: v_put.c,v 1.8 2016/05/27 09:18:12 martijn Exp $ */
/* $OpenBSD: v_put.c,v 1.9 2025/08/23 21:02:10 millert Exp $ */
/*-
* Copyright (c) 1992, 1993, 1994
@@ -43,15 +43,11 @@ v_Put(SCR *sp, VICMD *vp)
* Historic vi did not support a count with the 'p' and 'P'
* commands. It's useful, so we do.
*/
for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
if (put(sp, NULL,
F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
&vp->m_start, &vp->m_final, 0))
return (1);
vp->m_start = vp->m_final;
if (INTERRUPTED(sp))
return (1);
}
cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
if (put(sp, NULL, F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
&vp->m_start, &vp->m_final, 0, cnt))
return (1);
return (0);
}
@@ -74,15 +70,11 @@ v_put(SCR *sp, VICMD *vp)
* Historic vi did not support a count with the 'p' and 'P'
* commands. It's useful, so we do.
*/
for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
if (put(sp, NULL,
F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
&vp->m_start, &vp->m_final, 1))
return (1);
vp->m_start = vp->m_final;
if (INTERRUPTED(sp))
return (1);
}
cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
if (put(sp, NULL, F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
&vp->m_start, &vp->m_final, 1, cnt))
return (1);
return (0);
}