changeset 8534:485d4d8a97f6 v7.4.1557

commit https://github.com/vim/vim/commit/86edef664efccbfe685906c854b9cdd04e56f2d5 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Mar 13 18:07:30 2016 +0100 patch 7.4.1557 Problem: Windows cannot be identified. Solution: Add a unique window number to each window and functions to use it.
author Christian Brabandt <cb@256bit.org>
date Sun, 13 Mar 2016 18:15:05 +0100
parents 12c443cb2f05
children 6ec2cb295acd
files runtime/doc/eval.txt src/eval.c src/proto/eval.pro src/proto/window.pro src/structs.h src/testdir/Make_all.mak src/testdir/test_window_id.vim src/version.c src/window.c
diffstat 9 files changed, 270 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt*	For Vim version 7.4.  Last change: 2016 Mar 12
+*eval.txt*	For Vim version 7.4.  Last change: 2016 Mar 13
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -764,13 +764,23 @@ expressions are referring to the same |L
 of a |List| is different from the original |List|.  When using "is" without
 a |List| or a |Dictionary| it is equivalent to using "equal", using "isnot"
 equivalent to using "not equal".  Except that a different type means the
-values are different: "4 == '4'" is true, "4 is '4'" is false and "0 is []" is
-false and not an error. "is#"/"isnot#" and "is?"/"isnot?" can be used to match
-and ignore case.
+values are different: >
+	echo 4 == '4'
+	1
+	echo 4 is '4'
+	0
+	echo 0 is []
+	0
+"is#"/"isnot#" and "is?"/"isnot?" can be used to match and ignore case.
 
 When comparing a String with a Number, the String is converted to a Number,
-and the comparison is done on Numbers.	This means that "0 == 'x'" is TRUE,
-because 'x' converted to a Number is zero.
+and the comparison is done on Numbers.	This means that: >
+	echo 0 == 'x'
+	1
+because 'x' converted to a Number is zero.  However: >
+	echo [0] == ['x']
+	0
+Inside a List or Dictionary this conversion is not used.
 
 When comparing two Strings, this is done with strcmp() or stricmp().  This
 results in the mathematical difference (comparing byte values), not
@@ -2139,6 +2149,10 @@ values( {dict})			List	values in {dict}
 virtcol( {expr})		Number	screen column of cursor or mark
 visualmode( [expr])		String	last visual mode used
 wildmenumode()			Number	whether 'wildmenu' mode is active
+win_getid( [{win} [, {tab}]]) 	Number	get window ID for {win} in {tab}
+win_gotoid( {expr})		Number	go to window with ID {expr}
+win_id2tabwin( {expr})		List	get tab and window nr from window ID
+win_id2win( {expr})		Number	get window nr from window ID
 winbufnr( {nr})			Number	buffer number of window {nr}
 wincol()			Number	window column of the cursor
 winheight( {nr})		Number	height of window {nr}
@@ -7162,6 +7176,29 @@ wildmenumode()					*wildmenumode()*
 		(Note, this needs the 'wildcharm' option set appropriately).
 
 
+win_getid([{win} [, {tab}]])				*win_getid()*
+		Get the window ID for the specified window.
+		When {win} is missing use the current window.
+		With {win} this is the window number.  The top window has
+		number 1.
+		Without {tab} use the current tab, otherwise the tab with
+		number {tab}.  The first tab has number one.
+		Return zero if the window cannot be found.
+
+win_gotoid({expr})					*win_gotoid()*
+		Go to window with ID {expr}.  This may also change the current
+		tabpage.
+		Return 1 if successful, 0 if the window cannot be found.
+
+win_id2tabwin({expr}					*win_id2tabwin()*
+		Return a list with the tab number and window number of window
+		with ID {expr}: [tabnr, winnr].
+		Return [0, 0] if the window cannot be found.
+
+win_id2win({expr})					*win_id2win()*
+		Return the window number of window with ID {expr}.
+		Return 0 if the window cannot be found in the current tabpage.
+
 							*winbufnr()*
 winbufnr({nr})	The result is a Number, which is the number of the buffer
 		associated with window {nr}.  When {nr} is zero, the number of
--- a/src/eval.c
+++ b/src/eval.c
@@ -434,7 +434,6 @@ static int dict_equal(dict_T *d1, dict_T
 static int tv_equal(typval_T *tv1, typval_T *tv2, int ic, int recursive);
 static long list_find_nr(list_T *l, long idx, int *errorp);
 static long list_idx_of_item(list_T *l, listitem_T *item);
-static int list_append_number(list_T *l, varnumber_T n);
 static int list_extend(list_T	*l1, list_T *l2, listitem_T *bef);
 static int list_concat(list_T *l1, list_T *l2, typval_T *tv);
 static list_T *list_copy(list_T *orig, int deep, int copyID);
@@ -808,6 +807,10 @@ static void f_values(typval_T *argvars, 
 static void f_virtcol(typval_T *argvars, typval_T *rettv);
 static void f_visualmode(typval_T *argvars, typval_T *rettv);
 static void f_wildmenumode(typval_T *argvars, typval_T *rettv);
+static void f_win_getid(typval_T *argvars, typval_T *rettv);
+static void f_win_gotoid(typval_T *argvars, typval_T *rettv);
+static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv);
+static void f_win_id2win(typval_T *argvars, typval_T *rettv);
 static void f_winbufnr(typval_T *argvars, typval_T *rettv);
 static void f_wincol(typval_T *argvars, typval_T *rettv);
 static void f_winheight(typval_T *argvars, typval_T *rettv);
@@ -6469,7 +6472,7 @@ list_append_string(list_T *l, char_u *st
  * Append "n" to list "l".
  * Returns FAIL when out of memory.
  */
-    static int
+    int
 list_append_number(list_T *l, varnumber_T n)
 {
     listitem_T	*li;
@@ -8385,6 +8388,10 @@ static struct fst
     {"virtcol",		1, 1, f_virtcol},
     {"visualmode",	0, 1, f_visualmode},
     {"wildmenumode",	0, 0, f_wildmenumode},
+    {"win_getid",	0, 2, f_win_getid},
+    {"win_gotoid",	1, 1, f_win_gotoid},
+    {"win_id2tabwin",	1, 1, f_win_id2tabwin},
+    {"win_id2win",	1, 1, f_win_id2win},
     {"winbufnr",	1, 1, f_winbufnr},
     {"wincol",		0, 0, f_wincol},
     {"winheight",	1, 1, f_winheight},
@@ -12662,6 +12669,43 @@ f_getwinposx(typval_T *argvars UNUSED, t
 }
 
 /*
+ * "win_getid()" function
+ */
+    static void
+f_win_getid(typval_T *argvars, typval_T *rettv)
+{
+    rettv->vval.v_number = win_getid(argvars);
+}
+
+/*
+ * "win_gotoid()" function
+ */
+    static void
+f_win_gotoid(typval_T *argvars, typval_T *rettv)
+{
+    rettv->vval.v_number = win_gotoid(argvars);
+}
+
+/*
+ * "win_id2tabwin()" function
+ */
+    static void
+f_win_id2tabwin(typval_T *argvars, typval_T *rettv)
+{
+    if (rettv_list_alloc(rettv) != FAIL)
+	win_id2tabwin(argvars, rettv->vval.v_list);
+}
+
+/*
+ * "win_id2win()" function
+ */
+    static void
+f_win_id2win(typval_T *argvars, typval_T *rettv)
+{
+    rettv->vval.v_number = win_id2win(argvars);
+}
+
+/*
  * "getwinposy()" function
  */
     static void
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -59,6 +59,7 @@ void list_append(list_T *l, listitem_T *
 int list_append_tv(list_T *l, typval_T *tv);
 int list_append_dict(list_T *list, dict_T *dict);
 int list_append_string(list_T *l, char_u *str, int len);
+int list_append_number(list_T *l, varnumber_T n);
 int list_insert_tv(list_T *l, typval_T *tv, listitem_T *item);
 void list_insert(list_T *l, listitem_T *ni, listitem_T *item);
 void vimlist_remove(list_T *l, listitem_T *item, listitem_T *item2);
--- a/src/proto/window.pro
+++ b/src/proto/window.pro
@@ -83,4 +83,8 @@ void clear_matches(win_T *wp);
 matchitem_T *get_match(win_T *wp, int id);
 int get_win_number(win_T *wp, win_T *first_win);
 int get_tab_number(tabpage_T *tp);
+int win_getid(typval_T *argvars);
+int win_gotoid(typval_T *argvars);
+void win_id2tabwin(typval_T *argvars, list_T *list);
+int win_id2win(typval_T *argvars);
 /* vim: set ft=c : */
--- a/src/structs.h
+++ b/src/structs.h
@@ -2273,6 +2273,8 @@ struct matchitem
  */
 struct window_S
 {
+    int		w_id;		    /* unique window ID */
+
     buf_T	*w_buffer;	    /* buffer we are a window into (used
 				       often, keep it the first item!) */
 
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -186,6 +186,7 @@ NEW_TESTS = test_arglist.res \
 	    test_viminfo.res \
 	    test_viml.res \
 	    test_visual.res \
+	    test_window_id.res \
 	    test_alot.res
 
 
new file mode 100644
--- /dev/null
+++ b/src/testdir/test_window_id.vim
@@ -0,0 +1,71 @@
+" Test using the window ID.
+
+func Test_win_getid()
+  edit one
+  let id1 = win_getid()
+  split two
+  let id2 = win_getid()
+  split three
+  let id3 = win_getid()
+  tabnew
+  edit four
+  let id4 = win_getid()
+  split five
+  let id5 = win_getid()
+  tabnext
+
+  wincmd w
+  call assert_equal("two", expand("%"))
+  call assert_equal(id2, win_getid())
+  let nr2 = winnr()
+  wincmd w
+  call assert_equal("one", expand("%"))
+  call assert_equal(id1, win_getid())
+  let nr1 = winnr()
+  wincmd w
+  call assert_equal("three", expand("%"))
+  call assert_equal(id3, win_getid())
+  let nr3 = winnr()
+  tabnext
+  call assert_equal("five", expand("%"))
+  call assert_equal(id5, win_getid())
+  let nr5 = winnr()
+  wincmd w
+  call assert_equal("four", expand("%"))
+  call assert_equal(id4, win_getid())
+  let nr4 = winnr()
+  tabnext
+
+  exe nr1 . "wincmd w"
+  call assert_equal(id1, win_getid())
+  exe nr2 . "wincmd w"
+  call assert_equal(id2, win_getid())
+  exe nr3 . "wincmd w"
+  call assert_equal(id3, win_getid())
+  tabnext
+  exe nr4 . "wincmd w"
+  call assert_equal(id4, win_getid())
+  exe nr5 . "wincmd w"
+  call assert_equal(id5, win_getid())
+
+  call win_gotoid(id2)
+  call assert_equal("two", expand("%"))
+  call win_gotoid(id4)
+  call assert_equal("four", expand("%"))
+  call win_gotoid(id1)
+  call assert_equal("one", expand("%"))
+  call win_gotoid(id5)
+  call assert_equal("five", expand("%"))
+
+  call assert_equal(0, win_id2win(9999))
+  call assert_equal(nr5, win_id2win(id5))
+  call assert_equal(0, win_id2win(id1))
+  tabnext
+  call assert_equal(nr1, win_id2win(id1))
+
+  call assert_equal([0, 0], win_id2tabwin(9999))
+  call assert_equal([1, nr2], win_id2tabwin(id2))
+  call assert_equal([2, nr4], win_id2tabwin(id4))
+
+  only!
+endfunc
--- a/src/version.c
+++ b/src/version.c
@@ -744,6 +744,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1557,
+/**/
     1556,
 /**/
     1555,
--- a/src/window.c
+++ b/src/window.c
@@ -4541,6 +4541,8 @@ buf_jump_open_tab(buf_T *buf)
 }
 #endif
 
+static int last_win_id = 0;
+
 /*
  * Allocate a window structure and link it in the window list when "hidden" is
  * FALSE.
@@ -4563,6 +4565,8 @@ win_alloc(win_T *after UNUSED, int hidde
 	return NULL;
     }
 
+    new_wp->w_id = ++last_win_id;
+
 #ifdef FEAT_EVAL
     /* init w: variables */
     new_wp->w_vars = dict_alloc();
@@ -7198,3 +7202,99 @@ frame_check_width(frame_T *topfrp, int w
 }
 #endif
 
+#if defined(FEAT_EVAL) || defined(PROTO)
+    int
+win_getid(typval_T *argvars)
+{
+    int	    winnr;
+    win_T   *wp;
+
+    if (argvars[0].v_type == VAR_UNKNOWN)
+	return curwin->w_id;
+    winnr = get_tv_number(&argvars[0]);
+    if (winnr > 0)
+    {
+	if (argvars[1].v_type == VAR_UNKNOWN)
+	    wp = firstwin;
+	else
+	{
+	    tabpage_T	*tp;
+	    int		tabnr = get_tv_number(&argvars[1]);
+
+	    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
+		if (--tabnr == 0)
+		    break;
+	    if (tp == NULL)
+		return -1;
+	    wp = tp->tp_firstwin;
+	}
+	for ( ; wp != NULL; wp = wp->w_next)
+	    if (--winnr == 0)
+		return wp->w_id;
+    }
+    return 0;
+}
+
+    int
+win_gotoid(typval_T *argvars)
+{
+    win_T	*wp;
+    tabpage_T   *tp;
+    int		id = get_tv_number(&argvars[0]);
+
+    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
+	for (wp = tp == curtab ? firstwin : tp->tp_firstwin;
+						  wp != NULL; wp = wp->w_next)
+	    if (wp->w_id == id)
+	    {
+		goto_tabpage_win(tp, wp);
+		return 1;
+	    }
+    return 0;
+}
+
+    void
+win_id2tabwin(typval_T *argvars, list_T *list)
+{
+    win_T	*wp;
+    tabpage_T   *tp;
+    int		winnr = 1;
+    int		tabnr = 1;
+    int		id = get_tv_number(&argvars[0]);
+
+    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
+    {
+	for (wp = tp == curtab ? firstwin : tp->tp_firstwin;
+						  wp != NULL; wp = wp->w_next)
+	{
+	    if (wp->w_id == id)
+	    {
+		list_append_number(list, tabnr);
+		list_append_number(list, winnr);
+		return;
+	    }
+	    ++winnr;
+	}
+	++tabnr;
+	winnr = 1;
+    }
+    list_append_number(list, 0);
+    list_append_number(list, 0);
+}
+
+    int
+win_id2win(typval_T *argvars)
+{
+    win_T   *wp;
+    int	    nr = 1;
+    int	    id = get_tv_number(&argvars[0]);
+
+    for (wp = firstwin; wp != NULL; wp = wp->w_next)
+    {
+	if (wp->w_id == id)
+	    return nr;
+	++nr;
+    }
+    return 0;
+}
+#endif