Smol Libs is:
A series of small C libraries contained within source code of 80x25 characters.
Currently this restriction of 80x25 characters in the source is somewhat loosely followed.
Whilst these projects are not fully baked yet, I think it is about time to share some progress on these libraries.
Xgui is a small lightweight wrapper around Xlib that creates windows. Currently the supported features are:
xbm
format (a custom Xlib image format).And that’s pretty much it. It was created after I had some real trouble getting existing lightweight GUI libraries to compile, when I really just wanted something incredibly basic.
To do this, we use the following source:
0001 #pragma once /* xgui - A light wrapper around Xlib that offers */ 0002 #include <X11/Xlib.h> /* text, buttons and images. */ 0003 #include <string.h> /* Written by B[], 2022 */ 0004 enum type{ TXT, BTN, IMG }; char* xf = "-*-helvetica-*-r-*-*-16-*-*-*-*-*-*-*"; 0005 typedef struct{ int i, a, b; enum type t; float x, y, w, h; char* v; Pixmap d; } xobj; 0006 typedef struct{ Display* d; int s, n; Window w; GC g; long b, f; xobj* o[65536]; } xgui; 0007 void xgui_init(xgui* x, int w, int h, long b, long f){ x->b = b; x->f = f; 0008 x->d = XOpenDisplay(NULL); x->s = DefaultScreen(x->d); x->n = 0; x->g = DefaultGC(x->d, x->s); 0009 x->w = XCreateSimpleWindow(x->d, RootWindow(x->d, x->s), 0, 0, w, h, 1, x->f, x->b); 0010 XSelectInput(x->d, x->w, ExposureMask|KeyPressMask|ButtonPressMask); XMapWindow(x->d, x->w); } 0011 void xgui_add(xgui* x, xobj* o){ if(x->n + 1 < 65536) x->o[x->n++] = o; } 0012 void xgui_update(xgui* x, void (*c)(XEvent, xobj*, char, float, float, int, int)){ 0013 XEvent e; XNextEvent(x->d, &e); XWindowAttributes a; XGetWindowAttributes(x->d, x->w, &a); 0014 float w = a.width, h = a.height; int l, eks, ekc, i = -1; xobj o; 0015 XFontStruct* f = XLoadQueryFont(x->d, xf); XSetFont(x->d, x->g, f->fid); 0016 while(++i < x->n){ o = *(x->o[i]); eks = e.xkey.state; ekc = e.xkey.keycode; if(o.t != IMG){ 0017 XSetForeground(x->d, x->g, o.t == BTN ? x->f : x->b); eks &= ShiftMask; l = strlen(o.v); 0018 XFillRectangle(x->d, x->w, x->g, w * (o.x - o.w/2), h * (o.y - o.h/2), w*o.w, h*o.h); 0019 XSetForeground(x->d, x->g, o.t == BTN ? x->b : x->f); XDrawString(x->d, 0020 x->w, x->g, (w * o.x) - (XTextWidth(f, o.v, l)/2), h*o.y, o.v, l); 0021 }else if(e.type == Expose) XCopyPlane(x->d, o.d, x->w, x->g, 0, 0, o.a, o.b, o.x*w, o.y*h, 1); 0022 (*c)(e, x->o[i], XKeycodeToKeysym(x->d, ekc, eks ? 1 : 0), e.xbutton.x/w, e.xbutton.y/h, w, h); 0023 }} void xgui_close(xgui* x){ XDestroyWindow(x->d, x->w); XCloseDisplay(x->d); } 0024 int xgui_image(xgui* x, char* f, Pixmap* p, int* a, int* b){ int i, j; return 0025 XReadBitmapFile(x->d, x->w, f, a, b, p, &i, &j); } char* XGUI = "1.1.0";
Generally you would setup an xgui
object with xgui_init()
, add elements using xgui_add()
and process updates using xgui_update()
. You would need to look at the example programs for more detail, or read the source (it’s very small by design).
It still needs some work, but as you can see, it’s certainly compact! Note the version string XGUI
is currently 1.1.0 as of the time of writing.
The following are examples written in Xgui to demonstrate some of the cape abilities it has.
In this example we have a simple integer calculator. Values can be entered by either typing or clicking on the buttons.
As you resize the window, it resizes the elements automatically and client side code attempts to find a better font size depending on the window size. The corner background images remain in the corner, with the penguin disappearing for very small windows.
xgui_calc
weighs in at 19kB (not including image assets).
In this example I attempted to write a basic screensaver based on Langton’s Ant. Pressing any key quits the screensaver.
Again as you resize the window, it resizes the elements. It makes use of the libraries ability to change the type of an element during runtime, in this case switching between buttons and text.
xgui_calc
weighs in at 19kB.
There isn’t much room to extend this library further, but this is also a good thing. It’s pretty much complete minus some formatting, bug fixes and some tweaks here and there.
For example programs, I really want to build an ultra-lightweight file manager. It turns out to be quite a large undertaking due to file browsers being so complicated, but the one feature I desperately want is history and for tabs to come back after closing the program. I also want to be able to display large numbers of files and not have to wait several minutes for Gnome to figure out what thumbnails it should have, whilst throwing icons all over the place.
There are of course other Smol Lib projects already existing that will be introduced in good time.