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
;
16 memset(&r
, 0, sizeof(r
));
17 if ((unsigned char)(*e
) > 127) {
19 while (bytelen
> 0 && (unsigned char)(*e
) > 127) { ++e
; --bytelen
; }
20 Xutf8TextExtents(xfontset
, str
, e
-str
, &r
, NULL
);
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);
32 memset(&r
, 0, sizeof(r
));
33 Xutf8TextExtents(xfontset
, str
, bytelen
, &r
, NULL
);
37 //fprintf(stderr, "WDT=%d\n", 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
;
54 memset(&r
, 0, sizeof(r
));
55 if ((unsigned char)(*e
) > 127) {
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
);
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);
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;
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
) {
90 int bytelen
= strlen(str
);
91 int wdt
= xStringWidth(fontset
, str
, bytelen
);
95 //fprintf(stderr, "OK: wdt=%d\n", wdt);
96 xDrawStringPart(x
, y
, fontset
, str
, bytelen
);
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
109 int l
= xStringCharSize(s
, bl
);
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);
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
);
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));
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
145 // try to add last char
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
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
);
158 curwdt
= xStringWidth(fontset
, lastchar
, str
+bytelen
-lastchar
);
159 xDrawStringPart(x
+width
-curwdt
, y
, fontset
, lastchar
, str
+bytelen
-lastchar
);
161 //xDrawStringPart(x+width/2-ellen, y, fontset, "...", 3);
162 clen
= xStringWidth(fontset
, str
, rchar
-str
);
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
) {
173 int bytelen
= strlen(str
);
174 int wdt
= xStringWidth(fontset
, str
, bytelen
);
177 xDrawStringPart(x
, y
, fontset
, str
, bytelen
);
181 int ellen
= xStringWidth(fontset
, "...", 3);
184 int l
= xStringCharSize(s
, bl
);
188 cw
= xStringWidth(fontset
, str
, s
+l
-str
);
189 if (cw
> width
) break;
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
) {
202 xDrawStringPart(x
, y
, fontset
, str
, strlen(str
));
207 static void xdrawTabBar (void) {
208 if (xw
.tabheight
> 0 && updateTabBar
) {
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
;
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
);
231 title
= term_array
[f
]->title
;
232 if (!title
[0]) title
= opt_title
;
233 tit
= SPrintf("[%d]%s", f
, title
);
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
) {
244 xDrawStringEllCenter(x
+2, n
, tabw
-6, 2, tit
);
247 //xDrawStringEllLeft(x+2, n, tabw-6, 2, tit);
250 xDrawStringEllRight(x
+2, n
, tabw
-6, 2, tit
);
253 xDrawStringNoEll(x
+2, n
, tabw
-6, 2, 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);
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
);
279 XCopyArea(xw
.dpy
, xw
.pictab
, xw
.win
, dc
.gc
, 0, 0, xw
.w
, xw
.tabheight
, 0, 0);