wmii

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

commit f72c098ecf1768a06e48d92c9c3e44999e557acb
parent 9945dcce024292aa13903299af587c9a0e4900cf
Author: Anselm R. Garbe <garbeam@wmii.de>
Date:   Thu,  8 Jun 2006 10:54:19 +0200

merged Kris' changes


Diffstat:
LICENSE | 1+
cmd/wm/area.c | 220+++++++++++++++++++++++++++++++++++++++----------------------------------------
cmd/wm/bar.c | 124++++++++++++++++++++++++++++++++++++-------------------------------------------
cmd/wm/client.c | 259++++++++++++++++++++++++++++++++++++++++---------------------------------------
cmd/wm/column.c | 161++++++++++++++++++++++++++++++++++++-------------------------------------------
cmd/wm/event.c | 30+++++++++++++++---------------
cmd/wm/frame.c | 93++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
cmd/wm/fs.c | 622++++++++++++++++++++++++++++++++++++++-----------------------------------------
cmd/wm/key.c | 111++++++++++++++++++++++++++++++++-----------------------------------------------
cmd/wm/mouse.c | 24+++++++++++++-----------
cmd/wm/rule.c | 24+++++++++---------------
cmd/wm/view.c | 351+++++++++++++++++++++++++++++++++++++------------------------------------------
cmd/wm/wm.c | 25++++++++++---------------
cmd/wm/wm.h | 129+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
cmd/wm/wmii | 4++--
libcext/Makefile | 2+-
libcext/assert.c | 10++++++++++
libcext/cext.h | 4++++
libixp/ixp.h | 20+++++---------------
libixp/server.c | 66++++++++++++++++++++++++++++++------------------------------------
20 files changed, 1120 insertions(+), 1160 deletions(-)

diff --git a/LICENSE b/LICENSE @@ -3,6 +3,7 @@ MIT/X Consortium License (C)opyright MMIII-MMVI Anselm R. Garbe <garbeam at wmii dot de> (C)opyright MMV-MMVI Georg Neis <gn at wmii dot de> (C)opyright MMVI Sander van Dijk <sander at wmii dot de> +(C)opyright MMVI Kris Maglione <bsdaemon at comcast dot net> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/cmd/wm/area.c b/cmd/wm/area.c @@ -4,35 +4,33 @@ */ #include <stdlib.h> +#include <stdio.h> #include <string.h> #include "wm.h" -static Vector * -vector_of_areas(AreaVector *av) -{ - return (Vector *) av; -} - Area * -create_area(View *v, unsigned int pos, unsigned int w) +create_area(View *v, Area *pos, unsigned int w) { static unsigned short id = 1; - Area *a = nil; + unsigned int area_size; + Area *a, **p = pos ? &pos->next : &v->area; + + for(area_size = 0, a=v->area; a; a=a->next, area_size++); if(!w) { - if(v->area.size > 1) - w = rect.width / v->area.size - 1; + if(area_size > 1) + w = rect.width / area_size - 1; else w = rect.width; } if(w < MIN_COLWIDTH) w = MIN_COLWIDTH; - if(v->area.size >= 2 && (v->area.size - 1) * MIN_COLWIDTH + w > rect.width) + if(area_size >= 2 && (area_size - 1) * MIN_COLWIDTH + w > rect.width) return nil; - if(v->area.size > 1) + if(area_size > 1) scale_view(v, rect.width - w); a = cext_emallocz(sizeof(Area)); a->view = v; @@ -41,92 +39,80 @@ create_area(View *v, unsigned int pos, unsigned int w) a->rect.height = rect.height - brect.height; a->mode = def.colmode; a->rect.width = w; - cext_vattachat(vector_of_areas(&v->area), a, pos); - v->sel = pos; + a->frame = nil; + a->sel = nil; + + a->next = *p; + *p = a; + + v->sel = a; return a; } void destroy_area(Area *a) { - unsigned int i; + Client *c; + Area *t; View *v = a->view; - if(a->frame.size) { + if(a->frame) { fprintf(stderr, "%s", "wmiiwm: fatal, destroying non-empty area\n"); exit(1); } - if(a->frame.data) - free(a->frame.data); - if(v->revert == idx_of_area(a)) - v->revert = 0; - for(i = 0; i < client.size; i++) - if(client.data[i]->revert == a) - client.data[i]->revert = 0; - cext_vdetach(vector_of_areas(&v->area), a); - if(v->sel > 1) - v->sel--; - free(a); -} -int -idx_of_area(Area *a) -{ - int i; - View *v = a->view; - for(i = 0; i < v->area.size; i++) - if(v->area.data[i] == a) - return i; - return -1; -} + if(v->revert == a) + v->revert = nil; -int -idx_of_area_id(View *v, unsigned short id) -{ - int i; - for(i = 0; i < v->area.size; i++) - if(v->area.data[i]->id == id) - return i; - return -1; + for(c=client; c; c=c->next) + if(c->revert == a) + c->revert = nil; + + for(t=v->area; t && t->next != a; t=t->next); + if(t) { + t->next = a->next; + if(v->sel == a) + v->sel = t; + } + free(a); } void select_area(Area *a, char *arg) { Area *new; + unsigned int i; View *v = a->view; - int i = idx_of_area(a); - if(i == -1) - return; - if(i) - v->revert = i; + v->revert = a; if(!strncmp(arg, "toggle", 7)) { - if(i) - i = 0; - else if(v->revert > 0 && v->revert < v->area.size) - i = v->revert; + if(a != v->area) + new = v->area; + else if(v->revert && v->revert != v->area) + new = v->revert; else - i = 1; + new = v->area->next; } else if(!strncmp(arg, "prev", 5)) { - if(i <= 1) + if(a == v->area) return; - else - i--; + for(new=v->area->next; + new && new->next != a; + new=new->next); + if(!new) + new=v->area->next; } else if(!strncmp(arg, "next", 5)) { - if(i > 0 && (i + 1 < v->area.size)) - i++; - else + if(a == v->area) return; + new = a->next ? a->next : a; } else { if(sscanf(arg, "%d", &i) != 1) return; + for(new=view->area; i && new->next; new=new->next, i--); } - new = v->area.data[i]; - if(new->frame.size) - focus_client(new->frame.data[new->sel]->client, True); - v->sel = i; + if(new->sel) + focus_client(new->sel->client, True); + v->sel = new; draw_clients(); } @@ -144,11 +130,12 @@ place_client(Area *a, Client *c) { static unsigned int mx, my; static Bool *field = nil; + Frame *fr; Bool fit = False; BlitzAlign align = CENTER; - unsigned int i, j, k, x, y, maxx, maxy, dx, dy, cx, cy, diff, num = 0; + unsigned int i, j, x, y, maxx, maxy, dx, dy, cx, cy, diff, num = 0; XPoint p1 = {0, 0}, p2 = {0, 0}; - Frame *f = c->frame.data[c->sel]; + Frame *f = c->sel; int snap = rect.height / 66; XRectangle *rects; @@ -173,8 +160,7 @@ place_client(Area *a, Client *c) dx = rect.width / mx; dy = rect.height / my; - for(k = 0; k < a->frame.size; k++) { - Frame *fr = a->frame.data[k]; + for(fr=a->frame; fr; fr=fr->anext) { if(fr == f) { cx = f->rect.width / dx; cy = f->rect.height / dy; @@ -240,27 +226,28 @@ void attach_to_area(Area *a, Client *c, Bool send) { View *v = a->view; - unsigned int h = 0, aidx = idx_of_area(a); + unsigned int h = 0, i; Frame *f; + for(f=a->frame, i=1; f; f=f->anext, i++); - c->floating = !aidx; - if(aidx) { - h = a->rect.height / (a->frame.size + 1); - if(a->frame.size) + c->floating = (a == v->area); + if(!c->floating) { + h = a->rect.height / i; + if(a->frame) scale_column(a, a->rect.height - h); } - if(!send && aidx) { /* column */ + if(!send && !c->floating) { /* column */ unsigned int w = newcolw_of_view(v); - if(v->area.data[1]->frame.size && w) { - a = new_column(v, v->area.size, w); + if(v->area->next->frame && w) { + a = new_column(v, a, w); arrange_view(v); } } f = create_frame(a, c); - if(aidx) { /* column */ + if(!c->floating) { /* column */ f->rect.height = h; arrange_column(a, False); } @@ -274,56 +261,67 @@ void detach_from_area(Area *a, Client *c) { View *v = a->view; - int i; + Frame *f; - for(i = 0; i < c->frame.size; i++) - if(c->frame.data[i]->area == a) { - destroy_frame(c->frame.data[i]); - break; - } + for(f=c->frame; f && f->area != a; f=f->cnext); + if(f) + destroy_frame(f); - i = idx_of_area(a); - if(i && a->frame.size) - arrange_column(a, False); - else { - if(i) { - if(v->area.size > 2) + if(a != a->view->area) { + if(a->frame) + arrange_column(a, False); + else { + if(v->area->next->next) destroy_area(a); - else if(!a->frame.size && v->area.data[0]->frame.size) - v->sel = 0; /* focus floating area if it contains something */ + else if(!a->frame && v->area->frame) + v->sel = v->area; /* focus floating area if it contains something */ arrange_view(v); } - else if(!i && !a->frame.size) { - if(c->trans) { - /* focus area of transient, if possible */ - Client *cl = client_of_win(c->trans); - if(cl && cl->frame.size) { - a = cl->frame.data[cl->sel]->area; - if(a->view == v) - v->sel = idx_of_area(a); - } + } + else if(!a->frame) { + if(c->trans) { + /* focus area of transient, if possible */ + Client *cl = client_of_win(c->trans); + if(cl && cl->frame) { + a = cl->sel->area; + if(a->view == v) + v->sel = a; } - else if(v->area.data[1]->frame.size) - v->sel = 1; /* focus first col as fallback */ } + else if(v->area->next->frame) + v->sel = v->area->next; /* focus first col as fallback */ } } Bool is_of_area(Area *a, Client *c) { - unsigned int i; - for(i = 0; i < a->frame.size; i++) - if(a->frame.data[i]->client == c) + Frame *f; + for(f=a->frame; f; f=f->anext) + if(f->client == c) return True; return False; } +int +idx_of_area(Area *a) +{ + Area *t; + int i = 0; + for(t=a->view->area; t && t != a; t=t->next, i++); + return t ? i : -1; +} + +Area * +area_of_id(View *v, unsigned short id) +{ + Area *a; + for(a=v->area; a && a->id != id; a=a->next); + return a; +} + Client * sel_client_of_area(Area *a) { - if(a) { - return (a->frame.size) ? a->frame.data[a->sel]->client : nil; - } - return nil; + return a && a->sel ? a->sel->client : nil; } diff --git a/cmd/wm/bar.c b/cmd/wm/bar.c @@ -8,43 +8,44 @@ #include "wm.h" -static int -comp_bar(const void *b1, const void *b2) -{ - Bar *bb1 = *(Bar **)b1; - Bar *bb2 = *(Bar **)b2; - return strcmp(bb1->name, bb2->name); -} - -static Vector * -vector_of_bars(BarVector *bv) -{ - return (Vector *) bv; -} +Bar *free_bars = nil; Bar * -create_bar(char *name, Bool intern) +create_bar(char *name) { static unsigned int id = 1; - Bar *b = bar_of_name(name); - + Bar **i, *b = bar_of_name(name);; if(b) return b; - b = cext_emallocz(sizeof(Bar)); + + if(free_bars) { + b = free_bars; + free_bars = b->next; + } + else + b = cext_emallocz(sizeof(Bar)); + b->id = id++; cext_strlcpy(b->name, name, sizeof(b->name)); - cext_strlcpy(b->colstr, def.selcolor, sizeof(b->colstr)); + cext_strlcpy(b->colstr, def.normcolor, sizeof(b->colstr)); b->color = def.norm; - cext_vattach(vector_of_bars(&bar), b); - qsort(bar.data, bar.size, sizeof(Bar *), comp_bar); + + for(i=&bar; *i && (strcmp((*i)->name, name) < 0); i=&(*i)->next); + b->next = *i; + *i = b; + return b; } void destroy_bar(Bar *b) { - cext_vdetach(vector_of_bars(&bar), b); - free(b); + Bar **i; + for(i=&bar; *i && *i != b; i=&(*i)->next); + *i = b->next; + + b->next = free_bars; + free_bars = b; } unsigned int @@ -57,7 +58,10 @@ height_of_bar() void resize_bar() { - unsigned int i, j; + View *v; + Area *a; + Frame *f; + brect = rect; brect.height = height_of_bar(); brect.y = rect.height - brect.height; @@ -68,14 +72,13 @@ resize_bar() DefaultDepth(dpy, screen)); XSync(dpy, False); draw_bar(); - for(i = 0; i < view.size; i++) { - for(j = 1; j < view.data[i]->area.size; j++) { - Area *a = view.data[i]->area.data[j]; + + for(v=view; v; v=v->next) { + for(a = v->area; a; a=a->next) { a->rect.height = rect.height - brect.height; arrange_column(a, False); } - for(j = 0; j < view.data[i]->area.data[0]->frame.size; j++) { - Frame *f = view.data[i]->area.data[0]->frame.data[j]; + for(f=v->area->frame; f; f=f->anext) { resize_client(f->client, &f->rect, False); } } @@ -84,7 +87,8 @@ resize_bar() void draw_bar() { - unsigned int i = 0, w = 0; + unsigned int i = 0, w = 0, size = 0; + Bar *exp = nil; BlitzDraw d = { 0 }; Bar *b = nil; @@ -98,11 +102,10 @@ draw_bar() blitz_drawlabel(dpy, &d); blitz_drawborder(dpy, &d); - if(!bar.size) + if(!bar) goto MapBar; - for(i = 0; (i < bar.size) && (w < brect.width); i++) { - b = bar.data[i]; + for(b=bar; b && (w < brect.width); b=b->next, size++) { b->rect.x = 0; b->rect.y = 0; b->rect.width = brect.height; @@ -112,26 +115,27 @@ draw_bar() w += b->rect.width; } - if(i != bar.size) { /* give all bars same width */ - w = brect.width / bar.size; - for(i = 0; i < bar.size; i++) { - b = bar.data[i]; + if(b) { /* give all bars same width */ + for(; b; b=b->next, size++); + w = brect.width / size; + for(b=bar; b; b=b->next) { b->rect.x = i * w; b->rect.width = w; } } else { /* expand bar properly */ - bar.data[bar.size - 1]->rect.width += (brect.width - w); - for(i = 1; i < bar.size; i++) - bar.data[i]->rect.x = bar.data[i - 1]->rect.x + bar.data[i - 1]->rect.width; + for(exp = bar; exp && exp->next; exp=exp->next); + if(exp) + exp->rect.width += (brect.width - w); + for(b=bar; b->next; b=b->next) + b->next->rect.x = b->rect.x + b->rect.width; } - for(i = 0; i < bar.size; i++) { - b = bar.data[i]; + for(b=bar; b; b=b->next) { d.color = b->color; d.rect = b->rect; d.data = b->data; - if(i == bar.size - 1) + if(b == exp) d.align = EAST; else d.align = CENTER; @@ -143,35 +147,21 @@ MapBar: XSync(dpy, False); } -int -idx_of_bar(Bar *b) -{ - int i; - for(i = 0; i < bar.size; i++) - if(bar.data[i] == b) - return i; - return -1; -} - -int -idx_of_bar_id(unsigned short id) -{ - int i; - for(i = 0; i < bar.size; i++) - if(bar.data[i]->id == id) - return i; - return -1; -} - Bar * bar_of_name(const char *name) { static char buf[256]; - unsigned int i; + Bar *b; cext_strlcpy(buf, name, sizeof(buf)); - for(i = 0; i < bar.size; i++) - if(!strncmp(bar.data[i]->name, name, sizeof(bar.data[i]->name))) - return bar.data[i]; - return nil; + for(b=bar; b && strncmp(b->name, name, sizeof(b->name)); b=b->next); + return b; +} + +Bar * +bar_of_id(unsigned short id) +{ + Bar *b; + for(b=bar; b && b->id != id; b=b->next); + return b; } diff --git a/cmd/wm/client.c b/cmd/wm/client.c @@ -11,12 +11,6 @@ #define CLIENT_MASK (StructureNotifyMask | PropertyChangeMask | EnterWindowMask) -static Vector * -vector_of_clients(ClientVector *cv) -{ - return (Vector *) cv; -} - static void update_client_name(Client *c) { @@ -58,9 +52,10 @@ update_client_name(Client *c) Client * create_client(Window w, XWindowAttributes *wa) { - Client *c = (Client *) cext_emallocz(sizeof(Client)); + Client **t, *c = (Client *) cext_emallocz(sizeof(Client)); XSetWindowAttributes fwa; long msize; + unsigned int i; static unsigned int id = 1; static char buf[256]; @@ -97,8 +92,12 @@ create_client(Window w, XWindowAttributes *wa) CWOverrideRedirect | CWBackPixmap | CWEventMask, &fwa); c->gc = XCreateGC(dpy, c->framewin, 0, 0); XSync(dpy, False); - cext_vattach(vector_of_clients(&client), c); - snprintf(buf, sizeof(buf), "CreateClient %d\n", client.size - 1); + + for(t=&client, i=0; *t; t=&(*t)->next, i++); + c->next = *t; /* *t == nil */ + *t = c; + + snprintf(buf, sizeof(buf), "CreateClient %d\n", i); write_event(buf); return c; } @@ -130,15 +129,14 @@ void focus_client(Client *c, Bool restack) { Client *old = sel_client(); - Frame *f = c->frame.data[c->sel]; + Frame *f = c->sel; Client *old_in_area = sel_client_of_area(f->area); View *v = f->area->view; - int i = idx_of_area(f->area); static char buf[256]; - v->sel = i; - f->area->sel = idx_of_frame(f); - c->floating = !i; + v->sel = f->area; + f->area->sel = f; + c->floating = (f->area == v->area); if(restack) restack_view(v); else { @@ -147,7 +145,7 @@ focus_client(Client *c, Bool restack) update_client_grab(c, True); } - if(i > 0 && f->area->mode == Colstack) + if(!c->floating && f->area->mode == Colstack) arrange_column(f->area, False); XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); if(old && old != old_in_area && old != c) @@ -156,7 +154,7 @@ focus_client(Client *c, Bool restack) draw_client(old_in_area); draw_client(c); XSync(dpy, False); - snprintf(buf, sizeof(buf), "ClientFocus %d\n", idx_of_client_id(c->id)); + snprintf(buf, sizeof(buf), "ClientFocus %d\n", idx_of_client(c)); write_event(buf); } @@ -190,7 +188,7 @@ void configure_client(Client *c) { XConfigureEvent e; - Frame *f = c->frame.data[c->sel]; + Frame *f = c->sel; e.type = ConfigureNotify; e.event = c->win; e.window = c->win; @@ -263,7 +261,7 @@ prop_client(Client *c, XPropertyEvent *e) } if(e->atom == XA_WM_NAME || e->atom == net_atom[NetWMName]) { update_client_name(c); - if(c->frame.size) + if(c->frame) draw_client(c); } } @@ -272,16 +270,18 @@ void draw_client(Client *c) { BlitzDraw d = { 0 }; - Frame *f; + Frame *f, *t; char buf[256]; int fidx; - unsigned int w; + unsigned int w, size; - if(!c->frame.size) + if(!c->frame) return; /* might not have been attached atm */ - f = c->frame.data[c->sel]; - fidx = idx_of_frame(f); + f = c->sel; + for(fidx=0, t=f->area->frame; t && t != f; t=t->anext, fidx++); + for(size=fidx; t; t=t->anext, size++); + d.drawable = c->framewin; d.font = blitzfont; d.gc = c->gc; @@ -307,15 +307,15 @@ draw_client(Client *c) /* mode bar */ d.align = CENTER; snprintf(buf, sizeof(buf), "%s%d/%d", - /* if */ !idx_of_area(f->area) ? "~" : "", - fidx + 1, f->area->frame.size); + /* if */ (f->area == f->area->view->area) ? "~" : "", + fidx + 1, size); w = d.rect.width = d.rect.height + blitz_textwidth(dpy, &blitzfont, buf); if(w > f->rect.width) return; d.rect.x = f->rect.width - d.rect.width; d.data = buf; - if(f->area->sel == fidx) + if(f->area->sel == f) d.color = def.sel; else d.color = def.norm; @@ -428,7 +428,7 @@ manage_client(Client *c) map_client(c); XMapWindow(dpy, c->framewin); XSync(dpy, False); - if(c->frame.data[c->sel]->area->view == view.data[sel]) + if(c->sel->area->view == sel) focus_client(c, False); flush_masked_events(EnterWindowMask); } @@ -442,25 +442,32 @@ dummy_error_handler(Display *dpy, XErrorEvent *error) void destroy_client(Client *c) { - unsigned int i; + View *v; + Client *tc; XGrabServer(dpy); XSetErrorHandler(dummy_error_handler); - if(c->frame.size) { - c->rect.x = c->frame.data[c->sel]->rect.x; - c->rect.y = c->frame.data[c->sel]->rect.y; + if(c->frame) { + c->rect.x = c->sel->rect.x; + c->rect.y = c->sel->rect.y; } - for(i = 0; i < view.size; i++) - detach_from_view(view.data[i], c); + for(v=view; v; v=v->next) + detach_from_view(v, c); unmap_client(c); reparent_client(c, root, c->rect.x, c->rect.y); XFreeGC(dpy, c->gc); XDestroyWindow(dpy, c->framewin); - cext_vdetach(vector_of_clients(&client), c); + if(c==client) + client = c->next; + else { + for(tc=client; tc && tc->next != c; tc=tc->next); + if(tc) + tc->next = c->next; + } update_views(); free(c); @@ -473,18 +480,18 @@ destroy_client(Client *c) Client * sel_client() { - return view.size ? sel_client_of_view(view.data[sel]) : nil; + return sel && sel->sel->sel ? sel->sel->sel->client : nil; } void -match_sizehints(Client *c, XRectangle *r, int aidx, BlitzAlign sticky) +match_sizehints(Client *c, XRectangle *r, Bool floating, BlitzAlign sticky) { XSizeHints *s = &c->size; unsigned int dx = 2 * def.border; unsigned int dy = def.border + height_of_bar(); unsigned int hdiff, wdiff; - if(!aidx && (s->flags & PMinSize)) { + if(floating && (s->flags & PMinSize)) { if(r->width < s->min_width + dx) { wdiff = (s->min_width + dx) - r->width; r->width += wdiff; @@ -498,7 +505,7 @@ match_sizehints(Client *c, XRectangle *r, int aidx, BlitzAlign sticky) r->y -= hdiff; } } - if(!aidx && (s->flags & PMaxSize)) { + if(floating && (s->flags & PMaxSize)) { if(r->width > s->max_width + dx) { wdiff = r->width - (s->max_width + dx); r->width -= wdiff; @@ -546,9 +553,8 @@ match_sizehints(Client *c, XRectangle *r, int aidx, BlitzAlign sticky) void resize_client(Client *c, XRectangle *r, Bool ignore_xcall) { - Frame *f = c->frame.data[c->sel]; - int fidx = idx_of_frame(f); - int aidx = idx_of_area(f->area); + Frame *f = c->sel; + Bool floating = (f->area == f->area->view->area); BlitzAlign stickycorner = 0;; if(f->rect.x != r->x && f->rect.x + f->rect.width == r->x + r->width) stickycorner |= EAST; @@ -560,18 +566,18 @@ resize_client(Client *c, XRectangle *r, Bool ignore_xcall) stickycorner |= NORTH; f->rect = *r; - if((f->area->mode != Colstack) || (f->area->sel == fidx)) - match_sizehints(c, &c->frame.data[c->sel]->rect, aidx, stickycorner); + if((f->area->mode != Colstack) || (f->area->sel == f)) + match_sizehints(c, &c->sel->rect, floating, stickycorner); if(!ignore_xcall) { - if(!aidx && + if(floating && (c->rect.width >= rect.width) && (c->rect.height >= rect.height)) { f->rect.x = -def.border; f->rect.y = -height_of_bar(); } - if(f->area->view == view.data[sel]) + if(f->area->view == sel) XMoveResizeWindow(dpy, c->framewin, f->rect.x, f->rect.y, f->rect.width, f->rect.height); else @@ -581,7 +587,7 @@ resize_client(Client *c, XRectangle *r, Bool ignore_xcall) c->rect.x = def.border; c->rect.y = height_of_bar(); - if((f->area->sel == fidx) || (f->area->mode != Colstack)) { + if((f->area->sel == f) || (f->area->mode != Colstack)) { c->rect.width = f->rect.width - 2 * def.border; c->rect.height = f->rect.height - def.border - height_of_bar(); } @@ -593,47 +599,42 @@ resize_client(Client *c, XRectangle *r, Bool ignore_xcall) void select_client(Client *c, char *arg) { - Frame *f = c->frame.data[c->sel]; + unsigned int i; + Frame *f = c->sel, *r; Area *a = f->area; - int i = idx_of_frame(f); - if(i == -1) - return; - if(!strncmp(arg, "prev", 5)) { - if(!i) - i = a->frame.size - 1; - else - i--; - } else if(!strncmp(arg, "next", 5)) { - if(i + 1 < a->frame.size) - i++; - else - i = 0; - } + + if(!strncmp(arg, "prev", 5)) + for(r=a->frame; r->anext && r->anext != f; r=r->anext); + else if(!strncmp(arg, "next", 5)) + r = f->anext ? f->anext : a->frame; else { if(sscanf(arg, "%d", &i) != 1) return; + for(r=a->frame; i && r->anext; r=r->anext, i--); } - focus_client(a->frame.data[i]->client, True); + focus_client(r->client, True); flush_masked_events(EnterWindowMask); } void newcol_client(Client *c, char *arg) { - Frame *f = c->frame.data[c->sel]; + Frame *f = c->sel; Area *to, *a = f->area; View *v = a->view; - int i = idx_of_area(a); - if(i < 1) + if(a == v->area) + return; + if(!f->anext && f == a->frame) return; if(!strncmp(arg, "prev", 5)) { - to = new_column(v, i, 0); + for(to=v->area; to && to->next != a; to=to->next); + to = new_column(v, to, 0); send_to_area(to, a, c); } else if(!strncmp(arg, "next", 5)) { - to = new_column(v, i + 1, 0); + to = new_column(v, a, 0); send_to_area(to, a, c); } else @@ -644,7 +645,7 @@ newcol_client(Client *c, char *arg) void move_client(Client *c, char *arg) { - Frame *f = c->frame.data[c->sel]; + Frame *f = c->sel; XRectangle new = f->rect; int x, y; @@ -661,7 +662,7 @@ move_client(Client *c, char *arg) void size_client(Client *c, char *arg) { - Frame *f = c->frame.data[c->sel]; + Frame *f = c->sel; XRectangle new = f->rect; int w, h; @@ -669,7 +670,7 @@ size_client(Client *c, char *arg) return; new.width += w; new.height += h; - if(idx_of_area(f->area)) + if(f->area != f->area->view->area) resize_column(f->client, &new, nil); else resize_client(f->client, &new, False); @@ -678,7 +679,7 @@ size_client(Client *c, char *arg) void send_client(Client *c, char *arg) { - Frame *f = c->frame.data[c->sel]; + Frame *f = c->sel, *tf; Area *to, *a = f->area; View *v = a->view; int i = idx_of_area(a), j = idx_of_frame(f); @@ -687,56 +688,54 @@ send_client(Client *c, char *arg) return; if(i && !strncmp(arg, "prev", 5)) { - if(i > 1) - to = v->area.data[i - 1]; - else if(a->frame.size > 1) - to = new_column(v, 1, 0); - else + if(a == v->area) + return; + for(to=v->area->next; to && a != to->next; to=to->next); + if(!to && (f->anext || f != a->frame)) + to=new_column(v, v->area, 0); + if(!to) return; send_to_area(to, a, c); } else if(i && !strncmp(arg, "next", 5)) { - if(i < v->area.size - 1) - to = v->area.data[i + 1]; - else if(a->frame.size > 1) - to = new_column(v, v->area.size, 0); - else + if(a == v->area) + return; + if(!(to = a->next) && (f->anext || f!= a->frame)) + to = new_column(v, a, 0); + if(!to) return; send_to_area(to, a, c); } else if(!strncmp(arg, "toggle", 7)) { - if(i) - to = v->area.data[0]; - else if(c->revert && c->revert != v->area.data[0]) + if(a != v->area) + to = v->area; + else if(c->revert && c->revert != v->area) to = c->revert; else - to = v->area.data[1]; + to = v->area->next; send_to_area(to, a, c); } else if(i && !strncmp(arg, "up", 3)) { - if(j) - i = j - 1; - else + for(tf=a->frame; tf && tf->anext != f; tf=tf->anext); + if(!tf) return; - a->frame.data[j] = a->frame.data[i]; - a->frame.data[i] = f; + remove_frame(f); + insert_frame(tf, f, True); arrange_column(a, False); focus_client(c, True); } else if(i && !strncmp(arg, "down", 5)) { - if(j + 1 < a->frame.size) - i = j + 1; - else + if(!f->anext) return; - a->frame.data[j] = a->frame.data[i]; - a->frame.data[i] = f; + remove_frame(f); + insert_frame(f->anext, f, False); arrange_column(a, False); focus_client(c, True); } else if(i) { if(sscanf(arg, "%d", &j) != 1) return; - to = v->area.data[j]; + for(to=v->area; to && j; to=to->next, j--); send_to_area(to, a, c); } else @@ -747,14 +746,13 @@ send_client(Client *c, char *arg) void resize_all_clients() { - unsigned int i; - for(i = 0; i < client.size; i++) { - Client *c = client.data[i]; - if(c->frame.size && c->frame.data[c->sel]->area) { - if(idx_of_area(c->frame.data[c->sel]->area)) - resize_column(c, &c->frame.data[c->sel]->rect, nil); + Client *c; + for(c = client; c; c=c->next) { + if(c->frame && c->sel->area) { + if(idx_of_area(c->sel->area)) + resize_column(c, &c->sel->rect, nil); else - resize_client(c, &c->frame.data[c->sel]->rect, False); + resize_client(c, &c->sel->rect, False); } } flush_masked_events(EnterWindowMask); @@ -764,48 +762,57 @@ resize_all_clients() void focus(Client *c, Bool restack) { - Frame *f = c->frame.size ? c->frame.data[c->sel] : nil; + Frame *f = c->sel; View *v; if(!f) return; v = f->area->view; - if(view.data[sel] != v) + if(sel != v) focus_view(v); focus_client(c, restack); } +Client * +client_of_id(unsigned short id) +{ + Client *c; + for(c=client; c && c->id != id; c=c->next); + return c; +} + int -idx_of_client_id(unsigned short id) +idx_of_client(Client *c) { - int i; - for(i = 0; i < client.size; i++) - if(client.data[i]->id == id) - return i; - return -1; + Client *cl; + int i = 0; + for(cl=client; cl && cl != c; cl=cl->next, i++); + return cl ? i : -1; } Client * client_of_win(Window w) { - unsigned int i; + Client *c; - for(i = 0; (i < client.size) && client.data[i]; i++) - if(client.data[i]->win == w) - return client.data[i]; - return nil; + for(c=client; c && c->win != w; c=c->next); + return c; +} + +Client * +selected_client() +{ + return sel && sel->sel->sel ? sel->sel->sel->client : nil; } void draw_clients() { - unsigned int i; - for(i = 0; i < client.size; i++) { - Client *c = client.data[i]; - if(c->frame.size && (c->frame.data[c->sel]->area->view == view.data[sel])) + Client *c; + for(c=client; c; c=c->next) + if(c->sel && (c->sel->area->view == sel)) draw_client(c); - } } static Bool @@ -834,8 +841,8 @@ apply_tags(Client *c, const char *tags) if(!strncmp(toks[i], "~", 2)) c->floating = True; else if(!strncmp(toks[i], "!", 2)) { - if(view.size) - apply[j++] = view.data[sel]->name; + if(view) + apply[j++] = sel->name; else apply[j++] = "nil"; } @@ -857,15 +864,13 @@ apply_tags(Client *c, const char *tags) static void match_tags(Client *c, const char *prop) { - unsigned int i; + Rule *r; regmatch_t tmpregm; - for(i = 0; i < trule.size; i++) { - Rule *r = trule.data[i]; + for(r=trule; r; r=r->next) if(!regexec(&r->regex, prop, 1, &tmpregm, 0)) if(!strlen(c->tags) || !strncmp(c->tags, "nil", 4)) apply_tags(c, r->value); - } } void diff --git a/cmd/wm/column.c b/cmd/wm/column.c @@ -35,22 +35,24 @@ column_mode_of_str(char *arg) static void relax_column(Area *a) { - unsigned int i, yoff, h; + unsigned int frame_size, yoff, h; + Frame *f; int hdiff; Bool fallthrough = False; - if(!a->frame.size) + if(!a->frame) return; + for(f=a->frame, frame_size=0; f; f=f->anext, frame_size++); + switch(a->mode) { case Coldefault: - h = a->rect.height; - h /= a->frame.size; + h = a->rect.height / frame_size; if(h < 2 * height_of_bar()) fallthrough = True; break; case Colstack: - h = a->rect.height - (a->frame.size - 1) * height_of_bar(); + h = a->rect.height - frame_size * height_of_bar(); if(h < 3 * height_of_bar()) fallthrough = True; default: @@ -59,8 +61,7 @@ relax_column(Area *a) } if(fallthrough) { - for(i = 0; i < a->frame.size; i++) { - Frame *f = a->frame.data[i]; + for(f=a->frame; f; f=f->anext) { f->rect.x = a->rect.x + (a->rect.width - f->rect.width) / 2; f->rect.y = a->rect.y + (a->rect.height - f->rect.height) / 2; resize_client(f->client, &f->rect, False); @@ -70,8 +71,7 @@ relax_column(Area *a) /* some relaxing from potential increment gaps */ h = 0; - for(i = 0; i < a->frame.size; i++) { - Frame *f = a->frame.data[i]; + for(f=a->frame; f; f=f->anext) { if(a->mode == Colmax) { if(h < f->rect.height) h = f->rect.height; @@ -84,8 +84,7 @@ relax_column(Area *a) if((a->mode == Coldefault) && (hdiff > 0)) { int hx; for(hx = 1; hx < hdiff; hx++) - for(i = 0; (hx < hdiff) && (i < a->frame.size); i++) { - Frame *f = a->frame.data[i]; + for(f=a->frame; f && (hx < hdiff); f=f->anext) { unsigned int tmp = f->rect.height; f->rect.height += hx; resize_client(f->client, &f->rect, True); @@ -95,10 +94,9 @@ relax_column(Area *a) if(hdiff < 0) hdiff = 0; - hdiff /= a->frame.size; + hdiff /= frame_size; yoff = a->rect.y + hdiff / 2; - for(i = 0; i < a->frame.size; i++) { - Frame *f = a->frame.data[i]; + for(f=a->frame; f; f=f->anext) { f->rect.x = a->rect.x + (a->rect.width - f->rect.width) / 2; f->rect.y = yoff; if(a->mode != Colmax) @@ -110,37 +108,37 @@ relax_column(Area *a) void scale_column(Area *a, float h) { - unsigned int i, yoff; + unsigned int yoff, frame_size = 0; + Frame *f; unsigned int min_height = 2 * height_of_bar(); float scale, dy = 0; int hdiff; - if(!a->frame.size) + if(!a->frame) return; - for(i = 0; i < a->frame.size; i++) - dy += a->frame.data[i]->rect.height; + for(f=a->frame; f; f=f->anext, frame_size++) + dy += f->rect.height; + scale = h / dy; yoff = 0; - for(i = 0; i < a->frame.size; i++) { - Frame *f = a->frame.data[i]; + for(f=a->frame; f; f=f->anext) { f->rect.height *= scale; - if(i == a->frame.size - 1) + if(!f->anext) f->rect.height = h - yoff; yoff += f->rect.height; } /* min_height can only be respected when there is enough space; the caller should guarantee this */ - if(a->frame.size * min_height > h) + if(frame_size * min_height > h) return; yoff = 0; - for(i = 0; i < a->frame.size; i++) { - Frame *f = a->frame.data[i]; + for(f=a->frame; f; f=f->anext, frame_size--) { if(f->rect.height < min_height) f->rect.height = min_height; - else if((hdiff = yoff + f->rect.height - h + (a->frame.size - i) * min_height) > 0) + else if((hdiff = yoff + f->rect.height - h + frame_size * min_height) > 0) f->rect.height -= hdiff; - if(i == a->frame.size - 1) + if(!f->anext) f->rect.height = h - yoff; yoff += f->rect.height; } @@ -149,24 +147,26 @@ scale_column(Area *a, float h) void arrange_column(Area *a, Bool dirty) { - unsigned int i, yoff = a->rect.y, h; + unsigned int num_frames = 0, yoff = a->rect.y, h; + Frame *f; unsigned int min_height = 2 * height_of_bar(); - if(!a->frame.size) + if(!a->frame) return; + for(f=a->frame; f; f=f->anext, num_frames++); + switch(a->mode) { case Coldefault: - h = a->rect.height / a->frame.size; + h = a->rect.height / num_frames; if(h < min_height) goto Fallthrough; if(dirty) { - for(i = 0; i < a->frame.size; i++) - a->frame.data[i]->rect.height = h; + for(f=a->frame; f; f=f->anext) + f->rect.height = h; } scale_column(a, a->rect.height); - for(i = 0; i < a->frame.size; i++) { - Frame *f = a->frame.data[i]; + for(f=a->frame; f; f=f->anext) { f->rect.x = a->rect.x; f->rect.y = yoff; f->rect.width = a->rect.width; @@ -175,14 +175,13 @@ arrange_column(Area *a, Bool dirty) } break; case Colstack: - h = a->rect.height - (a->frame.size - 1) * height_of_bar(); + h = a->rect.height - num_frames * height_of_bar(); if(h < 3 * height_of_bar()) goto Fallthrough; - for(i = 0; i < a->frame.size; i++) { - Frame *f = a->frame.data[i]; + for(f=a->frame; f; f=f->anext) { f->rect = a->rect; f->rect.y = yoff; - if(i == a->sel) + if(f == a->sel) f->rect.height = h; else f->rect.height = height_of_bar(); @@ -192,8 +191,7 @@ arrange_column(Area *a, Bool dirty) break; Fallthrough: case Colmax: - for(i = 0; i < a->frame.size; i++) { - Frame *f = a->frame.data[i]; + for(f=a->frame; f; f=f->anext) { f->rect = a->rect; resize_client(f->client, &f->rect, True); } @@ -209,10 +207,9 @@ Fallthrough: static void match_horiz(Area *a, XRectangle *r) { - unsigned int i; + Frame *f; - for(i = 0; i < a->frame.size; i++) { - Frame *f = a->frame.data[i]; + for(f=a->frame; f; f=f->anext) { f->rect.x = r->x; f->rect.width = r->width; resize_client(f->client, &f->rect, False); @@ -226,17 +223,14 @@ drop_resize(Frame *f, XRectangle *new) Area *west = nil, *east = nil, *a = f->area; View *v = a->view; Frame *north = nil, *south = nil; - unsigned int i; unsigned int min_height = 2 * height_of_bar(); - for(i = 1; (i < v->area.size) && (v->area.data[i] != a); i++); + for(west=v->area->next; west && west->next != a; west=west->next); /* first managed area is indexed 1, thus (i > 1) ? ... */ - west = (i > 1) ? v->area.data[i - 1] : nil; - east = i + 1 < v->area.size ? v->area.data[i + 1] : nil; + east = (west && west->next && west->next->next) ? west->next->next : nil; - for(i = 0; (i < a->frame.size) && (a->frame.data[i] != f); i++); - north = i ? a->frame.data[i - 1] : nil; - south = i + 1 < a->frame.size ? a->frame.data[i + 1] : nil; + for(north=a->frame; north && north->anext != f; north=north->anext); + south = (north && north->anext && north->anext->anext) ? north->anext->anext : nil; /* validate (and trim if necessary) horizontal resize */ if(new->width < MIN_COLWIDTH) { @@ -329,22 +323,18 @@ AfterVertical: static Frame * frame_of_point(XPoint *pt) { - unsigned int i, j; Frame *f = nil; - View *v = view.size ? view.data[sel] : nil; + Area *a; + View *v = sel; if(!v) return nil; - for(i = 1; (i < v->area.size) && - !blitz_ispointinrect(pt->x, pt->y, &v->area.data[i]->rect); i++); - if(i < v->area.size) { - Area *a = v->area.data[i]; - for(j = 0; j < a->frame.size && - !blitz_ispointinrect(pt->x, pt->y, &a->frame.data[j]->rect); j++); - if(j < a->frame.size) - f = a->frame.data[j]; - } + for(a=v->area->next; a && !blitz_ispointinrect(pt->x, pt->y, &a->rect); + a=a->next); + if(a) + for(f=a->frame; f && !blitz_ispointinrect(pt->x, pt->y, &f->rect); + f=f->anext); return f; } @@ -353,60 +343,57 @@ drop_move(Frame *f, XRectangle *new, XPoint *pt) { Area *tgt = nil, *src = f->area; View *v = src->view; - unsigned int i; - int fidx; - Frame *ft; + Frame *ft, *tf; if(!pt) return; - for(i = 1; (i < v->area.size) && - !blitz_ispointinrect(pt->x, pt->y, &v->area.data[i]->rect); i++); - if(i < v->area.size) { + for(tgt=v->area->next; tgt && !blitz_ispointinrect(pt->x, pt->y, &tgt->rect); + tgt=tgt->next); + if(tgt) { if(pt->x <= 5) { - if(src->frame.size > 1 || idx_of_area(src) != 1) { - tgt = new_column(v, 1, 0); + if((src->frame && src->frame->anext) || (src != v->area->next)) { + tgt = new_column(v, v->area->next, 0); send_to_area(tgt, src, f->client); } } else if(pt->x >= rect.width - 5) { - if(src->frame.size > 1 || idx_of_area(src) != v->area.size - 1) { - tgt = new_column(v, v->area.size, 0); + if((src->frame && src->frame->anext) || src->next) { + for(tgt=src; tgt->next; tgt=tgt->next); + tgt = new_column(v, tgt, 0); send_to_area(tgt, src, f->client); } } - else if(src != (tgt = v->area.data[i])) { + else if(src != tgt) { Client *c = f->client; Bool before; if(!(ft = frame_of_point(pt)) || (f == ft)) return; - fidx = idx_of_frame(ft); before = pt->y < (ft->rect.y + ft->rect.height / 2); send_to_area(tgt, src, c); - f = c->frame.data[c->sel]; - cext_vdetach(vector_of_frames(&tgt->frame), f); + f = c->sel; + remove_frame(f); if(before) - cext_vattachat(vector_of_frames(&tgt->frame), f, fidx); + insert_frame(tf, f, True); else - cext_vattachat(vector_of_frames(&tgt->frame), f, fidx + 1); + insert_frame(ft, f, False); - tgt->sel = idx_of_frame(f); + tgt->sel = f; arrange_column(tgt, False); } - else { + else { /* !tgt */ if(!(ft = frame_of_point(pt)) || (f == ft)) return; - cext_vdetach(vector_of_frames(&tgt->frame), f); - fidx = idx_of_frame(ft); + remove_frame(f); if(pt->y < (ft->rect.y + ft->rect.height / 2)) - cext_vattachat(vector_of_frames(&tgt->frame), f, fidx); + insert_frame(tf, f, True); else - cext_vattachat(vector_of_frames(&tgt->frame), f, fidx + 1); + insert_frame(ft, f, False); - tgt->sel = idx_of_frame(f); + tgt->sel = f; arrange_column(tgt, False); } } @@ -415,7 +402,7 @@ drop_move(Frame *f, XRectangle *new, XPoint *pt) void resize_column(Client *c, XRectangle *r, XPoint *pt) { - Frame *f = c->frame.data[c->sel]; + Frame *f = c->sel; if((f->rect.width == r->width) && (f->rect.height == r->height)) drop_move(f, r, pt); else @@ -423,9 +410,9 @@ resize_column(Client *c, XRectangle *r, XPoint *pt) } Area * -new_column(View *v, unsigned int pos, unsigned int w) { - Area *a; - if(!(a = create_area(v, pos, w))) +new_column(View *v, Area *pos, unsigned int w) { + Area *a = create_area(v, pos, w); + if(!a) return nil; arrange_view(v); return a; diff --git a/cmd/wm/event.c b/cmd/wm/event.c @@ -67,21 +67,21 @@ static void handle_buttonrelease(XEvent *e) { Client *c; + Bar *b; XButtonPressedEvent *ev = &e->xbutton; static char buf[32]; if(ev->window == barwin) { - unsigned int i; - for(i = 0; i < bar.size; i++) - if(blitz_ispointinrect(ev->x, ev->y, &bar.data[i]->rect)) { + for(b=bar; b; b=b->next) + if(blitz_ispointinrect(ev->x, ev->y, &b->rect)) { snprintf(buf, sizeof(buf), "BarClick %s %d\n", - bar.data[i]->name, ev->button); + b->name, ev->button); write_event(buf); return; } } - else if((c = frame_of_win(ev->window)) && c->frame.size) { + else if((c = frame_of_win(ev->window)) && c->frame) { snprintf(buf, sizeof(buf), "ClientClick %d %d\n", - idx_of_client_id(c->id), ev->button); + idx_of_client(c), ev->button); write_event(buf); } } @@ -121,10 +121,10 @@ handle_configurerequest(XEvent *e) c = client_of_win(ev->window); ev->value_mask &= ~CWSibling; if(c) { - if(c->frame.size && !idx_of_area(c->frame.data[c->sel]->area)) { + if(c->frame && c->sel->area == c->sel->area->view->area) { gravitate_client(c, True); - if(c->frame.size) { + if(c->frame) { if(ev->value_mask & CWX) c->rect.x = ev->x; if(ev->value_mask & CWY) @@ -139,8 +139,8 @@ handle_configurerequest(XEvent *e) gravitate_client(c, False); - if(c->frame.size) { - Frame *f = c->frame.data[c->sel]; + if(c->frame) { + Frame *f = c->sel; if(c->rect.width >= rect.width && c->rect.height >= rect.height) { f->rect.y = wc.y = -height_of_bar(); f->rect.x = wc.x = -def.border; @@ -155,7 +155,7 @@ handle_configurerequest(XEvent *e) wc.border_width = 1; wc.sibling = None; wc.stack_mode = ev->detail; - if(f->area->view != view.data[sel]) + if(f->area->view != sel) wc.x += 2 * rect.width; XConfigureWindow(dpy, c->framewin, ev->value_mask, &wc); configure_client(c); @@ -168,7 +168,7 @@ handle_configurerequest(XEvent *e) wc.width = ev->width; wc.height = ev->height; - if(c && c->frame.size) { + if(c && c->frame) { wc.x = def.border; wc.y = height_of_bar(); wc.width = c->rect.width; @@ -204,11 +204,11 @@ handle_enternotify(XEvent *e) return; if((c = client_of_win(ev->window))) { - Client *old = sel_client_of_view(view.data[sel]); - Frame *f = c->frame.data[c->sel]; + Client *old = selected_client(); + Frame *f = c->sel; Area *a = f->area; if(a->mode == Colmax) - c = a->frame.data[a->sel]->client; + c = a->sel->client; if(c != old) focus(c, False); } diff --git a/cmd/wm/frame.c b/cmd/wm/frame.c @@ -7,17 +7,13 @@ #include "wm.h" -Vector * -vector_of_frames(FrameVector *fv) -{ - return (Vector *) fv; -} - Frame * create_frame(Area *a, Client *c) { static unsigned short id = 1; Frame *f = cext_emallocz(sizeof(Frame)); + Frame **fa = a->sel ? &a->sel->anext : &a->frame; + Frame **fc = c->sel ? &c->sel->cnext : &c->frame; f->id = id++; f->area = a; @@ -25,55 +21,84 @@ create_frame(Area *a, Client *c) f->rect = c->rect; f->rect.width += 2 * def.border; f->rect.height += def.border + height_of_bar(); - cext_vattach(vector_of_frames(&c->frame), f); - a->sel = a->frame.size ? a->sel + 1 : 0; - cext_vattachat(vector_of_frames(&a->frame), f, a->sel); - c->sel = c->frame.size - 1; + a->sel = f; + c->sel = f; + + f->anext = *fa; + *fa = f; + f->cnext = *fc; + *fc = f; + return f; } void +remove_frame(Frame *f) +{ + Area *a = f->area; + Frame **ft = &a->frame; + for(; *ft && *ft != f; ft=&(*ft)->anext); + cext_assert(*ft == f); + *ft = f->anext; +} + +void +insert_frame(Frame *pos, Frame *f, Bool before) +{ + Area *a = f->area; + if(before) { + Frame *ft; + for(ft=a->frame; ft && ft->anext != pos; ft=ft->anext); + pos=ft; + } + Frame **p = pos ? &pos->anext : &a->frame; + f->anext = *p; + *p = f; +} + +void destroy_frame(Frame *f) { Client *c = f->client; Area *a = f->area; + Frame **ft, *pr = nil; + + for(ft=&c->frame; *ft && *ft != f; pr = *ft, ft=&(*ft)->cnext); + cext_assert(*ft == f); + *ft = f->cnext; + if(c->sel == f) + c->sel = pr ? pr : *ft; + + for(ft=&a->frame; *ft && *ft != f; pr = *ft, ft=&(*ft)->anext); + cext_assert(*ft == f); + *ft = f->anext; + if(a->sel == f) + a->sel = pr ? pr : *ft; - cext_vdetach(vector_of_frames(&c->frame), f); - cext_vdetach(vector_of_frames(&a->frame), f); free(f); - if(c->sel > 0) - c->sel--; - if(a->sel > 0) - a->sel--; } -int -idx_of_frame_id(Area *a, unsigned short id) +Frame * +frame_of_id(Area *a, unsigned short id) { - int i; - for(i = 0; i < a->frame.size; i++) - if(a->frame.data[i]->id == id) - return i; - return -1; + Frame *f; + for(f=a->frame; f && f->id != id; f=f->anext); + return f; } int idx_of_frame(Frame *f) { - int i; - Area *a = f->area; - for(i = 0; i < a->frame.size; i++) - if(a->frame.data[i] == f) - return i; - return -1; + Frame *t; + int i = 0; + for(t=f->area->frame; t && t != f; t=t->anext); + return t ? i : -1; } Client * frame_of_win(Window w) { - unsigned int i; - for(i = 0; (i < client.size) && client.data[i]; i++) - if(client.data[i]->framewin == w) - return client.data[i]; - return nil; + Client *c; + for(c=client; c && c->framewin != w; c=c->next); + return c; } diff --git a/cmd/wm/fs.c b/cmd/wm/fs.c @@ -3,6 +3,7 @@ * See LICENSE file for license details. */ +#include <stdarg.h> #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -52,7 +53,6 @@ enum { WMII_IOUNIT = 2048 }; * /ctl FsFctl command interface (root) * /tag FsDtag * /tag/X/ FsDview - * /tag/X/ FsDview * /tag/X/ctl FsFctl command interface (tag) * /tag/X/name FsFname current view name * /tag/X/index FsFindex current view name @@ -68,11 +68,13 @@ enum { WMII_IOUNIT = 2048 }; * /tag/X/1/geom FsFgeom geometry of client * /tag/X/1/ctl FsFctl command interface (client) */ - -Qid root_qid; +const char *dirnames[] = { +}; /* IXP stuff */ +PackedQid root_qid; + /* * Qid->path is calculated related to the index of the associated structure. * i1 is associated to tag, key, global client, or bar @@ -80,74 +82,46 @@ Qid root_qid; * i3 is associated to client * ie /view/sel/ctl is i1id = sel tag id, i2id = sel area id , i3id = 0 (no id) */ -unsigned long long -pack_qpath(unsigned char type, unsigned short i1id, unsigned short i2id, unsigned short i3id) -{ - return ((unsigned long long) type << 48) | ((unsigned long long) i1id << 32) - | ((unsigned long long) i2id << 16) | (unsigned long long) i3id; -} static unsigned char -unpack_type(unsigned long long path) -{ - return (path >> 48) & 0xff; -} - -static unsigned short -unpack_i1id(unsigned long long path) -{ - return (path >> 32) & 0xffff; -} - -static unsigned short -unpack_i2id(unsigned long long path) -{ - return (path >> 16) & 0xffff; -} - -static unsigned short -unpack_i3id(unsigned long long path) +dir_of_qid(PackedQid wqid[IXP_MAX_WELEM], unsigned short qsel) { - return path & 0xffff; + return qsel ? wqid[qsel - 1].ptype : FsDroot; } -static unsigned char -dir_of_qid(Qid wqid[IXP_MAX_WELEM], unsigned short qsel) -{ - return qsel ? unpack_type(wqid[qsel - 1].path) : FsDroot; -} - -static void -unpack_qpath(Qid wqid[IXP_MAX_WELEM], unsigned short qsel, +static Bool +unpack_qpath(PackedQid wqid[IXP_MAX_WELEM], unsigned short qsel, unsigned char *type, int *i1, int *i2, int *i3) { - unsigned short i1id = unpack_i1id(wqid[qsel].path); - unsigned short i2id = unpack_i2id(wqid[qsel].path); - unsigned short i3id = unpack_i3id(wqid[qsel].path); - *type = unpack_type(wqid[qsel].path); + *type = wqid[qsel].ptype; - if(i1id) { + if(wqid[qsel].i1id) { unsigned char dir_type = dir_of_qid(wqid, qsel); if((dir_type == FsDGclient) || (dir_type == FsDclients)) - *i1 = idx_of_client_id(i1id); + *i1 = (int)client_of_id(wqid[qsel].i1id); else { switch(*type) { case FsFdata: case FsFcolors: - case FsDbar: *i1 = idx_of_bar_id(i1id); break; - default: *i1 = idx_of_view_id(i1id); break; + case FsDbar: *i1 = (int)bar_of_id(wqid[qsel].i1id); break; + default: *i1 = (int)view_of_id(wqid[qsel].i1id); break; } } - if(i2id && (*i1 != -1)) { - *i2 = idx_of_area_id(view.data[*i1], i2id); - if(i3id && (*i2 != -1)) - *i3 = idx_of_frame_id(view.data[*i1]->area.data[*i2], i3id); + if(!*i1) + return False; + if(wqid[qsel].i2id) { + if(!(*i2 = (int)area_of_id(VIEW(*i1), wqid[qsel].i2id))) + return False; + if(wqid[qsel].i3id) + if(!(*i3 = (int)frame_of_id(AREA(*i2), wqid[qsel].i3id))) + return False; } } + return True; } static char * -name_of_qid(Qid wqid[IXP_MAX_WELEM], unsigned short qsel) +name_of_qid(PackedQid wqid[IXP_MAX_WELEM], unsigned short qsel) { unsigned char dir_type, type; int i1 = -1, i2 = -1, i3 = -1; @@ -165,33 +139,33 @@ name_of_qid(Qid wqid[IXP_MAX_WELEM], unsigned short qsel) case FsDview: if(dir_type != FsDtag) return nil; - if(i1 == sel) + if(VIEW(i1) == sel) return "sel"; - return view.data[i1]->name; + return VIEW(i1)->name; break; case FsDbar: - if(i1 == -1) + if(!i1) return nil; - return bar.data[i1]->name; + return BAR(i1)->name; break; case FsDarea: - if(i1 == -1 || i2 == -1) + if(!i1 || !i2) return nil; - if(view.data[i1]->sel == i2) + if(VIEW(i1)->sel == AREA(i2)) return "sel"; snprintf(buf, sizeof(buf), "%u", i2); return buf; break; case FsDGclient: - if(i1 == -1) + if(!i1) return nil; - snprintf(buf, sizeof(buf), "%u", i1); + snprintf(buf, sizeof(buf), "%u", idx_of_client(CLIENT(i1))); return buf; break; case FsDclient: - if(i1 == -1 || i2 == -1 || i3 == -1) + if(!i2 || !i3) return nil; - if(view.data[i1]->area.data[i2]->sel == i3) + if(AREA(i2)->sel == FRAME(i3)) return "sel"; snprintf(buf, sizeof(buf), "%u", i3); return buf; @@ -205,32 +179,32 @@ name_of_qid(Qid wqid[IXP_MAX_WELEM], unsigned short qsel) case FsFkeys: return "keys"; break; case FsFcolors: return "colors"; break; case FsFdata: - if(i1 == -1) + if(!i1) return nil; return "data"; break; case FsFctl: return "ctl"; break; case FsFborder: return "border"; break; case FsFgeom: - if((dir_type == FsDclient) && (i1 == -1 || i2 == -1 || i3 == -1)) + if((dir_type == FsDclient) && (!i1 || !i2 || !i3)) return nil; - else if(i1 == -1) + else if(!i1) return nil; return "geom"; break; case FsFtags: - if((dir_type == FsDclient) && (i1 == -1 || i2 == -1 || i3 == -1)) + if((dir_type == FsDclient) && (!i1 || !i2 || !i3)) return nil; - else if((dir_type == FsDGclient) && (i1 == -1)) + else if((dir_type == FsDGclient) && !i1) return nil; return "tags"; break; case FsFprops: case FsFindex: case FsFname: - if((dir_type == FsDclient) && (i1 == -1 || i2 == -1 || i3 == -1)) + if((dir_type == FsDclient) && (!i1 || !i2 || !i3)) return nil; - else if(i1 == -1) + else if(!i1) return nil; switch(type) { case FsFname: @@ -247,7 +221,7 @@ name_of_qid(Qid wqid[IXP_MAX_WELEM], unsigned short qsel) } break; case FsFmode: - if((dir_type == FsDarea) && (i1 == -1 || i2 == -1)) + if((dir_type == FsDarea) && (!i1 || !i2)) return nil; return "mode"; break; @@ -258,7 +232,7 @@ name_of_qid(Qid wqid[IXP_MAX_WELEM], unsigned short qsel) } static unsigned char -type_of_name(Qid wqid[IXP_MAX_WELEM], unsigned short qsel, char *name) +type_of_name(PackedQid wqid[IXP_MAX_WELEM], unsigned short qsel, char *name) { unsigned char dir_type; int i1 = -1, i2 = -1, i3 = -1; @@ -333,12 +307,14 @@ dyndir: return FsLast; } -static Qid * -qid_of_name(Qid wqid[IXP_MAX_WELEM], unsigned short qsel, char *name) +static PackedQid * +qid_of_name(PackedQid wqid[IXP_MAX_WELEM], unsigned short qsel, char *name) { int i1 = -1, i2 = -1, i3 = -1, i; unsigned char dir_type, type; - static Qid new; + Client *c; + static PackedQid new; + memset(&new, 0, sizeof(PackedQid)); unpack_qpath(wqid, qsel, &dir_type, &i1, &i2, &i3); type = type_of_name(wqid, qsel, name); @@ -353,58 +329,64 @@ qid_of_name(Qid wqid[IXP_MAX_WELEM], unsigned short qsel, char *name) case FsDbars: if(dir_type != FsDroot) return nil; - new.type = IXP_QTDIR; - new.path = pack_qpath(type, 0, 0, 0); + new.type= IXP_QTDIR; + new.ptype= type; break; case FsDview: - if((dir_type != FsDtag) || !view.size) + if((dir_type != FsDtag) || !view) return nil; - new.type = IXP_QTDIR; - if(!strncmp(name, "sel", 4)) - new.path = pack_qpath(FsDview, view.data[sel]->id, 0, 0); - else { - View *v; - if(!(v = view_of_name(name))) - return nil; - new.path = pack_qpath(FsDview, v->id, 0, 0); - } + View *v = strncmp(name, "sel", 4) ? view_of_name(name) : sel; + if(!v) + return nil; + new.type= IXP_QTDIR; + new.ptype= FsDview; + new.i1id= v->id; break; case FsDarea: - if(i1 == -1 || dir_type != FsDview) + if(!i1 || dir_type != FsDview) return nil; { - View *p = view.data[i1]; - new.type = IXP_QTDIR; + View *p = VIEW(i1); + new.type= IXP_QTDIR; + new.ptype= FsDarea; + new.i1id= p->id; if(!strncmp(name, "sel", 4)) { - new.path = pack_qpath(FsDarea, p->id, p->area.data[p->sel]->id, 0); + new.i2id= p->sel->id; } else { + Area *a; if(sscanf(name, "%d", &i) != 1) return nil; - if(i >= p->area.size) + for(a=p->area; i && a; a=a->next, i--); + if(!a) return nil; - new.path = pack_qpath(FsDarea, p->id, p->area.data[i]->id, 0); + new.i2id= a->id; } } break; case FsDclient: - if(i1 == -1 || i2 == -1 || dir_type != FsDarea) + if(!i1 || !i2 || dir_type != FsDarea) return nil; { - View *p = view.data[i1]; - Area *a = p->area.data[i2]; - new.type = IXP_QTDIR; + View *p = VIEW(i1); + Area *a = AREA(i2); + new.type= IXP_QTDIR; + new.ptype= FsDclient; + new.i1id= p->id; + new.i2id= a->id; if(!strncmp(name, "sel", 4)) { - if(!a->frame.size) + if(!a->frame) return nil; - new.path = pack_qpath(FsDclient, p->id, a->id, a->frame.data[a->sel]->id); + new.i3id= a->sel->id; } else { + Frame *f; if(sscanf(name, "%d", &i) != 1) return nil; - if(i >= a->frame.size) + for(f=a->frame; f && i; f=f->anext, i--); + if(i) return nil; - new.path = pack_qpath(FsDclient, p->id, a->id, a->frame.data[i]->id); + new.i3id= f->id; } } break; @@ -413,9 +395,12 @@ qid_of_name(Qid wqid[IXP_MAX_WELEM], unsigned short qsel, char *name) return nil; if(sscanf(name, "%d", &i) != 1) return nil; - if(i >= client.size) + for(c=client; i && c; c=c->next, i--); + if(i) return nil; - new.path = pack_qpath(FsDGclient, client.data[i]->id, 0, 0); + new.type= IXP_QTDIR; + new.ptype= FsDGclient; + new.i1id= c->id; break; case FsDbar: if(dir_type != FsDbars) @@ -424,18 +409,19 @@ qid_of_name(Qid wqid[IXP_MAX_WELEM], unsigned short qsel, char *name) Bar *l; if(!(l = bar_of_name(name))) return nil; - new.type = IXP_QTDIR; - new.path = pack_qpath(FsDbar, l->id, 0, 0); + new.type= IXP_QTDIR; + new.ptype= FsDbar; + new.i1id= l->id; } break; case FsFdata: case FsFcolors: - if((i1 == -1) || (dir_type != FsDbar)) + if(!i1 || (dir_type != FsDbar)) return nil; goto Mkfile; break; case FsFmode: - if((dir_type == FsDarea) && (i1 == -1 || i2 == -1)) + if((dir_type == FsDarea) && (!i1 || !i2)) return nil; goto Mkfile; break; @@ -448,9 +434,9 @@ qid_of_name(Qid wqid[IXP_MAX_WELEM], unsigned short qsel, char *name) if(dir_type == FsDroot) return nil; case FsFtags: - if((dir_type == FsDclient) && ((i1 == -1 || i2 == -1 || i3 == -1))) + if((dir_type == FsDclient) && ((!i1 || !i2 || !i3))) return nil; - else if((dir_type == FsDGclient) && (i1 == -1)) + else if((dir_type == FsDGclient) && !i1) return nil; goto Mkfile; break; @@ -467,9 +453,9 @@ qid_of_name(Qid wqid[IXP_MAX_WELEM], unsigned short qsel, char *name) case FsFctl: case FsFevent: Mkfile: + new = wqid[qsel]; new.type = IXP_QTFILE; - new.path = pack_qpath(type, unpack_i1id(wqid[qsel].path), unpack_i2id(wqid[qsel].path), - unpack_i3id(wqid[qsel].path)); + new.ptype = type; break; default: return nil; @@ -479,10 +465,10 @@ Mkfile: } static unsigned int -pack_stat(Stat *stat, Qid wqid[IXP_MAX_WELEM], unsigned short qsel, +pack_stat(Stat *stat, PackedQid wqid[IXP_MAX_WELEM], unsigned short qsel, char *name, unsigned long long length, unsigned int mode) { - Qid *qid; + PackedQid *qid; stat->mode = mode; stat->atime = stat->mtime = time(0); cext_strlcpy(stat->uid, getenv("USER"), sizeof(stat->uid)); @@ -492,13 +478,13 @@ pack_stat(Stat *stat, Qid wqid[IXP_MAX_WELEM], unsigned short qsel, cext_strlcpy(stat->name, name, sizeof(stat->name)); stat->length = length; if((qid = qid_of_name(wqid, qsel ? qsel - 1 : 0, name))) - stat->qid = *qid; + stat->qid = qid->qid; return ixp_sizeof_stat(stat); } static unsigned int -stat_of_name(Stat *stat, char *name, Qid wqid[IXP_MAX_WELEM], unsigned short qsel) +stat_of_name(Stat *stat, char *name, PackedQid wqid[IXP_MAX_WELEM], unsigned short qsel) { unsigned char dir_type, type; int i1 = 0, i2 = 0, i3 = 0; @@ -506,8 +492,7 @@ stat_of_name(Stat *stat, char *name, Qid wqid[IXP_MAX_WELEM], unsigned short qse XRectangle fr; Frame *f; - unpack_qpath(wqid, qsel, &dir_type, &i1, &i2, &i3); - if((i1 == -1) || (i2 == -1) || (i3 == -1)) + if(!unpack_qpath(wqid, qsel, &dir_type, &i1, &i2, &i3)) return 0; type = type_of_name(wqid, qsel, name); @@ -538,27 +523,27 @@ stat_of_name(Stat *stat, char *name, Qid wqid[IXP_MAX_WELEM], unsigned short qse break; case FsFgeom: if(dir_type == FsDclient) - fr = view.data[i1]->area.data[i2]->frame.data[i3]->rect; - else if(client.data[i1]->frame.size) - fr = client.data[i1]->frame.data[client.data[i1]->sel]->rect; + fr = FRAME(i3)->rect; + else if(CLIENT(i1)->frame) + fr = CLIENT(i1)->sel->rect; else - fr = client.data[i1]->rect; + fr = CLIENT(i1)->rect; snprintf(buf, sizeof(buf), "%d %d %d %d", fr.x, fr.y, fr.width, fr.height); return pack_stat(stat, wqid, qsel, name, strlen(buf), IXP_DMREAD | IXP_DMWRITE); break; case FsFprops: if(dir_type == FsDclient) { - f = view.data[i1]->area.data[i2]->frame.data[i3]; + f = FRAME(i3); return pack_stat(stat, wqid, qsel, name, strlen(f->client->props), IXP_DMREAD); } else - return pack_stat(stat, wqid, qsel, name, strlen(client.data[i1]->props), IXP_DMREAD); + return pack_stat(stat, wqid, qsel, name, strlen(CLIENT(i1)->props), IXP_DMREAD); break; case FsFindex: switch(dir_type) { case FsDclient: - f = view.data[i1]->area.data[i2]->frame.data[i3]; - snprintf(buf, sizeof(buf), "%d", idx_of_client_id(f->client->id)); + f = FRAME(i3); + snprintf(buf, sizeof(buf), "%d", idx_of_client(f->client)); break; case FsDarea: snprintf(buf, sizeof(buf), "%d", i2); @@ -571,24 +556,24 @@ stat_of_name(Stat *stat, char *name, Qid wqid[IXP_MAX_WELEM], unsigned short qse break; case FsFname: if(dir_type == FsDclient) { - f = view.data[i1]->area.data[i2]->frame.data[i3]; + f = FRAME(i3); return pack_stat(stat, wqid, qsel, name, strlen(f->client->name), IXP_DMREAD); } else if(dir_type == FsDview) return pack_stat(stat, wqid, qsel, name, - view.size ? strlen(view.data[i1]->name) : 0, IXP_DMREAD); + view ? strlen(VIEW(i1)->name) : 0, IXP_DMREAD); else - return pack_stat(stat, wqid, qsel, name, strlen(client.data[i1]->name), IXP_DMREAD); + return pack_stat(stat, wqid, qsel, name, strlen(CLIENT(i1)->name), IXP_DMREAD); break; case FsFtags: switch(dir_type) { case FsDclient: - f = view.data[i1]->area.data[i2]->frame.data[i3]; + f = FRAME(i3); return pack_stat(stat, wqid, qsel, name, strlen(f->client->tags), IXP_DMREAD | IXP_DMWRITE); break; case FsDGclient: return pack_stat(stat, wqid, qsel, - name, strlen(client.data[i1]->tags), IXP_DMREAD | IXP_DMWRITE); + name, strlen(CLIENT(i1)->tags), IXP_DMREAD | IXP_DMWRITE); break; default: break; @@ -596,11 +581,11 @@ stat_of_name(Stat *stat, char *name, Qid wqid[IXP_MAX_WELEM], unsigned short qse break; case FsFdata: return pack_stat(stat, wqid, qsel, name, - (i1 == bar.size) ? 0 : strlen(bar.data[i1]->data), IXP_DMREAD | IXP_DMWRITE); + !BAR(i1)->next ? 0 : strlen(BAR(i1)->data), IXP_DMREAD | IXP_DMWRITE); break; case FsFmode: return pack_stat(stat, wqid, qsel, name, - strlen(str_of_column_mode(view.data[i1]->area.data[i2]->mode)), + strlen(str_of_column_mode(AREA(i2)->mode)), IXP_DMREAD | IXP_DMWRITE); break; case FsFcolors: @@ -625,6 +610,25 @@ stat_of_name(Stat *stat, char *name, Qid wqid[IXP_MAX_WELEM], unsigned short qse return 0; } +static unsigned int +stat_of_names(unsigned char **p, PackedQid wqid[IXP_MAX_WELEM], unsigned short qsel, ...) +{ + va_list ap; + char *str; + unsigned int n = 0; + Stat stat; + + va_start(ap, qsel); + + while((str = va_arg(ap, char *))) { + n += stat_of_name(&stat, str, wqid, qsel); + *p = ixp_pack_stat(*p, &stat); + } + + va_end(ap); + return n; +} + static char * xversion(IXPConn *c, Fcall *fcall) { @@ -641,8 +645,9 @@ static char * xattach(IXPConn *c, Fcall *fcall) { IXPMap *new = cext_emallocz(sizeof(IXPMap)); - cext_vattach(ixp_vector_of_maps(&c->map), new); - new->wqid[0] = root_qid; + new->next=c->map; + c->map=new; + new->wqid[0] = root_qid.qid; new->nwqid = 1; new->fid = fcall->fid; fcall->id = RATTACH; @@ -656,7 +661,7 @@ xwalk(IXPConn *c, Fcall *fcall) { IXPMap *m; unsigned int qsel, nwqid; - Qid wqid[IXP_MAX_WELEM], *qid; + PackedQid wqid[IXP_MAX_WELEM], *qid; if(!(m = ixp_server_fid2map(c, fcall->fid))) return Enofile; @@ -664,7 +669,7 @@ xwalk(IXPConn *c, Fcall *fcall) return Efidinuse; for(qsel = 0; qsel < m->nwqid; qsel++) - wqid[qsel] = m->wqid[qsel]; + wqid[qsel].qid = m->wqid[qsel]; if(qsel) qsel--; for(nwqid = 0; nwqid < fcall->nwname; nwqid++) { @@ -681,7 +686,7 @@ xwalk(IXPConn *c, Fcall *fcall) break; qsel++; } - fcall->wqid[nwqid] = wqid[qsel] = *qid; + fcall->wqid[nwqid] = wqid[qsel].qid = qid->qid; } if(fcall->nwname && !nwqid) @@ -692,10 +697,11 @@ xwalk(IXPConn *c, Fcall *fcall) unsigned int i; if(fcall->fid != fcall->newfid) { m = cext_emallocz(sizeof(IXPMap)); - cext_vattach(ixp_vector_of_maps(&c->map), m); + m->next=c->map; + c->map=m; } for(i = 0; i <= qsel; i++) - m->wqid[i] = wqid[i]; + m->wqid[i] = wqid[i].qid; m->nwqid = qsel + 1; m->sel = qsel; m->fid = fcall->newfid; @@ -710,7 +716,7 @@ static char * xcreate(IXPConn *c, Fcall *fcall) { IXPMap *m = ixp_server_fid2map(c, fcall->fid); - Qid *qid; + PackedQid *qid = (PackedQid *)&m->wqid[m->sel]; unsigned char type; if(!(fcall->mode | IXP_OWRITE)) @@ -719,18 +725,21 @@ xcreate(IXPConn *c, Fcall *fcall) return Enofile; if(!strncmp(fcall->name, ".", 2) || !strncmp(fcall->name, "..", 3)) return "illegal file name"; - type = unpack_type(m->wqid[m->sel].path); + + type = qid->ptype; switch(type) { case FsDbars: - create_bar(fcall->name, False); + create_bar(fcall->name); break; default: return Enofile; break; } - if(!(qid = qid_of_name(m->wqid, m->sel, fcall->name))) + + if(!(qid = qid_of_name((PackedQid *)&m->wqid, m->sel, fcall->name))) return Enofile; - m->wqid[m->nwqid++] = fcall->qid = *qid; + + m->wqid[m->nwqid++] = fcall->qid = qid->qid; m->sel++; fcall->id = RCREATE; fcall->iounit = WMII_IOUNIT; @@ -758,24 +767,29 @@ xopen(IXPConn *c, Fcall *fcall) static char * xremove(IXPConn *c, Fcall *fcall) { - IXPMap *m = ixp_server_fid2map(c, fcall->fid); + IXPMap *t, *m = ixp_server_fid2map(c, fcall->fid); unsigned char type; int i1 = 0, i2 = 0, i3 = 0; if(!m) return Enofile; - unpack_qpath(m->wqid, m->sel, &type, &i1, &i2, &i3); - if((i1 == -1) || (i2 == -1) || (i3 == -1)) + if(!unpack_qpath((PackedQid *)&m->wqid, m->sel, &type, &i1, &i2, &i3)) return Enofile; if(type != FsDbar) return Enoperm; /* clunk */ - cext_vdetach(ixp_vector_of_maps(&c->map), m); + if(c->map == m) + c->map = m->next; + else { + for(t=c->map; t && t->next != m; t=t->next); + if(t) + t->next = m->next; + } free(m); switch(type) { case FsDbar: { - Bar *b = bar.data[i1]; + Bar *b = BAR(i1); destroy_bar(b); draw_bar(); } @@ -793,6 +807,12 @@ xread(IXPConn *c, Fcall *fcall) { Stat stat; IXPMap *m = ixp_server_fid2map(c, fcall->fid); + PackedQid *pwqid = (PackedQid *)&m->wqid; + View *v; + Frame *f; + Area *a; + Client *cl; + Bar *b; int i1 = 0, i2 = 0, i3 = 0; unsigned int i, len; unsigned char dir_type, type, *p = fcall->data; @@ -801,10 +821,9 @@ xread(IXPConn *c, Fcall *fcall) if(!m) return Enofile; - unpack_qpath(m->wqid, m->sel, &type, &i1, &i2, &i3); - if((i1 == -1) || (i2 == -1) || (i3 == -1)) + if(!unpack_qpath(pwqid, m->sel, &type, &i1, &i2, &i3)) return Enofile; - dir_type = dir_of_qid(m->wqid, m->sel); + dir_type = dir_of_qid(pwqid, m->sel); fcall->count = 0; if(fcall->offset) { @@ -812,17 +831,17 @@ xread(IXPConn *c, Fcall *fcall) case FsDtag: /* jump to offset */ len = 0; - if(view.size) - len += stat_of_name(&stat, "sel", m->wqid, m->sel); - for(i = 0; i < view.size; i++) { - len += stat_of_name(&stat, view.data[i]->name, m->wqid, m->sel); + if(view) + len += stat_of_name(&stat, "sel", pwqid, m->sel); + for(v=view; v; v=v->next) { + len += stat_of_name(&stat, v->name, pwqid, m->sel); if(len <= fcall->offset) continue; break; } /* offset found, proceeding */ - for(; i < view.size; i++) { - len = stat_of_name(&stat, view.data[i]->name, m->wqid, m->sel); + for(; v; v=v->next) { + len = stat_of_name(&stat, v->name, pwqid, m->sel); if(fcall->count + len > fcall->iounit) break; fcall->count += len; @@ -832,17 +851,17 @@ xread(IXPConn *c, Fcall *fcall) case FsDclients: /* jump to offset */ len = 0; - for(i = 0; i < client.size; i++) { + for(cl=client, i=0; cl; cl=cl->next, i++) { snprintf(buf, sizeof(buf), "%u", i); - len += stat_of_name(&stat, buf, m->wqid, m->sel); + len += stat_of_name(&stat, buf, pwqid, m->sel); if(len <= fcall->offset) continue; break; } /* offset found, proceeding */ - for(; i < client.size; i++) { + for(; cl; cl=cl->next, i++) { snprintf(buf, sizeof(buf), "%u", i); - len = stat_of_name(&stat, buf, m->wqid, m->sel); + len = stat_of_name(&stat, buf, pwqid, m->sel); if(fcall->count + len > fcall->iounit) break; fcall->count += len; @@ -852,15 +871,15 @@ xread(IXPConn *c, Fcall *fcall) case FsDbars: /* jump to offset */ len = 0; - for(i = 0; i < bar.size; i++) { - len += stat_of_name(&stat, bar.data[i]->name, m->wqid, m->sel); + for(b=bar; b; b=b->next) { + len += stat_of_name(&stat, b->name, pwqid, m->sel); if(len <= fcall->offset) continue; break; } /* offset found, proceeding */ - for(; i < bar.size; i++) { - len = stat_of_name(&stat, bar.data[i]->name, m->wqid, m->sel); + for(; b; b=b->next) { + len = stat_of_name(&stat, b->name, pwqid, m->sel); if(fcall->count + len > fcall->iounit) break; fcall->count += len; @@ -870,22 +889,22 @@ xread(IXPConn *c, Fcall *fcall) case FsDview: /* jump to offset */ len = 0; - if(view.size) { - len = stat_of_name(&stat, "name", m->wqid, m->sel); - len += stat_of_name(&stat, "ctl", m->wqid, m->sel); - if(view.data[i1]->area.size) - len += stat_of_name(&stat, "sel", m->wqid, m->sel); - for(i = 0; i < view.data[i1]->area.size; i++) { + if(view) { + len = stat_of_name(&stat, "name", pwqid, m->sel); + len += stat_of_name(&stat, "ctl", pwqid, m->sel); + if(VIEW(i1)->area) + len += stat_of_name(&stat, "sel", pwqid, m->sel); + for(a=VIEW(i1)->area, i=0; a; a=a->next, i++) { snprintf(buf, sizeof(buf), "%u", i); - len += stat_of_name(&stat, buf, m->wqid, m->sel); + len += stat_of_name(&stat, buf, pwqid, m->sel); if(len <= fcall->offset) continue; break; } /* offset found, proceeding */ - for(; i < view.data[i1]->area.size; i++) { + for(; a; a=a->next, i++) { snprintf(buf, sizeof(buf), "%u", i); - len = stat_of_name(&stat, buf, m->wqid, m->sel); + len = stat_of_name(&stat, buf, pwqid, m->sel); if(fcall->count + len > fcall->iounit) break; fcall->count += len; @@ -895,23 +914,23 @@ xread(IXPConn *c, Fcall *fcall) break; case FsDarea: /* jump to offset */ - len = stat_of_name(&stat, "ctl", m->wqid, m->sel); - len += stat_of_name(&stat, "index", m->wqid, m->sel); + len = stat_of_name(&stat, "ctl", pwqid, m->sel); + len += stat_of_name(&stat, "index", pwqid, m->sel); if(i2) - len += stat_of_name(&stat, "mode", m->wqid, m->sel); - if(view.data[i1]->area.data[i2]->frame.size) - len += stat_of_name(&stat, "sel", m->wqid, m->sel); - for(i = 0; i < view.data[i1]->area.data[i2]->frame.size; i++) { + len += stat_of_name(&stat, "mode", pwqid, m->sel); + if(AREA(i2)->frame) + len += stat_of_name(&stat, "sel", pwqid, m->sel); + for(f=AREA(i2)->frame, i=0; f; f=f->anext, i++) { snprintf(buf, sizeof(buf), "%u", i); - len += stat_of_name(&stat, buf, m->wqid, m->sel); + len += stat_of_name(&stat, buf, pwqid, m->sel); if(len <= fcall->offset) continue; break; } /* offset found, proceeding */ - for(; i < view.data[i1]->area.data[i2]->frame.size; i++) { + for(; f; f=f->anext, i++) { snprintf(buf, sizeof(buf), "%u", i); - len = stat_of_name(&stat, buf, m->wqid, m->sel); + len = stat_of_name(&stat, buf, pwqid, m->sel); if(fcall->count + len > fcall->iounit) break; fcall->count += len; @@ -972,30 +991,20 @@ xread(IXPConn *c, Fcall *fcall) else { switch (type) { case FsDroot: - fcall->count = stat_of_name(&stat, "ctl", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "event", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "def", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "bar", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - if(view.size) { - fcall->count += stat_of_name(&stat, "tag", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); + fcall->count = stat_of_names(&p, pwqid, m->sel, "ctl", "event", "def", "bar", nil); + if(view) { + fcall->count += stat_of_names(&p, pwqid, m->sel, "tag", nil); } - if(client.size) { - fcall->count += stat_of_name(&stat, "client", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); + if(client) { + fcall->count += stat_of_names(&p, pwqid, m->sel, "client", nil); } break; case FsDtag: - if(view.size) { - fcall->count = stat_of_name(&stat, "sel", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); + if(view) { + fcall->count += stat_of_names(&p, pwqid, m->sel, "sel", nil); } - for(i = 0; i < view.size; i++) { - len = stat_of_name(&stat, view.data[i]->name, m->wqid, m->sel); + for(v=view; v; v=v->next) { + len = stat_of_name(&stat, v->name, pwqid, m->sel); if(fcall->count + len > fcall->iounit) break; fcall->count += len; @@ -1003,9 +1012,9 @@ xread(IXPConn *c, Fcall *fcall) } break; case FsDclients: - for(i = 0; i < client.size; i++) { + for(cl=client, i=0; cl; cl=cl->next, i++) { snprintf(buf, sizeof(buf), "%u", i); - len = stat_of_name(&stat, buf, m->wqid, m->sel); + len = stat_of_name(&stat, buf, pwqid, m->sel); if(fcall->count + len > fcall->iounit) break; fcall->count += len; @@ -1013,8 +1022,8 @@ xread(IXPConn *c, Fcall *fcall) } break; case FsDbars: - for(i = 0; i < bar.size; i++) { - len = stat_of_name(&stat, bar.data[i]->name, m->wqid, m->sel); + for(b=bar; b; b=b->next) { + len = stat_of_name(&stat, b->name, pwqid, m->sel); if(fcall->count + len > fcall->iounit) break; fcall->count += len; @@ -1022,44 +1031,23 @@ xread(IXPConn *c, Fcall *fcall) } break; case FsDbar: - if(i1 >= bar.size) + if(!i1) return Enofile; - fcall->count = stat_of_name(&stat, "colors", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "data", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); + fcall->count = stat_of_names(&p, pwqid, m->sel, "colors", "data", nil); break; case FsDdef: - fcall->count = stat_of_name(&stat, "border", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "selcolors", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "normcolors", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "font", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "keys", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "tagrules", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "grabmod", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "colrules", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); + fcall->count = stat_of_names(&p, pwqid, m->sel, "border", "selcolors", + "normcolors", "font", "keys", "tagrules", "grabmod", "colrules", nil); break; case FsDview: - if(view.size) { - fcall->count = stat_of_name(&stat, "name", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "ctl", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - if(view.data[i1]->area.size) { - fcall->count += stat_of_name(&stat, "sel", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); + if(view) { + fcall->count = stat_of_names(&p, pwqid, m->sel, "name", "ctl", nil); + if(VIEW(i1)->area) { + fcall->count += stat_of_names(&p, pwqid, m->sel, "sel", nil); } - for(i = 0; i < view.data[i1]->area.size; i++) { + for(a=VIEW(i1)->area, i=0; a; a=a->next, i++) { snprintf(buf, sizeof(buf), "%u", i); - len = stat_of_name(&stat, buf, m->wqid, m->sel); + len = stat_of_name(&stat, buf, pwqid, m->sel); if(fcall->count + len > fcall->iounit) break; fcall->count += len; @@ -1068,21 +1056,16 @@ xread(IXPConn *c, Fcall *fcall) } break; case FsDarea: - fcall->count = stat_of_name(&stat, "ctl", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "index", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); + fcall->count = stat_of_names(&p, pwqid, m->sel, "ctl", "index", nil); if(i2) { - fcall->count += stat_of_name(&stat, "mode", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); + fcall->count += stat_of_names(&p, pwqid, m->sel, "mode", nil); } - if(view.data[i1]->area.data[i2]->frame.size) { - fcall->count += stat_of_name(&stat, "sel", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); + if(AREA(i2)->frame) { + fcall->count += stat_of_names(&p, pwqid, m->sel, "sel", nil); } - for(i = 0; i < view.data[i1]->area.data[i2]->frame.size; i++) { + for(f=AREA(i2)->frame, i=0; f; f=f->anext, i++) { snprintf(buf, sizeof(buf), "%u", i); - len = stat_of_name(&stat, buf, m->wqid, m->sel); + len = stat_of_name(&stat, buf, pwqid, m->sel); if(fcall->count + len > fcall->iounit) break; fcall->count += len; @@ -1091,18 +1074,8 @@ xread(IXPConn *c, Fcall *fcall) break; case FsDGclient: case FsDclient: - fcall->count = stat_of_name(&stat, "props", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "name", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "index", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "tags", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "geom", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); - fcall->count += stat_of_name(&stat, "ctl", m->wqid, m->sel); - p = ixp_pack_stat(p, &stat); + fcall->count = stat_of_names(&p, pwqid, m->sel, "props", "name", + "indes", "tags", "geom", "ctl", nil); break; case FsFctl: return Enoperm; @@ -1119,30 +1092,30 @@ xread(IXPConn *c, Fcall *fcall) break; case FsFgeom: if(dir_type == FsDclient) - fr = view.data[i1]->area.data[i2]->frame.data[i3]->rect; - else if(client.data[i1]->frame.size) - fr = client.data[i1]->frame.data[client.data[i1]->sel]->rect; + fr = FRAME(i3)->rect; + else if(CLIENT(i1)->frame) + fr = CLIENT(i1)->sel->rect; else - fr = client.data[i1]->rect; + fr = CLIENT(i1)->rect; snprintf(buf, sizeof(buf), "%d %d %d %d", fr.x, fr.y, fr.width, fr.height); fcall->count = strlen(buf); memcpy(p, buf, fcall->count); break; case FsFprops: if(dir_type == FsDclient) { - if((fcall->count = strlen(view.data[i1]->area.data[i2]->frame.data[i3]->client->props))) - memcpy(p, view.data[i1]->area.data[i2]->frame.data[i3]->client->props, fcall->count); + if((fcall->count = strlen(FRAME(i3)->client->props))) + memcpy(p, FRAME(i3)->client->props, fcall->count); } else { - if((fcall->count = strlen(client.data[i1]->props))) - memcpy(p, client.data[i1]->props, fcall->count); + if((fcall->count = strlen(CLIENT(i1)->props))) + memcpy(p, CLIENT(i1)->props, fcall->count); } break; case FsFindex: switch(dir_type) { case FsDclient: snprintf(buf, sizeof(buf), "%d", - idx_of_client_id(view.data[i1]->area.data[i2]->frame.data[i3]->client->id)); + idx_of_client(FRAME(i3)->client)); break; case FsDarea: snprintf(buf, sizeof(buf), "%d", i2); @@ -1156,46 +1129,46 @@ xread(IXPConn *c, Fcall *fcall) break; case FsFname: if(dir_type == FsDclient) { - if((fcall->count = strlen(view.data[i1]->area.data[i2]->frame.data[i3]->client->name))) - memcpy(p, view.data[i1]->area.data[i2]->frame.data[i3]->client->name, fcall->count); + if((fcall->count = strlen(FRAME(i3)->client->name))) + memcpy(p, FRAME(i3)->client->name, fcall->count); } else if(dir_type == FsDview) { - if((fcall->count = strlen(view.data[i1]->name))) - memcpy(p, view.data[i1]->name, fcall->count); + if((fcall->count = strlen(VIEW(i1)->name))) + memcpy(p, VIEW(i1)->name, fcall->count); } else { - if((fcall->count = strlen(client.data[i1]->name))) - memcpy(p, client.data[i1]->name, fcall->count); + if((fcall->count = strlen(CLIENT(i1)->name))) + memcpy(p, CLIENT(i1)->name, fcall->count); } break; case FsFtags: switch(dir_type) { case FsDclient: { - Client *c = view.data[i1]->area.data[i2]->frame.data[i3]->client; + Client *c = FRAME(i3)->client; if((fcall->count = strlen(c->tags))) memcpy(p, c->tags, fcall->count); } break; case FsDGclient: - if((fcall->count = strlen(client.data[i1]->tags))) - memcpy(p, client.data[i1]->tags, fcall->count); + if((fcall->count = strlen(CLIENT(i1)->tags))) + memcpy(p, CLIENT(i1)->tags, fcall->count); break; default: break; } break; case FsFdata: - if(i1 >= bar.size) + if(!i1) return Enofile; - if((fcall->count = strlen(bar.data[i1]->data))) - memcpy(p, bar.data[i1]->data, fcall->count); + if((fcall->count = strlen(BAR(i1)->data))) + memcpy(p, BAR(i1)->data, fcall->count); break; case FsFcolors: - if(i1 >= bar.size) + if(!i1) return Enofile; - if((fcall->count = strlen(bar.data[i1]->colstr))) - memcpy(p, bar.data[i1]->colstr, fcall->count); + if((fcall->count = strlen(BAR(i1)->colstr))) + memcpy(p, BAR(i1)->colstr, fcall->count); break; case FsFselcolors: if((fcall->count = strlen(def.selcolor))) @@ -1242,7 +1215,7 @@ xread(IXPConn *c, Fcall *fcall) break; case FsFmode: snprintf(buf, sizeof(buf), "%s", - str_of_column_mode(view.data[i1]->area.data[i2]->mode)); + str_of_column_mode(AREA(i2)->mode)); fcall->count = strlen(buf); memcpy(p, buf, fcall->count); break; @@ -1264,9 +1237,9 @@ xstat(IXPConn *c, Fcall *fcall) if(!m) return Enofile; - if(!(name = name_of_qid(m->wqid, m->sel))) + if(!(name = name_of_qid((PackedQid *)&m->wqid, m->sel))) return Enofile; - if(!stat_of_name(&fcall->stat, name, m->wqid, m->sel ? m->sel - 1 : 0)) + if(!stat_of_name(&fcall->stat, name, (PackedQid *)&m->wqid, m->sel ? m->sel - 1 : 0)) return Enofile; fcall->id = RSTAT; ixp_server_respond_fcall(c, fcall); @@ -1286,10 +1259,9 @@ xwrite(IXPConn *c, Fcall *fcall) if(!m) return Enofile; - unpack_qpath(m->wqid, m->sel, &type, &i1, &i2, &i3); - if((i1 == -1) || (i2 == -1) || (i3 == -1)) + if(!unpack_qpath((PackedQid *)&m->wqid, m->sel, &type, &i1, &i2, &i3)) return Enofile; - dir_type = dir_of_qid(m->wqid, m->sel); + dir_type = dir_of_qid((PackedQid *)&m->wqid, m->sel); switch(type) { case FsFctl: @@ -1308,24 +1280,23 @@ xwrite(IXPConn *c, Fcall *fcall) break; case FsDview: if(!strncmp(buf, "select ", 7)) { - if(view.size) - select_area(view.data[i1]->area.data[view.data[i1]->sel], - &buf[7]); + if(view) + select_area(VIEW(i1)->sel, &buf[7]); } else return Enocommand; break; case FsDarea: if(!strncmp(buf, "select ", 7)) { - Area *a = view.data[i1]->area.data[i2]; - if(a->frame.size) - select_client(a->frame.data[a->sel]->client, &buf[7]); + Area *a = AREA(i2); + if(a->frame) + select_client(a->sel->client, &buf[7]); } else return Enocommand; break; case FsDclient: - f = view.data[i1]->area.data[i2]->frame.data[i3]; + f = FRAME(i3); if(!strncmp(buf, "kill", 5)) kill_client(f->client); else if(!strncmp(buf, "newcol ", 7)) @@ -1341,7 +1312,7 @@ xwrite(IXPConn *c, Fcall *fcall) break; case FsDGclient: if(!strncmp(buf, "kill", 5)) - kill_client(client.data[i1]); + kill_client(CLIENT(i1)); else return Enocommand; break; @@ -1368,28 +1339,28 @@ xwrite(IXPConn *c, Fcall *fcall) buf[fcall->count] = 0; cext_trim(buf, " \t/"); if(dir_type == FsDclient) - cl = view.data[i1]->area.data[i2]->frame.data[i3]->client; + cl = FRAME(i3)->client; else - cl = client.data[i1]; + cl = CLIENT(i1); apply_tags(cl, buf); update_views(); draw_client(cl); break; case FsFdata: len = fcall->count; - if(len >= sizeof(bar.data[i1]->data)) - len = sizeof(bar.data[i1]->data) - 1; - memcpy(bar.data[i1]->data, fcall->data, len); - bar.data[i1]->data[len] = 0; + if(len >= sizeof(BAR(i1)->data)) + len = sizeof(BAR(i1)->data) - 1; + memcpy(BAR(i1)->data, fcall->data, len); + BAR(i1)->data[len] = 0; draw_bar(); break; case FsFcolors: - if((i1 >= bar.size) || (fcall->count != 23) || (fcall->data[0] != '#') + if(!i1 || (fcall->count != 23) || (fcall->data[0] != '#') || (fcall->data[8] != '#') || (fcall->data[16] != '#')) return Ebadvalue; - memcpy(bar.data[i1]->colstr, fcall->data, fcall->count); - bar.data[i1]->colstr[fcall->count] = 0; - blitz_loadcolor(dpy, &bar.data[i1]->color, screen, bar.data[i1]->colstr); + memcpy(BAR(i1)->colstr, fcall->data, fcall->count); + BAR(i1)->colstr[fcall->count] = 0; + blitz_loadcolor(dpy, &BAR(i1)->color, screen, BAR(i1)->colstr); draw_bar(); break; case FsFselcolors: @@ -1459,7 +1430,7 @@ xwrite(IXPConn *c, Fcall *fcall) buf[fcall->count] = 0; if(dir_type == FsDclient) { XRectangle new; - f = view.data[i1]->area.data[i2]->frame.data[i3]; + f = FRAME(i3); new = f->rect; blitz_strtorect(&new, buf); if(new.width == 0) @@ -1485,8 +1456,8 @@ xwrite(IXPConn *c, Fcall *fcall) return Ebadvalue; cext_strlcpy(def.grabmod, buf, sizeof(def.grabmod)); def.mod = mod; - if(view.size) - restack_view(view.data[sel]); + if(view) + restack_view(sel); } break; case FsFfont: @@ -1500,15 +1471,15 @@ xwrite(IXPConn *c, Fcall *fcall) case FsFmode: if(fcall->count >= sizeof(buf)) return Ebadvalue; - if(dir_type == FsDarea && !i2) + if(dir_type == FsDarea && AREA(i2) == AREA(i2)->view->area) return Enofile; memcpy(buf, fcall->data, fcall->count); buf[fcall->count] = 0; if((i = column_mode_of_str(buf)) == -1) return Ebadvalue; - view.data[i1]->area.data[i2]->mode = i; - arrange_column(view.data[i1]->area.data[i2], True); - restack_view(view.data[i1]); + AREA(i2)->mode = i; + arrange_column(AREA(i2), True); + restack_view(VIEW(i1)); draw_clients(); break; case FsFevent: @@ -1532,25 +1503,31 @@ xwrite(IXPConn *c, Fcall *fcall) static char * xclunk(IXPConn *c, Fcall *fcall) { - IXPMap *m = ixp_server_fid2map(c, fcall->fid); + IXPMap *t, *m = ixp_server_fid2map(c, fcall->fid); + Client *cl; unsigned char type; if(!m) return Enofile; - type = unpack_type(m->wqid[m->sel].path); + type = ((PackedQid *)&m->wqid[m->sel])->ptype; if(type == FsFkeys) update_keys(); else if(type == FsFtagrules) { - unsigned int i; update_rules(&trule, def.tagrules); - for(i = 0; i < client.size; i++) - apply_rules(client.data[i]); + for(cl=client; cl; cl=cl->next) + apply_rules(cl); update_views(); } else if(type == FsFcolrules) { update_rules(&vrule, def.colrules); } - cext_vdetach(ixp_vector_of_maps(&c->map), m); + if(c->map == m) + c->map = m->next; + else { + for(t=c->map; t && t->next != m; t=t->next); + if(t) + t->next = m->next; + } free(m); fcall->id = RCLUNK; ixp_server_respond_fcall(c, fcall); @@ -1587,10 +1564,9 @@ do_fcall(IXPConn *c) void write_event(char *event) { - unsigned int i = 0; + IXPConn *c; - for(i = 0; i < srv.conn.size; i++) { - IXPConn *c = srv.conn.data[i]; + for(c=srv.conn; c; c=c->next) { if(c->is_pending) { /* pending reads on /event only, no qid checking */ IXPMap *m = ixp_server_fid2map(c, c->pending.fid); @@ -1598,7 +1574,7 @@ write_event(char *event) if(ixp_server_respond_error(c, &c->pending, Enofile)) return; } - else if(unpack_type(m->wqid[m->sel].path) == FsFevent) { + else if(((PackedQid *)&m->wqid[m->sel])->ptype == FsFevent) { /* pending reads on /event only, no qid checking */ c->pending.count = strlen(event); memcpy(c->pending.data, event, c->pending.count); diff --git a/cmd/wm/key.c b/cmd/wm/key.c @@ -85,17 +85,9 @@ ungrab_key(Key *k) static Key * name2key(const char *name) { - unsigned int i; - for(i = 0; i < key.size; i++) - if(!strncmp(key.data[i]->name, name, sizeof(key.data[i]->name))) - return key.data[i]; - return nil; -} - -static Vector * -key2vector(KeyVector *kv) -{ - return (Vector *) kv; + Key *k; + for(k=key; k && strncmp(k->name, name, sizeof(k->name)); k=k->lnext); + return k; } static Key * @@ -134,24 +126,13 @@ get_key(const char *name) } if(r) { r->id = id++; - cext_vattach(key2vector(&key), r); + r->lnext = key; + key = r; } return r; } -void -destroy_key(Key *k) -{ - Key *n; - cext_vdetach(key2vector(&key), k); - while(k) { - n = k->next; - free(k); - k = n; - } -} - static void next_keystroke(unsigned long *mod, KeyCode *keyCode) { @@ -187,89 +168,87 @@ emulate_key_press(unsigned long mod, KeyCode key) XSync(dpy, False); } -static KeyVector -match_keys(KeyVector kv, unsigned long mod, KeyCode keycode, Bool seq) +static Key * +match_keys(Key *k, unsigned long mod, KeyCode keycode, Bool seq) { - KeyVector result = {0}; - unsigned int i = 0; - for(i = 0; i < kv.size; i++) { - Key *k = kv.data[i]; + Key *ret = nil, *next; + for(next = k->tnext; k; (k=next) && (next=k->tnext)) { if(seq) k = k->next; - if(k && (k->mod == mod) && (k->key == keycode)) - cext_vattach(key2vector(&result), k); + if(k && (k->mod == mod) && (k->key == keycode)) { + k->tnext = ret; + ret = k; + } } - return result; + return ret; } static void -handle_key_seq(Window w, KeyVector done) +handle_key_seq(Window w, Key *done) { unsigned long mod; KeyCode key; - KeyVector found = {0}; + Key *found; char buf[128]; next_keystroke(&mod, &key); found = match_keys(done, mod, key, True); - if((done.data[0]->mod == mod) && (done.data[0]->key == key)) + if((done->mod == mod) && (done->key == key)) emulate_key_press(mod, key); /* double key */ else { - switch(found.size) { - case 0: + if(!found) { XBell(dpy, 0); - break; /* grabbed but not found */ - case 1: - if(!found.data[0]->next) { - snprintf(buf, sizeof(buf), "Key %s\n", found.data[0]->name); - write_event(buf); - break; - } - default: - handle_key_seq(w, found); - break; + } /* grabbed but not found */ + else if(!found->tnext && !found->next) { + snprintf(buf, sizeof(buf), "Key %s\n", found->name); + write_event(buf); } + else + handle_key_seq(w, found); } - free(found.data); } void handle_key(Window w, unsigned long mod, KeyCode keycode) { + Key *k; char buf[128]; - KeyVector found = match_keys(key, mod, keycode, False); - switch(found.size) { - case 0: + + for(k=key; k; k->tnext=k->lnext, k=k->lnext); + Key *found = match_keys(key, mod, keycode, False); + + if(!found) { XBell(dpy, 0); - break; /* grabbed but not found */ - case 1: - if(!found.data[0]->next) { - snprintf(buf, sizeof(buf), "Key %s\n", found.data[0]->name); - write_event(buf); - break; - } - default: + } /* grabbed but not found */ + else if(!found->tnext && !found->next) { + snprintf(buf, sizeof(buf), "Key %s\n", found->name); + write_event(buf); + } + else { XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime); handle_key_seq(w, found); XUngrabKeyboard(dpy, CurrentTime); XSync(dpy, False); - break; } - free(found.data); } void update_keys() { - Key *k; + Key *k, *n; char *l, *p; init_lock_keys(); - while(key.size) { - ungrab_key(key.data[0]); - destroy_key(key.data[0]); + while((k = key)) { + key = key->lnext; + ungrab_key(k); + + while((n = k)) { + k = k->next; + free(n); + } } for(l = p = def.keys; p && *p;) { diff --git a/cmd/wm/mouse.c b/cmd/wm/mouse.c @@ -111,8 +111,8 @@ snap_rect(XRectangle *rects, int num, XRectangle *current, BlitzAlign *mask, int snap) { SnapArgs a = { rects, num, 0, 0, 0, 0, *mask, nil }; - BlitzAlign ret; int dx = snap + 1, dy = snap + 1; + BlitzAlign ret; a.x1 = current->x; a.x2 = current->x + current->width; @@ -140,11 +140,13 @@ snap_rect(XRectangle *rects, int num, XRectangle *current, rect_morph_xy(current, abs(dx) <= snap ? dx : 0, abs(dy) <= snap ? dy : 0, mask); + ret = *mask; if(abs(dx) <= snap) ret ^= EAST|WEST; if(abs(dy) <= snap) ret ^= NORTH|SOUTH; + return ret ^ CENTER; } @@ -176,10 +178,10 @@ do_mouse_resize(Client *c, BlitzAlign align) Window dummy; XEvent ev; unsigned int num = 0, di; - Frame *f = c->frame.data[c->sel]; - int aidx = idx_of_area(f->area); - int snap = aidx ? 0 : rect.height / 66; - XRectangle *rects = aidx ? nil : rects_of_view(f->area->view, &num); + Frame *f = c->sel; + Bool floating = (f->area == f->area->view->area); + int snap = floating ? rect.height / 66 : 0; + XRectangle *rects = floating ? rects_of_view(f->area->view, &num) : nil; XRectangle frect = f->rect, ofrect; XRectangle origin = frect; XPoint pt; @@ -188,7 +190,7 @@ do_mouse_resize(Client *c, BlitzAlign align) rx = (float)ox / frect.width; ry = (float)oy / frect.height; - if (!aidx || align != CENTER) { + if (floating || align != CENTER) { px = ox = frect.width / 2; py = oy = frect.height / 2; if(align&NORTH) @@ -218,7 +220,7 @@ do_mouse_resize(Client *c, BlitzAlign align) switch (ev.type) { case ButtonRelease: draw_xor_border(&frect); - if(aidx) + if(!floating) resize_column(c, &frect, (align == CENTER) ? &pt : nil); else resize_client(c, &frect, False); @@ -235,20 +237,20 @@ do_mouse_resize(Client *c, BlitzAlign align) case MotionNotify: ofrect = frect; + pt.x = ev.xmotion.x; + pt.y = ev.xmotion.y; XTranslateCoordinates(dpy, c->framewin, root, ev.xmotion.x, ev.xmotion.y, &px, &py, &dummy); - pt.x = px; - pt.y = py; rect_morph_xy(&origin, px-ox, py-oy, &align); frect=origin; ox=px; oy=py; - if(!aidx) + if(floating) grav = snap_rect(rects, num, &frect, &align, snap); else grav = align ^ CENTER; - match_sizehints(c, &frect, aidx, grav); + match_sizehints(c, &frect, floating, grav); draw_xor_border(&ofrect); draw_xor_border(&frect); diff --git a/cmd/wm/rule.c b/cmd/wm/rule.c @@ -16,25 +16,19 @@ enum { VALUE }; -static Vector * -vector_of_rules(RuleVector *rv) -{ - return (Vector *) rv; -} - void -update_rules(RuleVector *rule, const char *data) +update_rules(Rule **rule, const char *data) { int mode = IGNORE; + Rule *rul; char *p, *r = nil, *v = nil, regex[256], value[256]; if(!data || !strlen(data)) return; - while(rule->size) { - Rule *rul = rule->data[0]; + while((rul = *rule)) { + *rule = rul->next; regfree(&rul->regex); - cext_vdetach(vector_of_rules(rule), rul); free(rul); } @@ -63,15 +57,15 @@ update_rules(RuleVector *rule, const char *data) break; case VALUE: if(*p == '\n' || *p == 0) { - Rule *rul = cext_emallocz(sizeof(Rule)); + *rule = cext_emallocz(sizeof(Rule)); *v = 0; cext_trim(value, " \t/"); - if(!regcomp(&rul->regex, regex, 0)) { - cext_strlcpy(rul->value, value, sizeof(rul->value)); - cext_vattach(vector_of_rules(rule), rul); + if(!regcomp(&(*rule)->regex, regex, 0)) { + cext_strlcpy((*rule)->value, value, sizeof(rul->value)); + rule = &(*rule)->next; } else - free(rul); + free(*rule); mode = IGNORE; } else { diff --git a/cmd/wm/view.c b/cmd/wm/view.c @@ -4,96 +4,79 @@ */ #include <stdlib.h> +#include <stdio.h> #include <string.h> #include "wm.h" -static Vector * -vector_of_views(ViewVector *vv) -{ - return (Vector *) vv; -} +static char buf[256]; -static int -comp_view_name(const void *v1, const void *v2) +static void +assign_sel_view(View *v) { - View *vv1 = *(View **)v1; - View *vv2 = *(View **)v2; - return strcmp(vv1->name, vv2->name); + if(sel && sel != v) { + snprintf(buf, sizeof(buf), "UnfocusTag %s\n", sel->name); + write_event(buf); + } + sel = v; + snprintf(buf, sizeof(buf), "FocusTag %s\n", sel->name); + write_event(buf); } -static View * +View * create_view(const char *name) { static unsigned short id = 1; - static char buf[256]; - View *v = cext_emallocz(sizeof(View)); + View **i, *v = cext_emallocz(sizeof(View)); v->id = id++; cext_strlcpy(v->name, name, sizeof(v->name)); - create_area(v, v->area.size, 0); - create_area(v, v->area.size, 0); - cext_vattach(vector_of_views(&view), v); - qsort(view.data, view.size, sizeof(View *), comp_view_name); - snprintf(buf, sizeof(buf), "CreateTag %s\n", name); - write_event(buf); - return v; -} + create_area(v, nil, 0); + create_area(v, v->area, 0); -static void -assign_sel_view(View *v) -{ - static char buf[256]; - int i = idx_of_view(v); + for(i=&view; *i && (strcmp((*i)->name, name) < 0); i=&(*i)->next); + v->next = *i; + *i = v; - i = idx_of_view(v); - if(sel < view.size && i != sel) { - snprintf(buf, sizeof(buf), "UnfocusTag %s\n", view.data[sel]->name); - write_event(buf); - } - snprintf(buf, sizeof(buf), "FocusTag %s\n", v->name); + snprintf(buf, sizeof(buf), "CreateTag %s\n", v->name); write_event(buf); - sel = i; + if(!sel) + assign_sel_view(v); + + return v; } -static void +void destroy_view(View *v) { - static char buf[256]; - while(v->area.size) - destroy_area(v->area.data[0]); + Area *a; + View **i; + + for(a=v->area; a; a=a->next) + destroy_area(a); + + for(i=&view; *i && *i != v; i=&(*i)->next); + *i = v->next; + + if(sel == v) + for(sel=view; sel && sel->next != *i; sel=sel->next); - cext_vdetach(vector_of_views(&view), v); - if(sel >= view.size && view.size) - assign_sel_view(view.data[0]); snprintf(buf, sizeof(buf), "DestroyTag %s\n", v->name); write_event(buf); free(v); } -int -idx_of_view(View *v) -{ - int i; - for(i = 0; i < view.size; i++) - if(v == view.data[i]) - return i; - return -1; -} - static void update_frame_selectors(View *v) { - unsigned int i, j; + Client *c; + Frame *f; /* select correct frames of clients */ - for(i = 0; i < client.size; i++) { - Client *c = client.data[i]; - for(j = 0; j < c->frame.size; j++) - if(c->frame.data[j]->area->view == v) { - c->sel = j; - break; - } + for(c=client; c; c=c->next) { + for(f=c->frame; f && f->area->view != v; f=f->cnext); + if(f) + c->sel = f; } } @@ -101,7 +84,8 @@ void focus_view(View *v) { Client *c; - unsigned int i; + + cext_assert(v); XGrabServer(dpy); assign_sel_view(v); @@ -109,19 +93,21 @@ focus_view(View *v) update_frame_selectors(v); /* gives all(!) clients proper geometry (for use of different tags) */ - for(i = 0; i < client.size; i++) - if(client.data[i]->frame.size) { - Frame *f = client.data[i]->frame.data[client.data[i]->sel]; - if(f->area->view == v) { - XMoveWindow(dpy, client.data[i]->framewin, f->rect.x, f->rect.y); - resize_client(client.data[i], &f->rect, False); + for(c=client; c; c=c->next) + if(c->sel) { + Frame *f = c->sel; + if(f && f->area->view == v) { + XMoveWindow(dpy, c->framewin, f->rect.x, f->rect.y); + resize_client(c, &f->rect, False); } else - XMoveWindow(dpy, client.data[i]->framewin, + XMoveWindow(dpy, c->framewin, 2 * rect.width + f->rect.x, f->rect.y); } - if((c = sel_client_of_view(v))) + + if((c = selected_client())) focus_client(c, True); + draw_clients(); XSync(dpy, False); XUngrabServer(dpy); @@ -132,40 +118,32 @@ XRectangle * rects_of_view(View *v, unsigned int *num) { XRectangle *result = nil; - unsigned int i; + Frame *f; - *num = v->area.data[0]->frame.size + 2; + *num = 2; + for(f=v->area->frame; f; f=f->anext, (*num)++); - if(*num) { - result = cext_emallocz(*num * sizeof(XRectangle)); - for(i = 0; i < v->area.data[0]->frame.size; i++) - result[i] = v->area.data[0]->frame.data[i]->rect; - result[*num - 1] = rect; - result[*num - 2] = brect; - } - return result; + result = cext_emallocz(*num * sizeof(XRectangle)); + for(f=v->area->frame; f; f=f->anext) + *(result++) = f->rect; + *(result++) = rect; + *(result++) = brect; + return (result - *num); } -int -idx_of_view_id(unsigned short id) -{ - int i; - for(i = 0; i < view.size; i++) - if(view.data[i]->id == id) - return i; - return -1; +View * +view_of_id(unsigned short id) { + View *v; + for(v = view; v && v->id != id; v=v->next); + return v; } View * view_of_name(const char *name) { - unsigned int i; - - for(i = 0; i < view.size; i++) - if(!strncmp(view.data[i]->name, name, strlen(name)) - && !strncmp(view.data[i]->name, name, strlen(view.data[i]->name))) - return view.data[i]; - return nil; + View *v; + for(v = view; v && strcmp(v->name, name); v=v->next); + return v; } static View * @@ -183,16 +161,16 @@ select_view(const char *arg) cext_trim(buf, " \t+"); if(!strlen(buf)) return; - focus_view(get_view(arg)); + assign_sel_view(get_view(arg)); update_views(); /* performs focus_view */ } static Bool is_of_view(View *v, Client *c) { - unsigned int i; - for(i = 0; i < v->area.size; i++) - if(is_of_area(v->area.data[i], c)) + Area *a; + for(a=v->area; a; a=a->next) + if(is_of_area(a, c)) return True; return False; } @@ -200,11 +178,11 @@ is_of_view(View *v, Client *c) void detach_from_view(View *v, Client *c) { - unsigned int i; + Area *a; - for(i = 0; i < v->area.size; i++) { - if(is_of_area(v->area.data[i], c)) { - detach_from_area(v->area.data[i], c); + for(a=v->area; a; a=a->next) { + if(is_of_area(a, c)) { + detach_from_area(a, c); XMoveWindow(dpy, c->framewin, 2 * rect.width, 0); } } @@ -219,46 +197,39 @@ attach_to_view(View *v, Client *c) if(c->trans || c->floating || c->fixedsize || (c->rect.width == rect.width && c->rect.height == rect.height)) - a = v->area.data[0]; + a = v->area; else - a = v->area.data[v->sel]; + a = v->sel; attach_to_area(a, c, False); - v->sel = idx_of_area(a); -} - -Client * -sel_client_of_view(View *v) -{ - if(v) { - Area *a = v->area.size ? v->area.data[v->sel] : nil; - return sel_client_of_area(a); - } - return nil; + v->sel = a; } void restack_view(View *v) { - unsigned int i, n = 0; - int j; + Area *a; + Frame *f; + Client *c; + unsigned int n=0, i=0; static Window *wins = nil; static unsigned int winssz = 0; - if(client.size > winssz) { - winssz = 2 * client.size; + for(c=client; c; c=c->next, i++); + if(i > winssz) { + winssz = 2 * i; wins = realloc(wins, sizeof(Window) * winssz); } - for(i = 0; i < v->area.size; i++) { - Area *a = v->area.data[i]; - if(a->frame.size) { - wins[n++] = a->frame.data[a->sel]->client->framewin; - for(j = a->frame.size - 1; j >= 0; j--) { - Client *c = a->frame.data[j]->client; - update_client_grab(c, (v->sel == i) && (a->sel == j)); - if(j == a->sel) - continue; - wins[n++] = c->framewin; + for(a=v->area; a; a=a->next) { + if(a->frame) { + wins[n++] = a->sel->client->framewin; + for(f=a->frame; f; f=f->anext, f != a->sel && n++); + i=n; + for(f=a->frame; f; f=f->anext) { + Client *c = f->client; + update_client_grab(c, (v->sel == a) && (a->sel == f)); + if(f != a->sel) + wins[--i] = c->framewin; } } } @@ -270,36 +241,35 @@ restack_view(View *v) void scale_view(View *v, float w) { - unsigned int i, xoff; + unsigned int xoff, i=0; + Area *a; float scale, dx = 0; int wdiff = 0; - if(v->area.size == 1) + if(!v->area->next) return; - for(i = 1; i < v->area.size; i++) - dx += v->area.data[i]->rect.width; + for(a=v->area->next; a; a=a->next, i++) + dx += a->rect.width; scale = w / dx; xoff = 0; - for(i = 1; i < v->area.size; i++) { - Area *a = v->area.data[i]; + for(a=v->area->next; a; a=a->next) { a->rect.width *= scale; - if(i == v->area.size - 1) + if(!a->next) a->rect.width = w - xoff; xoff += a->rect.width; } /* MIN_COLWIDTH can only be respected when there is enough space; the caller should guarantee this */ - if((v->area.size - 1) * MIN_COLWIDTH > w) + if(i * MIN_COLWIDTH > w) return; xoff = 0; - for(i = 1; i < v->area.size; i++) { - Area *a = v->area.data[i]; + for(a=v->area->next; a; a=a->next, i--) { if(a->rect.width < MIN_COLWIDTH) a->rect.width = MIN_COLWIDTH; - else if((wdiff = xoff + a->rect.width - w + (v->area.size - 1 - i) * MIN_COLWIDTH) > 0) + else if((wdiff = xoff + a->rect.width - w + i * MIN_COLWIDTH) > 0) a->rect.width -= wdiff; - if(i == v->area.size - 1) + if(!a->next) a->rect.width = w - xoff; xoff += a->rect.width; } @@ -308,14 +278,14 @@ scale_view(View *v, float w) void arrange_view(View *v) { - unsigned int i, xoff = 0; + unsigned int xoff = 0; + Area *a; - if(v->area.size == 1) + if(!v->area->next) return; scale_view(v, rect.width); - for(i = 1; i < v->area.size; i++) { - Area *a = v->area.data[i]; + for(a=v->area->next; a; a=a->next) { a->rect.x = xoff; a->rect.y = 0; a->rect.height = rect.height - brect.height; @@ -327,6 +297,8 @@ arrange_view(View *v) static void update_client_views(Client *c) { + static ViewLink *free_view_links = nil; + ViewLink *v; char buf[256]; char *toks[16]; unsigned int i, n; @@ -334,19 +306,32 @@ update_client_views(Client *c) cext_strlcpy(buf, c->tags, sizeof(buf)); n = cext_tokenize(toks, 16, buf, '+'); - while(c->view.size) - cext_vdetach(vector_of_views(&c->view), c->view.data[0]); + while((v = c->views)) { + c->views = v->next; + v->next = free_view_links; + free_view_links = v; + } - for(i = 0; i < n; i++) - cext_vattach(vector_of_views(&c->view), get_view(toks[i])); + for(i = 0; i < n; i++) { + if(free_view_links) { + v = free_view_links; + free_view_links = v->next; + } + else + v = cext_emallocz(sizeof(ViewLink)); + + v->next = c->views; + c->views = v; + v->view = get_view(toks[i]); + } } static Bool is_view_of(Client *c, View *v) { - unsigned int i; - for(i = 0; i < c->view.size; i++) - if(c->view.data[i] == v) + ViewLink *l; + for(l=c->views; l; l=l->next) + if(l->view == v) return True; return False; } @@ -354,74 +339,66 @@ is_view_of(Client *c, View *v) static Bool is_empty(View *v) { - unsigned int i; - for(i = 0; i < v->area.size; i++) - if(v->area.data[i]->frame.size) + Area *a; + for(a=v->area; a; a=a->next) + if(a->frame) return False; return True; } -static View * -next_empty_view(View *ignore) -{ - unsigned int i; - for(i = 0; i < view.size; i++) - if((view.data[i] != ignore) && is_empty(view.data[i])) - return view.data[i]; - return nil; -} - void update_views() { - unsigned int i, j; - View *v, *old = view.size ? view.data[sel] : nil; - - for(i = 0; i < client.size; i++) - update_client_views(client.data[i]); - - for(i = 0; i < client.size; i++) { - Client *c = client.data[i]; - for(j = 0; j < view.size; j++) { - View *vw = view.data[j]; - update_frame_selectors(vw); - if(is_view_of(c, vw)) { - if(!is_of_view(vw, c)) - attach_to_view(vw, c); + View **i, *v, *old = sel; + Client *c; + + for(c=client; c; c=c->next) + update_client_views(c); + + for(c=client; c; c=c->next) { + for(v=view; v; v=v->next) { + update_frame_selectors(v); + if(is_view_of(c, v)) { + if(!is_of_view(v, c)) + attach_to_view(v, c); } else { - if(is_of_view(vw, c)) - detach_from_view(vw, c); + if(is_of_view(v, c)) + detach_from_view(v, c); } } } if(old && !strncmp(old->name, "nil", 4)) old = nil; - while((v = next_empty_view(old))) - destroy_view(v); + + for(i=&view; *i; *i && (i=&(*i)->next)) + if((*i != old) && is_empty(*i)) + destroy_view(*i); if(old) focus_view(old); - else if(view.size) - focus_view(view.data[sel]); + else if(sel) + focus_view(sel); } unsigned int newcolw_of_view(View *v) { + Rule *r; + Area *a; unsigned int i, n; regmatch_t tmpregm; - for(i = 0; i < vrule.size; i++) { - Rule *r = vrule.data[i]; + for(r=vrule; r; r=r->next) { if(!regexec(&r->regex, v->name, 1, &tmpregm, 0)) { char buf[256]; char *toks[16]; cext_strlcpy(buf, r->value, sizeof(buf)); n = cext_tokenize(toks, 16, buf, '+'); - if(n && n > v->area.size - 1) { - if(sscanf(toks[v->area.size - 1], "%u", &n) == 1) + for(a=v->area, i=0; a; a=a->next, i--); + if(n && n > i - 1) { + if(sscanf(toks[i - 1], "%u", &n) == 1) return (rect.width * n) / 100; } break; diff --git a/cmd/wm/wm.c b/cmd/wm/wm.c @@ -197,12 +197,9 @@ startup_error_handler(Display * dpy, XErrorEvent * error) static void cleanup() { - unsigned int i; - for(i = 0; i<client.size; i++) { - Client *c = client.data[i]; - Frame *cf = c->frame.data[c->sel]; - reparent_client(c, root, cf->rect.x, cf->rect.y); - } + Client *c; + for(c=client; c; c=c->next) + reparent_client(c, root, c->sel->rect.x, c->sel->rect.y); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); XSync(dpy, False); } @@ -278,23 +275,21 @@ main(int argc, char *argv[]) /* IXP server */ ixp_server_open_conn(&srv, i, new_ixp_conn, ixp_server_close_conn); - root_qid.dir_type = FsDroot; + root_qid.qid.dir_type = FsDroot; root_qid.type = IXP_QTDIR; root_qid.version = 0; - root_qid.path = pack_qpath(FsDroot, 0, 0, 0); + root_qid.ptype = FsDroot; /* X server */ ixp_server_open_conn(&srv, ConnectionNumber(dpy), check_x_event, nil); init_x_event_handler(); - view.size = client.size = sel = 0; - view.data = nil; - client.data = nil; + view = nil; + client = nil; + sel = nil; + bar = nil; + key = nil; - key.data = nil; - key.size = 0; - bar.data = nil; - bar.size = 0; def.colrules = nil; def.colrulessz = 0; def.tagrules = nil; diff --git a/cmd/wm/wm.h b/cmd/wm/wm.h @@ -79,75 +79,92 @@ enum { MIN_COLWIDTH = 64 }; enum { WM_PROTOCOL_DELWIN = 1 }; typedef struct View View; +#define VIEW(p) ((View *)(p)) typedef struct Area Area; +#define AREA(p) ((Area *)(p)) typedef struct Frame Frame; +#define FRAME(p) ((Frame *)(p)) typedef struct Client Client; +#define CLIENT(p) ((Client *)(p)) -VECTOR(AreaVector, Area *); struct View { + View *next; char name[256]; unsigned short id; - AreaVector area; - unsigned int sel; - unsigned int revert; + Area *area; + Area *sel; + Area *revert; +}; + +typedef struct ViewLink ViewLink; +struct ViewLink { + ViewLink *next; + View *view; }; -VECTOR(FrameVector, Frame *); struct Area { - unsigned short id; - FrameVector frame; + Area *next; + Frame *frame; + Frame *sel; View *view; - unsigned int sel; + unsigned short id; int mode; XRectangle rect; }; struct Frame { + Frame *cnext; + Frame *anext; Area *area; unsigned short id; XRectangle rect; Client *client; }; -VECTOR(ViewVector, View *); struct Client { - unsigned short id; + Client *next; + ViewLink *views; + Area *revert; + Frame *frame; + Frame *sel; char name[256]; char tags[256]; - ViewVector view; char props[512]; - int proto; + unsigned short id; unsigned int border; + int proto; Bool floating; Bool fixedsize; Window win; Window trans; + Window framewin; XRectangle rect; XSizeHints size; - Window framewin; GC gc; - FrameVector frame; - unsigned int sel; - Area *revert; }; typedef struct Key Key; struct Key { + Key *next; + Key *lnext; + Key *tnext; unsigned short id; char name[128]; unsigned long mod; KeyCode key; - Key *next; }; -typedef struct { +#define BAR(p) ((Bar *)(p)) +typedef struct Bar Bar; +struct Bar { + Bar *next; char name[256]; - unsigned short id; char data[256]; char colstr[24]; + unsigned short id; BlitzColor color; XRectangle rect; -} Bar; +}; /* default values */ typedef struct { @@ -169,23 +186,37 @@ typedef struct { int colmode; } Default; -/* global variables */ -VECTOR(ClientVector, Client *); -VECTOR(KeyVector, Key *); -VECTOR(BarVector, Bar *); - typedef struct { + union { + Qid qid; + struct { + unsigned char type; + unsigned int version; + unsigned char ptype; + unsigned short i1id; + unsigned short i2id; + unsigned short i3id; + }; + }; +} PackedQid; + +/* global variables */ +typedef struct Rule Rule; +struct Rule { + Rule *next; regex_t regex; char value[256]; -} Rule; -VECTOR(RuleVector, Rule *); +}; /* global variables */ -ViewVector view; -unsigned int sel; -ClientVector client; -KeyVector key; -BarVector bar; +View *view; +Client *client; +Key *key; +Bar *bar; +Rule *trule; +Rule *vrule; + +View *sel; Display *dpy; int screen; Window root; @@ -197,7 +228,7 @@ Window barwin; GC bargc; GC xorgc; XRectangle brect; -Qid root_qid; +PackedQid root_qid; Default def; Atom wm_atom[WMLast]; Atom net_atom[NetLast]; @@ -205,31 +236,28 @@ Cursor cursor[CurLast]; unsigned int valid_mask; unsigned int num_lock_mask; void (*handler[LASTEvent]) (XEvent *); -RuleVector trule; -RuleVector vrule; /* area.c */ -Area *create_area(View *v, unsigned int pos, unsigned int w); +Area *create_area(View *v, Area *pos, unsigned int w); void destroy_area(Area *a); -int idx_of_area(Area *a); -int idx_of_area_id(View *t, unsigned short id); +Area *area_of_id(View *t, unsigned short id); void select_area(Area *a, char *arg); void send_to_area(Area *to, Area *from, Client *c); void attach_to_area(Area *a, Client *c, Bool send); void detach_from_area(Area *a, Client *c); Bool is_of_area(Area *a, Client *c); +int idx_of_area(Area *a); Client *sel_client_of_area(Area *a); /* bar.c */ -Bar *create_bar(char *name, Bool intern); +Bar *create_bar(char *name); void destroy_bar(Bar *b); void draw_bar(); -int idx_of_bar_id(unsigned short id); +Bar *bar_of_id(unsigned short id); void resize_bar(); unsigned int height_of_bar(); Bar *bar_of_name(const char *name); -int idx_of_bar(Bar *b); /* client.c */ Client *create_client(Window w, XWindowAttributes *wa); @@ -245,17 +273,20 @@ void reparent_client(Client *c, Window w, int x, int y); void manage_client(Client *c); void focus_client(Client *c, Bool restack); void focus(Client *c, Bool restack); -void match_sizehints(Client *c, XRectangle *r, int aidx, BlitzAlign sticky); void resize_client(Client *c, XRectangle *r, Bool ignore_xcall); void select_client(Client *c, char *arg); +Client *selected_client(); +void match_sizehints(Client *c, XRectangle *r, Bool floating, BlitzAlign sticky); void send_client(Client *c, char *arg); void move_client(Client *c, char *arg); void size_client(Client *c, char *arg); void newcol_client(Client *c, char *arg); void resize_all_clients(); Client *sel_client(); +Client *client_of_id(unsigned short id); int idx_of_client_id(unsigned short id); Client *client_of_win(Window w); +int idx_of_client(Client *c); void draw_clients(); void update_client_grab(Client *c, Bool is_sel); void apply_rules(Client *c); @@ -267,7 +298,7 @@ void scale_column(Area *a, float h); void resize_column(Client *c, XRectangle *r, XPoint *pt); int column_mode_of_str(char *arg); char *str_of_column_mode(int mode); -Area *new_column(View *v, unsigned int pos, unsigned int w); +Area *new_column(View *v, Area *pos, unsigned int w); /* event.c */ void init_x_event_handler(); @@ -275,11 +306,12 @@ void check_x_event(IXPConn *c); unsigned int flush_masked_events(long even_mask); /* frame.c */ -Vector *vector_of_frames(FrameVector *fv); Frame *create_frame(Area *a, Client *c); void destroy_frame(Frame *f); -int idx_of_frame_id(Area *a, unsigned short id); +void remove_frame(Frame *f); +void insert_frame(Frame *pos, Frame *f, Bool before); int idx_of_frame(Frame *f); +Frame *frame_of_id(Area *a, unsigned short id); Client *frame_of_win(Window w); /* fs.c */ @@ -302,21 +334,22 @@ BlitzAlign snap_rect(XRectangle *rects, int num, XRectangle *current, BlitzAlign *mask, int snap); /* rule.c */ -void update_rules(RuleVector *rule, const char *data); +void update_rules(Rule **rule, const char *data); /* view.c */ void arrange_view(View *v); void scale_view(View *v, float w); +View *create_view(const char *name); void focus_view(View *v); XRectangle *rects_of_view(View *v, unsigned int *num); -int idx_of_view_id(unsigned short id); +View *view_of_id(unsigned short id); void select_view(const char *arg); -int idx_of_view(View *v); void detach_from_view(View *v, Client *c); void attach_to_view(View *v, Client *c); Client *sel_client_of_view(View *v); void restack_view(View *v); View *view_of_name(const char *name); +void destroy_view(View *v); void update_views(); unsigned int newcolw_of_view(View *v); diff --git a/cmd/wm/wmii b/cmd/wm/wmii @@ -5,9 +5,9 @@ wmiiwm -c || exit 1 OLD_PATH="$PATH" export OLD_PATH PATH="$HOME/.wmii-4:CONFPREFIX/wmii-4:$PATH" export PATH -WMII_ADDRESS=unix!/tmp/ns.$USER.${DISPLAY%.0}/wmii export WMII_ADDRESS +WMII_ADDRESS=unix!/tmp/ns.$USER.$DISPLAY/wmii export WMII_ADDRESS -mkdir -m 700 /tmp/ns.$USER.$DISPLAY 2>/dev/null +mkdir -m 700 /tmp/ns.$USER.${DISPLAY%.0} 2>/dev/null wmiiwm -a $WMII_ADDRESS & wmiiwmpid=$! mkdir $HOME/.wmii-4 2>/dev/null && welcome & diff --git a/libcext/Makefile b/libcext/Makefile @@ -3,7 +3,7 @@ include ../config.mk -SRC = emallocz.c estrdup.c strlcat.c strlcpy.c tokenize.c trim.c vector.c +SRC = assert.c emallocz.c estrdup.c strlcat.c strlcpy.c tokenize.c trim.c vector.c OBJ = ${SRC:.c=.o} diff --git a/libcext/assert.c b/libcext/assert.c @@ -0,0 +1,10 @@ +/* Public Domain */ +#include <stdio.h> +#include <stdlib.h> + +void +cext_failed_assert(char *a, char *file, int line) +{ + fprintf(stderr, "Assertion \"%s\" failed at %s:%d\n", a, file, line); + exit(1); +} diff --git a/libcext/cext.h b/libcext/cext.h @@ -38,3 +38,7 @@ VECTOR(Vector, void *); void cext_vattach(Vector *v, void *p); void cext_vattachat(Vector *v, void *p, unsigned int pos); void cext_vdetach(Vector *v, void *p); + +/* assert.c */ +#define cext_assert(a) if(!(a)) cext_failed_assert(#a, __FILE__, __LINE__) +void cext_failed_assert(char *a, char *file, int line); diff --git a/libixp/ixp.h b/libixp/ixp.h @@ -60,7 +60,7 @@ enum { IXP_DMTMP = 0x04000000, /* mode bit for non-backed-up file */ IXP_DMREAD = 0x4<<6, /* mode bit for read permission */ IXP_DMWRITE = 0x2<<6, /* mode bit for write permission */ - IXP_DMEXEC = 0x1<<6 /* mode bit for execute permission */ + IXP_DMEXEC = 0x1<<6 /* mode bit for execute permission */ }; /* modes */ @@ -147,36 +147,27 @@ typedef struct IXPConn IXPConn; typedef struct IXPMap IXPMap; struct IXPMap { + IXPMap *next; unsigned int fid; unsigned short sel; unsigned short nwqid; Qid wqid[IXP_MAX_WELEM]; }; - -typedef struct { - unsigned int size; - IXPMap **data; -} MapVector; - struct IXPConn { + IXPConn *next; int fd; IXPServer *srv; void (*read) (IXPConn *); void (*close) (IXPConn *); - MapVector map; + IXPMap *map; Fcall pending; int is_pending; }; -typedef struct { - unsigned int size; - IXPConn **data; -} ConnVector; - struct IXPServer { int running; - ConnVector conn; + IXPConn *conn; int maxfd; fd_set rd; }; @@ -249,7 +240,6 @@ 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); void ixp_server_close(IXPServer *s); -Vector *ixp_vector_of_maps(MapVector *mv); /* socket.c */ int ixp_connect_sock(char *address); diff --git a/libixp/server.c b/libixp/server.c @@ -18,18 +18,6 @@ static unsigned char *msg[IXP_MAX_MSG]; -static Vector * -vector_of_conns(ConnVector *cv) -{ - return (Vector *) cv; -} - -Vector * -ixp_vector_of_maps(MapVector *mv) -{ - return (Vector *) mv; -} - IXPConn *ixp_server_open_conn(IXPServer *s, int fd, void (*read)(IXPConn *c), void (*close)(IXPConn *c)) { @@ -38,7 +26,8 @@ IXPConn *ixp_server_open_conn(IXPServer *s, int fd, void (*read)(IXPConn *c), c->srv = s; c->read = read; c->close = close; - cext_vattach(vector_of_conns(&s->conn), c); + c->next = s->conn; + s->conn = c; return c; } @@ -46,10 +35,17 @@ void ixp_server_close_conn(IXPConn *c) { IXPServer *s = c->srv; - cext_vdetach(vector_of_conns(&s->conn), c); - while(c->map.size) { - IXPMap *m = c->map.data[0]; - cext_vdetach(ixp_vector_of_maps(&c->map), m); + IXPConn *tc; + IXPMap *m; + if(s->conn == c) + s->conn = c->next; + else { + for(tc=s->conn; tc && tc->next != c; tc=tc->next); + if(tc) + tc->next = c->next; + } + while((m = c->map)) { + c->map = m->next; free(m); } shutdown(c->fd, SHUT_RDWR); @@ -60,24 +56,24 @@ ixp_server_close_conn(IXPConn *c) static void prepare_select(IXPServer *s) { - int i; + IXPConn *c; FD_ZERO(&s->rd); - for(i = 0; i < s->conn.size; i++) { - if(s->maxfd < s->conn.data[i]->fd) - s->maxfd = s->conn.data[i]->fd; - if(s->conn.data[i]->read) - FD_SET(s->conn.data[i]->fd, &s->rd); + for(c=s->conn; c; c=c->next) { + if(s->maxfd < c->fd) + s->maxfd = c->fd; + if(c->read) + FD_SET(c->fd, &s->rd); } } static void handle_conns(IXPServer *s) { - int i; - for(i = 0; i < s->conn.size; i++) - if(FD_ISSET(s->conn.data[i]->fd, &s->rd) && s->conn.data[i]->read) + IXPConn *c; + for(c=s->conn; c; c=c->next) + if(FD_ISSET(c->fd, &s->rd) && c->read) /* call read handler */ - s->conn.data[i]->read(s->conn.data[i]); + c->read(c); } char * @@ -104,11 +100,9 @@ ixp_server_loop(IXPServer *s) IXPMap * ixp_server_fid2map(IXPConn *c, unsigned int fid) { - unsigned int i; - for(i = 0; i < c->map.size; i++) - if(c->map.data[i]->fid == fid) - return c->map.data[i]; - return nil; + IXPMap *m; + for(m=c->map; m && m->fid != fid; m=m->next); + return m; } unsigned int @@ -155,8 +149,8 @@ ixp_server_respond_error(IXPConn *c, Fcall *fcall, char *errstr) void ixp_server_close(IXPServer *s) { - unsigned int i; - for(i = 0; i < s->conn.size; i++) - if(s->conn.data[i]->close) - s->conn.data[i]->close(s->conn.data[i]); + IXPConn *c; + for(c=s->conn; c; c=c->next) + if(c->close) + c->close(c); }