commit 3728e6420f91c308b552dba25d393d7f9378453b
parent 385860251d234cd14722aa8d2f21e1d9fc262747
Author: Anselm R. Garbe <garbeam@wmii.de>
Date: Fri, 3 Feb 2006 17:15:36 +0200
various changes in libixp/server.c, cmd/wmiibar.c and added id;s to Page, Client, and Area
Diffstat:
10 files changed, 395 insertions(+), 330 deletions(-)
diff --git a/cmd/wm/Makefile b/cmd/wm/Makefile
@@ -10,7 +10,7 @@ LDFLAGS += -L../../liblitz -llitz -L../../libwmii -lwmii \
# Solaris
# LDFLAGS += -lsocket
-SRC = fs.c wm.c client.c event.c mouse.c page.c column.c
+SRC = area.c fs.c wm.c client.c event.c mouse.c page.c column.c
OBJ = ${SRC:.c=.o}
all: wmiiwm
diff --git a/cmd/wm/area.c b/cmd/wm/area.c
@@ -0,0 +1,50 @@
+/*
+ * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
+ * See LICENSE file for license details.
+ */
+
+#include <stdlib.h>
+
+#include "wm.h"
+
+Area *
+alloc_area()
+{
+ static unsigned short id = 0;
+ Area *a = cext_emallocz(sizeof(Area));
+
+ a->id = id++;
+ return a;
+}
+
+void
+destroy_area(Area *a)
+{
+ size_t i;
+ while(a->nclient)
+ detach_client(client[i], False);
+ free(a->client);
+ free(a);
+}
+
+int
+index_of_area(Page *p, Area *a)
+{
+ int i;
+ for(i = 0; i < p->narea; i++)
+ if(p->area[i] == a)
+ return i;
+ return -1;
+}
+
+int
+index_of_area_id(Page *p, unsigned short id)
+{
+ int i;
+ if(id == NEW_OBJ)
+ return p->narea;
+ for(i = 0; i < p->narea; i++)
+ if(p->area[i]->id == id)
+ return i;
+ return -1;
+}
diff --git a/cmd/wm/client.c b/cmd/wm/client.c
@@ -26,8 +26,10 @@ alloc_client(Window w, XWindowAttributes *wa)
XSetWindowAttributes fwa;
int bw = def.border, bh;
long msize;
+ static unsigned short id = 0;
/* client itself */
+ c->id = id++;
c->win = w;
c->rect.x = wa->x;
c->rect.y = wa->y;
@@ -68,6 +70,7 @@ alloc_client(Window w, XWindowAttributes *wa)
XSync(dpy, False);
client = (Client **)cext_array_attach((void **)client, c, sizeof(Client *), &clientsz);
+ nclient++;
return c;
}
@@ -139,7 +142,6 @@ unmap_client(Client * c)
void
reparent_client(Client *c, Window w, int x, int y)
{
- c->attached = w == c->frame.win;
XReparentWindow(dpy, c->win, w, x, y);
c->ignore_unmap++;
}
@@ -176,7 +178,7 @@ configure_client(Client * c)
e.window = c->win;
e.x = c->rect.x;
e.y = c->rect.y;
- if(c->attached) {
+ if(c->page) {
e.x += c->frame.rect.x;
e.y += c->frame.rect.y;
}
@@ -218,7 +220,7 @@ handle_client_property(Client *c, XPropertyEvent *e)
cext_strlcpy(c->name, (char*) name.value, sizeof(c->name));
free(name.value);
}
- if(c->attached)
+ if(c->page)
draw_client(c);
/* TODO: client update */
break;
@@ -237,10 +239,17 @@ handle_client_property(Client *c, XPropertyEvent *e)
void
destroy_client(Client * c)
{
+ size_t i;
+ for(i = 0; i < ndet; i++)
+ if(det[i] == c) {
+ cext_array_detach((void **)det, c, &detsz);
+ ndet--;
+ break;
+ }
XFreeGC(dpy, c->frame.gc);
XDestroyWindow(dpy, c->frame.win);
- cext_array_detach((void **)det, c, &detsz);
- ndet--;
+ cext_array_detach((void **)client, c, &clientsz);
+ nclient--;
free(c);
}
@@ -382,23 +391,25 @@ attach_client(Client *c)
void
detach_client(Client *c, Bool unmap)
{
- if(index_of_area(c->page, c->area) > 0)
- detach_column(c);
- else {
- Area *a = c->page->area[0];
- cext_array_detach((void **)a->client, c, &a->clientsz);
- a->nclient--;
- if(!c->destroyed) {
- if(!unmap) {
- det = (Client **)cext_array_attach((void **)det, c,
- sizeof(Client *), &detsz);
- ndet++;
- unmap_client(c);
- }
- c->rect.x = c->frame.rect.x;
- c->rect.y = c->frame.rect.y;
- reparent_client(c, root, c->rect.x, c->rect.y);
- }
+ if(c->page) {
+ if(index_of_area(c->page, c->area) > 0)
+ detach_column(c);
+ else {
+ Area *a = c->page->area[0];
+ cext_array_detach((void **)a->client, c, &a->clientsz);
+ a->nclient--;
+ if(!c->destroyed) {
+ if(!unmap) {
+ det = (Client **)cext_array_attach((void **)det, c,
+ sizeof(Client *), &detsz);
+ ndet++;
+ unmap_client(c);
+ }
+ c->rect.x = c->frame.rect.x;
+ c->rect.y = c->frame.rect.y;
+ reparent_client(c, root, c->rect.x, c->rect.y);
+ }
+ }
}
c->page = nil;
if(c->destroyed)
@@ -526,3 +537,14 @@ max_client(void *obj, char *arg)
c->maximized = !c->maximized;
}
+int
+index_of_client_id(Area *a, unsigned short id)
+{
+ int i;
+ if(id == NEW_OBJ)
+ return a->nclient;
+ for(i = 0; i < a->nclient; i++)
+ if(a->client[i]->id == id)
+ return i;
+ return -1;
+}
diff --git a/cmd/wm/event.c b/cmd/wm/event.c
@@ -110,7 +110,7 @@ handle_configurerequest(XEvent * e)
ev->value_mask &= ~CWSibling;
if(c) {
- if(c->attached) {
+ if(c->page) {
bw = c->frame.border;
bh = bar_height(c);
}
@@ -135,7 +135,7 @@ handle_configurerequest(XEvent * e)
gravitate(c, bh ? bh : bw, bw, 0);
- if(c->attached) {
+ if(c->page) {
c->frame.rect.x = wc.x = c->rect.x - bw;
c->frame.rect.y = wc.y = c->rect.y - (bh ? bh : bw);
c->frame.rect.width = wc.width = c->rect.width + 2 * bw;
@@ -150,7 +150,7 @@ handle_configurerequest(XEvent * e)
wc.x = ev->x;
wc.y = ev->y;
- if(c && c->attached) {
+ if(c && c->page) {
/* if so, then bw and tabh are already initialized */
wc.x = bw;
wc.y = bh ? bh : bw;
@@ -217,7 +217,7 @@ handle_maprequest(XEvent * e)
c = win_to_client(ev->window);
if(!c)
c = alloc_client(ev->window, &wa);
- if(!c->attached)
+ if(!c->page)
attach_client(c);
}
diff --git a/cmd/wm/fs.c b/cmd/wm/fs.c
@@ -45,7 +45,6 @@
* /1/float/1/ Dclient
* /1/float/1/border Fborder 0..n
* /1/float/1/bar Fbar 0, 1
- * /1/float/1/inc Finc 0, 1
* /1/float/1/name Fname name of client
* /1/float/1/geom Fgeom geometry of client
* /1/float/1/ctl Fctl command interface (client)
@@ -55,7 +54,6 @@
* /1/1/1/1/ Dclient
* /1/1/1/border Fborder 0..n
* /1/1/1/bar Fbar 0, 1
- * /1/1/1/inc Finc 0, 1
* /1/1/1/name Fname name of client
* /1/1/1/geom Fgeom geometry of client
* /1/1/1/ctl Fctl command interface (client)
@@ -448,14 +446,7 @@ type_to_stat(Stat *stat, char *name, Qid *dir)
return mkstat(stat, dir, name, strlen(buf), DMREAD | DMWRITE);
break;
case Finc:
- if(dtyp == Ddefault)
- snprintf(buf, sizeof(buf), "%d", def.inc);
- else {
- idx = cext_strtonum(name, 0, 0xffff, &err);
- if(err)
- return 0;
- snprintf(buf, sizeof(buf), "%d", page[dpg]->area[darea]->client[idx]->inc);
- }
+ snprintf(buf, sizeof(buf), "%d", def.inc);
return mkstat(stat, dir, name, strlen(buf), DMREAD | DMWRITE);
break;
case Fgeom:
@@ -720,10 +711,7 @@ xread(IXPConn *c)
memcpy(p, buf, c->fcall->count);
break;
case Finc:
- if(m->qid.dtype == Ddefault)
- snprintf(buf, sizeof(buf), "%u", def.inc);
- else
- snprintf(buf, sizeof(buf), "%u", page[pg]->area[area]->client[cl]->inc);
+ snprintf(buf, sizeof(buf), "%u", def.inc);
c->fcall->count = strlen(buf);
memcpy(p, buf, c->fcall->count);
break;
@@ -902,12 +890,8 @@ xwrite(IXPConn *c)
errstr = "increment value out of range 0, 1";
return -1;
}
- if(m->qid.dtype == Ddefault)
- def.inc = i;
- else {
- page[pg]->area[area]->client[cl]->inc = i;
- /* TODO: resize client */
- }
+ def.inc = i;
+ /* TODO: resize all clients */
break;
case Fgeom:
if(c->fcall->count > sizeof(buf))
diff --git a/cmd/wm/page.c b/cmd/wm/page.c
@@ -27,9 +27,11 @@ Action page_acttbl[] = {
Page *
alloc_page()
{
+ static unsigned short id = 0;
Page *p = cext_emallocz(sizeof(Page));
Area *a = cext_emallocz(sizeof(Area));
+ p->id = id++;
p->area = (Area **)cext_array_attach((void **)p->area, a, sizeof(Area *), &p->areasz);
p->narea++;
do_pend_fcall("NewPage\n");
@@ -53,9 +55,9 @@ destroy_page(Page *p)
for(i = 0; i < naqueue; i++)
cext_array_detach((void **)aq, p, &aqsz);
- for(i = 0; i < nclient; i++)
- if(client[i]->page == p)
- detach_client(client[i], False);
+ for(i = 0; i < p->narea; i++)
+ destroy_area(p->area[i]);
+ free(p->area);
for(i = 0; (i < npage) && (p != page[i]); i++);
if(sel && (sel == i))
@@ -229,11 +231,13 @@ select_client(void *obj, char *arg)
}
int
-index_of_area(Page *p, Area *a)
+index_of_page_id(unsigned short id)
{
int i;
- for(i = 0; i < p->narea; i++)
- if(p->area[i] == a)
+ if(id == NEW_OBJ)
+ return npage;
+ for(i = 0; i < npage; i++)
+ if(page[i]->id == id)
return i;
return -1;
}
diff --git a/cmd/wm/wm.h b/cmd/wm/wm.h
@@ -47,11 +47,14 @@ enum {
#define ROOT_MASK SubstructureRedirectMask
#define CLIENT_MASK (StructureNotifyMask | PropertyChangeMask)
+#define NEW_OBJ (unsigned short)0xffff
+
typedef struct Area Area;
typedef struct Page Page;
typedef struct Client Client;
struct Area {
+ unsigned short id;
Client **client;
size_t clientsz;
size_t sel;
@@ -60,6 +63,7 @@ struct Area {
};
struct Page {
+ unsigned short id;
Area **area;
size_t areasz;
size_t narea;
@@ -67,6 +71,7 @@ struct Page {
};
struct Client {
+ unsigned short id;
char name[256];
int proto;
unsigned int border;
@@ -74,8 +79,6 @@ struct Client {
Bool inc;
Bool destroyed;
Bool maximized;
- Bool attached;
- Bool managed;
Page *page;
Area *area;
Window win;
@@ -157,6 +160,11 @@ Cursor se_cursor;
unsigned int valid_mask, num_lock_mask;
+/* area.c */
+Area *alloc_area();
+void destroy_area(Area *a);
+int index_of_area(Page *p, Area *a);
+int index_of_area_id(Page *p, unsigned short id);
/* client.c */
Client *alloc_client(Window w, XWindowAttributes *wa);
@@ -179,6 +187,7 @@ void focus_client(Client *c);
Client *win_to_frame(Window w);
void resize_client(Client *c, XRectangle * r, XPoint * pt);
unsigned int bar_height(Client *c);
+int index_of_client_id(Area *a, unsigned short id);
/* event.c */
void init_x_event_handler();
@@ -204,7 +213,7 @@ Page *alloc_page();
void destroy_page(Page *p);
void focus_page(Page *p);
XRectangle *rectangles(unsigned int *num);
-int index_of_area(Page *p, Area *a);
+int index_of_page_id(unsigned short id);
/* column.c */
void arrange_page(Page *p);
diff --git a/cmd/wmiibar.c b/cmd/wmiibar.c
@@ -65,8 +65,6 @@ static char Enomode[] = "mode not supported";
static char Enofunc[] = "function not supported";
static char Enocommand[] = "command 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;
@@ -217,7 +215,7 @@ handle_buttonpress(XButtonPressedEvent * e)
}
static void
-check_x_event(IXPServer *s, IXPConn *c)
+check_x_event(IXPConn *c)
{
XEvent e;
@@ -365,89 +363,82 @@ mkqid(Qid *dir, char *wname, Qid *new)
return 0;
}
-static int
-xversion(IXPConn *c)
+
+static char *
+xversion(IXPConn *c, Fcall *fcall)
{
- 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;
+ if(strncmp(fcall->version, IXP_VERSION, strlen(IXP_VERSION)))
+ return E9pversion;
+ else if(fcall->maxmsg > IXP_MAX_MSG)
+ fcall->maxmsg = IXP_MAX_MSG;
+ fcall->id = RVERSION;
+ ixp_server_respond_fcall(c, fcall);
+ return nil;
}
-static int
-xattach(IXPConn *c)
+static char *
+xattach(IXPConn *c, Fcall *fcall)
{
IXPMap *new = cext_emallocz(sizeof(IXPMap));
new->qid = root_qid;
- new->fid = c->fcall->fid;
+ new->fid = 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;
+ fcall->id = RATTACH;
+ fcall->qid = root_qid;
+ ixp_server_respond_fcall(c, fcall);
+ return nil;
}
-static int
-xwalk(IXPConn *c)
+static char *
+xwalk(IXPConn *c, Fcall *fcall)
{
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) {
+ if(!(m = ixp_server_fid2map(c, fcall->fid)))
+ return Enofid;
+ if(fcall->fid != fcall->newfid && (ixp_server_fid2map(c, fcall->newfid)))
+ return Enofid;
+ if(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;
- }
+ for(nwqid = 0; (nwqid < fcall->nwname)
+ && !mkqid(&dir, fcall->wname[nwqid], &fcall->wqid[nwqid]); nwqid++)
+ dir = fcall->wqid[nwqid];
+ if(!nwqid)
+ return Enofile;
}
/* a fid will only be valid, if the walk was complete */
- if(nwqid == c->fcall->nwname) {
- if(c->fcall->fid != c->fcall->newfid) {
+ if(nwqid == fcall->nwname) {
+ if(fcall->fid != fcall->newfid) {
m = cext_emallocz(sizeof(IXPMap));
- c->map = (IXPMap **)cext_array_attach((void **)c->map, m,
- sizeof(IXPMap *), &c->mapsz);
+ c->map = (IXPMap **)cext_array_attach((void **)c->map,
+ m, sizeof(IXPMap *), &c->mapsz);
}
m->qid = dir;
- m->fid = c->fcall->newfid;
+ m->fid = fcall->newfid;
}
- c->fcall->id = RWALK;
- c->fcall->nwqid = nwqid;
- return 0;
+ fcall->id = RWALK;
+ fcall->nwqid = nwqid;
+ ixp_server_respond_fcall(c, fcall);
+ return nil;
}
-static int
-xopen(IXPConn *c)
+static char *
+xopen(IXPConn *c, Fcall *fcall)
{
- IXPMap *m = ixp_server_fid2map(c, c->fcall->fid);
+ IXPMap *m = ixp_server_fid2map(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 = 256;
- return 0;
+ if(!m)
+ return Enofid;
+ if(!(fcall->mode | IXP_OREAD) && !(fcall->mode | IXP_OWRITE))
+ return Enomode;
+ fcall->id = ROPEN;
+ fcall->qid = m->qid;
+ fcall->iounit = 256;
+ ixp_server_respond_fcall(c, fcall);
+ return nil;
}
static unsigned int
@@ -504,28 +495,21 @@ type_to_stat(Stat *stat, char *name, Qid *dir)
i = 0;
return mkstat(stat, dir, name, 24, DMREAD | DMWRITE);
break;
- default:
- errstr = "invalid stat";
- break;
}
return 0;
}
-static int
-xremove(IXPConn *c)
+static char *
+xremove(IXPConn *c, Fcall *fcall)
{
- IXPMap *m = ixp_server_fid2map(c, c->fcall->fid);
+ IXPMap *m = ixp_server_fid2map(c, fcall->fid);
int i;
- if(!m) {
- errstr = Enofid;
- return -1;
- }
+ if(!m)
+ return Enofid;
i = index_of_id(qpath_id(m->qid.path));
- if(i == -1) {
- errstr = Enofile;
- return -1;
- }
+ if(i == -1)
+ return Enofile;
if((qpath_type(m->qid.path) == Ditem) && i && (i < nitem)) {
Item *it = item[i];
/* clunk */
@@ -534,38 +518,34 @@ xremove(IXPConn *c)
/* now detach the item */
detach_item(it);
free(it);
- c->fcall->id = RREMOVE;
if(iexpand >= nitem)
iexpand = 0;
draw();
- return 0;
+ fcall->id = RREMOVE;
+ ixp_server_respond_fcall(c, fcall);
+ return nil;
}
- errstr = Enoperm;
- return -1;
+ return Enoperm;
}
-static int
-xread(IXPConn *c)
+static char *
+xread(IXPConn *c, Fcall *fcall)
{
Stat stat;
- IXPMap *m = ixp_server_fid2map(c, c->fcall->fid);
- unsigned char *p = c->fcall->data;
+ IXPMap *m = ixp_server_fid2map(c, fcall->fid);
+ unsigned char *p = fcall->data;
unsigned int len;
int i;
char buf[32];
- if(!m) {
- errstr = Enofid;
- return -1;
- }
+ if(!m)
+ return Enofid;
i = index_of_id(qpath_id(m->qid.path));
- if(i == -1) {
- errstr = Enofile;
- return -1;
- }
+ if(i == -1)
+ return Enofile;
- c->fcall->count = 0;
- if(c->fcall->offset) {
+ fcall->count = 0;
+ if(fcall->offset) {
switch (qpath_type(m->qid.path)) {
case Droot:
/* jump to offset */
@@ -577,7 +557,7 @@ xread(IXPConn *c)
for(i = 1; i < nitem; i++) {
snprintf(buf, sizeof(buf), "%u", i);
len += type_to_stat(&stat, buf, &m->qid);
- if(len <= c->fcall->offset)
+ if(len <= fcall->offset)
continue;
break;
}
@@ -585,14 +565,15 @@ xread(IXPConn *c)
for(; i < nitem; i++) {
snprintf(buf, sizeof(buf), "%u", i);
len = type_to_stat(&stat, buf, &m->qid);
- if(c->fcall->count + len > c->fcall->iounit)
+ if(fcall->count + len > fcall->iounit)
break;
- c->fcall->count += len;
+ fcall->count += len;
p = ixp_enc_stat(p, &stat);
}
break;
case Fevent:
- return 1;
+ ixp_server_enqueue_fcall(c, fcall);
+ return nil;
break;
default:
break;
@@ -601,22 +582,22 @@ xread(IXPConn *c)
else {
switch (qpath_type(m->qid.path)) {
case Droot:
- c->fcall->count = type_to_stat(&stat, "ctl", &m->qid);
+ fcall->count = type_to_stat(&stat, "ctl", &m->qid);
p = ixp_enc_stat(p, &stat);
- c->fcall->count += type_to_stat(&stat, "font", &m->qid);
+ fcall->count += type_to_stat(&stat, "font", &m->qid);
p = ixp_enc_stat(p, &stat);
- c->fcall->count += type_to_stat(&stat, "color", &m->qid);
+ fcall->count += type_to_stat(&stat, "color", &m->qid);
p = ixp_enc_stat(p, &stat);
- c->fcall->count += type_to_stat(&stat, "new", &m->qid);
+ fcall->count += type_to_stat(&stat, "new", &m->qid);
p = ixp_enc_stat(p, &stat);
- c->fcall->count += type_to_stat(&stat, "event", &m->qid);
+ fcall->count += type_to_stat(&stat, "event", &m->qid);
p = ixp_enc_stat(p, &stat);
for(i = 1; i < nitem; i++) {
snprintf(buf, sizeof(buf), "%u", i);
len = type_to_stat(&stat, buf, &m->qid);
- if(c->fcall->count + len > c->fcall->iounit)
+ if(fcall->count + len > fcall->iounit)
break;
- c->fcall->count += len;
+ fcall->count += len;
p = ixp_enc_stat(p, &stat);
}
break;
@@ -625,108 +606,100 @@ xread(IXPConn *c)
goto error_xread;
if(i == nitem)
new_item();
- c->fcall->count = type_to_stat(&stat, "color", &m->qid);
+ fcall->count = type_to_stat(&stat, "color", &m->qid);
p = ixp_enc_stat(p, &stat);
- c->fcall->count += type_to_stat(&stat, "data", &m->qid);
+ fcall->count += type_to_stat(&stat, "data", &m->qid);
p = ixp_enc_stat(p, &stat);
break;
case Fctl:
- errstr = Enoperm;
- return -1;
+ return Enoperm;
break;
case Ffont:
- if((c->fcall->count = strlen(font)))
- memcpy(p, font, c->fcall->count);
+ if((fcall->count = strlen(font)))
+ memcpy(p, font, 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;
+ fcall->count = strlen(buf);
+ memcpy(p, buf, fcall->count);
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);
+ if((fcall->count = strlen(item[i]->data)))
+ memcpy(p, item[i]->data, fcall->count);
break;
case Fcolor:
if(i == nitem)
new_item();
if(i >= nitem)
goto error_xread;
- if((c->fcall->count = strlen(item[i]->colstr)))
- memcpy(p, item[i]->colstr, c->fcall->count);
+ if((fcall->count = strlen(item[i]->colstr)))
+ memcpy(p, item[i]->colstr, fcall->count);
+ break;
+ case Fevent:
+ ixp_server_enqueue_fcall(c, fcall);
+ return nil;
break;
default:
error_xread:
- if(!errstr)
- errstr = "invalid read";
- return -1;
+ return "invalid read";
break;
}
}
- c->fcall->id = RREAD;
- return 0;
+ fcall->id = RREAD;
+ ixp_server_respond_fcall(c, fcall);
+ return nil;
}
-static int
-xstat(IXPConn *c)
+static char *
+xstat(IXPConn *c, Fcall *fcall)
{
- IXPMap *m = ixp_server_fid2map(c, c->fcall->fid);
+ IXPMap *m = ixp_server_fid2map(c, fcall->fid);
char *name;
- if(!m) {
- errstr = Enofid;
- return -1;
- }
-
+ if(!m)
+ return Enofid;
name = qid_to_name(&m->qid);
- if(!type_to_stat(&c->fcall->stat, name, &m->qid))
- return -1;
- c->fcall->id = RSTAT;
- return 0;
+ if(!type_to_stat(&fcall->stat, name, &m->qid))
+ return Enofile;
+ fcall->id = RSTAT;
+ ixp_server_respond_fcall(c, fcall);
+ return nil;
}
-static int
-xwrite(IXPConn *c)
+static char *
+xwrite(IXPConn *c, Fcall *fcall)
{
char buf[256];
- IXPMap *m = ixp_server_fid2map(c, c->fcall->fid);
+ IXPMap *m = ixp_server_fid2map(c, fcall->fid);
int i;
- if(!m) {
- errstr = Enofid;
- return -1;
- }
+ if(!m)
+ return Enofid;
i = index_of_id(qpath_id(m->qid.path));
- if(i == -1) {
- errstr = Enofile;
- return -1;
- }
+ if(i == -1)
+ return Enofile;
switch (qpath_type(m->qid.path)) {
case Fctl:
- if(c->fcall->count == 4) {
- memcpy(buf, c->fcall->data, 4);
+ if(fcall->count == 4) {
+ memcpy(buf, fcall->data, 4);
buf[4] = 0;
if(!strncmp(buf, "quit", 5)) {
srv.running = 0;
break;
}
}
- errstr = Enocommand;
- return -1;
+ return Enocommand;
break;
case Ffont:
if(font)
free(font);
- font = cext_emallocz(c->fcall->count + 1);
- memcpy(font, c->fcall->data, c->fcall->count);
+ font = cext_emallocz(fcall->count + 1);
+ memcpy(font, fcall->data, fcall->count);
XFreeFont(dpy, xfont);
xfont = blitz_getfont(dpy, font);
update_geometry();
@@ -734,9 +707,9 @@ xwrite(IXPConn *c)
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;
+ if(fcall->count && fcall->count < 16) {
+ memcpy(buf, fcall->data, fcall->count);
+ buf[fcall->count] = 0;
i = (unsigned short) cext_strtonum(buf, 1, 0xffff, &err);
if(i < nitem) {
iexpand = i;
@@ -745,19 +718,18 @@ xwrite(IXPConn *c)
}
}
}
- errstr = "item not found";
- return -1;
+ return "item not found";
break;
case Fdata:
{
- unsigned int len = c->fcall->count;
+ unsigned int len = 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);
+ memcpy(item[i]->data, fcall->data, len);
item[i]->data[len] = 0;
draw();
}
@@ -765,105 +737,62 @@ xwrite(IXPConn *c)
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]->colstr, c->fcall->data, c->fcall->count);
- item[i]->colstr[c->fcall->count] = 0;
+ if((i >= nitem) || (fcall->count != 24)
+ || (fcall->data[0] != '#') || (fcall->data[8] != '#')
+ || (fcall->data[16] != '#')
+ )
+ return "wrong color format";
+ memcpy(item[i]->colstr, fcall->data, fcall->count);
+ item[i]->colstr[fcall->count] = 0;
blitz_loadcolor(dpy, screen, item[i]->colstr, &item[i]->color);
draw();
break;
default:
error_xwrite:
- if(!errstr)
- errstr = "invalid write";
- return -1;
+ return "invalid write";
break;
}
- c->fcall->id = RWRITE;
- return 0;
+ fcall->id = RWRITE;
+ ixp_server_respond_fcall(c, fcall);
+ return nil;
}
-static int
-xclunk(IXPConn *c)
+static char *
+xclunk(IXPConn *c, Fcall *fcall)
{
- IXPMap *m = ixp_server_fid2map(c, c->fcall->fid);
+ IXPMap *m = ixp_server_fid2map(c, fcall->fid);
- if(!m) {
- errstr = Enofid;
- return -1;
- }
+ if(!m)
+ return Enofid;
cext_array_detach((void **)c->map, m, &c->mapsz);
free(m);
- c->fcall->id = RCLUNK;
+ 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)
+do_fcall(IXPConn *c)
{
+ static Fcall fcall;
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;
+ char *errstr;
+
+ if((msize = ixp_server_receive_fcall(c, &fcall))) {
+ switch(fcall.id) {
+ case TVERSION: errstr = xversion(c, &fcall); break;
+ case TATTACH: errstr = xattach(c, &fcall); break;
+ case TWALK: errstr = xwalk(c, &fcall); break;
+ case TREMOVE: errstr = xremove(c, &fcall); break;
+ case TOPEN: errstr = xopen(c, &fcall); break;
+ case TREAD: errstr = xread(c, &fcall); break;
+ case TWRITE: errstr = xwrite(c, &fcall); break;
+ case TCLUNK: errstr = xclunk(c, &fcall); break;
+ case TSTAT: errstr = xstat(c, &fcall); break;
+ default: errstr = Enofunc; break;
}
+ if(errstr)
+ ixp_server_respond_error(c, &fcall, errstr);
}
- 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 *
@@ -887,53 +816,40 @@ do_pend_fcall(char *event)
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;
+ if(ixp_server_respond_error(c, fcall, Enofid))
+ break;
}
else if(qpath_type(m->qid.path) == Fevent) {
fcall->count = strlen(event);
memcpy(p, event, fcall->count);
fcall->id = RREAD;
+ if(ixp_server_respond_fcall(c, fcall))
+ break;
}
- 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)
+new_ixp_conn(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);
- }
+ if(fd >= 0)
+ ixp_server_open_conn(c->srv, fd, do_fcall, ixp_server_close_conn);
}
-
/* main */
int
main(int argc, char *argv[])
{
int i;
- IXPConn *c;
+ char *errstr;
XSetWindowAttributes wa;
XGCValues gcv;
@@ -973,18 +889,9 @@ main(int argc, char *argv[])
}
/* 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);
+ ixp_server_open_conn(&srv, i, new_ixp_conn, ixp_server_close_conn);
/* 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);
+ ixp_server_open_conn(&srv, ConnectionNumber(dpy), check_x_event, nil);
root_qid.type = IXP_QTDIR;
root_qid.version = 0;
@@ -1035,7 +942,7 @@ main(int argc, char *argv[])
/* cleanup */
for(i = 0; (i < srv.connsz) && srv.conn[i]; i++)
if(srv.conn[i]->close)
- srv.conn[i]->close(&srv, srv.conn[i]);
+ srv.conn[i]->close(srv.conn[i]);
XCloseDisplay(dpy);
return errstr ? 1 : 0;
diff --git a/libixp/ixp.h b/libixp/ixp.h
@@ -206,11 +206,11 @@ struct IXPMap {
struct IXPConn {
int fd;
- void (*read) (IXPServer *, IXPConn *);
- void (*close) (IXPServer *, IXPConn *);
+ IXPServer *srv;
+ void (*read) (IXPConn *);
+ void (*close) (IXPConn *);
IXPMap **map;
size_t mapsz;
- Fcall *fcall;
Fcall **pend;
size_t pendsz;
};
@@ -279,8 +279,15 @@ unsigned int ixp_fcall_to_msg(Fcall *fcall, void *msg, unsigned int msglen);
unsigned int ixp_msg_to_fcall(void *msg, unsigned int msglen, Fcall *fcall);
/* server.c */
+IXPConn *ixp_server_open_conn(IXPServer *s, int fd,
+ void (*read)(IXPConn *c), void (*close)(IXPConn *c));
+void ixp_server_close_conn(IXPConn *c);
char *ixp_server_loop(IXPServer *s);
IXPMap *ixp_server_fid2map(IXPConn *c, unsigned int fid);
+void ixp_server_enqueue_fcall(IXPConn *c, Fcall *fcall);
+unsigned int ixp_server_receive_fcall(IXPConn *c, Fcall *fcall);
+int ixp_server_respond_fcall(IXPConn *c, Fcall *fcall);
+int ixp_server_respond_error(IXPConn *c, Fcall *fcall, char *errstr);
/* socket.c */
int ixp_connect_sock(char *address);
diff --git a/libixp/server.c b/libixp/server.c
@@ -17,6 +17,42 @@
#include "ixp.h"
#include "cext.h"
+static unsigned char *msg[IXP_MAX_MSG];
+
+IXPConn *ixp_server_open_conn(IXPServer *s, int fd, void (*read)(IXPConn *c),
+ void (*close)(IXPConn *c))
+{
+ IXPConn *c = cext_emallocz(sizeof(IXPConn));
+ c->fd = fd;
+ c->srv = s;
+ c->read = read;
+ c->close = close;
+ s->conn = (IXPConn **)cext_array_attach((void **)s->conn, c,
+ sizeof(IXPConn *), &s->connsz);
+ return c;
+}
+
+void
+ixp_server_close_conn(IXPConn *c)
+{
+ size_t i;
+ IXPServer *s = c->srv;
+ 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
prepare_select(IXPServer *s)
{
@@ -37,7 +73,7 @@ handle_conns(IXPServer *s)
for(i = 0; (i < s->connsz) && s->conn[i]; i++)
if(FD_ISSET(s->conn[i]->fd, &s->rd) && s->conn[i]->read)
/* call read handler */
- s->conn[i]->read(s, s->conn[i]);
+ s->conn[i]->read(s->conn[i]);
}
char *
@@ -71,3 +107,49 @@ ixp_server_fid2map(IXPConn *c, unsigned int fid)
return c->map[i];
return nil;
}
+
+void ixp_server_enqueue_fcall(IXPConn *c, Fcall *fcall)
+{
+ c->pend = (Fcall **)cext_array_attach((void **)c->pend, fcall, sizeof(Fcall *), &c->pendsz);
+}
+
+unsigned int
+ixp_server_receive_fcall(IXPConn *c, Fcall *fcall)
+{
+ unsigned int msize;
+ char *errstr = 0;
+ if(!(msize = ixp_recv_message(c->fd, msg, IXP_MAX_MSG, &errstr))) {
+ if(c->close)
+ c->close(c);
+ return 0;
+ }
+ return ixp_msg_to_fcall(msg, IXP_MAX_MSG, fcall);
+}
+
+int
+ixp_server_respond_fcall(IXPConn *c, Fcall *fcall)
+{
+ char *errstr;
+ unsigned int msize = ixp_fcall_to_msg(fcall, msg, IXP_MAX_MSG);
+ if(ixp_send_message(c->fd, msg, msize, &errstr) != msize) {
+ if(c->close)
+ c->close(c);
+ return -1;
+ }
+ return 0;
+}
+
+int
+ixp_server_respond_error(IXPConn *c, Fcall *fcall, char *errstr)
+{
+ unsigned int msize;
+ fcall->id = RERROR;
+ cext_strlcpy(fcall->errstr, errstr, sizeof(fcall->errstr));
+ msize = ixp_fcall_to_msg(fcall, msg, IXP_MAX_MSG);
+ if(ixp_send_message(c->fd, msg, msize, &errstr) != msize) {
+ if(c->close)
+ c->close(c);
+ return -1;
+ }
+ return 0;
+}