Add experimental regex tag support.

This commit is contained in:
Kris Maglione 2008-01-24 22:55:45 -05:00
parent 504e36ae5f
commit 2d023f073c
9 changed files with 258 additions and 60 deletions

View File

@ -30,6 +30,7 @@ OBJ = area \
rule \
printevent\
utf \
_util \
view \
xdnd \
x11 \

115
cmd/wmii/_util.c Normal file
View File

@ -0,0 +1,115 @@
/* Copyright ©2008 Kris Maglione <fbsdaemon@gmail.com>
* 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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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