sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

commit 10c0bbd62abc7851f5dc238257c4c81ec82621aa
parent 3ae4caac371875a01f7ca910ecb3a83494c72fd5
Author: nzl <uruabi@gmail.com>
Date:   Thu,  7 Jun 2018 14:08:06 +0900

[dmenu][scroll] update

Diffstat:
tools.suckless.org/dmenu/patches/dmenu-scroll-20180224-8895128.diff | 266-------------------------------------------------------------------------------
tools.suckless.org/dmenu/patches/dmenu-scroll-20180607-a314412.diff | 245+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tools.suckless.org/dmenu/patches/scroll.md | 2+-
3 files changed, 246 insertions(+), 267 deletions(-)

diff --git a/tools.suckless.org/dmenu/patches/dmenu-scroll-20180224-8895128.diff b/tools.suckless.org/dmenu/patches/dmenu-scroll-20180224-8895128.diff @@ -1,266 +0,0 @@ -From 32ae6bfb5f3a840443c52c9a53c27b126c3b59d0 Mon Sep 17 00:00:00 2001 -From: nzl <uruabi@gmail.com> -Date: Sat, 24 Feb 2018 13:47:59 +0800 -Subject: [PATCH] Implement text scrolling - -a new function drw_text_align is added, it is different from drw_text in that -it doesn't append '...' for long text, and it allows drawing text right -justified. ---- - dmenu.c | 28 ++++++++--- - drw.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - drw.h | 2 + - 3 files changed, 191 insertions(+), 8 deletions(-) - -diff --git a/dmenu.c b/dmenu.c -index a246111..d51b404 100644 ---- a/dmenu.c -+++ b/dmenu.c -@@ -128,9 +128,11 @@ 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; -+ char ch; - - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, 0, 0, mw, mh, 1, 1); -@@ -141,14 +143,24 @@ 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; -+ -+ ch = text[cursor]; -+ text[cursor] = '\0'; -+ curlen = drw_fontset_getwidth(drw, text); -+ text[cursor] = ch; -+ rcurlen = drw_fontset_getwidth(drw, text + cursor); -+ curpos += curlen - oldcurlen; -+ curpos = MIN(w, MAX(0, curpos)); -+ curpos = MAX(curpos, w - rcurlen); -+ curpos = MIN(curpos, curlen); -+ oldcurlen = curlen; - -- drw_font_getexts(drw->fonts, text, cursor, &curpos, NULL); -- if ((curpos += lrpad / 2 - 1) < w) { -- drw_setscheme(drw, scheme[SchemeNorm]); -- drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0); -- } -+ 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); --- -2.15.1 - diff --git a/tools.suckless.org/dmenu/patches/dmenu-scroll-20180607-a314412.diff b/tools.suckless.org/dmenu/patches/dmenu-scroll-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); diff --git a/tools.suckless.org/dmenu/patches/scroll.md b/tools.suckless.org/dmenu/patches/scroll.md @@ -7,7 +7,7 @@ in surf, after having inserted a long url via tab-completion. Download -------- -* [dmenu-scroll-20180224-8895128.diff](dmenu-scroll-20180224-8895128.diff) +* [dmenu-scroll-20180607-a314412.diff](dmenu-scroll-20180607-a314412.diff) Author ------