patch 7.4.709
Problem:    ":tabmove" does not work as documented.
Solution:   Make it work consistently.  Update documentation and add tests.
            (Hirohito Higashi)
diff --git a/runtime/doc/tabpage.txt b/runtime/doc/tabpage.txt
index 2d44fe2..46e0a8f 100644
--- a/runtime/doc/tabpage.txt
+++ b/runtime/doc/tabpage.txt
@@ -202,23 +202,29 @@
 		Move the current tab page to after tab page N.  Use zero to
 		make the current tab page the first one.  Without N the tab
 		page is made the last one. >
+		    :.tabmove	" do nothing
 		    :-tabmove	" move the tab page to the left
-		    :tabmove	" move the tab page to the right
-		    :.tabmove	" as above
-		    :+tabmove	" as above
+		    :+tabmove	" move the tab page to the right
 		    :0tabmove	" move the tab page to the beginning of the tab
 				" list
-		    :$tabmove	" move the tab page to the end of the tab list
-<
+		    :tabmove 0	" as above
+		    :tabmove	" move the tab page to the last
+		    :$tabmove	" as above
+		    :tabmove $	" as above
 
 :tabm[ove] +[N]
 :tabm[ove] -[N]
 		Move the current tab page N places to the right (with +) or to
-		the left (with -).
+		the left (with -). >
+		    :tabmove -	" move the tab page to the left
+		    :tabmove -1	" as above
+		    :tabmove +	" move the tab page to the right
+		    :tabmove +1	" as above
+
 
 Note that although it is possible to move a tab behind the N-th one by using
-:Ntabmove, it is impossible to move it by N places by using :+Ntabmove. For
-clarification what +N means in this context see |[range]|.
+:Ntabmove. And move it by N places by using :+Ntabmove. For clarification what
++N means in this context see |[range]|.
 
 
 LOOPING OVER TAB PAGES:
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index e46ea05..af63b6c 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -8145,7 +8145,7 @@
 ex_tabmove(eap)
     exarg_T	*eap;
 {
-    int tab_number = 9999;
+    int tab_number;
 
     if (eap->arg && *eap->arg != NUL)
     {
@@ -8166,19 +8166,38 @@
 	else
 	    p = eap->arg;
 
-	if (p == skipdigits(p))
+	if (relative == 0)
 	{
-	    /* No numbers as argument. */
-	    eap->errmsg = e_invarg;
-	    return;
+	    if (STRCMP(p, "$") == 0)
+		tab_number = LAST_TAB_NR;
+	    else if (p == skipdigits(p))
+	    {
+		/* No numbers as argument. */
+		eap->errmsg = e_invarg;
+		return;
+	    }
+	    else
+		tab_number = getdigits(&p);
 	}
-
-	tab_number = getdigits(&p);
-	if (relative != 0)
-	    tab_number = tab_number * relative + tabpage_index(curtab) - 1;;
+	else
+	{
+	    if (*p != NUL)
+		tab_number = getdigits(&p);
+	    else
+		tab_number = 1;
+	    tab_number = tab_number * relative + tabpage_index(curtab);
+	    if (relative == -1)
+		--tab_number;
+	}
     }
     else if (eap->addr_count != 0)
+    {
 	tab_number = eap->line2;
+	if (**eap->cmdlinep == '-')
+	    --tab_number;
+    }
+    else
+	tab_number = LAST_TAB_NR;
 
     tabpage_move(tab_number);
 }
diff --git a/src/testdir/test62.in b/src/testdir/test62.in
index c201fe7..c437f36 100644
--- a/src/testdir/test62.in
+++ b/src/testdir/test62.in
Binary files differ
diff --git a/src/testdir/test62.ok b/src/testdir/test62.ok
index e35b2b1..a0115bf 100644
--- a/src/testdir/test62.ok
+++ b/src/testdir/test62.ok
@@ -9,14 +9,21 @@
 tab drop 2: pass
 tab drop 3: pass
 1
-6
+5
+5
 4
-8
+5
+3
+7
+10
+1
+10
+1
 10
 1
 10
 4
-6
+5
 E474 caught.
 === tab split ===
 WinLeave
diff --git a/src/version.c b/src/version.c
index a803708..850f37c 100644
--- a/src/version.c
+++ b/src/version.c
@@ -742,6 +742,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    709,
+/**/
     708,
 /**/
     707,
diff --git a/src/window.c b/src/window.c
index 9521430..609ab3e 100644
--- a/src/window.c
+++ b/src/window.c
@@ -4120,18 +4120,27 @@
 }
 
 /*
- * Move the current tab page to before tab page "nr".
+ * Move the current tab page to after tab page "nr".
  */
     void
 tabpage_move(nr)
     int		nr;
 {
-    int		n = nr;
-    tabpage_T	*tp;
+    int		n = 1;
+    tabpage_T	*tp, *tp_dst;
 
     if (first_tabpage->tp_next == NULL)
 	return;
 
+    for (tp = first_tabpage; tp->tp_next != NULL && n < nr; tp = tp->tp_next)
+	++n;
+
+    if (tp == curtab || (nr > 0 && tp->tp_next != NULL
+						    && tp->tp_next == curtab))
+	return;
+
+    tp_dst = tp;
+
     /* Remove the current tab page from the list of tab pages. */
     if (curtab == first_tabpage)
 	first_tabpage = curtab->tp_next;
@@ -4146,17 +4155,15 @@
     }
 
     /* Re-insert it at the specified position. */
-    if (n <= 0)
+    if (nr <= 0)
     {
 	curtab->tp_next = first_tabpage;
 	first_tabpage = curtab;
     }
     else
     {
-	for (tp = first_tabpage; tp->tp_next != NULL && n > 1; tp = tp->tp_next)
-	    --n;
-	curtab->tp_next = tp->tp_next;
-	tp->tp_next = curtab;
+	curtab->tp_next = tp_dst->tp_next;
+	tp_dst->tp_next = curtab;
     }
 
     /* Need to redraw the tabline.  Tab page contents doesn't change. */