diff --git a/README.md b/README.md index 0810f6a..88f2046 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ Refer to [https://tools.suckless.org/dmenu/](https://tools.suckless.org/dmenu/) ### Changelog: +2020-06-13 - Added the pango patch + 2020-06-10 - Added the case-insensitive patch 2020-05-29 - Added the alpha patch (derived from Baitinq's [build](https://github.com/Baitinq/dmenu)) and the color emoji patch @@ -77,6 +79,9 @@ Refer to [https://tools.suckless.org/dmenu/](https://tools.suckless.org/dmenu/) - this means that you can continue feeding dmenu while you type - the patch is meant to be used along with the incremental patch in order to use stdout to feed stdin + - [pango](https://github.com/StillANixRookie/dmenu-pango/) + - adds simple markup for dmenu using pango markup + - [password](https://tools.suckless.org/dmenu/patches/password/) - with this patch dmenu will not directly display the keyboard input, but instead replace it with dots - all data from stdin will be ignored diff --git a/config.def.h b/config.def.h index 02b88ab..e4fda08 100644 --- a/config.def.h +++ b/config.def.h @@ -19,6 +19,9 @@ static int center = 1; /* -c option; if 0, dmenu won't be static int min_width = 500; /* minimum width when centered */ #endif // CENTER_PATCH /* -fn option overrides fonts[0]; default X11 font or font set */ +#if PANGO_PATCH +static char font[] = "monospace 10"; +#else #if XRESOURCES_PATCH static char *fonts[] = #else @@ -27,6 +30,7 @@ static const char *fonts[] = { "monospace:size=10" }; +#endif // PANGO_PATCH static const char *prompt = NULL; /* -p option; prompt to the left of input field */ #if ALPHA_PATCH diff --git a/config.mk b/config.mk index b79896e..45b75a0 100644 --- a/config.mk +++ b/config.mk @@ -19,11 +19,15 @@ FREETYPEINC = /usr/include/freetype2 #FREETYPEINC = $(X11INC)/freetype2 # Uncomment this for the alpha patch / ALPHA_PATCH -# XRENDER = -lXrender +#XRENDER = -lXrender + +# Uncomment for the pango patch / PANGO_PATCH +#PANGOINC = `pkg-config --cflags xft pango pangoxft` +#PANGOLIB = `pkg-config --libs xft pango pangoxft` # includes and libs -INCS = -I$(X11INC) -I$(FREETYPEINC) -LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm $(XRENDER) +INCS = -I$(X11INC) -I$(FREETYPEINC) ${PANGOINC} +LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm $(XRENDER) ${PANGOLIB} # flags CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) diff --git a/dmenu.c b/dmenu.c index b318b70..fef13b2 100644 --- a/dmenu.c +++ b/dmenu.c @@ -24,7 +24,12 @@ #define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org))) #define LENGTH(X) (sizeof X / sizeof X[0]) +#if PANGO_PATCH +#define TEXTW(X) (drw_font_getwidth(drw, (X), False) + lrpad) +#define TEXTWM(X) (drw_font_getwidth(drw, (X), True) + lrpad) +#else #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) +#endif // PANGO_PATCH #if ALPHA_PATCH #define OPAQUE 0xffU #define OPACITY "_NET_WM_WINDOW_OPACITY" @@ -160,10 +165,18 @@ calcoffsets(void) n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">")); /* calculate which items will begin the next page and previous page */ for (i = 0, next = curr; next; next = next->right) + #if PANGO_PATCH + if ((i += (lines > 0) ? bh : MIN(TEXTWM(next->text), n)) > n) + #else if ((i += (lines > 0) ? bh : MIN(TEXTW(next->text), n)) > n) + #endif // PANGO_PATCH break; for (i = 0, prev = curr; prev && prev->left; prev = prev->left) + #if PANGO_PATCH + if ((i += (lines > 0) ? bh : MIN(TEXTWM(prev->left->text), n)) > n) + #else if ((i += (lines > 0) ? bh : MIN(TEXTW(prev->left->text), n)) > n) + #endif // PANGO_PATCH break; } @@ -205,9 +218,15 @@ drawitem(struct item *item, int x, int y, int w) drw_setscheme(drw, scheme[SchemeNorm]); #if FUZZYHIGHLIGHT_PATCH + #if PANGO_PATCH + r = drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0, True); + #else r = drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); + #endif // PANGO_PATCH drawhighlights(item, x, y, w); return r; + #elif PANGO_PATCH + return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0, True); #else return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); #endif // FUZZYHIGHLIGHT_PATCH @@ -224,7 +243,9 @@ drawmenu(void) #endif // SCROLL_PATCH struct item *item; int x = 0, y = 0, w; - #if LINE_HEIGHT_PATCH + #if LINE_HEIGHT_PATCH && PANGO_PATCH + int fh = drw->font->h; + #elif LINE_HEIGHT_PATCH int fh = drw->fonts->h; #endif // LINE_HEIGHT_PATCH #if PASSWORD_PATCH @@ -236,7 +257,11 @@ drawmenu(void) if (prompt && *prompt) { drw_setscheme(drw, scheme[SchemeSel]); + #if PANGO_PATCH + x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0, True); + #else x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0); + #endif // PANGO_PATCH } /* draw input field */ w = (lines > 0 || !matches) ? mw - x : inputw; @@ -279,10 +304,20 @@ drawmenu(void) if (passwd) { censort = ecalloc(1, sizeof(text)); memset(censort, '.', strlen(text)); + #if PANGO_PATCH + drw_text(drw, x, 0, w, bh, lrpad / 2, censort, 0, False); + #else drw_text(drw, x, 0, w, bh, lrpad / 2, censort, 0); + #endif // PANGO_PATCH free(censort); } else + #if PANGO_PATCH + drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0, False); + #else drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); + #endif // PANGO_PATCH + #elif PANGO_PATCH + drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0, False); #else drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); #endif // PASSWORD_PATCH @@ -312,15 +347,27 @@ drawmenu(void) w = TEXTW("<"); if (curr->left) { drw_setscheme(drw, scheme[SchemeNorm]); + #if PANGO_PATCH + drw_text(drw, x, 0, w, bh, lrpad / 2, "<", 0, True); + #else drw_text(drw, x, 0, w, bh, lrpad / 2, "<", 0); + #endif // PANGO_PATCH } x += w; for (item = curr; item != next; item = item->right) + #if PANGO_PATCH + x = drawitem(item, x, 0, MIN(TEXTWM(item->text), mw - x - TEXTW(">"))); + #else x = drawitem(item, x, 0, MIN(TEXTW(item->text), mw - x - TEXTW(">"))); + #endif // PANGO_PATCH if (next) { w = TEXTW(">"); drw_setscheme(drw, scheme[SchemeNorm]); + #if PANGO_PATCH + drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0, True); + #else drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0); + #endif // PANGO_PATCH } } drw_map(drw, win, 0, 0, mw, mh); @@ -863,7 +910,11 @@ readstdin(void) if (!(items[i].text = strdup(buf))) die("cannot strdup %u bytes:", strlen(buf) + 1); items[i].out = 0; + #if PANGO_PATCH + drw_font_getexts(drw->font, buf, strlen(buf), &tmpmax, NULL, True); + #else drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL); + #endif // PANGO_PATCH if (tmpmax > inputw) { inputw = tmpmax; imax = i; @@ -871,7 +922,11 @@ readstdin(void) } if (items) items[i].text = NULL; + #if PANGO_PATCH + inputw = items ? TEXTWM(items[imax].text) : 0; + #else inputw = items ? TEXTW(items[imax].text) : 0; + #endif // PANGO_PATCH lines = MIN(lines, i); } #endif // NON_BLOCKING_STDIN_PATCH @@ -966,13 +1021,19 @@ setup(void) #endif // WMTYPE_PATCH /* calculate menu geometry */ + #if PANGO_PATCH + bh = drw->font->h + 2; + #else bh = drw->fonts->h + 2; + #endif // PANGO_PATCH #if LINE_HEIGHT_PATCH bh = MAX(bh,lineheight); /* make a menu line AT LEAST 'lineheight' tall */ #endif // LINE_HEIGHT_PATCH lines = MAX(lines, 0); mh = (lines + 1) * bh; - #if CENTER_PATCH + #if CENTER_PATCH && PANGO_PATCH + promptw = (prompt && *prompt) ? TEXTWM(prompt) - lrpad / 4 : 0; + #elif CENTER_PATCH promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; #endif // CENTER_PATCH #ifdef XINERAMA @@ -1060,7 +1121,11 @@ setup(void) #endif // CENTER_PATCH / XYW_PATCH } #if !CENTER_PATCH + #if PANGO_PATCH + promptw = (prompt && *prompt) ? TEXTWM(prompt) - lrpad / 4 : 0; + #else promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; + #endif // PANGO_PATCH #endif // CENTER_PATCH inputw = MIN(inputw, mw/3); match(); @@ -1276,7 +1341,11 @@ main(int argc, char *argv[]) else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */ prompt = argv[++i]; else if (!strcmp(argv[i], "-fn")) /* font or font set */ + #if PANGO_PATCH + strcpy(font, argv[++i]); + #else fonts[0] = argv[++i]; + #endif // PANGO_PATCH #if LINE_HEIGHT_PATCH else if(!strcmp(argv[i], "-h")) { /* minimum height of one menu line */ lineheight = atoi(argv[++i]); @@ -1336,15 +1405,27 @@ main(int argc, char *argv[]) #endif // ALPHA_PATCH #if XRESOURCES_PATCH readxresources(); + #if PANGO_PATCH + if (!drw_font_create(drw, font)) + die("no fonts could be loaded."); + #else if (!drw_fontset_create(drw, (const char**)fonts, LENGTH(fonts))) die("no fonts could be loaded."); free(fonts[0]); + #endif // PANGO_PATCH + #elif PANGO_PATCH + if (!drw_font_create(drw, font)) + die("no fonts could be loaded."); #else if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) die("no fonts could be loaded."); - #endif // XRESOURCES_PATCH + #endif // XRESOURCES_PATCH | PANGO_PATCH + #if PANGO_PATCH + lrpad = drw->font->h; + #else lrpad = drw->fonts->h; + #endif // PANGO_PATCH #ifdef __OpenBSD__ if (pledge("stdio rpath", NULL) == -1) diff --git a/drw.c b/drw.c index fecbb4e..33f8f20 100644 --- a/drw.c +++ b/drw.c @@ -9,6 +9,7 @@ #include "drw.h" #include "util.h" +#if !PANGO_PATCH #define UTF_INVALID 0xFFFD #define UTF_SIZ 4 @@ -60,6 +61,7 @@ utf8decode(const char *c, long *u, size_t clen) return len; } +#endif // PANGO_PATCH Drw * #if ALPHA_PATCH @@ -115,6 +117,41 @@ drw_free(Drw *drw) free(drw); } +#if PANGO_PATCH +/* This function is an implementation detail. Library users should use + * drw_font_create instead. + */ +static Fnt * +xfont_create(Drw *drw, const char *fontname) +{ + Fnt *font; + PangoFontMap *fontmap; + PangoContext *context; + PangoFontDescription *desc; + PangoFontMetrics *metrics; + + if (!fontname) { + die("no font specified."); + } + + font = ecalloc(1, sizeof(Fnt)); + font->dpy = drw->dpy; + + fontmap = pango_xft_get_font_map(drw->dpy, drw->screen); + context = pango_font_map_create_context(fontmap); + desc = pango_font_description_from_string(fontname); + font->layout = pango_layout_new(context); + pango_layout_set_font_description(font->layout, desc); + + metrics = pango_context_get_metrics(context, desc, pango_language_from_string ("en-us")); + font->h = pango_font_metrics_get_height(metrics) / PANGO_SCALE; + + pango_font_metrics_unref(metrics); + g_object_unref(context); + + return font; +} +#else /* This function is an implementation detail. Library users should use * drw_fontset_create instead. */ @@ -158,7 +195,7 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) * and lots more all over the internet. */ FcBool iscol; - if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { + if (FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { XftFontClose(drw->dpy, xfont); return NULL; } @@ -172,18 +209,38 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) return font; } +#endif // PANGO_PATCH static void xfont_free(Fnt *font) { if (!font) return; + #if PANGO_PATCH + if (font->layout) + g_object_unref(font->layout); + #else if (font->pattern) FcPatternDestroy(font->pattern); XftFontClose(font->dpy, font->xfont); + #endif // PANGO_PATCH free(font); } +#if PANGO_PATCH +Fnt* +drw_font_create(Drw* drw, const char font[]) +{ + Fnt *fnt = NULL; + + if (!drw || !font) + return NULL; + + fnt = xfont_create(drw, font); + + return (drw->font = fnt); +} +#else Fnt* drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) { @@ -201,7 +258,16 @@ drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) } return (drw->fonts = ret); } +#endif // PANGO_PATCH +#if PANGO_PATCH +void +drw_font_free(Fnt *font) +{ + if (font) + xfont_free(font); +} +#else void drw_fontset_free(Fnt *font) { @@ -210,6 +276,7 @@ drw_fontset_free(Fnt *font) xfont_free(font); } } +#endif // PANGO_PATCH void #if ALPHA_PATCH @@ -260,12 +327,14 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) return ret; } +#if !PANGO_PATCH void drw_setfontset(Drw *drw, Fnt *set) { if (drw) drw->fonts = set; } +#endif // PANGO_PATCH void drw_setscheme(Drw *drw, Clr *scm) @@ -286,6 +355,73 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); } +#if PANGO_PATCH +int +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup) +{ + char buf[1024]; + int ty; + unsigned int ew; + XftDraw *d = NULL; + size_t i, len; + int render = x || y || w || h; + + if (!drw || (render && !drw->scheme) || !text || !drw->font) + return 0; + + if (!render) { + w = ~w; + } else { + XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + #if ALPHA_PATCH + d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); + #else + d = XftDrawCreate(drw->dpy, drw->drawable, + DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen)); + #endif // ALPHA_PATCH + x += lpad; + w -= lpad; + } + + len = strlen(text); + + if (len) { + drw_font_getexts(drw->font, text, len, &ew, NULL, markup); + /* shorten text if necessary */ + for (len = MIN(len, sizeof(buf) - 1); len && ew > w; len--) + drw_font_getexts(drw->font, text, len, &ew, NULL, markup); + + if (len) { + memcpy(buf, text, len); + buf[len] = '\0'; + if (len < strlen(text)) + for (i = len; i && i > len - 3; buf[--i] = '.') + ; /* NOP */ + + if (render) { + ty = y + (h - drw->font->h) / 2; + if (markup) + pango_layout_set_markup(drw->font->layout, buf, len); + else + pango_layout_set_text(drw->font->layout, buf, len); + pango_xft_render_layout(d, &drw->scheme[invert ? ColBg : ColFg], + drw->font->layout, x * PANGO_SCALE, ty * PANGO_SCALE); + if (markup) /* clear markup attributes */ + pango_layout_set_attributes(drw->font->layout, NULL); + } + x += ew; + w -= ew; + } + } + + if (d) + XftDrawDestroy(d); + + return x + (render ? w : 0); +} +#else int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) { @@ -420,6 +556,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp return x + (render ? w : 0); } +#endif // PANGO_PATCH void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) @@ -431,6 +568,15 @@ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) XSync(drw->dpy, False); } +#if PANGO_PATCH +unsigned int +drw_font_getwidth(Drw *drw, const char *text, Bool markup) +{ + if (!drw || !drw->font || !text) + return 0; + return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup); +} +#else unsigned int drw_fontset_getwidth(Drw *drw, const char *text) { @@ -438,7 +584,29 @@ drw_fontset_getwidth(Drw *drw, const char *text) return 0; return drw_text(drw, 0, 0, 0, 0, 0, text, 0); } +#endif // PANGO_PATCH +#if PANGO_PATCH +void +drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup) +{ + if (!font || !text) + return; + + PangoRectangle r; + if (markup) + pango_layout_set_markup(font->layout, text, len); + else + pango_layout_set_text(font->layout, text, len); + pango_layout_get_extents(font->layout, 0, &r); + if (markup) /* clear markup attributes */ + pango_layout_set_attributes(font->layout, NULL); + if (w) + *w = r.width / PANGO_SCALE; + if (h) + *h = font->h; +} +#else void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) { @@ -453,6 +621,7 @@ drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, if (h) *h = font->h; } +#endif // PANGO_PATCH Cur * drw_cur_create(Drw *drw, int shape) diff --git a/drw.h b/drw.h index bd357c8..a51e6e3 100644 --- a/drw.h +++ b/drw.h @@ -1,5 +1,10 @@ /* See LICENSE file for copyright and license details. */ +#if PANGO_PATCH +#include +#include +#endif // PANGO_PATCH + typedef struct { Cursor cursor; } Cur; @@ -7,9 +12,13 @@ typedef struct { typedef struct Fnt { Display *dpy; unsigned int h; + #if PANGO_PATCH + PangoLayout *layout; + #else XftFont *xfont; FcPattern *pattern; struct Fnt *next; + #endif // PANGO_PATCH } Fnt; enum { ColFg, ColBg }; /* Clr scheme index */ @@ -28,7 +37,11 @@ typedef struct { Drawable drawable; GC gc; Clr *scheme; + #if PANGO_PATCH + Fnt *font; + #else Fnt *fonts; + #endif // PANGO_PATCH } Drw; /* Drawable abstraction */ @@ -41,10 +54,17 @@ void drw_resize(Drw *drw, unsigned int w, unsigned int h); void drw_free(Drw *drw); /* Fnt abstraction */ +#if PANGO_PATCH +Fnt *drw_font_create(Drw* drw, const char font[]); +void drw_font_free(Fnt* set); +unsigned int drw_font_getwidth(Drw *drw, const char *text, Bool markup); +void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup); +#else Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); void drw_fontset_free(Fnt* set); unsigned int drw_fontset_getwidth(Drw *drw, const char *text); void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); +#endif // PANGO_PATCH /* Colorscheme abstraction */ #if ALPHA_PATCH @@ -60,12 +80,18 @@ Cur *drw_cur_create(Drw *drw, int shape); void drw_cur_free(Drw *drw, Cur *cursor); /* Drawing context manipulation */ +#if !PANGO_PATCH void drw_setfontset(Drw *drw, Fnt *set); +#endif // PANGO_PATCH 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); +#if PANGO_PATCH +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup); +#else int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); +#endif // PANGO_PATCH /* Map functions */ void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); diff --git a/patch/fuzzyhighlight.c b/patch/fuzzyhighlight.c index c327552..5d32972 100644 --- a/patch/fuzzyhighlight.c +++ b/patch/fuzzyhighlight.c @@ -33,6 +33,9 @@ drawhighlights(struct item *item, int x, int y, int maxw) y, MIN(maxw - indent, TEXTW(highlight) - lrpad), bh, 0, highlight, 0 + #if PANGO_PATCH + , True + #endif // PANGO_PATCH ); highlight[1] = c; i++; diff --git a/patch/xresources.c b/patch/xresources.c index b434325..d324863 100644 --- a/patch/xresources.c +++ b/patch/xresources.c @@ -12,9 +12,15 @@ readxresources(void) XrmValue xval; if (XrmGetResource(xdb, "dmenu.font", "*", &type, &xval)) + #if PANGO_PATCH + strcpy(font, xval.addr); + #else fonts[0] = strdup(xval.addr); + #endif // PANGO_PATCH + #if !PANGO_PATCH else fonts[0] = strdup(fonts[0]); + #endif // PANGO_PATCH if (XrmGetResource(xdb, "dmenu.background", "*", &type, &xval)) colors[SchemeNorm][ColBg] = strdup(xval.addr); else diff --git a/patches.def.h b/patches.def.h index 083a664..9fdffd2 100644 --- a/patches.def.h +++ b/patches.def.h @@ -83,6 +83,29 @@ */ #define NON_BLOCKING_STDIN_PATCH 0 +/* This patch adds simple markup for dmenu using pango markup. + * This depends on the pango library v1.44 or greater. + * You need to uncomment the corresponding lines in config.mk to use the pango libraries + * when including this patch. + * + * Note that the pango patch is incompatible with the scroll patch and will result in + * compilation errors if both are enabled. + * + * Note that the pango patch does not protect against the BadLength error from Xft + * when color glyphs are used, which means that dmenu will crash if color emoji is used. + * + * If you need color emoji then you may want to install this patched library from the AUR: + * https://aur.archlinux.org/packages/libxft-bgra/ + * + * A long term fix for the libXft library is pending approval of this pull request: + * https://gitlab.freedesktop.org/xorg/lib/libxft/-/merge_requests/1 + * + * Also see: + * https://developer.gnome.org/pygtk/stable/pango-markup-language.html + * https://github.com/StillANixRookie/dmenu-pango + */ +#define PANGO_PATCH 0 + /* With this patch dmenu will not directly display the keyboard input, but instead replace * it with dots. All data from stdin will be ignored. * https://tools.suckless.org/dmenu/patches/password/ diff --git a/util.h b/util.h index f633b51..531ab25 100644 --- a/util.h +++ b/util.h @@ -1,7 +1,11 @@ /* See LICENSE file for copyright and license details. */ +#ifndef MAX #define MAX(A, B) ((A) > (B) ? (A) : (B)) +#endif +#ifndef MIN #define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif #define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) void die(const char *fmt, ...);