To: vim_dev@googlegroups.com Subject: Patch 7.4a.043 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4a.043 Problem: More ml_get errors when adding or deleting lines from Python. (Vlad Irnov) Solution: Switch to a window with the buffer when possible. Files: src/if_py_both.h *** ../vim-7.4a.042/src/if_py_both.h 2013-07-17 17:15:20.000000000 +0200 --- src/if_py_both.h 2013-07-24 17:09:19.000000000 +0200 *************** *** 3695,3700 **** --- 3695,3733 ---- } /* + * Find a window that contains "buf" and switch to it. + * If there is no such window, use the current window and change "curbuf". + * Caller must initialize save_curbuf to NULL. + * restore_win_for_buf() MUST be called later! + */ + static void + switch_to_win_for_buf( + buf_T *buf, + win_T **save_curwinp, + tabpage_T **save_curtabp, + buf_T **save_curbufp) + { + win_T *wp; + tabpage_T *tp; + + if (find_win_for_buf(buf, &wp, &tp) == FAIL + || switch_win(save_curwinp, save_curtabp, wp, tp, TRUE) == FAIL) + switch_buffer(save_curbufp, buf); + } + + static void + restore_win_for_buf( + win_T *save_curwin, + tabpage_T *save_curtab, + buf_T *save_curbuf) + { + if (save_curbuf == NULL) + restore_win(save_curwin, save_curtab, TRUE); + else + restore_buffer(save_curbuf); + } + + /* * Replace a line in the specified buffer. The line number is * in Vim format (1-based). The replacement line is given as * a Python string object. The object is checked for validity *************** *** 3706,3711 **** --- 3739,3748 ---- static int SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change) { + buf_T *save_curbuf = NULL; + win_T *save_curwin = NULL; + tabpage_T *save_curtab = NULL; + /* First of all, we check the type of the supplied Python object. * There are three cases: * 1. NULL, or None - this is a deletion. *************** *** 3714,3723 **** */ if (line == Py_None || line == NULL) { - buf_T *savebuf; - PyErr_Clear(); ! switch_buffer(&savebuf, buf); VimTryStart(); --- 3751,3758 ---- */ if (line == Py_None || line == NULL) { PyErr_Clear(); ! switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf); VimTryStart(); *************** *** 3727,3738 **** RAISE_DELETE_LINE_FAIL; else { ! if (buf == savebuf) py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1); ! deleted_lines_mark((linenr_T)n, 1L); } ! restore_buffer(savebuf); if (VimTryEnd()) return FAIL; --- 3762,3776 ---- RAISE_DELETE_LINE_FAIL; else { ! if (buf == curbuf) py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1); ! 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. */ ! deleted_lines_mark((linenr_T)n, 1L); } ! restore_win_for_buf(save_curwin, save_curtab, save_curbuf); if (VimTryEnd()) return FAIL; *************** *** 3745,3751 **** else if (PyBytes_Check(line) || PyUnicode_Check(line)) { char *save = StringToLine(line); - buf_T *savebuf; if (save == NULL) return FAIL; --- 3783,3788 ---- *************** *** 3754,3760 **** /* We do not need to free "save" if ml_replace() consumes it. */ PyErr_Clear(); ! switch_buffer(&savebuf, buf); if (u_savesub((linenr_T)n) == FAIL) { --- 3791,3797 ---- /* We do not need to free "save" if ml_replace() consumes it. */ PyErr_Clear(); ! switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf); if (u_savesub((linenr_T)n) == FAIL) { *************** *** 3769,3778 **** else changed_bytes((linenr_T)n, 0); ! restore_buffer(savebuf); /* Check that the cursor is not beyond the end of the line now. */ ! if (buf == savebuf) check_cursor_col(); if (VimTryEnd()) --- 3806,3815 ---- else changed_bytes((linenr_T)n, 0); ! restore_win_for_buf(save_curwin, save_curtab, save_curbuf); /* Check that the cursor is not beyond the end of the line now. */ ! if (buf == curbuf) check_cursor_col(); if (VimTryEnd()) *************** *** 3806,3811 **** --- 3843,3852 ---- PyObject *list, PyInt *len_change) { + buf_T *save_curbuf = NULL; + win_T *save_curwin = NULL; + tabpage_T *save_curtab = NULL; + /* First of all, we check the type of the supplied Python object. * There are three cases: * 1. NULL, or None - this is a deletion. *************** *** 3816,3826 **** { PyInt i; PyInt n = (int)(hi - lo); - buf_T *savebuf; PyErr_Clear(); VimTryStart(); ! switch_buffer(&savebuf, buf); if (u_savedel((linenr_T)lo, (long)n) == FAIL) RAISE_UNDO_FAIL; --- 3857,3866 ---- { PyInt i; PyInt n = (int)(hi - lo); PyErr_Clear(); VimTryStart(); ! switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf); if (u_savedel((linenr_T)lo, (long)n) == FAIL) RAISE_UNDO_FAIL; *************** *** 3834,3845 **** break; } } ! if (buf == savebuf) py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n); ! deleted_lines_mark((linenr_T)lo, (long)i); } ! restore_buffer(savebuf); if (VimTryEnd()) return FAIL; --- 3874,3888 ---- break; } } ! if (buf == curbuf) py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n); ! 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. */ ! deleted_lines_mark((linenr_T)lo, (long)i); } ! restore_win_for_buf(save_curwin, save_curtab, save_curbuf); if (VimTryEnd()) return FAIL; *************** *** 3856,3862 **** PyInt old_len = hi - lo; PyInt extra = 0; /* lines added to text, can be negative */ char **array; - buf_T *savebuf; if (new_len == 0) /* avoid allocating zero bytes */ array = NULL; --- 3899,3904 ---- *************** *** 3888,3894 **** PyErr_Clear(); /* START of region without "return". Must call restore_buffer()! */ ! switch_buffer(&savebuf, buf); if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL) RAISE_UNDO_FAIL; --- 3930,3936 ---- PyErr_Clear(); /* START of region without "return". Must call restore_buffer()! */ ! switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf); if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL) RAISE_UNDO_FAIL; *************** *** 3960,3975 **** /* Adjust marks. Invalidate any which lie in the * changed range, and move any in the remainder of the buffer. ! */ ! mark_adjust((linenr_T)lo, (linenr_T)(hi - 1), (long)MAXLNUM, (long)extra); changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra); ! if (buf == savebuf) py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra); /* END of region without "return". */ ! restore_buffer(savebuf); if (VimTryEnd()) return FAIL; --- 4002,4019 ---- /* Adjust marks. Invalidate any which lie in the * changed range, and move any in the remainder of the buffer. ! * Only adjust marks if we managed to switch to a window that holds ! * the buffer, otherwise line numbers will be invalid. */ ! if (save_curbuf == NULL) ! mark_adjust((linenr_T)lo, (linenr_T)(hi - 1), (long)MAXLNUM, (long)extra); changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra); ! if (buf == curbuf) py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra); /* END of region without "return". */ ! restore_win_for_buf(save_curwin, save_curtab, save_curbuf); if (VimTryEnd()) return FAIL; *************** *** 3998,4006 **** 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. --- 4042,4048 ---- *************** *** 4015,4024 **** PyErr_Clear(); VimTryStart(); ! 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; --- 4057,4063 ---- PyErr_Clear(); VimTryStart(); ! switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf); if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL) RAISE_UNDO_FAIL; *************** *** 4030,4039 **** appended_lines_mark((linenr_T)n, 1L); vim_free(str); ! if (save_curbuf == NULL) ! restore_win(save_curwin, save_curtab, TRUE); ! else ! restore_buffer(save_curbuf); update_screen(VALID); if (VimTryEnd()) --- 4069,4075 ---- appended_lines_mark((linenr_T)n, 1L); vim_free(str); ! restore_win_for_buf(save_curwin, save_curtab, save_curbuf); update_screen(VALID); if (VimTryEnd()) *************** *** 4073,4082 **** PyErr_Clear(); VimTryStart(); ! 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; --- 4109,4115 ---- PyErr_Clear(); VimTryStart(); ! switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf); if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL) RAISE_UNDO_FAIL; *************** *** 4097,4114 **** } vim_free(array[i]); } ! if (i > 0) appended_lines_mark((linenr_T)n, (long)i); } /* Free the array of lines. All of its contents have now * been freed. */ PyMem_Free(array); - if (save_curbuf == NULL) - restore_win(save_curwin, save_curtab, TRUE); - else - restore_buffer(save_curbuf); update_screen(VALID); if (VimTryEnd()) --- 4130,4146 ---- } vim_free(array[i]); } ! if (i > 0 && 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, (long)i); } /* Free the array of lines. All of its contents have now * been freed. */ PyMem_Free(array); + restore_win_for_buf(save_curwin, save_curtab, save_curbuf); update_screen(VALID); if (VimTryEnd()) *** ../vim-7.4a.042/src/version.c 2013-07-24 16:02:32.000000000 +0200 --- src/version.c 2013-07-24 17:05:23.000000000 +0200 *************** *** 729,730 **** --- 729,732 ---- { /* Add new patch number below this line */ + /**/ + 43, /**/ -- hundred-and-one symptoms of being an internet addict: 24. You realize there is not a sound in the house and you have no idea where your children are. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///