/foo/ -> ~+!+max rules now working fine, also renamed /client/X/class into /client/X/props, props syntax is now class:instance:name

This commit is contained in:
Anselm R. Garbe 2006-05-30 16:32:28 +02:00
parent 8a89f37797
commit cdc57ca2fd
5 changed files with 95 additions and 109 deletions

View File

@ -12,7 +12,6 @@
(stacked) client is made visible. So, when the fifth client is focused
and made visible, the third would disappear (with n=2) -- this means on
boundaries, like in mutt(1).
- make /foo/ -> bar+! -alike rules working
- /def/ncol defines num of columns which should be created by default if possible.
maybe /tag/ -> 60+20+20 ? or only /tag/ -> tag?
- remove internal labels, now tagging seems easy and straightforward that they

View File

@ -21,6 +21,7 @@ static void
update_client_name(Client *c)
{
XTextProperty name;
XClassHint ch;
int n;
char **list = nil;
@ -42,6 +43,16 @@ update_client_name(Client *c)
}
}
XFree(name.value);
if(XGetClassHint(dpy, c->win, &ch)) {
snprintf(c->props, sizeof(c->props), "%s:%s:%s",
ch.res_class ? ch.res_class : "",
ch.res_name ? ch.res_name : "",
c->name);
if(ch.res_class)
XFree(ch.res_class);
if(ch.res_name)
XFree(ch.res_name);
}
}
Client *
@ -49,7 +60,6 @@ create_client(Window w, XWindowAttributes *wa)
{
Client *c = (Client *) cext_emallocz(sizeof(Client));
XSetWindowAttributes fwa;
XClassHint ch;
long msize;
static unsigned int id = 1;
static char buf[256];
@ -74,15 +84,6 @@ create_client(Window w, XWindowAttributes *wa)
c->fixedsize = False;
XAddToSaveSet(dpy, c->win);
update_client_name(c);
if(XGetClassHint(dpy, c->win, &ch)) {
snprintf(c->classinst, sizeof(c->classinst), "%s:%s",
ch.res_class ? ch.res_class : "",
ch.res_name ? ch.res_name : "");
if(ch.res_class)
XFree(ch.res_class);
if(ch.res_name)
XFree(ch.res_name);
}
fwa.override_redirect = 1;
fwa.background_pixmap = ParentRelative;
fwa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask

View File

@ -62,7 +62,7 @@ enum { WMII_IOUNIT = 2048 };
* /tag/X/1/ctl FsFctl command interface (area)
* /tag/X/1/mode FsFmode column mode
* /tag/X/1/sel/ FsDclient
* /tag/X/1/1/class FsFclass Class:instance of client
* /tag/X/1/1/props FsFprops Class:instance of client
* /tag/X/1/1/index FsFindex index of client in /client
* /tag/X/1/1/name FsFname name of client
* /tag/X/1/1/tags FsFtags tag of client
@ -226,7 +226,7 @@ name_of_qid(Qid wqid[IXP_MAX_WELEM], unsigned short qsel)
return nil;
return "tags";
break;
case FsFclass:
case FsFprops:
case FsFindex:
case FsFname:
if((dir_type == FsDclient) && (i1 == -1 || i2 == -1 || i3 == -1))
@ -237,8 +237,8 @@ name_of_qid(Qid wqid[IXP_MAX_WELEM], unsigned short qsel)
case FsFname:
return "name";
break;
case FsFclass:
return "class";
case FsFprops:
return "props";
break;
case FsFindex:
return "index";
@ -288,8 +288,8 @@ type_of_name(Qid wqid[IXP_MAX_WELEM], unsigned short qsel, char *name)
return FsFctl;
if(!strncmp(name, "event", 6))
return FsFevent;
if(!strncmp(name, "class", 6))
return FsFclass;
if(!strncmp(name, "props", 6))
return FsFprops;
if(!strncmp(name, "index", 6))
return FsFindex;
if(!strncmp(name, "name", 5))
@ -448,7 +448,7 @@ qid_of_name(Qid wqid[IXP_MAX_WELEM], unsigned short qsel, char *name)
if(dir_type == FsDview)
return nil;
case FsFname:
case FsFclass:
case FsFprops:
if(dir_type == FsDroot)
return nil;
case FsFtags:
@ -550,13 +550,13 @@ stat_of_name(Stat *stat, char *name, Qid wqid[IXP_MAX_WELEM], unsigned short qse
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 FsFclass:
case FsFprops:
if(dir_type == FsDclient) {
f = view.data[i1]->area.data[i2]->frame.data[i3];
return pack_stat(stat, wqid, qsel, name, strlen(f->client->classinst), IXP_DMREAD);
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]->classinst), IXP_DMREAD);
return pack_stat(stat, wqid, qsel, name, strlen(client.data[i1]->props), IXP_DMREAD);
break;
case FsFindex:
switch(dir_type) {
@ -1093,7 +1093,7 @@ xread(IXPConn *c, Fcall *fcall)
break;
case FsDGclient:
case FsDclient:
fcall->count = stat_of_name(&stat, "class", m->wqid, m->sel);
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);
@ -1130,14 +1130,14 @@ xread(IXPConn *c, Fcall *fcall)
fcall->count = strlen(buf);
memcpy(p, buf, fcall->count);
break;
case FsFclass:
case FsFprops:
if(dir_type == FsDclient) {
if((fcall->count = strlen(view.data[i1]->area.data[i2]->frame.data[i3]->client->classinst)))
memcpy(p, view.data[i1]->area.data[i2]->frame.data[i3]->client->classinst, fcall->count);
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);
}
else {
if((fcall->count = strlen(client.data[i1]->classinst)))
memcpy(p, client.data[i1]->classinst, fcall->count);
if((fcall->count = strlen(client.data[i1]->props)))
memcpy(p, client.data[i1]->props, fcall->count);
}
break;
case FsFindex:
@ -1371,13 +1371,11 @@ xwrite(IXPConn *c, Fcall *fcall)
memcpy(buf, fcall->data, fcall->count);
buf[fcall->count] = 0;
cext_trim(buf, " \t/");
if(!permit_tags(buf))
return Ebadvalue;
if(dir_type == FsDclient)
cl = view.data[i1]->area.data[i2]->frame.data[i3]->client;
else
cl = client.data[i1];
cext_strlcpy(cl->tags, buf, sizeof(cl->tags));
apply_tags(cl, buf);
update_views();
draw_client(cl);
break;

View File

@ -9,14 +9,8 @@
#include <regex.h>
#include "wm.h"
/*
* basic rule matching language
*
* /regex/ -> tag [tag ...]
*
* regex might contain POSIX regex syntax defined in regex(3)
*/
/* basic rule matching language /regex/ -> value
* regex might contain POSIX regex syntax defined in regex(3) */
enum {
IGNORE,
REGEX,
@ -25,13 +19,10 @@ enum {
typedef struct {
regex_t regex;
char tags[256];
Bool is_valid;
char values[256];
} Rule;
VECTOR(RuleVector, Rule *);
VECTOR(PropVector, char *);
static RuleVector rule;
static Vector *
@ -40,29 +31,14 @@ vector_of_rules(RuleVector *rv)
return (Vector *) rv;
}
static Vector *
vector_of_props(PropVector *pv)
{
return (Vector *) pv;
}
Bool
permit_tags(const char *tags)
static Bool
permit_tag(const char *tag)
{
static char *exclude[] = { "sel", "status" };
char buf[256];
char *toks[16];
unsigned int i, j, n;
cext_strlcpy(buf, tags, sizeof(buf));
if(!(n = cext_tokenize(toks, 16, buf, '+')))
return False;
unsigned int i;
for(i = 0; i < (sizeof(exclude) / sizeof(exclude[0])); i++)
for(j = 0; j < n; j++) {
if(!strncmp(exclude[i], toks[j], strlen(toks[j])) &&
!strncmp(exclude[i], toks[j], strlen(exclude[i])))
if(!strcmp(exclude[i], tag))
return False;
}
return True;
}
@ -71,14 +47,13 @@ update_rules()
{
unsigned int i;
int mode = IGNORE;
char *p, *r = nil, *t = nil, regex[256], tags[256];
char *p, *r = nil, *v = nil, regex[256], values[256];
if(!def.rules || !strlen(def.rules))
return;
while(rule.size) {
Rule *r = rule.data[0];
if(r->is_valid)
regfree(&r->regex);
cext_vdetach(vector_of_rules(&rule), r);
free(r);
@ -93,8 +68,8 @@ update_rules()
}
else if(*p == '>') {
mode = TAGS;
tags[0] = 0;
t = tags;
values[0] = 0;
v = values;
}
break;
case REGEX:
@ -109,22 +84,20 @@ update_rules()
break;
case TAGS:
if(*p == '\n' || *(p + 1) == 0) {
*t = 0;
cext_trim(tags, " \t/");
if(permit_tags(tags)) {
Rule *rul = cext_emallocz(sizeof(Rule));
rul->is_valid = !regcomp(&rul->regex, regex, 0);
cext_strlcpy(rul->tags, tags, sizeof(rul->tags));
*v = 0;
cext_trim(values, " \t/");
if(!regcomp(&rul->regex, regex, 0)) {
cext_strlcpy(rul->values, values, sizeof(rul->values));
cext_vattach(vector_of_rules(&rule), rul);
}
else
fprintf(stderr, "wmiiwm: ignoring rule with tags '%s', restricted tag name\n",
tags);
free(rul);
mode = IGNORE;
}
else {
*t = *p;
t++;
*v = *p;
v++;
}
break;
}
@ -133,49 +106,64 @@ update_rules()
update_views();
}
static void
match(Client *c, PropVector prop)
void
apply_tags(Client *c, const char *tags)
{
unsigned int i,j;
unsigned int i, j = 0, n;
char buf[256];
char *toks[16], *apply[16];
cext_strlcpy(buf, tags, sizeof(buf));
if(!(n = cext_tokenize(toks, 16, buf, '+')))
return;
for(i = 0; i < n; i++) {
if(!strncmp(toks[i], "~", 2))
c->floating = True;
else if(!strncmp(toks[i], "!", 2)) {
if(view.size)
apply[j++] = view.data[sel]->name;
else
apply[j++] = "nil";
}
else if(permit_tag(toks[i]))
apply[j++] = toks[i];
}
c->tags[0] = 0;
for(i = 0; i < j; i++) {
cext_strlcat(c->tags, apply[i], sizeof(c->tags) - strlen(c->tags) - 1);
if(i + 1 < j)
cext_strlcat(c->tags, "+", sizeof(c->tags) - strlen(c->tags) - 1);
}
if(!strlen(c->tags))
apply_tags(c, "nil");
}
static void
match(Client *c, const char *prop)
{
unsigned int i;
regmatch_t tmpregm;
for(i = 0; i < rule.size; i++) {
Rule *r = rule.data[i];
for(j=0; j < prop.size; j++)
if(r->is_valid && !regexec(&r->regex, prop.data[j], 1, &tmpregm, 0)) {
if(!strncmp(r->tags, "~", 2))
c->floating = True;
else if(!strlen(c->tags) || !strncmp(c->tags, "nil", 4)) {
if(!strncmp(r->tags, "!", 2)) {
if(view.size)
cext_strlcpy(c->tags, view.data[sel]->name, sizeof(c->tags));
else
cext_strlcpy(c->tags, "nil", sizeof(c->tags));
}
else
cext_strlcpy(c->tags, r->tags, sizeof(c->tags));
}
}
if(!regexec(&r->regex, prop, 1, &tmpregm, 0))
if(!strlen(c->tags) || !strncmp(c->tags, "nil", 4))
apply_tags(c, r->values);
}
}
void
apply_rules(Client *c)
{
PropVector prop = {0};
if(!def.rules)
goto Fallback;
cext_vattach(vector_of_props(&prop), c->classinst);
cext_vattach(vector_of_props(&prop), c->name);
match(c, prop);
while(prop.size)
cext_vdetach(vector_of_props(&prop), prop.data[0]);
match(c, c->props);
Fallback:
if(!strlen(c->tags))
cext_strlcpy(c->tags, "nil", sizeof(c->tags));
apply_tags(c, "nil");
}

View File

@ -66,7 +66,7 @@ enum {
FsFctl,
FsFname,
FsFrules,
FsFclass,
FsFprops,
FsFmode,
FsFtags,
FsFindex,
@ -114,7 +114,7 @@ struct Client {
char name[256];
char tags[256];
ViewVector view;
char classinst[256];
char props[512];
int proto;
unsigned int border;
Bool floating;
@ -293,7 +293,7 @@ void snap_move(XRectangle *r, XRectangle *rects, unsigned int num,
/* rule.c */
void update_rules();
void apply_rules(Client *c);
Bool permit_tags(const char *tags);
void apply_tags(Client *c, const char *tags);
/* view.c */
void arrange_view(View *v);