sites

public wiki contents of suckless.org
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 + 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);