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);