To: vim-dev@vim.org Subject: Patch 7.1.207 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ Patch 7.1.207 Problem: Netbeans: "remove" cannot delete one line. Solution: Remove partial lines and whole lines properly. Avoid a memory leak. (Xavier de Gaye) Files: src/netbeans.c *** ../vim-7.1.206/src/netbeans.c Thu May 10 18:40:48 2007 --- src/netbeans.c Sat Jan 5 18:03:24 2008 *************** *** 1204,1209 **** --- 1204,1257 ---- return result; } + /* + * Remove from "first" byte to "last" byte (inclusive), at line "lnum" of the + * current buffer. Remove to end of line when "last" is MAXCOL. + */ + static void + nb_partialremove(linenr_T lnum, colnr_T first, colnr_T last) + { + char_u *oldtext, *newtext; + int oldlen; + int lastbyte = last; + + oldtext = ml_get(lnum); + oldlen = STRLEN(oldtext); + if (first >= oldlen || oldlen == 0) /* just in case */ + return; + if (lastbyte >= oldlen) + lastbyte = oldlen - 1; + newtext = alloc(oldlen - (int)(lastbyte - first)); + if (newtext != NULL) + { + mch_memmove(newtext, oldtext, first); + mch_memmove(newtext + first, oldtext + lastbyte + 1, STRLEN(oldtext + lastbyte + 1) + 1); + nbdebug((" NEW LINE %d: %s\n", lnum, newtext)); + ml_replace(lnum, newtext, FALSE); + } + } + + /* + * Replace the "first" line with the concatenation of the "first" and + * the "other" line. The "other" line is not removed. + */ + static void + nb_joinlines(linenr_T first, linenr_T other) + { + int len_first, len_other; + char_u *p; + + len_first = STRLEN(ml_get(first)); + len_other = STRLEN(ml_get(other)); + p = alloc((unsigned)(len_first + len_other + 1)); + if (p != NULL) + { + mch_memmove(p, ml_get(first), len_first); + mch_memmove(p + len_first, ml_get(other), len_other + 1); + ml_replace(first, p, FALSE); + } + } + #define SKIP_STOP 2 #define streq(a,b) (strcmp(a,b) == 0) static int needupdate = 0; *************** *** 1371,1376 **** --- 1419,1426 ---- long count; pos_T first, last; pos_T *pos; + pos_T *next; + linenr_T del_from_lnum, del_to_lnum; /* lines to be deleted as a whole */ int oldFire = netbeansFireChanges; int oldSuppress = netbeansSuppressNoLines; int wasChanged; *************** *** 1420,1444 **** } last = *pos; nbdebug((" LAST POS: line %d, col %d\n", last.lnum, last.col)); ! curwin->w_cursor = first; doupdate = 1; ! /* keep part of first line */ ! if (first.lnum == last.lnum && first.col != last.col) { ! /* deletion is within one line */ ! char_u *p = ml_get(first.lnum); ! mch_memmove(p + first.col, p + last.col + 1, STRLEN(p + last.col) + 1); ! nbdebug((" NEW LINE %d: %s\n", first.lnum, p)); ! ml_replace(first.lnum, p, TRUE); } ! if (first.lnum < last.lnum) { int i; /* delete signs from the lines being deleted */ ! for (i = first.lnum; i <= last.lnum; i++) { int id = buf_findsign_id(buf->bufp, (linenr_T)i); if (id > 0) --- 1470,1544 ---- } last = *pos; nbdebug((" LAST POS: line %d, col %d\n", last.lnum, last.col)); ! del_from_lnum = first.lnum; ! del_to_lnum = last.lnum; doupdate = 1; ! /* Get the position of the first byte after the deleted ! * section. "next" is NULL when deleting to the end of the ! * file. */ ! next = off2pos(buf->bufp, off + count); ! ! /* Remove part of the first line. */ ! if (first.col != 0 || (next != NULL && first.lnum == next->lnum)) { ! if (first.lnum != last.lnum ! || (next != NULL && first.lnum != next->lnum)) ! { ! /* remove to the end of the first line */ ! nb_partialremove(first.lnum, first.col, ! (colnr_T)MAXCOL); ! if (first.lnum == last.lnum) ! { ! /* Partial line to remove includes the end of ! * line. Join the line with the next one, have ! * the next line deleted below. */ ! nb_joinlines(first.lnum, next->lnum); ! del_to_lnum = next->lnum; ! } ! } ! else ! { ! /* remove within one line */ ! nb_partialremove(first.lnum, first.col, last.col); ! } ! ++del_from_lnum; /* don't delete the first line */ ! } ! ! /* Remove part of the last line. */ ! if (first.lnum != last.lnum && next != NULL ! && next->col != 0 && last.lnum == next->lnum) ! { ! nb_partialremove(last.lnum, 0, last.col); ! if (del_from_lnum > first.lnum) ! { ! /* Join end of last line to start of first line; last ! * line is deleted below. */ ! nb_joinlines(first.lnum, last.lnum); ! } ! else ! /* First line is deleted as a whole, keep the last ! * line. */ ! --del_to_lnum; } ! /* First is partial line; last line to remove includes ! * the end of line; join first line to line following last ! * line; line following last line is deleted below. */ ! if (first.lnum != last.lnum && del_from_lnum > first.lnum ! && next != NULL && last.lnum != next->lnum) ! { ! nb_joinlines(first.lnum, next->lnum); ! del_to_lnum = next->lnum; ! } ! ! /* Delete whole lines if there are any. */ ! if (del_to_lnum >= del_from_lnum) { int i; /* delete signs from the lines being deleted */ ! for (i = del_from_lnum; i <= del_to_lnum; i++) { int id = buf_findsign_id(buf->bufp, (linenr_T)i); if (id > 0) *************** *** 1450,1459 **** nbdebug((" No sign on line %d\n", i)); } ! /* delete whole lines */ ! nbdebug((" Deleting lines %d through %d\n", first.lnum, last.lnum)); ! del_lines(last.lnum - first.lnum + 1, FALSE); } buf->bufp->b_changed = wasChanged; /* logically unchanged */ netbeansFireChanges = oldFire; netbeansSuppressNoLines = oldSuppress; --- 1550,1564 ---- nbdebug((" No sign on line %d\n", i)); } ! nbdebug((" Deleting lines %d through %d\n", del_from_lnum, del_to_lnum)); ! curwin->w_cursor.lnum = del_from_lnum; ! curwin->w_cursor.col = 0; ! del_lines(del_to_lnum - del_from_lnum + 1, FALSE); } + + /* Leave cursor at first deleted byte. */ + curwin->w_cursor = first; + check_cursor_lnum(); buf->bufp->b_changed = wasChanged; /* logically unchanged */ netbeansFireChanges = oldFire; netbeansSuppressNoLines = oldSuppress; *************** *** 2374,2381 **** * the current buffer as "buf". */ static void ! nb_set_curbuf(buf) ! buf_T *buf; { if (curbuf != buf && buf_jump_open_win(buf) == NULL) set_curbuf(buf, DOBUF_GOTO); --- 2479,2485 ---- * the current buffer as "buf". */ static void ! nb_set_curbuf(buf_T *buf) { if (curbuf != buf && buf_jump_open_win(buf) == NULL) set_curbuf(buf, DOBUF_GOTO); *** ../vim-7.1.206/src/version.c Sat Jan 5 13:58:48 2008 --- src/version.c Sat Jan 5 18:06:04 2008 *************** *** 668,669 **** --- 668,671 ---- { /* Add new patch number below this line */ + /**/ + 207, /**/ -- Q: How many hardware engineers does it take to change a lightbulb? A: None. We'll fix it in software. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ download, build and distribute -- http://www.A-A-P.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///