some redraw fixes
[k8sterm.git] / src / x11drawtabs.c
blob69c1f8fd1c3a7abc6d3ac2fded532f14ee37929f
1 // return char length
2 static inline int xStringCharSize (const char *str, int bytelen) {
3 return (bytelen >= K8T_UTF_SIZ || k8t_UTF8IsFull(str, bytelen) ? k8t_UTF8Size(str) : 0);
7 static int xStringWidth (int fontset, const char *str, int bytelen) {
8 XFontSet xfontset = dc.font[fontset].set;
9 int wdt = 0;
10 XRectangle r;
12 if (needConversion) {
13 while (bytelen > 0) {
14 const char *e = str;
16 memset(&r, 0, sizeof(r));
17 if ((unsigned char)(*e) > 127) {
18 // use UTF-8
19 while (bytelen > 0 && (unsigned char)(*e) > 127) { ++e; --bytelen; }
20 Xutf8TextExtents(xfontset, str, e-str, &r, NULL);
21 } else {
22 // use normal
23 while (bytelen > 0 && (unsigned char)(*e) <= 127) { ++e; --bytelen; }
24 XmbTextExtents(xfontset, str, e-str, &r, NULL);
25 //fprintf(stderr, "%c: w:%d\n", *str, r.width-r.x);
28 str = e;
29 wdt += r.width-r.x;
31 } else {
32 memset(&r, 0, sizeof(r));
33 Xutf8TextExtents(xfontset, str, bytelen, &r, NULL);
34 wdt = r.width-r.x;
37 //fprintf(stderr, "WDT=%d\n", wdt);
38 return wdt;
42 static void xDrawStringPart (int x, int y, int fontset, const char *str, int bytelen) {
43 XFontSet xfontset = dc.font[fontset].set;
44 //fprintf(stderr, "str: ["); fwrite(str, bytelen, 1, stderr); fprintf(stderr, "] (%d); x=%d; y=%d\n", bytelen, x, y);
45 y += dc.font[fontset].ascent;
46 #if 0
47 if (needConversion) {
48 while (bytelen > 0) {
49 const char *e = str;
50 XRectangle r;
52 memset(&r, 0, sizeof(r));
53 if ((unsigned char)(*e) > 127) {
54 // use UTF-8
55 while (bytelen > 0 && (unsigned char)(*e) > 127) { ++e; --bytelen; }
56 Xutf8DrawImageString(xw.dpy, xw.pictab, xfontset, dc.gc, x, y, str, e-str);
57 Xutf8TextExtents(xfontset, str, e-str, &r, NULL);
58 } else {
59 // use normal
60 while (bytelen > 0 && (unsigned char)(*e) <= 127) { ++e; --bytelen; }
61 XmbDrawImageString(xw.dpy, xw.pictab, xfontset, dc.gc, x, y, str, e-str);
62 XmbTextExtents(xfontset, str, e-str, &r, NULL);
63 //fprintf(stderr, "len=%d; exts:(%d,%d)-(%u,%u)\n", bytelen, r.x, r.y, r.width, r.height);
65 //fprintf(stderr, "s: ["); fwrite(str, e-str, 1, stderr); fprintf(stderr, "] (%d); w=%d\n", e-str, r.width-r.x);
66 str = e;
67 x += r.width-r.x;
69 } else {
70 Xutf8DrawImageString(xw.dpy, xw.pictab, xfontset, dc.gc, x, y, str, bytelen);
72 #else
73 Xutf8DrawImageString(xw.dpy, xw.pictab, xfontset, dc.gc, x, y, str, bytelen);
74 #endif
78 static const char *utf8prev (const void *str) {
79 const uint8_t *s = (const uint8_t *)str;
81 if (s == NULL || !s[0]) return (const char *)s;
82 if (s[0] < 128) return (const char *)s-1;
83 --s;
84 while ((s[0]&0xc0) == 0x80) --s;
85 return (const char *)s;
89 static void xDrawStringEllCenter (int x, int y, int width, int fontset, const char *str) {
90 if (width > 0) {
91 int bytelen = strlen(str);
92 int wdt = xStringWidth(fontset, str, bytelen);
94 if (wdt <= width) {
95 // it's ok
96 //fprintf(stderr, "OK: wdt=%d\n", wdt);
97 xDrawStringPart(x, y, fontset, str, bytelen);
98 } else {
99 // need to write it with ellipsis
100 const char *lastchar = str, *rchar = str; // last char in string
101 int ellen = xStringWidth(fontset, "...", 3);
102 int clen = 0; // length of str in chars
103 int curwdt;
106 const char *s = str;
107 int bl = bytelen;
109 while (bl > 0) {
110 int l = xStringCharSize(s, bl);
112 if (l < 1) break;
113 lastchar = s;
114 ++clen;
115 s += l;
116 bl -= l;
118 bytelen -= bl; // in case we have invalid UTF-8 string here
120 // check if we have enough chars and a room for ellipsis, first and last chars
121 //fprintf(stderr, "width=%d; ellen=%d\n", width, ellen);
123 if (clen < 3 ||
124 (ellen+xStringWidth(fontset, str, k8t_UTF8Size(str))+xStringWidth(fontset, lastchar, k8t_UTF8Size(lastchar)) > width)) {
125 // we have nothing to do
126 xDrawStringPart(x, y, fontset, str, bytelen);
127 return;
129 //fprintf(stderr, "<%c>\n", *lastchar);
130 // add chars to left and to right until we hit the limit
131 // note that the leftmost and the rightmost char widthes are already added to curwdt
132 // rchar points to the first unprocessed char
133 // lastchar points to the last processed char
134 curwdt = ellen+xStringWidth(fontset, lastchar, xStringCharSize(lastchar, 4));
135 for (;;) {
136 const char *pc;
137 int lw, rw, rsz;
139 // try to add first char
140 // current string width
141 lw = xStringWidth(fontset, str, rchar+(rsz = k8t_UTF8Size(rchar))-str);
142 rw = xStringWidth(fontset, lastchar, str+bytelen-lastchar);
143 if (lw+rw+ellen > width) break; // we hit the limit
144 // move left char to the right
145 rchar += rsz;
146 // try to add last char
147 // fix string width
148 pc = utf8prev(lastchar);
149 rw = xStringWidth(fontset, pc, str+bytelen-pc);
150 if (lw+rw+ellen > width) break; // we hit the limit
151 // move right char to the left
152 lastchar = pc;
155 //fprintf(stderr, "curwdt=%d; left=%d; right=%d\n", curwdt, rchar-str, str+bytelen-lastchar);
156 // now draw left part
157 xDrawStringPart(x, y, fontset, str, rchar-str);
158 // right part
159 curwdt = xStringWidth(fontset, lastchar, str+bytelen-lastchar);
160 xDrawStringPart(x+width-curwdt, y, fontset, lastchar, str+bytelen-lastchar);
161 // and ellipsis
162 //xDrawStringPart(x+width/2-ellen, y, fontset, "...", 3);
163 clen = xStringWidth(fontset, str, rchar-str);
164 x += clen;
165 width -= clen+curwdt;
166 xDrawStringPart(x+(width-ellen)/2, y, fontset, "...", 3);
172 static void xDrawStringEllRight (int x, int y, int width, int fontset, const char *str) {
173 if (width > 0) {
174 int bytelen = strlen(str);
175 int wdt = xStringWidth(fontset, str, bytelen);
177 if (wdt <= width) {
178 xDrawStringPart(x, y, fontset, str, bytelen);
179 } else {
180 const char *s = str;
181 int bl = bytelen;
182 int ellen = xStringWidth(fontset, "...", 3);
184 while (bl > 0) {
185 int l = xStringCharSize(s, bl);
186 int cw;
188 if (l < 1) break;
189 cw = xStringWidth(fontset, str, s+l-str);
190 if (cw > width) break;
191 s += l;
192 bl -= l;
194 xDrawStringPart(x, y, fontset, str, s-str);
195 xDrawStringPart(x+width-ellen, y, fontset, "...", 3);
201 static void xDrawStringNoEll (int x, int y, int width, int fontset, const char *str) {
202 if (width > 0) {
203 xDrawStringPart(x, y, fontset, str, strlen(str));
208 static void xdrawTabBar (void) {
209 if (xw.tabheight > 0 && updateTabBar) {
210 xclearunused();
212 if (updateTabBar > 0) {
213 int tabw = xw.w/opt_tabcount, n = (opt_tabposition == 0 ? 1 : 0);
214 //XFontSet fontset = dc.font[2].set;
216 XSetForeground(xw.dpy, dc.gc, getColor(normalTabBG));
217 XFillRectangle(xw.dpy, xw.pictab, dc.gc, 0, 0, xw.w, xw.tabheight);
219 for (int f = firstVisibleTab; f < firstVisibleTab+opt_tabcount; ++f) {
220 int x = (f-firstVisibleTab)*tabw;
221 const char *title;
222 char *tit;
224 if (f >= term_count) {
225 XSetForeground(xw.dpy, dc.gc, getColor(normalTabBG));
226 XFillRectangle(xw.dpy, xw.pictab, dc.gc, x, 0, xw.w, xw.tabheight);
228 XSetForeground(xw.dpy, dc.gc, getColor(normalTabFG));
229 XDrawLine(xw.dpy, xw.pictab, dc.gc, x/*+tabw-1*/, 0, x/*+tabw-1*/, xw.tabheight);
230 break;
232 title = term_array[f]->title;
233 if (!title[0]) title = opt_title;
234 tit = SPrintf("[%d]%s", f, title);
235 //title = tit;
237 XSetForeground(xw.dpy, dc.gc, getColor(f == termidx ? activeTabBG : normalTabBG));
238 XFillRectangle(xw.dpy, xw.pictab, dc.gc, x, 0, tabw, xw.tabheight);
240 XSetBackground(xw.dpy, dc.gc, getColor(f == termidx ? activeTabBG : normalTabBG));
241 XSetForeground(xw.dpy, dc.gc, getColor(f == termidx ? activeTabFG : normalTabFG));
243 switch (opt_tabellipsis) {
244 case 1: // center
245 xDrawStringEllCenter(x+2, n, tabw-6, 2, tit);
246 break;
247 case 2: // left
248 //xDrawStringEllLeft(x+2, n, tabw-6, 2, tit);
249 break;
250 case 3: // right
251 xDrawStringEllRight(x+2, n, tabw-6, 2, tit);
252 break;
253 default: // none
254 xDrawStringNoEll(x+2, n, tabw-6, 2, tit);
255 break;
257 free(tit);
259 XSetForeground(xw.dpy, dc.gc, getColor(f == termidx ? activeTabBG : normalTabBG));
260 XFillRectangle(xw.dpy, xw.pictab, dc.gc, x+tabw-2, 0, 2, xw.tabheight);
262 if (f > firstVisibleTab) {
263 XSetForeground(xw.dpy, dc.gc, getColor(normalTabFG));
264 XDrawLine(xw.dpy, xw.pictab, dc.gc, x/*+tabw-1*/, 0, x/*+tabw-1*/, xw.tabheight);
268 XSetForeground(xw.dpy, dc.gc, getColor(normalTabFG));
269 //XDrawRectangle(xw.dpy, xw.pictab, dc.gc, -1, 0, xw.w+1, xw.tabheight+1);
270 if (opt_tabposition == 0) {
271 XDrawLine(xw.dpy, xw.pictab, dc.gc, 0, 0, xw.w, 0);
272 } else {
273 XDrawLine(xw.dpy, xw.pictab, dc.gc, 0, xw.tabheight-1, xw.w, xw.tabheight-1);
277 if (opt_tabposition == 0) {
278 XCopyArea(xw.dpy, xw.pictab, xw.win, dc.gc, 0, 0, xw.w, xw.tabheight, 0, xw.h-xw.tabheight);
279 } else {
280 XCopyArea(xw.dpy, xw.pictab, xw.win, dc.gc, 0, 0, xw.w, xw.tabheight, 0, 0);
283 updateTabBar = 0;