blob: 0472e6b4be2da57dd80f87e0f0f3c9ccf8303406 [file] [log] [blame]
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +02001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * tabpanel.c:
12 */
13
14#include "vim.h"
15
16#if defined(FEAT_TABPANEL) || defined(PROTO)
17
18static void do_by_tplmode(int tplmode, int col_start, int col_end,
Hirohito Higashic659e4a2025-05-16 19:34:34 +020019 int *pcurtab_row, int *ptabpagenr);
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +020020
21// set pcurtab_row. don't redraw tabpanel.
22#define TPLMODE_GET_CURTAB_ROW 0
23// set ptabpagenr. don't redraw tabpanel.
24#define TPLMODE_GET_TABPAGENR 1
25// redraw tabpanel.
26#define TPLMODE_REDRAW 2
27
28#define TPL_FILLCHAR ' '
29
30#define VERT_LEN 1
31
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +020032// tpl_align's values
33#define ALIGN_LEFT 0
34#define ALIGN_RIGHT 1
35
36static char_u *opt_name = (char_u *)"tabpanel";
37static int opt_scope = OPT_LOCAL;
38static int tpl_align = ALIGN_LEFT;
39static int tpl_columns = 20;
Hirohito Higashic659e4a2025-05-16 19:34:34 +020040static int tpl_is_vert = FALSE;
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +020041
42typedef struct {
43 win_T *wp;
44 win_T *cwp;
45 char_u *user_defined;
46 int maxrow;
47 int offsetrow;
48 int *prow;
49 int *pcol;
50 int attr;
51 int col_start;
52 int col_end;
53} tabpanel_T;
54
55 int
56tabpanelopt_changed(void)
57{
58 char_u *p;
59 int new_align = ALIGN_LEFT;
60 int new_columns = 20;
Hirohito Higashic659e4a2025-05-16 19:34:34 +020061 int new_is_vert = FALSE;
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +020062
63 p = p_tplo;
64 while (*p != NUL)
65 {
66 if (STRNCMP(p, "align:left", 10) == 0)
67 {
68 p += 10;
69 new_align = ALIGN_LEFT;
70 }
71 else if (STRNCMP(p, "align:right", 11) == 0)
72 {
73 p += 11;
74 new_align = ALIGN_RIGHT;
75 }
76 else if (STRNCMP(p, "columns:", 8) == 0 && VIM_ISDIGIT(p[8]))
77 {
78 p += 8;
79 new_columns = getdigits(&p);
80 }
81 else if (STRNCMP(p, "vert", 4) == 0)
82 {
83 p += 4;
Hirohito Higashic659e4a2025-05-16 19:34:34 +020084 new_is_vert = TRUE;
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +020085 }
86
87 if (*p != ',' && *p != NUL)
88 return FAIL;
89 if (*p == ',')
90 ++p;
91 }
92
93 tpl_align = new_align;
94 tpl_columns = new_columns;
Hirohito Higashic659e4a2025-05-16 19:34:34 +020095 tpl_is_vert = new_is_vert;
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +020096
97 return OK;
98}
99
100/*
101 * Return the width of tabpanel.
102 */
103 int
104tabpanel_width(void)
105{
106 if (msg_scrolled != 0)
107 return 0;
108
109 switch (p_stpl)
110 {
111 case 0:
112 return 0;
113 case 1:
114 if (first_tabpage->tp_next == NULL)
115 return 0;
116 }
117 if (Columns < tpl_columns)
118 return 0;
119 else
120 return tpl_columns;
121}
122
123/*
124 * Return the offset of a window considering the width of tabpanel.
125 */
126 int
127tabpanel_leftcol(win_T *wp)
128{
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200129 if (cmdline_pum_active() || (wp != NULL && WIN_IS_POPUP(wp)))
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200130 return 0;
131 else
132 return tpl_align == ALIGN_RIGHT ? 0 : tabpanel_width();
133}
134
135/*
136 * draw the tabpanel.
137 */
138 void
139draw_tabpanel(void)
140{
141 int saved_KeyTyped = KeyTyped;
142 int saved_got_int = got_int;
143 int maxwidth = tabpanel_width();
144 int vs_attr = HL_ATTR(HLF_C);
145 int curtab_row = 0;
146#ifndef MSWIN
147 int row = 0;
148 int off = 0;
149#endif
150int vsrow = 0;
151 int is_right = tpl_align == ALIGN_RIGHT;
152
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200153 if (maxwidth == 0)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200154 return;
155
156#ifndef MSWIN
157 // We need this section only for the Vim running on WSL.
158 for (row = 0; row < cmdline_row; row++)
159 {
160 if (is_right)
161 off = LineOffset[row] + Columns - maxwidth;
162 else
163 off = LineOffset[row];
164
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200165 vim_memset(ScreenLines + off, ' ', (size_t)maxwidth * sizeof(schar_T));
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200166 if (enc_utf8)
167 vim_memset(ScreenLinesUC + off, -1,
168 (size_t)maxwidth * sizeof(u8char_T));
169 }
170#endif
171
172 // Reset got_int to avoid build_stl_str_hl() isn't evaluted.
173 got_int = FALSE;
174
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200175 if (tpl_is_vert)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200176 {
177 if (is_right)
178 {
179 // draw main contents in tabpanel
180 do_by_tplmode(TPLMODE_GET_CURTAB_ROW, VERT_LEN,
181 maxwidth - VERT_LEN, &curtab_row, NULL);
182 do_by_tplmode(TPLMODE_REDRAW, VERT_LEN, maxwidth, &curtab_row,
183 NULL);
184 // clear for multi-byte vert separater
185 screen_fill(0, cmdline_row, COLUMNS_WITHOUT_TPL(),
186 COLUMNS_WITHOUT_TPL() + VERT_LEN,
187 TPL_FILLCHAR, TPL_FILLCHAR, vs_attr);
188 // draw vert separater in tabpanel
189 for (vsrow = 0; vsrow < cmdline_row; vsrow++)
190 screen_putchar(curwin->w_fill_chars.tpl_vert, vsrow,
191 COLUMNS_WITHOUT_TPL(), vs_attr);
192 }
193 else
194 {
195 // draw main contents in tabpanel
196 do_by_tplmode(TPLMODE_GET_CURTAB_ROW, 0, maxwidth - VERT_LEN,
197 &curtab_row, NULL);
198 do_by_tplmode(TPLMODE_REDRAW, 0, maxwidth - VERT_LEN,
199 &curtab_row, NULL);
200 // clear for multi-byte vert separater
201 screen_fill(0, cmdline_row, maxwidth - VERT_LEN,
202 maxwidth, TPL_FILLCHAR, TPL_FILLCHAR, vs_attr);
203 // draw vert separater in tabpanel
204 for (vsrow = 0; vsrow < cmdline_row; vsrow++)
205 screen_putchar(curwin->w_fill_chars.tpl_vert, vsrow,
206 maxwidth - VERT_LEN, vs_attr);
207 }
208 }
209 else
210 {
211 do_by_tplmode(TPLMODE_GET_CURTAB_ROW, 0, maxwidth, &curtab_row, NULL);
212 do_by_tplmode(TPLMODE_REDRAW, 0, maxwidth, &curtab_row, NULL);
213 }
214
215 got_int |= saved_got_int;
216
217 // A user function may reset KeyTyped, restore it.
218 KeyTyped = saved_KeyTyped;
219
220 redraw_tabpanel = FALSE;
221}
222
223/*
224 * Return tabpagenr when clicking and dragging in tabpanel.
225 */
226 int
227get_tabpagenr_on_tabpanel(void)
228{
229 int maxwidth = tabpanel_width();
230 int curtab_row = 0;
231 int tabpagenr = 0;
232
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200233 if (maxwidth == 0)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200234 return -1;
235
236 do_by_tplmode(TPLMODE_GET_CURTAB_ROW, 0, maxwidth, &curtab_row, NULL);
237 do_by_tplmode(TPLMODE_GET_TABPAGENR, 0, maxwidth, &curtab_row,
238 &tabpagenr);
239
240 return tabpagenr;
241}
242
243/*
244 * Fill tailing area between {start_row} and {end_row - 1}.
245 */
246 static void
247screen_fill_tailing_area(
248 int tplmode,
249 int row_start,
250 int row_end,
251 int col_start,
252 int col_end,
253 int attr)
254{
255 int is_right = tpl_align == ALIGN_RIGHT;
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200256 if (tplmode == TPLMODE_REDRAW)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200257 screen_fill(row_start, row_end,
258 (is_right ? COLUMNS_WITHOUT_TPL() : 0) + col_start,
259 (is_right ? COLUMNS_WITHOUT_TPL() : 0) + col_end,
260 TPL_FILLCHAR, TPL_FILLCHAR, attr);
261}
262
263/*
264 * screen_puts_len() for tabpanel.
265 */
266 static void
267screen_puts_len_for_tabpanel(
268 int tplmode,
269 char_u *p,
270 int len,
271 int attr,
272 tabpanel_T *pargs)
273{
274 int j, k;
275 int chlen;
276 int chcells;
277 char_u buf[IOSIZE];
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200278 char_u *temp;
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200279
280 for (j = 0; j < len;)
281 {
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200282 if (tplmode != TPLMODE_GET_CURTAB_ROW
283 && pargs->maxrow <= *pargs->prow - pargs->offsetrow)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200284 break;
285
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200286 if (p[j] == '\n' || p[j] == '\r')
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200287 {
288 // fill the tailing area of current row.
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200289 if (*pargs->prow - pargs->offsetrow >= 0
290 && *pargs->prow - pargs->offsetrow < pargs->maxrow)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200291 screen_fill_tailing_area(tplmode,
292 *pargs->prow - pargs->offsetrow,
293 *pargs->prow - pargs->offsetrow + 1,
294 *pargs->pcol, pargs->col_end, attr);
295 (*pargs->prow)++;
296 *pargs->pcol = pargs->col_start;
297 j++;
298 }
299 else
300 {
301 if (has_mbyte)
302 chlen = (*mb_ptr2len)(p + j);
303 else
304 chlen = (int)STRLEN(p + j);
305
306 for (k = 0; k < chlen; k++)
307 buf[k] = p[j + k];
308 buf[chlen] = NUL;
309 j += chlen;
310
311 // Make all characters printable.
312 temp = transstr(buf);
313 if (temp != NULL)
314 {
315 vim_strncpy(buf, temp, sizeof(buf) - 1);
316 vim_free(temp);
317 }
318
319 if (has_mbyte)
320 chcells = (*mb_ptr2cells)(buf);
321 else
322 chcells = 1;
323
324 if (pargs->col_end < (*pargs->pcol) + chcells)
325 {
326 // fill the tailing area of current row.
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200327 if (*pargs->prow - pargs->offsetrow >= 0
328 && *pargs->prow - pargs->offsetrow < pargs->maxrow)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200329 screen_fill_tailing_area(tplmode,
330 *pargs->prow - pargs->offsetrow,
331 *pargs->prow - pargs->offsetrow + 1,
332 *pargs->pcol, pargs->col_end, attr);
333 *pargs->pcol = pargs->col_end;
334
335 if (pargs->col_end < chcells)
336 break;
337 }
338
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200339 if (*pargs->pcol + chcells <= pargs->col_end)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200340 {
341 int off = (tpl_align == ALIGN_RIGHT)
342 ? COLUMNS_WITHOUT_TPL()
343 : 0;
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200344 if (TPLMODE_REDRAW == tplmode
345 && (*pargs->prow - pargs->offsetrow >= 0
346 && *pargs->prow - pargs->offsetrow < pargs->maxrow))
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200347 screen_puts(buf, *pargs->prow - pargs->offsetrow,
348 *pargs->pcol + off, attr);
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200349 *pargs->pcol += chcells;
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200350 }
351 }
352 }
353}
354
355/*
356 * default tabpanel drawing behavior if 'tabpanel' option is empty.
357 */
358 static void
359draw_tabpanel_default(int tplmode, tabpanel_T *pargs)
360{
361 int modified;
362 int wincount;
363 int len = 0;
364 char_u buf[2] = { NUL, NUL };
365
366 modified = FALSE;
367 for (wincount = 0; pargs->wp != NULL;
368 pargs->wp = pargs->wp->w_next, ++wincount)
369 if (bufIsChanged(pargs->wp->w_buffer))
370 modified = TRUE;
371
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200372 if (modified || wincount > 1)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200373 {
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200374 if (wincount > 1)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200375 {
376 vim_snprintf((char *)NameBuff, MAXPATHL, "%d", wincount);
377 len = (int)STRLEN(NameBuff);
378 screen_puts_len_for_tabpanel(tplmode, NameBuff, len,
379#if defined(FEAT_SYN_HL)
380 hl_combine_attr(pargs->attr, HL_ATTR(HLF_T)),
381#else
382 pargs->attr,
383#endif
384 pargs);
385 }
386 if (modified)
387 {
388 buf[0] = '+';
389 screen_puts_len_for_tabpanel(tplmode, buf, 1, pargs->attr, pargs);
390 }
391
392 buf[0] = TPL_FILLCHAR;
393 screen_puts_len_for_tabpanel(tplmode, buf, 1, pargs->attr, pargs);
394 }
395
396 get_trans_bufname(pargs->cwp->w_buffer);
397 shorten_dir(NameBuff);
398 len = (int)STRLEN(NameBuff);
399 screen_puts_len_for_tabpanel(tplmode, NameBuff, len, pargs->attr, pargs);
400
401 // fill the tailing area of current row.
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200402 if (*pargs->prow - pargs->offsetrow >= 0
403 && *pargs->prow - pargs->offsetrow < pargs->maxrow)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200404 screen_fill_tailing_area(tplmode, *pargs->prow - pargs->offsetrow,
405 *pargs->prow - pargs->offsetrow + 1,
406 *pargs->pcol, pargs->col_end, pargs->attr);
407 *pargs->pcol = pargs->col_end;
408}
409
410/*
411 * default tabpanel drawing behavior if 'tabpanel' option is NOT empty.
412 */
413 static void
414draw_tabpanel_userdefined(int tplmode, tabpanel_T *pargs)
415{
416 char_u *p;
417 int p_crb_save;
418 char_u buf[IOSIZE];
419 stl_hlrec_T *hltab;
420 stl_hlrec_T *tabtab;
421 int curattr;
422 int n;
423
424 // Temporarily reset 'cursorbind', we don't want a side effect from moving
425 // the cursor away and back.
426 p_crb_save = pargs->cwp->w_p_crb;
427 pargs->cwp->w_p_crb = FALSE;
428
429 // Make a copy, because the statusline may include a function call that
430 // might change the option value and free the memory.
431 p = vim_strsave(pargs->user_defined);
432
433 build_stl_str_hl(pargs->cwp, buf, sizeof(buf),
434 p, opt_name, opt_scope,
435 TPL_FILLCHAR, pargs->col_end - pargs->col_start, &hltab, &tabtab);
436
437 vim_free(p);
438 pargs->cwp->w_p_crb = p_crb_save;
439
440 curattr = pargs->attr;
441 p = buf;
442 for (n = 0; hltab[n].start != NULL; n++)
443 {
444 screen_puts_len_for_tabpanel(tplmode, p, (int)(hltab[n].start - p),
445 curattr, pargs);
446 p = hltab[n].start;
447 if (hltab[n].userhl == 0)
448 curattr = pargs->attr;
449 else if (hltab[n].userhl < 0)
450 curattr = syn_id2attr(-hltab[n].userhl);
451#ifdef FEAT_TERMINAL
452 else if (pargs->wp != NULL && pargs->wp != curwin
453 && bt_terminal(pargs->wp->w_buffer)
454 && pargs->wp->w_status_height != 0)
455 curattr = highlight_stltermnc[hltab[n].userhl - 1];
456 else if (pargs->wp != NULL && bt_terminal(pargs->wp->w_buffer)
457 && pargs->wp->w_status_height != 0)
458 curattr = highlight_stlterm[hltab[n].userhl - 1];
459#endif
460 else if (pargs->wp != NULL && pargs->wp != curwin
461 && pargs->wp->w_status_height != 0)
462 curattr = highlight_stlnc[hltab[n].userhl - 1];
463 else
464 curattr = highlight_user[hltab[n].userhl - 1];
465 }
466 screen_puts_len_for_tabpanel(tplmode, p, (int)STRLEN(p), curattr, pargs);
467
468 // fill the tailing area of current row.
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200469 if (*pargs->prow - pargs->offsetrow >= 0
470 && *pargs->prow - pargs->offsetrow < pargs->maxrow)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200471 screen_fill_tailing_area(tplmode, *pargs->prow - pargs->offsetrow,
472 *pargs->prow - pargs->offsetrow + 1, *pargs->pcol,
473 pargs->col_end, curattr);
474 *pargs->pcol = pargs->col_end;
475}
476
477 static char_u *
478starts_with_percent_and_bang(tabpanel_T *pargs)
479{
480 int len = 0;
481 char_u *usefmt = p_tpl;
482
483 if (usefmt == NULL)
484 return NULL;
485
486 len = (int)STRLEN(usefmt);
487
488 if (len == 0)
489 return NULL;
490
491#ifdef FEAT_EVAL
492 // if "fmt" was set insecurely it needs to be evaluated in the sandbox
493 int use_sandbox = was_set_insecurely(opt_name, opt_scope);
494
495 // When the format starts with "%!" then evaluate it as an expression and
496 // use the result as the actual format string.
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200497 if (len > 1 && usefmt[0] == '%' && usefmt[1] == '!')
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200498 {
499 typval_T tv;
500 char_u *p = NULL;
501
502 tv.v_type = VAR_NUMBER;
503 tv.vval.v_number = pargs->cwp->w_id;
504 set_var((char_u *)"g:tabpanel_winid", &tv, FALSE);
505
506 p = eval_to_string_safe(usefmt + 2, use_sandbox, FALSE, FALSE);
507 if (p != NULL)
508 usefmt = p;
509
510 do_unlet((char_u *)"g:tabpanel_winid", TRUE);
511 }
512#endif
513
514 return usefmt;
515}
516
517/*
518 * do something by tplmode for drawing tabpanel.
519 */
520 static void
521do_by_tplmode(
522 int tplmode,
523 int col_start,
524 int col_end,
525 int *pcurtab_row,
526 int *ptabpagenr)
527{
528 int attr_tplf = HL_ATTR(HLF_TPLF);
529 int attr_tpls = HL_ATTR(HLF_TPLS);
530 int attr_tpl = HL_ATTR(HLF_TPL);
531 int col = col_start;
532 int row = 0;
533 tabpage_T *tp = NULL;
534 typval_T v;
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200535 tabpanel_T args;
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200536
537 args.maxrow = cmdline_row;
538 args.offsetrow = 0;
539 args.col_start = col_start;
540 args.col_end = col_end;
541
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200542 if (tplmode != TPLMODE_GET_CURTAB_ROW && args.maxrow > 0)
543 while (args.offsetrow + args.maxrow <= *pcurtab_row)
544 args.offsetrow += args.maxrow;
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200545
546 tp = first_tabpage;
547
548 for (row = 0; tp != NULL; row++)
549 {
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200550 if (tplmode != TPLMODE_GET_CURTAB_ROW
551 && args.maxrow <= row - args.offsetrow)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200552 break;
553
554 col = col_start;
555
556 v.v_type = VAR_NUMBER;
557 v.vval.v_number = tabpage_index(tp);
558 set_var((char_u *)"g:actual_curtabpage", &v, TRUE);
559
560 if (tp->tp_topframe == topframe)
561 {
562 args.attr = attr_tpls;
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200563 if (tplmode == TPLMODE_GET_CURTAB_ROW)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200564 {
565 *pcurtab_row = row;
566 break;
567 }
568 }
569 else
570 args.attr = attr_tpl;
571
572 if (tp == curtab)
573 {
574 args.cwp = curwin;
575 args.wp = firstwin;
576 }
577 else
578 {
579 args.cwp = tp->tp_curwin;
580 args.wp = tp->tp_firstwin;
581 }
582
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200583 char_u *usefmt = starts_with_percent_and_bang(&args);
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200584 if (usefmt != NULL)
585 {
586 char_u buf[IOSIZE];
587 char_u *p = usefmt;
588 size_t i = 0;
589
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200590 while (p[i] != NUL)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200591 {
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200592 while (p[i] == '\n' || p[i] == '\r')
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200593 {
594 // fill the tailing area of current row.
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200595 if (row - args.offsetrow >= 0
596 && row - args.offsetrow < args.maxrow)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200597 screen_fill_tailing_area(tplmode,
598 row - args.offsetrow,
599 row - args.offsetrow + 1,
600 col, args.col_end, args.attr);
601 row++;
602 col = col_start;
603 p++;
604 }
605
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200606 while (p[i] != '\n' && p[i] != '\r' && (p[i] != NUL))
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200607 {
608 if (i + 1 >= sizeof(buf))
609 break;
610 buf[i] = p[i];
611 i++;
612 }
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200613 buf[i] = NUL;
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200614
615 args.user_defined = buf;
616 args.prow = &row;
617 args.pcol = &col;
618 draw_tabpanel_userdefined(tplmode, &args);
619
620 p += i;
621 i = 0;
622 }
623 if (usefmt != p_tpl)
624 VIM_CLEAR(usefmt);
625 }
626 else
627 {
628 args.user_defined = NULL;
629 args.prow = &row;
630 args.pcol = &col;
631 draw_tabpanel_default(tplmode, &args);
632 }
633
634 do_unlet((char_u *)"g:actual_curtabpage", TRUE);
635
636 tp = tp->tp_next;
637
Hirohito Higashic659e4a2025-05-16 19:34:34 +0200638 if ((tplmode == TPLMODE_GET_TABPAGENR)
Naruhiko Nishinobe5bd4d2025-05-14 21:20:28 +0200639 && (mouse_row <= (row - args.offsetrow)))
640 {
641 *ptabpagenr = v.vval.v_number;
642 break;
643 }
644 }
645
646 // fill the area of TabPanelFill.
647 screen_fill_tailing_area(tplmode, row - args.offsetrow, args.maxrow,
648 args.col_start, args.col_end, attr_tplf);
649}
650
651#endif // FEAT_TABPANEL