X-Git-Url: https://git.subgeniuskitty.com/xmenu/.git/blobdiff_plain/7539247be35bae830dcc467d5fb415fdcaf99eed..70063f16f5da4e9eef33d369a41d7a0365ca11fa:/xmenu.c diff --git a/xmenu.c b/xmenu.c index c5a0795..3c83cd3 100644 --- a/xmenu.c +++ b/xmenu.c @@ -41,6 +41,7 @@ static struct Menu *parsestdin(void); /* text drawer, and its helper routine */ static FcChar32 getnextutf8char(const char *s, const char **end_ret); +static XftFont *getfontucode(FcChar32 ucode); static int drawtext(XftDraw *draw, XftColor *color, int x, int y, unsigned h, const char *text); /* structure setters, and their helper routines */ @@ -255,12 +256,16 @@ parsefonts(const char *s) i = 0; while (isspace(*p)) p++; - while (*p != '\0' && *p != ',') { + while (i < sizeof buf && *p != '\0' && *p != ',') buf[i++] = *p++; - } + if (i >= sizeof buf) + errx(1, "font name too long"); if (*p == ',') p++; buf[i] = '\0'; + if (nfont == 0) + if ((dc.pattern = FcNameParse((FcChar8 *)buf)) == NULL) + errx(1, "the first font in the cache must be loaded from a font string"); if ((dc.fonts[nfont++] = XftFontOpenName(dpy, screen, buf)) == NULL) errx(1, "cannot load font"); } @@ -295,7 +300,7 @@ initmonitor(void) if ((info = XineramaQueryScreens(dpy, &nmons)) != NULL) { int selmon = 0; - if (!mflag || (mflag && (config.monitor < 0 || config.monitor >= nmons))) { + if (!mflag || config.monitor < 0 || config.monitor >= nmons) { for (i = 0; i < nmons; i++) { if (BETWEEN(cursx, info[i].x_org, info[i].x_org + info[i].width) && BETWEEN(cursy, info[i].y_org, info[i].y_org + info[i].height)) { @@ -634,51 +639,87 @@ getnextutf8char(const char *s, const char **next_ret) return ucode; } -/* draw text into XftDraw */ +/* get which font contains a given code point */ +static XftFont * +getfontucode(FcChar32 ucode) +{ + FcCharSet *fccharset = NULL; + FcPattern *fcpattern = NULL; + FcPattern *match = NULL; + XftFont *retfont = NULL; + XftResult result; + size_t i; + + for (i = 0; i < dc.nfonts; i++) + if (XftCharExists(dpy, dc.fonts[i], ucode) == FcTrue) + return dc.fonts[i]; + + /* create a charset containing our code point */ + fccharset = FcCharSetCreate(); + FcCharSetAddChar(fccharset, ucode); + + /* create a pattern akin to the dc.pattern but containing our charset */ + if (fccharset) { + fcpattern = FcPatternDuplicate(dc.pattern); + FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); + } + + /* find pattern matching fcpattern */ + if (fcpattern) { + FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); + FcDefaultSubstitute(fcpattern); + match = XftFontMatch(dpy, screen, fcpattern, &result); + } + + /* if found a pattern, open its font */ + if (match) { + retfont = XftFontOpenPattern(dpy, match); + if (retfont && XftCharExists(dpy, retfont, ucode) == FcTrue) { + if ((dc.fonts = realloc(dc.fonts, dc.nfonts+1)) == NULL) + err(1, "realloc"); + dc.fonts[dc.nfonts] = retfont; + return dc.fonts[dc.nfonts++]; + } else { + XftFontClose(dpy, retfont); + } + } + + /* in case no fount was found, return the first one */ + return dc.fonts[0]; +} + +/* draw text into XftDraw, return width of text glyphs */ static int drawtext(XftDraw *draw, XftColor *color, int x, int y, unsigned h, const char *text) { - const char *s, *nexts; - FcChar32 ucode; - XftFont *currfont; - int textlen = 0; + int textwidth = 0; - s = text; - while (*s) { + while (*text) { + XftFont *currfont; XGlyphInfo ext; - int charexists; + FcChar32 ucode; + const char *next; size_t len; - size_t i; - - charexists = 0; - ucode = getnextutf8char(s, &nexts); - for (i = 0; i < dc.nfonts; i++) { - charexists = XftCharExists(dpy, dc.fonts[i], ucode); - if (charexists) - break; - } - if (charexists) - currfont = dc.fonts[i]; - len = nexts - s; + ucode = getnextutf8char(text, &next); + currfont = getfontucode(ucode); - XftTextExtentsUtf8(dpy, currfont, (XftChar8 *)s, - len, &ext); - textlen += ext.xOff; + len = next - text; + XftTextExtentsUtf8(dpy, currfont, (XftChar8 *)text, len, &ext); + textwidth += ext.xOff; if (draw) { int texty; texty = y + (h - (currfont->ascent + currfont->descent))/2 + currfont->ascent; - XftDrawStringUtf8(draw, color, currfont, x, texty, - (XftChar8 *)s, len); + XftDrawStringUtf8(draw, color, currfont, x, texty, (XftChar8 *)text, len); x += ext.xOff; } - s = nexts; + text = next; } - return textlen; + return textwidth; } /* setup the height, width and icon of the items of a menu */