various changes in libixp/server.c, cmd/wmiibar.c and added id;s to Page, Client, and Area

This commit is contained in:
Anselm R. Garbe 2006-02-03 17:15:36 +02:00
parent 385860251d
commit 3728e6420f
10 changed files with 395 additions and 330 deletions

View File

@ -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

50
cmd/wm/area.c Normal file
View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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))

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;
}