summaryrefslogtreecommitdiff
path: root/examples/dte/screen-tabbar.c
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2026-01-21 22:52:54 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2026-01-21 22:52:54 +0100
commitdcacc00e3750300617ba6e16eb346713f91a783a (patch)
tree38e2d4fb5ed9d119711d4295c6eda4b014af73fd /examples/dte/screen-tabbar.c
parent58dac10aeb8f5a041c46bddbeaf4c7966a99b998 (diff)
downloadcrep-dcacc00e3750300617ba6e16eb346713f91a783a.tar.gz
Remove testing data
Diffstat (limited to 'examples/dte/screen-tabbar.c')
-rw-r--r--examples/dte/screen-tabbar.c176
1 files changed, 0 insertions, 176 deletions
diff --git a/examples/dte/screen-tabbar.c b/examples/dte/screen-tabbar.c
deleted file mode 100644
index 57de14e..0000000
--- a/examples/dte/screen-tabbar.c
+++ /dev/null
@@ -1,176 +0,0 @@
1#include "screen.h"
2#include "util/numtostr.h"
3#include "util/strtonum.h"
4
5static size_t tab_title_width(size_t tab_number, const char *filename)
6{
7 return 3 + size_str_width(tab_number) + u_str_width(filename);
8}
9
10static void update_tab_title_width(View *view, size_t tab_number)
11{
12 size_t w = tab_title_width(tab_number, buffer_filename(view->buffer));
13 view->tt_width = w;
14 view->tt_truncated_width = w;
15}
16
17static void update_first_tab_idx(Window *window)
18{
19 size_t max_first_idx = window->views.count;
20 for (size_t w = 0; max_first_idx > 0; max_first_idx--) {
21 const View *view = window->views.ptrs[max_first_idx - 1];
22 w += view->tt_truncated_width;
23 if (w > window->w) {
24 break;
25 }
26 }
27
28 size_t min_first_idx = window->views.count;
29 for (size_t w = 0; min_first_idx > 0; min_first_idx--) {
30 const View *view = window->views.ptrs[min_first_idx - 1];
31 if (w || view == window->view) {
32 w += view->tt_truncated_width;
33 }
34 if (w > window->w) {
35 break;
36 }
37 }
38
39 size_t idx = CLAMP(window->first_tab_idx, min_first_idx, max_first_idx);
40 window->first_tab_idx = idx;
41}
42
43static void calculate_tabbar(Window *window)
44{
45 int total_w = 0;
46 for (size_t i = 0, n = window->views.count; i < n; i++) {
47 View *view = window->views.ptrs[i];
48 if (view == window->view) {
49 // Make sure current tab is visible
50 window->first_tab_idx = MIN(i, window->first_tab_idx);
51 }
52 update_tab_title_width(view, i + 1);
53 total_w += view->tt_width;
54 }
55
56 if (total_w <= window->w) {
57 // All tabs fit without truncating
58 window->first_tab_idx = 0;
59 return;
60 }
61
62 // Truncate all wide tabs
63 total_w = 0;
64 int truncated_count = 0;
65 for (size_t i = 0, n = window->views.count; i < n; i++) {
66 View *view = window->views.ptrs[i];
67 int truncated_w = 20;
68 if (view->tt_width > truncated_w) {
69 view->tt_truncated_width = truncated_w;
70 total_w += truncated_w;
71 truncated_count++;
72 } else {
73 total_w += view->tt_width;
74 }
75 }
76
77 if (total_w > window->w) {
78 // Not all tabs fit even after truncating wide tabs
79 update_first_tab_idx(window);
80 return;
81 }
82
83 // All tabs fit after truncating wide tabs
84 int extra = window->w - total_w;
85
86 // Divide extra space between truncated tabs
87 while (extra > 0) {
88 BUG_ON(truncated_count == 0);
89 int extra_avg = extra / truncated_count;
90 int extra_mod = extra % truncated_count;
91
92 for (size_t i = 0, n = window->views.count; i < n; i++) {
93 View *view = window->views.ptrs[i];
94 int add = view->tt_width - view->tt_truncated_width;
95 if (add == 0) {
96 continue;
97 }
98
99 int avail = extra_avg;
100 if (extra_mod) {
101 // This is needed for equal divide
102 if (extra_avg == 0) {
103 avail++;
104 extra_mod--;
105 }
106 }
107 if (add > avail) {
108 add = avail;
109 } else {
110 truncated_count--;
111 }
112
113 view->tt_truncated_width += add;
114 extra -= add;
115 }
116 }
117
118 window->first_tab_idx = 0;
119}
120
121static void print_tab_title(Terminal *term, const ColorScheme *colors, const View *view, size_t idx)
122{
123 const char *filename = buffer_filename(view->buffer);
124 int skip = view->tt_width - view->tt_truncated_width;
125 if (skip > 0) {
126 filename += u_skip_chars(filename, &skip);
127 }
128
129 const char *tab_number = uint_to_str((unsigned int)idx + 1);
130 TermOutputBuffer *obuf = &term->obuf;
131 bool is_active_tab = (view == view->window->view);
132 bool is_modified = buffer_modified(view->buffer);
133 bool left_overflow = (obuf->x == 0 && idx > 0);
134
135 set_builtin_color(term, colors, is_active_tab ? BC_ACTIVETAB : BC_INACTIVETAB);
136 term_put_char(obuf, left_overflow ? '<' : ' ');
137 term_add_str(obuf, tab_number);
138 term_put_char(obuf, is_modified ? '+' : ':');
139 term_add_str(obuf, filename);
140
141 size_t ntabs = view->window->views.count;
142 bool right_overflow = (obuf->x == (obuf->width - 1) && idx < (ntabs - 1));
143 term_put_char(obuf, right_overflow ? '>' : ' ');
144}
145
146void print_tabbar(Terminal *term, const ColorScheme *colors, Window *window)
147{
148 TermOutputBuffer *obuf = &term->obuf;
149 term_output_reset(term, window->x, window->w, 0);
150 term_move_cursor(obuf, window->x, window->y);
151 calculate_tabbar(window);
152
153 size_t i = window->first_tab_idx;
154 size_t n = window->views.count;
155 for (; i < n; i++) {
156 const View *view = window->views.ptrs[i];
157 if (obuf->x + view->tt_truncated_width > window->w) {
158 break;
159 }
160 print_tab_title(term, colors, view, i);
161 }
162
163 set_builtin_color(term, colors, BC_TABBAR);
164
165 if (i == n) {
166 term_clear_eol(term);
167 return;
168 }
169
170 while (obuf->x < obuf->width - 1) {
171 term_put_char(obuf, ' ');
172 }
173 if (obuf->x == obuf->width - 1) {
174 term_put_char(obuf, '>');
175 }
176}