mirror of
https://github.com/mintycube/dmenu.git
synced 2024-10-22 12:05:48 +00:00
Adding pango patch
This commit is contained in:
parent
9248bbb392
commit
419de40e2c
@ -15,6 +15,8 @@ Refer to [https://tools.suckless.org/dmenu/](https://tools.suckless.org/dmenu/)
|
|||||||
|
|
||||||
### Changelog:
|
### Changelog:
|
||||||
|
|
||||||
|
2020-06-13 - Added the pango patch
|
||||||
|
|
||||||
2020-06-10 - Added the case-insensitive 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
|
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
|
- 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
|
- 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/)
|
- [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
|
- with this patch dmenu will not directly display the keyboard input, but instead replace it with dots
|
||||||
- all data from stdin will be ignored
|
- all data from stdin will be ignored
|
||||||
|
@ -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 */
|
static int min_width = 500; /* minimum width when centered */
|
||||||
#endif // CENTER_PATCH
|
#endif // CENTER_PATCH
|
||||||
/* -fn option overrides fonts[0]; default X11 font or font set */
|
/* -fn option overrides fonts[0]; default X11 font or font set */
|
||||||
|
#if PANGO_PATCH
|
||||||
|
static char font[] = "monospace 10";
|
||||||
|
#else
|
||||||
#if XRESOURCES_PATCH
|
#if XRESOURCES_PATCH
|
||||||
static char *fonts[] =
|
static char *fonts[] =
|
||||||
#else
|
#else
|
||||||
@ -27,6 +30,7 @@ static const char *fonts[] =
|
|||||||
{
|
{
|
||||||
"monospace:size=10"
|
"monospace:size=10"
|
||||||
};
|
};
|
||||||
|
#endif // PANGO_PATCH
|
||||||
static const char *prompt = NULL; /* -p option; prompt to the left of input field */
|
static const char *prompt = NULL; /* -p option; prompt to the left of input field */
|
||||||
|
|
||||||
#if ALPHA_PATCH
|
#if ALPHA_PATCH
|
||||||
|
10
config.mk
10
config.mk
@ -19,11 +19,15 @@ FREETYPEINC = /usr/include/freetype2
|
|||||||
#FREETYPEINC = $(X11INC)/freetype2
|
#FREETYPEINC = $(X11INC)/freetype2
|
||||||
|
|
||||||
# Uncomment this for the alpha patch / ALPHA_PATCH
|
# 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
|
# includes and libs
|
||||||
INCS = -I$(X11INC) -I$(FREETYPEINC)
|
INCS = -I$(X11INC) -I$(FREETYPEINC) ${PANGOINC}
|
||||||
LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm $(XRENDER)
|
LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm $(XRENDER) ${PANGOLIB}
|
||||||
|
|
||||||
# flags
|
# flags
|
||||||
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
|
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
|
||||||
|
87
dmenu.c
87
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)) \
|
#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)))
|
* MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org)))
|
||||||
#define LENGTH(X) (sizeof X / sizeof X[0])
|
#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)
|
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
|
||||||
|
#endif // PANGO_PATCH
|
||||||
#if ALPHA_PATCH
|
#if ALPHA_PATCH
|
||||||
#define OPAQUE 0xffU
|
#define OPAQUE 0xffU
|
||||||
#define OPACITY "_NET_WM_WINDOW_OPACITY"
|
#define OPACITY "_NET_WM_WINDOW_OPACITY"
|
||||||
@ -160,10 +165,18 @@ calcoffsets(void)
|
|||||||
n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">"));
|
n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">"));
|
||||||
/* calculate which items will begin the next page and previous page */
|
/* calculate which items will begin the next page and previous page */
|
||||||
for (i = 0, next = curr; next; next = next->right)
|
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)
|
if ((i += (lines > 0) ? bh : MIN(TEXTW(next->text), n)) > n)
|
||||||
|
#endif // PANGO_PATCH
|
||||||
break;
|
break;
|
||||||
for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
|
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)
|
if ((i += (lines > 0) ? bh : MIN(TEXTW(prev->left->text), n)) > n)
|
||||||
|
#endif // PANGO_PATCH
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,9 +218,15 @@ drawitem(struct item *item, int x, int y, int w)
|
|||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
drw_setscheme(drw, scheme[SchemeNorm]);
|
||||||
|
|
||||||
#if FUZZYHIGHLIGHT_PATCH
|
#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);
|
r = drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0);
|
||||||
|
#endif // PANGO_PATCH
|
||||||
drawhighlights(item, x, y, w);
|
drawhighlights(item, x, y, w);
|
||||||
return r;
|
return r;
|
||||||
|
#elif PANGO_PATCH
|
||||||
|
return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0, True);
|
||||||
#else
|
#else
|
||||||
return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0);
|
return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0);
|
||||||
#endif // FUZZYHIGHLIGHT_PATCH
|
#endif // FUZZYHIGHLIGHT_PATCH
|
||||||
@ -224,7 +243,9 @@ drawmenu(void)
|
|||||||
#endif // SCROLL_PATCH
|
#endif // SCROLL_PATCH
|
||||||
struct item *item;
|
struct item *item;
|
||||||
int x = 0, y = 0, w;
|
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;
|
int fh = drw->fonts->h;
|
||||||
#endif // LINE_HEIGHT_PATCH
|
#endif // LINE_HEIGHT_PATCH
|
||||||
#if PASSWORD_PATCH
|
#if PASSWORD_PATCH
|
||||||
@ -236,7 +257,11 @@ drawmenu(void)
|
|||||||
|
|
||||||
if (prompt && *prompt) {
|
if (prompt && *prompt) {
|
||||||
drw_setscheme(drw, scheme[SchemeSel]);
|
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);
|
x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0);
|
||||||
|
#endif // PANGO_PATCH
|
||||||
}
|
}
|
||||||
/* draw input field */
|
/* draw input field */
|
||||||
w = (lines > 0 || !matches) ? mw - x : inputw;
|
w = (lines > 0 || !matches) ? mw - x : inputw;
|
||||||
@ -279,10 +304,20 @@ drawmenu(void)
|
|||||||
if (passwd) {
|
if (passwd) {
|
||||||
censort = ecalloc(1, sizeof(text));
|
censort = ecalloc(1, sizeof(text));
|
||||||
memset(censort, '.', strlen(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);
|
drw_text(drw, x, 0, w, bh, lrpad / 2, censort, 0);
|
||||||
|
#endif // PANGO_PATCH
|
||||||
free(censort);
|
free(censort);
|
||||||
} else
|
} 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);
|
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
|
#else
|
||||||
drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0);
|
drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0);
|
||||||
#endif // PASSWORD_PATCH
|
#endif // PASSWORD_PATCH
|
||||||
@ -312,15 +347,27 @@ drawmenu(void)
|
|||||||
w = TEXTW("<");
|
w = TEXTW("<");
|
||||||
if (curr->left) {
|
if (curr->left) {
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
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);
|
drw_text(drw, x, 0, w, bh, lrpad / 2, "<", 0);
|
||||||
|
#endif // PANGO_PATCH
|
||||||
}
|
}
|
||||||
x += w;
|
x += w;
|
||||||
for (item = curr; item != next; item = item->right)
|
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(">")));
|
x = drawitem(item, x, 0, MIN(TEXTW(item->text), mw - x - TEXTW(">")));
|
||||||
|
#endif // PANGO_PATCH
|
||||||
if (next) {
|
if (next) {
|
||||||
w = TEXTW(">");
|
w = TEXTW(">");
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
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);
|
drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0);
|
||||||
|
#endif // PANGO_PATCH
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drw_map(drw, win, 0, 0, mw, mh);
|
drw_map(drw, win, 0, 0, mw, mh);
|
||||||
@ -863,7 +910,11 @@ readstdin(void)
|
|||||||
if (!(items[i].text = strdup(buf)))
|
if (!(items[i].text = strdup(buf)))
|
||||||
die("cannot strdup %u bytes:", strlen(buf) + 1);
|
die("cannot strdup %u bytes:", strlen(buf) + 1);
|
||||||
items[i].out = 0;
|
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);
|
drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL);
|
||||||
|
#endif // PANGO_PATCH
|
||||||
if (tmpmax > inputw) {
|
if (tmpmax > inputw) {
|
||||||
inputw = tmpmax;
|
inputw = tmpmax;
|
||||||
imax = i;
|
imax = i;
|
||||||
@ -871,7 +922,11 @@ readstdin(void)
|
|||||||
}
|
}
|
||||||
if (items)
|
if (items)
|
||||||
items[i].text = NULL;
|
items[i].text = NULL;
|
||||||
|
#if PANGO_PATCH
|
||||||
|
inputw = items ? TEXTWM(items[imax].text) : 0;
|
||||||
|
#else
|
||||||
inputw = items ? TEXTW(items[imax].text) : 0;
|
inputw = items ? TEXTW(items[imax].text) : 0;
|
||||||
|
#endif // PANGO_PATCH
|
||||||
lines = MIN(lines, i);
|
lines = MIN(lines, i);
|
||||||
}
|
}
|
||||||
#endif // NON_BLOCKING_STDIN_PATCH
|
#endif // NON_BLOCKING_STDIN_PATCH
|
||||||
@ -966,13 +1021,19 @@ setup(void)
|
|||||||
#endif // WMTYPE_PATCH
|
#endif // WMTYPE_PATCH
|
||||||
|
|
||||||
/* calculate menu geometry */
|
/* calculate menu geometry */
|
||||||
|
#if PANGO_PATCH
|
||||||
|
bh = drw->font->h + 2;
|
||||||
|
#else
|
||||||
bh = drw->fonts->h + 2;
|
bh = drw->fonts->h + 2;
|
||||||
|
#endif // PANGO_PATCH
|
||||||
#if LINE_HEIGHT_PATCH
|
#if LINE_HEIGHT_PATCH
|
||||||
bh = MAX(bh,lineheight); /* make a menu line AT LEAST 'lineheight' tall */
|
bh = MAX(bh,lineheight); /* make a menu line AT LEAST 'lineheight' tall */
|
||||||
#endif // LINE_HEIGHT_PATCH
|
#endif // LINE_HEIGHT_PATCH
|
||||||
lines = MAX(lines, 0);
|
lines = MAX(lines, 0);
|
||||||
mh = (lines + 1) * bh;
|
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;
|
promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
|
||||||
#endif // CENTER_PATCH
|
#endif // CENTER_PATCH
|
||||||
#ifdef XINERAMA
|
#ifdef XINERAMA
|
||||||
@ -1060,7 +1121,11 @@ setup(void)
|
|||||||
#endif // CENTER_PATCH / XYW_PATCH
|
#endif // CENTER_PATCH / XYW_PATCH
|
||||||
}
|
}
|
||||||
#if !CENTER_PATCH
|
#if !CENTER_PATCH
|
||||||
|
#if PANGO_PATCH
|
||||||
|
promptw = (prompt && *prompt) ? TEXTWM(prompt) - lrpad / 4 : 0;
|
||||||
|
#else
|
||||||
promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
|
promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
|
||||||
|
#endif // PANGO_PATCH
|
||||||
#endif // CENTER_PATCH
|
#endif // CENTER_PATCH
|
||||||
inputw = MIN(inputw, mw/3);
|
inputw = MIN(inputw, mw/3);
|
||||||
match();
|
match();
|
||||||
@ -1276,7 +1341,11 @@ main(int argc, char *argv[])
|
|||||||
else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */
|
else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */
|
||||||
prompt = argv[++i];
|
prompt = argv[++i];
|
||||||
else if (!strcmp(argv[i], "-fn")) /* font or font set */
|
else if (!strcmp(argv[i], "-fn")) /* font or font set */
|
||||||
|
#if PANGO_PATCH
|
||||||
|
strcpy(font, argv[++i]);
|
||||||
|
#else
|
||||||
fonts[0] = argv[++i];
|
fonts[0] = argv[++i];
|
||||||
|
#endif // PANGO_PATCH
|
||||||
#if LINE_HEIGHT_PATCH
|
#if LINE_HEIGHT_PATCH
|
||||||
else if(!strcmp(argv[i], "-h")) { /* minimum height of one menu line */
|
else if(!strcmp(argv[i], "-h")) { /* minimum height of one menu line */
|
||||||
lineheight = atoi(argv[++i]);
|
lineheight = atoi(argv[++i]);
|
||||||
@ -1336,15 +1405,27 @@ main(int argc, char *argv[])
|
|||||||
#endif // ALPHA_PATCH
|
#endif // ALPHA_PATCH
|
||||||
#if XRESOURCES_PATCH
|
#if XRESOURCES_PATCH
|
||||||
readxresources();
|
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)))
|
if (!drw_fontset_create(drw, (const char**)fonts, LENGTH(fonts)))
|
||||||
die("no fonts could be loaded.");
|
die("no fonts could be loaded.");
|
||||||
|
|
||||||
free(fonts[0]);
|
free(fonts[0]);
|
||||||
|
#endif // PANGO_PATCH
|
||||||
|
#elif PANGO_PATCH
|
||||||
|
if (!drw_font_create(drw, font))
|
||||||
|
die("no fonts could be loaded.");
|
||||||
#else
|
#else
|
||||||
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
|
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
|
||||||
die("no fonts could be loaded.");
|
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;
|
lrpad = drw->fonts->h;
|
||||||
|
#endif // PANGO_PATCH
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
if (pledge("stdio rpath", NULL) == -1)
|
if (pledge("stdio rpath", NULL) == -1)
|
||||||
|
171
drw.c
171
drw.c
@ -9,6 +9,7 @@
|
|||||||
#include "drw.h"
|
#include "drw.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#if !PANGO_PATCH
|
||||||
#define UTF_INVALID 0xFFFD
|
#define UTF_INVALID 0xFFFD
|
||||||
#define UTF_SIZ 4
|
#define UTF_SIZ 4
|
||||||
|
|
||||||
@ -60,6 +61,7 @@ utf8decode(const char *c, long *u, size_t clen)
|
|||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
#endif // PANGO_PATCH
|
||||||
|
|
||||||
Drw *
|
Drw *
|
||||||
#if ALPHA_PATCH
|
#if ALPHA_PATCH
|
||||||
@ -115,6 +117,41 @@ drw_free(Drw *drw)
|
|||||||
free(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
|
/* This function is an implementation detail. Library users should use
|
||||||
* drw_fontset_create instead.
|
* drw_fontset_create instead.
|
||||||
*/
|
*/
|
||||||
@ -158,7 +195,7 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
|
|||||||
* and lots more all over the internet.
|
* and lots more all over the internet.
|
||||||
*/
|
*/
|
||||||
FcBool iscol;
|
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);
|
XftFontClose(drw->dpy, xfont);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -172,18 +209,38 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
|
|||||||
|
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
#endif // PANGO_PATCH
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xfont_free(Fnt *font)
|
xfont_free(Fnt *font)
|
||||||
{
|
{
|
||||||
if (!font)
|
if (!font)
|
||||||
return;
|
return;
|
||||||
|
#if PANGO_PATCH
|
||||||
|
if (font->layout)
|
||||||
|
g_object_unref(font->layout);
|
||||||
|
#else
|
||||||
if (font->pattern)
|
if (font->pattern)
|
||||||
FcPatternDestroy(font->pattern);
|
FcPatternDestroy(font->pattern);
|
||||||
XftFontClose(font->dpy, font->xfont);
|
XftFontClose(font->dpy, font->xfont);
|
||||||
|
#endif // PANGO_PATCH
|
||||||
free(font);
|
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*
|
Fnt*
|
||||||
drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
|
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);
|
return (drw->fonts = ret);
|
||||||
}
|
}
|
||||||
|
#endif // PANGO_PATCH
|
||||||
|
|
||||||
|
#if PANGO_PATCH
|
||||||
|
void
|
||||||
|
drw_font_free(Fnt *font)
|
||||||
|
{
|
||||||
|
if (font)
|
||||||
|
xfont_free(font);
|
||||||
|
}
|
||||||
|
#else
|
||||||
void
|
void
|
||||||
drw_fontset_free(Fnt *font)
|
drw_fontset_free(Fnt *font)
|
||||||
{
|
{
|
||||||
@ -210,6 +276,7 @@ drw_fontset_free(Fnt *font)
|
|||||||
xfont_free(font);
|
xfont_free(font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // PANGO_PATCH
|
||||||
|
|
||||||
void
|
void
|
||||||
#if ALPHA_PATCH
|
#if ALPHA_PATCH
|
||||||
@ -260,12 +327,14 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !PANGO_PATCH
|
||||||
void
|
void
|
||||||
drw_setfontset(Drw *drw, Fnt *set)
|
drw_setfontset(Drw *drw, Fnt *set)
|
||||||
{
|
{
|
||||||
if (drw)
|
if (drw)
|
||||||
drw->fonts = set;
|
drw->fonts = set;
|
||||||
}
|
}
|
||||||
|
#endif // PANGO_PATCH
|
||||||
|
|
||||||
void
|
void
|
||||||
drw_setscheme(Drw *drw, Clr *scm)
|
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);
|
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
|
int
|
||||||
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
|
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);
|
return x + (render ? w : 0);
|
||||||
}
|
}
|
||||||
|
#endif // PANGO_PATCH
|
||||||
|
|
||||||
void
|
void
|
||||||
drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
|
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);
|
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
|
unsigned int
|
||||||
drw_fontset_getwidth(Drw *drw, const char *text)
|
drw_fontset_getwidth(Drw *drw, const char *text)
|
||||||
{
|
{
|
||||||
@ -438,7 +584,29 @@ drw_fontset_getwidth(Drw *drw, const char *text)
|
|||||||
return 0;
|
return 0;
|
||||||
return drw_text(drw, 0, 0, 0, 0, 0, text, 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
|
void
|
||||||
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
|
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)
|
if (h)
|
||||||
*h = font->h;
|
*h = font->h;
|
||||||
}
|
}
|
||||||
|
#endif // PANGO_PATCH
|
||||||
|
|
||||||
Cur *
|
Cur *
|
||||||
drw_cur_create(Drw *drw, int shape)
|
drw_cur_create(Drw *drw, int shape)
|
||||||
|
26
drw.h
26
drw.h
@ -1,5 +1,10 @@
|
|||||||
/* See LICENSE file for copyright and license details. */
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
|
||||||
|
#if PANGO_PATCH
|
||||||
|
#include <pango/pango.h>
|
||||||
|
#include <pango/pangoxft.h>
|
||||||
|
#endif // PANGO_PATCH
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Cursor cursor;
|
Cursor cursor;
|
||||||
} Cur;
|
} Cur;
|
||||||
@ -7,9 +12,13 @@ typedef struct {
|
|||||||
typedef struct Fnt {
|
typedef struct Fnt {
|
||||||
Display *dpy;
|
Display *dpy;
|
||||||
unsigned int h;
|
unsigned int h;
|
||||||
|
#if PANGO_PATCH
|
||||||
|
PangoLayout *layout;
|
||||||
|
#else
|
||||||
XftFont *xfont;
|
XftFont *xfont;
|
||||||
FcPattern *pattern;
|
FcPattern *pattern;
|
||||||
struct Fnt *next;
|
struct Fnt *next;
|
||||||
|
#endif // PANGO_PATCH
|
||||||
} Fnt;
|
} Fnt;
|
||||||
|
|
||||||
enum { ColFg, ColBg }; /* Clr scheme index */
|
enum { ColFg, ColBg }; /* Clr scheme index */
|
||||||
@ -28,7 +37,11 @@ typedef struct {
|
|||||||
Drawable drawable;
|
Drawable drawable;
|
||||||
GC gc;
|
GC gc;
|
||||||
Clr *scheme;
|
Clr *scheme;
|
||||||
|
#if PANGO_PATCH
|
||||||
|
Fnt *font;
|
||||||
|
#else
|
||||||
Fnt *fonts;
|
Fnt *fonts;
|
||||||
|
#endif // PANGO_PATCH
|
||||||
} Drw;
|
} Drw;
|
||||||
|
|
||||||
/* Drawable abstraction */
|
/* Drawable abstraction */
|
||||||
@ -41,10 +54,17 @@ void drw_resize(Drw *drw, unsigned int w, unsigned int h);
|
|||||||
void drw_free(Drw *drw);
|
void drw_free(Drw *drw);
|
||||||
|
|
||||||
/* Fnt abstraction */
|
/* 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);
|
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
|
||||||
void drw_fontset_free(Fnt* set);
|
void drw_fontset_free(Fnt* set);
|
||||||
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
|
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);
|
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
|
||||||
|
#endif // PANGO_PATCH
|
||||||
|
|
||||||
/* Colorscheme abstraction */
|
/* Colorscheme abstraction */
|
||||||
#if ALPHA_PATCH
|
#if ALPHA_PATCH
|
||||||
@ -60,12 +80,18 @@ Cur *drw_cur_create(Drw *drw, int shape);
|
|||||||
void drw_cur_free(Drw *drw, Cur *cursor);
|
void drw_cur_free(Drw *drw, Cur *cursor);
|
||||||
|
|
||||||
/* Drawing context manipulation */
|
/* Drawing context manipulation */
|
||||||
|
#if !PANGO_PATCH
|
||||||
void drw_setfontset(Drw *drw, Fnt *set);
|
void drw_setfontset(Drw *drw, Fnt *set);
|
||||||
|
#endif // PANGO_PATCH
|
||||||
void drw_setscheme(Drw *drw, Clr *scm);
|
void drw_setscheme(Drw *drw, Clr *scm);
|
||||||
|
|
||||||
/* Drawing functions */
|
/* Drawing functions */
|
||||||
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
|
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);
|
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 */
|
/* Map functions */
|
||||||
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
|
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
|
||||||
|
@ -33,6 +33,9 @@ drawhighlights(struct item *item, int x, int y, int maxw)
|
|||||||
y,
|
y,
|
||||||
MIN(maxw - indent, TEXTW(highlight) - lrpad),
|
MIN(maxw - indent, TEXTW(highlight) - lrpad),
|
||||||
bh, 0, highlight, 0
|
bh, 0, highlight, 0
|
||||||
|
#if PANGO_PATCH
|
||||||
|
, True
|
||||||
|
#endif // PANGO_PATCH
|
||||||
);
|
);
|
||||||
highlight[1] = c;
|
highlight[1] = c;
|
||||||
i++;
|
i++;
|
||||||
|
@ -12,9 +12,15 @@ readxresources(void)
|
|||||||
XrmValue xval;
|
XrmValue xval;
|
||||||
|
|
||||||
if (XrmGetResource(xdb, "dmenu.font", "*", &type, &xval))
|
if (XrmGetResource(xdb, "dmenu.font", "*", &type, &xval))
|
||||||
|
#if PANGO_PATCH
|
||||||
|
strcpy(font, xval.addr);
|
||||||
|
#else
|
||||||
fonts[0] = strdup(xval.addr);
|
fonts[0] = strdup(xval.addr);
|
||||||
|
#endif // PANGO_PATCH
|
||||||
|
#if !PANGO_PATCH
|
||||||
else
|
else
|
||||||
fonts[0] = strdup(fonts[0]);
|
fonts[0] = strdup(fonts[0]);
|
||||||
|
#endif // PANGO_PATCH
|
||||||
if (XrmGetResource(xdb, "dmenu.background", "*", &type, &xval))
|
if (XrmGetResource(xdb, "dmenu.background", "*", &type, &xval))
|
||||||
colors[SchemeNorm][ColBg] = strdup(xval.addr);
|
colors[SchemeNorm][ColBg] = strdup(xval.addr);
|
||||||
else
|
else
|
||||||
|
@ -83,6 +83,29 @@
|
|||||||
*/
|
*/
|
||||||
#define NON_BLOCKING_STDIN_PATCH 0
|
#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
|
/* With this patch dmenu will not directly display the keyboard input, but instead replace
|
||||||
* it with dots. All data from stdin will be ignored.
|
* it with dots. All data from stdin will be ignored.
|
||||||
* https://tools.suckless.org/dmenu/patches/password/
|
* https://tools.suckless.org/dmenu/patches/password/
|
||||||
|
4
util.h
4
util.h
@ -1,7 +1,11 @@
|
|||||||
/* See LICENSE file for copyright and license details. */
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||||
|
#endif
|
||||||
|
#ifndef MIN
|
||||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||||
|
#endif
|
||||||
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
|
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
|
||||||
|
|
||||||
void die(const char *fmt, ...);
|
void die(const char *fmt, ...);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user