refactor: move tabline code to statusline.c (#21008)

* refactor: move tabline code to statusline.c

Problem:	Tabline code is closely related to statusline, but still left over in drawscreen.c and screen.c.
Solution:	Move it to statusline.c.

* refactor: add statusline_defs.h
This commit is contained in:
luukvbaal
2022-11-10 12:05:16 +01:00
committed by GitHub
parent befae73044
commit 69507c0204
13 changed files with 461 additions and 459 deletions

View File

@@ -582,65 +582,6 @@ void check_for_delay(bool check_msg_scroll)
}
}
/// Clear status line, window bar or tab page line click definition table
///
/// @param[out] tpcd Table to clear.
/// @param[in] tpcd_size Size of the table.
void stl_clear_click_defs(StlClickDefinition *const click_defs, const long click_defs_size)
{
if (click_defs != NULL) {
for (long i = 0; i < click_defs_size; i++) {
if (i == 0 || click_defs[i].func != click_defs[i - 1].func) {
xfree(click_defs[i].func);
}
}
memset(click_defs, 0, (size_t)click_defs_size * sizeof(click_defs[0]));
}
}
/// Allocate or resize the click definitions array if needed.
StlClickDefinition *stl_alloc_click_defs(StlClickDefinition *cdp, long width, size_t *size)
{
if (*size < (size_t)width) {
xfree(cdp);
*size = (size_t)width;
cdp = xcalloc(*size, sizeof(StlClickDefinition));
}
return cdp;
}
/// Fill the click definitions array if needed.
void stl_fill_click_defs(StlClickDefinition *click_defs, StlClickRecord *click_recs, char *buf,
int width, bool tabline)
{
if (click_defs == NULL) {
return;
}
int col = 0;
int len = 0;
StlClickDefinition cur_click_def = {
.type = kStlClickDisabled,
};
for (int i = 0; click_recs[i].start != NULL; i++) {
len += vim_strnsize(buf, (int)(click_recs[i].start - buf));
while (col < len) {
click_defs[col++] = cur_click_def;
}
buf = (char *)click_recs[i].start;
cur_click_def = click_recs[i].def;
if (!tabline && !(cur_click_def.type == kStlClickDisabled
|| cur_click_def.type == kStlClickFuncRun)) {
// window bar and status line only support click functions
cur_click_def.type = kStlClickDisabled;
}
}
while (col < width) {
click_defs[col++] = cur_click_def;
}
}
/// Set cursor to its position in the current window.
void setcursor(void)
{
@@ -959,217 +900,6 @@ static void recording_mode(int attr)
}
}
/// Draw the tab pages line at the top of the Vim window.
void draw_tabline(void)
{
int tabcount = 0;
int tabwidth = 0;
int col = 0;
int scol = 0;
int attr;
win_T *wp;
win_T *cwp;
int wincount;
int modified;
int c;
int len;
int attr_nosel = HL_ATTR(HLF_TP);
int attr_fill = HL_ATTR(HLF_TPF);
char_u *p;
int room;
int use_sep_chars = (t_colors < 8);
if (default_grid.chars == NULL) {
return;
}
redraw_tabline = false;
if (ui_has(kUITabline)) {
ui_ext_tabline_update();
return;
}
if (tabline_height() < 1) {
return;
}
// Init TabPageIdxs[] to zero: Clicking outside of tabs has no effect.
assert(Columns == tab_page_click_defs_size);
stl_clear_click_defs(tab_page_click_defs, tab_page_click_defs_size);
// Use the 'tabline' option if it's set.
if (*p_tal != NUL) {
win_redr_custom(NULL, false, false);
} else {
FOR_ALL_TABS(tp) {
tabcount++;
}
if (tabcount > 0) {
tabwidth = (Columns - 1 + tabcount / 2) / tabcount;
}
if (tabwidth < 6) {
tabwidth = 6;
}
attr = attr_nosel;
tabcount = 0;
FOR_ALL_TABS(tp) {
if (col >= Columns - 4) {
break;
}
scol = col;
if (tp == curtab) {
cwp = curwin;
wp = firstwin;
} else {
cwp = tp->tp_curwin;
wp = tp->tp_firstwin;
}
if (tp->tp_topframe == topframe) {
attr = win_hl_attr(cwp, HLF_TPS);
}
if (use_sep_chars && col > 0) {
grid_putchar(&default_grid, '|', 0, col++, attr);
}
if (tp->tp_topframe != topframe) {
attr = win_hl_attr(cwp, HLF_TP);
}
grid_putchar(&default_grid, ' ', 0, col++, attr);
modified = false;
for (wincount = 0; wp != NULL; wp = wp->w_next, wincount++) {
if (bufIsChanged(wp->w_buffer)) {
modified = true;
}
}
if (modified || wincount > 1) {
if (wincount > 1) {
vim_snprintf((char *)NameBuff, MAXPATHL, "%d", wincount);
len = (int)strlen(NameBuff);
if (col + len >= Columns - 3) {
break;
}
grid_puts_len(&default_grid, NameBuff, len, 0, col,
hl_combine_attr(attr, win_hl_attr(cwp, HLF_T)));
col += len;
}
if (modified) {
grid_puts_len(&default_grid, "+", 1, 0, col++, attr);
}
grid_putchar(&default_grid, ' ', 0, col++, attr);
}
room = scol - col + tabwidth - 1;
if (room > 0) {
// Get buffer name in NameBuff[]
get_trans_bufname(cwp->w_buffer);
shorten_dir(NameBuff);
len = vim_strsize((char *)NameBuff);
p = (char_u *)NameBuff;
while (len > room) {
len -= ptr2cells((char *)p);
MB_PTR_ADV(p);
}
if (len > Columns - col - 1) {
len = Columns - col - 1;
}
grid_puts_len(&default_grid, (char *)p, (int)STRLEN(p), 0, col, attr);
col += len;
}
grid_putchar(&default_grid, ' ', 0, col++, attr);
// Store the tab page number in tab_page_click_defs[], so that
// jump_to_mouse() knows where each one is.
tabcount++;
while (scol < col) {
tab_page_click_defs[scol++] = (StlClickDefinition) {
.type = kStlClickTabSwitch,
.tabnr = tabcount,
.func = NULL,
};
}
}
if (use_sep_chars) {
c = '_';
} else {
c = ' ';
}
grid_fill(&default_grid, 0, 1, col, Columns, c, c, attr_fill);
// Put an "X" for closing the current tab if there are several.
if (first_tabpage->tp_next != NULL) {
grid_putchar(&default_grid, 'X', 0, Columns - 1, attr_nosel);
tab_page_click_defs[Columns - 1] = (StlClickDefinition) {
.type = kStlClickTabClose,
.tabnr = 999,
.func = NULL,
};
}
}
// Reset the flag here again, in case evaluating 'tabline' causes it to be
// set.
redraw_tabline = false;
}
static void ui_ext_tabline_update(void)
{
Arena arena = ARENA_EMPTY;
size_t n_tabs = 0;
FOR_ALL_TABS(tp) {
n_tabs++;
}
Array tabs = arena_array(&arena, n_tabs);
FOR_ALL_TABS(tp) {
Dictionary tab_info = arena_dict(&arena, 2);
PUT_C(tab_info, "tab", TABPAGE_OBJ(tp->handle));
win_T *cwp = (tp == curtab) ? curwin : tp->tp_curwin;
get_trans_bufname(cwp->w_buffer);
PUT_C(tab_info, "name", STRING_OBJ(arena_string(&arena, cstr_as_string((char *)NameBuff))));
ADD_C(tabs, DICTIONARY_OBJ(tab_info));
}
size_t n_buffers = 0;
FOR_ALL_BUFFERS(buf) {
n_buffers += buf->b_p_bl ? 1 : 0;
}
Array buffers = arena_array(&arena, n_buffers);
FOR_ALL_BUFFERS(buf) {
// Do not include unlisted buffers
if (!buf->b_p_bl) {
continue;
}
Dictionary buffer_info = arena_dict(&arena, 2);
PUT_C(buffer_info, "buffer", BUFFER_OBJ(buf->handle));
get_trans_bufname(buf);
PUT_C(buffer_info, "name", STRING_OBJ(arena_string(&arena, cstr_as_string((char *)NameBuff))));
ADD_C(buffers, DICTIONARY_OBJ(buffer_info));
}
ui_call_tabline_update(curtab->handle, tabs, curbuf->handle, buffers);
arena_mem_free(arena_finish(&arena));
}
void get_trans_bufname(buf_T *buf)
{
if (buf_spname(buf) != NULL) {