summaryrefslogtreecommitdiff
path: root/patches/6.dmenu-textscroll-20180607-a314412.diff
diff options
context:
space:
mode:
Diffstat (limited to 'patches/6.dmenu-textscroll-20180607-a314412.diff')
-rw-r--r--patches/6.dmenu-textscroll-20180607-a314412.diff245
1 files changed, 245 insertions, 0 deletions
diff --git a/patches/6.dmenu-textscroll-20180607-a314412.diff b/patches/6.dmenu-textscroll-20180607-a314412.diff
new file mode 100644
index 0000000..7a7386a
--- /dev/null
+++ b/patches/6.dmenu-textscroll-20180607-a314412.diff
@@ -0,0 +1,245 @@
+diff --git a/dmenu.c b/dmenu.c
+index 5c835dd..71efe52 100644
+--- a/dmenu.c
++++ b/dmenu.c
+@@ -131,9 +131,10 @@ drawitem(struct item *item, int x, int y, int w)
+ static void
+ drawmenu(void)
+ {
+- unsigned int curpos;
++ static int curpos, oldcurlen;
+ struct item *item;
+ int x = 0, y = 0, w;
++ int curlen, rcurlen;
+
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ drw_rect(drw, 0, 0, mw, mh, 1, 1);
+@@ -144,14 +145,21 @@ drawmenu(void)
+ }
+ /* draw input field */
+ w = (lines > 0 || !matches) ? mw - x : inputw;
+- drw_setscheme(drw, scheme[SchemeNorm]);
+- drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0);
++ w -= lrpad / 2;
++ x += lrpad / 2;
+
+- curpos = TEXTW(text) - TEXTW(&text[cursor]);
+- if ((curpos += lrpad / 2 - 1) < w) {
+- drw_setscheme(drw, scheme[SchemeNorm]);
+- drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0);
+- }
++ rcurlen = drw_fontset_getwidth(drw, text + cursor);
++ curlen = drw_fontset_getwidth(drw, text) - rcurlen;
++ curpos += curlen - oldcurlen;
++ curpos = MIN(w, MAX(0, curpos));
++ curpos = MAX(curpos, w - rcurlen);
++ curpos = MIN(curpos, curlen);
++ oldcurlen = curlen;
++
++ drw_setscheme(drw, scheme[SchemeNorm]);
++ drw_text_align(drw, x, 0, curpos, bh, text, cursor, AlignR);
++ drw_text_align(drw, x + curpos, 0, w - curpos, bh, text + cursor, strlen(text) - cursor, AlignL);
++ drw_rect(drw, x + curpos - 1, 2, 2, bh - 4, 1, 0);
+
+ if (lines > 0) {
+ /* draw vertical list */
+diff --git a/drw.c b/drw.c
+index c638323..bfffbc1 100644
+--- a/drw.c
++++ b/drw.c
+@@ -364,6 +364,175 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
+ return x + (render ? w : 0);
+ }
+
++int
++utf8nextchar(const char *str, int len, int i, int inc)
++{
++ int n;
++
++ for (n = i + inc; n + inc >= 0 && n + inc <= len
++ && (str[n] & 0xc0) == 0x80; n += inc)
++ ;
++ return n;
++}
++
++int
++drw_text_align(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int textlen, int align)
++{
++ int ty;
++ unsigned int ew;
++ XftDraw *d = NULL;
++ Fnt *usedfont, *curfont, *nextfont;
++ size_t len;
++ int utf8strlen, utf8charlen, render = x || y || w || h;
++ long utf8codepoint = 0;
++ const char *utf8str;
++ FcCharSet *fccharset;
++ FcPattern *fcpattern;
++ FcPattern *match;
++ XftResult result;
++ int charexists = 0;
++ int i, n;
++
++ if (!drw || (render && !drw->scheme) || !text || !drw->fonts || textlen <= 0
++ || (align != AlignL && align != AlignR))
++ return 0;
++
++ if (!render) {
++ w = ~w;
++ } else {
++ XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel);
++ XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
++ d = XftDrawCreate(drw->dpy, drw->drawable,
++ DefaultVisual(drw->dpy, drw->screen),
++ DefaultColormap(drw->dpy, drw->screen));
++ }
++
++ usedfont = drw->fonts;
++ i = align == AlignL ? 0 : textlen;
++ x = align == AlignL ? x : x + w;
++ while (1) {
++ utf8strlen = 0;
++ nextfont = NULL;
++ /* if (align == AlignL) */
++ utf8str = text + i;
++
++ while ((align == AlignL && i < textlen) || (align == AlignR && i > 0)) {
++ if (align == AlignL) {
++ utf8charlen = utf8decode(text + i, &utf8codepoint, MIN(textlen - i, UTF_SIZ));
++ if (!utf8charlen) {
++ textlen = i;
++ break;
++ }
++ } else {
++ n = utf8nextchar(text, textlen, i, -1);
++ utf8charlen = utf8decode(text + n, &utf8codepoint, MIN(textlen - n, UTF_SIZ));
++ if (!utf8charlen) {
++ textlen -= i;
++ text += i;
++ i = 0;
++ break;
++ }
++ }
++ for (curfont = drw->fonts; curfont; curfont = curfont->next) {
++ charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
++ if (charexists) {
++ if (curfont == usedfont) {
++ utf8strlen += utf8charlen;
++ i += align == AlignL ? utf8charlen : -utf8charlen;
++ } else {
++ nextfont = curfont;
++ }
++ break;
++ }
++ }
++
++ if (!charexists || nextfont)
++ break;
++ else
++ charexists = 0;
++ }
++
++ if (align == AlignR)
++ utf8str = text + i;
++
++ if (utf8strlen) {
++ drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
++ /* shorten text if necessary */
++ if (align == AlignL) {
++ for (len = utf8strlen; len && ew > w; ) {
++ len = utf8nextchar(utf8str, len, len, -1);
++ drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
++ }
++ } else {
++ for (len = utf8strlen; len && ew > w; ) {
++ n = utf8nextchar(utf8str, len, 0, +1);
++ utf8str += n;
++ len -= n;
++ drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
++ }
++ }
++
++ if (len) {
++ if (render) {
++ ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
++ XftDrawStringUtf8(d, &drw->scheme[ColFg],
++ usedfont->xfont, align == AlignL ? x : x - ew, ty, (XftChar8 *)utf8str, len);
++ }
++ x += align == AlignL ? ew : -ew;
++ w -= ew;
++ }
++ if (len < utf8strlen)
++ break;
++ }
++
++ if ((align == AlignR && i <= 0) || (align == AlignL && i >= textlen)) {
++ break;
++ } else if (nextfont) {
++ charexists = 0;
++ usedfont = nextfont;
++ } else {
++ /* Regardless of whether or not a fallback font is found, the
++ * character must be drawn. */
++ charexists = 1;
++
++ fccharset = FcCharSetCreate();
++ FcCharSetAddChar(fccharset, utf8codepoint);
++
++ if (!drw->fonts->pattern) {
++ /* Refer to the comment in xfont_create for more information. */
++ die("the first font in the cache must be loaded from a font string.");
++ }
++
++ fcpattern = FcPatternDuplicate(drw->fonts->pattern);
++ FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
++ FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
++
++ FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
++ FcDefaultSubstitute(fcpattern);
++ match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
++
++ FcCharSetDestroy(fccharset);
++ FcPatternDestroy(fcpattern);
++
++ if (match) {
++ usedfont = xfont_create(drw, NULL, match);
++ if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
++ for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
++ ; /* NOP */
++ curfont->next = usedfont;
++ } else {
++ xfont_free(usedfont);
++ usedfont = drw->fonts;
++ }
++ }
++ }
++ }
++ if (d)
++ XftDrawDestroy(d);
++
++ return x;
++}
++
+ void
+ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
+ {
+diff --git a/drw.h b/drw.h
+index 4c67419..b66a83e 100644
+--- a/drw.h
++++ b/drw.h
+@@ -13,6 +13,7 @@ typedef struct Fnt {
+ } Fnt;
+
+ enum { ColFg, ColBg }; /* Clr scheme index */
++enum { AlignL, AlignR };
+ typedef XftColor Clr;
+
+ typedef struct {
+@@ -52,6 +53,7 @@ void drw_setscheme(Drw *drw, Clr *scm);
+ /* Drawing functions */
+ void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
+ int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
++int drw_text_align(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int textlen, int align);
+
+ /* Map functions */
+ void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);