@@ -240,26 +240,28 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
240240int
241241drw_text (Drw * drw , int x , int y , unsigned int w , unsigned int h , unsigned int lpad , const char * text , int invert )
242242{
243- char buf [1024 ];
244- int ty ;
245- unsigned int ew ;
243+ int i , ty , ellipsis_x = 0 ;
244+ unsigned int tmpw , ew , ellipsis_w = 0 , ellipsis_len ;
246245 XftDraw * d = NULL ;
247246 Fnt * usedfont , * curfont , * nextfont ;
248- size_t i , len ;
249247 int utf8strlen , utf8charlen , render = x || y || w || h ;
250248 long utf8codepoint = 0 ;
251249 const char * utf8str ;
252250 FcCharSet * fccharset ;
253251 FcPattern * fcpattern ;
254252 FcPattern * match ;
255253 XftResult result ;
256- int charexists = 0 ;
254+ int charexists = 0 , overflow = 0 ;
255+ /* keep track of a couple codepoints for which we have no match. */
256+ enum { nomatches_len = 64 };
257+ static struct { long codepoint [nomatches_len ]; unsigned int idx ; } nomatches ;
258+ static unsigned int ellipsis_width = 0 ;
257259
258- if (!drw || (render && !drw -> scheme ) || !text || !drw -> fonts )
260+ if (!drw || (render && ( !drw -> scheme || ! w ) ) || !text || !drw -> fonts )
259261 return 0 ;
260262
261263 if (!render ) {
262- w = ~ w ;
264+ w = invert ? invert : ~ invert ;
263265 } else {
264266 XSetForeground (drw -> dpy , drw -> gc , drw -> scheme [invert ? ColFg : ColBg ].pixel );
265267 XFillRectangle (drw -> dpy , drw -> drawable , drw -> gc , x , y , w , h );
@@ -271,55 +273,64 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
271273 }
272274
273275 usedfont = drw -> fonts ;
276+ if (!ellipsis_width && render )
277+ ellipsis_width = drw_fontset_getwidth (drw , "..." );
274278 while (1 ) {
275- utf8strlen = 0 ;
279+ ew = ellipsis_len = utf8strlen = 0 ;
276280 utf8str = text ;
277281 nextfont = NULL ;
278282 while (* text ) {
279283 utf8charlen = utf8decode (text , & utf8codepoint , UTF_SIZ );
280284 for (curfont = drw -> fonts ; curfont ; curfont = curfont -> next ) {
281285 charexists = charexists || XftCharExists (drw -> dpy , curfont -> xfont , utf8codepoint );
282286 if (charexists ) {
283- if (curfont == usedfont ) {
287+ drw_font_getexts (curfont , text , utf8charlen , & tmpw , NULL );
288+ if (ew + ellipsis_width <= w ) {
289+ /* keep track where the ellipsis still fits */
290+ ellipsis_x = x + ew ;
291+ ellipsis_w = w - ew ;
292+ ellipsis_len = utf8strlen ;
293+ }
294+
295+ if (ew + tmpw > w ) {
296+ overflow = 1 ;
297+ /* called from drw_fontset_getwidth_clamp():
298+ * it wants the width AFTER the overflow
299+ */
300+ if (!render )
301+ x += tmpw ;
302+ else
303+ utf8strlen = ellipsis_len ;
304+ } else if (curfont == usedfont ) {
284305 utf8strlen += utf8charlen ;
285306 text += utf8charlen ;
307+ ew += tmpw ;
286308 } else {
287309 nextfont = curfont ;
288310 }
289311 break ;
290312 }
291313 }
292314
293- if (!charexists || nextfont )
315+ if (overflow || !charexists || nextfont )
294316 break ;
295317 else
296318 charexists = 0 ;
297319 }
298320
299321 if (utf8strlen ) {
300- drw_font_getexts (usedfont , utf8str , utf8strlen , & ew , NULL );
301- /* shorten text if necessary */
302- for (len = MIN (utf8strlen , sizeof (buf ) - 1 ); len && ew > w ; len -- )
303- drw_font_getexts (usedfont , utf8str , len , & ew , NULL );
304-
305- if (len ) {
306- memcpy (buf , utf8str , len );
307- buf [len ] = '\0' ;
308- if (len < utf8strlen )
309- for (i = len ; i && i > len - 3 ; buf [-- i ] = '.' )
310- ; /* NOP */
311-
312- if (render ) {
313- ty = y + (h - usedfont -> h ) / 2 + usedfont -> xfont -> ascent ;
314- XftDrawStringUtf8 (d , & drw -> scheme [invert ? ColBg : ColFg ],
315- usedfont -> xfont , x , ty , (XftChar8 * )buf , len );
316- }
317- x += ew ;
318- w -= ew ;
322+ if (render ) {
323+ ty = y + (h - usedfont -> h ) / 2 + usedfont -> xfont -> ascent ;
324+ XftDrawStringUtf8 (d , & drw -> scheme [invert ? ColBg : ColFg ],
325+ usedfont -> xfont , x , ty , (XftChar8 * )utf8str , utf8strlen );
319326 }
327+ x += ew ;
328+ w -= ew ;
320329 }
330+ if (render && overflow )
331+ drw_text (drw , ellipsis_x , y , ellipsis_w , h , 0 , "..." , invert );
321332
322- if (!* text ) {
333+ if (!* text || overflow ) {
323334 break ;
324335 } else if (nextfont ) {
325336 charexists = 0 ;
@@ -329,6 +340,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
329340 * character must be drawn. */
330341 charexists = 1 ;
331342
343+ for (i = 0 ; i < nomatches_len ; ++ i ) {
344+ /* avoid calling XftFontMatch if we know we won't find a match */
345+ if (utf8codepoint == nomatches .codepoint [i ])
346+ goto no_match ;
347+ }
348+
332349 fccharset = FcCharSetCreate ();
333350 FcCharSetAddChar (fccharset , utf8codepoint );
334351
@@ -340,7 +357,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
340357 fcpattern = FcPatternDuplicate (drw -> fonts -> pattern );
341358 FcPatternAddCharSet (fcpattern , FC_CHARSET , fccharset );
342359 FcPatternAddBool (fcpattern , FC_SCALABLE , FcTrue );
343- FcPatternAddBool (fcpattern , FC_COLOR , FcFalse );
344360
345361 FcConfigSubstitute (NULL , fcpattern , FcMatchPattern );
346362 FcDefaultSubstitute (fcpattern );
@@ -357,6 +373,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
357373 curfont -> next = usedfont ;
358374 } else {
359375 xfont_free (usedfont );
376+ nomatches .codepoint [++ nomatches .idx % nomatches_len ] = utf8codepoint ;
377+ no_match :
360378 usedfont = drw -> fonts ;
361379 }
362380 }
@@ -386,6 +404,15 @@ drw_fontset_getwidth(Drw *drw, const char *text)
386404 return drw_text (drw , 0 , 0 , 0 , 0 , 0 , text , 0 );
387405}
388406
407+ unsigned int
408+ drw_fontset_getwidth_clamp (Drw * drw , const char * text , unsigned int n )
409+ {
410+ unsigned int tmp = 0 ;
411+ if (drw && drw -> fonts && text && n )
412+ tmp = drw_text (drw , 0 , 0 , 0 , 0 , 0 , text , n );
413+ return MIN (n , tmp );
414+ }
415+
389416void
390417drw_font_getexts (Fnt * font , const char * text , unsigned int len , unsigned int * w , unsigned int * h )
391418{
0 commit comments