To: vim-dev@vim.org Subject: Patch 6.1.220 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ Patch 6.1.220 Problem: When using a BufReadPost autocommand that changes the line count, e.g., "$-1join", reloading a file that was changed outside Vim does not work properly. (Alan G Isaac) Solution: Make the buffer empty before reading the new version of the file. Save the lines in a dummy buffer, so that they can be put back when reading the file fails. Files: src/buffer.c, src/ex_cmds.c, src/fileio.c, src/globals.h, src/proto/buffer.pro *** ../vim61.219/src/buffer.c Mon Oct 7 20:45:41 2002 --- src/buffer.c Sun Oct 13 18:22:22 2002 *************** *** 4545,4551 **** /* Force the 'fileencoding' and 'fileformat' to be equal. */ if (prep_exarg(&ea, buf) == FAIL) { ! close_buffer(NULL, newbuf, DOBUF_WIPE); return TRUE; } --- 4545,4551 ---- /* Force the 'fileencoding' and 'fileformat' to be equal. */ if (prep_exarg(&ea, buf) == FAIL) { ! wipe_buffer(newbuf, FALSE); return TRUE; } *************** *** 4585,4591 **** #endif if (curbuf != newbuf) /* safety check */ ! wipe_buffer(newbuf); return differ; } --- 4585,4591 ---- #endif if (curbuf != newbuf) /* safety check */ ! wipe_buffer(newbuf, FALSE); return differ; } *************** *** 4595,4605 **** * this buffer. Call this to wipe out a temp buffer that does not contain any * marks. */ void ! wipe_buffer(buf) buf_T *buf; { if (buf->b_fnum == top_file_num - 1) --top_file_num; close_buffer(NULL, buf, DOBUF_WIPE); } --- 4595,4616 ---- * this buffer. Call this to wipe out a temp buffer that does not contain any * marks. */ + /*ARGSUSED*/ void ! wipe_buffer(buf, aucmd) buf_T *buf; + int aucmd; /* When TRUE trigger autocommands. */ { if (buf->b_fnum == top_file_num - 1) --top_file_num; + + #ifdef FEAT_AUTOCMD + if (!aucmd) /* Don't trigger BufDelete autocommands here. */ + ++autocmd_block; + #endif close_buffer(NULL, buf, DOBUF_WIPE); + #ifdef FEAT_AUTOCMD + if (!aucmd) + --autocmd_block; + #endif } *** ../vim61.219/src/ex_cmds.c Wed Sep 25 22:21:44 2002 --- src/ex_cmds.c Sun Oct 13 18:22:31 2002 *************** *** 4518,4524 **** { buf = buflist_findnr(empty_fnum); if (buf != NULL) ! wipe_buffer(buf); } /* keep the previous alternate file */ --- 4518,4524 ---- { buf = buflist_findnr(empty_fnum); if (buf != NULL) ! wipe_buffer(buf, TRUE); } /* keep the previous alternate file */ *** ../vim61.219/src/fileio.c Sat Oct 12 15:48:03 2002 --- src/fileio.c Sun Oct 13 18:42:11 2002 *************** *** 5043,5048 **** --- 5218,5268 ---- } /* + * Move all the lines from buffer "frombuf" to buffer "tobuf". + * Return OK or FAIL. When FAIL "tobuf" is incomplete and/or "frombuf" is not + * empty. + */ + static int + move_lines(frombuf, tobuf) + buf_T *frombuf; + buf_T *tobuf; + { + buf_T *tbuf = curbuf; + int retval = OK; + linenr_T lnum; + char_u *p; + + /* Copy the lines in "frombuf" to "tobuf". */ + curbuf = tobuf; + for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum) + { + p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE)); + if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL) + { + retval = FAIL; + break; + } + } + + /* Delete all the lines in "frombuf". */ + if (retval != FAIL) + { + curbuf = frombuf; + while (!bufempty()) + if (ml_delete(curbuf->b_ml.ml_line_count, FALSE) == FAIL) + { + /* Oops! We could try putting back the saved lines, but that + * might fail again... */ + retval = FAIL; + break; + } + } + + curbuf = tbuf; + return retval; + } + + /* * Check if buffer "buf" has been changed. * Also check if the file for a new buffer unexpectedly appeared. * return 1 if a changed buffer was found. *************** *** 5230,5240 **** if (reload) { - linenr_T old_line_count = buf->b_ml.ml_line_count; exarg_T ea; pos_T old_cursor; linenr_T old_topline; int old_ro = curbuf->b_p_ro; #ifdef FEAT_AUTOCMD aco_save_T aco; --- 5450,5461 ---- if (reload) { exarg_T ea; pos_T old_cursor; linenr_T old_topline; int old_ro = curbuf->b_p_ro; + buf_T *savebuf; + int saved = OK; #ifdef FEAT_AUTOCMD aco_save_T aco; *************** *** 5254,5280 **** { old_cursor = curwin->w_cursor; old_topline = curwin->w_topline; if (bufempty()) ! old_line_count = 0; ! curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */ ! #ifdef FEAT_AUTOCMD ! keep_filetype = TRUE; /* don't detect 'filetype' */ ! #endif ! if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0, (linenr_T)0, ! (linenr_T)MAXLNUM, &ea, READ_NEW) == FAIL) ! EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname); else { ! /* Delete the old lines. */ ! while (old_line_count-- > 0) ! ml_delete(buf->b_ml.ml_line_count, FALSE); ! /* Mark the buffer as unmodified and free undo info. */ ! unchanged(buf, TRUE); ! u_blockfree(buf); ! u_clearall(buf); } vim_free(ea.cmd); #ifdef FEAT_DIFF /* Invalidate diff info if necessary. */ diff_invalidate(); --- 5475,5547 ---- { old_cursor = curwin->w_cursor; old_topline = curwin->w_topline; + + /* + * To behave like when a new file is edited (matters for + * BufReadPost autocommands) we first need to delete the current + * buffer contents. But if reading the file fails we should keep + * the old contents. Can't use memory only, the file might be + * too big. Use a hidden buffer to move the buffer contents to. + */ if (bufempty()) ! savebuf = NULL; else { ! /* Allocate a buffer without putting it in the buffer list. */ ! savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY); ! if (savebuf != NULL) ! { ! /* Open the memline. */ ! curbuf = savebuf; ! curwin->w_buffer = savebuf; ! saved = ml_open(); ! curbuf = buf; ! curwin->w_buffer = buf; ! } ! if (savebuf == NULL || saved == FAIL ! || move_lines(buf, savebuf) == FAIL) ! { ! EMSG2(_("E461: Could not prepare for reloading \"%s\""), ! buf->b_fname); ! saved = FAIL; ! } ! } ! ! if (saved == OK) ! { ! curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */ ! #ifdef FEAT_AUTOCMD ! keep_filetype = TRUE; /* don't detect 'filetype' */ ! #endif ! if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0, ! (linenr_T)0, ! (linenr_T)MAXLNUM, &ea, READ_NEW) == FAIL) ! { ! EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname); ! if (savebuf != NULL) ! { ! /* Put the text back from the save buffer. First ! * delete any lines that readfile() added. */ ! while (!bufempty()) ! if (ml_delete(curbuf->b_ml.ml_line_count, FALSE) ! == FAIL) ! break; ! (void)move_lines(savebuf, buf); ! } ! } ! else ! { ! /* Mark the buffer as unmodified and free undo info. */ ! unchanged(buf, TRUE); ! u_blockfree(buf); ! u_clearall(buf); ! } } vim_free(ea.cmd); + if (savebuf != NULL) + wipe_buffer(savebuf, FALSE); + #ifdef FEAT_DIFF /* Invalidate diff info if necessary. */ diff_invalidate(); *************** *** 5313,5319 **** #ifdef FEAT_AUTOCMD /* restore curwin/curbuf and a few other things */ aucmd_restbuf(&aco); - /* Careful: autocommands may have made "buf" invalid! */ #else curwin->w_buffer = save_curbuf; --- 5580,5585 ---- *************** *** 6820,6828 **** #endif /* ! * Quickly return if there are no autocommands for this event. */ ! if (first_autopat[(int)event] == NULL) return retval; /* --- 7086,7095 ---- #endif /* ! * Quickly return if there are no autocommands for this event or ! * autocommands are blocked. */ ! if (first_autopat[(int)event] == NULL || autocmd_block > 0) return retval; /* *** ../vim61.219/src/globals.h Mon Oct 7 20:45:41 2002 --- src/globals.h Sun Oct 13 18:18:07 2002 *************** *** 238,243 **** --- 238,244 ---- EXTERN int autocmd_busy INIT(= FALSE); /* Is apply_autocmds() busy? */ EXTERN int autocmd_no_enter INIT(= FALSE); /* *Enter autocmds disabled */ EXTERN int autocmd_no_leave INIT(= FALSE); /* *Leave autocmds disabled */ + EXTERN int autocmd_block INIT(= 0); /* block all autocmds */ EXTERN int modified_was_set; /* did ":set modified" */ EXTERN int did_filetype INIT(= FALSE); /* FileType event found */ EXTERN int keep_filetype INIT(= FALSE); /* value for did_filetype when *** ../vim61.219/src/proto/buffer.pro Fri Mar 22 21:41:05 2002 --- src/proto/buffer.pro Sun Oct 13 18:23:45 2002 *************** *** 60,64 **** void sign_mark_adjust __ARGS((linenr_T line1, linenr_T line2, long amount, long amount_after)); void set_buflisted __ARGS((int on)); int buf_contents_changed __ARGS((buf_T *buf)); ! void wipe_buffer __ARGS((buf_T *buf)); /* vim: set ft=c : */ --- 60,64 ---- void sign_mark_adjust __ARGS((linenr_T line1, linenr_T line2, long amount, long amount_after)); void set_buflisted __ARGS((int on)); int buf_contents_changed __ARGS((buf_T *buf)); ! void wipe_buffer __ARGS((buf_T *buf, int aucmd)); /* vim: set ft=c : */ *** ../vim61.219/src/version.c Sun Oct 13 16:05:33 2002 --- src/version.c Sun Oct 13 18:45:52 2002 *************** *** 608,609 **** --- 608,611 ---- { /* Add new patch number below this line */ + /**/ + 220, /**/ -- hundred-and-one symptoms of being an internet addict: 211. Your husband leaves you...taking the computer with him and you call him crying, and beg him to bring the computer back. /// Bram Moolenaar -- Bram@moolenaar.net -- http://www.moolenaar.net \\\ /// Creator of Vim - Vi IMproved -- http://www.vim.org \\\ \\\ Project leader for A-A-P -- http://www.a-a-p.org /// \\\ Lord Of The Rings helps Uganda - http://iccf-holland.org/lotr.html ///