patch 9.0.0342: ":wincmd =" equalizes in two directions

Problem:    ":wincmd =" equalizes in two directions.
Solution:   Make ":vertical wincmd =" equalize vertically only and
            ":horizontal wincmd =" equalize horizontally only.
diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt
index 13f648f..32ec102 100644
--- a/runtime/doc/windows.txt
+++ b/runtime/doc/windows.txt
@@ -256,9 +256,16 @@
 						*:vert* *:vertical*
 :vert[ical] {cmd}
 		Execute {cmd}.  If it contains a command that splits a window,
-		it will be split vertically.
+		it will be split vertically.  For `vertical wincmd =` windows
+		will be equialized only vertically.
 		Doesn't work for |:execute| and |:normal|.
 
+						*:hor* *:horizontal*
+:hor[izontal] {cmd}
+		Execute {cmd}.  Currently only makes a difference for
+		`horizontal wincmd =`, which will equal windows only
+		horizontally.
+
 :lefta[bove] {cmd}				*:lefta* *:leftabove*
 :abo[veleft] {cmd}				*:abo* *:aboveleft*
 		Execute {cmd}.  If it contains a command that splits a window,
@@ -553,6 +560,10 @@
 		'winheight' and 'winwidth' for the current window.
 		Windows with 'winfixheight' set keep their height and windows
 		with 'winfixwidth' set keep their width.
+		To equalize only vertically (make window equally high) use
+		`vertical wincmd =`
+		To equalize only horizontally (make window equally wide) use
+		`horizontal wincmd =`
 
 :res[ize] -N					*:res* *:resize* *CTRL-W_-*
 CTRL-W -	Decrease current window height by N (default 1).
diff --git a/src/ex_cmdidxs.h b/src/ex_cmdidxs.h
index fe5ca9b..065bf05 100644
--- a/src/ex_cmdidxs.h
+++ b/src/ex_cmdidxs.h
@@ -13,24 +13,24 @@
   /* f */ 166,
   /* g */ 183,
   /* h */ 189,
-  /* i */ 198,
-  /* j */ 218,
-  /* k */ 220,
-  /* l */ 225,
-  /* m */ 288,
-  /* n */ 306,
-  /* o */ 326,
-  /* p */ 338,
-  /* q */ 377,
-  /* r */ 380,
-  /* s */ 400,
-  /* t */ 470,
-  /* u */ 516,
-  /* v */ 527,
-  /* w */ 548,
-  /* x */ 562,
-  /* y */ 572,
-  /* z */ 573
+  /* i */ 199,
+  /* j */ 219,
+  /* k */ 221,
+  /* l */ 226,
+  /* m */ 289,
+  /* n */ 307,
+  /* o */ 327,
+  /* p */ 339,
+  /* q */ 378,
+  /* r */ 381,
+  /* s */ 401,
+  /* t */ 471,
+  /* u */ 517,
+  /* v */ 528,
+  /* w */ 549,
+  /* x */ 563,
+  /* y */ 573,
+  /* z */ 574
 };
 
 /*
@@ -48,7 +48,7 @@
   /* e */ {  1,  0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  9, 11, 12,  0,  0,  0,  0,  0,  0,  0, 23,  0, 24,  0,  0 },
   /* f */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 10,  0,  0,  0,  0,  0, 16,  0,  0,  0,  0,  0 },
   /* g */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  2,  0,  0,  4,  5,  0,  0,  0,  0 },
-  /* h */ {  5,  0,  0,  0,  0,  0,  0,  0,  6,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
+  /* h */ {  5,  0,  0,  0,  0,  0,  0,  0,  6,  0,  0,  0,  0,  0,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
   /* i */ {  1,  0,  0,  0,  0,  3,  0,  0,  0,  4,  0,  5,  6,  0,  0,  0,  0,  0, 15,  0, 17,  0,  0,  0,  0,  0 },
   /* j */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0 },
   /* k */ {  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
@@ -69,4 +69,4 @@
   /* z */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }
 };
 
-static const int command_count = 590;
+static const int command_count = 591;
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index 3ebbf23..8da0da1 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -707,6 +707,9 @@
 EXCMD(CMD_history,	"history",	ex_history,
 	EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
 	ADDR_NONE),
+EXCMD(CMD_horizontal,	"horizontal",	ex_wrongmodifier,
+	EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM,
+	ADDR_NONE),
 EXCMD(CMD_insert,	"insert",	ex_append,
 	EX_BANG|EX_RANGE|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY,
 	ADDR_LINES),
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 0d52f58..681ab2c 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -2987,8 +2987,13 @@
 			    continue;
 			}
 
+	    case 'h':	if (checkforcmd_noparen(&eap->cmd, "horizontal", 3))
+			{
+			    cmod->cmod_split |= WSP_HOR;
+			    continue;
+			}
 			// ":hide" and ":hide | cmd" are not modifiers
-	    case 'h':	if (p != eap->cmd || !checkforcmd_noparen(&p, "hide", 3)
+			if (p != eap->cmd || !checkforcmd_noparen(&p, "hide", 3)
 					       || *p == NUL || ends_excmd(*p))
 			    break;
 			eap->cmd = p;
diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim
index 04a5d10..bea612f 100644
--- a/src/testdir/test_window_cmd.vim
+++ b/src/testdir/test_window_cmd.vim
@@ -367,6 +367,46 @@
   bw Xa Xb Xc
 endfunc
 
+func Test_wincmd_equal()
+  edit Xone
+  below split Xtwo
+  rightbelow vsplit Xthree
+  call assert_equal('Xone', bufname(winbufnr(1)))
+  call assert_equal('Xtwo', bufname(winbufnr(2)))
+  call assert_equal('Xthree', bufname(winbufnr(3)))
+
+  " Xone and Xtwo should be about the same height
+  let [wh1, wh2] = [winheight(1), winheight(2)]
+  call assert_inrange(wh1 - 1, wh1 + 1, wh2)
+  " Xtwo and Xthree should be about the same width
+  let [ww2, ww3] = [winwidth(2), winwidth(3)]
+  call assert_inrange(ww2 - 1, ww2 + 1, ww3)
+
+  1wincmd w
+  10wincmd _
+  2wincmd w
+  20wincmd |
+  call assert_equal(10, winheight(1))
+  call assert_equal(20, winwidth(2))
+
+  " equalizing horizontally doesn't change the heights
+  hor wincmd =
+  call assert_equal(10, winheight(1))
+  let [ww2, ww3] = [winwidth(2), winwidth(3)]
+  call assert_inrange(ww2 - 1, ww2 + 1, ww3)
+
+  2wincmd w
+  20wincmd |
+  call assert_equal(20, winwidth(2))
+  " equalizing vertically doesn't change the widths
+  vert wincmd =
+  call assert_equal(20, winwidth(2))
+  let [wh1, wh2] = [winheight(1), winheight(2)]
+  call assert_inrange(wh1 - 1, wh1 + 1, wh2)
+
+  bwipe Xone Xtwo Xthree
+endfunc
+
 func Test_window_width()
   e Xa
   vsplit Xb
diff --git a/src/version.c b/src/version.c
index 2db1aa6..68f7baa 100644
--- a/src/version.c
+++ b/src/version.c
@@ -708,6 +708,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    342,
+/**/
     341,
 /**/
     340,
diff --git a/src/vim.h b/src/vim.h
index 05b6632..54a858a 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -1209,14 +1209,15 @@
 /*
  * arguments for win_split()
  */
-#define WSP_ROOM	1	// require enough room
-#define WSP_VERT	2	// split vertically
-#define WSP_TOP		4	// window at top-left of shell
-#define WSP_BOT		8	// window at bottom-right of shell
-#define WSP_HELP	16	// creating the help window
-#define WSP_BELOW	32	// put new window below/right
-#define WSP_ABOVE	64	// put new window above/left
-#define WSP_NEWLOC	128	// don't copy location list
+#define WSP_ROOM	0x01	// require enough room
+#define WSP_VERT	0x02	// split/equalize vertically
+#define WSP_HOR		0x04	// equalize horizontally
+#define WSP_TOP		0x08	// window at top-left of shell
+#define WSP_BOT		0x10	// window at bottom-right of shell
+#define WSP_HELP	0x20	// creating the help window
+#define WSP_BELOW	0x40	// put new window below/right
+#define WSP_ABOVE	0x80	// put new window above/left
+#define WSP_NEWLOC	0x100	// don't copy location list
 
 /*
  * arguments for gui_set_shellsize()
diff --git a/src/window.c b/src/window.c
index 65dec10..3632735 100644
--- a/src/window.c
+++ b/src/window.c
@@ -434,12 +434,16 @@
 			| ((nchar == 'H' || nchar == 'K') ? WSP_TOP : WSP_BOT));
 		break;
 
-// make all windows the same height
+// make all windows the same width and/or height
     case '=':
+		{
+		    int mod = cmdmod.cmod_split & (WSP_VERT | WSP_HOR);
 #ifdef FEAT_GUI
-		need_mouse_correct = TRUE;
+		    need_mouse_correct = TRUE;
 #endif
-		win_equal(NULL, FALSE, 'b');
+		    win_equal(NULL, FALSE,
+			   mod == WSP_VERT ? 'v' : mod == WSP_HOR ? 'h' : 'b');
+		}
 		break;
 
 // increase current window height