changeset 5202:8edba3805d78 v7.4a.027

updated for version 7.4a.027 Problem: When Python adds lines to another buffer the cursor position is wrong, it might be below the last line causing ml_get errors. (Vlad Irnov) Solution: Temporarily change the current window, so that marks are corrected properly.
author Bram Moolenaar <bram@vim.org>
date Wed, 17 Jul 2013 17:15:25 +0200
parents b2ed17f5d19c
children 72e04e0e326d
files src/if_py_both.h src/proto/buffer.pro src/version.c src/window.c
diffstat 4 files changed, 34 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -3997,30 +3997,43 @@ SetBufferLineList(
     static int
 InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
 {
+    buf_T	*save_curbuf = NULL;
+    win_T	*wp;
+    win_T	*save_curwin = NULL;
+    tabpage_T	*tp;
+    tabpage_T	*save_curtab = NULL;
+
     /* First of all, we check the type of the supplied Python object.
      * It must be a string or a list, or the call is in error.
      */
     if (PyBytes_Check(lines) || PyUnicode_Check(lines))
     {
-	char	*str = StringToLine(lines);
-	buf_T	*savebuf;
+	char		*str = StringToLine(lines);
 
 	if (str == NULL)
 	    return FAIL;
 
 	PyErr_Clear();
 	VimTryStart();
-	switch_buffer(&savebuf, buf);
-
-	if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
+	if (find_win_for_buf(buf, &wp, &tp) == FAIL
+		|| switch_win(&save_curwin, &save_curtab, wp, tp, TRUE)
+								      == FAIL)
+	    switch_buffer(&save_curbuf, buf);
+
+	if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
 	    RAISE_UNDO_FAIL;
 	else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL)
 	    RAISE_INSERT_LINE_FAIL;
-	else
+	else if (save_curbuf == NULL)
+	    /* Only adjust marks if we managed to switch to a window that
+	     * holds the buffer, otherwise line numbers will be invalid. */
 	    appended_lines_mark((linenr_T)n, 1L);
 
 	vim_free(str);
-	restore_buffer(savebuf);
+	if (save_curbuf == NULL)
+	    restore_win(save_curwin, save_curtab, TRUE);
+	else
+	    restore_buffer(save_curbuf);
 	update_screen(VALID);
 
 	if (VimTryEnd())
@@ -4036,7 +4049,6 @@ InsertBufferLines(buf_T *buf, PyInt n, P
 	PyInt	i;
 	PyInt	size = PyList_Size(lines);
 	char	**array;
-	buf_T	*savebuf;
 
 	array = PyMem_New(char *, size);
 	if (array == NULL)
@@ -4061,7 +4073,10 @@ InsertBufferLines(buf_T *buf, PyInt n, P
 
 	PyErr_Clear();
 	VimTryStart();
-	switch_buffer(&savebuf, buf);
+	if (find_win_for_buf(buf, &wp, &tp) == FAIL
+		|| switch_win(&save_curwin, &save_curtab, wp, tp, TRUE)
+								      == FAIL)
+	    switch_buffer(&save_curbuf, buf);
 
 	if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
 	    RAISE_UNDO_FAIL;
@@ -4087,11 +4102,13 @@ InsertBufferLines(buf_T *buf, PyInt n, P
 	}
 
 	/* Free the array of lines. All of its contents have now
-	 * been freed.
-	 */
+	 * been freed. */
 	PyMem_Free(array);
 
-	restore_buffer(savebuf);
+	if (save_curbuf == NULL)
+	    restore_win(save_curwin, save_curtab, TRUE);
+	else
+	    restore_buffer(save_curbuf);
 	update_screen(VALID);
 
 	if (VimTryEnd())
--- a/src/proto/buffer.pro
+++ b/src/proto/buffer.pro
@@ -52,6 +52,7 @@ void do_modelines __ARGS((int flags));
 int read_viminfo_bufferlist __ARGS((vir_T *virp, int writing));
 void write_viminfo_bufferlist __ARGS((FILE *fp));
 char_u *buf_spname __ARGS((buf_T *buf));
+int find_win_for_buf __ARGS((buf_T *buf, win_T **wp, tabpage_T **tp));
 void buf_addsign __ARGS((buf_T *buf, int id, linenr_T lnum, int typenr));
 linenr_T buf_change_sign_type __ARGS((buf_T *buf, int markId, int typenr));
 int buf_getsigntype __ARGS((buf_T *buf, linenr_T lnum, int type));
--- a/src/version.c
+++ b/src/version.c
@@ -728,6 +728,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    27,
+/**/
     26,
 /**/
     25,
--- a/src/window.c
+++ b/src/window.c
@@ -6577,7 +6577,8 @@ restore_snapshot_rec(sn, fr)
 
 #endif
 
-#if defined(FEAT_EVAL) || defined(PROTO)
+#if defined(FEAT_EVAL) || defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) \
+	|| defined(PROTO)
 /*
  * Set "win" to be the curwin and "tp" to be the current tab page.
  * restore_win() MUST be called to undo.