all repos — dwm @ 9e56e1ded6889335035c8ffbe2763d3d83978673

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
 30/* extern */
 31
 32void
 33compileregs(void) {
 34	unsigned int i;
 35	regex_t *reg;
 36
 37	if(regs)
 38		return;
 39	nrules = sizeof rule / sizeof rule[0];
 40	regs = emallocz(nrules * sizeof(Regs));
 41	for(i = 0; i < nrules; i++) {
 42		if(rule[i].prop) {
 43			reg = emallocz(sizeof(regex_t));
 44			if(regcomp(reg, rule[i].prop, REG_EXTENDED))
 45				free(reg);
 46			else
 47				regs[i].propregex = reg;
 48		}
 49		if(rule[i].tags) {
 50			reg = emallocz(sizeof(regex_t));
 51			if(regcomp(reg, rule[i].tags, REG_EXTENDED))
 52				free(reg);
 53			else
 54				regs[i].tagregex = reg;
 55		}
 56	}
 57}
 58
 59Bool
 60isvisible(Client *c) {
 61	unsigned int i;
 62
 63	for(i = 0; i < ntags; i++)
 64		if(c->tags[i] && seltag[i])
 65			return True;
 66	return False;
 67}
 68
 69void
 70settags(Client *c, Client *trans) {
 71	unsigned int i, j;
 72	regmatch_t tmp;
 73	Bool matched = trans != NULL;
 74	XClassHint ch = { 0 };
 75	XTextProperty name;
 76
 77	if(matched) {
 78		for(i = 0; i < ntags; i++)
 79			c->tags[i] = trans->tags[i];
 80		return;
 81	}
 82	else {
 83		/* check if window has set a property */
 84		name.nitems = 0;
 85		XGetTextProperty(dpy, c->win, &name, dwmtags);
 86		if(name.nitems && name.encoding == XA_STRING) {
 87			strncpy(prop, (char *)name.value, sizeof prop - 1);
 88			prop[sizeof prop - 1] = '\0';
 89			XFree(name.value);
 90			for(i = 0; i < ntags && i < sizeof prop - 1 && prop[i] != '\0'; i++)
 91				if((c->tags[i] = prop[i] == '+'))
 92					matched = True;
 93		}
 94		if(matched)
 95			return;
 96		/* rule matching */
 97		XGetClassHint(dpy, c->win, &ch);
 98		snprintf(prop, sizeof prop, "%s:%s:%s",
 99				ch.res_class ? ch.res_class : "",
100				ch.res_name ? ch.res_name : "", c->name);
101		for(i = 0; i < nrules; i++)
102			if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0)) {
103				c->isfloating = rule[i].isfloating;
104				for(j = 0; regs[i].tagregex && j < ntags; j++) {
105					if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
106						matched = True;
107						c->tags[j] = True;
108					}
109				}
110			}
111		if(ch.res_class)
112			XFree(ch.res_class);
113		if(ch.res_name)
114			XFree(ch.res_name);
115	}
116	if(!matched)
117		for(i = 0; i < ntags; i++)
118			c->tags[i] = seltag[i];
119}
120
121void
122tag(const char *arg) {
123	int i;
124
125	if(!sel)
126		return;
127	for(i = 0; i < ntags; i++)
128		sel->tags[i] = arg == NULL;
129	i = arg ? atoi(arg) : 0;
130	if(i >= 0 && i < ntags)
131		sel->tags[i] = True;
132	if(sel) {
133		for(i = 0; i < ntags && i < sizeof prop - 1; i++)
134			prop[i] = sel->tags[i] ? '+' : '-';
135		prop[i] = '\0';
136		XChangeProperty(dpy, sel->win, dwmtags, XA_STRING, 8, PropModeReplace, (unsigned char *)prop, i);
137	}
138	arrange();
139}
140
141void
142toggletag(const char *arg) {
143	int i, j;
144
145	if(!sel)
146		return;
147	i = arg ? atoi(arg) : 0;
148	sel->tags[i] = !sel->tags[i];
149	for(j = 0; j < ntags && !sel->tags[j]; j++);
150	if(j == ntags)
151		sel->tags[i] = True;
152	arrange();
153}
154
155void
156toggleview(const char *arg) {
157	int i, j;
158
159	i = arg ? atoi(arg) : 0;
160	seltag[i] = !seltag[i];
161	for(j = 0; j < ntags && !seltag[j]; j++);
162	if(j == ntags)
163		seltag[i] = True; /* cannot toggle last view */
164	arrange();
165}
166
167void
168view(const char *arg) {
169	int i;
170
171	for(i = 0; i < ntags; i++)
172		seltag[i] = arg == NULL;
173	i = arg ? atoi(arg) : 0;
174	if(i >= 0 && i < ntags)
175		seltag[i] = True;
176	arrange();
177}