summaryrefslogtreecommitdiff
path: root/data/vim/patches/8.1.1335
diff options
context:
space:
mode:
Diffstat (limited to 'data/vim/patches/8.1.1335')
-rw-r--r--data/vim/patches/8.1.1335449
1 files changed, 449 insertions, 0 deletions
diff --git a/data/vim/patches/8.1.1335 b/data/vim/patches/8.1.1335
new file mode 100644
index 000000000..4ff489812
--- /dev/null
+++ b/data/vim/patches/8.1.1335
@@ -0,0 +1,449 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 8.1.1335
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 8.1.1335
+Problem: Listener callback is called after inserting text.
+Solution: Flush the changes before inserting or deleting a line. Store
+ changes per buffer.
+Files: src/change.c, src/proto/change.pro, src/memline.c,
+ src/structs.h, src/testdir/test_listener.vim
+
+
+*** ../vim-8.1.1334/src/change.c 2019-05-15 22:45:33.956067651 +0200
+--- src/change.c 2019-05-16 21:44:23.932078618 +0200
+***************
+*** 152,183 ****
+ }
+
+ #ifdef FEAT_EVAL
+- static list_T *recorded_changes = NULL;
+ static long next_listener_id = 0;
+
+ /*
+! * Record a change for listeners added with listener_add().
+ */
+! static void
+! may_record_change(
+! linenr_T lnum,
+! colnr_T col,
+! linenr_T lnume,
+! long xtra)
+ {
+! dict_T *dict;
+!
+! if (curbuf->b_listener == NULL)
+! return;
+!
+! // If the new change is going to change the line numbers in already listed
+! // changes, then flush.
+! if (recorded_changes != NULL && xtra != 0)
+ {
+ listitem_T *li;
+ linenr_T nr;
+
+! for (li = recorded_changes->lv_first; li != NULL; li = li->li_next)
+ {
+ nr = (linenr_T)dict_get_number(
+ li->li_tv.vval.v_dict, (char_u *)"lnum");
+--- 152,181 ----
+ }
+
+ #ifdef FEAT_EVAL
+ static long next_listener_id = 0;
+
+ /*
+! * Check if the change at "lnum" / "col" is above or overlaps with an existing
+! * changed. If above then flush changes and invoke listeners.
+! * If "merge" is TRUE do the merge.
+! * Returns TRUE if the change was merged.
+ */
+! static int
+! check_recorded_changes(
+! buf_T *buf,
+! linenr_T lnum,
+! colnr_T col,
+! linenr_T lnume,
+! long xtra,
+! int merge)
+ {
+! if (buf->b_recorded_changes != NULL && xtra != 0)
+ {
+ listitem_T *li;
+ linenr_T nr;
+
+! for (li = buf->b_recorded_changes->lv_first; li != NULL;
+! li = li->li_next)
+ {
+ nr = (linenr_T)dict_get_number(
+ li->li_tv.vval.v_dict, (char_u *)"lnum");
+***************
+*** 187,221 ****
+ && col + 1 == (colnr_T)dict_get_number(
+ li->li_tv.vval.v_dict, (char_u *)"col"))
+ {
+! dictitem_T *di;
+!
+! // Same start point and nothing is following, entries can
+! // be merged.
+! di = dict_find(li->li_tv.vval.v_dict, (char_u *)"end", -1);
+! nr = tv_get_number(&di->di_tv);
+! if (lnume > nr)
+! di->di_tv.vval.v_number = lnume;
+! di = dict_find(li->li_tv.vval.v_dict,
+ (char_u *)"added", -1);
+! di->di_tv.vval.v_number += xtra;
+! return;
+ }
+-
+- // the current change is going to make the line number in the
+- // older change invalid, flush now
+- invoke_listeners(curbuf);
+- break;
+ }
+ }
+ }
+
+! if (recorded_changes == NULL)
+ {
+! recorded_changes = list_alloc();
+! if (recorded_changes == NULL) // out of memory
+ return;
+! ++recorded_changes->lv_refcount;
+! recorded_changes->lv_lock = VAR_FIXED;
+ }
+
+ dict = dict_alloc();
+--- 185,248 ----
+ && col + 1 == (colnr_T)dict_get_number(
+ li->li_tv.vval.v_dict, (char_u *)"col"))
+ {
+! if (merge)
+! {
+! dictitem_T *di;
+!
+! // Same start point and nothing is following, entries
+! // can be merged.
+! di = dict_find(li->li_tv.vval.v_dict,
+! (char_u *)"end", -1);
+! nr = tv_get_number(&di->di_tv);
+! if (lnume > nr)
+! di->di_tv.vval.v_number = lnume;
+! di = dict_find(li->li_tv.vval.v_dict,
+ (char_u *)"added", -1);
+! di->di_tv.vval.v_number += xtra;
+! return TRUE;
+! }
+! }
+! else
+! {
+! // the current change is going to make the line number in
+! // the older change invalid, flush now
+! invoke_listeners(curbuf);
+! break;
+ }
+ }
+ }
+ }
++ return FALSE;
++ }
+
+! /*
+! * Record a change for listeners added with listener_add().
+! * Always for the current buffer.
+! */
+! static void
+! may_record_change(
+! linenr_T lnum,
+! colnr_T col,
+! linenr_T lnume,
+! long xtra)
+! {
+! dict_T *dict;
+!
+! if (curbuf->b_listener == NULL)
+! return;
+!
+! // If the new change is going to change the line numbers in already listed
+! // changes, then flush.
+! if (check_recorded_changes(curbuf, lnum, col, lnume, xtra, TRUE))
+! return;
+!
+! if (curbuf->b_recorded_changes == NULL)
+ {
+! curbuf->b_recorded_changes = list_alloc();
+! if (curbuf->b_recorded_changes == NULL) // out of memory
+ return;
+! ++curbuf->b_recorded_changes->lv_refcount;
+! curbuf->b_recorded_changes->lv_lock = VAR_FIXED;
+ }
+
+ dict = dict_alloc();
+***************
+*** 226,232 ****
+ dict_add_number(dict, "added", (varnumber_T)xtra);
+ dict_add_number(dict, "col", (varnumber_T)col + 1);
+
+! list_append_dict(recorded_changes, dict);
+ }
+
+ /*
+--- 253,259 ----
+ dict_add_number(dict, "added", (varnumber_T)xtra);
+ dict_add_number(dict, "col", (varnumber_T)col + 1);
+
+! list_append_dict(curbuf->b_recorded_changes, dict);
+ }
+
+ /*
+***************
+*** 317,322 ****
+--- 344,359 ----
+ }
+
+ /*
++ * Called before inserting a line above "lnum"/"lnum3" or deleting line "lnum"
++ * to "lnume".
++ */
++ void
++ may_invoke_listeners(buf_T *buf, linenr_T lnum, linenr_T lnume, int added)
++ {
++ check_recorded_changes(buf, lnum, 0, lnume, added, FALSE);
++ }
++
++ /*
+ * Called when a sequence of changes is done: invoke listeners added with
+ * listener_add().
+ */
+***************
+*** 332,338 ****
+ linenr_T end = 0;
+ linenr_T added = 0;
+
+! if (recorded_changes == NULL // nothing changed
+ || buf->b_listener == NULL) // no listeners
+ return;
+
+--- 369,375 ----
+ linenr_T end = 0;
+ linenr_T added = 0;
+
+! if (buf->b_recorded_changes == NULL // nothing changed
+ || buf->b_listener == NULL) // no listeners
+ return;
+
+***************
+*** 340,346 ****
+ argv[0].vval.v_number = buf->b_fnum; // a:bufnr
+
+
+! for (li = recorded_changes->lv_first; li != NULL; li = li->li_next)
+ {
+ varnumber_T lnum;
+
+--- 377,383 ----
+ argv[0].vval.v_number = buf->b_fnum; // a:bufnr
+
+
+! for (li = buf->b_recorded_changes->lv_first; li != NULL; li = li->li_next)
+ {
+ varnumber_T lnum;
+
+***************
+*** 360,366 ****
+ argv[3].vval.v_number = added;
+
+ argv[4].v_type = VAR_LIST;
+! argv[4].vval.v_list = recorded_changes;
+ ++textlock;
+
+ for (lnr = buf->b_listener; lnr != NULL; lnr = lnr->lr_next)
+--- 397,403 ----
+ argv[3].vval.v_number = added;
+
+ argv[4].v_type = VAR_LIST;
+! argv[4].vval.v_list = buf->b_recorded_changes;
+ ++textlock;
+
+ for (lnr = buf->b_listener; lnr != NULL; lnr = lnr->lr_next)
+***************
+*** 371,378 ****
+ }
+
+ --textlock;
+! list_unref(recorded_changes);
+! recorded_changes = NULL;
+ }
+ #endif
+
+--- 408,415 ----
+ }
+
+ --textlock;
+! list_unref(buf->b_recorded_changes);
+! buf->b_recorded_changes = NULL;
+ }
+ #endif
+
+*** ../vim-8.1.1334/src/proto/change.pro 2019-05-14 21:20:32.597441034 +0200
+--- src/proto/change.pro 2019-05-16 21:43:11.104455404 +0200
+***************
+*** 5,10 ****
+--- 5,11 ----
+ void f_listener_add(typval_T *argvars, typval_T *rettv);
+ void f_listener_flush(typval_T *argvars, typval_T *rettv);
+ void f_listener_remove(typval_T *argvars, typval_T *rettv);
++ void may_invoke_listeners(buf_T *buf, linenr_T lnum, linenr_T lnume, int added);
+ void invoke_listeners(buf_T *buf);
+ void changed_bytes(linenr_T lnum, colnr_T col);
+ void inserted_bytes(linenr_T lnum, colnr_T col, int added);
+*** ../vim-8.1.1334/src/memline.c 2019-05-11 17:03:55.170019762 +0200
+--- src/memline.c 2019-05-16 22:10:02.903781871 +0200
+***************
+*** 2790,2795 ****
+--- 2790,2801 ----
+ if (len == 0)
+ len = (colnr_T)STRLEN(line) + 1; // space needed for the text
+
++ #ifdef FEAT_EVAL
++ // When inserting above recorded changes: flush the changes before changing
++ // the text.
++ may_invoke_listeners(buf, lnum + 1, lnum + 1, 1);
++ #endif
++
+ #ifdef FEAT_TEXT_PROP
+ if (curbuf->b_has_textprop && lnum > 0)
+ // Add text properties that continue from the previous line.
+***************
+*** 3526,3531 ****
+--- 3532,3542 ----
+ if (lnum < 1 || lnum > buf->b_ml.ml_line_count)
+ return FAIL;
+
++ #ifdef FEAT_EVAL
++ // When inserting above recorded changes: flush the changes before changing
++ // the text.
++ may_invoke_listeners(buf, lnum, lnum + 1, -1);
++ #endif
+ if (lowest_marked && lowest_marked > lnum)
+ lowest_marked--;
+
+*** ../vim-8.1.1334/src/structs.h 2019-05-11 19:14:11.585314006 +0200
+--- src/structs.h 2019-05-16 21:35:50.642762505 +0200
+***************
+*** 2439,2444 ****
+--- 2439,2445 ----
+ dict_T *b_vars; /* internal variables, local to buffer */
+
+ listener_T *b_listener;
++ list_T *b_recorded_changes;
+ #endif
+ #ifdef FEAT_TEXT_PROP
+ int b_has_textprop; // TRUE when text props were added
+*** ../vim-8.1.1334/src/testdir/test_listener.vim 2019-05-14 21:20:32.597441034 +0200
+--- src/testdir/test_listener.vim 2019-05-16 22:09:20.164017981 +0200
+***************
+*** 1,6 ****
+ " tests for listener_add() and listener_remove()
+
+! func s:StoreList(l)
+ let s:list = a:l
+ endfunc
+
+--- 1,8 ----
+ " tests for listener_add() and listener_remove()
+
+! func s:StoreList(s, l)
+! let s:start = a:s
+! let s:text = getline(a:s)
+ let s:list = a:l
+ endfunc
+
+***************
+*** 17,23 ****
+ new
+ call setline(1, ['one', 'two'])
+ let s:list = []
+! let id = listener_add({b, s, e, a, l -> s:StoreList(l)})
+ call setline(1, 'one one')
+ call listener_flush()
+ call assert_equal([{'lnum': 1, 'end': 2, 'col': 1, 'added': 0}], s:list)
+--- 19,25 ----
+ new
+ call setline(1, ['one', 'two'])
+ let s:list = []
+! let id = listener_add({b, s, e, a, l -> s:StoreList(s, l)})
+ call setline(1, 'one one')
+ call listener_flush()
+ call assert_equal([{'lnum': 1, 'end': 2, 'col': 1, 'added': 0}], s:list)
+***************
+*** 66,73 ****
+--- 68,77 ----
+ " an insert just above a previous change that was the last one gets merged
+ call setline(1, ['one one', 'two'])
+ call listener_flush()
++ let s:list = []
+ call setline(2, 'something')
+ call append(1, 'two two')
++ call assert_equal([], s:list)
+ call listener_flush()
+ call assert_equal([{'lnum': 2, 'end': 3, 'col': 1, 'added': 1}], s:list)
+
+***************
+*** 77,84 ****
+--- 81,112 ----
+ call setline(2, 'something')
+ call append(0, 'two two')
+ call assert_equal([{'lnum': 2, 'end': 3, 'col': 1, 'added': 0}], s:list)
++ call assert_equal('something', s:text)
+ call listener_flush()
+ call assert_equal([{'lnum': 1, 'end': 1, 'col': 1, 'added': 1}], s:list)
++ call assert_equal('two two', s:text)
++
++ " a delete at a previous change that was the last one gets merged
++ call setline(1, ['one one', 'two'])
++ call listener_flush()
++ let s:list = []
++ call setline(2, 'something')
++ 2del
++ call assert_equal([], s:list)
++ call listener_flush()
++ call assert_equal([{'lnum': 2, 'end': 3, 'col': 1, 'added': -1}], s:list)
++
++ " a delete above a previous change causes a flush
++ call setline(1, ['one one', 'two'])
++ call listener_flush()
++ call setline(2, 'another')
++ 1del
++ call assert_equal([{'lnum': 2, 'end': 3, 'col': 1, 'added': 0}], s:list)
++ call assert_equal(2, s:start)
++ call assert_equal('another', s:text)
++ call listener_flush()
++ call assert_equal([{'lnum': 1, 'end': 2, 'col': 1, 'added': -1}], s:list)
++ call assert_equal('another', s:text)
+
+ " the "o" command first adds an empty line and then changes it
+ %del
+*** ../vim-8.1.1334/src/version.c 2019-05-16 20:29:40.799834279 +0200
+--- src/version.c 2019-05-16 22:10:40.187576723 +0200
+***************
+*** 769,770 ****
+--- 769,772 ----
+ { /* Add new patch number below this line */
++ /**/
++ 1335,
+ /**/
+
+--
+Hacker: Someone skilled in computer programming (good guy).
+Cracker: A hacker that uses his skills to crack software (bad guy).
+
+ /// 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 ///