patch 8.2.0191: cannot put a terminal in a popup window

Problem:    Cannot put a terminal in a popup window.
Solution:   Allow opening a terminal in a popup window.  It will always have
            keyboard focus until closed.
diff --git a/src/popupwin.c b/src/popupwin.c
index 8a3f500..b1ae16d 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -1337,6 +1337,11 @@
 
     wp->w_has_scrollbar = wp->w_want_scrollbar
 	   && (wp->w_topline > 1 || lnum <= wp->w_buffer->b_ml.ml_line_count);
+#ifdef FEAT_TERMINAL
+    if (wp->w_buffer->b_term != NULL)
+	// Terminal window never has a scrollbar, adjusts to window height.
+	wp->w_has_scrollbar = FALSE;
+#endif
     if (wp->w_has_scrollbar)
     {
 	++right_extra;
@@ -1769,20 +1774,13 @@
 		semsg(_(e_nobufnr), argvars[0].vval.v_number);
 		return NULL;
 	    }
-#ifdef FEAT_TERMINAL
-	    if (buf->b_term != NULL)
-	    {
-		emsg(_("E278: Cannot put a terminal buffer in a popup window"));
-		return NULL;
-	    }
-#endif
 	}
 	else if (!(argvars[0].v_type == VAR_STRING
 			&& argvars[0].vval.v_string != NULL)
 		    && !(argvars[0].v_type == VAR_LIST
 			&& argvars[0].vval.v_list != NULL))
 	{
-	    emsg(_(e_listreq));
+	    emsg(_("E450: buffer number, text or a list required"));
 	    return NULL;
 	}
 	if (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL)
@@ -2031,6 +2029,10 @@
     redraw_all_later(NOT_VALID);
     popup_mask_refresh = TRUE;
 
+    // When running a terminal in the popup it becomes the current window.
+    if (buf->b_term != NULL)
+	win_enter(wp, FALSE);
+
     return wp;
 }
 
@@ -2107,6 +2109,13 @@
 {
     int id = wp->w_id;
 
+    if (wp == curwin && curbuf->b_term != NULL)
+    {
+	// Closing popup window with a terminal: put focus back on the previous
+	// window.
+	win_enter(prevwin, FALSE);
+    }
+
     // Just in case a check higher up is missing.
     if (wp == curwin && ERROR_IF_POPUP_WINDOW)
 	return;
@@ -2118,7 +2127,7 @@
     popup_close(id);
 }
 
-    static void
+    void
 popup_close_with_retval(win_T *wp, int retval)
 {
     typval_T res;
@@ -2834,7 +2843,10 @@
     int
 error_if_popup_window()
 {
-    if (WIN_IS_POPUP(curwin))
+    // win_execute() may set "curwin" to a popup window temporarily, but many
+    // commands are disallowed then.  When a terminal runs in the popup most
+    // things are allowed.
+    if (WIN_IS_POPUP(curwin) && curbuf->b_term == NULL)
     {
 	emsg(_("E994: Not allowed in a popup window"));
 	return TRUE;
@@ -2842,6 +2854,17 @@
     return FALSE;
 }
 
+    int
+error_if_term_popup_window()
+{
+    if (WIN_IS_POPUP(curwin) && curbuf->b_term != NULL)
+    {
+	emsg(_("E899: Not allowed for a terminal in a popup window"));
+	return TRUE;
+    }
+    return FALSE;
+}
+
 /*
  * Reset all the "handled_flag" flags in global popup windows and popup windows
  * in the current tab page.
@@ -2961,6 +2984,10 @@
     int		state;
     int		was_must_redraw = must_redraw;
 
+    // Popup window with terminal always gets focus.
+    if (popup_is_popup(curwin) && curbuf->b_term != NULL)
+	return FALSE;
+
     if (recursive)
 	return FALSE;
     recursive = TRUE;
@@ -3430,6 +3457,9 @@
 
 	wp->w_winrow -= top_off;
 	wp->w_wincol -= left_extra;
+	// cursor position matters in terminal
+	wp->w_wrow += top_off;
+	wp->w_wcol += left_extra;
 
 	total_width = popup_width(wp);
 	total_height = popup_height(wp);