This is a discussion on mg yank/undo fix within the mailing.openbsd.tech forums, part of the OpenBSD category; --> The following diff fixes an error where undoing a yank operation actually doubles the text in the yank buffer. ...
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| The following diff fixes an error where undoing a yank operation actually doubles the text in the yank buffer. to reproduce, do a C-K, C-Y, M-x undo, C-Y in a buffer with some text. Please have a close look at this one, as it changes the semantics of the KFORW/KBACK flags into, well, flags. Index: def.h ================================================== ================= RCS file: /usr/local/cvs/src/usr.bin/mg/def.h,v retrieving revision 1.72 diff -u -r1.72 def.h --- def.h 7 Nov 2005 23:32:20 -0000 1.72 +++ def.h 16 Nov 2005 18:40:46 -0000 @@ -108,9 +108,10 @@ /* * Flags for "ldelete"/"kinsert" */ -#define KNONE 0 -#define KFORW 1 -#define KBACK 2 +#define KNONE 0x0001 +#define KFORW 0x0002 +#define KBACK 0x0004 +#define KUNDO 0x0008 /* @@ -357,6 +358,7 @@ void kdelete(void); int kinsert(int, int); int kremove(int); +int kchunk(char *, RSIZE, int); /* window.c X */ MGWIN *new_window(BUFFER *); Index: line.c ================================================== ================= RCS file: /usr/local/cvs/src/usr.bin/mg/line.c,v retrieving revision 1.25 diff -u -r1.25 line.c --- line.c 13 Oct 2005 20:28:49 -0000 1.25 +++ line.c 16 Nov 2005 18:42:45 -0000 @@ -427,13 +427,6 @@ undo_add_delete(curwp->w_dotp, curwp->w_doto, n); - /* - * HACK - doesn't matter, and fixes back-over-nl bug for empty - * kill buffers. - */ - if (kused == kstart) - kflag = KFORW; - while (n != 0) { dotp = curwp->w_dotp; doto = curwp->w_doto; @@ -452,7 +445,7 @@ return (FALSE); lchange(WFHARD); if (ldelnewline() == FALSE || - (kflag != KNONE && kinsert('\n', kflag) == FALSE)) + kinsert('\n', kflag) == FALSE) return (FALSE); --n; continue; @@ -460,20 +453,8 @@ lchange(WFEDIT); /* Scrunch text */ cp1 = &dotp->l_text[doto]; - if (kflag == KFORW) { - while (ksize - kused < chunk) - if (kgrow(FALSE) == FALSE) - return (FALSE); - bcopy(cp1, &(kbufp[kused]), (int)chunk); - kused += chunk; - } else if (kflag == KBACK) { - while (kstart < chunk) - if (kgrow(TRUE) == FALSE) - return (FALSE); - bcopy(cp1, &(kbufp[kstart - chunk]), (int)chunk); - kstart -= chunk; - } else if (kflag != KNONE) - panic("broken ldelete call"); + if (kchunk(cp1, chunk, kflag) != TRUE) + return (FALSE); for (cp2 = cp1 + chunk; cp2 < &dotp->l_text[dotp->l_used]; cp2++) *cp1++ = *cp2; @@ -622,17 +603,20 @@ * that if you put something in the kill buffer you are going to put more * stuff there too later. Return TRUE if all is well, and FALSE on errors. * Print a message on errors. Dir says whether to put it at back or front. + * This call is ignored if KUNDO or KNONE is set. */ int -kinsert(int c, int dir) +kinsert(int c, int kflag) { - if (kused == ksize && dir == KFORW && kgrow(FALSE) == FALSE) + if (kflag & (KUNDO | KNONE)) + return (TRUE); + if (kused == ksize && (kflag & KFORW) && kgrow(FALSE) == FALSE) return (FALSE); - if (kstart == 0 && dir == KBACK && kgrow(TRUE) == FALSE) + if (kstart == 0 && (kflag & KBACK) && kgrow(TRUE) == FALSE) return (FALSE); - if (dir == KFORW) + if (kflag & KFORW) kbufp[kused++] = c; - else if (dir == KBACK) + else if (kflag & KBACK) kbufp[--kstart] = c; else panic("broken kinsert call"); /* Oh shit! */ @@ -640,7 +624,7 @@ } /* - * kgrow - just get more kill buffer for the callee. back is true if + * kgrow - just get more kill buffer for the callee. If back is TRUE, * we are trying to get space at the beginning of the kill buffer. */ static int @@ -680,4 +664,37 @@ if (n < 0 || n + kstart >= kused) return (-1); return (CHARMASK(kbufp[n + kstart])); +} + +/* + * copy a string into the kill buffer. kflag gives direction. + * if KUNDO set, do nothing. + */ +int +kchunk(char *cp1, RSIZE chunk, int kflag) +{ + /* + * HACK - doesn't matter, and fixes back-over-nl bug for empty + * kill buffers. + */ + if (kused == kstart) + kflag |= KFORW; + if (kflag & KUNDO) { + return (TRUE); + } else if (kflag & KFORW) { + while (ksize - kused < chunk) + if (kgrow(FALSE) == FALSE) + return (FALSE); + bcopy(cp1, &(kbufp[kused]), (int)chunk); + kused += chunk; + } else if (kflag & KBACK) { + while (kstart < chunk) + if (kgrow(TRUE) == FALSE) + return (FALSE); + bcopy(cp1, &(kbufp[kstart - chunk]), (int)chunk); + kstart -= chunk; + } else if (!(kflag & KNONE)) + panic("broken kchunk call"); + + return (TRUE); } Index: undo.c ================================================== ================= RCS file: /usr/local/cvs/src/usr.bin/mg/undo.c,v retrieving revision 1.33 diff -u -r1.33 undo.c --- undo.c 12 Nov 2005 18:48:08 -0000 1.33 +++ undo.c 16 Nov 2005 18:33:01 -0000 @@ -506,7 +506,7 @@ */ switch (ptr->type) { case INSERT: - ldelete(ptr->region.r_size, KFORW); + ldelete(ptr->region.r_size, KFORW | KUNDO); break; case DELETE: region_put_data(ptr->content, |