From 2d023f073c92989631cf5d4351d25780bd7c2c0e Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Thu, 24 Jan 2008 22:55:45 -0500 Subject: [PATCH] Add experimental regex tag support. --- cmd/wmii/Makefile | 1 + cmd/wmii/_util.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++ cmd/wmii/client.c | 75 +++++++++++++++++++++++------- cmd/wmii/dat.h | 18 ++++++++ cmd/wmii/fns.h | 6 +++ cmd/wmii/frame.c | 3 ++ cmd/wmii/geom.c | 28 ----------- cmd/wmii/mouse.c | 6 ++- cmd/wmii/view.c | 66 ++++++++++++++++++++------ 9 files changed, 258 insertions(+), 60 deletions(-) create mode 100644 cmd/wmii/_util.c diff --git a/cmd/wmii/Makefile b/cmd/wmii/Makefile index eeee909a..44f22b5a 100644 --- a/cmd/wmii/Makefile +++ b/cmd/wmii/Makefile @@ -30,6 +30,7 @@ OBJ = area \ rule \ printevent\ utf \ + _util \ view \ xdnd \ x11 \ diff --git a/cmd/wmii/_util.c b/cmd/wmii/_util.c new file mode 100644 index 00000000..29ffb71d --- /dev/null +++ b/cmd/wmii/_util.c @@ -0,0 +1,115 @@ +/* Copyright ©2008 Kris Maglione + * See LICENSE file for license details. + */ +#include "dat.h" +#include "fns.h" + +/* Blech. */ +#define VECTOR(type, nam, c) \ +void \ +vector_##c##init(Vector_##nam *v) { \ + memset(v, 0, sizeof *v); \ +} \ + \ +void \ +vector_##c##free(Vector_##nam *v) { \ + free(v->ary); \ + memset(v, 0, sizeof *v); \ +} \ + \ +void \ +vector_##c##push(Vector_##nam *v, type val) { \ + if(v->n == v->size) { \ + if(v->size == 0) \ + v->size = 2; \ + v->size <<= 2; \ + v->ary = erealloc(v->ary, v->size * sizeof *v->ary); \ + } \ + v->ary[v->n++] = val; \ +} \ + +VECTOR(long, long, l) +VECTOR(Rectangle, rect, r) +VECTOR(void*, ptr, p) + +void +reinit(Regex *r, char *regx) { + + refree(r); + + r->regex = estrdup(regx); + r->regc = regcomp(regx); +} + +void +refree(Regex *r) { + + free(r->regex); + free(r->regc); + r->regex = nil; + r->regc = nil; +} + +void +uniq(char **toks) { + char **p, **q; + + q = toks; + if(*q == nil) + return; + for(p=q+1; *p; p++) + if(strcmp(*q, *p)) + *++q = *p; + *++q = nil; +} + +char** +comm(int cols, char **toka, char **tokb) { + Vector_ptr vec; + char **ret; + char *p; + int cmp, len, i; + + len = 0; + vector_pinit(&vec); + while(*toka || *tokb) { + if(!*toka) + cmp = 1; + else if(!*tokb) + cmp = -1; + else + cmp = strcmp(*toka, *tokb); + if(cmp < 0) { + if(cols & CLeft) { + vector_ppush(&vec, *toka); + len += strlen(*toka) + 1; + } + toka++; + }else if(cmp > 0) { + if(cols & CRight) { + vector_ppush(&vec, *tokb); + len += strlen(*tokb) + 1; + } + tokb++; + }else { + if(cols & CCenter) { + vector_ppush(&vec, *toka); + len += strlen(*toka) + 1; + } + toka++; + tokb++; + } + } + ret = emalloc((vec.n+1) * sizeof(char*) + len); + ret[vec.n] = nil; + p = (char*)&ret[vec.n+1]; + for(i=0; i < vec.n; i++) { + len = strlen(vec.ary[i]) + 1; + memcpy(p, vec.ary[i], len); + ret[i] = p; + p += len; + } + free(vec.ary); + return ret; +} + diff --git a/cmd/wmii/client.c b/cmd/wmii/client.c index f81756c1..1f8625fa 100644 --- a/cmd/wmii/client.c +++ b/cmd/wmii/client.c @@ -245,6 +245,8 @@ client_destroy(Client *c) { none = nil; client_setviews(c, &none); sethandler(&c->w, nil); + refree(&c->tagre); + free(c->retags); if(hide) reparentwindow(&c->w, &scr.root, screen->r.max); @@ -910,6 +912,7 @@ client_setviews(Client *c, char **tags) { f = frame_create(c, view_create(*tags)); if(f->view == screen->sel || !c->sel) c->sel = f; + kludge = c; view_attach(f->view, f); f->cnext = *fp; *fp = f; @@ -918,7 +921,8 @@ client_setviews(Client *c, char **tags) { tags++; } } - view_update_all(); + if(c->sel == nil) + c->sel = c->frame; } static int @@ -943,10 +947,13 @@ static char *badtags[] = { void apply_tags(Client *c, const char *tags) { + View *v; uint i, j, k, n; bool add; char buf[512], last; - char *toks[32], *cur; + char *toks[32], *vtags[32]; + char **p; + char *cur; buf[0] = 0; @@ -958,7 +965,6 @@ apply_tags(Client *c, const char *tags) { utflcpy(buf, c->tags, sizeof(c->tags)); strlcat(buf, &tags[n], sizeof(buf)); - trim(buf, " \t/"); n = 0; add = True; @@ -971,6 +977,27 @@ apply_tags(Client *c, const char *tags) { j = 0; while(buf[n] && n < sizeof(buf) && j < 32) { + if(buf[n] == '/') { + for(i=n+1; i < sizeof(buf) - 1; i++) + if(buf[i] == '/') + break; + if(buf[i] != '/') + goto ifnot; + i++; + if(buf[i] != '+' + && buf[i] != '-' + && buf[i] != '\0') /* Don't be lenient */ + goto ifnot; + buf[i-1] = '\0'; + if(add) + reinit(&c->tagre, buf+n+1); + else + refree(&c->tagre); + last = buf[i]; + buf[i] = '\0'; + goto next; + } + ifnot: for(i = n; i < sizeof(buf) - 1; i++) if(buf[i] == '+' || buf[i] == '-' @@ -979,6 +1006,8 @@ apply_tags(Client *c, const char *tags) { last = buf[i]; buf[i] = '\0'; + trim(buf+n, " \t/"); + cur = nil; if(!strcmp(buf+n, "~")) c->floating = add; @@ -990,7 +1019,7 @@ apply_tags(Client *c, const char *tags) { cur = buf+n; n = i + 1; - if(cur) { + if(cur && j < nelem(toks)-1) { if(add) toks[j++] = cur; else { @@ -1001,6 +1030,7 @@ apply_tags(Client *c, const char *tags) { } } + next: if(last == '+') add = True; if(last == '-') @@ -1009,20 +1039,33 @@ apply_tags(Client *c, const char *tags) { buf[n] = '\0'; } - if(!j) - return; - + toks[j] = nil; qsort(toks, j, sizeof *toks, strpcmp); - + uniq(toks); c->tags[0] = '\0'; - for(i=0, n=0; i < j; i++) - if(n == 0 || strcmp(toks[i], toks[n-1])) { - if(i > 0) - strlcat(c->tags, "+", sizeof c->tags); - strlcat(c->tags, toks[i], sizeof c->tags); - toks[n++] = toks[i]; - } - toks[n] = nil; + for(p=toks; *p; p++) { + if(p > toks) + strlcat(c->tags, "+", sizeof c->tags); + strlcat(c->tags, *p, sizeof c->tags); + } + + i = 0; + if(c->tagre.regex) + for(v=view; v; v=v->next) + if(regexec(c->tagre.regc, v->name, nil, 0)) + if(i < nelem(vtags)-1) + vtags[i++] = v->name; + vtags[i] = nil; + + free(c->retags); + c->retags = comm(CRight, toks, vtags); + + for(p=vtags; *p; p++) + if(j < nelem(toks)-1) + toks[j++] = *p; + toks[j] = nil; + qsort(toks, j, sizeof *toks, strpcmp); + uniq(toks); client_setviews(c, toks); diff --git a/cmd/wmii/dat.h b/cmd/wmii/dat.h index 443b06c3..8d98f115 100644 --- a/cmd/wmii/dat.h +++ b/cmd/wmii/dat.h @@ -25,6 +25,12 @@ enum { PingTime = 10000, }; +enum { + CLeft = 1<<0, + CCenter = 1<<1, + CRight = 1<<2, +}; + enum { UrgManager, UrgClient, @@ -93,6 +99,7 @@ typedef struct Group Group; typedef struct Key Key; typedef struct Map Map; typedef struct MapEnt MapEnt; +typedef struct Regex Regex; typedef struct Rule Rule; typedef struct Ruleset Ruleset; typedef struct Strut Strut; @@ -124,6 +131,11 @@ struct Bar { CTuple col; }; +struct Regex { + char* regex; + Reprog* regc; +}; + struct Client { Client* next; Frame* frame; @@ -131,10 +143,12 @@ struct Client { Window w; Window* framewin; XWindow trans; + Regex tagre; Group* group; Strut* strut; Cursor cursor; Rectangle r; + char** retags; char name[256]; char tags[256]; char props[512]; @@ -212,6 +226,7 @@ struct Rule { Rule* next; Reprog* regex; char value[256]; + }; struct Ruleset { @@ -253,6 +268,7 @@ void vector_##c##push(Vector_##nam*, type); \ VECTOR(long, long, l) VECTOR(Rectangle, rect, r) +VECTOR(void*, ptr, p) #undef VECTOR #ifndef EXTERN @@ -334,6 +350,8 @@ EXTERN int debugflag; EXTERN int debugfile; EXTERN long xtime; +EXTERN Client* kludge; + extern char* debugtab[]; #define Debug(x) if((debugflag|debugfile)&(x) && setdebug(x)) diff --git a/cmd/wmii/fns.h b/cmd/wmii/fns.h index b90ec336..ee70e749 100644 --- a/cmd/wmii/fns.h +++ b/cmd/wmii/fns.h @@ -216,6 +216,12 @@ void view_update_all(void); void view_update_rect(View*); Rectangle* view_rects(View*, uint *num, Frame *ignore); +/* util.c */ +void refree(Regex*); +void reinit(Regex*, char*); +char** comm(int, char**, char**); +void uniq(char**); + /* utf.c */ char* toutf8(const char*); char* toutf8n(const char*, size_t); diff --git a/cmd/wmii/frame.c b/cmd/wmii/frame.c index 347e2291..b31b4a01 100644 --- a/cmd/wmii/frame.c +++ b/cmd/wmii/frame.c @@ -301,6 +301,9 @@ frame_resize(Frame *f, Rectangle r) { return; } + if(f->area->floating) + f->collapsed = false; + stickycorner = get_sticky(f->r, r); f->crect = frame_hints(f, r, stickycorner); diff --git a/cmd/wmii/geom.c b/cmd/wmii/geom.c index f34bfbd5..1362db7d 100644 --- a/cmd/wmii/geom.c +++ b/cmd/wmii/geom.c @@ -89,31 +89,3 @@ get_sticky(Rectangle src, Rectangle dst) { return stickycorner; } -/* XXX: These don't belong here. */ -/* Blech. */ -#define VECTOR(type, nam, c) \ -void \ -vector_##c##init(Vector_##nam *v) { \ - memset(v, 0, sizeof *v); \ -} \ - \ -void \ -vector_##c##free(Vector_##nam *v) { \ - free(v->ary); \ - memset(v, 0, sizeof *v); \ -} \ - \ -void \ -vector_##c##push(Vector_##nam *v, type val) { \ - if(v->n == v->size) { \ - if(v->size == 0) \ - v->size = 2; \ - v->size <<= 2; \ - v->ary = erealloc(v->ary, v->size * sizeof *v->ary); \ - } \ - v->ary[v->n++] = val; \ -} \ - -VECTOR(long, long, l) -VECTOR(Rectangle, rect, r) - diff --git a/cmd/wmii/mouse.c b/cmd/wmii/mouse.c index 7860cbc2..f7946817 100644 --- a/cmd/wmii/mouse.c +++ b/cmd/wmii/mouse.c @@ -408,6 +408,8 @@ mouse_resizecolframe(Frame *f, Align align) { assert((align&(East|West)) != (East|West)); assert((align&(North|South)) != (North|South)); + f->collapsed = false; + v = screen->sel; d = divs; for(a=v->area->next; a != f->area; a=a->next) @@ -681,8 +683,10 @@ static int (*tramp[])(Frame*) = { static void trampoline(int fn, Frame *f) { - while(fn > 0) + while(fn > 0) { + f->collapsed = false; fn = tramp[fn](f); + } ungrabpointer(); warppointer(grabboxcenter(f)); diff --git a/cmd/wmii/view.c b/cmd/wmii/view.c index 2ae2d226..a62366e5 100644 --- a/cmd/wmii/view.c +++ b/cmd/wmii/view.c @@ -7,11 +7,25 @@ static bool empty_p(View *v) { + Frame *f; Area *a; + char **p; + int cmp; + for(a=v->area; a; a=a->next) - if(a->frame) - return False; - return True; + for(f=a->frame; f; f=f->anext) { + for(p=f->client->retags; *p; p++) { + cmp = strcmp(*p, v->name); + if(cmp == 0) + goto nextframe; + if(cmp > 0) + return false; + } + return false; + nextframe: + continue; + } + return true; } static void @@ -43,12 +57,18 @@ view_fullscreen_p(View *v) { View* view_create(const char *name) { static ushort id = 1; - View **i, *v; + View **vp; + Client *c; + View *v; for(v=view; v; v=v->next) if(!strcmp(name, v->name)) return v; + print("xviews:\n"); + for(View *q=view; q; q=q->next) + print("view: %d %s\n", !strcmp(name, q->name), q->name); + v = emallocz(sizeof(View)); v->id = id++; v->r = screen->r; @@ -62,11 +82,17 @@ view_create(const char *name) { area_focus(v->area->next); - for(i=&view; *i; i=&(*i)->next) - if(strcmp((*i)->name, name) >= 0) + for(vp=&view; *vp; vp=&(*vp)->next) + if(strcmp((*vp)->name, name) >= 0) break; - v->next = *i; - *i = v; + v->next = *vp; + *vp = v; + + /* FIXME: Belongs elsewhere */ + /* FIXME: Can do better. */ + for(c=client; c; c=c->next) + if(c != kludge) + apply_tags(c, c->tags); view_arrange(v); if(!screen->sel) @@ -77,22 +103,29 @@ view_create(const char *name) { void view_destroy(View *v) { + View **vp; + Frame *f; + View *tv; Area *a; - View **i, *tv; + + for(vp=&view; *vp; vp=&(*vp)->next) + if(*vp == v) break; + *vp = v->next; + + /* FIXME: Can do better */ + for(a=v->area; a; a=a->next) + for(f=a->frame; f; f=f->anext) + apply_tags(f->client, f->client->tags); while((a = v->area->next)) area_destroy(a); area_destroy(v->area); - for(i=&view; *i; i=&(*i)->next) - if(*i == v) break; - *i = v->next; - event("DestroyTag %s\n", v->name); if(v == screen->sel) { for(tv=view; tv; tv=tv->next) - if(tv->next == *i) break; + if(tv->next == *vp) break; if(tv == nil) tv = view; if(tv) @@ -259,6 +292,9 @@ view_attach(View *v, Frame *f) { a = v->area->next; area_attach(a, f); + + if(c->sel == nil) + c->sel = f; } void @@ -429,7 +465,7 @@ view_newcolw(View *v, int num) { char buf[sizeof r->value]; char *toks[16]; - strcpy(buf, r->value); + utflcpy(buf, r->value, sizeof buf); n = tokenize(toks, 16, buf, '+'); if(num < n)