/* Utility Functions
*****************************************************************************/
-static void die(char* errstr) {
+static void die(char* errstr)
+{
fprintf(stderr, "error: %s\n", errstr);
exit(1);
}
-static Atom atom(XConf* x, char* s) {
+static Atom atom(XConf* x, char* s)
+{
return XInternAtom(x->display, s, False);
}
-static void* xfree(void* p) {
- if (p) XFree(p);
+static void* xfree(void* p)
+{
+ if (p)
+ {
+ XFree(p);
+ }
return NULL;
}
-static int get_prop(XConf* x, Window w, Atom name, Atom* type, int* format, void** data, size_t* ndata) {
+static int get_prop(XConf* x, Window w, Atom name, Atom* type, int* format, void** data, size_t* ndata)
+{
unsigned long nleft;
return XGetWindowProperty(
x->display, w, name, 0, -1, False, AnyPropertyType, type, format, ndata, &nleft, (unsigned char**)data);
/* List Handling
*****************************************************************************/
-static void list_add(Node** list, Node* parent, Node* node) {
- if (!parent) {
+static void list_add(Node** list, Node* parent, Node* node)
+{
+ if (!parent)
+ {
node->next = *list;
node->prev = NULL;
if (*list) (*list)->prev = node;
*list = node;
- } else {
+ }
+ else
+ {
node->next = parent->next;
node->prev = parent;
parent->next = node;
- if (node->next) node->next->prev = node;
+ if (node->next)
+ {
+ node->next->prev = node;
+ }
}
}
-static void list_del(Node** list, Node* node) {
- if (node->prev) node->prev->next = node->next;
- if (node->next) node->next->prev = node->prev;
+static void list_del(Node** list, Node* node)
+{
+ if (node->prev)
+ {
+ node->prev->next = node->next;
+ }
+ if (node->next)
+ {
+ node->next->prev = node->prev;
+ }
node->next = NULL, node->prev = NULL;
- if (*list == node) *list = node->next;
+ if (*list == node)
+ {
+ *list = node->next;
+ }
}
-static void* list_reduce(Node* list, Reducer rfn, void* accum) {
+static void* list_reduce(Node* list, Reducer rfn, void* accum)
+{
return (list ? list_reduce(list->next, rfn, rfn(list, accum)) : accum);
}
-static size_t list_count(Node* curr) {
+static size_t list_count(Node* curr)
+{
size_t nclients = 0;
for (; curr; curr = curr->next, nclients++);
return nclients;
static void client_reconfig(XConf* xs, Client* c);
static void client_config(XConf* xs, Client* c, int x, int y, int w, int h);
-static void* biggest(Node* node, void* accum) {
+static void* biggest(Node* node, void* accum)
+{
if (!accum || TCLIENT(node)->h > ((Client*)accum)->h)
+ {
accum = TCLIENT(node);
+ }
return accum;
}
-static void* find_win(Node* n, void* env) {
+static void* find_win(Node* n, void* env)
+{
struct { Window w; Client* c; }* state = env;
if ((MCLIENT(n)->frame == state->w) || (MCLIENT(n)->win == state->w))
+ {
state->c = MCLIENT(n);
+ }
return env;
}
-static void* grow_client(Node* node, void* env) {
+static void* grow_client(Node* node, void* env)
+{
GrowState* state = env;
Client* curr = TCLIENT(node);
state->nclients--;
curr->y = state->nexty;
if (curr == state->c)
+ {
curr->h = state->sh - state->nexty - (state->nclients * BARHEIGHT(&X));
+ }
else
+ {
curr->h = BARHEIGHT(&X);
+ }
client_reconfig(&X, curr);
state->nexty += curr->h;
return state;
}
-static int client_flags(Client* c, int mask) {
+static int client_flags(Client* c, int mask)
+{
return (c->flags & mask);
}
-static void client_raise(XConf* x, Client* c) {
+static void client_raise(XConf* x, Client* c)
+{
XMapWindow(x->display, c->frame);
XMapWindow(x->display, c->win);
- if (!client_flags(c, FLOATING)) {
+ if (!client_flags(c, FLOATING))
+ {
XLowerWindow(x->display, c->frame);
XLowerWindow(x->display, c->win);
- } else {
+ }
+ else
+ {
XRaiseWindow(x->display, c->frame);
XRaiseWindow(x->display, c->win);
}
XSync(x->display, False);
}
-static void client_add(Client* c, int dtop) {
+static void client_add(Client* c, int dtop)
+{
list_add(&All_Clients, NULL, &(c->mnode));
- if (!client_flags(c, FLOATING)) {
+ if (!client_flags(c, FLOATING))
+ {
Client* parent = list_reduce(Desktops[dtop].tiled, biggest, NULL);
list_add(&Desktops[dtop].tiled, (parent ? &(parent->tnode) : NULL), &(c->tnode));
- if (parent) {
+ if (parent)
+ {
c->h = (parent->h - (parent->h / 2));
parent->h /= 2;
c->y = parent->y + parent->h;
client_config(&X, parent, parent->x, parent->y, parent->w, parent->h);
}
- } else {
+ }
+ else
+ {
list_add(&Desktops[dtop].floated, NULL, &(c->tnode));
}
}
-static void client_del(Client* c) {
+static void client_del(Client* c)
+{
list_del(&All_Clients, &(c->mnode));
- if (!client_flags(c, FLOATING)) {
+ if (!client_flags(c, FLOATING))
+ {
list_del(&Tiled_Clients, &(c->tnode));
int y = c->y, h = c->h;
Node* nsucc = (c->tnode.prev ? c->tnode.prev : c->tnode.next);
- if (nsucc) {
+ if (nsucc)
+ {
Client* succ = TCLIENT(nsucc);
succ->h += h;
if (nsucc == c->tnode.next)
client_config(&X, succ, succ->x, succ->y, succ->w, succ->h);
client_raise(&X, succ);
}
- } else {
+ }
+ else
+ {
list_del(&Floated_Clients, &(c->tnode));
}
}
-static void client_redraw(XConf* x, Client* c) {
+static void client_redraw(XConf* x, Client* c)
+{
XftColor fgclr, bgclr;
if (!c->name) return;
xftcolor(x, &fgclr, -1);
XftColorFree(x->display, x->visual, x->colormap, &bgclr);
}
-static void client_reconfig(XConf* xs, Client* c) {
+static void client_reconfig(XConf* xs, Client* c)
+{
int height = BARHEIGHT(xs);
XMoveResizeWindow(xs->display, c->frame, c->x, c->y, c->w - 2, height);
- if (c->h <= height) {
+ if (c->h <= height)
+ {
XUnmapWindow(xs->display, c->win);
c->flags |= TOO_SMALL;
- } else {
+ }
+ else
+ {
XMoveResizeWindow(xs->display, c->win, c->x, c->y + height, c->w - 2, c->h - height - 2);
- if (client_flags(c, TOO_SMALL)) {
+ if (client_flags(c, TOO_SMALL))
+ {
c->flags &= ~TOO_SMALL;
XMapWindow(xs->display, c->win);
}
XSync(xs->display, False);
}
-static void client_config(XConf* xs, Client* c, int x, int y, int w, int h) {
+static void client_config(XConf* xs, Client* c, int x, int y, int w, int h)
+{
c->x = x, c->y = y, c->w = w, c->h = h;
client_reconfig(xs, c);
client_redraw(xs, c);
}
-static void client_initprops(XConf* x, Client* c) {
+static void client_initprops(XConf* x, Client* c)
+{
int nprops = 0;
Atom* props = XListProperties(x->display, c->win, &nprops);
Atom type;
int format;
void* data = 0;
size_t ndata;
- for (int i = 0; i < nprops; i++) {
- if (props[i] == XA_NET_WM_WINDOW_TYPE) {
+ for (int i = 0; i < nprops; i++)
+ {
+ if (props[i] == XA_NET_WM_WINDOW_TYPE)
+ {
if (Success == get_prop(x, c->win, props[i], &type, &format, &data, &ndata))
+ {
if (((Atom*)data)[0] == XA_NET_WM_WINDOW_TYPE_DIALOG)
+ {
c->flags |= FLOATING;
- } else if (props[i] == XA_WM_PROTOCOLS) {
+ }
+ }
+ }
+ else if (props[i] == XA_WM_PROTOCOLS)
+ {
/* register desire for WM_DELETE message here */
}
data = xfree(data);
}
}
-static void client_create(XConf* x, Window win) {
+static void client_create(XConf* x, Window win)
+{
Client* c = calloc(1, sizeof(Client));
c->win = win;
XGrabServer(x->display);
client_initprops(x, c);
/* create the frame window */
- if (client_flags(c, FLOATING)) {
+ if (client_flags(c, FLOATING))
+ {
XWindowAttributes attr;
XGetWindowAttributes(x->display, c->win, &attr);
c->x = attr.x, c->y = attr.y;
c->w = attr.width;
c->h = attr.height;
- } else {
+ }
+ else
+ {
c->x = 0, c->y = 0;
c->w = WidthOfScreen(DefaultScreenOfDisplay(x->display));
c->h = HeightOfScreen(DefaultScreenOfDisplay(x->display));
XUngrabServer(x->display);
}
-static void client_destroy(XConf* x, Client* c) {
+static void client_destroy(XConf* x, Client* c)
+{
client_del(c);
XGrabServer(x->display);
XftDrawDestroy(c->xft);
XUngrabServer(x->display);
}
-static Client* client_find(Window win) {
+static Client* client_find(Window win)
+{
struct { Window w; Client* c; } state = { .w = win };
list_reduce(All_Clients, find_win, &state);
return state.c;
}
-static void client_resize(XConf* x, Client* c, int dir) {
+static void client_resize(XConf* x, Client* c, int dir)
+{
(void)x, (void)c, (void)dir;
if (!c->tnode.prev) return;
Client* prev = TCLIENT(c->tnode.prev);
client_reconfig(x, c);
}
-static void client_grow(XConf* x, Client* c) {
+static void client_grow(XConf* x, Client* c)
+{
GrowState state = {
.c = c,
.nclients = list_count(Tiled_Clients),
list_reduce(Tiled_Clients, grow_client, &state);
}
-static void client_maximize(XConf* xs, Client* c) {
+static void client_maximize(XConf* xs, Client* c)
+{
int y = c->y, h = c->h;
c->y = 0, c->h = HeightOfScreen(DefaultScreenOfDisplay(xs->display));
client_reconfig(xs, c);
/* Desktop Management
*****************************************************************************/
-static void* hide_wins(Node* node, void* data) {
+static void* hide_wins(Node* node, void* data)
+{
Client* c = TCLIENT(node);
XUnmapWindow(X.display, c->frame);
XUnmapWindow(X.display, c->win);
return data;
}
-static void* show_wins(Node* node, void* data) {
+static void* show_wins(Node* node, void* data)
+{
Client* c = TCLIENT(node);
XMapWindow(X.display, c->frame);
XMapWindow(X.display, c->win);
return data;
}
-static void change_desktop(const Arg arg) {
+static void change_desktop(const Arg arg)
+{
XGrabServer(X.display);
list_reduce(Tiled_Clients, hide_wins, NULL);
list_reduce(Floated_Clients, hide_wins, NULL);
XSync(X.display, False);
}
-static void client_to_desktop(const Arg arg) {
+static void client_to_desktop(const Arg arg)
+{
int bar;
Window foo, win;
- do{
+ do
+ {
(void)XQueryPointer(X.display, DefaultRootWindow(X.display),
&foo, &win, &bar, &bar, &bar, &bar, (unsigned int*)&bar);
- } while (win <= 0);
+ }
+ while (win <= 0);
Client* c = client_find(win);
if (!c) return;
client_del(c);
* Shift+B2: Move one column to the right
*/
-static void xbtnpress(XConf* x, XEvent* e) {
+static void xbtnpress(XConf* x, XEvent* e)
+{
Client* c = client_find(e->xbutton.window);
if (!c || c->frame != e->xbutton.window || client_flags(c, FLOATING))
return;
- if (Button1 == e->xbutton.button) {
+ if (Button1 == e->xbutton.button)
+ {
XDefineCursor(X.display, e->xbutton.window, Move_Cursor);
StartY = e->xbutton.y;
- } else if (Button2 == e->xbutton.button) {
+ }
+ else if (Button2 == e->xbutton.button)
+ {
if (e->xbutton.state & (1 << (Button1 + 7)))
XDestroyWindow(x->display, e->xbutton.window);
else
client_grow(x, c);
- } else if (Button3 == e->xbutton.button) {
+ }
+ else if (Button3 == e->xbutton.button)
+ {
client_maximize(x, c);
}
XSync(X.display, False);
}
-static void xbtnrelease(XConf* x, XEvent* e) {
+static void xbtnrelease(XConf* x, XEvent* e)
+{
Client* c = client_find(e->xbutton.window);
if (!c || c->frame != e->xbutton.window || client_flags(c, FLOATING))
return;
- if (Button1 == e->xbutton.button) {
+ if (Button1 == e->xbutton.button)
+ {
XUndefineCursor(X.display, e->xbutton.window);
client_resize(x, c, e->xbutton.y - StartY);
}
XSync(X.display, False);
}
-static void xconfigrequest(XConf* x, XEvent* e) {
+static void xconfigrequest(XConf* x, XEvent* e)
+{
/*
Check if it's a window we care about. If it is, and it's floating, just
grant the request. Otherwise, deny it as we have it tiled already. All
XConfigureWindow(x->display, e->xconfigurerequest.window, e->xconfigurerequest.value_mask, &wc);
}
-static void xmaprequest(XConf* x, XEvent* e) {
+static void xmaprequest(XConf* x, XEvent* e)
+{
static XWindowAttributes attr = {0};
- if (XGetWindowAttributes(x->display, e->xmaprequest.window, &attr)) {
+ if (XGetWindowAttributes(x->display, e->xmaprequest.window, &attr))
+ {
if (attr.override_redirect) return; /* ignore certain windows (like frames) */
if (!client_find(e->xmaprequest.window))
client_create(x, e->xmaprequest.window);
}
}
-static void xunmapnotify(XConf* x, XEvent* e) {
+static void xunmapnotify(XConf* x, XEvent* e)
+{
}
-static void xdestroynotify(XConf* x, XEvent* e) {
+static void xdestroynotify(XConf* x, XEvent* e)
+{
/* This is where we cleanup windows we care about. destroy them and their frames. */
Client* c = client_find(e->xdestroywindow.window);
if (c) client_destroy(x, c);
}
-static void xclientmsg(XConf* x, XEvent* e) {
+static void xclientmsg(XConf* x, XEvent* e)
+{
}
-static void xpropnotify(XConf* x, XEvent* e) {
+static void xpropnotify(XConf* x, XEvent* e)
+{
/*
We only care about updating the window titles here for now
*/
}
}
-static void xenternotify(XConf* x, XEvent* e) {
+static void xenternotify(XConf* x, XEvent* e)
+{
/*
Handle focus follows mouse here.
*/
}
-static void xexpose(XConf* x, XEvent* e) {
+static void xexpose(XConf* x, XEvent* e)
+{
Client* c = client_find(e->xexpose.window);
if (c && e->xexpose.count == 0)
client_redraw(x, c);
}
#include <X11/XKBlib.h>
-static void xkeypress(XConf* x, XEvent* e) {
+static void xkeypress(XConf* x, XEvent* e)
+{
KeySym keysym = XkbKeycodeToKeysym(
x->display, e->xkey.keycode, 0, 0);
for (size_t i = 0; i < nelem(keys); i++)
#pragma GCC diagnostic pop
-int main(void) {
+int main(void)
+{
/* initialize basic x11 handling */
x11_init(&X);
X.font = x11_font_load(&X, Fonts[0]);
char* ARGV0;
Atom XA_REGISTRAR, XA_OPEN, XA_DONE;
-int spawn(char* cmd) {
+int spawn(char* cmd)
+{
int pid = fork();
if (pid == 0)
+ {
exit(execvp(cmd, (char*[]){cmd, 0}));
+ }
return pid;
}
-Window start_registrar(XConf* x) {
+Window start_registrar(XConf* x)
+{
/* launch registrar if it isn't yet running */
- if (None == XGetSelectionOwner(x->display, XA_REGISTRAR)) {
+ if (None == XGetSelectionOwner(x->display, XA_REGISTRAR))
+ {
if (spawn("registrar") > 0)
+ {
sleep(1);
+ }
}
return XGetSelectionOwner(x->display, XA_REGISTRAR);
}
-void prop_set(XConf* x, Window win, char* prop, char* value) {
+void prop_set(XConf* x, Window win, char* prop, char* value)
+{
Atom xa_prop = XInternAtom(x->display, prop, False);
XChangeProperty(
x->display, win, xa_prop, XA_STRING, 8, PropModeReplace,
(const unsigned char *)value, strlen(value)+1);
}
-void edit_file(XConf* x, Window registrar, char* path, char* addr, int force) {
+void edit_file(XConf* x, Window registrar, char* path, char* addr, int force)
+{
char host[8192];
char* rpath = realpath(path, NULL);
prop_set(x, x->self, "FILE", (rpath ? rpath : path));
prop_set(x, x->self, "ADDR", addr);
if (!gethostname(host, sizeof(host)))
+ {
prop_set(x, x->self, "HOST", host);
+ }
free(rpath);
XChangeProperty(
x->display, registrar, XA_OPEN, XA_WINDOW, 32, PropModeAppend,
(const unsigned char *)&(x->self), 1);
EditCmd[2] = addr, EditCmd[3] = path;
- if (force) {
+ if (force)
+ {
if (!fork())
exit(execvp(EditCmd[0], EditCmd));
- } else {
+ }
+ else
+ {
/* wait for the "done" message */
- for (XEvent e;;) {
+ for (XEvent e;;)
+ {
XNextEvent(x->display, &e);
- if (e.type == ClientMessage) {
- if (e.xclient.message_type == XA_DONE) {
+ if (e.type == ClientMessage)
+ {
+ if (e.xclient.message_type == XA_DONE)
+ {
break;
- } else if (e.xclient.message_type == XA_OPEN) {
+ }
+ else if (e.xclient.message_type == XA_OPEN)
+ {
if (!fork())
+ {
exit(execvp(EditCmd[0], EditCmd));
+ }
break;
}
}
}
}
-int main(int argc, char** argv) {
+int main(int argc, char** argv)
+{
int force = 0;
OPTBEGIN { case 'f': force = 1; break; } OPTEND;
- if (argc == 0) {
+ if (argc == 0)
+ {
spawn("tide");
- } else {
+ }
+ else
+ {
XConf x = {0};
x11_init(&x);
x11_mkwin(&x, 1, 1, 0);
XA_OPEN = XInternAtom(x.display, "OPEN", 0);
XA_DONE = XInternAtom(x.display, "DONE", 0);
Window registrar = start_registrar(&x);
- if (registrar == None) {
+ if (registrar == None)
+ {
fprintf(stderr, "Failed to contact registrar.\n");
return 1;
}
/* Loop over files and send an OPEN message for each one. */
- for (int i = 0; i < argc; i++) {
+ for (int i = 0; i < argc; i++)
+ {
char* addr = strrchr(argv[i], ':');
- if (addr) *addr = '\0', addr++;
+ if (addr)
+ {
+ *addr = '\0', addr++;
+ }
edit_file(&x, registrar, argv[i], (addr ? addr : "0"), force);
}
XSync(x.display, False);
/******************************************************************************/
-char* getvar(char* val) {
+char* getvar(char* val)
+{
val = getenv(val);
return (val ? val : "");
}
-char* eval(char* str) {
+char* eval(char* str)
+{
static bool inited = false;
static char* patt = "\\$([a-zA-Z0-9_]+)";
static regex_t regex;
- if (!inited && (regcomp(®ex, patt, REG_EXTENDED) < 0)) {
+ if (!inited && (regcomp(®ex, patt, REG_EXTENDED) < 0))
+ {
perror("regcomp() :");
exit(1);
}
regmatch_t matches[2] = {{0},{0}};
- if (regexec(®ex, str, nelem(matches), matches, 0) < 0) {
+ if (regexec(®ex, str, nelem(matches), matches, 0) < 0)
+ {
return str;
- } else if (matches[1].rm_so > 0) {
+ }
+ else if (matches[1].rm_so > 0)
+ {
char* var = strndup(str+matches[1].rm_so, matches[1].rm_eo-matches[1].rm_so);
char* val = getvar(var);
size_t sz = strlen(str) + strlen(val);
/******************************************************************************/
-bool complete(void) {
+bool complete(void)
+{
exit(0);
return false;
}
-bool matches(char* var, char* patt) {
+bool matches(char* var, char* patt)
+{
regex_t regex = {0};
regmatch_t matches[10] = {{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}};
- if (regcomp(®ex, patt, REG_EXTENDED) == 0) {
+ if (regcomp(®ex, patt, REG_EXTENDED) == 0)
+ {
var = getvar(var);
int err = regexec(®ex, var, nelem(matches), matches, 0);
- for (int i = 0; i < 10 && matches[i].rm_so >= 0; i++) {
+ for (int i = 0; i < 10 && matches[i].rm_so >= 0; i++)
+ {
char* matchval = strndup(var+matches[i].rm_so, matches[i].rm_eo-matches[i].rm_so);
setenv((char[]){ 'M', ('0' + i), 0 }, matchval, 1);
free(matchval);
return false;
}
-bool var_is(char* var, char* val) {
+bool var_is(char* var, char* val)
+{
return (strcmp(getvar(var), eval(val)) == 0);
}
-bool var_isset(char* var) {
+bool var_isset(char* var)
+{
return (getenv(var) != NULL);
}
-bool var_isdir(char* var) {
+bool var_isdir(char* var)
+{
struct stat st = {0};
char* path = eval(var);
- if ((stat(path, &st) < 0) && (errno == ENOENT)) {
+ if ((stat(path, &st) < 0) && (errno == ENOENT))
+ {
return false;
- } else if (S_ISDIR(st.st_mode)) {
+ }
+ else if (S_ISDIR(st.st_mode))
+ {
setenv("dir", var, 1);
return true;
- } else {
+ }
+ else
+ {
return false;
}
}
-bool var_isfile(char* var) {
+bool var_isfile(char* var)
+{
struct stat st = {0};
char* path = eval(var);
- if ((stat(eval(var), &st) < 0) && (errno == ENOENT)) {
+ if ((stat(eval(var), &st) < 0) && (errno == ENOENT))
+ {
return false;
- } else if (!S_ISDIR(st.st_mode)) {
+ }
+ else if (!S_ISDIR(st.st_mode))
+ {
setenv("file", path, 1);
return true;
- } else {
+ }
+ else
+ {
return false;
}
}
-bool var_set(char* var, char* val) {
+bool var_set(char* var, char* val)
+{
return (setenv(var, eval(val), 1) == 0);
}
-bool var_unset(char* var) {
+bool var_unset(char* var)
+{
return (unsetenv(var) == 0);
}
-bool find_file(char* file) {
+bool find_file(char* file)
+{
(void)file;
return false;
}
-void runcmd(char* cmd) {
+void runcmd(char* cmd)
+{
char* shellcmd[] = { getvar("SHELL"), "-c", cmd, NULL };
if (!shellcmd[0]) shellcmd[0] = "/bin/sh";
_exit(execvp(shellcmd[0], shellcmd));
}
-bool exec(char* cmd) {
+bool exec(char* cmd)
+{
int pid, status;
- if ((pid = fork()) < 0) return false;
- if (pid == 0) {
+ if ((pid = fork()) < 0)
+ {
+ return false;
+ }
+ if (pid == 0)
+ {
runcmd(cmd);
- } else {
+ }
+ else
+ {
waitpid(pid, &status, 0);
return (status == 0);
}
return false;
}
-bool launch(char* cmd) {
+bool launch(char* cmd)
+{
int pid = fork();
if (pid > 0)
+ {
return true;
+ }
else if (pid == 0)
+ {
runcmd(cmd);
+ }
return false;
}
-bool apply_rule(Rule* rule) {
- switch (rule->type) {
+bool apply_rule(Rule* rule)
+{
+ switch (rule->type)
+ {
case COMPLETE: exit(0);
case MATCHES: return matches(rule->arg1, rule->arg2);
case IS: return var_is(rule->arg1, rule->arg2);
/******************************************************************************/
-void usage(char* pname) {
+void usage(char* pname)
+{
fprintf(stderr, "Usage: %s [ITEM]\n", pname);
exit(1);
}
-char* type2str(int type) {
- switch (type) {
+char* type2str(int type)
+{
+ switch (type)
+ {
case COMPLETE: return "COMPLETE";
case MATCHES: return "MATCHES";
case IS: return "IS";
return "UNKNOWN";
}
-int main(int argc, char** argv) {
+int main(int argc, char** argv)
+{
int debug = 0;
OPTBEGIN { case 'd': debug = 1; } OPTEND;
if (debug)
printf("Data: '%s'\n", *argv);
- for (unsigned int i = 0; i < nelem(BuiltinRules); i++) {
+ for (unsigned int i = 0; i < nelem(BuiltinRules); i++)
+ {
Rule* rule = BuiltinRules[i];
if (debug)
printf("\nRuleset %d:\n", i);
- for (; rule->type != COMPLETE; rule++) {
+ for (; rule->type != COMPLETE; rule++)
+ {
if (debug)
printf(" %s '%s' '%s'\n", type2str(rule->type), rule->arg1, rule->arg2);
- if (!apply_rule(rule)) {
+ if (!apply_rule(rule))
+ {
if (debug)
printf(" FAIL\n");
break;
{ .name = "CLIPBOARD" },
};
-static struct XSel* selfetch(Atom atom) {
+static struct XSel* selfetch(Atom atom)
+{
for (unsigned int i = 0; i < (sizeof(Selections) / sizeof(Selections[0])); i++)
+ {
if (atom == Selections[i].atom)
+ {
return &Selections[i];
+ }
+ }
return NULL;
}
-static void xselclear(XConf* x, XEvent* e) {
+static void xselclear(XConf* x, XEvent* e)
+{
(void)x;
struct XSel* sel = selfetch(e->xselectionclear.selection);
if (!sel) return;
sel->text = NULL;
}
-static void xselnotify(XConf* x, XEvent* e) {
+static void xselnotify(XConf* x, XEvent* e)
+{
/* bail if the selection cannot be converted */
if (e->xselection.property == None)
return;
unsigned char* propdata = NULL;
XGetWindowProperty(x->display, x->self, sel->atom, 0, -1, False, AnyPropertyType, &rtype,
(int*)&format, &nitems, &nleft, &propdata);
- if (e->xselection.target == SelTarget) {
+ if (e->xselection.target == SelTarget)
+ {
void(*cbfn)(char*) = sel->callback;
sel->callback = NULL;
cbfn((char*)propdata);
if (propdata) XFree(propdata);
}
-static void xselrequest(XConf* x, XEvent* e) {
+static void xselrequest(XConf* x, XEvent* e)
+{
XEvent s;
struct XSel* sel = selfetch( e->xselectionrequest.selection );
s.xselection.type = SelectionNotify;
Atom target = e->xselectionrequest.target;
Atom xatargets = XInternAtom(x->display, "TARGETS", 0);
Atom xastring = XInternAtom(x->display, "STRING", 0);
- if (target == xatargets) {
+ if (target == xatargets)
+ {
/* respond with the supported type */
XChangeProperty(
x->display,
s.xselection.property,
XA_ATOM, 32, PropModeReplace,
(unsigned char*)&SelTarget, 1);
- } else if (target == SelTarget || target == xastring) {
+ }
+ else if (target == SelTarget || target == xastring)
+ {
XChangeProperty(
x->display,
s.xselection.requestor,
XSendEvent(x->display, s.xselection.requestor, True, 0, &s);
}
-void x11_sel_init(XConf* x) {
+void x11_sel_init(XConf* x)
+{
/* initialize selection atoms */
for (unsigned int i = 0; i < (sizeof(Selections) / sizeof(Selections[0])); i++)
+ {
Selections[i].atom = XInternAtom(x->display, Selections[i].name, 0);
+ }
SelTarget = XInternAtom(x->display, "UTF8_STRING", 0);
if (SelTarget == None)
+ {
SelTarget = XInternAtom(x->display, "STRING", 0);
+ }
/* setup event handlers */
x->eventfns[SelectionClear] = xselclear;
x->eventfns[SelectionNotify] = xselnotify;
x->eventfns[SelectionRequest] = xselrequest;
}
-int x11_sel_get(XConf* x, int selid, void(*cbfn)(char*)) {
+int x11_sel_get(XConf* x, int selid, void(*cbfn)(char*))
+{
struct XSel* sel = &(Selections[selid]);
if (sel->callback) return 0;
Window owner = XGetSelectionOwner(x->display, sel->atom);
- if (owner == x->self) {
+ if (owner == x->self)
+ {
cbfn(sel->text);
- } else if (owner != None){
+ }
+ else if (owner != None)
+ {
sel->callback = cbfn;
XConvertSelection(x->display, sel->atom, SelTarget, sel->atom, x->self, CurrentTime);
}
return 1;
}
-int x11_sel_set(XConf* x, int selid, char* str) {
+int x11_sel_set(XConf* x, int selid, char* str)
+{
struct XSel* sel = &(Selections[selid]);
- if (!sel || !str || !*str) {
+ if (!sel || !str || !*str)
+ {
free(str);
return 0;
- } else {
+ }
+ else
+ {
sel->text = str;
XSetSelectionOwner(x->display, sel->atom, x->self, CurrentTime);
return 1;
}
}
-void x11_sel_quit(XConf* x, XEvent* e) {
+void x11_sel_quit(XConf* x, XEvent* e)
+{
xselclear(x, e);
if (!Selections[PRIMARY].text && !Selections[CLIPBOARD].text)
+ {
x->running = False;
+ }
}
-int x11_sel_ready(XConf* x) {
+int x11_sel_ready(XConf* x)
+{
(void)x;
return (Selections[PRIMARY].text || Selections[CLIPBOARD].text);
}
size_t ChoiceIdx = 0;
size_t Offset = 0;
-static int peekc(FILE* in) {
+static int peekc(FILE* in)
+{
int c = fgetc(in);
ungetc(c, in);
return c;
}
-static char* rdline(FILE* fin, size_t* len) {
+static char* rdline(FILE* fin, size_t* len)
+{
if (feof(fin) || ferror(fin))
return NULL;
size_t size = 256;
size_t index = 0;
char* str = (char*)calloc(size,1);
- while (!feof(stdin)) {
- if (index+2 >= size) {
+ while (!feof(stdin))
+ {
+ if (index+2 >= size)
+ {
size = size << 1;
str = realloc(str, size);
}
return str;
}
-static int by_score(const void* a, const void* b) {
+static int by_score(const void* a, const void* b)
+{
Choice* ca = ((Choice*)a);
Choice* cb = ((Choice*)b);
if (ca->score < cb->score)
return strcmp(ca->string, cb->string);
}
-static void load_choices(XConf* x) {
+static void load_choices(XConf* x)
+{
size_t choice_len;
char* choice_text;
bool shown = false;
Choice choice = {0};
vec_init(&Choices, sizeof(Choice));
- while ((choice_text = rdline(stdin, &choice_len)) != NULL) {
- if (choice_len > 0) {
+ while ((choice_text = rdline(stdin, &choice_len)) != NULL)
+ {
+ if (choice_len > 0)
+ {
choice.string = choice_text;
choice.length = strlen(choice_text);
choice.score = 1.0;
- if (!shown && peekc(stdin) != EOF) {
+ if (!shown && peekc(stdin) != EOF)
+ {
x11_show(x);
redraw(x);
shown = true;
}
vec_push_back(&Choices, &choice);
- } else {
+ }
+ else
+ {
free(choice_text);
}
}
}
-static char* find_char(char* str, int ch) {
+static char* find_char(char* str, int ch)
+{
for (; *str; str++)
if (tolower(*str) == tolower(ch))
return str;
return NULL;
}
-static inline bool find_match(char *string, char* query, size_t offset, char **start, char **end) {
+static inline bool find_match(char *string, char* query, size_t offset, char **start, char **end)
+{
char *s, *e;
/* find first match char or bail */
s = e = find_char(&string[offset], *query);
return true;
}
-static bool match(char *string, size_t offset, size_t *start, size_t *end) {
+static bool match(char *string, size_t offset, size_t *start, size_t *end)
+{
char *s1 = 0, *e1 = 0, *s2, *e2;
/* first check if we match at all */
if (!find_match(string, Query, offset, &s1, &e1))
return true;
}
-static void score(void) {
+static void score(void)
+{
unsigned int nchoices = vec_size(&Choices);
for (unsigned int i = 0; i < nchoices; i++) {
Choice* choice = (Choice*)vec_at(&Choices, i);
float qlen = (float)QueryIdx;
- if (match(choice->string, 0, &choice->match_start, &choice->match_end)) {
+ if (match(choice->string, 0, &choice->match_start, &choice->match_end))
+ {
float clen = (float)(choice->match_end - choice->match_start) + 1;
choice->score = qlen / clen / (float)(choice->length);
- } else {
+ }
+ else
+ {
choice->match_start = 0;
choice->match_end = 0;
choice->score = 0.0f;
vec_sort(&Choices, by_score);
}
-int main(int argc, char** argv) {
+int main(int argc, char** argv)
+{
XConf x = {0};
if (argc >= 2) {
size_t sz = min(strlen(argv[1]), sizeof(Query)-1);
return 0;
}
-static void xkeypress(XConf* x, XEvent* e) {
+static void xkeypress(XConf* x, XEvent* e)
+{
char buf[8];
KeySym key;
Status status;
Xutf8LookupString(x->xic, &(e->xkey), buf, sizeof(buf), &key, &status);
else
XLookupString(&(e->xkey), buf, sizeof(buf), &key, 0);
- if (key == XK_Return) {
+ if (key == XK_Return)
+ {
x->running = false;
- } else if (key == XK_Escape) {
+ }
+ else if (key == XK_Escape)
+ {
x->running = false;
ChoiceIdx = SIZE_MAX;
- } else if (key == XK_Up) {
+ }
+ else if (key == XK_Up)
+ {
if (ChoiceIdx > 0)
ChoiceIdx--;
if (ChoiceIdx < Offset)
Offset--;
- } else if (key == XK_Down) {
+ }
+ else if (key == XK_Down)
+ {
size_t nlines = ((x->height - x->font->height - 4) / x->font->height) - 1;
size_t maxidx = Offset + nlines;
if (ChoiceIdx+1 < vec_size(&Choices))
ChoiceIdx++;
if (ChoiceIdx > maxidx)
Offset++;
- } else if (key == XK_BackSpace) {
+ }
+ else if (key == XK_BackSpace)
+ {
if (QueryIdx > 0)
Query[--QueryIdx] = '\0';
score();
- } else if (key >= 0x20 && key <= 0x7F) {
+ }
+ else if (key >= 0x20 && key <= 0x7F)
+ {
if (QueryIdx < sizeof(Query)-1)
Query[QueryIdx++] = key;
Offset = ChoiceIdx = 0;
}
}
-static void xbtnpress(XConf* x, XEvent* e) {
+static void xbtnpress(XConf* x, XEvent* e)
+{
(void)x;
- if (e->xbutton.button == Button1) {
+ if (e->xbutton.button == Button1)
+ {
int starty = x->font->height + 4;
e->xbutton.y = (e->xbutton.y < starty ? starty : e->xbutton.y - starty);
ChoiceIdx = Offset + (e->xbutton.y / x->font->height);
if (ChoiceIdx >= vec_size(&Choices))
ChoiceIdx = vec_size(&Choices)-1;
- } else if (e->xbutton.button == Button2) {
+ }
+ else if (e->xbutton.button == Button2)
+ {
x->running = false;
- } else if (e->xbutton.button == Button3) {
+ }
+ else if (e->xbutton.button == Button3)
+ {
x->running = false;
ChoiceIdx = SIZE_MAX;
- } else if (e->xbutton.button == Button4) {
+ }
+ else if (e->xbutton.button == Button4)
+ {
if (Offset > 0) Offset--;
- } else if (e->xbutton.button == Button5) {
+ }
+ else if (e->xbutton.button == Button5)
+ {
if (Offset < vec_size(&Choices)) Offset++;
}
}
-static void redraw(XConf* x) {
+static void redraw(XConf* x)
+{
/* draw the background colors and border */
size_t fheight = x->font->height;
size_t nlines = ((x->height - x->font->height - 4) / x->font->height) - 1;
x11_draw_string(x, x->font, offset + 2, fheight, Palette[TagsFg], Query);
/* draw the scored and sorted results */
- if (vec_size(&Choices)) {
- for (int i = Offset, y = 2 * fheight + 4; ((size_t)i < vec_size(&Choices)) && ((size_t)i <= Offset+nlines); i++, y += fheight) {
+ if (vec_size(&Choices))
+ {
+ for (int i = Offset, y = 2 * fheight + 4; ((size_t)i < vec_size(&Choices)) && ((size_t)i <= Offset+nlines); i++, y += fheight)
+ {
if ((size_t)i == ChoiceIdx)
x11_draw_rect(x, Palette[EditSel], ScrollWidth+3, y - x->font->ascent, x->width, fheight);
x11_draw_string(x, x->font, ScrollWidth+3, y, Palette[TagsFg], ((Choice*)vec_at(&Choices, i))->string);
}
- } else {
+ }
+ else
+ {
x11_draw_string(x, x->font, ScrollWidth+3, 2 * fheight + 4, Palette[TagsFg], "Loading...");
}
x11_flip(x);
}
-static void xinit(XConf* x) {
+static void xinit(XConf* x)
+{
x11_init(x);
x11_mkdialog(x, 640, 480, 0
| StructureNotifyMask
);
x11_init_gc(x);
x11_centerwin(x);
- if (!(x->font = x11_font_load(x, Fonts[0]))) {
+ if (!(x->font = x11_font_load(x, Fonts[0])))
+ {
perror("unable to load base font");
exit(EXIT_FAILURE);
}
Atom XA_REGISTRAR, XA_ADD, XA_DEL, XA_OPEN, XA_DONE, XA_TIDE;
TWindow* Windows = NULL;
-void* readprop(XConf* x, Window win, char* prop, Atom type, size_t* length) {
+void* readprop(XConf* x, Window win, char* prop, Atom type, size_t* length)
+{
Atom rtype, xa_prop = XInternAtom(x->display, prop, False);
int format;
unsigned long datalen, nleft;
x->display, win, xa_prop, 0, -1, False, type,
&rtype, &format, &datalen, &nleft, &data);
if (length) *length = datalen;
- if (rtype != type) {
+ if (rtype != type)
+ {
if (data) XFree(data);
data = 0;
if (length) *length = 0;
return (void*)data;
}
-char* read_path(XConf* x, Window id) {
+char* read_path(XConf* x, Window id)
+{
int nprops;
char* path = NULL;
Atom xa_file = XInternAtom(x->display, "FILE", False);
Atom* props = XListProperties(x->display, id, &nprops);
if (!props) return NULL;
- for (int i = 0; i < nprops; i++) {
- if (props[i] == xa_file) {
+ for (int i = 0; i < nprops; i++)
+ {
+ if (props[i] == xa_file)
+ {
path = readprop(x, id, "FILE", XA_STRING, 0);
break;
}
return path;
}
-void win_add(XConf* x, Window id) {
+void win_add(XConf* x, Window id)
+{
char* path = read_path(x, id);
if (!path) return;
printf("ADD 0x%x: '%s'\n", (unsigned int)id, path);
Windows = win;
}
-void win_del(Window id) {
+void win_del(Window id)
+{
if (!Windows) return;
- if (Windows->win == id) {
+ if (Windows->win == id)
+ {
TWindow* deadite = Windows;
Windows = deadite->next;
free(deadite);
- } else {
+ }
+ else
+ {
TWindow* w = Windows;
for (;w && w->next && (w->next->win != id); w = w->next);
- if (w && w->next) {
+ if (w && w->next)
+ {
TWindow* deadite = w->next;
w->next = deadite->next;
free(deadite->path), deadite->path = NULL;
}
}
-void win_send(XConf* x, Window from, Window to, int mask, char* atom, size_t val) {
+void win_send(XConf* x, Window from, Window to, int mask, char* atom, size_t val)
+{
XEvent ev = {0};
ev.xclient.type = ClientMessage;
ev.xclient.send_event = True;
XSendEvent(x->display, to, False, mask, &ev);
}
-void win_open(XConf* x, Window winid, char* path, char* addr, char* host) {
+void win_open(XConf* x, Window winid, char* path, char* addr, char* host)
+{
if (!path) return;
/* search for an existing window */
- for (TWindow* win = Windows; win; win = win->next) {
+ for (TWindow* win = Windows; win; win = win->next)
+ {
/* refresh the filepath and crudely determine if window still valid */
free(win->path);
win->path = NULL;
win->path = (file ? file : NULL);
if (win->host && !strcmp(win->host, host) &&
- win->path && !strcmp(win->path, path)) {
+ win->path && !strcmp(win->path, path))
+ {
/* double check that the window id didnt get reassigned to a non-tide window */
printf("found open window: 0x%x '%s'\n", (unsigned int)win->win, win->path);
x11_error_clear();
char* type = readprop(x, win->win, "TIDE", XA_STRING, 0);
- if (!type || x11_error_get()) {
+ if (!type || x11_error_get())
+ {
puts("window invalid, marking for cleanup");
free(win->path), win->path = NULL;
free(win->host), win->host = NULL;
free(type);
break;
- } else {
+ }
+ else
+ {
puts("window still valid, raising");
XEvent ev = {0};
ev.xclient.type = ClientMessage;
win_send(x, x->self, winid, 0, "OPEN", 0);
}
-void selclear(XConf* x, XEvent* e) {
+void selclear(XConf* x, XEvent* e)
+{
(void)e;
XSync(x->display, False);
puts("quitting");
exit(0);
}
-void clientmsg(XConf* x, XEvent* e) {
+void clientmsg(XConf* x, XEvent* e)
+{
if (XA_REGISTRAR != e->xclient.message_type)
return;
if (XA_ADD == (Atom)(e->xclient.data.l[0]))
XSync(x->display, False);
}
-TWindow* win_sweep(TWindow* win) {
- if (win) {
- if (win->path) {
+TWindow* win_sweep(TWindow* win)
+{
+ if (win)
+ {
+ if (win->path)
+ {
win->next = win_sweep(win->next);
- } else {
+ }
+ else
+ {
TWindow* dead = win;
printf("swept: %x\n", (unsigned)win->win);
win = win_sweep(win->next);
return win;
}
-void propnotify(XConf* x, XEvent* e) {
+void propnotify(XConf* x, XEvent* e)
+{
(void)e;
Atom type;
int format;
x->display, x->self, XA_OPEN, 0, -1, True, XA_WINDOW,
&type, &format, &datalen, &nleft, &data);
/* handle all of the window requests */
- for (Window* win = (Window*)data; datalen && win && *win; win++, datalen--) {
+ for (Window* win = (Window*)data; datalen && win && *win; win++, datalen--)
+ {
char* file = readprop(x, *win, "FILE", XA_STRING, NULL);
char* addr = readprop(x, *win, "ADDR", XA_STRING, NULL);
char* host = readprop(x, *win, "HOST", XA_STRING, NULL);
Windows = win_sweep(Windows);
}
-void find_windows(XConf* x) {
+void find_windows(XConf* x)
+{
XGrabServer(x->display);
size_t nwindows = 0;
Window* windows = readprop(x, x->root, "_NET_CLIENT_LIST", XA_WINDOW, &nwindows);
puts("done finding windows");
}
-int daemonize(void) {
+int daemonize(void)
+{
int status;
/* fork into the background first */
if ((status = fork()) < 0)
return 0;
}
-int main(int argc, char** argv) {
+int main(int argc, char** argv)
+{
OPTBEGIN {
case 'F': Foreground = 1; break;
} OPTEND;
x.eventfns[ClientMessage] = clientmsg;
x.eventfns[PropertyNotify] = propnotify;
puts("inited");
- if (None == XGetSelectionOwner(x.display, XA_REGISTRAR)) {
+ if (None == XGetSelectionOwner(x.display, XA_REGISTRAR))
+ {
XSetSelectionOwner(x.display, XA_REGISTRAR, x.self, CurrentTime);
puts("made owner");
- if (x.self == XGetSelectionOwner(x.display, XA_REGISTRAR)) {
+ if (x.self == XGetSelectionOwner(x.display, XA_REGISTRAR))
+ {
puts("finding windows");
find_windows(&x);
puts("event loop");
x11_event_loop(&x, 0);
puts("done");
- } else {
+ }
+ else
+ {
puts("fail");
}
}
#include <qcheck.h>
#include "config.h"
-int main(int argc, char** argv) {
+int main(int argc, char** argv)
+{
qcinit(argc >= 2 ? strtol(argv[1], 0, 0) : 0);
atf_init(argc, argv);
RUN_EXTERN_TEST_SUITE(BufferTests);