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… |