Xinqi Bao's Git

fix UB with the function iscntrl()
[dmenu.git] / drw.c
diff --git a/drw.c b/drw.c
index e65d069..a50c9ee 100644 (file)
--- a/drw.c
+++ b/drw.c
@@ -251,7 +251,7 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
 int
 drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
 {
-       int ty, ellipsis_x = 0;
+       int i, ty, ellipsis_x = 0;
        unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, ellipsis_width;
        XftDraw *d = NULL;
        Fnt *usedfont, *curfont, *nextfont;
@@ -263,12 +263,15 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
        FcPattern *match;
        XftResult result;
        int charexists = 0, overflow = 0;
+       /* keep track of a couple codepoints for which we have no match. */
+       enum { nomatches_len = 64 };
+       static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches;
 
        if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
                return 0;
 
        if (!render) {
-               w = ~w;
+               w = invert ? invert : ~invert;
        } else {
                XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
                XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
@@ -300,7 +303,13 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
 
                                        if (ew + tmpw > w) {
                                                overflow = 1;
-                                               utf8strlen = ellipsis_len;
+                                               /* called from drw_fontset_getwidth_clamp():
+                                                * it wants the width AFTER the overflow
+                                                */
+                                               if (!render)
+                                                       x += tmpw;
+                                               else
+                                                       utf8strlen = ellipsis_len;
                                        } else if (curfont == usedfont) {
                                                utf8strlen += utf8charlen;
                                                text += utf8charlen;
@@ -340,6 +349,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
                         * character must be drawn. */
                        charexists = 1;
 
+                       for (i = 0; i < nomatches_len; ++i) {
+                               /* avoid calling XftFontMatch if we know we won't find a match */
+                               if (utf8codepoint == nomatches.codepoint[i])
+                                       goto no_match;
+                       }
+
                        fccharset = FcCharSetCreate();
                        FcCharSetAddChar(fccharset, utf8codepoint);
 
@@ -368,6 +383,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
                                        curfont->next = usedfont;
                                } else {
                                        xfont_free(usedfont);
+                                       nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
+no_match:
                                        usedfont = drw->fonts;
                                }
                        }
@@ -397,6 +414,15 @@ drw_fontset_getwidth(Drw *drw, const char *text)
        return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
 }
 
+unsigned int
+drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n)
+{
+       unsigned int tmp = 0;
+       if (drw && drw->fonts && text && n)
+               tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
+       return MIN(n, tmp);
+}
+
 void
 drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
 {