add initial X11 version - libsl - draw back-ends for dwm, dmenu, etc
 (HTM) git clone git://git.codemadness.org/libsl
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit b450cbeceb639c6372733d14d1a3af95550109d2
 (DIR) parent 09ba5ebb3fb9c4b4766d7efb7a477a624734f135
 (HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       Date:   Thu, 26 Sep 2019 23:03:21 +0200
       
       add initial X11 version
       
       based on a combination of the current drw logic and the "old" X11 version code.
       
       Diffstat:
         A x11/drw.c                           |     254 +++++++++++++++++++++++++++++++
         A x11/drw.h                           |      58 ++++++++++++++++++++++++++++++
       
       2 files changed, 312 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/x11/drw.c b/x11/drw.c
       @@ -0,0 +1,254 @@
       +/* See LICENSE file for copyright and license details. */
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +#include <X11/Xlib.h>
       +
       +#include "drw.h"
       +#include "util.h"
       +
       +Drw *
       +drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
       +{
       +        Drw *drw;
       +
       +        drw = ecalloc(1, sizeof(Drw));
       +        drw->dpy = dpy;
       +        drw->screen = screen;
       +        drw->root = root;
       +        drw->w = w;
       +        drw->h = h;
       +        drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
       +        drw->gc = XCreateGC(dpy, root, 0, NULL);
       +        XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
       +
       +        return drw;
       +}
       +
       +void
       +drw_resize(Drw *drw, unsigned int w, unsigned int h)
       +{
       +        drw->w = w;
       +        drw->h = h;
       +        if (drw->drawable)
       +                XFreePixmap(drw->dpy, drw->drawable);
       +        drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
       +}
       +
       +void
       +drw_free(Drw *drw)
       +{
       +        XFreePixmap(drw->dpy, drw->drawable);
       +        XFreeGC(drw->dpy, drw->gc);
       +        free(drw);
       +}
       +
       +static Fnt *
       +xfont_create(Display *dpy, const char *fontname)
       +{
       +        Fnt *font;
       +        XFontStruct **xfonts;
       +        char **font_names;
       +        char *def, **missing;
       +        int n;
       +
       +        font = ecalloc(1, sizeof(Fnt));
       +        font->dpy = dpy;
       +        font->set = XCreateFontSet(dpy, fontname, &missing, &n, &def);
       +        if (missing) {
       +                while (n--)
       +                        fprintf(stderr, "drw: missing fontset: %s\n", missing[n]);
       +                XFreeStringList(missing);
       +        }
       +        if (font->set) {
       +                XExtentsOfFontSet(font->set);
       +                n = XFontsOfFontSet(font->set, &xfonts, &font_names);
       +                while (n--) {
       +                        font->ascent = MAX(font->ascent, (*xfonts)->ascent);
       +                        font->descent = MAX(font->descent,(*xfonts)->descent);
       +                        xfonts++;
       +                }
       +        } else {
       +                if (!(font->xfont = XLoadQueryFont(dpy, fontname))
       +                && !(font->xfont = XLoadQueryFont(dpy, "fixed")))
       +                        die("error, cannot load font: '%s'\n", fontname);
       +                font->ascent = font->xfont->ascent;
       +                font->descent = font->xfont->descent;
       +        }
       +        font->h = font->ascent + font->descent;
       +
       +        return font;
       +}
       +
       +void
       +xfont_free(Display *dpy, Fnt *font)
       +{
       +        if (font->set)
       +                XFreeFontSet(dpy, font->set);
       +        else
       +                XFreeFont(dpy, font->xfont);
       +        free(font);
       +}
       +
       +Fnt *
       +drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
       +{
       +        /* just create using first font */
       +        /* TODO: more? */
       +        drw->fonts = xfont_create(drw->dpy, fonts[0]);
       +        return drw->fonts;
       +}
       +
       +void
       +drw_fontset_free(Fnt *font)
       +{
       +        xfont_free(font->dpy, font);
       +}
       +
       +void
       +drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
       +{
       +        Colormap cmap;
       +        XColor ecolor;
       +
       +        cmap = DefaultColormap(drw->dpy, drw->screen);
       +        if (!XAllocNamedColor(drw->dpy, cmap, clrname, dest, &ecolor))
       +                die("error, cannot allocate color '%s'\n", clrname);
       +}
       +
       +/* Wrapper to create color schemes. The caller has to call free(3) on the
       + * returned color scheme when done using it. */
       +Clr *
       +drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
       +{
       +        size_t i;
       +        Clr *ret;
       +
       +        ret = ecalloc(clrcount, sizeof(Clr));
       +        for (i = 0; i < clrcount; i++)
       +                drw_clr_create(drw, &ret[i], clrnames[i]);
       +
       +        return ret;
       +}
       +
       +void
       +drw_setfontset(Drw *drw, Fnt *set)
       +{
       +        drw->fonts = set;
       +}
       +
       +void
       +drw_setscheme(Drw *drw, Clr *scheme)
       +{
       +        drw->scheme = scheme;
       +}
       +
       +void
       +drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled,
       +        int invert)
       +{
       +        int dx;
       +
       +        XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColBg : ColFg].pixel);
       +        dx = (drw->fonts->ascent + drw->fonts->descent + 2) / 4;
       +        if (filled)
       +                XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w + 1, h + 1);
       +        else
       +                XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
       +}
       +
       +int
       +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad,
       +        const char *text, int invert)
       +{
       +        char buf[256];
       +        int i, tx, ty, th, len, olen;
       +        unsigned int texw, texh;
       +
       +        /* TODO: lpad */
       +
       +        XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
       +        XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
       +
       +        olen = strlen(text);
       +        drw_font_getexts(drw->fonts, text, olen, &texw, &texh);
       +        th = drw->fonts->ascent + drw->fonts->descent;
       +        ty = y + (h / 2) - (th / 2) + drw->fonts->ascent;
       +        tx = x + (h / 2);
       +        /* shorten text if necessary */
       +        for (len = MIN(olen, sizeof buf); len && (texw > w - texh || w < texh); len--)
       +                drw_font_getexts(drw->fonts, text, len, &texw, &texh);
       +        if (!len)
       +                return x;
       +        memcpy(buf, text, len);
       +        if (len < olen)
       +                for (i = len; i && i > len - 3; buf[--i] = '.')
       +                        ;
       +        XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
       +        if (drw->fonts->set)
       +                XmbDrawString(drw->dpy, drw->drawable, drw->fonts->set, drw->gc, tx, ty, buf, len);
       +        else
       +                XDrawString(drw->dpy, drw->drawable, drw->gc, tx, ty, buf, len);
       +
       +        return x + w;
       +}
       +
       +void
       +drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
       +{
       +        XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
       +        XSync(drw->dpy, False);
       +}
       +
       +static unsigned int
       +drw_font_getexts_width(Fnt *font, const char *text, unsigned int len)
       +{
       +        unsigned int w;
       +
       +        drw_font_getexts(font, text, len, &w, NULL);
       +
       +        return w;
       +}
       +
       +unsigned int
       +drw_fontset_getwidth(Drw *drw, const char *text)
       +{
       +        return drw_font_getexts_width(drw->fonts, text, strlen(text));
       +}
       +
       +void
       +drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
       +{
       +        XRectangle r;
       +
       +        if (font->set) {
       +                XmbTextExtents(font->set, text, len, NULL, &r);
       +                if (w)
       +                        *w = r.width;
       +                if (h)
       +                        *h = r.height;
       +        } else {
       +                if (h)
       +                        *h = font->ascent + font->descent;
       +                if (w)
       +                        *w = XTextWidth(font->xfont, text, len);
       +        }
       +}
       +
       +Cur *
       +drw_cur_create(Drw *drw, int shape)
       +{
       +        Cur *cur;
       +
       +        cur = ecalloc(1, sizeof(Cur));
       +        cur->cursor = XCreateFontCursor(drw->dpy, shape);
       +
       +        return cur;
       +}
       +
       +void
       +drw_cur_free(Drw *drw, Cur *cursor)
       +{
       +        XFreeCursor(drw->dpy, cursor->cursor);
       +        free(cursor);
       +}
 (DIR) diff --git a/x11/drw.h b/x11/drw.h
       @@ -0,0 +1,58 @@
       +/* See LICENSE file for copyright and license details. */
       +
       +typedef struct {
       +        Cursor cursor;
       +} Cur;
       +
       +typedef struct {
       +        Display *dpy;
       +        int ascent;
       +        int descent;
       +        unsigned int h;
       +        XFontSet set;
       +        XFontStruct *xfont;
       +} Fnt;
       +
       +enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */
       +typedef XColor Clr;
       +
       +typedef struct {
       +        unsigned int w, h;
       +        Display *dpy;
       +        int screen;
       +        Window root;
       +        Drawable drawable;
       +        GC gc;
       +        Clr *scheme;
       +        Fnt *fonts;
       +} Drw;
       +
       +/* Drawable abstraction */
       +Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h);
       +void drw_resize(Drw *drw, unsigned int w, unsigned int h);
       +void drw_free(Drw *drw);
       +
       +/* Fnt abstraction */
       +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);
       +
       +/* Colorscheme abstraction */
       +void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
       +Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
       +
       +/* Cursor abstraction */
       +Cur *drw_cur_create(Drw *drw, int shape);
       +void drw_cur_free(Drw *drw, Cur *cursor);
       +
       +/* Drawing context manipulation */
       +void drw_setfontset(Drw *drw, Fnt *set);
       +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);
       +
       +/* Map functions */
       +void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);