From 2cc256f97c1b789dc568732eb4a97a6a34f20fdf Mon Sep 17 00:00:00 2001 From: Kjell Wooding Date: Thu, 6 Oct 2005 16:48:01 +0000 Subject: Make mg undo much more emacs like (and correct). Undo boundaries are now placed at newlines, and undo of search-replace works as expected. Fixes bad behaviour reported by matthieu Ok deraadt@, beck@ --- usr.bin/mg/def.h | 3 +- usr.bin/mg/line.c | 97 ++++++++++++++----------------------------------------- usr.bin/mg/undo.c | 28 ++++++++++++---- 3 files changed, 47 insertions(+), 81 deletions(-) (limited to 'usr.bin/mg') diff --git a/usr.bin/mg/def.h b/usr.bin/mg/def.h index a6bd33ef798..3cab2907800 100644 --- a/usr.bin/mg/def.h +++ b/usr.bin/mg/def.h @@ -1,4 +1,4 @@ -/* $OpenBSD: def.h,v 1.64 2005/06/14 18:14:40 kjell Exp $ */ +/* $OpenBSD: def.h,v 1.65 2005/10/06 16:48:00 kjell Exp $ */ /* This file is in the public domain. */ @@ -596,6 +596,7 @@ int undo_enable(int); int undo_add_boundary(void); int undo_add_insert(LINE *, int, int); int undo_add_delete(LINE *, int, int); +void undo_no_boundary(int); int undo_add_change(LINE *, int, int); int undo(int, int); diff --git a/usr.bin/mg/line.c b/usr.bin/mg/line.c index 30c1d379a27..2d7fd220b7b 100644 --- a/usr.bin/mg/line.c +++ b/usr.bin/mg/line.c @@ -1,4 +1,4 @@ -/* $OpenBSD: line.c,v 1.23 2005/06/14 18:14:40 kjell Exp $ */ +/* $OpenBSD: line.c,v 1.24 2005/10/06 16:48:00 kjell Exp $ */ /* This file is in the public domain. */ @@ -336,18 +336,17 @@ lnewline_at(LINE *lp1, int doto) LINE *lp2; int nlen; MGWIN *wp; + int retval = TRUE; lchange(WFHARD); - undo_add_boundary(); - undo_add_insert(lp1, llength(lp1), 1); - undo_add_boundary(); - /* avoid unnecessary copying */ if (doto == 0) { /* new first part */ - if ((lp2 = lalloc(0)) == NULL) - return (FALSE); + if ((lp2 = lalloc(0)) == NULL) { + retval = FALSE; + goto lnl_done; + } lp2->l_bp = lp1->l_bp; lp1->l_bp->l_fp = lp2; lp2->l_fp = lp1; @@ -355,15 +354,17 @@ lnewline_at(LINE *lp1, int doto) for (wp = wheadp; wp != NULL; wp = wp->w_wndp) if (wp->w_linep == lp1) wp->w_linep = lp2; - return (TRUE); + goto lnl_done; } /* length of new part */ nlen = llength(lp1) - doto; /* new second half line */ - if ((lp2 = lalloc(nlen)) == NULL) - return (FALSE); + if ((lp2 = lalloc(nlen)) == NULL) { + retval = FALSE; + goto lnl_done; + } if (nlen != 0) bcopy(&lp1->l_text[doto], &lp2->l_text[0], nlen); lp1->l_used = doto; @@ -382,7 +383,11 @@ lnewline_at(LINE *lp1, int doto) wp->w_marko -= doto; } } - return (TRUE); +lnl_done: + undo_add_boundary(); + undo_add_insert(lp1, llength(lp1), 1); + undo_add_boundary(); + return (retval); } /* @@ -576,77 +581,23 @@ int lreplace(RSIZE plen, char *st, int f) { RSIZE rlen; /* replacement length */ - int rtype; /* capitalization */ - int c; /* used for random characters */ - int doto; /* offset into line */ if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read only"); return (FALSE); } - - undo_add_change(curwp->w_dotp, curwp->w_doto, plen); - - /* - * Find the capitalization of the word that was found. f says use - * exact case of replacement string (same thing that happens with - * lowercase found), so bypass check. - */ - /* NOSTRICT */ + undo_add_boundary(); + undo_no_boundary(TRUE); + (void)backchar(FFARG | FFRAND, (int)plen); - rtype = _MG_L; - c = lgetc(curwp->w_dotp, curwp->w_doto); - if (ISUPPER(c) != FALSE && f == FALSE) { - rtype = _MG_U | _MG_L; - if (curwp->w_doto + 1 < llength(curwp->w_dotp)) { - c = lgetc(curwp->w_dotp, curwp->w_doto + 1); - if (ISUPPER(c) != FALSE) { - rtype = _MG_U; - } - } - } + (void)ldelete(plen, KNONE); - /* - * make the string lengths match (either pad the line - * so that it will fit, or scrunch out the excess). - * be careful with dot's offset. - */ rlen = strlen(st); - doto = curwp->w_doto; - if (plen > rlen) - (void)ldelete((RSIZE) (plen - rlen), KNONE); - else if (plen < rlen) { - if (linsert((int)(rlen - plen), ' ') == FALSE) - return (FALSE); - } - curwp->w_doto = doto; - - /* - * do the replacement: If was capital, then place first - * char as if upper, and subsequent chars as if lower. - * If inserting upper, check replacement for case. - */ - while ((c = CHARMASK(*st++)) != '\0') { - if ((rtype & _MG_U) != 0 && ISLOWER(c) != 0) - c = TOUPPER(c); - if (rtype == (_MG_U | _MG_L)) - rtype = _MG_L; - if (c == CCHR('J')) { - if (curwp->w_doto == llength(curwp->w_dotp)) - (void)forwchar(FFRAND, 1); - else { - if (ldelete((RSIZE) 1, KNONE) != FALSE) - (void)lnewline(); - } - } else if (curwp->w_dotp == curbp->b_linep) { - (void)linsert(1, c); - } else if (curwp->w_doto == llength(curwp->w_dotp)) { - if (ldelete((RSIZE) 1, KNONE) != FALSE) - (void)linsert(1, c); - } else - lputc(curwp->w_dotp, curwp->w_doto++, c); - } + region_put_data(st, rlen); lchange(WFHARD); + + undo_no_boundary(FALSE); + undo_add_boundary(); return (TRUE); } diff --git a/usr.bin/mg/undo.c b/usr.bin/mg/undo.c index 3630f3f5354..f5e7d5c3f2e 100644 --- a/usr.bin/mg/undo.c +++ b/usr.bin/mg/undo.c @@ -1,4 +1,4 @@ -/* $OpenBSD: undo.c,v 1.27 2005/05/29 21:37:49 cloder Exp $ */ +/* $OpenBSD: undo.c,v 1.28 2005/10/06 16:48:00 kjell Exp $ */ /* * Copyright (c) 2002 Vincent Labrecque * All rights reserved. @@ -184,6 +184,13 @@ undo_enable(int on) return (pon ? FALSE : TRUE); } +void +undo_no_boundary(int flag) +{ + if (!undo_disable_flag) + nobound = flag; +} + int undo_add_boundary(void) { @@ -192,6 +199,9 @@ undo_add_boundary(void) if (nobound) return (TRUE); + if (lastrectype() == BOUNDARY) + return (TRUE); + rec = new_undo_record(); rec->type = BOUNDARY; @@ -304,10 +314,10 @@ undo_add_change(LINE *lp, int offset, int size) if (undo_disable_flag) return (TRUE); undo_add_boundary(); - nobound = 1; + nobound = TRUE; undo_add_delete(lp, offset, size); undo_add_insert(lp, offset, size); - nobound = 0; + nobound = FALSE; undo_add_boundary(); return (TRUE); @@ -408,14 +418,17 @@ undo(int f, int n) int done, rval; LINE *lp; int offset, save, dot; + static int nulled = FALSE; dot = find_dot(curwp->w_dotp, curwp->w_doto); ptr = curwp->w_undoptr; /* if we moved, make ptr point back to the top of the list */ - if (ptr == NULL || curwp->w_undopos != dot) + if ((ptr == NULL && nulled == TRUE) || curwp->w_undopos != dot) { ptr = LIST_FIRST(&curwp->w_undo); + nulled = TRUE; + } rval = TRUE; while (n--) { @@ -434,19 +447,20 @@ undo(int f, int n) if (ptr == NULL) { ewprintf("No further undo information"); rval = FALSE; + nulled = TRUE; break; } + nulled = FALSE; /* * Loop while we don't get a boundary specifying we've * finished the current action... */ - if (lastrectype() != BOUNDARY) - undo_add_boundary(); + undo_add_boundary(); save = nobound; - nobound = 1; + nobound = TRUE; done = 0; do { -- cgit v1.2.3