all repos — dwm @ 8fcc4ff0ae2b20f9605370cee02ebcda50f8777c

fork of suckless dynamic window manager

tag.c (view raw)

  1/* See LICENSE file for copyright and license details. */
  2#include "dwm.h"
  3#include <regex.h>
  4#include <stdio.h>
  5#include <stdlib.h>
  6#include <string.h>
  7#include <X11/Xatom.h>
  8#include <X11/Xutil.h>
  9
 10/* static */
 11
 12typedef struct {
 13	const char *prop;
 14	const char *tags;
 15	Bool isfloating;
 16} Rule;
 17
 18typedef struct {
 19	regex_t *propregex;
 20	regex_t *tagregex;
 21} Regs;
 22
 23TAGS
 24RULES
 25
 26static Regs *regs = NULL;
 27static unsigned int nrules = 0;
 28static char prop[512];
 29
 30static void
 31persisttags(Client *c)
 32{
 33	unsigned int i;
 34
 35	for(i = 0; i < ntags && i < sizeof prop - 1; i++)
 36		prop[i] = c->tags[i] ? '+' : '-';
 37	prop[i] = '\0';
 38	XChangeProperty(dpy, c->win, dwmtags, XA_STRING, 8,
 39			PropModeReplace, (unsigned char *)prop, i);
 40}
 41
 42/* extern */
 43
 44void
 45compileregs(void) {
 46	unsigned int i;
 47	regex_t *reg;
 48
 49	if(regs)
 50		return;
 51	nrules = sizeof rule / sizeof rule[0];
 52	regs = emallocz(nrules * sizeof(Regs));
 53	for(i = 0; i < nrules; i++) {
 54		if(rule[i].prop) {
 55			reg = emallocz(sizeof(regex_t));
 56			if(regcomp(reg, rule[i].prop, REG_EXTENDED))
 57				free(reg);
 58			else
 59				regs[i].propregex = reg;
 60		}
 61		if(rule[i].tags) {
 62			reg = emallocz(sizeof(regex_t));
 63			if(regcomp(reg, rule[i].tags, REG_EXTENDED))
 64				free(reg);
 65			else
 66				regs[i].tagregex = reg;
 67		}
 68	}
 69}
 70
 71Bool
 72isvisible(Client *c) {
 73	unsigned int i;
 74
 75	for(i = 0; i < ntags; i++)
 76		if(c->tags[i] && seltag[i])
 77			return True;
 78	return False;
 79}
 80
 81void
 82settags(Client *c, Client *trans) {
 83	unsigned int i, j;
 84	regmatch_t tmp;
 85	Bool matched = trans != NULL;
 86	XClassHint ch = { 0 };
 87	XTextProperty name;
 88
 89	if(matched) {
 90		for(i = 0; i < ntags; i++)
 91			c->tags[i] = trans->tags[i];
 92	}
 93	else {
 94		/* check if window has set a property */
 95		name.nitems = 0;
 96		XGetTextProperty(dpy, c->win, &name, dwmtags);
 97		if(name.nitems && name.encoding == XA_STRING) {
 98			strncpy(prop, (char *)name.value, sizeof prop - 1);
 99			prop[sizeof prop - 1] = '\0';
100			XFree(name.value);
101			for(i = 0; i < ntags && i < sizeof prop - 1 && prop[i] != '\0'; i++)
102				if((c->tags[i] = prop[i] == '+'))
103					matched = True;
104		}
105	}
106	if(!matched) {
107		/* rule matching */
108		XGetClassHint(dpy, c->win, &ch);
109		snprintf(prop, sizeof prop, "%s:%s:%s",
110				ch.res_class ? ch.res_class : "",
111				ch.res_name ? ch.res_name : "", c->name);
112		for(i = 0; i < nrules; i++)
113			if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0)) {
114				c->isfloating = rule[i].isfloating;
115				for(j = 0; regs[i].tagregex && j < ntags; j++) {
116					if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
117						matched = True;
118						c->tags[j] = True;
119					}
120				}
121			}
122		if(ch.res_class)
123			XFree(ch.res_class);
124		if(ch.res_name)
125			XFree(ch.res_name);
126	}
127	if(!matched)
128		for(i = 0; i < ntags; i++)
129			c->tags[i] = seltag[i];
130	persisttags(c);
131}
132
133void
134tag(const char *arg) {
135	int i;
136
137	if(!sel)
138		return;
139	for(i = 0; i < ntags; i++)
140		sel->tags[i] = arg == NULL;
141	i = arg ? atoi(arg) : 0;
142	if(i >= 0 && i < ntags)
143		sel->tags[i] = True;
144	if(sel)
145		persisttags(sel);
146	arrange();
147}
148
149void
150toggletag(const char *arg) {
151	int i, j;
152
153	if(!sel)
154		return;
155	i = arg ? atoi(arg) : 0;
156	sel->tags[i] = !sel->tags[i];
157	for(j = 0; j < ntags && !sel->tags[j]; j++);
158	if(j == ntags)
159		sel->tags[i] = True;
160	if(sel)
161		persisttags(sel);
162	arrange();
163}
164
165void
166toggleview(const char *arg) {
167	int i, j;
168
169	i = arg ? atoi(arg) : 0;
170	seltag[i] = !seltag[i];
171	for(j = 0; j < ntags && !seltag[j]; j++);
172	if(j == ntags)
173		seltag[i] = True; /* cannot toggle last view */
174	arrange();
175}
176
177void
178view(const char *arg) {
179	int i;
180
181	for(i = 0; i < ntags; i++)
182		seltag[i] = arg == NULL;
183	i = arg ? atoi(arg) : 0;
184	if(i >= 0 && i < ntags)
185		seltag[i] = True;
186	arrange();
187}