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/Make_ami.mak b/src/Make_ami.mak
index 4dc86dd..bd8b525 100644
--- a/src/Make_ami.mak
+++ b/src/Make_ami.mak
@@ -162,6 +162,7 @@
strings.c \
syntax.c \
tag.c \
+ tabpanel.c \
term.c \
termlib.c \
testing.c \
diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak
index ab9c3b1..37f9f6c 100644
--- a/src/Make_cyg_ming.mak
+++ b/src/Make_cyg_ming.mak
@@ -875,6 +875,7 @@
$(OUTDIR)/spellsuggest.o \
$(OUTDIR)/strings.o \
$(OUTDIR)/syntax.o \
+ $(OUTDIR)/tabpanel.o \
$(OUTDIR)/tag.o \
$(OUTDIR)/term.o \
$(OUTDIR)/testing.o \
diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak
index d6dbd2b..08016d4 100644
--- a/src/Make_mvc.mak
+++ b/src/Make_mvc.mak
@@ -779,6 +779,7 @@
$(OUTDIR)\spellsuggest.obj \
$(OUTDIR)\strings.obj \
$(OUTDIR)\syntax.obj \
+ $(OUTDIR)\tabpanel.obj \
$(OUTDIR)\tag.obj \
$(OUTDIR)\term.obj \
$(OUTDIR)\testing.obj \
@@ -1778,6 +1779,8 @@
$(OUTDIR)/syntax.obj: $(OUTDIR) syntax.c $(INCL)
+$(OUTDIR)/tabpanel.obj: $(OUTDIR) tabpanel.c $(INCL)
+
$(OUTDIR)/tag.obj: $(OUTDIR) tag.c $(INCL)
$(OUTDIR)/term.obj: $(OUTDIR) term.c $(INCL)
@@ -2001,6 +2004,7 @@
proto/spellsuggest.pro \
proto/strings.pro \
proto/syntax.pro \
+ proto/tabpanel.pro \
proto/tag.pro \
proto/term.pro \
proto/testing.pro \
diff --git a/src/Make_vms.mms b/src/Make_vms.mms
index a30ed65..9dce2b5 100644
--- a/src/Make_vms.mms
+++ b/src/Make_vms.mms
@@ -424,6 +424,7 @@
spellsuggest.c \
strings.c \
syntax.c \
+ tabpanel.c \
tag.c \
term.c \
terminal.c \
@@ -559,6 +560,7 @@
spellsuggest.obj \
strings.obj \
syntax.obj \
+ tabpanel.obj \
tag.obj \
term.obj \
terminal.obj \
@@ -1146,6 +1148,10 @@
ascii.h keymap.h termdefs.h macros.h structs.h regexp.h \
gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \
errors.h globals.h
+tabpanel.obj : tabpanel.c vim.h [.auto]config.h feature.h os_unix.h \
+ ascii.h keymap.h termdefs.h macros.h structs.h regexp.h \
+ gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \
+ errors.h globals.h
tag.obj : tag.c vim.h [.auto]config.h feature.h os_unix.h \
ascii.h keymap.h termdefs.h macros.h structs.h regexp.h gui.h beval.h \
[.proto]gui_beval.pro option.h ex_cmds.h proto.h errors.h globals.h
diff --git a/src/Makefile b/src/Makefile
index 962e47b..9a1a1cc 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1576,6 +1576,7 @@
spellsuggest.c \
strings.c \
syntax.c \
+ tabpanel.c \
tag.c \
term.c \
terminal.c \
@@ -1737,6 +1738,7 @@
objects/spellsuggest.o \
objects/strings.o \
objects/syntax.o \
+ objects/tabpanel.o \
objects/tag.o \
objects/term.o \
objects/terminal.o \
@@ -1930,6 +1932,7 @@
spellsuggest.pro \
strings.pro \
syntax.pro \
+ tabpanel.pro \
tag.pro \
term.pro \
terminal.pro \
@@ -3547,6 +3550,9 @@
objects/syntax.o: syntax.c
$(CCC) -o $@ syntax.c
+objects/tabpanel.o: tabpanel.c
+ $(CCC) -o $@ tabpanel.c
+
objects/tag.o: tag.c
$(CCC) -o $@ tag.c
@@ -4214,6 +4220,11 @@
proto/gui_beval.pro structs.h regexp.h gui.h libvterm/include/vterm.h \
libvterm/include/vterm_keycodes.h alloc.h ex_cmds.h spell.h proto.h \
globals.h errors.h
+objects/tabpanel.o: tabpanel.c vim.h protodef.h auto/config.h feature.h os_unix.h \
+ auto/osdef.h ascii.h keymap.h termdefs.h macros.h option.h beval.h \
+ proto/gui_beval.pro structs.h regexp.h gui.h \
+ libvterm/include/vterm_keycodes.h alloc.h ex_cmds.h spell.h proto.h \
+ globals.h errors.h
objects/tag.o: tag.c vim.h protodef.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h termdefs.h macros.h option.h beval.h \
proto/gui_beval.pro structs.h regexp.h gui.h libvterm/include/vterm.h \
diff --git a/src/change.c b/src/change.c
index c48d254..438bbda 100644
--- a/src/change.c
+++ b/src/change.c
@@ -142,6 +142,9 @@
ml_setflags(curbuf);
check_status(curbuf);
redraw_tabline = TRUE;
+#if defined(FEAT_TABPANEL)
+ redraw_tabpanel = TRUE;
+#endif
need_maketitle = TRUE; // set window title later
}
@@ -917,6 +920,9 @@
save_file_ff(buf);
check_status(buf);
redraw_tabline = TRUE;
+#if defined(FEAT_TABPANEL)
+ redraw_tabpanel = TRUE;
+#endif
need_maketitle = TRUE; // set window title later
++CHANGEDTICK(buf);
}
diff --git a/src/clipboard.c b/src/clipboard.c
index fb967dc..d0feb2f 100644
--- a/src/clipboard.c
+++ b/src/clipboard.c
@@ -404,7 +404,7 @@
gui_mch_invert_rectangle(row, col, height, width);
else
#endif
- screen_draw_rectangle(row, col, height, width, invert);
+ screen_draw_rectangle(row, col + TPL_LCOL(NULL), height, width, invert);
#ifdef FEAT_PROP_POPUP
screen_zindex = 0;
#endif
diff --git a/src/drawline.c b/src/drawline.c
index 57ee9a5..3be9a3a 100644
--- a/src/drawline.c
+++ b/src/drawline.c
@@ -875,7 +875,7 @@
}
}
- screen_line(wp, wlv->screen_row, wp->w_wincol, wlv->col,
+ screen_line(wp, wlv->screen_row, wp->w_wincol + TPL_LCOL(wp), wlv->col,
clear_end ? wp->w_width : -wp->w_width,
wlv->vcol - 1, wlv->screen_line_flags);
}
@@ -4355,7 +4355,7 @@
#ifdef FEAT_PROP_POPUP
&& !text_prop_above && !text_prop_follows
#endif
- && wp->w_width == Columns)
+ && wp->w_width == COLUMNS_WITHOUT_TPL())
{
// Remember that the line wraps, used for modeless copy.
LineWraps[wlv.screen_row - 1] = TRUE;
@@ -4380,7 +4380,7 @@
== 2
|| (*mb_off2cells)(
LineOffset[wlv.screen_row - 1]
- + (int)Columns - 2,
+ + (int)COLUMNS_WITHOUT_TPL() - 2,
LineOffset[wlv.screen_row]
+ screen_Columns) == 2)))
{
@@ -4390,17 +4390,17 @@
// auto-wrap, we overwrite the character.
if (screen_cur_col != wp->w_width)
screen_char(LineOffset[wlv.screen_row - 1]
- + (unsigned)Columns - 1,
- wlv.screen_row - 1, (int)(Columns - 1));
+ + (unsigned)COLUMNS_WITHOUT_TPL() - 1,
+ wlv.screen_row - 1, (int)(COLUMNS_WITHOUT_TPL() - 1));
// When there is a multi-byte character, just output a
// space to keep it simple.
if (has_mbyte && MB_BYTE2LEN(ScreenLines[LineOffset[
- wlv.screen_row - 1] + (Columns - 1)]) > 1)
+ wlv.screen_row - 1] + (COLUMNS_WITHOUT_TPL() - 1)]) > 1)
out_char(' ');
else
out_char(ScreenLines[LineOffset[wlv.screen_row - 1]
- + (Columns - 1)]);
+ + (COLUMNS_WITHOUT_TPL() - 1)]);
// force a redraw of the first char on the next line
ScreenAttrs[LineOffset[wlv.screen_row]] = (sattr_T)-1;
screen_start(); // don't know where cursor is now
diff --git a/src/drawscreen.c b/src/drawscreen.c
index 4736bf1..1e71cae 100644
--- a/src/drawscreen.c
+++ b/src/drawscreen.c
@@ -209,6 +209,9 @@
redraw_cmdline = TRUE;
redraw_tabline = TRUE;
}
+#if defined(FEAT_TABPANEL)
+ redraw_tabpanel = TRUE;
+#endif
}
msg_scrolled = 0;
need_wait_return = FALSE;
@@ -265,6 +268,11 @@
if (redraw_tabline || type >= UPD_NOT_VALID)
draw_tabline();
+#if defined(FEAT_TABPANEL)
+ if (redraw_tabpanel || type >= UPD_NOT_VALID)
+ draw_tabpanel();
+#endif
+
#ifdef FEAT_SYN_HL
// Correct stored syntax highlighting info for changes in each displayed
// buffer. Each buffer must only be done once.
@@ -331,6 +339,10 @@
win_redr_status(wp, TRUE); // any popup menu will be redrawn below
}
}
+#if defined(FEAT_TABPANEL)
+ if (redraw_tabpanel)
+ draw_tabpanel();
+#endif
#if defined(FEAT_SEARCH_EXTRA)
end_search_hl();
#endif
@@ -529,14 +541,13 @@
plen = this_ru_col - 1;
}
- screen_puts(p, row, wp->w_wincol, attr);
- screen_fill(row, row + 1, plen + wp->w_wincol,
- this_ru_col + wp->w_wincol, fillchar, fillchar, attr);
-
+ screen_puts(p, row, wp->w_wincol + TPL_LCOL(wp), attr);
+ screen_fill(row, row + 1, plen + wp->w_wincol + TPL_LCOL(wp),
+ this_ru_col + wp->w_wincol + TPL_LCOL(wp), fillchar, fillchar, attr);
if ((NameBufflen = get_keymap_str(wp, (char_u *)"<%s>", NameBuff, MAXPATHL)) > 0
&& (this_ru_col - plen) > (NameBufflen + 1))
screen_puts(NameBuff, row, (int)(this_ru_col - NameBufflen
- - 1 + wp->w_wincol), attr);
+ - 1 + wp->w_wincol + TPL_LCOL(wp)), attr);
win_redr_ruler(wp, TRUE, ignore_pum);
@@ -561,7 +572,8 @@
fillchar = fillchar_status(&attr, wp);
else
fillchar = fillchar_vsep(&attr, wp);
- screen_putchar(fillchar, row, W_ENDCOL(wp), attr);
+ if (W_ENDCOL(wp) < COLUMNS_WITHOUT_TPL())
+ screen_putchar(fillchar, row, W_ENDCOL(wp) + TPL_LCOL(wp), attr);
}
busy = FALSE;
}
@@ -620,6 +632,11 @@
// Redraw the tab pages line if needed.
if (redraw_tabline)
draw_tabline();
+
+#if defined(FEAT_TABPANEL)
+ if (redraw_tabpanel)
+ draw_tabpanel();
+#endif
}
void
@@ -781,11 +798,11 @@
buffer[bufferlen] = NUL;
}
- screen_puts(buffer, row, this_ru_col + off, attr);
+ screen_puts(buffer, row, this_ru_col + off + TPL_LCOL(wp), attr);
n1 = redraw_cmdline;
screen_fill(row, row + 1,
- this_ru_col + off + bufferlen,
- (off + width),
+ this_ru_col + off + bufferlen + TPL_LCOL(wp),
+ (off + width) + TPL_LCOL(wp),
fillchar, fillchar, attr);
// don't redraw the cmdline because of showing the ruler
redraw_cmdline = n1;
@@ -1026,8 +1043,8 @@
}
wp->w_winbar_items[item_idx].wb_menu = NULL; // end marker
- screen_line(wp, wp->w_winrow, wp->w_wincol, wp->w_width, wp->w_width, -1,
- 0);
+ screen_line(wp, wp->w_winrow, wp->w_wincol + TPL_LCOL(wp), wp->w_width,
+ wp->w_width, -1, 0);
}
#endif
@@ -1361,8 +1378,8 @@
}
#endif
- screen_line(wp, row + W_WINROW(wp), wp->w_wincol,
- wp->w_width, wp->w_width, -1, 0);
+ screen_line(wp, row + W_WINROW(wp), wp->w_wincol + TPL_LCOL(wp),
+ wp->w_width, wp->w_width, -1, 0);
// Update w_cline_height and w_cline_folded if the cursor line was
// updated (saves a call to plines() later).
@@ -2672,8 +2689,8 @@
// Last line isn't finished: Display "@@@" at the end.
screen_fill(W_WINROW(wp) + wp->w_height - 1,
W_WINROW(wp) + wp->w_height,
- start_col < wp->w_wincol ? wp->w_wincol : start_col,
- (int)W_ENDCOL(wp),
+ (start_col < wp->w_wincol ? wp->w_wincol : start_col) + TPL_LCOL(wp),
+ (int)W_ENDCOL(wp) + TPL_LCOL(wp),
symbol, symbol, HL_ATTR(HLF_AT));
set_empty_rows(wp, srow);
wp->w_botline = lnum;
@@ -2898,6 +2915,11 @@
win_redr_status(wp, FALSE);
}
+#if defined(FEAT_TABPANEL)
+ if (redraw_tabpanel)
+ draw_tabpanel();
+#endif
+
update_finish();
}
#endif
@@ -2930,6 +2952,11 @@
if (redraw_tabline)
draw_tabline();
+#if defined(FEAT_TABPANEL)
+ if (redraw_tabpanel)
+ draw_tabpanel();
+#endif
+
if (wp->w_redr_status || p_ru
# ifdef FEAT_STL_OPT
|| *p_stl != NUL || *wp->w_p_stl != NUL
@@ -3328,6 +3355,11 @@
win_redr_status(wp, FALSE);
if (redraw_tabline)
draw_tabline();
+
+#if defined(FEAT_TABPANEL)
+ if (redraw_tabpanel)
+ draw_tabpanel();
+#endif
}
/*
diff --git a/src/edit.c b/src/edit.c
index 3c98bb8..4d45e8e 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -1714,7 +1714,7 @@
if (fix_col != pc_col)
{
- screen_putchar(' ', pc_row, fix_col, attr);
+ screen_putchar(' ', pc_row, fix_col + TPL_LCOL(NULL), attr);
--curwin->w_wcol;
pc_status = PC_STATUS_RIGHT;
}
@@ -1734,7 +1734,7 @@
screen_getbytes(pc_row, pc_col, pc_bytes, &pc_attr);
pc_status = PC_STATUS_SET;
}
- screen_putchar(c, pc_row, pc_col, attr);
+ screen_putchar(c, pc_row, pc_col + TPL_LCOL(NULL), attr);
}
#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
diff --git a/src/errors.h b/src/errors.h
index d718507..eddfc1b 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -3730,3 +3730,5 @@
#endif
EXTERN char e_cannot_switch_to_a_closing_buffer[]
INIT(= N_("E1546: Cannot switch to a closing buffer"));
+EXTERN char e_cannot_not_support_redrawtabpanel[]
+ INIT(= N_("E1547: This version of Vim does support :redrawtabpanel"));
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 74afd9d..76955a7 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -7415,6 +7415,13 @@
0
#endif
},
+ {"tabpanel",
+#if defined(FEAT_TABPANEL)
+ 1,
+#else
+ 0,
+#endif
+ },
{"tag_binary", 1}, // graduated feature
{"tcl",
#if defined(FEAT_TCL) && !defined(DYNAMIC_TCL)
diff --git a/src/ex_cmdidxs.h b/src/ex_cmdidxs.h
index 609a81d..1f01c2f 100644
--- a/src/ex_cmdidxs.h
+++ b/src/ex_cmdidxs.h
@@ -23,14 +23,14 @@
/* p */ 341,
/* q */ 382,
/* r */ 385,
- /* s */ 405,
- /* t */ 475,
- /* u */ 522,
- /* v */ 533,
- /* w */ 554,
- /* x */ 568,
- /* y */ 578,
- /* z */ 579
+ /* s */ 406,
+ /* t */ 476,
+ /* u */ 523,
+ /* v */ 534,
+ /* w */ 555,
+ /* x */ 569,
+ /* y */ 579,
+ /* z */ 580
};
/*
@@ -58,7 +58,7 @@
/* o */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 5, 0, 0, 0, 0, 0, 0, 9, 0, 11, 0, 0, 0 },
/* p */ { 1, 3, 4, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 10, 0, 0, 17, 18, 27, 0, 29, 0, 30, 0 },
/* q */ { 2, 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 },
- /* r */ { 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 19, 0, 0, 0, 0 },
+ /* r */ { 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 20, 0, 0, 0, 0 },
/* s */ { 2, 6, 15, 0, 19, 23, 0, 25, 26, 0, 0, 29, 31, 35, 39, 41, 0, 50, 0, 51, 0, 64, 65, 0, 66, 0 },
/* t */ { 2, 0, 19, 0, 24, 26, 0, 27, 0, 29, 0, 30, 34, 37, 39, 40, 0, 41, 43, 0, 44, 0, 0, 0, 46, 0 },
/* u */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 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 = 596;
+static const int command_count = 597;
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index 4eb67e3..d3d757b 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -1854,6 +1854,9 @@
if (rename_buffer(eap->arg) == FAIL)
return;
redraw_tabline = TRUE;
+#if defined(FEAT_TABPANEL)
+ redraw_tabpanel = TRUE;
+#endif
}
// print file name if no argument or 'F' is not in 'shortmess'
@@ -2100,6 +2103,9 @@
{
curbuf->b_p_ro = FALSE;
redraw_tabline = TRUE;
+#if defined(FEAT_TABPANEL)
+ redraw_tabpanel = TRUE;
+#endif
}
}
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index 0659f87..fb8d62f 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -1292,6 +1292,9 @@
EXCMD(CMD_redrawtabline, "redrawtabline", ex_redrawtabline,
EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
ADDR_NONE),
+EXCMD(CMD_redrawtabpanel, "redrawtabpanel", ex_redrawtabpanel,
+ EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
+ ADDR_NONE),
EXCMD(CMD_registers, "registers", ex_display,
EX_EXTRA|EX_NOTRLCOM|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
ADDR_NONE),
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index b87e3c7..a929465 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -247,6 +247,7 @@
static void ex_redir(exarg_T *eap);
static void ex_redrawstatus(exarg_T *eap);
static void ex_redrawtabline(exarg_T *eap);
+static void ex_redrawtabpanel(exarg_T *eap);
static void close_redir(void);
static void ex_mark(exarg_T *eap);
static void ex_startinsert(exarg_T *eap);
@@ -8233,7 +8234,7 @@
{
n = W_WINROW(curwin) + curwin->w_wrow - msg_scrolled;
if (n >= 0)
- windgoto(n, curwin->w_wincol + curwin->w_wcol);
+ windgoto(n, curwin->w_wincol + curwin->w_wcol + TPL_LCOL(curwin));
}
len = eap->line2;
@@ -8992,6 +8993,29 @@
out_flush();
}
+/*
+ * ":redrawtabpanel": force redraw of the tabpanel
+ */
+ static void
+ex_redrawtabpanel(exarg_T *eap UNUSED)
+{
+ int save_RedrawingDisabled = RedrawingDisabled;
+ RedrawingDisabled = 0;
+
+ int save_p_lz = p_lz;
+ p_lz = FALSE;
+
+#if defined(FEAT_TABPANEL)
+ draw_tabpanel();
+#else
+ emsg(_(e_cannot_not_support_redrawtabpanel));
+#endif
+
+ RedrawingDisabled = save_RedrawingDisabled;
+ p_lz = save_p_lz;
+ out_flush();
+}
+
static void
close_redir(void)
{
diff --git a/src/feature.h b/src/feature.h
index 703a72f..56d1958 100644
--- a/src/feature.h
+++ b/src/feature.h
@@ -524,6 +524,13 @@
#endif
/*
+ * +tabpanel Tab SideBar
+ */
+#ifdef FEAT_HUGE
+# define FEAT_TABPANEL
+#endif
+
+/*
* +browse ":browse" command.
* or just the ":browse" command modifier
*/
diff --git a/src/fileio.c b/src/fileio.c
index f6e35ab..2c6c40e 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -3534,6 +3534,9 @@
}
status_redraw_all();
redraw_tabline = TRUE;
+#if defined(FEAT_TABPANEL)
+ redraw_tabpanel = TRUE;
+#endif
#if defined(FEAT_PROP_POPUP) && defined(FEAT_QUICKFIX)
popup_update_preview_title();
#endif
diff --git a/src/globals.h b/src/globals.h
index 7006364..f143c8f 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1056,6 +1056,10 @@
EXTERN tabpage_T *lastused_tabpage;
EXTERN int redraw_tabline INIT(= FALSE); // need to redraw tabline
+#if defined(FEAT_TABPANEL)
+EXTERN int redraw_tabpanel INIT(= FALSE); // need to redraw tabpanel
+#endif
+
/*
* All buffers are linked in a list. 'firstbuf' points to the first entry,
* 'lastbuf' to the last entry and 'curbuf' to the currently active buffer.
diff --git a/src/gui.c b/src/gui.c
index 7b61381..41647d6 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -4906,6 +4906,9 @@
row = Y_2_ROW(y);
col = X_2_COL(x);
+
+ col -= TPL_LCOL(NULL);
+
if (row < 0 || col < 0) // before first window
return NULL;
wp = mouse_find_win(&row, &col, popup);
@@ -5376,6 +5379,8 @@
int col = X_2_COL(x);
win_T *wp;
+ col -= TPL_LCOL(NULL);
+
if (row < 0 || col < 0)
return;
diff --git a/src/highlight.c b/src/highlight.c
index 6567035..807753a 100644
--- a/src/highlight.c
+++ b/src/highlight.c
@@ -249,6 +249,9 @@
"TabLineSel term=bold cterm=bold gui=bold"),
CENT("TabLineFill term=reverse cterm=reverse",
"TabLineFill term=reverse cterm=reverse gui=reverse"),
+ "default link TabPanel TabLine",
+ "default link TabPanelSel TabLineSel",
+ "default link TabPanelFill TabLineFill",
#ifdef FEAT_GUI
"Cursor guibg=fg guifg=bg",
"lCursor guibg=fg guifg=bg", // should be different, but what?
diff --git a/src/misc2.c b/src/misc2.c
index 909812c..7912577 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -1879,6 +1879,9 @@
// This may cause the buffer to become (un)modified.
check_status(curbuf);
redraw_tabline = TRUE;
+#if defined(FEAT_TABPANEL)
+ redraw_tabpanel = TRUE;
+#endif
need_maketitle = TRUE; // set window title later
}
diff --git a/src/mouse.c b/src/mouse.c
index 4e10e72..65540e5 100644
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -232,6 +232,9 @@
int moved; // Has cursor moved?
int in_status_line; // mouse in status line
static int in_tab_line = FALSE; // mouse clicked in tab line
+#if defined(FEAT_TABPANEL)
+ static int in_tabpanel = FALSE; // mouse clicked in tabpanel
+#endif
int in_sep_line; // mouse in vertical separator line
int c1, c2;
#if defined(FEAT_FOLDING)
@@ -342,9 +345,16 @@
if (!is_drag) // release, reset got_click
{
got_click = FALSE;
- if (in_tab_line)
+ if (in_tab_line
+#if defined(FEAT_TABPANEL)
+ || in_tabpanel
+#endif
+ )
{
in_tab_line = FALSE;
+#if defined(FEAT_TABPANEL)
+ in_tabpanel = FALSE;
+#endif
return FALSE;
}
}
@@ -469,6 +479,78 @@
start_visual.lnum = 0;
+ // Check for clicking in the tab page line.
+#if defined(FEAT_TABPANEL)
+ if (mouse_col < TPL_LCOL(NULL))
+ {
+ if (is_drag)
+ {
+ if (in_tabpanel)
+ {
+ c1 = get_tabpagenr_on_tabpanel();
+ tabpage_move(c1 <= 0 ? 9999 : c1 < tabpage_index(curtab)
+ ? c1 - 1 : c1);
+ }
+ return FALSE;
+ }
+
+ // click in a tab selects that tab page
+ if (is_click
+# ifdef FEAT_CMDWIN
+ && cmdwin_type == 0
+# endif
+ && mouse_col < Columns)
+ {
+ in_tabpanel = TRUE;
+ c1 = get_tabpagenr_on_tabpanel();
+ if (c1 >= 0)
+ {
+ if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
+ {
+ // double click opens new page
+ end_visual_mode();
+ tabpage_new();
+ tabpage_move(c1 == 0 ? 9999 : c1 - 1);
+ }
+ else
+ {
+ // Go to specified tab page, or next one if not clicking
+ // on a label.
+ goto_tabpage(c1);
+
+ // It's like clicking on the status line of a window.
+ if (curwin != old_curwin)
+ end_visual_mode();
+ }
+ }
+ else
+ {
+ tabpage_T *tp;
+
+ // Close the current or specified tab page.
+ if (c1 == -999)
+ tp = curtab;
+ else
+ tp = find_tabpage(-c1);
+ if (tp == curtab)
+ {
+ if (first_tabpage->tp_next != NULL)
+ tabpage_close(FALSE);
+ }
+ else if (tp != NULL)
+ tabpage_close_other(tp, FALSE);
+ }
+ }
+ return TRUE;
+ }
+ else if (is_drag && in_tabpanel)
+ {
+ c1 = get_tabpagenr_on_tabpanel();
+ tabpage_move(c1 <= 0 ? 9999 : c1 - 1);
+ return FALSE;
+ }
+#endif
+
if (TabPageIdxs != NULL) // only when initialized
{
// Check for clicking in the tab page line.
@@ -1643,6 +1725,10 @@
int mouse_char = ' ';
#endif
+ col -= TPL_LCOL(NULL);
+ if (col < 0)
+ return IN_TABPANEL;
+
mouse_past_bottom = FALSE;
mouse_past_eol = FALSE;
@@ -1727,7 +1813,7 @@
if (!(flags & MOUSE_FOCUS))
{
- if (row < 0 || col < 0) // check if it makes sense
+ if (row < 0 || col + TPL_LCOL(NULL) < 0) // check if it makes sense
return IN_UNKNOWN;
// find the window where the row is in and adjust "row" and "col" to be
@@ -3247,6 +3333,9 @@
winid = wp->w_id;
winrow = row + 1;
wincol = col + 1;
+ wincol -= TPL_LCOL(NULL);
+ if (wincol < 0)
+ wincol = 0;
row -= top_off;
col -= left_off;
if (row >= 0 && row < wp->w_height && col >= 0 && col < wp->w_width)
diff --git a/src/netbeans.c b/src/netbeans.c
index 5cbbab7..4f53785 100644
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -1747,6 +1747,9 @@
{
check_status(buf->bufp);
redraw_tabline = TRUE;
+#if defined(FEAT_TABPANEL)
+ redraw_tabpanel = TRUE;
+#endif
maketitle();
update_screen(0);
}
diff --git a/src/option.c b/src/option.c
index ab9ee66..d6a0098 100644
--- a/src/option.c
+++ b/src/option.c
@@ -3107,6 +3107,9 @@
{
need_maketitle = TRUE;
redraw_tabline = TRUE;
+#if defined(FEAT_TABPANEL)
+ redraw_tabpanel = TRUE;
+#endif
}
/*
@@ -8832,6 +8835,18 @@
#endif
}
+#if defined(FEAT_TABPANEL)
+/*
+ * Process the new 'showtabpanel' option value.
+ */
+ char *
+did_set_showtabpanel(optset_T *args)
+{
+ shell_new_columns();
+ return NULL;
+}
+#endif
+
#if defined(FEAT_EVAL) || defined(PROTO)
static void
didset_options_sctx(int opt_flags, char **buf)
diff --git a/src/option.h b/src/option.h
index bb1226e..e78a7cb 100644
--- a/src/option.h
+++ b/src/option.h
@@ -984,7 +984,15 @@
#define SWB_NEWTAB 0x008
#define SWB_VSPLIT 0x010
#define SWB_USELAST 0x020
+
EXTERN char_u *p_spk; // 'splitkeep'
+
+#if defined(FEAT_TABPANEL)
+EXTERN char_u *p_tpl; // 'tabpanel'
+EXTERN long p_stpl; // 'showtabpanel'
+EXTERN char_u *p_tplo; // 'tabpanelopt'
+#endif
+
#ifdef FEAT_SYN_HL
EXTERN char_u *p_syn; // 'syntax'
#endif
diff --git a/src/optiondefs.h b/src/optiondefs.h
index f035104..d509463 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -305,7 +305,7 @@
# define ISP_LATIN1 (char_u *)"@,161-255"
#endif
-# define HIGHLIGHT_INIT "8:SpecialKey,~:EndOfBuffer,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,y:CurSearch,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow,N:CursorLineNr,G:CursorLineSign,O:CursorLineFold,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,E:DiffTextAdd,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,k:PmenuMatch,<:PmenuMatchSel,[:PmenuKind,]:PmenuKindSel,{:PmenuExtra,}:PmenuExtraSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine,z:StatusLineTerm,Z:StatusLineTermNC,g:MsgArea,h:ComplMatchIns"
+# define HIGHLIGHT_INIT "8:SpecialKey,~:EndOfBuffer,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,y:CurSearch,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow,N:CursorLineNr,G:CursorLineSign,O:CursorLineFold,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,E:DiffTextAdd,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,k:PmenuMatch,<:PmenuMatchSel,[:PmenuKind,]:PmenuKindSel,{:PmenuExtra,}:PmenuExtraSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine,z:StatusLineTerm,Z:StatusLineTermNC,g:MsgArea,h:ComplMatchIns,%:TabPanel,^:TabPanelSel,&:TabPanelFill"
// Default python version for pyx* commands
#if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
@@ -2368,6 +2368,11 @@
{"showtabline", "stal", P_NUM|P_VI_DEF|P_RALL,
(char_u *)&p_stal, PV_NONE, did_set_showtabline, NULL,
{(char_u *)1L, (char_u *)0L} SCTX_INIT},
+#if defined(FEAT_TABPANEL)
+ {"showtabpanel", "stpl", P_NUM|P_RALL,
+ (char_u *)&p_stpl, PV_NONE, did_set_showtabpanel, NULL,
+ {(char_u *)0L, (char_u *)0L} SCTX_INIT},
+#endif
{"sidescroll", "ss", P_NUM|P_VI_DEF,
(char_u *)&p_ss, PV_NONE, NULL, NULL,
{(char_u *)0L, (char_u *)0L} SCTX_INIT},
@@ -2527,6 +2532,16 @@
{"tabpagemax", "tpm", P_NUM|P_VI_DEF,
(char_u *)&p_tpm, PV_NONE, NULL, NULL,
{(char_u *)10L, (char_u *)0L} SCTX_INIT},
+#if defined(FEAT_TABPANEL)
+ {"tabpanel", "tpl", P_STRING|P_VI_DEF|P_RALL,
+ (char_u *)&p_tpl, PV_NONE, NULL, NULL,
+ {(char_u *)"", (char_u *)0L} SCTX_INIT},
+ {"tabpanelopt","tplo", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
+ (char_u *)&p_tplo, PV_NONE, did_set_tabpanelopt,
+ expand_set_tabpanelopt,
+ {(char_u *)"", (char_u *)0L}
+ SCTX_INIT},
+#endif
{"tabstop", "ts", P_NUM|P_VI_DEF|P_RBUF,
(char_u *)&p_ts, PV_TS,
did_set_shiftwidth_tabstop, NULL,
diff --git a/src/optionstr.c b/src/optionstr.c
index ce57cb4..8e233e8 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -28,6 +28,9 @@
// Note: Keep this in sync with briopt_check()
static char *(p_briopt_values[]) = {"shift:", "min:", "sbr", "list:", "column:", NULL};
#endif
+#if defined(FEAT_TABPANEL)
+static char *(p_tpl_values[]) = {"wrap", "align:", "columns:", "vert:", NULL};
+#endif
#if defined(FEAT_DIFF)
// Note: Keep this in sync with diffopt_changed()
static char *(p_dip_values[]) = {"filler", "context:", "iblank", "icase", "iwhite", "iwhiteall", "iwhiteeol", "horizontal", "vertical", "closeoff", "hiddenoff", "foldcolumn:", "followwrap", "internal", "indent-heuristic", "algorithm:", "inline:", "linematch:", NULL};
@@ -3547,6 +3550,33 @@
}
#endif
+#if defined(FEAT_TABPANEL)
+/*
+ * Process the new 'tabpanelopt' option value.
+ */
+ char *
+did_set_tabpanelopt(optset_T *args)
+{
+ if (tabpanelopt_changed() == FAIL)
+ return e_invalid_argument;
+
+ shell_new_columns();
+
+ return NULL;
+}
+
+ int
+expand_set_tabpanelopt(optexpand_T *args, int *numMatches, char_u ***matches)
+{
+ return expand_set_opt_string(
+ args,
+ p_tpl_values,
+ ARRAY_LENGTH(p_tpl_values) - 1,
+ numMatches,
+ matches);
+}
+#endif
+
/*
* The 'scrollopt' option is changed.
*/
diff --git a/src/popupmenu.c b/src/popupmenu.c
index 4aaddaf..d629049 100644
--- a/src/popupmenu.c
+++ b/src/popupmenu.c
@@ -656,22 +656,24 @@
width = cells + over_cell + 1;
rt = orig_rt;
- screen_putchar(truncrl, row, col - width + 1, attr);
+ screen_putchar(truncrl, row, col - width + 1 + TPL_LCOL(NULL), attr);
if (over_cell > 0)
- screen_fill(row, row + 1, col - width + 2,
- col - width + 2 + over_cell, ' ', ' ', attr);
+ screen_fill(row, row + 1, col - width + 2 + TPL_LCOL(NULL),
+ col - width + 2 + over_cell + TPL_LCOL(NULL), ' ', ' ',
+ attr);
}
if (attrs == NULL)
- screen_puts_len(rt, (int)STRLEN(rt), row, col - cells + 1, attr);
+ screen_puts_len(rt, (int)STRLEN(rt), row,
+ col - cells + 1 + TPL_LCOL(NULL), attr);
else
- pum_screen_puts_with_attrs(row, col - cells + 1, cells, rt,
- (int)STRLEN(rt), attrs);
+ pum_screen_puts_with_attrs(row, col - cells + 1 + TPL_LCOL(NULL),
+ cells, rt, (int)STRLEN(rt), attrs);
vim_free(rt_start);
VIM_CLEAR(st);
- return col - width;
+ return col - width + TPL_LCOL(NULL);
}
#endif
@@ -743,17 +745,18 @@
}
if (attrs == NULL)
- screen_puts_len(st, size, row, col, attr);
+ screen_puts_len(st, size, row, col + TPL_LCOL(NULL), attr);
else
- pum_screen_puts_with_attrs(row, col, cells, st, size, attrs);
+ pum_screen_puts_with_attrs(row, col + TPL_LCOL(NULL), cells, st, size,
+ attrs);
if (truncated)
{
if (over_cell > 0)
- screen_fill(row, row + 1, col + cells,
- col + cells + over_cell, ' ', ' ', attr);
+ screen_fill(row, row + 1, col + cells + TPL_LCOL(NULL),
+ col + cells + over_cell + TPL_LCOL(NULL), ' ', ' ', attr);
- screen_putchar(trunc, row, col + cells + over_cell, attr);
+ screen_putchar(trunc, row, col + cells + over_cell + TPL_LCOL(NULL), attr);
}
VIM_CLEAR(st);
@@ -863,10 +866,10 @@
#ifdef FEAT_RIGHTLEFT
if (pum_rl)
- screen_putchar(' ', row, pum_col - pum_width, attr);
+ screen_putchar(' ', row, pum_col - pum_width + TPL_LCOL(NULL), attr);
else
#endif
- screen_putchar(' ', row, pum_col + pum_width, attr);
+ screen_putchar(' ', row, pum_col + pum_width + TPL_LCOL(NULL), attr);
}
/*
@@ -949,12 +952,12 @@
if (pum_rl)
{
if (pum_col < curwin->w_wincol + curwin->w_width - 1)
- screen_putchar(' ', row, pum_col + 1, attr);
+ screen_putchar(' ', row, pum_col + 1 + TPL_LCOL(NULL), attr);
}
else
#endif
if (pum_col > 0)
- screen_putchar(' ', row, pum_col - 1, attr);
+ screen_putchar(' ', row, pum_col - 1 + TPL_LCOL(NULL), attr);
// Display each entry, use two spaces for a Tab.
// Do this 3 times and order from p_cia
@@ -995,15 +998,16 @@
#ifdef FEAT_RIGHTLEFT
if (pum_rl)
{
- screen_fill(row, row + 1, pum_col - basic_width - n + 1,
- col + 1, ' ', ' ', orig_attr);
+ screen_fill(row, row + 1, pum_col - basic_width - n + 1 + TPL_LCOL(NULL),
+ col + 1 + TPL_LCOL(NULL), ' ', ' ', orig_attr);
col = pum_col - basic_width - n;
}
else
#endif
{
- screen_fill(row, row + 1, col, pum_col + basic_width + n,
- ' ', ' ', orig_attr);
+ screen_fill(row, row + 1, col + TPL_LCOL(NULL),
+ pum_col + basic_width + n + TPL_LCOL(NULL), ' ', ' ',
+ orig_attr);
col = pum_col + basic_width + n;
}
totwidth = basic_width + n;
@@ -1011,12 +1015,14 @@
#ifdef FEAT_RIGHTLEFT
if (pum_rl)
- screen_fill(row, row + 1, pum_col - pum_width + 1, col + 1, ' ',
- ' ', orig_attr);
+ screen_fill(row, row + 1,
+ pum_col - pum_width + 1 + TPL_LCOL(NULL),
+ col + 1 + TPL_LCOL(NULL), ' ', ' ', orig_attr);
else
#endif
- screen_fill(row, row + 1, col, pum_col + pum_width, ' ', ' ',
- orig_attr);
+ screen_fill(row, row + 1, col + TPL_LCOL(NULL),
+ pum_col + pum_width + TPL_LCOL(NULL),
+ ' ', ' ', orig_attr);
pum_draw_scrollbar(row, i, thumb_pos, thumb_height);
++row;
@@ -1396,6 +1402,9 @@
pum_array = NULL;
redraw_all_later(UPD_NOT_VALID);
redraw_tabline = TRUE;
+#if defined(FEAT_TABPANEL)
+ redraw_tabpanel = TRUE;
+#endif
if (pum_in_cmdline)
{
clear_cmdline = TRUE;
diff --git a/src/popupwin.c b/src/popupwin.c
index 60a54d7..a9a2843 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -86,7 +86,7 @@
if (STRCMP(key, "line") == 0)
n = screen_screenrow() + 1 + n;
else // "col"
- n = screen_screencol() + 1 + n;
+ n = screen_screencol() + 1 + n - TPL_LCOL(NULL);
// Zero means "not set", use -1 instead.
if (n == 0)
@@ -1545,7 +1545,7 @@
}
if (center_hor)
{
- wp->w_wincol = (Columns - wp->w_width - extra_width) / 2;
+ wp->w_wincol = (Columns - wp->w_width - extra_width - TPL_LCOL(NULL)) / 2;
if (wp->w_wincol < 0)
wp->w_wincol = 0;
}
@@ -4081,7 +4081,7 @@
// win_update() doesn't handle them.
top_off = popup_top_extra(wp);
left_extra = wp->w_popup_padding[3] + wp->w_popup_border[3]
- - wp->w_popup_leftoff;
+ + TPL_LCOL(NULL) - wp->w_popup_leftoff;
if (wp->w_wincol + left_extra < 0)
left_extra = -wp->w_wincol;
wp->w_winrow += top_off;
@@ -4163,7 +4163,7 @@
}
// Title goes on top of border or padding.
- title_wincol = wp->w_wincol + 1;
+ title_wincol = wp->w_wincol + 1 + TPL_LCOL(NULL);
if (wp->w_popup_title != NULL)
{
title_len = vim_strsize(wp->w_popup_title);
@@ -4191,7 +4191,7 @@
wp->w_popup_border[0] > 0 ? border_attr[0] : popup_attr);
}
- wincol = wp->w_wincol - wp->w_popup_leftoff;
+ wincol = wp->w_wincol - wp->w_popup_leftoff + TPL_LCOL(NULL);
top_padding = wp->w_popup_padding[0];
if (wp->w_popup_border[0] > 0)
{
@@ -4229,7 +4229,7 @@
{
padcol = wincol + wp->w_popup_border[3];
padendcol = wp->w_wincol + total_width - wp->w_popup_border[1]
- - wp->w_has_scrollbar;
+ + TPL_LCOL(NULL) - wp->w_has_scrollbar;
if (padcol < 0)
{
padendcol += padcol;
@@ -4327,7 +4327,7 @@
if (wp->w_has_scrollbar)
{
int line = i - top_off;
- int scroll_col = wp->w_wincol + total_width - 1
+ int scroll_col = wp->w_wincol + total_width - 1 + TPL_LCOL(NULL)
- wp->w_popup_border[1];
if (line >= 0 && line < wp->w_height)
diff --git a/src/proto.h b/src/proto.h
index a5ca9e4..8282dc3 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -123,6 +123,9 @@
# ifdef FEAT_VIMINFO
# include "viminfo.pro"
# endif
+# ifdef FEAT_TABPANEL
+# include "tabpanel.pro"
+# endif
// These prototypes cannot be produced automatically.
int smsg(const char *, ...) ATTRIBUTE_COLD ATTRIBUTE_FORMAT_PRINTF(1, 2);
diff --git a/src/proto/option.pro b/src/proto/option.pro
index c6dfc1b..f9ae7c4 100644
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -1,4 +1,5 @@
/* option.c */
+char *did_set_showtabpanel(optset_T *args);
void set_init_1(int clean_arg);
void set_fencs_unicode(void);
void set_string_default(char *name, char_u *val);
diff --git a/src/proto/optionstr.pro b/src/proto/optionstr.pro
index 4c4ec3e..84dd1fb 100644
--- a/src/proto/optionstr.pro
+++ b/src/proto/optionstr.pro
@@ -1,4 +1,6 @@
/* optionstr.c */
+char *did_set_tabpanelopt(optset_T *args);
+int expand_set_tabpanelopt(optexpand_T *args, int *numMatches, char_u ***matches);
void didset_string_options(void);
void trigger_optionset_string(int opt_idx, int opt_flags, char_u *oldval, char_u *oldval_l, char_u *oldval_g, char_u *newval);
void check_buf_options(buf_T *buf);
diff --git a/src/proto/tabpanel.pro b/src/proto/tabpanel.pro
new file mode 100644
index 0000000..3cbaa2f
--- /dev/null
+++ b/src/proto/tabpanel.pro
@@ -0,0 +1,7 @@
+/* tabpanel.c */
+int tabpanel_width(void);
+int tabpanel_leftcol(win_T *wp);
+int tabpanelopt_changed(void);
+void draw_tabpanel(void);
+int get_tabpagenr_on_tabpanel(void);
+/* vim: set ft=c : */
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 = '<';
}
diff --git a/src/structs.h b/src/structs.h
index 1cb70b8..cd7370d 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -3851,6 +3851,9 @@
int diff;
int eob;
int lastline;
+#if defined(FEAT_TABPANEL)
+ int tpl_vert;
+#endif
int trunc;
int truncrl;
} fill_chars_T;
diff --git a/src/tabpanel.c b/src/tabpanel.c
new file mode 100644
index 0000000..f4bed4b
--- /dev/null
+++ b/src/tabpanel.c
@@ -0,0 +1,660 @@
+/* vi:set ts=8 sts=4 sw=4 noet:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+/*
+ * tabpanel.c:
+ */
+
+#include "vim.h"
+
+#if defined(FEAT_TABPANEL) || defined(PROTO)
+
+static void do_by_tplmode(int tplmode, int col_start, int col_end,
+ int* pcurtab_row, int* ptabpagenr);
+
+// set pcurtab_row. don't redraw tabpanel.
+#define TPLMODE_GET_CURTAB_ROW 0
+// set ptabpagenr. don't redraw tabpanel.
+#define TPLMODE_GET_TABPAGENR 1
+// redraw tabpanel.
+#define TPLMODE_REDRAW 2
+
+#define TPL_FILLCHAR ' '
+
+#define VERT_LEN 1
+
+// tpl_vert's values
+#define VERT_OFF 0
+#define VERT_ON 1
+
+// tpl_align's values
+#define ALIGN_LEFT 0
+#define ALIGN_RIGHT 1
+
+static char_u *opt_name = (char_u *)"tabpanel";
+static int opt_scope = OPT_LOCAL;
+static int tpl_align = ALIGN_LEFT;
+static int tpl_columns = 20;
+static int tpl_vert = VERT_OFF;
+
+typedef struct {
+ win_T *wp;
+ win_T *cwp;
+ char_u *user_defined;
+ int maxrow;
+ int offsetrow;
+ int *prow;
+ int *pcol;
+ int attr;
+ int col_start;
+ int col_end;
+} tabpanel_T;
+
+ int
+tabpanelopt_changed(void)
+{
+ char_u *p;
+ int new_align = ALIGN_LEFT;
+ int new_columns = 20;
+ int new_vert = VERT_OFF;
+
+ p = p_tplo;
+ while (*p != NUL)
+ {
+ if (STRNCMP(p, "align:left", 10) == 0)
+ {
+ p += 10;
+ new_align = ALIGN_LEFT;
+ }
+ else if (STRNCMP(p, "align:right", 11) == 0)
+ {
+ p += 11;
+ new_align = ALIGN_RIGHT;
+ }
+ else if (STRNCMP(p, "columns:", 8) == 0 && VIM_ISDIGIT(p[8]))
+ {
+ p += 8;
+ new_columns = getdigits(&p);
+ }
+ else if (STRNCMP(p, "vert", 4) == 0)
+ {
+ p += 4;
+ new_vert = VERT_ON;
+ }
+
+ if (*p != ',' && *p != NUL)
+ return FAIL;
+ if (*p == ',')
+ ++p;
+ }
+
+ tpl_align = new_align;
+ tpl_columns = new_columns;
+ tpl_vert = new_vert;
+
+ return OK;
+}
+
+/*
+ * Return the width of tabpanel.
+ */
+ int
+tabpanel_width(void)
+{
+ if (msg_scrolled != 0)
+ return 0;
+
+ switch (p_stpl)
+ {
+ case 0:
+ return 0;
+ case 1:
+ if (first_tabpage->tp_next == NULL)
+ return 0;
+ }
+ if (Columns < tpl_columns)
+ return 0;
+ else
+ return tpl_columns;
+}
+
+/*
+ * Return the offset of a window considering the width of tabpanel.
+ */
+ int
+tabpanel_leftcol(win_T *wp)
+{
+ if (cmdline_pum_active())
+ return 0;
+ else if (wp != NULL && WIN_IS_POPUP(wp))
+ return 0;
+ else
+ return tpl_align == ALIGN_RIGHT ? 0 : tabpanel_width();
+}
+
+/*
+ * draw the tabpanel.
+ */
+ void
+draw_tabpanel(void)
+{
+ int saved_KeyTyped = KeyTyped;
+ int saved_got_int = got_int;
+ int maxwidth = tabpanel_width();
+ int vs_attr = HL_ATTR(HLF_C);
+ int curtab_row = 0;
+#ifndef MSWIN
+ int row = 0;
+ int off = 0;
+#endif
+int vsrow = 0;
+ int is_right = tpl_align == ALIGN_RIGHT;
+
+ if (0 == maxwidth)
+ return;
+
+#ifndef MSWIN
+ // We need this section only for the Vim running on WSL.
+ for (row = 0; row < cmdline_row; row++)
+ {
+ if (is_right)
+ off = LineOffset[row] + Columns - maxwidth;
+ else
+ off = LineOffset[row];
+
+ vim_memset(ScreenLines + off, ' ',
+ (size_t)maxwidth * sizeof(schar_T));
+ if (enc_utf8)
+ vim_memset(ScreenLinesUC + off, -1,
+ (size_t)maxwidth * sizeof(u8char_T));
+ }
+#endif
+
+ // Reset got_int to avoid build_stl_str_hl() isn't evaluted.
+ got_int = FALSE;
+
+ if (tpl_vert == VERT_ON)
+ {
+ if (is_right)
+ {
+ // draw main contents in tabpanel
+ do_by_tplmode(TPLMODE_GET_CURTAB_ROW, VERT_LEN,
+ maxwidth - VERT_LEN, &curtab_row, NULL);
+ do_by_tplmode(TPLMODE_REDRAW, VERT_LEN, maxwidth, &curtab_row,
+ NULL);
+ // clear for multi-byte vert separater
+ screen_fill(0, cmdline_row, COLUMNS_WITHOUT_TPL(),
+ COLUMNS_WITHOUT_TPL() + VERT_LEN,
+ TPL_FILLCHAR, TPL_FILLCHAR, vs_attr);
+ // draw vert separater in tabpanel
+ for (vsrow = 0; vsrow < cmdline_row; vsrow++)
+ screen_putchar(curwin->w_fill_chars.tpl_vert, vsrow,
+ COLUMNS_WITHOUT_TPL(), vs_attr);
+ }
+ else
+ {
+ // draw main contents in tabpanel
+ do_by_tplmode(TPLMODE_GET_CURTAB_ROW, 0, maxwidth - VERT_LEN,
+ &curtab_row, NULL);
+ do_by_tplmode(TPLMODE_REDRAW, 0, maxwidth - VERT_LEN,
+ &curtab_row, NULL);
+ // clear for multi-byte vert separater
+ screen_fill(0, cmdline_row, maxwidth - VERT_LEN,
+ maxwidth, TPL_FILLCHAR, TPL_FILLCHAR, vs_attr);
+ // draw vert separater in tabpanel
+ for (vsrow = 0; vsrow < cmdline_row; vsrow++)
+ screen_putchar(curwin->w_fill_chars.tpl_vert, vsrow,
+ maxwidth - VERT_LEN, vs_attr);
+ }
+ }
+ else
+ {
+ do_by_tplmode(TPLMODE_GET_CURTAB_ROW, 0, maxwidth, &curtab_row, NULL);
+ do_by_tplmode(TPLMODE_REDRAW, 0, maxwidth, &curtab_row, NULL);
+ }
+
+ got_int |= saved_got_int;
+
+ // A user function may reset KeyTyped, restore it.
+ KeyTyped = saved_KeyTyped;
+
+ redraw_tabpanel = FALSE;
+}
+
+/*
+ * Return tabpagenr when clicking and dragging in tabpanel.
+ */
+ int
+get_tabpagenr_on_tabpanel(void)
+{
+ int maxwidth = tabpanel_width();
+ int curtab_row = 0;
+ int tabpagenr = 0;
+
+ if (0 == maxwidth)
+ return -1;
+
+ do_by_tplmode(TPLMODE_GET_CURTAB_ROW, 0, maxwidth, &curtab_row, NULL);
+ do_by_tplmode(TPLMODE_GET_TABPAGENR, 0, maxwidth, &curtab_row,
+ &tabpagenr);
+
+ return tabpagenr;
+}
+
+/*
+ * Fill tailing area between {start_row} and {end_row - 1}.
+ */
+ static void
+screen_fill_tailing_area(
+ int tplmode,
+ int row_start,
+ int row_end,
+ int col_start,
+ int col_end,
+ int attr)
+{
+ int is_right = tpl_align == ALIGN_RIGHT;
+ if (TPLMODE_REDRAW == tplmode)
+ screen_fill(row_start, row_end,
+ (is_right ? COLUMNS_WITHOUT_TPL() : 0) + col_start,
+ (is_right ? COLUMNS_WITHOUT_TPL() : 0) + col_end,
+ TPL_FILLCHAR, TPL_FILLCHAR, attr);
+}
+
+/*
+ * screen_puts_len() for tabpanel.
+ */
+ static void
+screen_puts_len_for_tabpanel(
+ int tplmode,
+ char_u *p,
+ int len,
+ int attr,
+ tabpanel_T *pargs)
+{
+ int j, k;
+ int chlen;
+ int chcells;
+ char_u buf[IOSIZE];
+ char_u* temp;
+
+ for (j = 0; j < len;)
+ {
+ if ((TPLMODE_GET_CURTAB_ROW != tplmode)
+ && (pargs->maxrow <= (*pargs->prow - pargs->offsetrow)))
+ break;
+
+ if ((p[j] == '\n') || (p[j] == '\r'))
+ {
+ // fill the tailing area of current row.
+ if (0 <= (*pargs->prow - pargs->offsetrow)
+ && (*pargs->prow - pargs->offsetrow) < pargs->maxrow)
+ screen_fill_tailing_area(tplmode,
+ *pargs->prow - pargs->offsetrow,
+ *pargs->prow - pargs->offsetrow + 1,
+ *pargs->pcol, pargs->col_end, attr);
+ (*pargs->prow)++;
+ *pargs->pcol = pargs->col_start;
+ j++;
+ }
+ else
+ {
+ if (has_mbyte)
+ chlen = (*mb_ptr2len)(p + j);
+ else
+ chlen = (int)STRLEN(p + j);
+
+ for (k = 0; k < chlen; k++)
+ buf[k] = p[j + k];
+ buf[chlen] = NUL;
+ j += chlen;
+
+ // Make all characters printable.
+ temp = transstr(buf);
+ if (temp != NULL)
+ {
+ vim_strncpy(buf, temp, sizeof(buf) - 1);
+ vim_free(temp);
+ }
+
+ if (has_mbyte)
+ chcells = (*mb_ptr2cells)(buf);
+ else
+ chcells = 1;
+
+ if (pargs->col_end < (*pargs->pcol) + chcells)
+ {
+ // fill the tailing area of current row.
+ if (0 <= (*pargs->prow - pargs->offsetrow)
+ && (*pargs->prow - pargs->offsetrow) < pargs->maxrow)
+ screen_fill_tailing_area(tplmode,
+ *pargs->prow - pargs->offsetrow,
+ *pargs->prow - pargs->offsetrow + 1,
+ *pargs->pcol, pargs->col_end, attr);
+ *pargs->pcol = pargs->col_end;
+
+ if (pargs->col_end < chcells)
+ break;
+ }
+
+ if ((*pargs->pcol) + chcells <= pargs->col_end)
+ {
+ int off = (tpl_align == ALIGN_RIGHT)
+ ? COLUMNS_WITHOUT_TPL()
+ : 0;
+ if ((TPLMODE_REDRAW == tplmode)
+ && (0 <= (*pargs->prow - pargs->offsetrow)
+ && (*pargs->prow - pargs->offsetrow) < pargs->maxrow))
+ screen_puts(buf, *pargs->prow - pargs->offsetrow,
+ *pargs->pcol + off, attr);
+ (*pargs->pcol) += chcells;
+ }
+ }
+ }
+}
+
+/*
+ * default tabpanel drawing behavior if 'tabpanel' option is empty.
+ */
+ static void
+draw_tabpanel_default(int tplmode, tabpanel_T *pargs)
+{
+ int modified;
+ int wincount;
+ int len = 0;
+ char_u buf[2] = { NUL, NUL };
+
+ modified = FALSE;
+ for (wincount = 0; pargs->wp != NULL;
+ pargs->wp = pargs->wp->w_next, ++wincount)
+ if (bufIsChanged(pargs->wp->w_buffer))
+ modified = TRUE;
+
+ if (modified || 1 < wincount)
+ {
+ if (1 < wincount)
+ {
+ vim_snprintf((char *)NameBuff, MAXPATHL, "%d", wincount);
+ len = (int)STRLEN(NameBuff);
+ screen_puts_len_for_tabpanel(tplmode, NameBuff, len,
+#if defined(FEAT_SYN_HL)
+ hl_combine_attr(pargs->attr, HL_ATTR(HLF_T)),
+#else
+ pargs->attr,
+#endif
+ pargs);
+ }
+ if (modified)
+ {
+ buf[0] = '+';
+ screen_puts_len_for_tabpanel(tplmode, buf, 1, pargs->attr, pargs);
+ }
+
+ buf[0] = TPL_FILLCHAR;
+ screen_puts_len_for_tabpanel(tplmode, buf, 1, pargs->attr, pargs);
+ }
+
+ get_trans_bufname(pargs->cwp->w_buffer);
+ shorten_dir(NameBuff);
+ len = (int)STRLEN(NameBuff);
+ screen_puts_len_for_tabpanel(tplmode, NameBuff, len, pargs->attr, pargs);
+
+ // fill the tailing area of current row.
+ if (0 <= (*pargs->prow - pargs->offsetrow)
+ && (*pargs->prow - pargs->offsetrow) < pargs->maxrow)
+ screen_fill_tailing_area(tplmode, *pargs->prow - pargs->offsetrow,
+ *pargs->prow - pargs->offsetrow + 1,
+ *pargs->pcol, pargs->col_end, pargs->attr);
+ *pargs->pcol = pargs->col_end;
+}
+
+/*
+ * default tabpanel drawing behavior if 'tabpanel' option is NOT empty.
+ */
+ static void
+draw_tabpanel_userdefined(int tplmode, tabpanel_T *pargs)
+{
+ char_u *p;
+ int p_crb_save;
+ char_u buf[IOSIZE];
+ stl_hlrec_T *hltab;
+ stl_hlrec_T *tabtab;
+ int curattr;
+ int n;
+
+ // Temporarily reset 'cursorbind', we don't want a side effect from moving
+ // the cursor away and back.
+ p_crb_save = pargs->cwp->w_p_crb;
+ pargs->cwp->w_p_crb = FALSE;
+
+ // Make a copy, because the statusline may include a function call that
+ // might change the option value and free the memory.
+ p = vim_strsave(pargs->user_defined);
+
+ build_stl_str_hl(pargs->cwp, buf, sizeof(buf),
+ p, opt_name, opt_scope,
+ TPL_FILLCHAR, pargs->col_end - pargs->col_start, &hltab, &tabtab);
+
+ vim_free(p);
+ pargs->cwp->w_p_crb = p_crb_save;
+
+ curattr = pargs->attr;
+ p = buf;
+ for (n = 0; hltab[n].start != NULL; n++)
+ {
+ screen_puts_len_for_tabpanel(tplmode, p, (int)(hltab[n].start - p),
+ curattr, pargs);
+ p = hltab[n].start;
+ if (hltab[n].userhl == 0)
+ curattr = pargs->attr;
+ else if (hltab[n].userhl < 0)
+ curattr = syn_id2attr(-hltab[n].userhl);
+#ifdef FEAT_TERMINAL
+ else if (pargs->wp != NULL && pargs->wp != curwin
+ && bt_terminal(pargs->wp->w_buffer)
+ && pargs->wp->w_status_height != 0)
+ curattr = highlight_stltermnc[hltab[n].userhl - 1];
+ else if (pargs->wp != NULL && bt_terminal(pargs->wp->w_buffer)
+ && pargs->wp->w_status_height != 0)
+ curattr = highlight_stlterm[hltab[n].userhl - 1];
+#endif
+ else if (pargs->wp != NULL && pargs->wp != curwin
+ && pargs->wp->w_status_height != 0)
+ curattr = highlight_stlnc[hltab[n].userhl - 1];
+ else
+ curattr = highlight_user[hltab[n].userhl - 1];
+ }
+ screen_puts_len_for_tabpanel(tplmode, p, (int)STRLEN(p), curattr, pargs);
+
+ // fill the tailing area of current row.
+ if (0 <= (*pargs->prow - pargs->offsetrow)
+ && (*pargs->prow - pargs->offsetrow) < pargs->maxrow)
+ screen_fill_tailing_area(tplmode, *pargs->prow - pargs->offsetrow,
+ *pargs->prow - pargs->offsetrow + 1, *pargs->pcol,
+ pargs->col_end, curattr);
+ *pargs->pcol = pargs->col_end;
+}
+
+ static char_u *
+starts_with_percent_and_bang(tabpanel_T *pargs)
+{
+ int len = 0;
+ char_u *usefmt = p_tpl;
+
+ if (usefmt == NULL)
+ return NULL;
+
+ len = (int)STRLEN(usefmt);
+
+ if (len == 0)
+ return NULL;
+
+#ifdef FEAT_EVAL
+ // if "fmt" was set insecurely it needs to be evaluated in the sandbox
+ int use_sandbox = was_set_insecurely(opt_name, opt_scope);
+
+ // When the format starts with "%!" then evaluate it as an expression and
+ // use the result as the actual format string.
+ if (1 < len && usefmt[0] == '%' && usefmt[1] == '!')
+ {
+ typval_T tv;
+ char_u *p = NULL;
+
+ tv.v_type = VAR_NUMBER;
+ tv.vval.v_number = pargs->cwp->w_id;
+ set_var((char_u *)"g:tabpanel_winid", &tv, FALSE);
+
+ p = eval_to_string_safe(usefmt + 2, use_sandbox, FALSE, FALSE);
+ if (p != NULL)
+ usefmt = p;
+
+ do_unlet((char_u *)"g:tabpanel_winid", TRUE);
+ }
+#endif
+
+ return usefmt;
+}
+
+/*
+ * do something by tplmode for drawing tabpanel.
+ */
+ static void
+do_by_tplmode(
+ int tplmode,
+ int col_start,
+ int col_end,
+ int *pcurtab_row,
+ int *ptabpagenr)
+{
+ int attr_tplf = HL_ATTR(HLF_TPLF);
+ int attr_tpls = HL_ATTR(HLF_TPLS);
+ int attr_tpl = HL_ATTR(HLF_TPL);
+ int col = col_start;
+ int row = 0;
+ tabpage_T *tp = NULL;
+ typval_T v;
+ tabpanel_T args;
+
+ args.maxrow = cmdline_row;
+ args.offsetrow = 0;
+ args.col_start = col_start;
+ args.col_end = col_end;
+
+ if (TPLMODE_GET_CURTAB_ROW != tplmode)
+ if (0 < args.maxrow)
+ while (args.offsetrow + args.maxrow <= *pcurtab_row)
+ args.offsetrow += args.maxrow;
+
+ tp = first_tabpage;
+
+ for (row = 0; tp != NULL; row++)
+ {
+ if ((TPLMODE_GET_CURTAB_ROW != tplmode)
+ && (args.maxrow <= (row - args.offsetrow)))
+ break;
+
+ col = col_start;
+
+ v.v_type = VAR_NUMBER;
+ v.vval.v_number = tabpage_index(tp);
+ set_var((char_u *)"g:actual_curtabpage", &v, TRUE);
+
+ if (tp->tp_topframe == topframe)
+ {
+ args.attr = attr_tpls;
+ if (TPLMODE_GET_CURTAB_ROW == tplmode)
+ {
+ *pcurtab_row = row;
+ break;
+ }
+ }
+ else
+ args.attr = attr_tpl;
+
+ if (tp == curtab)
+ {
+ args.cwp = curwin;
+ args.wp = firstwin;
+ }
+ else
+ {
+ args.cwp = tp->tp_curwin;
+ args.wp = tp->tp_firstwin;
+ }
+
+ char_u* usefmt = starts_with_percent_and_bang(&args);
+ if (usefmt != NULL)
+ {
+ char_u buf[IOSIZE];
+ char_u *p = usefmt;
+ size_t i = 0;
+
+ while (p[i] != '\0')
+ {
+ while ((p[i] == '\n') || (p[i] == '\r'))
+ {
+ // fill the tailing area of current row.
+ if (0 <= (row - args.offsetrow)
+ && (row - args.offsetrow) < args.maxrow)
+ screen_fill_tailing_area(tplmode,
+ row - args.offsetrow,
+ row - args.offsetrow + 1,
+ col, args.col_end, args.attr);
+ row++;
+ col = col_start;
+ p++;
+ }
+
+ while ((p[i] != '\n') && (p[i] != '\r')
+ && (p[i] != '\0'))
+ {
+ if (i + 1 >= sizeof(buf))
+ break;
+ buf[i] = p[i];
+ i++;
+ }
+ buf[i] = '\0';
+
+ args.user_defined = buf;
+ args.prow = &row;
+ args.pcol = &col;
+ draw_tabpanel_userdefined(tplmode, &args);
+
+ p += i;
+ i = 0;
+ }
+ if (usefmt != p_tpl)
+ VIM_CLEAR(usefmt);
+ }
+ else
+ {
+ args.user_defined = NULL;
+ args.prow = &row;
+ args.pcol = &col;
+ draw_tabpanel_default(tplmode, &args);
+ }
+
+ do_unlet((char_u *)"g:actual_curtabpage", TRUE);
+
+ tp = tp->tp_next;
+
+ if ((TPLMODE_GET_TABPAGENR == tplmode)
+ && (mouse_row <= (row - args.offsetrow)))
+ {
+ *ptabpagenr = v.vval.v_number;
+ break;
+ }
+ }
+
+ // fill the area of TabPanelFill.
+ screen_fill_tailing_area(tplmode, row - args.offsetrow, args.maxrow,
+ args.col_start, args.col_end, attr_tplf);
+}
+
+#endif // FEAT_TABPANEL
diff --git a/src/term.c b/src/term.c
index 03bad0d..2d2c940 100644
--- a/src/term.c
+++ b/src/term.c
@@ -4454,9 +4454,16 @@
{
OUT_STR(tgoto((char *)T_CS, W_WINROW(wp) + wp->w_height - 1,
W_WINROW(wp) + off));
+#if defined(FEAT_TABPANEL)
+ if (*T_CSV != NUL)
+ OUT_STR(tgoto((char *)T_CSV,
+ wp->w_wincol + wp->w_width - 1 + TPL_LCOL(NULL),
+ wp->w_wincol + TPL_LCOL(NULL)));
+#else
if (*T_CSV != NUL && wp->w_width != Columns)
OUT_STR(tgoto((char *)T_CSV, wp->w_wincol + wp->w_width - 1,
wp->w_wincol));
+#endif
screen_start(); // don't know where cursor is now
}
@@ -4468,7 +4475,7 @@
{
OUT_STR(tgoto((char *)T_CS, (int)Rows - 1, 0));
if (*T_CSV != NUL)
- OUT_STR(tgoto((char *)T_CSV, (int)Columns - 1, 0));
+ OUT_STR(tgoto((char *)T_CSV, COLUMNS_WITHOUT_TPL() - 1, 0));
screen_start(); // don't know where cursor is now
}
diff --git a/src/terminal.c b/src/terminal.c
index 9f94825..a075840 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -1351,7 +1351,7 @@
// do not use the window cursor position
position_cursor(curwin, &curbuf->b_term->tl_cursor_pos);
windgoto(W_WINROW(curwin) + curwin->w_wrow,
- curwin->w_wincol + curwin->w_wcol);
+ curwin->w_wincol + curwin->w_wcol + TPL_LCOL(NULL));
}
if (redraw)
{
@@ -1430,6 +1430,10 @@
if (buffer == curbuf && (State & MODE_CMDLINE) == 0)
{
update_screen(UPD_VALID_NO_UPDATE);
+#if defined(FEAT_TABPANEL)
+ if (redraw_tabpanel)
+ draw_tabpanel();
+#endif
// update_screen() can be slow, check the terminal wasn't closed
// already
if (buffer == curbuf && curbuf->b_term != NULL)
@@ -4116,7 +4120,8 @@
#ifdef FEAT_MENU
+ winbar_height(wp)
#endif
- , wp->w_wincol, pos.col, wp->w_width, -1,
+ , wp->w_wincol + TPL_LCOL(wp), pos.col,
+ wp->w_width, -1,
#ifdef FEAT_PROP_POPUP
popup_is_popup(wp) ? SLF_POPUP :
#endif
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index 88bf5c3..ef86a7d 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -311,6 +311,7 @@
test_tab \
test_tabline \
test_tabpage \
+ test_tabpanel \
test_tagcase \
test_tagfunc \
test_tagjump \
@@ -567,6 +568,7 @@
test_system.res \
test_tab.res \
test_tabpage.res \
+ test_tabpanel.res \
test_tagjump.res \
test_taglist.res \
test_tcl.res \
diff --git a/src/testdir/dumps/Test_tabpanel_commandline_0.dump b/src/testdir/dumps/Test_tabpanel_commandline_0.dump
new file mode 100644
index 0000000..5ed359c
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_commandline_0.dump
@@ -0,0 +1,10 @@
+|[+8#0000001#e0e0e08|N|o| |N|a|m|e|]| | +0#0000000#ffffff0@34
+|[+2&&|N|o| |N|a|m|e|]| |~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+|a+0#0000001#ffff4012|b@1|r|e|v|i|a|t|e| +3#0000000#ffffff0@1|a|b|c|l|e|a|r| @1|a|b|o|v|e|l|e|f|t| @1|a|b|s|t|r|a|c|t| @4
+|:+0&&|a|b@1|r|e|v|i|a|t|e> @33
diff --git a/src/testdir/dumps/Test_tabpanel_commandline_1.dump b/src/testdir/dumps/Test_tabpanel_commandline_1.dump
new file mode 100644
index 0000000..a44f54e
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_commandline_1.dump
@@ -0,0 +1,10 @@
+|[+8#0000001#e0e0e08|N|o| |N|a|m|e|]| | +0#0000000#ffffff0@34
+|[+2&&|N|o| |N|a|m|e|]| |~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +0#0000001#e0e0e08|a|b@1|r|e|v|i|a|t|e| @4| +0#4040ff13#ffffff0@28
+| +0#0000001#ffd7ff255|a|b|c|l|e|a|r| @7| +0#4040ff13#ffffff0@28
+| +0#0000001#ffd7ff255|a|b|o|v|e|l|e|f|t| @5| +0#4040ff13#ffffff0@28
+| +0#0000001#ffd7ff255|a|b|s|t|r|a|c|t| @6| +0#4040ff13#ffffff0@28
+|:+0#0000000&|a|b@1|r|e|v|i|a|t|e> @33
diff --git a/src/testdir/dumps/Test_tabpanel_dont_overflow_into_tabpanel_0.dump b/src/testdir/dumps/Test_tabpanel_dont_overflow_into_tabpanel_0.dump
new file mode 100644
index 0000000..5fd8f9b
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_dont_overflow_into_tabpanel_0.dump
@@ -0,0 +1,10 @@
+|[+8#0000001#e0e0e08|N|o| |N|a|m|e|]| @1|[|N|o| |N|a|m|e|]| | +2#0000000#ffffff0|+| |[|N|o| |N|a|m|e|]| | +1&&@9|X+8#0000001#e0e0e08
+|++2#0000000#ffffff0| |[|N|o| |N|a|m|e>x+0&&@34
+| +1&&@9|x+0&&@34
+| +1&&@9|x+0&&@29| @4
+| +1&&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +0#0000000&@36|1|,|1| @4
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_00.dump b/src/testdir/dumps/Test_tabpanel_drawing_00.dump
new file mode 100644
index 0000000..1491b66
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_00.dump
@@ -0,0 +1,6 @@
+> +0&#ffffff0@44
+|~+0#4040ff13&| @43
+|~| @43
+|~| @43
+|~| @43
+| +0#0000000&@26|0|,|0|-|1| @8|A|l@1|
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_01.dump b/src/testdir/dumps/Test_tabpanel_drawing_01.dump
new file mode 100644
index 0000000..8601542
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_01.dump
@@ -0,0 +1,6 @@
+|X+2&#ffffff0|t|a|b|p|a|n|e|l|1| @5> +0&&@28
+| +1&&@15|~+0#4040ff13&| @27
+| +1#0000000&@15|~+0#4040ff13&| @27
+| +1#0000000&@15|~+0#4040ff13&| @27
+| +1#0000000&@15|~+0#4040ff13&| @27
+| +0#0000000&@26|0|,|0|-|1| @8|A|l|0|,
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_02.dump b/src/testdir/dumps/Test_tabpanel_drawing_02.dump
new file mode 100644
index 0000000..f7567dc
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_02.dump
@@ -0,0 +1,6 @@
+|2+2#e000e06#ffffff0| +2#0000000&|X|t|a|b|p|a|n|e|l|1| @3> +0&&@19||+1&&| +0&&@7
+| +1&&@15|~+0#4040ff13&| @18||+1#0000000&|~+0#4040ff13&| @6
+| +1#0000000&@15|~+0#4040ff13&| @18||+1#0000000&|~+0#4040ff13&| @6
+| +1#0000000&@15|~+0#4040ff13&| @18||+1#0000000&|~+0#4040ff13&| @6
+| +1#0000000&@15|<+3&&|a|b|p|a|n|e|l|1| |0|,|0|-|1| @1|A|l@1| |<+1&&|l|1| |0|,|0|-
+| +0&&@44
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_03.dump b/src/testdir/dumps/Test_tabpanel_drawing_03.dump
new file mode 100644
index 0000000..cb67b9e
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_03.dump
@@ -0,0 +1,6 @@
+|2+2#e000e06#ffffff0|++2#0000000&| |X|t|a|b|p|a|n|e|l|1| @2>a+0&&| @18||+1&&|a+0&&| @6
+| +1&&@15|b+0&&| @18||+1&&|b+0&&| @6
+| +1&&@15|c+0&&| @18||+1&&|c+0&&| @6
+| +1&&@15|~+0#4040ff13&| @18||+1#0000000&|~+0#4040ff13&| @6
+| +1#0000000&@15|<+3&&|n|e|l|1| |[|+|]| |1|,|1| @3|A|l@1| |<+1&&|+|]| |1|,|1|
+| +0&&@44
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_04.dump b/src/testdir/dumps/Test_tabpanel_drawing_04.dump
new file mode 100644
index 0000000..61b759e
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_04.dump
@@ -0,0 +1,6 @@
+|2+8#e000e06#e0e0e08|++8#0000001&| |X|t|a|b|p|a|n|e|l|1| @2>d+0#0000000#ffffff0| @27
+|++2&&| |X|t|a|b|p|a|n|e|l|2| @3|e+0&&| @27
+| +1&&@15|f+0&&| @27
+| +1&&@15|~+0#4040ff13&| @27
+| +1#0000000&@15|~+0#4040ff13&| @27
+| +0#0000000&@42|1|,
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_05.dump b/src/testdir/dumps/Test_tabpanel_drawing_05.dump
new file mode 100644
index 0000000..e9ea7cb
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_05.dump
@@ -0,0 +1,6 @@
+| +8#0000001#e0e0e08@15>d+0#0000000#ffffff0| @27
+|1+8#0000001#e0e0e08|:|X+2#4040ff13#ffffff0|t|a|b|p|a|n|e|l|1| +8#0000001#e0e0e08@3|e+0#0000000#ffffff0| @27
+| +2&&@15|f+0&&| @27
+|2+2&&|:|X+0#4040ff13&|t|a|b|p|a|n|e|l|2| +2#0000000&@3|~+0#4040ff13&| @27
+| +1#0000000&@15|~+0#4040ff13&| @27
+| +0#0000000&@42|1|,
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_06.dump b/src/testdir/dumps/Test_tabpanel_drawing_06.dump
new file mode 100644
index 0000000..b5935d3
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_06.dump
@@ -0,0 +1,6 @@
+>d+0&#ffffff0| @27| +8#0000001#e0e0e08@15
+|e+0#0000000#ffffff0| @27|1+8#0000001#e0e0e08|:|X+2#4040ff13#ffffff0|t|a|b|p|a|n|e|l|1| +8#0000001#e0e0e08@3
+|f+0#0000000#ffffff0| @27| +2&&@15
+|~+0#4040ff13&| @27|2+2#0000000&|:|X+0#4040ff13&|t|a|b|p|a|n|e|l|2| +2#0000000&@3
+|~+0#4040ff13&| @27| +1#0000000&@15
+| +0&&@26|1|,|1| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_07.dump b/src/testdir/dumps/Test_tabpanel_drawing_07.dump
new file mode 100644
index 0000000..440988b
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_07.dump
@@ -0,0 +1,6 @@
+> +0&#ffffff0@28| +8#0000001#e0e0e08@15
+|~+0#4040ff13#ffffff0| @27|1+8#0000001#e0e0e08|:|X+2#4040ff13#ffffff0|t|a|b|p|a|n|e|l|1| +8#0000001#e0e0e08@3
+|~+0#4040ff13#ffffff0| @27| +8#0000001#e0e0e08@15
+|~+0#4040ff13#ffffff0| @27|2+8#0000001#e0e0e08|:|X+0#4040ff13#ffffff0|t|a|b|p|a|n|e|l|2| +8#0000001#e0e0e08@3
+|~+0#4040ff13#ffffff0| @27| +2#0000000&@15
+| +0&&@26|0|,|0|-|1| @8|A|l@1|
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_08.dump b/src/testdir/dumps/Test_tabpanel_drawing_08.dump
new file mode 100644
index 0000000..57bbf92
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_08.dump
@@ -0,0 +1,6 @@
+>a+0&#ffffff0| @18||+1&&|a+0&&| @6| +2&&@15
+|b+0&&| @18||+1&&|b+0&&| @6|1+2&&|:|X+0#4040ff13&|t|a|b|p|a|n|e|l|1| +2#0000000&@3
+|c+0&&| @18||+1&&|c+0&&| @6| +1&&@15
+|~+0#4040ff13&| @18||+1#0000000&|~+0#4040ff13&| @6| +1#0000000&@15
+|<+3&&|n|e|l|1| |[|+|]| |1|,|1| @3|A|l@1| |<+1&&|+|]| |1|,|1| @16
+| +0&&@26|1|,|1| @10|A|l@1|
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_fill_tailing_0.dump b/src/testdir/dumps/Test_tabpanel_drawing_fill_tailing_0.dump
new file mode 100644
index 0000000..40e3bd7
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_fill_tailing_0.dump
@@ -0,0 +1,10 @@
+| +8#0000001#e0e0e08@19> +0#0000000#ffffff0@24
+|T+8#0000001#e0e0e08|O|P| @16|~+0#4040ff13#ffffff0| @23
+|a+8#0000001#e0e0e08@2|.|t|x|t| @12|~+0#4040ff13#ffffff0| @23
+|B+8#0000001#e0e0e08|O|T@1|O|M| @13|~+0#4040ff13#ffffff0| @23
+| +2#0000000&@19|~+0#4040ff13&| @23
+|T+2#0000000&|O|P| @16|~+0#4040ff13&| @23
+|b+2#0000000&@2|.|t|x|t| @12|~+0#4040ff13&| @23
+|B+2#0000000&|O|T@1|O|M| @13|~+0#4040ff13&| @23
+| +1#0000000&@19|~+0#4040ff13&| @23
+| +0#0000000&@44
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_pum_0.dump b/src/testdir/dumps/Test_tabpanel_drawing_pum_0.dump
new file mode 100644
index 0000000..190e5d9
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_pum_0.dump
@@ -0,0 +1,10 @@
+|a+8#0000001#e0e0e08@2|.|t|x|t| @12|!+0#0000000#ffffff0> @23
+|b+2&&@2|.|t|x|t| @12|!+0#0000001#e0e0e08| @14| +0#0000000#0000001| +0#4040ff13#ffffff0@7
+| +1#0000000&@19|#+0#0000001#ffd7ff255| @14| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@7
+| +1#0000000&@19|&+0#0000001#ffd7ff255| @14| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@7
+| +1#0000000&@19|*+0#0000001#ffd7ff255| @14| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@7
+| +1#0000000&@19|++0#0000001#ffd7ff255@1| @13| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@7
+| +1#0000000&@19|-+0#0000001#ffd7ff255@1| @13| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@7
+| +1#0000000&@19|<+0#0000001#ffd7ff255| @14| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@7
+| +1#0000000&@19|=+0#0000001#ffd7ff255| @14| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@7
+|-+2#0000000&@1| |m+0#00e0003&|a|t|c|h| |1| |o|f| |5|9|6| +0#0000000&@27
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_pum_1.dump b/src/testdir/dumps/Test_tabpanel_drawing_pum_1.dump
new file mode 100644
index 0000000..9888bc0
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_pum_1.dump
@@ -0,0 +1,10 @@
+|a+8#0000001#e0e0e08@2|.|t|x|t| @12|!+0#0000000#ffffff0| @23
+|++2&&| |b@2|.|t|x|t| @10| +0&&@1|a|b@1|r|e|v|i|a|t|e> @12
+| +1&&@19|~+0#4040ff13&| +0#0000001#e0e0e08|a|b@1|r|e|v|i|a|t|e| @4| +0#4040ff13#ffffff0@7
+| +1#0000000&@19|~+0#4040ff13&| +0#0000001#ffd7ff255|a|b|c|l|e|a|r| @7| +0#4040ff13#ffffff0@7
+| +1#0000000&@19|~+0#4040ff13&| +0#0000001#ffd7ff255|a|b|o|v|e|l|e|f|t| @5| +0#4040ff13#ffffff0@7
+| +1#0000000&@19|~+0#4040ff13&| +0#0000001#ffd7ff255|a|b|s|t|r|a|c|t| @6| +0#4040ff13#ffffff0@7
+| +1#0000000&@19|~+0#4040ff13&| @23
+| +1#0000000&@19|~+0#4040ff13&| @23
+| +1#0000000&@19|~+0#4040ff13&| @23
+|-+2#0000000&@1| |m+0#00e0003&|a|t|c|h| |1| |o|f| |4| +0#0000000&@29
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_scrolling_0.dump b/src/testdir/dumps/Test_tabpanel_drawing_scrolling_0.dump
new file mode 100644
index 0000000..fa1947e
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_scrolling_0.dump
@@ -0,0 +1,10 @@
+|a+8#0000001#e0e0e08@2|.|t|x|t| @12| +0#af5f00255#ffffff0@1|9| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t||+1&&| +0#af5f00255&@1|1|
+|2+2#e000e06&|++2#0000000&| |b@2|.|t|x|t| @9| +0#af5f00255&|1|0| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t||+1&&| +0#af5f00255&@1|2|
+| +1#0000000&@19| +0#af5f00255&|1@1| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t||+1&&| +0#af5f00255&@1|3|
+| +1#0000000&@19| +0#af5f00255&|1|2| >@+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t||+1&&| +0#af5f00255&@1|4|
+| +1#0000000&@19| +0#af5f00255&|1|3| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t||+1&&| +0#af5f00255&@1|5|
+| +1#0000000&@19| +0#af5f00255&|1|4| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t||+1&&| +0#af5f00255&@1|6|
+| +1#0000000&@19| +0#af5f00255&|1|5| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t||+1&&| +0#af5f00255&@1|7|
+| +1#0000000&@19| +0#af5f00255&|1|6| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t||+1&&| +0#af5f00255&@1|8|
+| +1#0000000&@19|<+3&&|.|t|x|t| |[|+|]| |1|2|,|1| @3|8|%| |<+1&&| |1|,
+| +0&&@44
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_scrolling_1.dump b/src/testdir/dumps/Test_tabpanel_drawing_scrolling_1.dump
new file mode 100644
index 0000000..6370449
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_scrolling_1.dump
@@ -0,0 +1,10 @@
+|a+8#0000001#e0e0e08@2|.|t|x|t| @12| +0#af5f00255#ffffff0@1|1| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| @1
+|2+2#e000e06&|++2#0000000&| |b@2|.|t|x|t| @9| +0#af5f00255&@1|2| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| @1
+| +1&&@19| +0#af5f00255&@1|3| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| @1
+| +1&&@19|b@2|.|t|x|t| |[|+|]| @1|1|,|1| @5|T|o|p
+| @19| +0#af5f00255&|1|5| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| @1
+| +1&&@19| +0#af5f00255&|1|6| >@+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| @1
+| +1&&@19| +0#af5f00255&|1|7| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| @1
+| +1&&@19| +0#af5f00255&|1|8| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| @1
+| +1&&@19|b+3&&@2|.|t|x|t| |[|+|]| @1|1|6|,|1| @4|1|4|%
+| +0&&@44
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_scrolling_2.dump b/src/testdir/dumps/Test_tabpanel_drawing_scrolling_2.dump
new file mode 100644
index 0000000..50b55ea
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_scrolling_2.dump
@@ -0,0 +1,10 @@
+|a+8#0000001#e0e0e08@2|.|t|x|t| @12| +0#af5f00255#ffffff0|1|9| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| @1
+|2+2#e000e06&|++2#0000000&| |b@2|.|t|x|t| @9| +0#af5f00255&|2|0| >@+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| @1
+| +1&&@19| +0#af5f00255&|2|1| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| @1
+| +1&&@19| +0#af5f00255&|2@1| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| @1
+| +1&&@19|b+3&&@2|.|t|x|t| |[|+|]| @1|2|0|,|1| @4|1|8|%
+| +1&&@19| +0#af5f00255&@1|1| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| @1
+| +1&&@19| +0#af5f00255&@1|2| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| @1
+| +1&&@19| +0#af5f00255&@1|3| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t|e|x|t| @1
+| +1&&@19|b@2|.|t|x|t| |[|+|]| @1|1|,|1| @5|T|o|p
+| +0&&@44
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_scrolling_3.dump b/src/testdir/dumps/Test_tabpanel_drawing_scrolling_3.dump
new file mode 100644
index 0000000..fdde1ab
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_scrolling_3.dump
@@ -0,0 +1,10 @@
+|a+8#0000001#e0e0e08@2|.|t|x|t| @12| +0#af5f00255#ffffff0@1|1| ||+1#0000000&| +0#af5f00255&|2|5| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t
+|2+2#e000e06&|++2#0000000&| |b@2|.|t|x|t| @9| +0#af5f00255&@1|2| ||+1#0000000&| +0#af5f00255&|2|6| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t
+| +1&&@19| +0#af5f00255&@1|3| ||+1#0000000&| +0#af5f00255&|2|7| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t
+| +1&&@19| +0#af5f00255&@1|4| ||+1#0000000&| +0#af5f00255&|2|8| >@+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t
+| +1&&@19| +0#af5f00255&@1|5| ||+1#0000000&| +0#af5f00255&|2|9| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t
+| +1&&@19| +0#af5f00255&@1|6| ||+1#0000000&| +0#af5f00255&|3|0| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t
+| +1&&@19| +0#af5f00255&@1|7| ||+1#0000000&| +0#af5f00255&|3|1| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t
+| +1&&@19| +0#af5f00255&@1|8| ||+1#0000000&| +0#af5f00255&|3|2| |t+0#0000000&|e|x|t| |t|e|x|t| |t|e|x|t| |t
+| +1&&@19|<| |1|,| |<+3&&|.|t|x|t| |[|+|]| |2|8|,|1| @2|2|6|%
+| +0&&@44
diff --git a/src/testdir/dumps/Test_tabpanel_drawing_with_popupwin_0.dump b/src/testdir/dumps/Test_tabpanel_drawing_with_popupwin_0.dump
new file mode 100644
index 0000000..080fa27
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_drawing_with_popupwin_0.dump
@@ -0,0 +1,10 @@
+|[+8#0000001#e0e0e08|N|o| |N|a|m|e|]| @10|╔+0#0000000#ffffff0|═|╗|.@18|╔|═|╗
+|[+2&&|S|c|r|a|t|c|h|]| @10|║+0&&|@|║|.@18|║|@|║
+| +1&&@19|╚+0&&|═|╝|.@5|a|t|c|u|r|s|o|r|.@4|╚|═|╝
+| +1&&@19|.+0&&@8>.@15
+| +1&&@19|.+0&&@24
+| +1&&@19|╔+0&&|═|╗|.@18|╔|═|╗
+| +1&&@19|║+0&&|@|║|.@18|║|@|║
+| +1&&@19|╚+0&&|═|╝|.@18|╚|═|╝
+| +1&&@19|.+0&&@24
+| @44
diff --git a/src/testdir/dumps/Test_tabpanel_eval_tabpanel_statusline_tabline_0.dump b/src/testdir/dumps/Test_tabpanel_eval_tabpanel_statusline_tabline_0.dump
new file mode 100644
index 0000000..9214434
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_eval_tabpanel_statusline_tabline_0.dump
@@ -0,0 +1,10 @@
+|$+8#0000001#e0e0e08| |[|a@2|]| |$|│+1#0000000#ffffff0|$| @13|[|c@2|]| @13|$
+|$+8#0000001#e0e0e08| |[|b@2|]| |$|│+1#0000000#ffffff0> +0&&@34
+|$+2&&| |[|c@2|]| |$|│+1&&|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|$+3&&| @13|[|c@2|]| @13|$
+|"+0&&|c@2|"| |[|N|e|w|]| @33
diff --git a/src/testdir/dumps/Test_tabpanel_eval_tabpanel_statusline_tabline_1.dump b/src/testdir/dumps/Test_tabpanel_eval_tabpanel_statusline_tabline_1.dump
new file mode 100644
index 0000000..dae0d0b
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_eval_tabpanel_statusline_tabline_1.dump
@@ -0,0 +1,10 @@
+|$+1&#ffffff0| @13|[|c@2|]| @13|$|│|$+8#0000001#e0e0e08| |[|a@2|]| |$
+> +0#0000000#ffffff0@34|│+1&&|$+8#0000001#e0e0e08| |[|b@2|]| |$
+|~+0#4040ff13#ffffff0| @33|│+1#0000000&|$+2&&| |[|c@2|]| |$
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|$+3&&| @13|[|c@2|]| @13|$|│+1&&| @8
+|:+0&&|s|e|t| |t|a|b|p|a|n|e|l|o|p|t|+|=|a|l|i|g|n|:|r|i|g|h|t| @15
diff --git a/src/testdir/dumps/Test_tabpanel_eval_tabpanel_with_linebreaks_0.dump b/src/testdir/dumps/Test_tabpanel_eval_tabpanel_with_linebreaks_0.dump
new file mode 100644
index 0000000..dd55218
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_eval_tabpanel_with_linebreaks_0.dump
@@ -0,0 +1,10 @@
+|t+8#0000001#e0e0e08|o|p| @7|a@2| @1|b@2| | +2#0000000#ffffff0|c@2| | +1&&@18|X+8#0000001#e0e0e08
+|$| |[|a@2|]| @1|$> +0#0000000#ffffff0@34
+|b+8#0000001#e0e0e08|o|t@1|o|m| @3|~+0#4040ff13#ffffff0| @33
+|t+8#0000001#e0e0e08|o|p| @6|~+0#4040ff13#ffffff0| @33
+|$+8#0000001#e0e0e08| |[|b@2|]| @1|$|~+0#4040ff13#ffffff0| @33
+|b+8#0000001#e0e0e08|o|t@1|o|m| @3|~+0#4040ff13#ffffff0| @33
+|t+2#0000000&|o|p| @6|~+0#4040ff13&| @33
+|$+2#0000000&| |[|c@2|]| @1|$|~+0#4040ff13&| @33
+|b+2#0000000&|o|t@1|o|m| @3|~+0#4040ff13&| @33
+|"+0#0000000&|c@2|"| |[|N|e|w|]| @25|0|,|0|-|1| @2
diff --git a/src/testdir/dumps/Test_tabpanel_eval_tabpanel_with_linebreaks_1.dump b/src/testdir/dumps/Test_tabpanel_eval_tabpanel_with_linebreaks_1.dump
new file mode 100644
index 0000000..84bf683
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_eval_tabpanel_with_linebreaks_1.dump
@@ -0,0 +1,10 @@
+| +8#0000001#e0e0e08|a@2| @1|b@2| | +2#0000000#ffffff0|c@2| | +1&&@19|t+8#0000001#e0e0e08|o|p| @6
+> +0#0000000#ffffff0@34|$+8#0000001#e0e0e08| |[|a@2|]| @1|$
+|~+0#4040ff13#ffffff0| @33|b+8#0000001#e0e0e08|o|t@1|o|m| @3
+|~+0#4040ff13#ffffff0| @33|t+8#0000001#e0e0e08|o|p| @6
+|~+0#4040ff13#ffffff0| @33|$+8#0000001#e0e0e08| |[|b@2|]| @1|$
+|~+0#4040ff13#ffffff0| @33|b+8#0000001#e0e0e08|o|t@1|o|m| @3
+|~+0#4040ff13#ffffff0| @33|t+2#0000000&|o|p| @6
+|~+0#4040ff13&| @33|$+2#0000000&| |[|c@2|]| @1|$
+|~+0#4040ff13&| @33|b+2#0000000&|o|t@1|o|m| @3
+|:+0&&|s|e|t| |t|a|b|p|a|n|e|l|o|p|t|+|=|a|l|i|g|n|:|r|i|g|0|,|0|-|1| @8|A|l@1|
diff --git a/src/testdir/dumps/Test_tabpanel_many_tabpages_0.dump b/src/testdir/dumps/Test_tabpanel_many_tabpages_0.dump
new file mode 100644
index 0000000..e974381
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_many_tabpages_0.dump
@@ -0,0 +1,10 @@
+|1+2&#ffffff0|:|t|a|b| @4> +0&&@34
+|2+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|3+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|4+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|5+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|6+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|7+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|8+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|9+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+| +0#0000000&@36|0|,|0|-|1| @2
diff --git a/src/testdir/dumps/Test_tabpanel_many_tabpages_1.dump b/src/testdir/dumps/Test_tabpanel_many_tabpages_1.dump
new file mode 100644
index 0000000..3ac3dde
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_many_tabpages_1.dump
@@ -0,0 +1,10 @@
+|1+8#0000001#e0e0e08|:|t|a|b| @4> +0#0000000#ffffff0@34
+|2+2&&|:|t|a|b| @4|~+0#4040ff13&| @33
+|3+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|4+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|5+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|6+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|7+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|8+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|9+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+| +0#0000000&@36|0|,|0|-|1| @2
diff --git a/src/testdir/dumps/Test_tabpanel_many_tabpages_2.dump b/src/testdir/dumps/Test_tabpanel_many_tabpages_2.dump
new file mode 100644
index 0000000..7b980e6
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_many_tabpages_2.dump
@@ -0,0 +1,10 @@
+|1+8#0000001#e0e0e08|:|t|a|b| @4> +0#0000000#ffffff0@34
+|2+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|3+2#0000000&|:|t|a|b| @4|~+0#4040ff13&| @33
+|4+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|5+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|6+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|7+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|8+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|9+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+| +0#0000000&@36|0|,|0|-|1| @2
diff --git a/src/testdir/dumps/Test_tabpanel_many_tabpages_3.dump b/src/testdir/dumps/Test_tabpanel_many_tabpages_3.dump
new file mode 100644
index 0000000..fa3c09c
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_many_tabpages_3.dump
@@ -0,0 +1,10 @@
+|1+8#0000001#e0e0e08|:|t|a|b| @4> +0#0000000#ffffff0@34
+|2+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|3+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|4+2#0000000&|:|t|a|b| @4|~+0#4040ff13&| @33
+|5+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|6+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|7+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|8+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+|9+8#0000001#e0e0e08|:|t|a|b| @4|~+0#4040ff13#ffffff0| @33
+| +0#0000000&@36|0|,|0|-|1| @2
diff --git a/src/testdir/dumps/Test_tabpanel_many_tabpages_4.dump b/src/testdir/dumps/Test_tabpanel_many_tabpages_4.dump
new file mode 100644
index 0000000..07ff180
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_many_tabpages_4.dump
@@ -0,0 +1,10 @@
+|1+8#0000001#e0e0e08|0|:|t|a|b| @3> +0#0000000#ffffff0@34
+|1+2&&@1|:|t|a|b| @3|~+0#4040ff13&| @33
+|1+8#0000001#e0e0e08|2|:|t|a|b| @3|~+0#4040ff13#ffffff0| @33
+|1+8#0000001#e0e0e08|3|:|t|a|b| @3|~+0#4040ff13#ffffff0| @33
+|1+8#0000001#e0e0e08|4|:|t|a|b| @3|~+0#4040ff13#ffffff0| @33
+|1+8#0000001#e0e0e08|5|:|t|a|b| @3|~+0#4040ff13#ffffff0| @33
+|1+8#0000001#e0e0e08|6|:|t|a|b| @3|~+0#4040ff13#ffffff0| @33
+|1+8#0000001#e0e0e08|7|:|t|a|b| @3|~+0#4040ff13#ffffff0| @33
+|1+8#0000001#e0e0e08|8|:|t|a|b| @3|~+0#4040ff13#ffffff0| @33
+|:+0#0000000&|t|a|b|n|e|x|t| |-|3| @25|0|,|0|-|1| @2
diff --git a/src/testdir/dumps/Test_tabpanel_noeval_tabpanel_statusline_tabline_0.dump b/src/testdir/dumps/Test_tabpanel_noeval_tabpanel_statusline_tabline_0.dump
new file mode 100644
index 0000000..9214434
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_noeval_tabpanel_statusline_tabline_0.dump
@@ -0,0 +1,10 @@
+|$+8#0000001#e0e0e08| |[|a@2|]| |$|│+1#0000000#ffffff0|$| @13|[|c@2|]| @13|$
+|$+8#0000001#e0e0e08| |[|b@2|]| |$|│+1#0000000#ffffff0> +0&&@34
+|$+2&&| |[|c@2|]| |$|│+1&&|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|$+3&&| @13|[|c@2|]| @13|$
+|"+0&&|c@2|"| |[|N|e|w|]| @33
diff --git a/src/testdir/dumps/Test_tabpanel_noeval_tabpanel_statusline_tabline_1.dump b/src/testdir/dumps/Test_tabpanel_noeval_tabpanel_statusline_tabline_1.dump
new file mode 100644
index 0000000..dae0d0b
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_noeval_tabpanel_statusline_tabline_1.dump
@@ -0,0 +1,10 @@
+|$+1&#ffffff0| @13|[|c@2|]| @13|$|│|$+8#0000001#e0e0e08| |[|a@2|]| |$
+> +0#0000000#ffffff0@34|│+1&&|$+8#0000001#e0e0e08| |[|b@2|]| |$
+|~+0#4040ff13#ffffff0| @33|│+1#0000000&|$+2&&| |[|c@2|]| |$
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|$+3&&| @13|[|c@2|]| @13|$|│+1&&| @8
+|:+0&&|s|e|t| |t|a|b|p|a|n|e|l|o|p|t|+|=|a|l|i|g|n|:|r|i|g|h|t| @15
diff --git a/src/testdir/dumps/Test_tabpanel_tabline_and_tabpanel_0.dump b/src/testdir/dumps/Test_tabpanel_tabline_and_tabpanel_0.dump
new file mode 100644
index 0000000..fdca7f1
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_tabline_and_tabpanel_0.dump
@@ -0,0 +1,10 @@
+|a+8#0000001#e0e0e08@2|.|t|x|t| @1|│+1#0000000#ffffff0| +8#0000001#e0e0e08|a@2|.|t|x|t| @1|b@2|.|t|x|t| | +2#0000000#ffffff0|c@2|.|t|x|t| | +1&&@6|X+8#0000001#e0e0e08
+|b@2|.|t|x|t| @1|│+1#0000000#ffffff0> +0&&@34
+|c+2&&@2|.|t|x|t| @1|│+1&&|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+|"+0#0000000&|c@2|.|t|x|t|"| |[|N|e|w|]| @21|0|,|0|-|1| @2
diff --git a/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_left_0.dump b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_left_0.dump
new file mode 100644
index 0000000..a50355f
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_left_0.dump
@@ -0,0 +1,10 @@
+|[+8#0000001#e0e0e08|N|o| |N|a|m|e|]|│+1#0000000#ffffff0| +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| | +2#0000000#ffffff0|[|N|o| |N|a|m|e|]| | +1&&@11|X+8#0000001#e0e0e08
+|[+2#0000000#ffffff0|N|o| |N|a|m|e|]|│+1&&> +0&&@34
+| +1&&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +0#0000000&@36|0|,|0|-|1| @2
diff --git a/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_left_1.dump b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_left_1.dump
new file mode 100644
index 0000000..e347c7e
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_left_1.dump
@@ -0,0 +1,10 @@
+|│+1&#ffffff0| +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| | +2#0000000#ffffff0|[|N|o| |N|a|m|e|]| | +1&&@20|X+8#0000001#e0e0e08
+|│+1#0000000#ffffff0> +0&&@43
+|│+1&&|~+0#4040ff13&| @42
+|│+1#0000000&|~+0#4040ff13&| @42
+|│+1#0000000&|~+0#4040ff13&| @42
+|│+1#0000000&|~+0#4040ff13&| @42
+|│+1#0000000&|~+0#4040ff13&| @42
+|│+1#0000000&|~+0#4040ff13&| @42
+|│+1#0000000&|~+0#4040ff13&| @42
+|:+0#0000000&|s|e|t| |t|a|b|p|a|n|e|l|o|p|t|=|c|o|l|u|m|n|s|:|1|,|v|0|,|0|-|1| @8|A|l@1
diff --git a/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_left_2.dump b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_left_2.dump
new file mode 100644
index 0000000..d1c5b92
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_left_2.dump
@@ -0,0 +1,10 @@
+|[+8#0000001#e0e0e08|N|o| |N|a|m|e|]|│+1#0000000#ffffff0| +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| | +2#0000000#ffffff0|[|N|o| |N|a|m|e|]| | +1&&@11|X+8#0000001#e0e0e08
+|[+2#0000000#ffffff0|N|o| |N|a|m|e|]|│+1&&> +0&&@34
+| +1&&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+| +1#0000000&@8|│|~+0#4040ff13&| @33
+|:+0#0000000&|s|e|t| |t|a|b|p|a|n|e|l|o|p|t|=|c|o|l|u|m|n|s|:|1|0|,|v|e|r|t| @4|0|,|0|-|1| @2
diff --git a/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_left_3.dump b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_left_3.dump
new file mode 100644
index 0000000..fc84c0b
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_left_3.dump
@@ -0,0 +1,10 @@
+|[+8#0000001#e0e0e08|│+1#0000000#ffffff0| +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| | +2#0000000#ffffff0|[|N|o| |N|a|m|e|]| | +1&&@19|X+8#0000001#e0e0e08
+|[+2#0000000#ffffff0|│+1&&> +0&&@42
+| +1&&|│|~+0#4040ff13&| @41
+| +1#0000000&|│|~+0#4040ff13&| @41
+| +1#0000000&|│|~+0#4040ff13&| @41
+| +1#0000000&|│|~+0#4040ff13&| @41
+| +1#0000000&|│|~+0#4040ff13&| @41
+| +1#0000000&|│|~+0#4040ff13&| @41
+| +1#0000000&|│|~+0#4040ff13&| @41
+|:+0#0000000&|s|e|t| |t|a|b|p|a|n|e|l|o|p|t|=|c|o|l|u|m|n|s|:|2|,|v|e|0|,|0|-|1| @8|A|l
diff --git a/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_right_0.dump b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_right_0.dump
new file mode 100644
index 0000000..02aa109
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_right_0.dump
@@ -0,0 +1,10 @@
+| +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| | +2#0000000#ffffff0|[|N|o| |N|a|m|e|]| | +1&&@12|│|[+8#0000001#e0e0e08|N|o| |N|a|m|e|]
+> +0#0000000#ffffff0@34|│+1&&|[+2&&|N|o| |N|a|m|e|]
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+| +0&&@26|0|,|0|-|1| @8|A|l@1|
diff --git a/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_right_1.dump b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_right_1.dump
new file mode 100644
index 0000000..8e97a7e
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_right_1.dump
@@ -0,0 +1,10 @@
+| +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| | +2#0000000#ffffff0|[|N|o| |N|a|m|e|]| | +1&&@21|│
+> +0&&@43|│+1&&
+|~+0#4040ff13&| @42|│+1#0000000&
+|~+0#4040ff13&| @42|│+1#0000000&
+|~+0#4040ff13&| @42|│+1#0000000&
+|~+0#4040ff13&| @42|│+1#0000000&
+|~+0#4040ff13&| @42|│+1#0000000&
+|~+0#4040ff13&| @42|│+1#0000000&
+|~+0#4040ff13&| @42|│+1#0000000&
+|:+0&&|s|e|t| |t|a|b|p|a|n|e|l|o|p|t|=|a|l|i|g|n|:|r|i|g|h|0|,|0|-|1| @8|A|l@1|
diff --git a/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_right_2.dump b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_right_2.dump
new file mode 100644
index 0000000..6e33239
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_right_2.dump
@@ -0,0 +1,10 @@
+| +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| | +2#0000000#ffffff0|[|N|o| |N|a|m|e|]| | +1&&@12|│|[+8#0000001#e0e0e08|N|o| |N|a|m|e|]
+> +0#0000000#ffffff0@34|│+1&&|[+2&&|N|o| |N|a|m|e|]
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|~+0#4040ff13&| @33|│+1#0000000&| @8
+|:+0&&|s|e|t| |t|a|b|p|a|n|e|l|o|p|t|=|a|l|i|g|n|:|r|i|g|h|0|,|0|-|1| @8|A|l@1|
diff --git a/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_right_3.dump b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_right_3.dump
new file mode 100644
index 0000000..1f9255b
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_vert_is_multibytes_right_3.dump
@@ -0,0 +1,10 @@
+| +8#0000001#e0e0e08|[|N|o| |N|a|m|e|]| | +2#0000000#ffffff0|[|N|o| |N|a|m|e|]| | +1&&@20|│|[+8#0000001#e0e0e08
+> +0#0000000#ffffff0@42|│+1&&|[+2&&
+|~+0#4040ff13&| @41|│+1#0000000&|
+|~+0#4040ff13&| @41|│+1#0000000&|
+|~+0#4040ff13&| @41|│+1#0000000&|
+|~+0#4040ff13&| @41|│+1#0000000&|
+|~+0#4040ff13&| @41|│+1#0000000&|
+|~+0#4040ff13&| @41|│+1#0000000&|
+|~+0#4040ff13&| @41|│+1#0000000&|
+|:+0&&|s|e|t| |t|a|b|p|a|n|e|l|o|p|t|=|a|l|i|g|n|:|r|i|g|h|0|,|0|-|1| @8|A|l@1|
diff --git a/src/testdir/dumps/Test_tabpanel_visual_0.dump b/src/testdir/dumps/Test_tabpanel_visual_0.dump
new file mode 100644
index 0000000..af7ba65
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_visual_0.dump
@@ -0,0 +1,10 @@
+|[+8#0000001#e0e0e08|N|o| |N|a|m|e|]| |a+0&#a8a8a8255@2|1| |b@2|1| >c+0#0000000#ffffff0@2|1| |d@2|1| @15
+|++2&&| |[|N|o| |N|a|m|e|a+0&&@2|2| |b@2|2| |c@2|2| |d@2|2| @15
+| +1&&@9|a+0&&@2|3| |b@2|3| |c@2|3| |d@2|3| @15
+| +1&&@9|a+0&&@2|4| |b@2|4| |c@2|4| |d@2|4| @15
+| +1&&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+|-+2#0000000&@1| |V|I|S|U|A|L| |-@1| +0&&@4|1@1| @17|1|,|1@1| @3
diff --git a/src/testdir/dumps/Test_tabpanel_visual_1.dump b/src/testdir/dumps/Test_tabpanel_visual_1.dump
new file mode 100644
index 0000000..0cdc5f2
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_visual_1.dump
@@ -0,0 +1,10 @@
+|[+8#0000001#e0e0e08|N|o| |N|a|m|e|]| |a+0#0000000#ffffff0@2|1| |b@2|1| |c@2|1| |d@2|1| @15
+|++2&&| |[|N|o| |N|a|m|e|a+0&&@2|2| |b+0#0000001#a8a8a8255@2|2| |c@2>2+0#0000000#ffffff0| |d@2|2| @15
+| +1&&@9|a+0&&@2|3| |b@2|3| |c@2|3| |d@2|3| @15
+| +1&&@9|a+0&&@2|4| |b@2|4| |c@2|4| |d@2|4| @15
+| +1&&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+|-+2#0000000&@1| |V|I|S|U|A|L| |-@1| +0&&@4|9| @18|2|,|1|4| @3
diff --git a/src/testdir/dumps/Test_tabpanel_visual_2.dump b/src/testdir/dumps/Test_tabpanel_visual_2.dump
new file mode 100644
index 0000000..9a307c1
--- /dev/null
+++ b/src/testdir/dumps/Test_tabpanel_visual_2.dump
@@ -0,0 +1,10 @@
+|[+8#0000001#e0e0e08|N|o| |N|a|m|e|]| |a+0#0000000#ffffff0@2|1| |b@2|1| |c@2|1| |d@2|1| @15
+|++2&&| |[|N|o| |N|a|m|e|a+0&&@2|2| >b@2|2| |c@2|2| |d@2|2| @15
+| +1&&@9|a+0&&@2|3| |b@2|3| |c@2|3| |d@2|3| @15
+| +1&&@9|a+0&&@2|4| |b@2|4| |c@2|4| |d@2|4| @15
+| +1&&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+| +1#0000000&@9|~+0#4040ff13&| @33
+|b+0#0000000&@2|2| |c@2|2| @27|2|,|6| @4
diff --git a/src/testdir/gen_opt_test.vim b/src/testdir/gen_opt_test.vim
index 3d798e9..1f15453 100644
--- a/src/testdir/gen_opt_test.vim
+++ b/src/testdir/gen_opt_test.vim
@@ -94,6 +94,7 @@
\ 'scrolljump': [[-100, -1, 0, 1, 2, 15], [-101, 999]],
\ 'scrolloff': [[0, 1, 8, 999], [-1]],
\ 'shiftwidth': [[0, 1, 8, 999], [-1]],
+ \ 'showtabpanel': [[0, 1, 2], []],
\ 'sidescroll': [[0, 1, 8, 999], [-1]],
\ 'sidescrolloff': [[0, 1, 8, 999], [-1]],
\ 'tabstop': [[1, 4, 8, 12, 9999], [-1, 0, 10000]],
@@ -301,6 +302,11 @@
\ ['xxx']],
\ 'tabclose': [['', 'left', 'uselast', 'left,uselast'], ['xxx']],
\ 'tabline': [['', 'xxx'], ['%$', '%{', '%{%', '%{%}', '%(', '%)']],
+ \ 'tabpanel': [['', 'aaa', 'bbb'], []],
+ \ 'tabpanelopt': [['', 'align:left', 'align:right', 'vert', 'columns:0',
+ \ 'columns:20', 'columns:999'],
+ \ ['xxx', 'align:', 'align:middle', 'colomns:', 'cols:10',
+ \ 'cols:-1']],
\ 'tagcase': [['followic', 'followscs', 'ignore', 'match', 'smart'],
\ ['', 'xxx', 'smart,match']],
\ 'termencoding': [has('gui_gtk') ? [] : ['', 'utf-8'], ['xxx']],
@@ -373,8 +379,17 @@
\ 'verbosefile': [[], ['call delete("Xfile")']],
\}
-const invalid_options = test_values->keys()
+let invalid_options = test_values->keys()
\->filter({-> v:val !~# '^other' && !exists($"&{v:val}")})
+for s:skip_option in [
+ \ [!has('tabpanel'), 'tabpanel'],
+ \ [!has('tabpanel'), 'tabpanelopt'],
+ \ [!has('tabpanel'), 'showtabpanel'],
+ \ ]
+ if s:skip_option[0]
+ call remove(invalid_options, s:skip_option[1])
+ endif
+endfor
if !empty(invalid_options)
throw $"Invalid option name in test_values: '{invalid_options->join("', '")}'"
endif
@@ -406,6 +421,8 @@
let [pre_processing, post_processing] = get(test_prepost, fullname, [[], []])
let script += pre_processing
+ " Setting an option can only fail when it's implemented.
+ call add(script, $"if exists('+{fullname}')")
if line =~ 'P_BOOL'
for opt in [fullname, shortname]
for cmd in ['set', 'setlocal', 'setglobal']
@@ -439,8 +456,6 @@
endfor
" Failure tests
- " Setting an option can only fail when it's implemented.
- call add(script, $"if exists('+{fullname}')")
for opt in [fullname, shortname]
for cmd in ['set', 'setlocal', 'setglobal']
for val in invalid_values
@@ -464,7 +479,6 @@
endfor
endfor
endfor
- call add(script, "endif")
endif
" Cannot change 'termencoding' in GTK
@@ -476,6 +490,8 @@
call add(script, 'endif')
endif
+ call add(script, "endif")
+
let script += post_processing
call add(script, 'endfunc')
endwhile
diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim
index 68933a3..9a3fe20 100644
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -4345,4 +4345,9 @@
set wildoptions&
endfunc
+func Test_redrawtabpanel_error()
+ CheckNotFeature tabpanel
+ call assert_fails(':redrawtabpanel', 'E1547:')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_tabpanel.vim b/src/testdir/test_tabpanel.vim
new file mode 100644
index 0000000..630226f
--- /dev/null
+++ b/src/testdir/test_tabpanel.vim
@@ -0,0 +1,480 @@
+" Tests for tabpanel
+
+source check.vim
+source screendump.vim
+CheckFeature tabpanel
+
+function! s:reset()
+ set tabpanel&
+ set tabpanelopt&
+ set showtabpanel&
+endfunc
+
+function! Test_tabpanel_mouse()
+ let save_showtabline = &showtabline
+ let save_mouse = &mouse
+ set showtabline=0 mouse=a
+
+ tabnew
+ tabnew
+
+ call test_setmouse(1, 1)
+ call feedkeys("\<LeftMouse>", 'xt')
+ call assert_equal(3, tabpagenr())
+
+ set showtabpanel=2 tabpanelopt=columns:10
+
+ call test_setmouse(1, 1)
+ call feedkeys("\<LeftMouse>", 'xt')
+ call assert_equal(1, tabpagenr())
+ call test_setmouse(2, 1)
+ call feedkeys("\<LeftMouse>", 'xt')
+ call assert_equal(2, tabpagenr())
+ call test_setmouse(3, 1)
+ call feedkeys("\<LeftMouse>", 'xt')
+ call assert_equal(3, tabpagenr())
+
+ call feedkeys("\<LeftMouse>", 'xt')
+ call test_setmouse(2, 3)
+ let pos = getmousepos()
+ call assert_equal(2, pos['winrow'])
+ call assert_equal(0, pos['wincol'])
+ call assert_equal(2, pos['screenrow'])
+ call assert_equal(3, pos['screencol'])
+
+ call test_setmouse(1, 11)
+ call feedkeys("\<LeftMouse>", 'xt')
+ let pos = getmousepos()
+ call assert_equal(1, pos['winrow'])
+ call assert_equal(1, pos['wincol'])
+ call assert_equal(1, pos['screenrow'])
+ call assert_equal(11, pos['screencol'])
+
+ new
+ wincmd x
+
+ call test_setmouse(10, 11)
+ call feedkeys("\<LeftMouse>", 'xt')
+ let pos = getmousepos()
+ call assert_equal(10, pos['winrow'])
+ call assert_equal(1, pos['wincol'])
+ call assert_equal(10, pos['screenrow'])
+ call assert_equal(11, pos['screencol'])
+
+ tabonly!
+ call s:reset()
+ let &mouse = save_mouse
+ let &showtabline = save_showtabline
+endfunc
+
+function! Test_tabpanel_drawing()
+ CheckScreendump
+
+ let lines =<< trim END
+ function! MyTabPanel()
+ let n = g:actual_curtabpage
+ let hi = n == tabpagenr() ? 'TabLineSel' : 'TabLine'
+ let label = printf("\n%%#%sTabNumber#%d:%%#%s#", hi, n, hi)
+ let label ..= '%1*%f%*'
+ return label
+ endfunction
+ hi User1 ctermfg=12
+
+ set showtabline=0
+ set showtabpanel=0
+ set tabpanelopt=columns:16
+ set tabpanel=
+ silent edit Xtabpanel1
+
+ nnoremap \01 <Cmd>set showtabpanel=2<CR>
+ nnoremap \02 <C-w>v
+ nnoremap \03 <Cmd>call setline(1, ['a', 'b', 'c'])<CR>
+ nnoremap \04 <Cmd>silent tabnew Xtabpanel2<CR><Cmd>call setline(1, ['d', 'e', 'f'])<CR>
+ nnoremap \05 <Cmd>set tabpanel=%!MyTabPanel()<CR>
+ nnoremap \06 <Cmd>set tabpanelopt+=align:right<CR>
+ nnoremap \07 <Cmd>tab terminal NONE<CR><C-w>N
+ nnoremap \08 <Cmd>tabclose!<CR><Cmd>tabclose!<CR>
+ END
+ call writefile(lines, 'XTest_tabpanel', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel', {'rows': 6, 'cols': 45})
+
+ call VerifyScreenDump(buf, 'Test_tabpanel_drawing_00', {})
+
+ for i in range(1, 8)
+ let n = printf('%02d', i)
+ call term_sendkeys(buf, '\' .. n)
+ call VerifyScreenDump(buf, 'Test_tabpanel_drawing_' .. n, {})
+ endfor
+
+ call StopVimInTerminal(buf)
+endfunc
+
+function! Test_tabpanel_drawing_with_popupwin()
+ CheckScreendump
+
+ let lines =<< trim END
+ set showtabpanel=2
+ set tabpanelopt=columns:20
+ set showtabline=0
+ tabnew
+ setlocal buftype=nofile
+ call setbufline(bufnr(), 1, repeat([repeat('.', &columns - 20)], &lines))
+ highlight TestingForTabPanelPopupwin guibg=#7777ff guifg=#000000
+ for line in [1, &lines]
+ for col in [1, &columns - 20 - 2]
+ call popup_create([
+ \ '@',
+ \ ], {
+ \ 'line': line,
+ \ 'col': col,
+ \ 'border': [],
+ \ 'highlight': 'TestingForTabPanelPopupwin',
+ \ })
+ endfor
+ endfor
+ call cursor(4, 10)
+ call popup_atcursor('atcursor', {
+ \ 'highlight': 'TestingForTabPanelPopupwin',
+ \ })
+ END
+ call writefile(lines, 'XTest_tabpanel_with_popupwin', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel_with_popupwin', {'rows': 10, 'cols': 45})
+
+ call VerifyScreenDump(buf, 'Test_tabpanel_drawing_with_popupwin_0', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+function! Test_tabpanel_drawing_fill_tailing()
+ CheckScreendump
+
+ let lines =<< trim END
+ set showtabpanel=2
+ set tabpanelopt=columns:20
+ set showtabline=0
+ e aaa.txt
+ tabnew
+ e bbb.txt
+ let &tabpanel = "abc"
+ redraw!
+ " Check whether "abc" is cleared
+ let &tabpanel = "\nTOP\n%f\nBOTTOM"
+ END
+ call writefile(lines, 'XTest_tabpanel_fill_tailing', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel_fill_tailing', {'rows': 10, 'cols': 45})
+
+ call VerifyScreenDump(buf, 'Test_tabpanel_drawing_fill_tailing_0', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+function! Test_tabpanel_drawing_pum()
+ CheckScreendump
+
+ let lines =<< trim END
+ set showtabpanel=2
+ set tabpanelopt=columns:20
+ set showtabline=0
+ e aaa.txt
+ tabnew
+ e bbb.txt
+ END
+ call writefile(lines, 'XTest_tabpanel_pum', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel_pum', {'rows': 10, 'cols': 45})
+
+ call term_sendkeys(buf, "i\<C-x>\<C-v>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_drawing_pum_0', {})
+
+ call term_sendkeys(buf, "\<cr> ab\<C-x>\<C-v>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_drawing_pum_1', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+function! Test_tabpanel_scrolling()
+ CheckScreendump
+
+ let lines =<< trim END
+ set showtabpanel=2
+ set tabpanelopt=columns:20
+ set showtabline=0
+ set nowrap
+ set number
+ e aaa.txt
+ tabnew
+ e bbb.txt
+ vsplit
+ call setbufline(bufnr(), 1, repeat(['text text text text'], 100))
+ wincmd =
+ END
+ call writefile(lines, 'XTest_tabpanel_scrolling', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel_scrolling', {'rows': 10, 'cols': 45})
+ let n = 0
+ for c in ['H', 'J', 'K', 'L']
+ call term_sendkeys(buf, ":wincmd " .. c .. "\<cr>")
+ call term_sendkeys(buf, "\<C-d>\<C-d>")
+ call term_sendkeys(buf, "r@")
+ call VerifyScreenDump(buf, 'Test_tabpanel_drawing_scrolling_' .. n, {})
+ let n += 1
+ endfor
+
+ call StopVimInTerminal(buf)
+endfunc
+
+function! Test_tabpanel_many_tabpages()
+ CheckScreendump
+
+ let lines =<< trim END
+ set showtabpanel=2
+ set tabpanelopt=columns:10
+ set showtabline=0
+ set tabpanel=%{g:actual_curtabpage}:tab
+ execute join(repeat(['tabnew'], 20), ' | ')
+ END
+ call writefile(lines, 'XTest_tabpanel_many_tabpages', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel_many_tabpages', {'rows': 10, 'cols': 45})
+ for n in range(0, 3)
+ call term_sendkeys(buf, "gt")
+ call VerifyScreenDump(buf, 'Test_tabpanel_many_tabpages_' .. n, {})
+ endfor
+ call term_sendkeys(buf, ":tabnext +10\<cr>")
+ call term_sendkeys(buf, ":tabnext -3\<cr>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_many_tabpages_4', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+function! Test_tabpanel_visual()
+ CheckScreendump
+
+ let lines =<< trim END
+ set showtabpanel=2
+ set tabpanelopt=columns:10
+ set showtabline=0
+ tabnew
+ call setbufline(bufnr(), 1, ['aaa1 bbb1 ccc1 ddd1', 'aaa2 bbb2 ccc2 ddd2', 'aaa3 bbb3 ccc3 ddd3', 'aaa4 bbb4 ccc4 ddd4'])
+ END
+ call writefile(lines, 'XTest_tabpanel_visual', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel_visual', {'rows': 10, 'cols': 45})
+ call term_sendkeys(buf, "v2w")
+ call VerifyScreenDump(buf, 'Test_tabpanel_visual_0', {})
+ call term_sendkeys(buf, "\<esc>0jw")
+ call term_sendkeys(buf, "v2wge")
+ call VerifyScreenDump(buf, 'Test_tabpanel_visual_1', {})
+ call term_sendkeys(buf, "y:echo @\"\<cr>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_visual_2', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+function! Test_tabpanel_commandline()
+ CheckScreendump
+
+ let lines =<< trim END
+ set showtabpanel=2
+ set tabpanelopt=columns:10
+ set showtabline=0
+ tabnew
+ END
+ call writefile(lines, 'XTest_tabpanel_commandline', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel_commandline', {'rows': 10, 'cols': 45})
+ call term_sendkeys(buf, ":ab\<tab>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_commandline_0', {})
+
+ call term_sendkeys(buf, "\<esc>")
+ call term_sendkeys(buf, ":set wildoptions=pum\<cr>")
+ call term_sendkeys(buf, ":ab\<tab>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_commandline_1', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+function! Test_tabpanel_tabline_and_tabpanel()
+ CheckScreendump
+
+ let lines =<< trim END
+ set showtabpanel=2
+ set tabpanelopt=columns:10,vert
+ set fillchars=tpl_vert:│
+ set showtabline=2
+ e aaa.txt
+ tabnew
+ e bbb.txt
+ tabnew
+ e ccc.txt
+ END
+ call writefile(lines, 'XTest_tabpanel_tabline_and_tabpanel', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel_tabline_and_tabpanel', {'rows': 10, 'cols': 45})
+ call VerifyScreenDump(buf, 'Test_tabpanel_tabline_and_tabpanel_0', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+function! Test_tabpanel_dont_overflow_into_tabpanel()
+ CheckScreendump
+
+ let lines =<< trim END
+ set showtabpanel=2
+ set tabpanelopt=columns:10
+ set showtabline=2
+ tabnew
+ call setline(1, repeat('x', 100))
+ set wrap
+ END
+ call writefile(lines, 'XTest_tabpanel_dont_overflow_into_tabpanel', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel_dont_overflow_into_tabpanel', {'rows': 10, 'cols': 45})
+ call VerifyScreenDump(buf, 'Test_tabpanel_dont_overflow_into_tabpanel_0', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+function! Test_tabpanel_dont_vert_is_multibytes_left()
+ CheckScreendump
+
+ let lines =<< trim END
+ set showtabpanel=2
+ set tabpanelopt=columns:10,vert
+ set fillchars=tpl_vert:│
+ set showtabline=2
+ tabnew
+ END
+ call writefile(lines, 'XTest_tabpanel_vert_is_multibyte_lefts', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel_vert_is_multibyte_lefts', {'rows': 10, 'cols': 45})
+ call VerifyScreenDump(buf, 'Test_tabpanel_vert_is_multibytes_left_0', {})
+
+ call term_sendkeys(buf, ":set tabpanelopt=columns:1,vert\<cr>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_vert_is_multibytes_left_1', {})
+
+ call term_sendkeys(buf, ":set tabpanelopt=columns:10,vert\<cr>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_vert_is_multibytes_left_2', {})
+
+ call term_sendkeys(buf, ":set tabpanelopt=columns:2,vert\<cr>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_vert_is_multibytes_left_3', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+function! Test_tabpanel_dont_vert_is_multibytes_right()
+ CheckScreendump
+
+ let lines =<< trim END
+ set showtabpanel=2
+ set tabpanelopt=align:right,columns:10,vert
+ set fillchars=tpl_vert:│
+ set showtabline=2
+ tabnew
+ END
+ call writefile(lines, 'XTest_tabpanel_vert_is_multibytes_right', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel_vert_is_multibytes_right', {'rows': 10, 'cols': 45})
+ call VerifyScreenDump(buf, 'Test_tabpanel_vert_is_multibytes_right_0', {})
+
+ call term_sendkeys(buf, ":set tabpanelopt=align:right,columns:1,vert\<cr>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_vert_is_multibytes_right_1', {})
+
+ call term_sendkeys(buf, ":set tabpanelopt=align:right,columns:10,vert\<cr>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_vert_is_multibytes_right_2', {})
+
+ call term_sendkeys(buf, ":set tabpanelopt=align:right,columns:2,vert\<cr>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_vert_is_multibytes_right_3', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+function! Test_tabpanel_eval_tabpanel_statusline_tabline()
+ CheckScreendump
+
+ let lines =<< trim END
+ function! Expr()
+ return "$%=[%f]%=$"
+ endfunction
+ set laststatus=2
+ set showtabline=2
+ set showtabpanel=2
+ set statusline=%!Expr()
+ set tabline=%!Expr()
+ set tabpanel=%!Expr()
+ set tabpanelopt=columns:10,vert
+ set fillchars=tpl_vert:│
+ e aaa
+ tabnew
+ e bbb
+ tabnew
+ e ccc
+ END
+ call writefile(lines, 'XTest_tabpanel_eval_tabpanel_statusline_tabline', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel_eval_tabpanel_statusline_tabline', {'rows': 10, 'cols': 45})
+ call VerifyScreenDump(buf, 'Test_tabpanel_eval_tabpanel_statusline_tabline_0', {})
+ call term_sendkeys(buf, ":set tabpanelopt+=align:right\<cr>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_eval_tabpanel_statusline_tabline_1', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+function! Test_tabpanel_noeval_tabpanel_statusline_tabline()
+ CheckScreendump
+
+ let lines =<< trim END
+ set laststatus=2
+ set showtabline=2
+ set showtabpanel=2
+ set statusline=$%=[%f]%=$
+ set tabline=$%=[%f]%=$
+ set tabpanel=$%=[%f]%=$
+ set tabpanelopt=columns:10,vert
+ set fillchars=tpl_vert:│
+ e aaa
+ tabnew
+ e bbb
+ tabnew
+ e ccc
+ END
+ call writefile(lines, 'XTest_tabpanel_noeval_tabpanel_statusline_tabline', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel_noeval_tabpanel_statusline_tabline', {'rows': 10, 'cols': 45})
+ call VerifyScreenDump(buf, 'Test_tabpanel_noeval_tabpanel_statusline_tabline_0', {})
+ call term_sendkeys(buf, ":set tabpanelopt+=align:right\<cr>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_noeval_tabpanel_statusline_tabline_1', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+function! Test_tabpanel_eval_tabpanel_with_linebreaks()
+ CheckScreendump
+
+ let lines =<< trim END
+ function! Expr()
+ return "top\n$%=[%f]%=$\nbottom"
+ endfunction
+ set showtabpanel=2
+ set tabpanel=%!Expr()
+ set tabpanelopt=columns:10
+ e aaa
+ tabnew
+ e bbb
+ tabnew
+ e ccc
+ END
+ call writefile(lines, 'XTest_tabpanel_eval_tabpanel_with_linebreaks', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_tabpanel_eval_tabpanel_with_linebreaks', {'rows': 10, 'cols': 45})
+ call VerifyScreenDump(buf, 'Test_tabpanel_eval_tabpanel_with_linebreaks_0', {})
+ call term_sendkeys(buf, ":set tabpanelopt+=align:right\<cr>")
+ call VerifyScreenDump(buf, 'Test_tabpanel_eval_tabpanel_with_linebreaks_1', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 5475e0a..88653f8 100644
--- a/src/version.c
+++ b/src/version.c
@@ -555,6 +555,11 @@
#if defined(USE_SYSTEM) && defined(UNIX)
"+system()",
#endif
+#if defined(FEAT_TABPANEL)
+ "+tabpanel",
+#else
+ "-tabpanel",
+#endif
"+tag_binary",
"-tag_old_static",
"-tag_any_white",
@@ -4037,7 +4042,7 @@
// start displaying the message lines after half of the blank lines
row = blanklines / 2;
- if ((row >= 2 && Columns >= 50) || colon)
+ if ((row >= 2 && COLUMNS_WITHOUT_TPL() >= 50) || colon)
{
for (i = 0; i < (int)ARRAY_LENGTH(lines); ++i)
{
@@ -4120,7 +4125,7 @@
}
col += (int)STRLEN(vers);
}
- col = (Columns - col) / 2;
+ col = (COLUMNS_WITHOUT_TPL() - col) / 2;
if (col < 0)
col = 0;
@@ -4139,13 +4144,14 @@
else
clen += byte2cells(p[l]);
}
- screen_puts_len(p, l, row, col, *p == '<' ? HL_ATTR(HLF_8) : attr);
+ screen_puts_len(p, l, row, col + TPL_LCOL(NULL),
+ *p == '<' ? HL_ATTR(HLF_8) : attr);
col += clen;
}
// Add the version number to the version line.
if (add_version)
- screen_puts(vers, row, col, 0);
+ screen_puts(vers, row, col + TPL_LCOL(NULL), 0);
}
/*
@@ -4155,6 +4161,9 @@
ex_intro(exarg_T *eap UNUSED)
{
screenclear();
+#if defined(FEAT_TABPANEL)
+ draw_tabpanel();
+#endif
intro_message(TRUE);
wait_return(TRUE);
}
diff --git a/src/vim.h b/src/vim.h
index fbe5c34..26adc18 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -919,6 +919,14 @@
#define FINDFILE_DIR 1 // only directories
#define FINDFILE_BOTH 2 // files and directories
+#if defined(FEAT_TABPANEL)
+# define COLUMNS_WITHOUT_TPL() (Columns - tabpanel_width())
+# define TPL_LCOL(W) tabpanel_leftcol(W)
+#else
+# define COLUMNS_WITHOUT_TPL() Columns
+# define TPL_LCOL(W) 0
+#endif
+
#define W_ENDCOL(wp) ((wp)->w_wincol + (wp)->w_width)
#ifdef FEAT_MENU
# define W_WINROW(wp) ((wp)->w_winrow + (wp)->w_winbar_height)
@@ -1547,6 +1555,9 @@
, HLF_ST // status lines of terminal windows
, HLF_STNC // status lines of not-current terminal windows
, HLF_MSG // message area
+ , HLF_TPL // tabpanel
+ , HLF_TPLS // tabpanel selected
+ , HLF_TPLF // tabpanel filler
, HLF_COUNT // MUST be the last one
} hlf_T;
@@ -1558,7 +1569,8 @@
'B', 'P', 'R', 'L', \
'+', '=', 'k', '<','[', ']', '{', '}', 'x', 'X', \
'*', '#', '_', '!', '.', 'o', 'q', \
- 'z', 'Z', 'g'}
+ 'z', 'Z', 'g', \
+ '%', '^', '&' }
/*
* Values for behaviour in spell_move_to
@@ -2077,6 +2089,7 @@
#define IN_STATUS_LINE 2 // on status or command line
#define IN_SEP_LINE 4 // on vertical separator line
#define IN_OTHER_WIN 8 // in other window but can't go there
+#define IN_TABPANEL 16 // in tabpanel
#define CURSOR_MOVED 0x100
#define MOUSE_FOLD_CLOSE 0x200 // clicked on '-' in fold column
#define MOUSE_FOLD_OPEN 0x400 // clicked on '+' in fold column
diff --git a/src/window.c b/src/window.c
index 1eb32bc..c7fea12 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1386,7 +1386,7 @@
if (flags & (WSP_TOP | WSP_BOT))
{
wp->w_wincol = 0;
- win_new_width(wp, Columns);
+ win_new_width(wp, COLUMNS_WITHOUT_TPL());
wp->w_vsep_width = 0;
}
else
@@ -2086,7 +2086,7 @@
dir = *p_ead;
win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current,
topframe, dir, 0, tabline_height(),
- (int)Columns, topframe->fr_height);
+ (int)COLUMNS_WITHOUT_TPL(), topframe->fr_height);
if (!is_aucmd_win(next_curwin))
win_fix_scroll(TRUE);
}
@@ -2144,7 +2144,7 @@
// frame.
n = frame_minwidth(topfr, NOWIN);
// add one for the rightmost window, it doesn't have a separator
- if (col + width == Columns)
+ if (col + width == COLUMNS_WITHOUT_TPL())
extra_sep = 1;
else
extra_sep = 0;
@@ -2623,6 +2623,10 @@
apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
if (old_curbuf != curbuf)
apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
+#if defined(FEAT_TABPANEL)
+ if (p_stpl > 0)
+ shell_new_columns();
+#endif
return TRUE;
}
@@ -4558,7 +4562,7 @@
if (curwin->w_frame == NULL)
return FAIL;
topframe = curwin->w_frame;
- topframe->fr_width = Columns;
+ topframe->fr_width = COLUMNS_WITHOUT_TPL();
topframe->fr_height = Rows - p_ch;
return OK;
@@ -4588,8 +4592,8 @@
firstwin->w_height = ROWS_AVAIL;
firstwin->w_prev_height = ROWS_AVAIL;
topframe->fr_height = ROWS_AVAIL;
- firstwin->w_width = Columns;
- topframe->fr_width = Columns;
+ firstwin->w_width = COLUMNS_WITHOUT_TPL();
+ topframe->fr_width = COLUMNS_WITHOUT_TPL();
}
/*
@@ -4963,7 +4967,7 @@
tp->tp_lastwin = lastwin;
tp->tp_old_Rows = Rows;
if (tp->tp_old_Columns != -1)
- tp->tp_old_Columns = Columns;
+ tp->tp_old_Columns = COLUMNS_WITHOUT_TPL();
firstwin = NULL;
lastwin = NULL;
return OK;
@@ -5026,12 +5030,12 @@
#endif
))
shell_new_rows();
- if (curtab->tp_old_Columns != Columns)
+ if (curtab->tp_old_Columns != COLUMNS_WITHOUT_TPL())
{
if (starting == 0)
{
shell_new_columns(); // update window widths
- curtab->tp_old_Columns = Columns;
+ curtab->tp_old_Columns = COLUMNS_WITHOUT_TPL();
}
else
curtab->tp_old_Columns = -1; // update window widths later
@@ -5244,6 +5248,9 @@
// Need to redraw the tabline. Tab page contents doesn't change.
redraw_tabline = TRUE;
+#if defined(FEAT_TABPANEL)
+ redraw_tabpanel = TRUE;
+#endif
}
@@ -5667,6 +5674,9 @@
redraw_mode = TRUE;
#endif
redraw_tabline = TRUE;
+#if defined(FEAT_TABPANEL)
+ redraw_tabpanel = TRUE;
+#endif
if (restart_edit)
redraw_later(UPD_VALID); // causes status line redraw
@@ -5792,7 +5802,7 @@
if (!hidden)
win_append(after, new_wp);
new_wp->w_wincol = 0;
- new_wp->w_width = Columns;
+ new_wp->w_width = COLUMNS_WITHOUT_TPL();
// position the display and the cursor at the top of the file.
new_wp->w_topline = 1;
@@ -6181,9 +6191,9 @@
// First try setting the widths of windows with 'winfixwidth'. If that
// doesn't result in the right width, forget about that option.
- frame_new_width(topframe, (int)Columns, FALSE, TRUE);
- if (!frame_check_width(topframe, Columns))
- frame_new_width(topframe, (int)Columns, FALSE, FALSE);
+ frame_new_width(topframe, COLUMNS_WITHOUT_TPL(), FALSE, TRUE);
+ if (!frame_check_width(topframe, COLUMNS_WITHOUT_TPL()))
+ frame_new_width(topframe, COLUMNS_WITHOUT_TPL(), FALSE, FALSE);
(void)win_comp_pos(); // recompute w_winrow and w_wincol
#if 0
@@ -6425,7 +6435,7 @@
if (frp != curfrp)
room -= frame_minheight(frp, NULL);
}
- if (curfrp->fr_width != Columns)
+ if (curfrp->fr_width != COLUMNS_WITHOUT_TPL())
room_cmdline = 0;
else
{
@@ -6438,7 +6448,7 @@
if (height <= room + room_cmdline)
break;
- if (run == 2 || curfrp->fr_width == Columns)
+ if (run == 2 || curfrp->fr_width == COLUMNS_WITHOUT_TPL())
{
height = room + room_cmdline;
break;
@@ -7333,7 +7343,7 @@
// Find bottom frame with width of screen.
frame_T *frp = lastwin->w_frame;
- while (frp->fr_width != Columns && frp->fr_parent != NULL)
+ while (frp->fr_width != COLUMNS_WITHOUT_TPL() && frp->fr_parent != NULL)
frp = frp->fr_parent;
// Avoid changing the height of a window with 'winfixheight' set.