patch 8.0.1330: MS-Windows: job in terminal can't get back to Vim

Problem:    MS-Windows: job in terminal can't get back to Vim.
Solution:   set VIM_SERVERNAME in the environment. (Yasuhiro Matsumoto, closes
            #2360)
diff --git a/src/os_win32.c b/src/os_win32.c
index 3a2b356..becbeee 100644
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -5034,10 +5034,10 @@
  * environment argument of vim_create_process().
  */
     void
-win32_build_env(dict_T *env, garray_T *gap)
+win32_build_env(dict_T *env, garray_T *gap, int is_terminal)
 {
     hashitem_T	*hi;
-    int		todo = (int)env->dv_hashtab.ht_used;
+    long_u	todo = env != NULL ? env->dv_hashtab.ht_used : 0;
     LPVOID	base = GetEnvironmentStringsW();
 
     /* for last \0 */
@@ -5062,35 +5062,56 @@
 	*((WCHAR*)gap->ga_data + gap->ga_len++) = L'\0';
     }
 
-    for (hi = env->dv_hashtab.ht_array; todo > 0; ++hi)
+    if (env != NULL)
     {
-	if (!HASHITEM_EMPTY(hi))
+	for (hi = env->dv_hashtab.ht_array; todo > 0; ++hi)
 	{
-	    typval_T *item = &dict_lookup(hi)->di_tv;
-	    WCHAR   *wkey = enc_to_utf16((char_u *)hi->hi_key, NULL);
-	    WCHAR   *wval = enc_to_utf16(get_tv_string(item), NULL);
-	    --todo;
-	    if (wkey != NULL && wval != NULL)
+	    if (!HASHITEM_EMPTY(hi))
 	    {
-		size_t	n;
-		size_t	lkey = wcslen(wkey);
-		size_t	lval = wcslen(wval);
+		typval_T *item = &dict_lookup(hi)->di_tv;
+		WCHAR   *wkey = enc_to_utf16((char_u *)hi->hi_key, NULL);
+		WCHAR   *wval = enc_to_utf16(get_tv_string(item), NULL);
+		--todo;
+		if (wkey != NULL && wval != NULL)
+		{
+		    size_t	n;
+		    size_t	lkey = wcslen(wkey);
+		    size_t	lval = wcslen(wval);
 
-		if (ga_grow(gap, (int)(lkey + lval + 2)) != OK)
-		    continue;
-		for (n = 0; n < lkey; n++)
-		    *((WCHAR*)gap->ga_data + gap->ga_len++) = wkey[n];
-		*((WCHAR*)gap->ga_data + gap->ga_len++) = L'=';
-		for (n = 0; n < lval; n++)
-		    *((WCHAR*)gap->ga_data + gap->ga_len++) = wval[n];
-		*((WCHAR*)gap->ga_data + gap->ga_len++) = L'\0';
+		    if (ga_grow(gap, (int)(lkey + lval + 2)) != OK)
+			continue;
+		    for (n = 0; n < lkey; n++)
+			*((WCHAR*)gap->ga_data + gap->ga_len++) = wkey[n];
+		    *((WCHAR*)gap->ga_data + gap->ga_len++) = L'=';
+		    for (n = 0; n < lval; n++)
+			*((WCHAR*)gap->ga_data + gap->ga_len++) = wval[n];
+		    *((WCHAR*)gap->ga_data + gap->ga_len++) = L'\0';
+		}
+		if (wkey != NULL) vim_free(wkey);
+		if (wval != NULL) vim_free(wval);
 	    }
-	    if (wkey != NULL) vim_free(wkey);
-	    if (wval != NULL) vim_free(wval);
 	}
     }
 
-    *((WCHAR*)gap->ga_data + gap->ga_len++) = L'\0';
+# ifdef FEAT_CLIENTSERVER
+    if (is_terminal)
+    {
+	char_u	*servername = get_vim_var_str(VV_SEND_SERVER);
+	size_t	lval = STRLEN(servername);
+	size_t	n;
+
+	if (ga_grow(gap, (int)(14 + lval + 2)) == OK)
+	{
+	    for (n = 0; n < 15; n++)
+		*((WCHAR*)gap->ga_data + gap->ga_len++) =
+		    (WCHAR)"VIM_SERVERNAME="[n];
+	    for (n = 0; n < lval; n++)
+		*((WCHAR*)gap->ga_data + gap->ga_len++) =
+		    (WCHAR)servername[n];
+	    *((WCHAR*)gap->ga_data + gap->ga_len++) = L'\0';
+	}
+    }
+# endif
 }
 
     void
@@ -5133,7 +5154,7 @@
     }
 
     if (options->jo_env != NULL)
-	win32_build_env(options->jo_env, &ga);
+	win32_build_env(options->jo_env, &ga, FALSE);
 
     ZeroMemory(&pi, sizeof(pi));
     ZeroMemory(&si, sizeof(si));
diff --git a/src/proto/os_win32.pro b/src/proto/os_win32.pro
index 188a45b..a87d8b7 100644
--- a/src/proto/os_win32.pro
+++ b/src/proto/os_win32.pro
@@ -67,5 +67,5 @@
 void set_alist_count(void);
 void fix_arg_enc(void);
 int mch_setenv(char *var, char *value, int x);
-void win32_build_env(dict_T *l, garray_T *gap);
+void win32_build_env(dict_T *l, garray_T *gap, int is_terminal);
 /* vim: set ft=c : */
diff --git a/src/terminal.c b/src/terminal.c
index 2e6b399..716d0b5 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -3424,12 +3424,10 @@
 	return FAIL;
     if (opt->jo_cwd != NULL)
 	cwd_wchar = enc_to_utf16(opt->jo_cwd, NULL);
-    if (opt->jo_env != NULL)
-    {
-	ga_init2(&ga_env, (int)sizeof(char*), 20);
-	win32_build_env(opt->jo_env, &ga_env);
-	env_wchar = ga_env.ga_data;
-    }
+
+    ga_init2(&ga_env, (int)sizeof(char*), 20);
+    win32_build_env(opt->jo_env, &ga_env, TRUE);
+    env_wchar = ga_env.ga_data;
 
     job = job_alloc();
     if (job == NULL)
@@ -3531,8 +3529,7 @@
 failed:
     if (argvar->v_type == VAR_LIST)
 	vim_free(ga_cmd.ga_data);
-    if (opt->jo_env != NULL)
-	vim_free(ga_env.ga_data);
+    vim_free(ga_env.ga_data);
     vim_free(cmd_wchar);
     vim_free(cwd_wchar);
     if (spawn_config != NULL)
diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim
index 295ccf1..cdff5c3 100644
--- a/src/testdir/test_terminal.vim
+++ b/src/testdir/test_terminal.vim
@@ -434,6 +434,27 @@
   call delete('Xdir', 'rf')
 endfunc
 
+func Test_terminal_servername()
+  if !has('clientserver')
+    return
+  endif
+  let g:buf = Run_shell_in_terminal({})
+  " Wait for the shell to display a prompt
+  call WaitFor('term_getline(g:buf, 1) != ""')
+  if has('win32')
+    call term_sendkeys(g:buf, "echo %VIM_SERVERNAME%\r")
+  else
+    call term_sendkeys(g:buf, "echo $VIM_SERVERNAME\r")
+  endif
+  call term_wait(g:buf)
+  call Stop_shell_in_terminal(g:buf)
+  call WaitFor('getline(2) == v:servername')
+  call assert_equal(v:servername, getline(2))
+
+  exe g:buf . 'bwipe'
+  unlet g:buf
+endfunc
+
 func Test_terminal_env()
   let g:buf = Run_shell_in_terminal({'env': {'TESTENV': 'correct'}})
   " Wait for the shell to display a prompt
diff --git a/src/version.c b/src/version.c
index 93fb5cb..ebc57ed 100644
--- a/src/version.c
+++ b/src/version.c
@@ -772,6 +772,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1330,
+/**/
     1329,
 /**/
     1328,