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
;
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
;
52 memset(&r
, 0, sizeof(r
));
53 if ((unsigned char)(*e
) > 127) {
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
);
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);
70 Xutf8DrawImageString(xw
.dpy
, xw
.pictab
, xfontset
, dc
.gc
, x
, y
, str
, bytelen
);
73 Xutf8DrawImageString(xw
.dpy
, xw
.pictab
, xfontset
, dc
.gc
, x
, y
, str
, bytelen
);
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;
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
) {
91 int bytelen
= strlen(str
);
92 int wdt
= xStringWidth(fontset
, str
, bytelen
);
96 //fprintf(stderr, "OK: wdt=%d\n", wdt);
97 xDrawStringPart(x
, y
, fontset
, str
, bytelen
);
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
110 int l
= xStringCharSize(s
, bl
);
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);
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
);
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));
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
146 // try to add last char
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
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
);
159 curwdt
= xStringWidth(fontset
, lastchar
, str
+bytelen
-lastchar
);
160 xDrawStringPart(x
+width
-curwdt
, y
, fontset
, lastchar
, str
+bytelen
-lastchar
);
162 //xDrawStringPart(x+width/2-ellen, y, fontset, "...", 3);
163 clen
= xStringWidth(fontset
, str
, rchar
-str
);
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
) {
174 int bytelen
= strlen(str
);
175 int wdt
= xStringWidth(fontset
, str
, bytelen
);
178 xDrawStringPart(x
, y
, fontset
, str
, bytelen
);
182 int ellen
= xStringWidth(fontset
, "...", 3);
185 int l
= xStringCharSize(s
, bl
);
189 cw
= xStringWidth(fontset
, str
, s
+l
-str
);
190 if (cw
> width
) break;
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
) {
203 xDrawStringPart(x
, y
, fontset
, str
, strlen(str
));
208 static void xdrawTabBar (void) {
209 if (xw
.tabheight
> 0 && updateTabBar
) {
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
;
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
);
232 title
= term_array
[f
]->title
;
233 if (!title
[0]) title
= opt_title
;
234 tit
= SPrintf("[%d]%s", f
, title
);
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
) {
245 xDrawStringEllCenter(x
+2, n
, tabw
-6, 2, tit
);
248 //xDrawStringEllLeft(x+2, n, tabw-6, 2, tit);
251 xDrawStringEllRight(x
+2, n
, tabw
-6, 2, tit
);
254 xDrawStringNoEll(x
+2, n
, tabw
-6, 2, 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);
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
);
280 XCopyArea(xw
.dpy
, xw
.pictab
, xw
.win
, dc
.gc
, 0, 0, xw
.w
, xw
.tabheight
, 0, 0);