dmenu-scroll-20180607-a314412.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       dmenu-scroll-20180607-a314412.diff (7072B)
       ---
            1 diff --git a/dmenu.c b/dmenu.c
            2 index 5c835dd..71efe52 100644
            3 --- a/dmenu.c
            4 +++ b/dmenu.c
            5 @@ -131,9 +131,10 @@ drawitem(struct item *item, int x, int y, int w)
            6  static void
            7  drawmenu(void)
            8  {
            9 -        unsigned int curpos;
           10 +        static int curpos, oldcurlen;
           11          struct item *item;
           12          int x = 0, y = 0, w;
           13 +        int curlen, rcurlen;
           14  
           15          drw_setscheme(drw, scheme[SchemeNorm]);
           16          drw_rect(drw, 0, 0, mw, mh, 1, 1);
           17 @@ -144,14 +145,21 @@ drawmenu(void)
           18          }
           19          /* draw input field */
           20          w = (lines > 0 || !matches) ? mw - x : inputw;
           21 -        drw_setscheme(drw, scheme[SchemeNorm]);
           22 -        drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0);
           23 +        w -= lrpad / 2;
           24 +        x += lrpad / 2;
           25  
           26 -        curpos = TEXTW(text) - TEXTW(&text[cursor]);
           27 -        if ((curpos += lrpad / 2 - 1) < w) {
           28 -                drw_setscheme(drw, scheme[SchemeNorm]);
           29 -                drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0);
           30 -        }
           31 +        rcurlen = drw_fontset_getwidth(drw, text + cursor);
           32 +        curlen = drw_fontset_getwidth(drw, text) - rcurlen;
           33 +        curpos += curlen - oldcurlen;
           34 +        curpos = MIN(w, MAX(0, curpos));
           35 +        curpos = MAX(curpos, w - rcurlen);
           36 +        curpos = MIN(curpos, curlen);
           37 +        oldcurlen = curlen;
           38 +
           39 +        drw_setscheme(drw, scheme[SchemeNorm]);
           40 +        drw_text_align(drw, x, 0, curpos, bh, text, cursor, AlignR);
           41 +        drw_text_align(drw, x + curpos, 0, w - curpos, bh, text + cursor, strlen(text) - cursor, AlignL);
           42 +        drw_rect(drw, x + curpos - 1, 2, 2, bh - 4, 1, 0);
           43  
           44          if (lines > 0) {
           45                  /* draw vertical list */
           46 diff --git a/drw.c b/drw.c
           47 index c638323..bfffbc1 100644
           48 --- a/drw.c
           49 +++ b/drw.c
           50 @@ -364,6 +364,175 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
           51          return x + (render ? w : 0);
           52  }
           53  
           54 +int
           55 +utf8nextchar(const char *str, int len, int i, int inc)
           56 +{
           57 +        int n;
           58 +
           59 +        for (n = i + inc; n + inc >= 0 && n + inc <= len
           60 +          && (str[n] & 0xc0) == 0x80; n += inc)
           61 +                ;
           62 +        return n;
           63 +}
           64 +
           65 +int
           66 +drw_text_align(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int textlen, int align)
           67 +{
           68 +        int ty;
           69 +        unsigned int ew;
           70 +        XftDraw *d = NULL;
           71 +        Fnt *usedfont, *curfont, *nextfont;
           72 +        size_t len;
           73 +        int utf8strlen, utf8charlen, render = x || y || w || h;
           74 +        long utf8codepoint = 0;
           75 +        const char *utf8str;
           76 +        FcCharSet *fccharset;
           77 +        FcPattern *fcpattern;
           78 +        FcPattern *match;
           79 +        XftResult result;
           80 +        int charexists = 0;
           81 +        int i, n;
           82 +
           83 +        if (!drw || (render && !drw->scheme) || !text || !drw->fonts || textlen <= 0
           84 +          || (align != AlignL && align != AlignR))
           85 +                return 0;
           86 +
           87 +        if (!render) {
           88 +                w = ~w;
           89 +        } else {
           90 +                XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel);
           91 +                XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
           92 +                d = XftDrawCreate(drw->dpy, drw->drawable,
           93 +                                  DefaultVisual(drw->dpy, drw->screen),
           94 +                                  DefaultColormap(drw->dpy, drw->screen));
           95 +        }
           96 +
           97 +        usedfont = drw->fonts;
           98 +        i = align == AlignL ? 0 : textlen;
           99 +        x = align == AlignL ? x : x + w;
          100 +        while (1) {
          101 +                utf8strlen = 0;
          102 +                nextfont = NULL;
          103 +                /* if (align == AlignL) */
          104 +                utf8str = text + i;
          105 +
          106 +                while ((align == AlignL && i < textlen) || (align == AlignR && i > 0)) {
          107 +                        if (align == AlignL) {
          108 +                                utf8charlen = utf8decode(text + i, &utf8codepoint, MIN(textlen - i, UTF_SIZ));
          109 +                                if (!utf8charlen) {
          110 +                                        textlen = i;
          111 +                                        break;
          112 +                                }
          113 +                        } else {
          114 +                                n = utf8nextchar(text, textlen, i, -1);
          115 +                                utf8charlen = utf8decode(text + n, &utf8codepoint, MIN(textlen - n, UTF_SIZ));
          116 +                                if (!utf8charlen) {
          117 +                                        textlen -= i;
          118 +                                        text += i;
          119 +                                        i = 0;
          120 +                                        break;
          121 +                                }
          122 +                        }
          123 +                        for (curfont = drw->fonts; curfont; curfont = curfont->next) {
          124 +                                charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
          125 +                                if (charexists) {
          126 +                                        if (curfont == usedfont) {
          127 +                                                utf8strlen += utf8charlen;
          128 +                                                i += align == AlignL ? utf8charlen : -utf8charlen;
          129 +                                        } else {
          130 +                                                nextfont = curfont;
          131 +                                        }
          132 +                                        break;
          133 +                                }
          134 +                        }
          135 +
          136 +                        if (!charexists || nextfont)
          137 +                                break;
          138 +                        else
          139 +                                charexists = 0;
          140 +                }
          141 +
          142 +                if (align == AlignR)
          143 +                        utf8str = text + i;
          144 +
          145 +                if (utf8strlen) {
          146 +                        drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
          147 +                        /* shorten text if necessary */
          148 +                        if (align == AlignL) {
          149 +                                for (len = utf8strlen; len && ew > w; ) {
          150 +                                        len = utf8nextchar(utf8str, len, len, -1);
          151 +                                        drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
          152 +                                }
          153 +                        } else {
          154 +                                for (len = utf8strlen; len && ew > w; ) {
          155 +                                        n = utf8nextchar(utf8str, len, 0, +1);
          156 +                                        utf8str += n;
          157 +                                        len -= n;
          158 +                                        drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
          159 +                                }
          160 +                        }
          161 +
          162 +                        if (len) {
          163 +                                if (render) {
          164 +                                        ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
          165 +                                        XftDrawStringUtf8(d, &drw->scheme[ColFg],
          166 +                                                          usedfont->xfont, align == AlignL ? x : x - ew, ty, (XftChar8 *)utf8str, len);
          167 +                                }
          168 +                                x += align == AlignL ? ew : -ew;
          169 +                                w -= ew;
          170 +                        }
          171 +                        if (len < utf8strlen)
          172 +                                break;
          173 +                }
          174 +
          175 +                if ((align == AlignR && i <= 0) || (align == AlignL && i >= textlen)) {
          176 +                        break;
          177 +                } else if (nextfont) {
          178 +                        charexists = 0;
          179 +                        usedfont = nextfont;
          180 +                } else {
          181 +                        /* Regardless of whether or not a fallback font is found, the
          182 +                         * character must be drawn. */
          183 +                        charexists = 1;
          184 +
          185 +                        fccharset = FcCharSetCreate();
          186 +                        FcCharSetAddChar(fccharset, utf8codepoint);
          187 +
          188 +                        if (!drw->fonts->pattern) {
          189 +                                /* Refer to the comment in xfont_create for more information. */
          190 +                                die("the first font in the cache must be loaded from a font string.");
          191 +                        }
          192 +
          193 +                        fcpattern = FcPatternDuplicate(drw->fonts->pattern);
          194 +                        FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
          195 +                        FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
          196 +
          197 +                        FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
          198 +                        FcDefaultSubstitute(fcpattern);
          199 +                        match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
          200 +
          201 +                        FcCharSetDestroy(fccharset);
          202 +                        FcPatternDestroy(fcpattern);
          203 +
          204 +                        if (match) {
          205 +                                usedfont = xfont_create(drw, NULL, match);
          206 +                                if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
          207 +                                        for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
          208 +                                                ; /* NOP */
          209 +                                        curfont->next = usedfont;
          210 +                                } else {
          211 +                                        xfont_free(usedfont);
          212 +                                        usedfont = drw->fonts;
          213 +                                }
          214 +                        }
          215 +                }
          216 +        }
          217 +        if (d)
          218 +                XftDrawDestroy(d);
          219 +
          220 +        return x;
          221 +}
          222 +
          223  void
          224  drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
          225  {
          226 diff --git a/drw.h b/drw.h
          227 index 4c67419..b66a83e 100644
          228 --- a/drw.h
          229 +++ b/drw.h
          230 @@ -13,6 +13,7 @@ typedef struct Fnt {
          231  } Fnt;
          232  
          233  enum { ColFg, ColBg }; /* Clr scheme index */
          234 +enum { AlignL, AlignR };
          235  typedef XftColor Clr;
          236  
          237  typedef struct {
          238 @@ -52,6 +53,7 @@ void drw_setscheme(Drw *drw, Clr *scm);
          239  /* Drawing functions */
          240  void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
          241  int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
          242 +int drw_text_align(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int textlen, int align);
          243  
          244  /* Map functions */
          245  void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);