]> granicus.if.org Git - vim/commitdiff
updated for version 7.3.963 v7.3.963
authorBram Moolenaar <Bram@vim.org>
Fri, 17 May 2013 14:03:57 +0000 (16:03 +0200)
committerBram Moolenaar <Bram@vim.org>
Fri, 17 May 2013 14:03:57 +0000 (16:03 +0200)
Problem:    Setting curbuf without curwin causes trouble.
Solution:   Add switch_buffer() and restore_buffer().  Block autocommands to
            avoid trouble.

src/eval.c
src/if_py_both.h
src/proto/eval.pro
src/proto/window.pro
src/testdir/test86.ok
src/version.c
src/window.c

index db2dc616e8cfbdacfb6cfefdd83baa5fff8be649..756baa39b89736e1c836eadaa8be8b36f04cd8d3 100644 (file)
@@ -11894,7 +11894,7 @@ getwinvar(argvars, rettv, off)
     win_T      *win, *oldcurwin;
     char_u     *varname;
     dictitem_T *v;
-    tabpage_T  *tp;
+    tabpage_T  *tp, *oldtabpage;
     int                done = FALSE;
 
 #ifdef FEAT_WINDOWS
@@ -11912,11 +11912,9 @@ getwinvar(argvars, rettv, off)
 
     if (win != NULL && varname != NULL)
     {
-       /* Set curwin to be our win, temporarily.  Also set curbuf, so
-        * that we can get buffer-local options. */
-       oldcurwin = curwin;
-       curwin = win;
-       curbuf = win->w_buffer;
+       /* Set curwin to be our win, temporarily.  Also set the tabpage,
+        * otherwise the window is not valid. */
+       switch_win(&oldcurwin, &oldtabpage, win, tp);
 
        if (*varname == '&')    /* window-local-option */
        {
@@ -11936,8 +11934,7 @@ getwinvar(argvars, rettv, off)
        }
 
        /* restore previous notion of curwin */
-       curwin = oldcurwin;
-       curbuf = curwin->w_buffer;
+       restore_win(oldcurwin, oldtabpage);
     }
 
     if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
@@ -16641,44 +16638,6 @@ f_setwinvar(argvars, rettv)
     setwinvar(argvars, rettv, 0);
 }
 
-    int
-switch_win(save_curwin, save_curtab, win, tp)
-    win_T      **save_curwin;
-    tabpage_T  **save_curtab;
-    win_T      *win;
-    tabpage_T  *tp;
-{
-#ifdef FEAT_WINDOWS
-    /* set curwin to be our win, temporarily */
-    *save_curwin = curwin;
-    *save_curtab = curtab;
-    goto_tabpage_tp(tp, FALSE, FALSE);
-    if (!win_valid(win))
-       return FAIL;
-    curwin = win;
-    curbuf = curwin->w_buffer;
-#endif
-    return OK;
-}
-
-    void
-restore_win(save_curwin, save_curtab)
-    win_T      *save_curwin;
-    tabpage_T  *save_curtab;
-{
-#ifdef FEAT_WINDOWS
-    /* Restore current tabpage and window, if still valid (autocommands can
-     * make them invalid). */
-    if (valid_tabpage(save_curtab))
-       goto_tabpage_tp(save_curtab, FALSE, FALSE);
-    if (win_valid(save_curwin))
-    {
-       curwin = save_curwin;
-       curbuf = curwin->w_buffer;
-    }
-#endif
-}
-
 /*
  * "setwinvar()" and "settabwinvar()" functions
  */
index 4bd5bae7d4b1ea954ef5cbdd6ca5383872267612..9539943edee46b3184afa1aec52aeb04092722f7 100644 (file)
@@ -1413,14 +1413,14 @@ set_option_value_for(key, numval, stringval, opt_flags, opt_type, from)
 {
     win_T      *save_curwin;
     tabpage_T  *save_curtab;
-    aco_save_T aco;
+    buf_T      *save_curbuf;
     int                r = 0;
 
     switch (opt_type)
     {
        case SREQ_WIN:
-           if (switch_win(&save_curwin, &save_curtab, (win_T *) from, curtab)
-                                                                     == FAIL)
+           if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
+                                    win_find_tabpage((win_T *)from)) == FAIL)
            {
                PyErr_SetVim("Problem while switching windows.");
                return -1;
@@ -1429,9 +1429,9 @@ set_option_value_for(key, numval, stringval, opt_flags, opt_type, from)
            restore_win(save_curwin, save_curtab);
            break;
        case SREQ_BUF:
-           aucmd_prepbuf(&aco, (buf_T *) from);
+           switch_buffer(&save_curbuf, (buf_T *)from);
            set_option_value(key, numval, stringval, opt_flags);
-           aucmd_restbuf(&aco);
+           restore_buffer(save_curbuf);
            break;
        case SREQ_GLOBAL:
            set_option_value(key, numval, stringval, opt_flags);
@@ -2240,10 +2240,10 @@ SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
      */
     if (line == Py_None || line == NULL)
     {
-       buf_T *savebuf = curbuf;
+       buf_T *savebuf;
 
        PyErr_Clear();
-       curbuf = buf;
+       switch_buffer(&savebuf, buf);
 
        if (u_savedel((linenr_T)n, 1L) == FAIL)
            PyErr_SetVim(_("cannot save undo information"));
@@ -2251,12 +2251,12 @@ SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
            PyErr_SetVim(_("cannot delete line"));
        else
        {
-           if (buf == curwin->w_buffer)
+           if (buf == savebuf)
                py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
            deleted_lines_mark((linenr_T)n, 1L);
        }
 
-       curbuf = savebuf;
+       restore_buffer(savebuf);
 
        if (PyErr_Occurred() || VimErrorCheck())
            return FAIL;
@@ -2269,14 +2269,14 @@ SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
     else if (PyString_Check(line))
     {
        char *save = StringToLine(line);
-       buf_T *savebuf = curbuf;
+       buf_T *savebuf;
 
        if (save == NULL)
            return FAIL;
 
        /* We do not need to free "save" if ml_replace() consumes it. */
        PyErr_Clear();
-       curbuf = buf;
+       switch_buffer(&savebuf, buf);
 
        if (u_savesub((linenr_T)n) == FAIL)
        {
@@ -2291,10 +2291,10 @@ SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
        else
            changed_bytes((linenr_T)n, 0);
 
-       curbuf = savebuf;
+       restore_buffer(savebuf);
 
        /* Check that the cursor is not beyond the end of the line now. */
-       if (buf == curwin->w_buffer)
+       if (buf == savebuf)
            check_cursor_col();
 
        if (PyErr_Occurred() || VimErrorCheck())
@@ -2333,10 +2333,10 @@ SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_cha
     {
        PyInt   i;
        PyInt   n = (int)(hi - lo);
-       buf_T   *savebuf = curbuf;
+       buf_T   *savebuf;
 
        PyErr_Clear();
-       curbuf = buf;
+       switch_buffer(&savebuf, buf);
 
        if (u_savedel((linenr_T)lo, (long)n) == FAIL)
            PyErr_SetVim(_("cannot save undo information"));
@@ -2350,12 +2350,12 @@ SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_cha
                    break;
                }
            }
-           if (buf == curwin->w_buffer)
+           if (buf == savebuf)
                py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
            deleted_lines_mark((linenr_T)lo, (long)i);
        }
 
-       curbuf = savebuf;
+       restore_buffer(savebuf);
 
        if (PyErr_Occurred() || VimErrorCheck())
            return FAIL;
@@ -2400,10 +2400,10 @@ SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_cha
            }
        }
 
-       savebuf = curbuf;
-
        PyErr_Clear();
-       curbuf = buf;
+
+       // START of region without "return".  Must call restore_buffer()!
+       switch_buffer(&savebuf, buf);
 
        if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
            PyErr_SetVim(_("cannot save undo information"));
@@ -2480,10 +2480,11 @@ SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_cha
                                                  (long)MAXLNUM, (long)extra);
        changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
 
-       if (buf == curwin->w_buffer)
+       if (buf == savebuf)
            py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
 
-       curbuf = savebuf;
+       // END of region without "return".
+       restore_buffer(savebuf);
 
        if (PyErr_Occurred() || VimErrorCheck())
            return FAIL;
@@ -2522,10 +2523,8 @@ InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
        if (str == NULL)
            return FAIL;
 
-       savebuf = curbuf;
-
        PyErr_Clear();
-       curbuf = buf;
+       switch_buffer(&savebuf, buf);
 
        if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
            PyErr_SetVim(_("cannot save undo information"));
@@ -2535,7 +2534,7 @@ InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
            appended_lines_mark((linenr_T)n, 1L);
 
        vim_free(str);
-       curbuf = savebuf;
+       restore_buffer(savebuf);
        update_screen(VALID);
 
        if (PyErr_Occurred() || VimErrorCheck())
@@ -2574,10 +2573,8 @@ InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
            }
        }
 
-       savebuf = curbuf;
-
        PyErr_Clear();
-       curbuf = buf;
+       switch_buffer(&savebuf, buf);
 
        if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
            PyErr_SetVim(_("cannot save undo information"));
@@ -2607,7 +2604,7 @@ InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
         */
        vim_free(array);
 
-       curbuf = savebuf;
+       restore_buffer(savebuf);
        update_screen(VALID);
 
        if (PyErr_Occurred() || VimErrorCheck())
@@ -3023,7 +3020,7 @@ BufferMark(PyObject *self, PyObject *args)
     pos_T      *posp;
     char       *pmark;
     char       mark;
-    buf_T      *curbuf_save;
+    buf_T      *savebuf;
 
     if (CheckBuffer((BufferObject *)(self)))
        return NULL;
@@ -3032,10 +3029,9 @@ BufferMark(PyObject *self, PyObject *args)
        return NULL;
     mark = *pmark;
 
-    curbuf_save = curbuf;
-    curbuf = ((BufferObject *)(self))->buf;
+    switch_buffer(&savebuf, ((BufferObject *)(self))->buf);
     posp = getmark(mark, FALSE);
-    curbuf = curbuf_save;
+    restore_buffer(savebuf);
 
     if (posp == NULL)
     {
index 7af6cd33813e92351f418877a76fac62a1cf2fa0..dfea118999cebdc82b38b509bdc86417e22aa036 100644 (file)
@@ -33,6 +33,8 @@ void prof_child_enter __ARGS((proftime_T *tm));
 void prof_child_exit __ARGS((proftime_T *tm));
 int eval_foldexpr __ARGS((char_u *arg, int *cp));
 void ex_let __ARGS((exarg_T *eap));
+void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
+void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
 void *eval_for_line __ARGS((char_u *arg, int *errp, char_u **nextcmdp, int skip));
 int next_for_item __ARGS((void *fi_void, char_u *arg));
 void free_for_info __ARGS((void *fi_void));
@@ -125,8 +127,4 @@ void last_set_msg __ARGS((scid_T scriptID));
 void ex_oldfiles __ARGS((exarg_T *eap));
 int modify_fname __ARGS((char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen));
 char_u *do_string_sub __ARGS((char_u *str, char_u *pat, char_u *sub, char_u *flags));
-int switch_win __ARGS((win_T **, tabpage_T **, win_T *, tabpage_T *));
-void restore_win __ARGS((win_T *, tabpage_T *));
-void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
-void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
 /* vim: set ft=c : */
index a7fcf0c861dace9bd2f2bc5a596a2d6dcbb147d6..83116c9e2ee4cfc012165111fff6b740ae61d0ed 100644 (file)
@@ -32,6 +32,7 @@ void goto_tabpage_win __ARGS((tabpage_T *tp, win_T *wp));
 void tabpage_move __ARGS((int nr));
 void win_goto __ARGS((win_T *wp));
 win_T *win_find_nr __ARGS((int winnr));
+tabpage_T *win_find_tabpage __ARGS((win_T *win));
 void win_enter __ARGS((win_T *wp, int undo_sync));
 win_T *buf_jump_open_win __ARGS((buf_T *buf));
 win_T *buf_jump_open_tab __ARGS((buf_T *buf));
@@ -69,6 +70,10 @@ int only_one_window __ARGS((void));
 void check_lnums __ARGS((int do_curwin));
 void make_snapshot __ARGS((int idx));
 void restore_snapshot __ARGS((int idx, int close_curwin));
+int switch_win __ARGS((win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp));
+void restore_win __ARGS((win_T *save_curwin, tabpage_T *save_curtab));
+void switch_buffer __ARGS((buf_T **save_curbuf, buf_T *buf));
+void restore_buffer __ARGS((buf_T *save_curbuf));
 int win_hasvertsplit __ARGS((void));
 int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id));
 int match_delete __ARGS((win_T *wp, int id, int perr));
index b33b5380ac71b1eb714029ed2e6cd4ce998f5c97..2f0d496efdaed5623d7a72898e1975266a1a1334 100644 (file)
@@ -333,7 +333,7 @@ Number of tabs: 4
 Current tab pages:
   <tabpage 0>(1): 1 windows, current is <window object (unknown)>
   Windows:
-    <window object (unknown)>(0): displays buffer <buffer test86.in>; cursor is at (955, 0)
+    <window object (unknown)>(0): displays buffer <buffer test86.in>; cursor is at (954, 0)
   <tabpage 1>(2): 1 windows, current is <window object (unknown)>
   Windows:
     <window object (unknown)>(0): displays buffer <buffer 0>; cursor is at (1, 0)
index c57d2a44c499dd9e24ef042c1f1d21c58071a931..b20a4f596d147a701826ceef723e1b042fb7f341 100644 (file)
@@ -728,6 +728,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    963,
 /**/
     962,
 /**/
index aeba15f85b9c9b60e90bd600ef82858d1f0ab921..a51ca947ca14af20bea8bbfe47e0276d260aa01a 100644 (file)
@@ -4058,6 +4058,25 @@ win_find_nr(winnr)
 }
 #endif
 
+#if (defined(FEAT_WINDOWS) && defined(FEAT_PYTHON)) || defined(PROTO)
+/*
+ * Find the tabpage for window "win".
+ */
+    tabpage_T *
+win_find_tabpage(win)
+    win_T      *win;
+{
+    win_T      *wp;
+    tabpage_T  *tp;
+
+    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
+       for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next)
+           if (wp == win)
+               return tp;
+    return NULL;
+}
+#endif
+
 #ifdef FEAT_VERTSPLIT
 /*
  * Move to window above or below "count" times.
@@ -6550,6 +6569,105 @@ restore_snapshot_rec(sn, fr)
 
 #endif
 
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Set "win" to be the curwin and "tp" to be the current tab page.
+ * restore_win() MUST be called to undo.
+ * No autocommands will be executed.
+ * Returns FAIL if switching to "win" failed.
+ */
+    int
+switch_win(save_curwin, save_curtab, win, tp)
+    win_T      **save_curwin;
+    tabpage_T  **save_curtab;
+    win_T      *win;
+    tabpage_T  *tp;
+{
+# ifdef FEAT_AUTOCMD
+    block_autocmds();
+# endif
+# ifdef FEAT_WINDOWS
+    *save_curwin = curwin;
+    if (tp != NULL)
+    {
+       *save_curtab = curtab;
+       goto_tabpage_tp(tp, FALSE, FALSE);
+    }
+    if (!win_valid(win))
+    {
+# ifdef FEAT_AUTOCMD
+       unblock_autocmds();
+# endif
+       return FAIL;
+    }
+    curwin = win;
+    curbuf = curwin->w_buffer;
+# endif
+    return OK;
+}
+
+/*
+ * Restore current tabpage and window saved by switch_win(), if still valid.
+ */
+    void
+restore_win(save_curwin, save_curtab)
+    win_T      *save_curwin;
+    tabpage_T  *save_curtab;
+{
+# ifdef FEAT_WINDOWS
+    if (save_curtab != NULL && valid_tabpage(save_curtab))
+       goto_tabpage_tp(save_curtab, FALSE, FALSE);
+    if (win_valid(save_curwin))
+    {
+       curwin = save_curwin;
+       curbuf = curwin->w_buffer;
+    }
+# endif
+# ifdef FEAT_AUTOCMD
+    unblock_autocmds();
+# endif
+}
+
+/*
+ * Make "buf" the current buffer.  restore_buffer() MUST be called to undo.
+ * No autocommands will be executed.  Use aucmd_prepbuf() if there are any.
+ */
+    void
+switch_buffer(save_curbuf, buf)
+    buf_T *buf;
+    buf_T **save_curbuf;
+{
+# ifdef FEAT_AUTOCMD
+    block_autocmds();
+# endif
+    *save_curbuf = curbuf;
+    --curbuf->b_nwindows;
+    curbuf = buf;
+    curwin->w_buffer = buf;
+    ++curbuf->b_nwindows;
+}
+
+/*
+ * Restore the current buffer after using switch_buffer().
+ */
+    void
+restore_buffer(save_curbuf)
+    buf_T *save_curbuf;
+{
+# ifdef FEAT_AUTOCMD
+    unblock_autocmds();
+# endif
+    /* Check for valid buffer, just in case. */
+    if (buf_valid(save_curbuf))
+    {
+       --curbuf->b_nwindows;
+       curwin->w_buffer = save_curbuf;
+       curbuf = save_curbuf;
+       ++curbuf->b_nwindows;
+    }
+}
+#endif
+
 #if (defined(FEAT_GUI) && defined(FEAT_VERTSPLIT)) || defined(PROTO)
 /*
  * Return TRUE if there is any vertically split window.