more fixes to 1049
[k8sterm.git] / src / x11drawtabs.c
blobf00a85d2a6fbcb948dbed5c7b89eb4792beb2684
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;
45 //fprintf(stderr, "str: ["); fwrite(str, bytelen, 1, stderr); fprintf(stderr, "] (%d); x=%d; y=%d\n", bytelen, x, y);
47 y += dc.font[fontset].ascent;
49 if (needConversion) {
50 while (bytelen > 0) {
51 const char *e = str;
52 XRectangle r;
54 memset(&r, 0, sizeof(r));
55 if ((unsigned char)(*e) > 127) {
56 // use UTF-8
57 while (bytelen > 0 && (unsigned char)(*e) > 127) { ++e; --bytelen; }
58 Xutf8DrawImageString(xw.dpy, xw.pictab, xfontset, dc.gc, x, y, str, e-str);
59 Xutf8TextExtents(xfontset, str, e-str, &r, NULL);
60 } else {
61 // use normal
62 while (bytelen > 0 && (unsigned char)(*e) <= 127) { ++e; --bytelen; }
63 XmbDrawImageString(xw.dpy, xw.pictab, xfontset, dc.gc, x, y, str, e-str);
64 XmbTextExtents(xfontset, str, e-str, &r, NULL);
65 //fprintf(stderr, "len=%d; exts:(%d,%d)-(%u,%u)\n", bytelen, r.x, r.y, r.width, r.height);
67 //fprintf(stderr, "s: ["); fwrite(str, e-str, 1, stderr); fprintf(stderr, "] (%d); w=%d\n", e-str, r.width-r.x);
68 str = e;
69 x += r.width-r.x;
71 } else {
72 Xutf8DrawImageString(xw.dpy, xw.pictab, xfontset, dc.gc, x, y, str, bytelen);
77 static const char *utf8prev (const void *str) {
78 const uint8_t *s = (const uint8_t *)str;
80 if (s == NULL || !s[0]) return (const char *)s;
81 if (s[0] < 128) return (const char *)s-1;
82 --s;
83 while ((s[0]&0xc0) == 0x80) --s;
84 return (const char *)s;
88 static void xDrawStringEllCenter (int x, int y, int width, int fontset, const char *str) {
89 if (width > 0) {
90 int bytelen = strlen(str);
91 int wdt = xStringWidth(fontset, str, bytelen);
93 if (wdt <= width) {
94 // it's ok
95 //fprintf(stderr, "OK: wdt=%d\n", wdt);
96 xDrawStringPart(x, y, fontset, str, bytelen);
97 } else {
98 // need to write it with ellipsis
99 const char *lastchar = str, *rchar = str; // last char in string
100 int ellen = xStringWidth(fontset, "...", 3);
101 int clen = 0; // length of str in chars
102 int curwdt;
105 const char *s = str;
106 int bl = bytelen;
108 while (bl > 0) {
109 int l = xStringCharSize(s, bl);
111 if (l < 1) break;
112 lastchar = s;
113 ++clen;
114 s += l;
115 bl -= l;
117 bytelen -= bl; // in case we have invalid UTF-8 string here
119 // check if we have enough chars and a room for ellipsis, first and last chars
120 //fprintf(stderr, "width=%d; ellen=%d\n", width, ellen);
122 if (clen < 3 ||
123 (ellen+xStringWidth(fontset, str, k8t_UTF8Size(str))+xStringWidth(fontset, lastchar, k8t_UTF8Size(lastchar)) > width)) {
124 // we have nothing to do
125 xDrawStringPart(x, y, fontset, str, bytelen);
126 return;
128 //fprintf(stderr, "<%c>\n", *lastchar);
129 // add chars to left and to right until we hit the limit
130 // note that the leftmost and the rightmost char widthes are already added to curwdt
131 // rchar points to the first unprocessed char
132 // lastchar points to the last processed char
133 curwdt = ellen+xStringWidth(fontset, lastchar, xStringCharSize(lastchar, 4));
134 for (;;) {
135 const char *pc;
136 int lw, rw, rsz;
138 // try to add first char
139 // current string width
140 lw = xStringWidth(fontset, str, rchar+(rsz = k8t_UTF8Size(rchar))-str);
141 rw = xStringWidth(fontset, lastchar, str+bytelen-lastchar);
142 if (lw+rw+ellen > width) break; // we hit the limit
143 // move left char to the right
144 rchar += rsz;
145 // try to add last char
146 // fix string width
147 pc = utf8prev(lastchar);
148 rw = xStringWidth(fontset, pc, str+bytelen-pc);
149 if (lw+rw+ellen > width) break; // we hit the limit
150 // move right char to the left
151 lastchar = pc;
154 //fprintf(stderr, "curwdt=%d; left=%d; right=%d\n", curwdt, rchar-str, str+bytelen-lastchar);
155 // now draw left part
156 xDrawStringPart(x, y, fontset, str, rchar-str);
157 // right part
158 curwdt = xStringWidth(fontset, lastchar, str+bytelen-lastchar);
159 xDrawStringPart(x+width-curwdt, y, fontset, lastchar, str+bytelen-lastchar);
160 // and ellipsis
161 //xDrawStringPart(x+width/2-ellen, y, fontset, "...", 3);
162 clen = xStringWidth(fontset, str, rchar-str);
163 x += clen;
164 width -= clen+curwdt;
165 xDrawStringPart(x+(width-ellen)/2, y, fontset, "...", 3);
171 static void xDrawStringEllRight (int x, int y, int width, int fontset, const char *str) {
172 if (width > 0) {
173 int bytelen = strlen(str);
174 int wdt = xStringWidth(fontset, str, bytelen);
176 if (wdt <= width) {
177 xDrawStringPart(x, y, fontset, str, bytelen);
178 } else {
179 const char *s = str;
180 int bl = bytelen;
181 int ellen = xStringWidth(fontset, "...", 3);
183 while (bl > 0) {
184 int l = xStringCharSize(s, bl);
185 int cw;
187 if (l < 1) break;
188 cw = xStringWidth(fontset, str, s+l-str);
189 if (cw > width) break;
190 s += l;
191 bl -= l;
193 xDrawStringPart(x, y, fontset, str, s-str);
194 xDrawStringPart(x+width-ellen, y, fontset, "...", 3);
200 static void xDrawStringNoEll (int x, int y, int width, int fontset, const char *str) {
201 if (width > 0) {
202 xDrawStringPart(x, y, fontset, str, strlen(str));
207 static void xdrawTabBar (void) {
208 if (xw.tabheight > 0 && updateTabBar) {
209 xclearunused();
211 if (updateTabBar > 0) {
212 int tabw = xw.w/opt_tabcount, n = (opt_tabposition == 0 ? 1 : 0);
213 //XFontSet fontset = dc.font[2].set;
215 XSetForeground(xw.dpy, dc.gc, getColor(normalTabBG));
216 XFillRectangle(xw.dpy, xw.pictab, dc.gc, 0, 0, xw.w, xw.tabheight);
218 for (int f = firstVisibleTab; f < firstVisibleTab+opt_tabcount; ++f) {
219 int x = (f-firstVisibleTab)*tabw;
220 const char *title;
221 char *tit;
223 if (f >= term_count) {
224 XSetForeground(xw.dpy, dc.gc, getColor(normalTabBG));
225 XFillRectangle(xw.dpy, xw.pictab, dc.gc, x, 0, xw.w, xw.tabheight);
227 XSetForeground(xw.dpy, dc.gc, getColor(normalTabFG));
228 XDrawLine(xw.dpy, xw.pictab, dc.gc, x/*+tabw-1*/, 0, x/*+tabw-1*/, xw.tabheight);
229 break;
231 title = term_array[f]->title;
232 if (!title[0]) title = opt_title;
233 tit = SPrintf("[%d]%s", f, title);
234 //title = tit;
236 XSetForeground(xw.dpy, dc.gc, getColor(f == termidx ? activeTabBG : normalTabBG));
237 XFillRectangle(xw.dpy, xw.pictab, dc.gc, x, 0, tabw, xw.tabheight);
239 XSetBackground(xw.dpy, dc.gc, getColor(f == termidx ? activeTabBG : normalTabBG));
240 XSetForeground(xw.dpy, dc.gc, getColor(f == termidx ? activeTabFG : normalTabFG));
242 switch (opt_tabellipsis) {
243 case 1: // center
244 xDrawStringEllCenter(x+2, n, tabw-6, 2, tit);
245 break;
246 case 2: // left
247 //xDrawStringEllLeft(x+2, n, tabw-6, 2, tit);
248 break;
249 case 3: // right
250 xDrawStringEllRight(x+2, n, tabw-6, 2, tit);
251 break;
252 default: // none
253 xDrawStringNoEll(x+2, n, tabw-6, 2, tit);
254 break;
256 free(tit);
258 XSetForeground(xw.dpy, dc.gc, getColor(f == termidx ? activeTabBG : normalTabBG));
259 XFillRectangle(xw.dpy, xw.pictab, dc.gc, x+tabw-2, 0, 2, xw.tabheight);
261 if (f > firstVisibleTab) {
262 XSetForeground(xw.dpy, dc.gc, getColor(normalTabFG));
263 XDrawLine(xw.dpy, xw.pictab, dc.gc, x/*+tabw-1*/, 0, x/*+tabw-1*/, xw.tabheight);
267 XSetForeground(xw.dpy, dc.gc, getColor(normalTabFG));
268 //XDrawRectangle(xw.dpy, xw.pictab, dc.gc, -1, 0, xw.w+1, xw.tabheight+1);
269 if (opt_tabposition == 0) {
270 XDrawLine(xw.dpy, xw.pictab, dc.gc, 0, 0, xw.w, 0);
271 } else {
272 XDrawLine(xw.dpy, xw.pictab, dc.gc, 0, xw.tabheight-1, xw.w, xw.tabheight-1);
276 if (opt_tabposition == 0) {
277 XCopyArea(xw.dpy, xw.pictab, xw.win, dc.gc, 0, 0, xw.w, xw.tabheight, 0, xw.h-xw.tabheight);
278 } else {
279 XCopyArea(xw.dpy, xw.pictab, xw.win, dc.gc, 0, 0, xw.w, xw.tabheight, 0, 0);
282 updateTabBar = 0;