patch 9.1.1391: Vim does not have a vertical tabpanel

Problem:  Vim does not have a tabpanel
Solution: include the tabpanel feature
          (Naruhiko Nishino, thinca)

closes: #17263

Co-authored-by: thinca <thinca@gmail.com>
Signed-off-by: Naruhiko Nishino <naru123456789@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/screen.c b/src/screen.c
index 4fcd9d3..d8a060f 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -156,13 +156,13 @@
     if (wp->w_p_rl)
     {
 	screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + endrow,
-		W_ENDCOL(wp) - nn, (int)W_ENDCOL(wp) - off,
+		W_ENDCOL(wp) - nn + TPL_LCOL(wp), (int)W_ENDCOL(wp) - off + TPL_LCOL(wp),
 		c1, c2, attr);
     }
     else
 #endif
 	screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + endrow,
-		wp->w_wincol + off, (int)wp->w_wincol + nn,
+		wp->w_wincol + off + TPL_LCOL(wp), (int)wp->w_wincol + nn + TPL_LCOL(wp),
 		c1, c2, attr);
     return nn;
 }
@@ -215,17 +215,17 @@
     if (wp->w_p_rl)
     {
 	screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + endrow,
-		wp->w_wincol, W_ENDCOL(wp) - 1 - n,
-		c2, c2, attr);
+		wp->w_wincol + TPL_LCOL(wp), W_ENDCOL(wp) - 1 - n +
+		TPL_LCOL(wp), c2, c2, attr);
 	screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + endrow,
-		W_ENDCOL(wp) - 1 - n, W_ENDCOL(wp) - n,
-		c1, c2, attr);
+		W_ENDCOL(wp) - 1 - n + TPL_LCOL(wp), W_ENDCOL(wp) - n +
+		TPL_LCOL(wp), c1, c2, attr);
     }
     else
 #endif
     {
 	screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + endrow,
-		wp->w_wincol + n, (int)W_ENDCOL(wp),
+		wp->w_wincol + n + TPL_LCOL(wp), (int)W_ENDCOL(wp) + TPL_LCOL(wp),
 		c1, c2, attr);
     }
 
@@ -395,7 +395,9 @@
 
     if (!popup_visible)
 	return FALSE;
-    off = row * screen_Columns + col;
+    if (col < TPL_LCOL(NULL))
+	return FALSE;
+    off = row * screen_Columns + col - TPL_LCOL(NULL);
     return popup_mask[off] > screen_zindex || popup_transparent[off];
 }
 #endif
@@ -855,7 +857,7 @@
     {
 	// For a window that has a right neighbor, draw the separator char
 	// right of the window contents.  But not on top of a popup window.
-	if (coloff + col < Columns)
+	if (coloff + col < TPL_LCOL(NULL) + COLUMNS_WITHOUT_TPL())
 	{
 	    if (!skip_for_popup(row, col + coloff))
 	    {
@@ -920,10 +922,13 @@
     if (!wp->w_vsep_width)
 	return;
 
+    if (COLUMNS_WITHOUT_TPL() <= W_ENDCOL(wp) + 1)
+	return;
+
     // draw the vertical separator right of this window
     c = fillchar_vsep(&hl, wp);
     screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + wp->w_height,
-	    W_ENDCOL(wp), W_ENDCOL(wp) + 1,
+	    W_ENDCOL(wp) + TPL_LCOL(wp), W_ENDCOL(wp) + 1 + TPL_LCOL(wp),
 	    c, ' ', hl);
 }
 
@@ -1053,7 +1058,7 @@
 	row = 0;
 	fillchar = ' ';
 	attr = HL_ATTR(HLF_TPF);
-	maxwidth = Columns;
+	maxwidth = COLUMNS_WITHOUT_TPL();
 	opt_name = (char_u *)"tabline";
     }
     else
@@ -1150,7 +1155,7 @@
     for (n = 0; hltab[n].start != NULL; n++)
     {
 	len = (int)(hltab[n].start - p);
-	screen_puts_len(p, len, row, col, curattr);
+	screen_puts_len(p, len, row, col + TPL_LCOL(wp), curattr);
 	col += vim_strnsize(p, len);
 	p = hltab[n].start;
 
@@ -1171,7 +1176,7 @@
 	else
 	    curattr = highlight_user[hltab[n].userhl - 1];
     }
-    screen_puts(p, row, col, curattr);
+    screen_puts(p, row, col + TPL_LCOL(wp), curattr);
 
     if (wp == NULL)
     {
@@ -1188,7 +1193,7 @@
 	    p = tabtab[n].start;
 	    fillchar = tabtab[n].userhl;
 	}
-	while (col < Columns)
+	while (col < COLUMNS_WITHOUT_TPL())
 	    TabPageIdxs[col++] = fillchar;
     }
 
@@ -2128,14 +2133,14 @@
     if (wp == NULL)
     {
 	col = 0;
-	width = Columns;
+	width = COLUMNS_WITHOUT_TPL();
     }
     else
     {
 	col = wp->w_wincol;
 	width = wp->w_width;
     }
-    screen_draw_rectangle(row, col, end - row, width, FALSE);
+    screen_draw_rectangle(row, col + TPL_LCOL(wp), end - row, width, FALSE);
 }
 
     void
@@ -2850,6 +2855,9 @@
     win_rest_invalid(firstwin);	// redraw all regular windows
     redraw_cmdline = TRUE;
     redraw_tabline = TRUE;
+#if defined(FEAT_TABPANEL)
+    redraw_tabpanel = TRUE;
+#endif
     if (must_redraw == UPD_CLEAR)	// no need to clear again
 	must_redraw = UPD_NOT_VALID;
     msg_scrolled = 0;		// compute_cmdrow() uses this
@@ -2910,6 +2918,11 @@
     unsigned	off_to = LineOffset[to] + wp->w_wincol;
     unsigned	off_from = LineOffset[from] + wp->w_wincol;
 
+#if defined(FEAT_TABPANEL)
+    off_to += TPL_LCOL(wp);
+    off_from += TPL_LCOL(wp);
+#endif
+
     mch_memmove(ScreenLines + off_to, ScreenLines + off_from,
 	    wp->w_width * sizeof(schar_T));
     if (enc_utf8)
@@ -3243,7 +3256,7 @@
 			   && (*mb_ptr2cells)(ml_get_cursor()) == 2
 			   && vim_isprintc(gchar_cursor())) ? 2 : 1)) :
 #endif
-							    curwin->w_wcol));
+					    curwin->w_wcol) + TPL_LCOL(NULL));
     }
 }
 
@@ -3313,7 +3326,7 @@
 	if (lastrow > Rows)
 	    lastrow = Rows;
 	screen_fill(nextrow - line_count, lastrow - line_count,
-		  wp->w_wincol, (int)W_ENDCOL(wp),
+		  wp->w_wincol + TPL_LCOL(wp), (int)W_ENDCOL(wp) + TPL_LCOL(wp),
 		  ' ', ' ', 0);
     }
 
@@ -3411,7 +3424,8 @@
 	return FAIL;
 
     // only a few lines left: redraw is faster
-    if (mayclear && Rows - line_count < 5 && wp->w_width == Columns)
+    if (mayclear && Rows - line_count < 5
+	    && wp->w_width == COLUMNS_WITHOUT_TPL())
     {
 	if (!no_win_do_lines_ins)
 	    screenclear();	    // will set wp->w_lines_valid to 0
@@ -3428,7 +3442,7 @@
     if (row + line_count >= wp->w_height)
     {
 	screen_fill(W_WINROW(wp) + row, W_WINROW(wp) + wp->w_height,
-		wp->w_wincol, (int)W_ENDCOL(wp),
+		wp->w_wincol + TPL_LCOL(wp), (int)W_ENDCOL(wp) + TPL_LCOL(wp),
 		' ', ' ', 0);
 	return OK;
     }
@@ -3450,9 +3464,10 @@
      * a character in the lower right corner of the scroll region may cause a
      * scroll-up .
      */
-    if (scroll_region || wp->w_width != Columns)
+    if (scroll_region || wp->w_width != COLUMNS_WITHOUT_TPL())
     {
-	if (scroll_region && (wp->w_width == Columns || *T_CSV != NUL))
+	if (scroll_region && (wp->w_width == COLUMNS_WITHOUT_TPL()
+		    || *T_CSV != NUL))
 	    scroll_region_set(wp, row);
 	if (del)
 	    retval = screen_del_lines(W_WINROW(wp) + row, 0, line_count,
@@ -3460,7 +3475,8 @@
 	else
 	    retval = screen_ins_lines(W_WINROW(wp) + row, 0, line_count,
 					   wp->w_height - row, clear_attr, wp);
-	if (scroll_region && (wp->w_width == Columns || *T_CSV != NUL))
+	if (scroll_region && (wp->w_width == COLUMNS_WITHOUT_TPL()
+		    || *T_CSV != NUL))
 	    scroll_region_reset();
 	return retval;
     }
@@ -3583,7 +3599,7 @@
      * exists.
      */
     result_empty = (row + line_count >= end);
-    if (wp != NULL && wp->w_width != Columns && *T_CSV == NUL)
+    if (wp != NULL && wp->w_width != COLUMNS_WITHOUT_TPL() && *T_CSV == NUL)
     {
 	// Avoid that lines are first cleared here and then redrawn, which
 	// results in many characters updated twice.  This happens with CTRL-F
@@ -3629,7 +3645,7 @@
 #ifdef FEAT_CLIPBOARD
     // Remove a modeless selection when inserting lines halfway the screen
     // or not the full width of the screen.
-    if (off + row > 0 || (wp != NULL && wp->w_width != Columns))
+    if (off + row > 0 || (wp != NULL && wp->w_width != COLUMNS_WITHOUT_TPL()))
 	clip_clear_selection(&clip_star);
     else
 	clip_scroll_selection(-line_count);
@@ -3661,7 +3677,7 @@
     end += off;
     for (i = 0; i < line_count; ++i)
     {
-	if (wp != NULL && wp->w_width != Columns)
+	if (wp != NULL && wp->w_width != COLUMNS_WITHOUT_TPL())
 	{
 	    // need to copy part of a line
 	    j = end - 1 - i;
@@ -3669,10 +3685,11 @@
 		linecopy(j + line_count, j, wp);
 	    j += line_count;
 	    if (can_clear((char_u *)" "))
-		lineclear(LineOffset[j] + wp->w_wincol, wp->w_width,
-								   clear_attr);
+		lineclear(LineOffset[j] + wp->w_wincol + TPL_LCOL(wp),
+			wp->w_width, clear_attr);
 	    else
-		lineinvalid(LineOffset[j] + wp->w_wincol, wp->w_width);
+		lineinvalid(LineOffset[j] + wp->w_wincol + TPL_LCOL(wp),
+			wp->w_width);
 	    LineWraps[j] = FALSE;
 	}
 	else
@@ -3687,9 +3704,10 @@
 	    LineOffset[j + line_count] = temp;
 	    LineWraps[j + line_count] = FALSE;
 	    if (can_clear((char_u *)" "))
-		lineclear(temp, (int)Columns, clear_attr);
+		lineclear(temp + TPL_LCOL(wp), COLUMNS_WITHOUT_TPL(),
+			clear_attr);
 	    else
-		lineinvalid(temp, (int)Columns);
+		lineinvalid(temp + TPL_LCOL(wp), COLUMNS_WITHOUT_TPL());
 	}
     }
 
@@ -3740,6 +3758,10 @@
 	}
     }
 
+#if defined(FEAT_TABPANEL)
+    redraw_tabpanel = TRUE;
+#endif
+
 #ifdef FEAT_GUI
     gui_can_update_cursor();
     if (gui.in_use)
@@ -3818,7 +3840,7 @@
      * 5. Use T_DL (delete line) if it exists.
      * 6. redraw the characters from ScreenLines[].
      */
-    if (wp != NULL && wp->w_width != Columns && *T_CSV == NUL)
+    if (wp != NULL && wp->w_width != COLUMNS_WITHOUT_TPL() && *T_CSV == NUL)
     {
 	// Avoid that lines are first cleared here and then redrawn, which
 	// results in many characters updated twice.  This happens with CTRL-F
@@ -3841,7 +3863,7 @@
     else if (*T_CDL != NUL && line_count > 1 && can_delete)
 	type = USE_T_CDL;
     else if (can_clear(T_CE) && result_empty
-	    && (wp == NULL || wp->w_width == Columns))
+	    && (wp == NULL || wp->w_width == COLUMNS_WITHOUT_TPL()))
 	type = USE_T_CE;
     else if (*T_DL != NUL && can_delete)
 	type = USE_T_DL;
@@ -3853,7 +3875,7 @@
 #ifdef FEAT_CLIPBOARD
     // Remove a modeless selection when deleting lines halfway the screen or
     // not the full width of the screen.
-    if (off + row > 0 || (wp != NULL && wp->w_width != Columns))
+    if (off + row > 0 || (wp != NULL && wp->w_width != COLUMNS_WITHOUT_TPL()))
 	clip_clear_selection(&clip_star);
     else
 	clip_scroll_selection(line_count);
@@ -3892,7 +3914,7 @@
     end += off;
     for (i = 0; i < line_count; ++i)
     {
-	if (wp != NULL && wp->w_width != Columns)
+	if (wp != NULL && wp->w_width != COLUMNS_WITHOUT_TPL())
 	{
 	    // need to copy part of a line
 	    j = row + i;
@@ -3900,10 +3922,11 @@
 		linecopy(j - line_count, j, wp);
 	    j -= line_count;
 	    if (can_clear((char_u *)" "))
-		lineclear(LineOffset[j] + wp->w_wincol, wp->w_width,
-								   clear_attr);
+		lineclear(LineOffset[j] + wp->w_wincol + TPL_LCOL(wp),
+			wp->w_width, clear_attr);
 	    else
-		lineinvalid(LineOffset[j] + wp->w_wincol, wp->w_width);
+		lineinvalid(LineOffset[j] + wp->w_wincol + TPL_LCOL(wp),
+			wp->w_width);
 	    LineWraps[j] = FALSE;
 	}
 	else
@@ -3919,9 +3942,10 @@
 	    LineOffset[j - line_count] = temp;
 	    LineWraps[j - line_count] = FALSE;
 	    if (can_clear((char_u *)" "))
-		lineclear(temp, (int)Columns, clear_attr);
+		lineclear(temp + TPL_LCOL(NULL), COLUMNS_WITHOUT_TPL(),
+			clear_attr);
 	    else
-		lineinvalid(temp, (int)Columns);
+		lineinvalid(temp + TPL_LCOL(NULL), COLUMNS_WITHOUT_TPL());
 	}
     }
 
@@ -3992,6 +4016,10 @@
 	}
     }
 
+#if defined(FEAT_TABPANEL)
+    redraw_tabpanel = TRUE;
+#endif
+
 #ifdef FEAT_GUI
     gui_can_update_cursor();
     if (gui.in_use)
@@ -4304,6 +4332,10 @@
 #endif
 					    );
 
+#if defined(FEAT_TABPANEL)
+    col = TPL_LCOL(NULL);
+#endif
+
     if (ScreenLines == NULL)
 	return;
     redraw_tabline = FALSE;
@@ -4332,7 +4364,7 @@
 	FOR_ALL_TABPAGES(tp)
 	    ++tabcount;
 
-	tabwidth = (Columns - 1 + tabcount / 2) / tabcount;
+	tabwidth = (COLUMNS_WITHOUT_TPL() - 1 + tabcount / 2) / tabcount;
 	if (tabwidth < 6)
 	    tabwidth = 6;
 
@@ -4713,6 +4745,9 @@
     CHARSTAB_ENTRY(&fill_chars.diff,	    "diff"),
     CHARSTAB_ENTRY(&fill_chars.eob,	    "eob"),
     CHARSTAB_ENTRY(&fill_chars.lastline,    "lastline"),
+#if defined(FEAT_TABPANEL)
+    CHARSTAB_ENTRY(&fill_chars.tpl_vert,    "tpl_vert"),
+#endif
     CHARSTAB_ENTRY(&fill_chars.trunc,	    "trunc"),
     CHARSTAB_ENTRY(&fill_chars.truncrl,	    "truncrl"),
 };
@@ -4828,6 +4863,9 @@
 		fill_chars.diff = '-';
 		fill_chars.eob = '~';
 		fill_chars.lastline = '@';
+#if defined(FEAT_TABPANEL)
+		fill_chars.tpl_vert = '|';
+#endif
 		fill_chars.trunc = '>';
 		fill_chars.truncrl = '<';
 	    }