mirror of https://github.com/0intro/wmii
Add experimental regex tag support.
This commit is contained in:
parent
504e36ae5f
commit
2d023f073c
|
@ -30,6 +30,7 @@ OBJ = area \
|
|||
rule \
|
||||
printevent\
|
||||
utf \
|
||||
_util \
|
||||
view \
|
||||
xdnd \
|
||||
x11 \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue