| dmenu-scroll-20180607-a314412.diff - sites - public wiki contents of suckless.o… | |
| git clone git://git.suckless.org/sites | |
| Log | |
| Files | |
| 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 + curso… | |
| 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, u… | |
| 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, … | |
| 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 ||… | |
| 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].pi… | |
| 91 + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, … | |
| 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 == Al… | |
| 107 + if (align == AlignL) { | |
| 108 + utf8charlen = utf8decode(text + i, &utf… | |
| 109 + if (!utf8charlen) { | |
| 110 + textlen = i; | |
| 111 + break; | |
| 112 + } | |
| 113 + } else { | |
| 114 + n = utf8nextchar(text, textlen, i, -1); | |
| 115 + utf8charlen = utf8decode(text + n, &utf… | |
| 116 + if (!utf8charlen) { | |
| 117 + textlen -= i; | |
| 118 + text += i; | |
| 119 + i = 0; | |
| 120 + break; | |
| 121 + } | |
| 122 + } | |
| 123 + for (curfont = drw->fonts; curfont; curfont = c… | |
| 124 + charexists = charexists || XftCharExist… | |
| 125 + if (charexists) { | |
| 126 + if (curfont == usedfont) { | |
| 127 + utf8strlen += utf8charl… | |
| 128 + i += align == AlignL ? … | |
| 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,… | |
| 147 + /* shorten text if necessary */ | |
| 148 + if (align == AlignL) { | |
| 149 + for (len = utf8strlen; len && ew > w; )… | |
| 150 + len = utf8nextchar(utf8str, len… | |
| 151 + drw_font_getexts(usedfont, utf8… | |
| 152 + } | |
| 153 + } else { | |
| 154 + for (len = utf8strlen; len && ew > w; )… | |
| 155 + n = utf8nextchar(utf8str, len, … | |
| 156 + utf8str += n; | |
| 157 + len -= n; | |
| 158 + drw_font_getexts(usedfont, utf8… | |
| 159 + } | |
| 160 + } | |
| 161 + | |
| 162 + if (len) { | |
| 163 + if (render) { | |
| 164 + ty = y + (h - usedfont->h) / 2 … | |
| 165 + XftDrawStringUtf8(d, &drw->sche… | |
| 166 + usedfont->xfo… | |
| 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 && … | |
| 176 + break; | |
| 177 + } else if (nextfont) { | |
| 178 + charexists = 0; | |
| 179 + usedfont = nextfont; | |
| 180 + } else { | |
| 181 + /* Regardless of whether or not a fallback font… | |
| 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… | |
| 190 + die("the first font in the cache must b… | |
| 191 + } | |
| 192 + | |
| 193 + fcpattern = FcPatternDuplicate(drw->fonts->patt… | |
| 194 + FcPatternAddCharSet(fcpattern, FC_CHARSET, fcch… | |
| 195 + FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue… | |
| 196 + | |
| 197 + FcConfigSubstitute(NULL, fcpattern, FcMatchPatt… | |
| 198 + FcDefaultSubstitute(fcpattern); | |
| 199 + match = XftFontMatch(drw->dpy, drw->screen, fcp… | |
| 200 + | |
| 201 + FcCharSetDestroy(fccharset); | |
| 202 + FcPatternDestroy(fcpattern); | |
| 203 + | |
| 204 + if (match) { | |
| 205 + usedfont = xfont_create(drw, NULL, matc… | |
| 206 + if (usedfont && XftCharExists(drw->dpy,… | |
| 207 + for (curfont = drw->fonts; curf… | |
| 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 in… | |
| 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, i… | |
| 241 int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, un… | |
| 242 +int drw_text_align(Drw *drw, int x, int y, unsigned int w, unsigned int… | |
| 243 | |
| 244 /* Map functions */ | |
| 245 void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsign… |