commit aa5f91e0d54333e4da247528f5eacb721710d16d
parent 77aac73c1e88d840dc9a8b07f2c02b5cb8553835
Author: Enno Boland (tox) <tox@s01.de>
Date: Mon, 7 Sep 2009 13:32:58 +0200
adding sourcecode.
Diffstat:
tabbed.c | | | 317 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 317 insertions(+), 0 deletions(-)
diff --git a/tabbed.c b/tabbed.c
@@ -0,0 +1,317 @@
+/* See LICENSE file for copyright and license details.
+ *
+ * To understand tabbed, start reading main().
+ */
+#include <locale.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xproto.h>
+#include <X11/extensions/XTest.h>
+
+/* macros */
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define LENGTH(x) (sizeof x / sizeof x[0])
+#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask))
+
+enum { ColFG, ColBG, ColLast }; /* color */
+
+typedef union {
+ int i;
+ unsigned int ui;
+ float f;
+ const void *v;
+} Arg;
+
+typedef struct {
+ unsigned int mod;
+ KeySym keysym;
+ void (*func)(const Arg *);
+ const Arg arg;
+} Key;
+
+typedef struct {
+ int x, y, w, h;
+ unsigned long norm[ColLast];
+ unsigned long sel[ColLast];
+ Drawable drawable;
+ GC gc;
+ struct {
+ int ascent;
+ int descent;
+ int height;
+ XFontSet set;
+ XFontStruct *xfont;
+ } font;
+} DC; /* draw context */
+
+typedef struct Client Client;
+struct Client {
+ char name[256];
+ struct Client *next;
+ Window win;
+};
+
+/* function declarations */
+static void cleanup(void);
+static void configurenotify(XEvent *e);
+static void unmapnotify(XEvent *e);
+static void die(const char *errstr, ...);
+static void expose(XEvent *e);
+static unsigned long getcolor(const char *colstr);
+static void initfont(const char *fontstr);
+static void keypress(XEvent *e);
+static void move(const Arg *arg);
+static void newtab(const Arg *arg);
+static void rotate(const Arg *arg);
+static void run(void);
+static void setup(void);
+static int textnw(const char *text, unsigned int len);
+static void updatenumlockmask(void);
+
+/* variables */
+static int screen;
+static int wx, wy, ww, wh;
+static void (*handler[LASTEvent]) (XEvent *) = {
+ [ConfigureNotify] = configurenotify,
+ [UnmapNotify] = unmapnotify,
+ [KeyPress] = keypress,
+ [Expose] = expose,
+};
+static Display *dpy;
+static DC dc;
+static Window root, win;
+static Bool running = True;
+static unsigned int numlockmask = 0;
+/* configuration, allows nested code to access above variables */
+#define TABBED
+#include "config.h"
+
+void
+buttonrelease(XEvent *e) {
+ //XButtonPressedEvent *ev = &e->xbutton;
+}
+
+void
+cleanup(void) {
+ if(dc.font.set)
+ XFreeFontSet(dpy, dc.font.set);
+ else
+ XFreeFont(dpy, dc.font.xfont);
+ XFreePixmap(dpy, dc.drawable);
+ XFreeGC(dpy, dc.gc);
+ XDestroyWindow(dpy, win);
+ XSync(dpy, False);
+ XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
+}
+
+void
+configurenotify(XEvent *e) {
+ XConfigureEvent *ev = &e->xconfigure;
+
+ if(ev->window == win && (ev->width != ww || ev->height != wh)) {
+ ww = ev->width;
+ wh = ev->height;
+ XFreePixmap(dpy, dc.drawable);
+ dc.drawable = XCreatePixmap(dpy, root, ww, wh, DefaultDepth(dpy, screen));
+ }
+}
+
+void
+die(const char *errstr, ...) {
+ va_list ap;
+
+ va_start(ap, errstr);
+ vfprintf(stderr, errstr, ap);
+ va_end(ap);
+ exit(EXIT_FAILURE);
+}
+
+void
+unmapnotify(XEvent *e) {
+ running = False;
+}
+
+void
+expose(XEvent *e) {
+ /*XExposeEvent *ev = &e->xexpose;*/
+}
+
+unsigned long
+getcolor(const char *colstr) {
+ Colormap cmap = DefaultColormap(dpy, screen);
+ XColor color;
+
+ if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
+ die("error, cannot allocate color '%s'\n", colstr);
+ return color.pixel;
+}
+
+void
+initfont(const char *fontstr) {
+ char *def, **missing;
+ int i, n;
+
+ missing = NULL;
+ if(dc.font.set)
+ XFreeFontSet(dpy, dc.font.set);
+ dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
+ if(missing) {
+ while(n--)
+ fprintf(stderr, "tabbed: missing fontset: %s\n", missing[n]);
+ XFreeStringList(missing);
+ }
+ if(dc.font.set) {
+ XFontSetExtents *font_extents;
+ XFontStruct **xfonts;
+ char **font_names;
+ dc.font.ascent = dc.font.descent = 0;
+ font_extents = XExtentsOfFontSet(dc.font.set);
+ n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
+ for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
+ dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent);
+ dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent);
+ xfonts++;
+ }
+ }
+ else {
+ if(dc.font.xfont)
+ XFreeFont(dpy, dc.font.xfont);
+ dc.font.xfont = NULL;
+ if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
+ && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
+ die("error, cannot load font: '%s'\n", fontstr);
+ dc.font.ascent = dc.font.xfont->ascent;
+ dc.font.descent = dc.font.xfont->descent;
+ }
+ dc.font.height = dc.font.ascent + dc.font.descent;
+}
+
+void
+keypress(XEvent *e) {
+ unsigned int i;
+ KeySym keysym;
+ XKeyEvent *ev;
+
+ ev = &e->xkey;
+ keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
+ for(i = 0; i < LENGTH(keys); i++)
+ if(keysym == keys[i].keysym
+ && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
+ && keys[i].func)
+ keys[i].func(&(keys[i].arg));
+}
+
+void
+move(const Arg *arg) {
+
+}
+
+void
+newtab(const Arg *arg) {
+
+}
+
+void
+rotate(const Arg *arg) {
+
+}
+
+void
+run(void) {
+ XEvent ev;
+
+ /* main event loop, also reads status text from stdin */
+ XSync(dpy, False);
+ while(running) {
+ XNextEvent(dpy, &ev);
+ if(handler[ev.type])
+ (handler[ev.type])(&ev); /* call handler */
+ }
+}
+
+void
+setup(void) {
+ XWMHints *wmh;
+
+ /* init screen */
+ screen = DefaultScreen(dpy);
+ root = RootWindow(dpy, screen);
+ initfont(font);
+
+ /* init appearance */
+ wx = 0;
+ wy = 0;
+ ww = 800;
+ wh = 600;
+ dc.norm[ColBG] = getcolor(normbgcolor);
+ dc.norm[ColFG] = getcolor(normfgcolor);
+ dc.sel[ColBG] = getcolor(selbgcolor);
+ dc.sel[ColFG] = getcolor(selfgcolor);
+ dc.drawable = XCreatePixmap(dpy, root, ww, wh, DefaultDepth(dpy, screen));
+ dc.gc = XCreateGC(dpy, root, 0, 0);
+ if(!dc.font.set)
+ XSetFont(dpy, dc.gc, dc.font.xfont->fid);
+
+ win = XCreateSimpleWindow(dpy, root, wx, wy, ww, wh, 0, dc.norm[ColFG], dc.norm[ColBG]);
+ XSelectInput(dpy, win, StructureNotifyMask|PointerMotionMask|
+ ButtonReleaseMask|ButtonPressMask|ExposureMask|
+ LeaveWindowMask);
+ wmh = XAllocWMHints();
+ wmh->input = False;
+ wmh->flags = InputHint;
+ XSetWMHints(dpy, win, wmh);
+ XFree(wmh);
+ XMapRaised(dpy, win);
+}
+
+int
+textnw(const char *text, unsigned int len) {
+ XRectangle r;
+
+ if(dc.font.set) {
+ XmbTextExtents(dc.font.set, text, len, NULL, &r);
+ return r.width;
+ }
+ return XTextWidth(dc.font.xfont, text, len);
+}
+
+void
+updatenumlockmask(void) {
+ unsigned int i, j;
+ XModifierKeymap *modmap;
+
+ numlockmask = 0;
+ modmap = XGetModifierMapping(dpy);
+ for(i = 0; i < 8; i++)
+ for(j = 0; j < modmap->max_keypermod; j++)
+ if(modmap->modifiermap[i * modmap->max_keypermod + j]
+ == XKeysymToKeycode(dpy, XK_Num_Lock))
+ numlockmask = (1 << i);
+ XFreeModifiermap(modmap);
+}
+
+int
+main(int argc, char *argv[]) {
+ if(argc == 2 && !strcmp("-v", argv[1]))
+ die("tabbed-"VERSION", © 2006-2008 surf engineers, see LICENSE for details\n");
+ else if(argc != 1)
+ die("usage: tabbed [surf-options]\n");
+ if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
+ fprintf(stderr, "warning: no locale support\n");
+ if(!(dpy = XOpenDisplay(0)))
+ die("tabbed: cannot open display\n");
+ setup();
+ run();
+ /*dummys*/
+ cleanup();
+ XCloseDisplay(dpy);
+ return 0;
+ textnw(surfexec[0], strlen(surfexec[0]));
+ updatenumlockmask();
+}