wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

commit 460620d711951e644ed451a03258641119fe2593
parent 06f4d727e656f5037bd647425788b495e417c578
Author: Anselm R. Garbe <garbeam@wmii.de>
Date:   Sun, 29 Jan 2006 22:11:14 +0200

removed old wmiibar, now wmiibar2 is wmiibar


Diffstat:
cmd/Makefile | 12+-----------
cmd/wmiibar.c | 1340++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
cmd/wmiibar2.c | 1084-------------------------------------------------------------------------------
3 files changed, 926 insertions(+), 1510 deletions(-)

diff --git a/cmd/Makefile b/cmd/Makefile @@ -12,9 +12,6 @@ LDFLAGS2 += ${LIBS} -L../liblitz -llitz -L../libixp2 -lixp \ SRC_bar = wmiibar.c OBJ_bar = ${SRC_bar:.c=.o} -SRC_bar2 = wmiibar2.c -OBJ_bar2 = ${SRC_bar2:.c=.o} - SRC_menu = wmiimenu.c OBJ_menu = ${SRC_menu:.c=.o} @@ -45,14 +42,7 @@ all: wmiibar wmiibar2 wmiimenu wmiir wmiir2 wmiifs wmiikeys wmiiplumb wmiiwarp wmiibar: ${OBJ_bar} @echo LD $@ - @${CC} -o $@ ${OBJ_bar} ${LDFLAGS} -# Solaris -# @${CC} -o $@ ${OBJ_bar} ${LDFLAGS} -lsocket - - -wmiibar2: ${OBJ_bar2} - @echo LD $@ - @${CC} -o $@ ${OBJ_bar2} ${LDFLAGS2} + @${CC} -o $@ ${OBJ_bar} ${LDFLAGS2} # Solaris # @${CC} -o $@ ${OBJ_bar2} ${LDFLAGS2} -lsocket diff --git a/cmd/wmiibar.c b/cmd/wmiibar.c @@ -9,69 +9,84 @@ #include <string.h> #include <sys/stat.h> #include <sys/wait.h> -#include <X11/Xlib.h> +#include <sys/types.h> +#include <time.h> +#include <unistd.h> #include <X11/Xatom.h> #include <X11/cursorfont.h> #include <X11/Xproto.h> #include <X11/Xutil.h> +#include <sys/socket.h> -#include "wmii.h" - -/* array indexes for file pointers */ -typedef enum { - B_CTL, - B_NEW, - B_EXPANDABLE, - B_GEOMETRY, - B_FONT, - B_FG_COLOR, - B_BORDER_COLOR, - B_BG_COLOR, - B_EVENT_RESIZE, - B_LAST -} BarIndexes; - -typedef struct Item Item; -struct Item { - File *root; - Draw d; - Item *next; +#include "../libixp2/ixp.h" +#include "blitz.h" + +/* + * filesystem specification + * / Droot + * /display Fdisplay 'north', 'south', 'none' + * /font Ffont <xlib font name> + * /event Fevent + * /expand Fexpand id of expandable label + * /ctl Fctl command interface + * /new Dnew returns content of new item + * /default/ Ditem + * /default/color Fcolor <#RRGGBB> <#RRGGBB> <#RRGGBB> + * /1/ Ditem + * /1/data Fdata <arbitrary data which gets displayed> + * /1/color Fcolor <#RRGGBB> <#RRGGBB> <#RRGGBB> + */ + +/* 8-bit qid.path.type */ +enum { + Droot, + Ditem, + Fctl, + Fdisplay, + Ffont, + Fexpand, + Fevent, + Fdata, /* data to display */ + Fcolor }; -static unsigned int id = 1; -static IXPServer *ixps = 0; +typedef struct { + char data[256]; + char color[24]; + unsigned long fg; + unsigned long bg; + unsigned long border; + XRectangle rect; +} Item; + +static char E9pversion[] = "9P version not supported"; +static char Enoperm[] = "permission denied"; +static char Enofid[] = "fid not assigned"; +static char Enofile[] = "file not found"; +static char Enomode[] = "mode not supported"; +static char Enofunc[] = "function not supported"; + +static unsigned char *msg[IXP_MAX_MSG]; +char *errstr = 0; +static size_t nitem = 0; +static size_t itemsz = 0; +static size_t iexpand = 0; +static Item **item = 0; +static char *address = nil; +static pid_t mypid = 0; +static IXPServer srv = { 0 }; +static Qid root_qid; static Display *dpy; +static int screen_num; +static char *font = nil; +static Align align = CENTER; +static XFontStruct *xfont; static GC gc; static Window win; -static XRectangle rect; -static XRectangle brect; -static int screen_num; -static Bool displayed = False; -static char *sockfile = nil; -static File *file[B_LAST]; -static Item *items = nil; -static size_t nitems = 0; +static XRectangle brect, rect; static Pixmap pmap; -static XFontStruct *font; -static Align align = SOUTH; - -static Draw zero_draw = { 0 }; - -static void draw_bar(void *obj, char *arg); -static void quit(void *obj, char *arg); -static void display(void *obj, char *arg); -static void reset(void *obj, char *arg); -static void xdestroy(void *obj, char *arg); -static void handle_after_write(IXPServer * s, File * f); - -static Action acttbl[] = { - {"quit", quit}, - {"display", display}, - {"update", draw_bar}, - {"reset", reset}, - {"destroy", xdestroy}, - {0, 0} -}; + +static void do_pend_fcall(char *event); static char *version[] = { "wmiibar - window manager improved bar - " VERSION "\n" @@ -81,399 +96,883 @@ static char *version[] = { static void usage() { - fprintf(stderr, "%s", - "usage: wmiibar -s <socket file> [-v]\n" - " -s socket file\n" " -v version info\n"); + fprintf(stderr, "%s %d", + "usage: wmiibar -a <server address> [-v]\n" + " -a server address \n" + " -v version info\n", 0); exit(1); } -/** - * <path>/data "<txt value>" - * <path>/fgcolor "#RRGGBBAA" - * <path>/bgcolor "#RRGGBBAA" - * <path>/bordercolor "#RRGGBBAA" - * <path>/b1press "<command>" - * <path>/b2press "<command>" - * <path>/b3press "<command>" - * <path>/b4press "<command>" - * <path>/b5press "<command>" - */ -static void -create_label(char *path) +static int +dummy_error_handler(Display * dpy, XErrorEvent * err) { - File *f; - char buf[MAX_BUF]; - int i; + return 0; +} - snprintf(buf, MAX_BUF, "%s/data", path); - f = ixp_create(ixps, buf); - f->after_write = handle_after_write; - snprintf(buf, MAX_BUF, "%s/fgcolor", path); - wmii_create_ixpfile(ixps, buf, file[B_FG_COLOR]->content); - snprintf(buf, MAX_BUF, "%s/bgcolor", path); - wmii_create_ixpfile(ixps, buf, file[B_BG_COLOR]->content); - snprintf(buf, MAX_BUF, "%s/bordercolor", path); - wmii_create_ixpfile(ixps, buf, file[B_BORDER_COLOR]->content); - for(i = 1; i < 6; i++) { /* 5 buttons events */ - snprintf(buf, MAX_BUF, "%s/b%dpress", path, i); - ixp_create(ixps, buf); - } +static void +new_item() +{ + Item *it = cext_emallocz(sizeof(Item)); + if(nitem > 0) { + cext_strlcpy(it->color, item[0]->color, sizeof(it->color)); + it->fg = item[0]->fg; + it->bg = item[0]->bg; + it->border = item[0]->border; + } + item = (Item **)cext_array_attach((void **)item, it, sizeof(Item *), &itemsz); + nitem++; } static void -xdestroy(void *obj, char *arg) +detach_item(Item *it) { - char buf[512]; - if(!arg) - return; - snprintf(buf, sizeof(buf), "/%s", arg); - ixps->remove(ixps, buf); - draw_bar(0, 0); + cext_array_detach((void **)item, it, &itemsz); + nitem--; } static void -reset(void *obj, char *arg) +draw() { - int i; - char buf[512]; - for(i = 1; i <= id; i++) { - snprintf(buf, sizeof(buf), "/%d", i); - ixps->remove(ixps, buf); - } - id = 1; - draw_bar(0, 0); + size_t i; + unsigned int w = 0; + Draw d = { 0 }; + + d.gc = gc; + d.drawable = pmap; + d.rect = brect; + d.rect.y = 0; + d.font = xfont; + + if(nitem == 1) { /* /default only */ + d.fg = item[0]->fg; + d.bg = item[0]->bg; + d.border = item[0]->border; + blitz_drawlabel(dpy, &d); + } + else { + if(!iexpand) + iexpand = nitem - 1; + for(i = 1; i < nitem; i++) { + Item *it = item[i]; + it->rect.x = it->rect.y = 0; + it->rect.width = it->rect.height = brect.height; + if(i == iexpand) + continue; + if(strlen(it->data)) { + if(!strncmp(it->data, "%m:", 3)) + it->rect.width = brect.height / 2; + else + it->rect.width += XTextWidth(xfont, it->data, strlen(it->data)); + } + w += it->rect.width; + } + if(w >= brect.width) { + /* failsafe mode, give all labels same width */ + w = brect.width / nitem; + for(i = 1; i < nitem; i++) + item[i]->rect.width = w; + i--; + item[i]->rect.width = brect.width - ((i - 1) * w); + } else + item[iexpand]->rect.width = brect.width - w; + for(i = 1; i < nitem; i++) { + d.fg = item[i]->fg; + d.bg = item[i]->bg; + d.border = item[i]->border; + if(i > 1) + item[i]->rect.x = item[i - 1]->rect.x + item[i - 1]->rect.width; + d.rect = item[i]->rect; + d.data = item[i]->data; + if(d.data && !strncmp(d.data, "%m:", 3)) + blitz_drawmeter(dpy, &d); + else + blitz_drawlabel(dpy, &d); + } + } + XCopyArea(dpy, pmap, win, gc, 0, 0, brect.width, brect.height, 0, 0); + XSync(dpy, False); } static void -quit(void *obj, char *arg) +update_color(Item *it) { - ixps->runlevel = SHUTDOWN; + it->fg = blitz_loadcolor(dpy, screen_num, &it->color[0]); + it->bg = blitz_loadcolor(dpy, screen_num, &it->color[8]); + it->border = blitz_loadcolor(dpy, screen_num, &it->color[16]); } static void -display(void *obj, char *arg) -{ - if(!arg) - return; - displayed = blitz_strtonum(arg, 0, 1); - if(displayed) { - XMapRaised(dpy, win); - draw_bar(0, 0); - } else { - XUnmapWindow(dpy, win); - XSync(dpy, False); - } +update_geometry() +{ + char buf[64]; + brect = rect; + brect.height = xfont->ascent + xfont->descent + 4; + if(align == SOUTH) + brect.y = rect.height - brect.height; + XMoveResizeWindow(dpy, win, brect.x, brect.y, brect.width, brect.height); + XSync(dpy, False); + XFreePixmap(dpy, pmap); + pmap = XCreatePixmap(dpy, win, brect.width, brect.height, + DefaultDepth(dpy, screen_num)); + XSync(dpy, False); + snprintf(buf, sizeof(buf), "NewGeometry %d %d %d %d\n", brect.x, brect.y, brect.width, brect.height); + do_pend_fcall(buf); + draw(); } static void -init_draw_label(char *path, Draw * d) -{ - char buf[MAX_BUF]; - File *f; - - /* text stuff */ - snprintf(buf, MAX_BUF, "%s/data", path); - f = ixp_walk(ixps, buf); - d->data = f->content; - /* style stuff */ - snprintf(buf, MAX_BUF, "%s/fgcolor", path); - f = ixp_walk(ixps, buf); - d->fg = blitz_loadcolor(dpy, screen_num, f->content); - snprintf(buf, MAX_BUF, "%s/bgcolor", path); - f = ixp_walk(ixps, buf); - d->bg = blitz_loadcolor(dpy, screen_num, f->content); - snprintf(buf, MAX_BUF, "%s/bordercolor", path); - f = ixp_walk(ixps, buf); - d->border = blitz_loadcolor(dpy, screen_num, f->content); +handle_buttonpress(XButtonPressedEvent * e) +{ + size_t i; + char buf[32]; + for(i = 0; i < nitem; i++) + if(blitz_ispointinrect(e->x, e->y, &item[i]->rect)) { + snprintf(buf, sizeof(buf), "Button%dPress %d\n", e->button, i); + do_pend_fcall(buf); + } } static void -init_item(char *path, Item * i) +check_x_event(IXPServer *s, IXPConn *c) +{ + XEvent e; + + while(XPending(dpy)) { + XNextEvent(dpy, &e); + switch (e.type) { + case ButtonPress: + handle_buttonpress(&e.xbutton); + break; + case Expose: + if(e.xexpose.count == 0) + draw(); + break; + default: + break; + } + } +} + + +/* IXP stuff */ + +static unsigned long long +mkqpath(unsigned char type, unsigned short item) { - i->d = zero_draw; - i->root = ixp_walk(ixps, path); - i->d.gc = gc; - i->d.drawable = pmap; - i->d.rect = brect; - i->d.rect.y = 0; - init_draw_label(path, &i->d); + return ((unsigned long long) item << 8) | (unsigned long long) type; +} + +static unsigned char +qpath_type(unsigned long long path) +{ + return path & 0xff; +} + +static unsigned short +qpath_item(unsigned long long path) +{ + return (path >> 8) & 0xffff; +} + +static char * +qid_to_name(Qid *qid) +{ + unsigned char type = qpath_type(qid->path); + unsigned short i = qpath_item(qid->path); + static char buf[32]; + + switch(type) { + case Droot: return "/"; break; + case Ditem: + if(!i) + return "default"; + else if(i == nitem) + return "new"; + snprintf(buf, sizeof(buf), "%u", i); + return buf; + break; + case Fctl: return "ctl"; break; + case Fdisplay: return "display"; break; + case Ffont: return "font"; break; + case Fexpand: return "expand"; break; + case Fdata: return "data"; break; + case Fevent: return "event"; break; + case Fcolor: return "color"; break; + default: return nil; break; + } } static int -comp_str(const void *s1, const void *s2) +name_to_type(char *name) { - return strcmp(*(char **) s1, *(char **) s2); + const char *err; + unsigned int i; + if(!name || !name[0] || !strncmp(name, "/", 2) || !strncmp(name, "..", 3)) + return Droot; + if(!strncmp(name, "default", 8) || !strncmp(name, "new", 4)) + return Ditem; + if(!strncmp(name, "ctl", 4)) + return Fctl; + if(!strncmp(name, "display", 8)) + return Fdisplay; + if(!strncmp(name, "font", 5)) + return Ffont; + if(!strncmp(name, "expand", 7)) + return Fexpand; + if(!strncmp(name, "data", 5)) + return Fdata; + if(!strncmp(name, "event", 6)) + return Fevent; + if(!strncmp(name, "color", 6)) + return Fcolor; + i = (unsigned short) cext_strtonum(name, 1, 0xffff, &err); + if(!err && (i <= nitem)) + return Ditem; + return -1; } -static void -draw() +static int +mkqid(Qid *dir, char *wname, Qid *new) { - Item *i; - unsigned int idx = 0, w = 0, xoff = 0; - unsigned expandable = 0; - char buf[32]; - - if(!nitems) - return; - - expandable = blitz_strtonum(file[B_EXPANDABLE]->content, 1, nitems + 1); - snprintf(buf, sizeof(buf), "/%d", expandable); - expandable--; - if(!ixp_walk(ixps, buf)) - expandable = 0; - - /* precalc */ - for(i = items; i; i = i->next) { - if(idx != expandable) { - i->d.rect.width = brect.height; - if(i->d.data) { - if(!strncmp(i->d.data, "%m:", 3)) - /* meter */ - i->d.rect.width = brect.height / 2; - else - i->d.rect.width += - XTextWidth(font, i->d.data, strlen(i->d.data)); - } - w += i->d.rect.width; + const char *err; + int type = name_to_type(wname); + unsigned short i = qpath_item(dir->path); + + if((dir->type != IXP_QTDIR) || (type == -1)) + return -1; + + new->version = 0; + switch(type) { + case Droot: + new->type = IXP_QTDIR; + *new = root_qid; + break; + case Ditem: + new->type = IXP_QTDIR; + if(!strncmp(wname, "default", 8)) + new->path = mkqpath(Ditem, 0); + else if(!strncmp(wname, "new", 4)) + new->path = mkqpath(Ditem, nitem); + else { + unsigned short i = cext_strtonum(wname, 1, 0xffff, &err); + if(err || (i >= nitem)) + return -1; + new->path = mkqpath(Ditem, i); + } + break; + case Fdata: /* note, Fdata needs to be before Fcolor, fallthrough */ + if(!i) + return -1; + case Fcolor: + if(i > nitem) + return -1; + default: + new->type = IXP_QTFILE; + new->path = mkqpath(type, i); + break; + } + return 0; +} + +static int +xversion(IXPConn *c) +{ + if(strncmp(c->fcall->version, IXP_VERSION, strlen(IXP_VERSION))) { + errstr = E9pversion; + return -1; + } else if(c->fcall->maxmsg > IXP_MAX_MSG) + c->fcall->maxmsg = IXP_MAX_MSG; + c->fcall->id = RVERSION; + return 0; +} + +static int +xattach(IXPConn *c) +{ + IXPMap *new = cext_emallocz(sizeof(IXPMap)); + new->qid = root_qid; + new->fid = c->fcall->fid; + c->map = (IXPMap **)cext_array_attach((void **)c->map, new, + sizeof(IXPMap *), &c->mapsz); + c->fcall->id = RATTACH; + c->fcall->qid = root_qid; + return 0; +} + +static int +xwalk(IXPConn *c) +{ + unsigned short nwqid = 0; + Qid dir = root_qid; + IXPMap *m; + + if(!(m = ixp_server_fid2map(c, c->fcall->fid))) { + errstr = Enofid; + return -1; + } + if(c->fcall->fid != c->fcall->newfid + && (ixp_server_fid2map(c, c->fcall->newfid))) { + errstr = Enofid; + return -1; + } + if(c->fcall->nwname) { + dir = m->qid; + for(nwqid = 0; (nwqid < c->fcall->nwname) + && !mkqid(&dir, c->fcall->wname[nwqid], &c->fcall->wqid[nwqid]); nwqid++) + dir = c->fcall->wqid[nwqid]; + if(!nwqid) { + errstr = Enofile; + return -1; } - idx++; } - if(w > brect.width) { - /* failsafe mode, give all labels same width */ - w = brect.width / nitems; - for(i = items; i && i->next; i = i->next) - i->d.rect.width = w; - i->d.rect.width = w; - i->d.rect.width = brect.width - i->d.rect.x; - } else { - idx = 0; - for(i = items; i && idx != expandable; i = i->next) - idx++; - i->d.rect.width = brect.width - w; + /* a fid will only be valid, if the walk was complete */ + if(nwqid == c->fcall->nwname) { + if(c->fcall->fid != c->fcall->newfid) { + m = cext_emallocz(sizeof(IXPMap)); + c->map = (IXPMap **)cext_array_attach((void **)c->map, m, + sizeof(IXPMap *), &c->mapsz); + } + m->qid = dir; + m->fid = c->fcall->newfid; } - for(i = items; i; i = i->next) { - i->d.font = font; - i->d.rect.x = xoff; - xoff += i->d.rect.width; - if(i->d.data && !strncmp(i->d.data, "%m:", 3)) - blitz_drawmeter(dpy, &i->d); - else - blitz_drawlabel(dpy, &i->d); + c->fcall->id = RWALK; + c->fcall->nwqid = nwqid; + return 0; +} + +static int +xopen(IXPConn *c) +{ + IXPMap *m = ixp_server_fid2map(c, c->fcall->fid); + + if(!m) { + errstr = Enofid; + return -1; } - XCopyArea(dpy, pmap, win, gc, 0, 0, brect.width, brect.height, 0, 0); - XSync(dpy, False); + if(!(c->fcall->mode | IXP_OREAD) && !(c->fcall->mode | IXP_OWRITE)) { + errstr = Enomode; + return -1; + } + c->fcall->id = ROPEN; + c->fcall->qid = m->qid; + c->fcall->iounit = c->fcall->maxmsg + - (sizeof(unsigned char) + sizeof(unsigned short) + 2 * sizeof(unsigned int)); + return 0; } -static void -draw_bar(void *obj, char *arg) -{ - File *label = 0; - unsigned int j = 0; - Item *i, *it; - char buf[512]; - - if(!displayed) - return; - while((i = items)) { - items = items->next; - free(i); +static unsigned int +mkstat(Stat *stat, Qid *dir, char *name, unsigned long long length, unsigned int mode) +{ + stat->mode = mode; + stat->atime = stat->mtime = time(0); + cext_strlcpy(stat->uid, getenv("USER"), sizeof(stat->uid)); + cext_strlcpy(stat->gid, getenv("USER"), sizeof(stat->gid)); + cext_strlcpy(stat->muid, getenv("USER"), sizeof(stat->muid)); + + cext_strlcpy(stat->name, name, sizeof(stat->name)); + stat->length = length; + mkqid(dir, name, &stat->qid); + return ixp_sizeof_stat(stat); +} + +static unsigned int +type_to_stat(Stat *stat, char *name, unsigned short i) +{ + int type = name_to_type(name); + Qid dir = {IXP_QTDIR, 0, mkqpath(Ditem, i)}; + char buf[16]; + + switch (type) { + case Droot: + case Ditem: + return mkstat(stat, &root_qid, name, 0, DMDIR | DMREAD | DMEXEC); + break; + case Fctl: + return mkstat(stat, &root_qid, name, 0, DMWRITE); + break; + case Fdisplay: + if(align == SOUTH || align == NORTH) + return mkstat(stat, &root_qid, name, 6, DMREAD | DMWRITE); + else + return mkstat(stat, &root_qid, name, 5, DMREAD | DMWRITE); + break; + case Fevent: + return mkstat(stat, &root_qid, name, 0, DMREAD); + break; + case Ffont: + return mkstat(stat, &root_qid, name, strlen(font), + DMREAD | DMWRITE); + break; + case Fexpand: + snprintf(buf, sizeof(buf), "%u", iexpand); + return mkstat(stat, &root_qid, name, strlen(buf), DMREAD | DMWRITE); + break; + case Fdata: + if(i == nitem) + i = 0; + return mkstat(stat, &dir, name, strlen(item[i]->data), + DMREAD | DMWRITE); + break; + case Fcolor: + if(i == nitem) + i = 0; + return mkstat(stat, &dir, name, strlen(item[i]->color), + DMREAD | DMWRITE); + break; + default: + errstr = "invalid stat"; + break; } - it = items = nil; - snprintf(buf, sizeof(buf), "%s", "/1"); - label = ixp_walk(ixps, buf); - if(!label) { - Draw d = { 0 }; - /* default stuff */ - d.gc = gc; - d.drawable = pmap; - d.rect.width = brect.width; - d.rect.height = brect.height; - d.bg = blitz_loadcolor(dpy, screen_num, file[B_BG_COLOR]->content); - d.fg = blitz_loadcolor(dpy, screen_num, file[B_FG_COLOR]->content); - d.border = - blitz_loadcolor(dpy, screen_num, - file[B_BORDER_COLOR]->content); - blitz_drawlabelnoborder(dpy, &d); - } else { - File *f; - char **paths = 0; - /* - * take order into account, directory names are used in - * alphabetical order - */ - nitems = 0; - for(f = label; f; f = f->next) - nitems++; - paths = cext_emallocz(sizeof(char *) * nitems); - j = 0; - for(f = label; f; f = f->next) - paths[j++] = f->name; - qsort(paths, nitems, sizeof(char *), comp_str); - for(j = 0; j < nitems; j++) { - snprintf(buf, sizeof(buf), "/%s", paths[j]); - i = cext_emallocz(sizeof(Item)); - init_item(buf, i); - if(!it) - it = items = i; - else { - it->next = i; - it = i; - } - } - free(paths); - draw(); + return 0; +} + +static int +xremove(IXPConn *c) +{ + IXPMap *m = ixp_server_fid2map(c, c->fcall->fid); + unsigned short i; + + if(!m) { + errstr = Enofid; + return -1; } + i = qpath_item(m->qid.path); + if((qpath_type(m->qid.path) == Ditem) && i && (i < nitem)) { + Item *it = item[i]; + detach_item(it); + free(it); + c->fcall->id = RREMOVE; + if(iexpand >= nitem) + iexpand = 0; + draw(); + return 0; + } + errstr = Enoperm; + return -1; } -static Item * -item_for_file(File * f) +static int +xread(IXPConn *c) { - Item *i; - for(i = items; i; i = i->next) { - if(f == i->root) - return i; + Stat stat; + IXPMap *m = ixp_server_fid2map(c, c->fcall->fid); + unsigned char *p = c->fcall->data; + unsigned short i; + unsigned int len; + char buf[32]; + + if(!m) { + errstr = Enofid; + return -1; } - return nil; + i = qpath_item(m->qid.path); + + c->fcall->count = 0; + if(c->fcall->offset) { + switch (qpath_type(m->qid.path)) { + case Droot: + /* jump to offset */ + len = type_to_stat(&stat, "ctl", 0); + len += type_to_stat(&stat, "display", 0); + len += type_to_stat(&stat, "font", 0); + len += type_to_stat(&stat, "new", 0); + len += type_to_stat(&stat, "event", 0); + len += type_to_stat(&stat, "default", 0); + for(i = 1; i < nitem; i++) { + snprintf(buf, sizeof(buf), "%u", i); + len += type_to_stat(&stat, buf, i); + if(len < c->fcall->offset) + continue; + else + break; + } + /* offset found, proceeding */ + for(; i < nitem; i++) { + snprintf(buf, sizeof(buf), "%u", i); + len = type_to_stat(&stat, buf, i); + if(c->fcall->count + len >= c->fcall->iounit) + break; + c->fcall->count += len; + p = ixp_enc_stat(p, &stat); + } + break; + case Fevent: + return 1; + break; + default: + break; + } + } + else { + switch (qpath_type(m->qid.path)) { + case Droot: + c->fcall->count = type_to_stat(&stat, "ctl", 0); + p = ixp_enc_stat(p, &stat); + c->fcall->count += type_to_stat(&stat, "display", 0); + p = ixp_enc_stat(p, &stat); + c->fcall->count += type_to_stat(&stat, "font", 0); + p = ixp_enc_stat(p, &stat); + c->fcall->count += type_to_stat(&stat, "new", 0); + p = ixp_enc_stat(p, &stat); + c->fcall->count += type_to_stat(&stat, "event", 0); + p = ixp_enc_stat(p, &stat); + c->fcall->count += type_to_stat(&stat, "default", 0); + p = ixp_enc_stat(p, &stat); + for(i = 1; i < nitem; i++) { + snprintf(buf, sizeof(buf), "%u", i); + len = type_to_stat(&stat, buf, i); + if(c->fcall->count + len >= c->fcall->iounit) + break; + c->fcall->count += len; + p = ixp_enc_stat(p, &stat); + } + break; + case Ditem: + if(i > nitem) + goto error_xread; + if(!i) { + c->fcall->count = type_to_stat(&stat, "color", i); + p = ixp_enc_stat(p, &stat); + break; + } + if(i == nitem) + new_item(); + c->fcall->count = type_to_stat(&stat, "color", i); + p = ixp_enc_stat(p, &stat); + c->fcall->count += type_to_stat(&stat, "data", i); + p = ixp_enc_stat(p, &stat); + break; + case Fctl: + errstr = Enoperm; + return -1; + break; + case Fdisplay: + switch(align) { + case SOUTH: + memcpy(p, "south", 5); + c->fcall->count = 5; + break; + case NORTH: + memcpy(p, "north", 5); + c->fcall->count = 5; + break; + default: + memcpy(p, "none", 4); + c->fcall->count = 4; + break; + } + break; + case Ffont: + if((c->fcall->count = strlen(font))) + memcpy(p, font, c->fcall->count); + break; + case Fexpand: + snprintf(buf, sizeof(buf), "%u", iexpand); + c->fcall->count = strlen(buf); + memcpy(p, buf, c->fcall->count); + break; + case Fevent: + return 1; + break; + case Fdata: + if(i == nitem) + new_item(); + if(i >= nitem) + goto error_xread; + if((c->fcall->count = strlen(item[i]->data))) + memcpy(p, item[i]->data, c->fcall->count); + break; + case Fcolor: + if(i == nitem) + new_item(); + if(i >= nitem) + goto error_xread; + if((c->fcall->count = strlen(item[i]->color))) + memcpy(p, item[i]->color, c->fcall->count); + break; + default: + error_xread: + if(!errstr) + errstr = "invalid read"; + return -1; + break; + } + } + c->fcall->id = RREAD; + return 0; } -static void -handle_buttonpress(XButtonPressedEvent * e) +static int +xstat(IXPConn *c) { - Item *i; - File *p; - char buf[MAX_BUF]; - char path[512]; - for(i = items; i; i = i->next) - if(blitz_ispointinrect(e->x, e->y, &i->d.rect)) { - path[0] = 0; - wmii_get_ixppath(i->root, path, sizeof(path)); - snprintf(buf, MAX_BUF, "%s/b%upress", path, e->button); - if((p = ixp_walk(ixps, buf))) - if(p->content) - wmii_spawn(dpy, p->content); - return; - } + IXPMap *m = ixp_server_fid2map(c, c->fcall->fid); + char *name; + + if(!m) { + errstr = Enofid; + return -1; + } + + name = qid_to_name(&m->qid); + if(!type_to_stat(&c->fcall->stat, name, qpath_item(m->qid.path))) + return -1; + c->fcall->id = RSTAT; + return 0; } -static void -check_event(Connection * e) +static int +xwrite(IXPConn *c) { - XEvent ev; + char buf[256]; + IXPMap *m = ixp_server_fid2map(c, c->fcall->fid); + unsigned short i; - while(XPending(dpy)) { - XNextEvent(dpy, &ev); - switch (ev.type) { - case ButtonPress: - handle_buttonpress(&ev.xbutton); - break; - case Expose: - if(ev.xexpose.count == 0) { - /* XRaiseWindow(dpy, win); */ - draw_bar(0, 0); - } - break; - default: - break; - } + if(!m) { + errstr = Enofid; + return -1; } + + i = qpath_item(m->qid.path); + switch (qpath_type(m->qid.path)) { + case Fctl: + if(c->fcall->count == 5) { + memcpy(buf, c->fcall->data, 4); + buf[4] = 0; + if(!strncmp(buf, "quit", 5)) { + srv.running = 0; + break; + } + } + errstr = "command not supported"; + return -1; + break; + case Fdisplay: + if(c->fcall->count != 6 && c->fcall->count != 5) + goto error_xwrite; + memcpy(buf, c->fcall->data, c->fcall->count); + buf[c->fcall->count] = 0; + if(blitz_strtoalign(&align, buf) == -1) + goto error_xwrite; + update_geometry(); + if(align == NORTH || align == SOUTH) { + XMapRaised(dpy, win); + draw(); + } + else + XUnmapWindow(dpy, win); + XSync(dpy, False); + break; + case Ffont: + if(font) + free(font); + font = cext_emallocz(c->fcall->count + 1); + memcpy(font, c->fcall->data, c->fcall->count); + xfont = blitz_getfont(dpy, font); + update_geometry(); + break; + case Fexpand: + { + const char *err; + if(c->fcall->count && c->fcall->count < 16) { + memcpy(buf, c->fcall->data, c->fcall->count); + buf[c->fcall->count] = 0; + i = (unsigned short) cext_strtonum(buf, 1, 0xffff, &err); + if(i < nitem) { + iexpand = i; + draw(); + break; + } + } + } + errstr = "item not found"; + return -1; + break; + case Fdata: + { + unsigned int len = c->fcall->count; + if(i == nitem) + new_item(); + if(!i || (i >= nitem)) + goto error_xwrite; + if(len >= sizeof(item[i]->data)) + len = sizeof(item[i]->data) - 1; + memcpy(item[i]->data, c->fcall->data, len); + item[i]->data[len] = 0; + draw(); + } + break; + case Fcolor: + if(i == nitem) + new_item(); + if((i >= nitem) || (c->fcall->count != 24) + || (c->fcall->data[0] != '#') || (c->fcall->data[8] != '#') + || (c->fcall->data[16] != '#')) + { + errstr = "wrong color format"; + goto error_xwrite; + } + memcpy(item[i]->color, c->fcall->data, c->fcall->count); + item[i]->color[c->fcall->count] = 0; + update_color(item[i]); + draw(); + break; + default: +error_xwrite: + if(!errstr) + errstr = "invalid write"; + return -1; + break; + } + c->fcall->id = RWRITE; + return 0; +} + +static int +xclunk(IXPConn *c) +{ + IXPMap *m = ixp_server_fid2map(c, c->fcall->fid); + + if(!m) { + errstr = Enofid; + return -1; + } + cext_array_detach((void **)c->map, m, &c->mapsz); + free(m); + c->fcall->id = RCLUNK; + return 0; } static void -update_geometry() +close_ixp_conn(IXPServer *s, IXPConn *c) { - brect = rect; - brect.height = font->ascent + font->descent + 4; - if(align == SOUTH) - brect.y = rect.height - brect.height; - XMoveResizeWindow(dpy, win, brect.x, brect.y, brect.width, - brect.height); - XSync(dpy, False); - XFreePixmap(dpy, pmap); - pmap = - XCreatePixmap(dpy, win, brect.width, brect.height, - DefaultDepth(dpy, screen_num)); - XSync(dpy, False); - if(file[B_EVENT_RESIZE]->content) - wmii_spawn(dpy, file[B_EVENT_RESIZE]->content); + size_t i; + cext_array_detach((void **)s->conn, c, &s->connsz); + if(c->map) { + for(i = 0; (i < c->mapsz) && c->map[i]; i++) + free(c->map[i]); + free(c->map); + } + if(c->pend) { + for(i = 0; (i < c->pendsz) && c->pend[i]; i++) + free(c->pend[i]); + free(c->pend); + } + shutdown(c->fd, SHUT_RDWR); + close(c->fd); + free(c); } static void -handle_after_write(IXPServer * s, File * f) +do_fcall(IXPServer *s, IXPConn *c) { - int i; - size_t len; - Item *item; - char buf[512]; - - buf[0] = 0; - if(!strncmp(f->name, "data", 5)) { - if((item = item_for_file(f->parent))) { - wmii_get_ixppath(f->parent, buf, sizeof(buf)); - init_draw_label(buf, &item->d); - draw(); - } - } else if(file[B_GEOMETRY] == f) { - if(f->content) { - if(!strncmp(f->content, "south", 6)) - align = SOUTH; - else if(!strncmp(f->content, "north", 6)) - align = NORTH; - update_geometry(); - draw_bar(0, 0); - } - } else if(file[B_CTL] == f) { - for(i = 0; acttbl[i].name; i++) { - len = strlen(acttbl[i].name); - if(!strncmp(acttbl[i].name, (char *) f->content, len)) { - if(strlen(f->content) > len) { - acttbl[i].func(0, &((char *) f->content)[len + 1]); - } else { - acttbl[i].func(0, 0); - } - break; - } - } - } else if(file[B_FONT] == f) { - XFreeFont(dpy, font); - font = blitz_getfont(dpy, file[B_FONT]->content); - update_geometry(); - draw_bar(0, 0); - } - check_event(0); + unsigned int msize; + int ret = -1; + errstr = 0; + if(!(msize = ixp_recv_message(c->fd, msg, IXP_MAX_MSG, &errstr))) { + close_ixp_conn(s, c); + return; + } + if(!c->fcall) + c->fcall = cext_emallocz(sizeof(Fcall)); + if((msize = ixp_msg_to_fcall(msg, IXP_MAX_MSG, c->fcall))) { + switch(c->fcall->id) { + case TVERSION: ret = xversion(c); break; + case TATTACH: ret = xattach(c); break; + case TWALK: ret = xwalk(c); break; + case TREMOVE: ret = xremove(c); break; + case TOPEN: ret = xopen(c); break; + case TREAD: ret = xread(c); break; + case TWRITE: ret = xwrite(c); break; + case TCLUNK: ret = xclunk(c); break; + case TSTAT: ret = xstat(c); break; + default: + break; + } + } + if(ret == -1) { + if(!errstr) + errstr = Enofunc; + c->fcall->id = RERROR; + cext_strlcpy(c->fcall->errstr, errstr, sizeof(c->fcall->errstr)); + } + else if(ret == 1) { + c->pend = (Fcall **)cext_array_attach((void **)c->pend, c->fcall, sizeof(Fcall *), &c->pendsz); + c->fcall = nil; + return; /* response asynchroneously */ + } + msize = ixp_fcall_to_msg(c->fcall, msg, IXP_MAX_MSG); + if(ixp_send_message(c->fd, msg, msize, &errstr) != msize) + close_ixp_conn(s, c); +} + +static Fcall * +pending(IXPConn *c, unsigned char id) +{ + size_t i; + for(i = 0; (i < c->pendsz) && c->pend[i]; i++) + if(c->pend[i]->id == id) + return c->pend[i]; + return nil; } static void -handle_before_read(IXPServer * s, File * f) -{ - char buf[64]; - if(f == file[B_GEOMETRY]) { - snprintf(buf, 64, "%d %d %d %d", brect.x, brect.y, brect.width, - brect.height); - if(f->content) - free(f->content); - f->content = cext_estrdup(buf); - f->size = strlen(buf); - } else if(f == file[B_NEW]) { - snprintf(buf, sizeof(buf), "%d", id++); - if(f->content) - free(f->content); - f->content = strdup(buf); - f->size = strlen(buf); - create_label(buf); - draw_bar(0, 0); - } +do_pend_fcall(char *event) +{ + size_t i; + Fcall *fcall; + for(i = 0; (i < srv.connsz) && srv.conn[i]; i++) { + IXPConn *c = srv.conn[i]; + /* all pending TREADs are on /event, so no qid checking necessary */ + while((fcall = pending(c, TREAD))) { + IXPMap *m = ixp_server_fid2map(c, fcall->fid); + unsigned char *p = fcall->data; + unsigned int msize; + + if(!m) { + errstr = Enofid; + fcall->id = RERROR; + } + else if(qpath_type(m->qid.path) == Fevent) { + fcall->count = strlen(event); + memcpy(p, event, fcall->count); + fcall->id = RREAD; + } + msize = ixp_fcall_to_msg(fcall, msg, IXP_MAX_MSG); + /* remove pending request */ + cext_array_detach((void **)c->pend, fcall, &c->pendsz); + free(fcall); + if(ixp_send_message(c->fd, msg, msize, &errstr) != msize) { + close_ixp_conn(&srv, c); + break; + } + } + } } -static int -dummy_error_handler(Display * dpy, XErrorEvent * err) +static void +new_ixp_conn(IXPServer *s, IXPConn *c) { - return 0; + IXPConn *new; + int fd = ixp_accept_sock(c->fd); + + if(fd >= 0) { + new = cext_emallocz(sizeof(IXPConn)); + new->fd = fd; + new->read = do_fcall; + new->close = close_ixp_conn; + s->conn = (IXPConn **)cext_array_attach((void **)s->conn, new, + sizeof(IXPConn *), &s->connsz); + } } + +/* main */ + int main(int argc, char *argv[]) { int i; + IXPConn *c; XSetWindowAttributes wa; XGCValues gcv; @@ -484,9 +983,9 @@ main(int argc, char *argv[]) fprintf(stdout, "%s", version[0]); exit(0); break; - case 's': + case 'a': if(i + 1 < argc) - sockfile = argv[++i]; + address = argv[++i]; else usage(); break; @@ -504,51 +1003,60 @@ main(int argc, char *argv[]) XSetErrorHandler(dummy_error_handler); screen_num = DefaultScreen(dpy); - ixps = wmii_setup_server(sockfile); + if(!address) { + fprintf(stderr, "%s\n", "wmiibar: no socket address provided"); + exit(1); + } + i = ixp_create_sock(address, &errstr); + if(i < 0) { + fprintf(stderr, "wmiibar: fatal: %s\n", errstr); + exit(1); + } + /* IXP server */ + c = cext_emallocz(sizeof(IXPConn)); + c->fd = i; + c->read = new_ixp_conn; + c->close = close_ixp_conn; + srv.conn = (IXPConn **)cext_array_attach((void **)srv.conn, c, + sizeof(IXPConn *), &srv.connsz); + /* X server */ + c = cext_emallocz(sizeof(IXPConn)); + c->fd = ConnectionNumber(dpy); + c->read = check_x_event; + srv.conn = (IXPConn **)cext_array_attach((void **)srv.conn, c, + sizeof(IXPConn *), &srv.connsz); - /* init */ - if(!(file[B_CTL] = ixp_create(ixps, "/ctl"))) { - perror("wmiibar: cannot connect IXP server"); - exit(1); - } - file[B_CTL]->after_write = handle_after_write; - file[B_NEW] = ixp_create(ixps, "/new"); - file[B_NEW]->before_read = handle_before_read; - file[B_FONT] = wmii_create_ixpfile(ixps, "/font", BLITZ_FONT); - file[B_FONT]->after_write = handle_after_write; - font = blitz_getfont(dpy, file[B_FONT]->content); - file[B_BG_COLOR] = - wmii_create_ixpfile(ixps, "/bgcolor", BLITZ_NORM_BG_COLOR); - file[B_FG_COLOR] = - wmii_create_ixpfile(ixps, "/fgcolor", BLITZ_NORM_FG_COLOR); - file[B_BORDER_COLOR] = - wmii_create_ixpfile(ixps, "/bordercolor", BLITZ_NORM_BORDER_COLOR); - file[B_GEOMETRY] = ixp_create(ixps, "/geometry"); - file[B_GEOMETRY]->before_read = handle_before_read; - file[B_GEOMETRY]->after_write = handle_after_write; - file[B_EXPANDABLE] = ixp_create(ixps, "/expandable"); - file[B_EVENT_RESIZE] = ixp_create(ixps, "/event/resize"); + root_qid.type = IXP_QTDIR; + root_qid.version = 0; + root_qid.path = mkqpath(Droot, 0); + + mypid = getpid(); + /* default settings */ + new_item(); + cext_strlcpy(item[0]->color, BLITZ_SEL_COLOR, sizeof(item[0]->color)); + update_color(item[0]); + + /* X stuff */ + font = strdup(BLITZ_FONT); + xfont = blitz_getfont(dpy, font); wa.override_redirect = 1; wa.background_pixmap = ParentRelative; - wa.event_mask = - ExposureMask | ButtonPressMask | SubstructureRedirectMask | - SubstructureNotifyMask; + wa.event_mask = ExposureMask | ButtonPressMask + | SubstructureRedirectMask | SubstructureNotifyMask; rect.x = rect.y = 0; rect.width = DisplayWidth(dpy, screen_num); rect.height = DisplayHeight(dpy, screen_num); brect = rect; - brect.height = font->ascent + font->descent + 4; + brect.height = xfont->ascent + xfont->descent + 4; brect.y = rect.height - brect.height; win = XCreateWindow(dpy, RootWindow(dpy, screen_num), brect.x, brect.y, - brect.width, brect.height, 0, DefaultDepth(dpy, - screen_num), + brect.width, brect.height, 0, DefaultDepth(dpy, screen_num), CopyFromParent, DefaultVisual(dpy, screen_num), - CWOverrideRedirect | CWBackPixmap | CWEventMask, - &wa); + CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_left_ptr)); XSync(dpy, False); @@ -556,17 +1064,19 @@ main(int argc, char *argv[]) gcv.graphics_exposures = False; gc = XCreateGC(dpy, win, 0, 0); - pmap = - XCreatePixmap(dpy, win, brect.width, brect.height, - DefaultDepth(dpy, screen_num)); + pmap = XCreatePixmap(dpy, win, brect.width, brect.height, + DefaultDepth(dpy, screen_num)); - /* main event loop */ - run_server_with_fd_support(ixps, ConnectionNumber(dpy), check_event, - 0); - deinit_server(ixps); - XFreePixmap(dpy, pmap); - XFreeGC(dpy, gc); - XCloseDisplay(dpy); + /* main loop */ + errstr = ixp_server_loop(&srv); - return 0; + if(errstr) + fprintf(stderr, "wmiibar: fatal: %s\n", errstr); + + /* cleanup */ + for(i = 0; (i < srv.connsz) && srv.conn[i]; i++) + if(srv.conn[i]->close) + srv.conn[i]->close(&srv, srv.conn[i]); + + return errstr ? 1 : 0; } diff --git a/cmd/wmiibar2.c b/cmd/wmiibar2.c @@ -1,1084 +0,0 @@ -/* - * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> - * See LICENSE file for license details. - */ - -#include <assert.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <sys/types.h> -#include <time.h> -#include <unistd.h> -#include <X11/Xatom.h> -#include <X11/cursorfont.h> -#include <X11/Xproto.h> -#include <X11/Xutil.h> -#include <sys/socket.h> - -#include "../libixp2/ixp.h" -#include "blitz.h" - -/* - * filesystem specification - * / Droot - * /display Fdisplay 'north', 'south', 'none' - * /font Ffont <xlib font name> - * /event Fevent - * /expand Fexpand id of expandable label - * /ctl Fctl command interface - * /new Dnew returns content of new item - * /default/ Ditem - * /default/color Fcolor <#RRGGBB> <#RRGGBB> <#RRGGBB> - * /1/ Ditem - * /1/data Fdata <arbitrary data which gets displayed> - * /1/color Fcolor <#RRGGBB> <#RRGGBB> <#RRGGBB> - */ - -/* 8-bit qid.path.type */ -enum { - Droot, - Ditem, - Fctl, - Fdisplay, - Ffont, - Fexpand, - Fevent, - Fdata, /* data to display */ - Fcolor -}; - -typedef struct { - char data[256]; - char color[24]; - unsigned long fg; - unsigned long bg; - unsigned long border; - XRectangle rect; -} Item; - -static char E9pversion[] = "9P version not supported"; -static char Enoperm[] = "permission denied"; -static char Enofid[] = "fid not assigned"; -static char Enofile[] = "file not found"; -static char Enomode[] = "mode not supported"; -static char Enofunc[] = "function not supported"; - -static unsigned char *msg[IXP_MAX_MSG]; -char *errstr = 0; -static size_t nitem = 0; -static size_t itemsz = 0; -static size_t iexpand = 0; -static Item **item = 0; -static char *address = nil; -static pid_t mypid = 0; -static IXPServer srv = { 0 }; -static Qid root_qid; -static Display *dpy; -static int screen_num; -static char *font = nil; -static Align align = CENTER; -static XFontStruct *xfont; -static GC gc; -static Window win; -static XRectangle brect, rect; -static Pixmap pmap; - -static void do_pend_fcall(char *event); - -static char *version[] = { - "wmiibar - window manager improved bar - " VERSION "\n" - " (C)opyright MMIV-MMVI Anselm R. Garbe\n", 0 -}; - -static void -usage() -{ - fprintf(stderr, "%s %d", - "usage: wmiibar -a <server address> [-v]\n" - " -a server address \n" - " -v version info\n", 0); - exit(1); -} - -static int -dummy_error_handler(Display * dpy, XErrorEvent * err) -{ - return 0; -} - -static void -new_item() -{ - Item *it = cext_emallocz(sizeof(Item)); - if(nitem > 0) { - cext_strlcpy(it->color, item[0]->color, sizeof(it->color)); - it->fg = item[0]->fg; - it->bg = item[0]->bg; - it->border = item[0]->border; - } - item = (Item **)cext_array_attach((void **)item, it, sizeof(Item *), &itemsz); - nitem++; -} - -static void -detach_item(Item *it) -{ - cext_array_detach((void **)item, it, &itemsz); - nitem--; -} - -static void -draw() -{ - size_t i; - unsigned int w = 0; - Draw d = { 0 }; - - d.gc = gc; - d.drawable = pmap; - d.rect = brect; - d.rect.y = 0; - d.font = xfont; - - if(nitem == 1) { /* /default only */ - d.fg = item[0]->fg; - d.bg = item[0]->bg; - d.border = item[0]->border; - blitz_drawlabel(dpy, &d); - } - else { - if(!iexpand) - iexpand = nitem - 1; - for(i = 1; i < nitem; i++) { - Item *it = item[i]; - it->rect.x = it->rect.y = 0; - it->rect.width = it->rect.height = brect.height; - if(i == iexpand) - continue; - if(strlen(it->data)) { - if(!strncmp(it->data, "%m:", 3)) - it->rect.width = brect.height / 2; - else - it->rect.width += XTextWidth(xfont, it->data, strlen(it->data)); - } - w += it->rect.width; - } - if(w >= brect.width) { - /* failsafe mode, give all labels same width */ - w = brect.width / nitem; - for(i = 1; i < nitem; i++) - item[i]->rect.width = w; - i--; - item[i]->rect.width = brect.width - ((i - 1) * w); - } else - item[iexpand]->rect.width = brect.width - w; - for(i = 1; i < nitem; i++) { - d.fg = item[i]->fg; - d.bg = item[i]->bg; - d.border = item[i]->border; - if(i > 1) - item[i]->rect.x = item[i - 1]->rect.x + item[i - 1]->rect.width; - d.rect = item[i]->rect; - d.data = item[i]->data; - if(d.data && !strncmp(d.data, "%m:", 3)) - blitz_drawmeter(dpy, &d); - else - blitz_drawlabel(dpy, &d); - } - } - XCopyArea(dpy, pmap, win, gc, 0, 0, brect.width, brect.height, 0, 0); - XSync(dpy, False); -} - -static void -update_color(Item *it) -{ - it->fg = blitz_loadcolor(dpy, screen_num, &it->color[0]); - it->bg = blitz_loadcolor(dpy, screen_num, &it->color[8]); - it->border = blitz_loadcolor(dpy, screen_num, &it->color[16]); -} - -static void -update_geometry() -{ - char buf[64]; - brect = rect; - brect.height = xfont->ascent + xfont->descent + 4; - if(align == SOUTH) - brect.y = rect.height - brect.height; - XMoveResizeWindow(dpy, win, brect.x, brect.y, brect.width, brect.height); - XSync(dpy, False); - XFreePixmap(dpy, pmap); - pmap = XCreatePixmap(dpy, win, brect.width, brect.height, - DefaultDepth(dpy, screen_num)); - XSync(dpy, False); - snprintf(buf, sizeof(buf), "NewGeometry %d %d %d %d\n", brect.x, brect.y, brect.width, brect.height); - do_pend_fcall(buf); - draw(); -} - -static void -handle_buttonpress(XButtonPressedEvent * e) -{ - size_t i; - char buf[32]; - for(i = 0; i < nitem; i++) - if(blitz_ispointinrect(e->x, e->y, &item[i]->rect)) { - snprintf(buf, sizeof(buf), "Button%dPress %d\n", e->button, i); - do_pend_fcall(buf); - } -} - -static void -check_x_event(IXPServer *s, IXPConn *c) -{ - XEvent e; - - while(XPending(dpy)) { - XNextEvent(dpy, &e); - switch (e.type) { - case ButtonPress: - handle_buttonpress(&e.xbutton); - break; - case Expose: - if(e.xexpose.count == 0) - draw(); - break; - default: - break; - } - } -} - - -/* IXP stuff */ - -static unsigned long long -mkqpath(unsigned char type, unsigned short item) -{ - return ((unsigned long long) item << 8) | (unsigned long long) type; -} - -static unsigned char -qpath_type(unsigned long long path) -{ - return path & 0xff; -} - -static unsigned short -qpath_item(unsigned long long path) -{ - return (path >> 8) & 0xffff; -} - -static char * -qid_to_name(Qid *qid) -{ - unsigned char type = qpath_type(qid->path); - unsigned short i = qpath_item(qid->path); - static char buf[32]; - - switch(type) { - case Droot: return "/"; break; - case Ditem: - if(!i) - return "default"; - else if(i == nitem) - return "new"; - snprintf(buf, sizeof(buf), "%u", i); - return buf; - break; - case Fctl: return "ctl"; break; - case Fdisplay: return "display"; break; - case Ffont: return "font"; break; - case Fexpand: return "expand"; break; - case Fdata: return "data"; break; - case Fevent: return "event"; break; - case Fcolor: return "color"; break; - default: return nil; break; - } -} - -static int -name_to_type(char *name) -{ - const char *err; - unsigned int i; - if(!name || !name[0] || !strncmp(name, "/", 2) || !strncmp(name, "..", 3)) - return Droot; - if(!strncmp(name, "default", 8) || !strncmp(name, "new", 4)) - return Ditem; - if(!strncmp(name, "ctl", 4)) - return Fctl; - if(!strncmp(name, "display", 8)) - return Fdisplay; - if(!strncmp(name, "font", 5)) - return Ffont; - if(!strncmp(name, "expand", 7)) - return Fexpand; - if(!strncmp(name, "data", 5)) - return Fdata; - if(!strncmp(name, "event", 6)) - return Fevent; - if(!strncmp(name, "color", 6)) - return Fcolor; - i = (unsigned short) cext_strtonum(name, 1, 0xffff, &err); - if(!err && (i <= nitem)) - return Ditem; - return -1; -} - -static int -mkqid(Qid *dir, char *wname, Qid *new) -{ - const char *err; - int type = name_to_type(wname); - unsigned short i = qpath_item(dir->path); - - if((dir->type != IXP_QTDIR) || (type == -1)) - return -1; - - new->version = 0; - switch(type) { - case Droot: - new->type = IXP_QTDIR; - *new = root_qid; - break; - case Ditem: - new->type = IXP_QTDIR; - if(!strncmp(wname, "default", 8)) - new->path = mkqpath(Ditem, 0); - else if(!strncmp(wname, "new", 4)) - new->path = mkqpath(Ditem, nitem); - else { - unsigned short i = cext_strtonum(wname, 1, 0xffff, &err); - if(err || (i >= nitem)) - return -1; - new->path = mkqpath(Ditem, i); - } - break; - case Fdata: /* note, Fdata needs to be before Fcolor, fallthrough */ - if(!i) - return -1; - case Fcolor: - if(i > nitem) - return -1; - default: - new->type = IXP_QTFILE; - new->path = mkqpath(type, i); - break; - } - return 0; -} - -static int -xversion(IXPConn *c) -{ - if(strncmp(c->fcall->version, IXP_VERSION, strlen(IXP_VERSION))) { - errstr = E9pversion; - return -1; - } else if(c->fcall->maxmsg > IXP_MAX_MSG) - c->fcall->maxmsg = IXP_MAX_MSG; - c->fcall->id = RVERSION; - return 0; -} - -static int -xattach(IXPConn *c) -{ - IXPMap *new = cext_emallocz(sizeof(IXPMap)); - new->qid = root_qid; - new->fid = c->fcall->fid; - c->map = (IXPMap **)cext_array_attach((void **)c->map, new, - sizeof(IXPMap *), &c->mapsz); - c->fcall->id = RATTACH; - c->fcall->qid = root_qid; - return 0; -} - -static int -xwalk(IXPConn *c) -{ - unsigned short nwqid = 0; - Qid dir = root_qid; - IXPMap *m; - - if(!(m = ixp_server_fid2map(c, c->fcall->fid))) { - errstr = Enofid; - return -1; - } - if(c->fcall->fid != c->fcall->newfid - && (ixp_server_fid2map(c, c->fcall->newfid))) { - errstr = Enofid; - return -1; - } - if(c->fcall->nwname) { - dir = m->qid; - for(nwqid = 0; (nwqid < c->fcall->nwname) - && !mkqid(&dir, c->fcall->wname[nwqid], &c->fcall->wqid[nwqid]); nwqid++) - dir = c->fcall->wqid[nwqid]; - if(!nwqid) { - errstr = Enofile; - return -1; - } - } - /* a fid will only be valid, if the walk was complete */ - if(nwqid == c->fcall->nwname) { - if(c->fcall->fid != c->fcall->newfid) { - m = cext_emallocz(sizeof(IXPMap)); - c->map = (IXPMap **)cext_array_attach((void **)c->map, m, - sizeof(IXPMap *), &c->mapsz); - } - m->qid = dir; - m->fid = c->fcall->newfid; - } - c->fcall->id = RWALK; - c->fcall->nwqid = nwqid; - return 0; -} - -static int -xopen(IXPConn *c) -{ - IXPMap *m = ixp_server_fid2map(c, c->fcall->fid); - - if(!m) { - errstr = Enofid; - return -1; - } - if(!(c->fcall->mode | IXP_OREAD) && !(c->fcall->mode | IXP_OWRITE)) { - errstr = Enomode; - return -1; - } - c->fcall->id = ROPEN; - c->fcall->qid = m->qid; - c->fcall->iounit = c->fcall->maxmsg - - (sizeof(unsigned char) + sizeof(unsigned short) + 2 * sizeof(unsigned int)); - return 0; -} - -static unsigned int -mkstat(Stat *stat, Qid *dir, char *name, unsigned long long length, unsigned int mode) -{ - stat->mode = mode; - stat->atime = stat->mtime = time(0); - cext_strlcpy(stat->uid, getenv("USER"), sizeof(stat->uid)); - cext_strlcpy(stat->gid, getenv("USER"), sizeof(stat->gid)); - cext_strlcpy(stat->muid, getenv("USER"), sizeof(stat->muid)); - - cext_strlcpy(stat->name, name, sizeof(stat->name)); - stat->length = length; - mkqid(dir, name, &stat->qid); - return ixp_sizeof_stat(stat); -} - -static unsigned int -type_to_stat(Stat *stat, char *name, unsigned short i) -{ - int type = name_to_type(name); - Qid dir = {IXP_QTDIR, 0, mkqpath(Ditem, i)}; - - switch (type) { - case Droot: - case Ditem: - return mkstat(stat, &root_qid, name, 0, DMDIR | DMREAD | DMEXEC); - break; - case Fctl: - return mkstat(stat, &root_qid, name, 0, DMWRITE); - break; - case Fdisplay: - if(align == SOUTH || align == NORTH) - return mkstat(stat, &root_qid, name, 6, DMREAD | DMWRITE); - else - return mkstat(stat, &root_qid, name, 5, DMREAD | DMWRITE); - break; - case Fevent: - return mkstat(stat, &root_qid, name, 0, DMREAD); - break; - case Ffont: - return mkstat(stat, &root_qid, name, strlen(font), - DMREAD | DMWRITE); - break; - case Fexpand: - { - char buf[16]; - snprintf(buf, sizeof(buf), "%u", iexpand); - return mkstat(stat, &root_qid, name, strlen(buf), DMREAD | DMWRITE); - } - break; - case Fdata: - if(i == nitem) - i = 0; - return mkstat(stat, &dir, name, strlen(item[i]->data), - DMREAD | DMWRITE); - break; - case Fcolor: - if(i == nitem) - i = 0; - return mkstat(stat, &dir, name, strlen(item[i]->color), - DMREAD | DMWRITE); - break; - default: - errstr = "invalid stat"; - break; - } - return 0; -} - -static int -xremove(IXPConn *c) -{ - IXPMap *m = ixp_server_fid2map(c, c->fcall->fid); - unsigned short i; - - if(!m) { - errstr = Enofid; - return -1; - } - i = qpath_item(m->qid.path); - if((qpath_type(m->qid.path) == Ditem) && i && (i < nitem)) { - Item *it = item[i]; - detach_item(it); - free(it); - c->fcall->id = RREMOVE; - if(iexpand >= nitem) - iexpand = 0; - draw(); - return 0; - } - errstr = Enoperm; - return -1; -} - -static int -xread(IXPConn *c) -{ - Stat stat; - IXPMap *m = ixp_server_fid2map(c, c->fcall->fid); - unsigned char *p = c->fcall->data; - unsigned short i; - unsigned int len; - char buf[32]; - - if(!m) { - errstr = Enofid; - return -1; - } - i = qpath_item(m->qid.path); - - c->fcall->count = 0; - if(c->fcall->offset) { - switch (qpath_type(m->qid.path)) { - case Droot: - /* jump to offset */ - len = type_to_stat(&stat, "ctl", 0); - len += type_to_stat(&stat, "display", 0); - len += type_to_stat(&stat, "font", 0); - len += type_to_stat(&stat, "new", 0); - len += type_to_stat(&stat, "event", 0); - len += type_to_stat(&stat, "default", 0); - for(i = 1; i < nitem; i++) { - snprintf(buf, sizeof(buf), "%u", i); - len += type_to_stat(&stat, buf, i); - if(len < c->fcall->offset) - continue; - else - break; - } - /* offset found, proceeding */ - for(; i < nitem; i++) { - snprintf(buf, sizeof(buf), "%u", i); - len = type_to_stat(&stat, buf, i); - if(c->fcall->count + len >= c->fcall->iounit) - break; - c->fcall->count += len; - p = ixp_enc_stat(p, &stat); - } - break; - case Fevent: - return 1; - break; - default: - break; - } - } - else { - switch (qpath_type(m->qid.path)) { - case Droot: - c->fcall->count = type_to_stat(&stat, "ctl", 0); - p = ixp_enc_stat(p, &stat); - c->fcall->count += type_to_stat(&stat, "display", 0); - p = ixp_enc_stat(p, &stat); - c->fcall->count += type_to_stat(&stat, "font", 0); - p = ixp_enc_stat(p, &stat); - c->fcall->count += type_to_stat(&stat, "new", 0); - p = ixp_enc_stat(p, &stat); - c->fcall->count += type_to_stat(&stat, "event", 0); - p = ixp_enc_stat(p, &stat); - c->fcall->count += type_to_stat(&stat, "default", 0); - p = ixp_enc_stat(p, &stat); - for(i = 1; i < nitem; i++) { - snprintf(buf, sizeof(buf), "%u", i); - len = type_to_stat(&stat, buf, i); - if(c->fcall->count + len >= c->fcall->iounit) - break; - c->fcall->count += len; - p = ixp_enc_stat(p, &stat); - } - break; - case Ditem: - if(i > nitem) - goto error_xread; - if(!i) { - c->fcall->count = type_to_stat(&stat, "color", i); - p = ixp_enc_stat(p, &stat); - break; - } - if(i == nitem) - new_item(); - c->fcall->count = type_to_stat(&stat, "color", i); - p = ixp_enc_stat(p, &stat); - c->fcall->count += type_to_stat(&stat, "data", i); - p = ixp_enc_stat(p, &stat); - break; - case Fctl: - errstr = Enoperm; - return -1; - break; - case Fdisplay: - switch(align) { - case SOUTH: - memcpy(p, "south", 5); - c->fcall->count = 5; - break; - case NORTH: - memcpy(p, "north", 5); - c->fcall->count = 5; - break; - default: - memcpy(p, "none", 4); - c->fcall->count = 4; - break; - } - break; - case Ffont: - if((c->fcall->count = strlen(font))) - memcpy(p, font, c->fcall->count); - break; - case Fexpand: - snprintf(buf, sizeof(buf), "%u", iexpand); - c->fcall->count = strlen(buf); - memcpy(p, buf, c->fcall->count); - break; - case Fevent: - return 1; - break; - case Fdata: - if(i == nitem) - new_item(); - if(i >= nitem) - goto error_xread; - if((c->fcall->count = strlen(item[i]->data))) - memcpy(p, item[i]->data, c->fcall->count); - break; - case Fcolor: - if(i == nitem) - new_item(); - if(i >= nitem) - goto error_xread; - if((c->fcall->count = strlen(item[i]->color))) - memcpy(p, item[i]->color, c->fcall->count); - break; - default: - error_xread: - if(!errstr) - errstr = "invalid read"; - return -1; - break; - } - } - c->fcall->id = RREAD; - return 0; -} - -static int -xstat(IXPConn *c) -{ - IXPMap *m = ixp_server_fid2map(c, c->fcall->fid); - char *name; - - if(!m) { - errstr = Enofid; - return -1; - } - - name = qid_to_name(&m->qid); - if(!type_to_stat(&c->fcall->stat, name, qpath_item(m->qid.path))) - return -1; - c->fcall->id = RSTAT; - return 0; -} - -static int -xwrite(IXPConn *c) -{ - char buf[256]; - IXPMap *m = ixp_server_fid2map(c, c->fcall->fid); - unsigned short i; - - if(!m) { - errstr = Enofid; - return -1; - } - - i = qpath_item(m->qid.path); - switch (qpath_type(m->qid.path)) { - case Fctl: - if(c->fcall->count == 5) { - memcpy(buf, c->fcall->data, 4); - buf[4] = 0; - if(!strncmp(buf, "quit", 5)) { - srv.running = 0; - break; - } - } - errstr = "command not supported"; - return -1; - break; - case Fdisplay: - if(c->fcall->count != 6 && c->fcall->count != 5) - goto error_xwrite; - memcpy(buf, c->fcall->data, c->fcall->count); - buf[c->fcall->count] = 0; - if(blitz_strtoalign(&align, buf) == -1) - goto error_xwrite; - update_geometry(); - if(align == NORTH || align == SOUTH) { - XMapRaised(dpy, win); - draw(); - } - else - XUnmapWindow(dpy, win); - XSync(dpy, False); - break; - case Ffont: - if(font) - free(font); - font = cext_emallocz(c->fcall->count + 1); - memcpy(font, c->fcall->data, c->fcall->count); - xfont = blitz_getfont(dpy, font); - update_geometry(); - break; - case Fexpand: - { - const char *err; - if(c->fcall->count && c->fcall->count < 16) { - memcpy(buf, c->fcall->data, c->fcall->count); - buf[c->fcall->count] = 0; - i = (unsigned short) cext_strtonum(buf, 1, 0xffff, &err); - if(i < nitem) { - iexpand = i; - draw(); - break; - } - } - } - errstr = "item not found"; - return -1; - break; - case Fdata: - { - unsigned int len = c->fcall->count; - if(i == nitem) - new_item(); - if(!i || (i >= nitem)) - goto error_xwrite; - if(len >= sizeof(item[i]->data)) - len = sizeof(item[i]->data) - 1; - memcpy(item[i]->data, c->fcall->data, len); - item[i]->data[len] = 0; - draw(); - } - break; - case Fcolor: - if(i == nitem) - new_item(); - if((i >= nitem) || (c->fcall->count != 24) - || (c->fcall->data[0] != '#') || (c->fcall->data[8] != '#') - || (c->fcall->data[16] != '#')) - { - errstr = "wrong color format"; - goto error_xwrite; - } - memcpy(item[i]->color, c->fcall->data, c->fcall->count); - item[i]->color[c->fcall->count] = 0; - update_color(item[i]); - draw(); - break; - default: -error_xwrite: - if(!errstr) - errstr = "invalid write"; - return -1; - break; - } - c->fcall->id = RWRITE; - return 0; -} - -static int -xclunk(IXPConn *c) -{ - IXPMap *m = ixp_server_fid2map(c, c->fcall->fid); - - if(!m) { - errstr = Enofid; - return -1; - } - cext_array_detach((void **)c->map, m, &c->mapsz); - free(m); - c->fcall->id = RCLUNK; - return 0; -} - -static void -close_ixp_conn(IXPServer *s, IXPConn *c) -{ - size_t i; - cext_array_detach((void **)s->conn, c, &s->connsz); - if(c->map) { - for(i = 0; (i < c->mapsz) && c->map[i]; i++) - free(c->map[i]); - free(c->map); - } - if(c->pend) { - for(i = 0; (i < c->pendsz) && c->pend[i]; i++) - free(c->pend[i]); - free(c->pend); - } - shutdown(c->fd, SHUT_RDWR); - close(c->fd); - free(c); -} - -static void -do_fcall(IXPServer *s, IXPConn *c) -{ - unsigned int msize; - int ret = -1; - errstr = 0; - if(!(msize = ixp_recv_message(c->fd, msg, IXP_MAX_MSG, &errstr))) { - close_ixp_conn(s, c); - return; - } - if(!c->fcall) - c->fcall = cext_emallocz(sizeof(Fcall)); - if((msize = ixp_msg_to_fcall(msg, IXP_MAX_MSG, c->fcall))) { - switch(c->fcall->id) { - case TVERSION: ret = xversion(c); break; - case TATTACH: ret = xattach(c); break; - case TWALK: ret = xwalk(c); break; - case TREMOVE: ret = xremove(c); break; - case TOPEN: ret = xopen(c); break; - case TREAD: ret = xread(c); break; - case TWRITE: ret = xwrite(c); break; - case TCLUNK: ret = xclunk(c); break; - case TSTAT: ret = xstat(c); break; - default: - break; - } - } - if(ret == -1) { - if(!errstr) - errstr = Enofunc; - c->fcall->id = RERROR; - cext_strlcpy(c->fcall->errstr, errstr, sizeof(c->fcall->errstr)); - } - else if(ret == 1) { - c->pend = (Fcall **)cext_array_attach((void **)c->pend, c->fcall, sizeof(Fcall *), &c->pendsz); - c->fcall = nil; - return; /* response asynchroneously */ - } - msize = ixp_fcall_to_msg(c->fcall, msg, IXP_MAX_MSG); - if(ixp_send_message(c->fd, msg, msize, &errstr) != msize) - close_ixp_conn(s, c); -} - -static Fcall * -pending(IXPConn *c, unsigned char id) -{ - size_t i; - for(i = 0; (i < c->pendsz) && c->pend[i]; i++) - if(c->pend[i]->id == id) - return c->pend[i]; - return nil; -} - -static void -do_pend_fcall(char *event) -{ - size_t i; - Fcall *fcall; - for(i = 0; (i < srv.connsz) && srv.conn[i]; i++) { - IXPConn *c = srv.conn[i]; - /* all pending TREADs are on /event, so no qid checking necessary */ - while((fcall = pending(c, TREAD))) { - IXPMap *m = ixp_server_fid2map(c, fcall->fid); - unsigned char *p = fcall->data; - unsigned int msize; - - if(!m) { - errstr = Enofid; - fcall->id = RERROR; - } - else if(qpath_type(m->qid.path) == Fevent) { - fcall->count = strlen(event); - memcpy(p, event, fcall->count); - fcall->id = RREAD; - } - msize = ixp_fcall_to_msg(fcall, msg, IXP_MAX_MSG); - /* remove pending request */ - cext_array_detach((void **)c->pend, fcall, &c->pendsz); - free(fcall); - if(ixp_send_message(c->fd, msg, msize, &errstr) != msize) { - close_ixp_conn(&srv, c); - break; - } - } - } -} - -static void -new_ixp_conn(IXPServer *s, IXPConn *c) -{ - IXPConn *new; - int fd = ixp_accept_sock(c->fd); - - if(fd >= 0) { - new = cext_emallocz(sizeof(IXPConn)); - new->fd = fd; - new->read = do_fcall; - new->close = close_ixp_conn; - s->conn = (IXPConn **)cext_array_attach((void **)s->conn, new, - sizeof(IXPConn *), &s->connsz); - } -} - - -/* main */ - -int -main(int argc, char *argv[]) -{ - int i; - IXPConn *c; - XSetWindowAttributes wa; - XGCValues gcv; - - /* command line args */ - for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) { - switch (argv[i][1]) { - case 'v': - fprintf(stdout, "%s", version[0]); - exit(0); - break; - case 'a': - if(i + 1 < argc) - address = argv[++i]; - else - usage(); - break; - default: - usage(); - break; - } - } - - dpy = XOpenDisplay(0); - if(!dpy) { - fprintf(stderr, "%s", "wmiibar: cannot open display\n"); - exit(1); - } - XSetErrorHandler(dummy_error_handler); - screen_num = DefaultScreen(dpy); - - if(!address) { - fprintf(stderr, "%s\n", "wmiibar: no socket address provided"); - exit(1); - } - i = ixp_create_sock(address, &errstr); - if(i < 0) { - fprintf(stderr, "wmiibar: fatal: %s\n", errstr); - exit(1); - } - - /* IXP server */ - c = cext_emallocz(sizeof(IXPConn)); - c->fd = i; - c->read = new_ixp_conn; - c->close = close_ixp_conn; - srv.conn = (IXPConn **)cext_array_attach((void **)srv.conn, c, - sizeof(IXPConn *), &srv.connsz); - /* X server */ - c = cext_emallocz(sizeof(IXPConn)); - c->fd = ConnectionNumber(dpy); - c->read = check_x_event; - srv.conn = (IXPConn **)cext_array_attach((void **)srv.conn, c, - sizeof(IXPConn *), &srv.connsz); - - root_qid.type = IXP_QTDIR; - root_qid.version = 0; - root_qid.path = mkqpath(Droot, 0); - - mypid = getpid(); - - /* default settings */ - new_item(); - cext_strlcpy(item[0]->color, BLITZ_SEL_COLOR, sizeof(item[0]->color)); - update_color(item[0]); - - /* X stuff */ - font = strdup(BLITZ_FONT); - xfont = blitz_getfont(dpy, font); - wa.override_redirect = 1; - wa.background_pixmap = ParentRelative; - wa.event_mask = ExposureMask | ButtonPressMask - | SubstructureRedirectMask | SubstructureNotifyMask; - - rect.x = rect.y = 0; - rect.width = DisplayWidth(dpy, screen_num); - rect.height = DisplayHeight(dpy, screen_num); - brect = rect; - brect.height = xfont->ascent + xfont->descent + 4; - brect.y = rect.height - brect.height; - - win = XCreateWindow(dpy, RootWindow(dpy, screen_num), brect.x, brect.y, - brect.width, brect.height, 0, DefaultDepth(dpy, screen_num), - CopyFromParent, DefaultVisual(dpy, screen_num), - CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); - XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_left_ptr)); - XSync(dpy, False); - - gcv.function = GXcopy; - gcv.graphics_exposures = False; - gc = XCreateGC(dpy, win, 0, 0); - - pmap = XCreatePixmap(dpy, win, brect.width, brect.height, - DefaultDepth(dpy, screen_num)); - - /* main loop */ - errstr = ixp_server_loop(&srv); - - if(errstr) - fprintf(stderr, "wmiibar: fatal: %s\n", errstr); - - /* cleanup */ - for(i = 0; (i < srv.connsz) && srv.conn[i]; i++) - if(srv.conn[i]->close) - srv.conn[i]->close(&srv, srv.conn[i]); - - return errstr ? 1 : 0; -}