all repos — dwm @ 5a1a2edf0e584e660e16d2e01094851e0f9161e2

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 <X11/Xutil.h>
  7
  8/* static */
  9
 10typedef struct {
 11	const char *prop;
 12	const char *tags;
 13	Bool isfloating;
 14} Rule;
 15
 16typedef struct {
 17	regex_t *propregex;
 18	regex_t *tagregex;
 19} Regs;
 20
 21TAGS
 22RULES
 23
 24static Regs *regs = NULL;
 25static unsigned int nrules = 0;
 26
 27/* extern */
 28
 29void
 30compileregs(void) {
 31	unsigned int i;
 32	regex_t *reg;
 33
 34	if(regs)
 35		return;
 36	nrules = sizeof rule / sizeof rule[0];
 37	regs = emallocz(nrules * sizeof(Regs));
 38	for(i = 0; i < nrules; i++) {
 39		if(rule[i].prop) {
 40			reg = emallocz(sizeof(regex_t));
 41			if(regcomp(reg, rule[i].prop, REG_EXTENDED))
 42				free(reg);
 43			else
 44				regs[i].propregex = reg;
 45		}
 46		if(rule[i].tags) {
 47			reg = emallocz(sizeof(regex_t));
 48			if(regcomp(reg, rule[i].tags, REG_EXTENDED))
 49				free(reg);
 50			else
 51				regs[i].tagregex = reg;
 52		}
 53	}
 54}
 55
 56Bool
 57isvisible(Client *c) {
 58	unsigned int i;
 59
 60	for(i = 0; i < ntags; i++)
 61		if(c->tags[i] && seltag[i])
 62			return True;
 63	return False;
 64}
 65
 66void
 67settags(Client *c, Client *trans) {
 68	char prop[512];
 69	unsigned int i, j;
 70	regmatch_t tmp;
 71	Bool matched = trans != NULL;
 72	XClassHint ch = { 0 };
 73
 74	if(matched)
 75		for(i = 0; i < ntags; i++)
 76			c->tags[i] = trans->tags[i];
 77	else {
 78		XGetClassHint(dpy, c->win, &ch);
 79		snprintf(prop, sizeof prop, "%s:%s:%s",
 80				ch.res_class ? ch.res_class : "",
 81				ch.res_name ? ch.res_name : "", c->name);
 82		for(i = 0; i < nrules; i++)
 83			if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0)) {
 84				c->isfloating = rule[i].isfloating;
 85				for(j = 0; regs[i].tagregex && j < ntags; j++) {
 86					if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
 87						matched = True;
 88						c->tags[j] = True;
 89					}
 90				}
 91			}
 92		if(ch.res_class)
 93			XFree(ch.res_class);
 94		if(ch.res_name)
 95			XFree(ch.res_name);
 96	}
 97	if(!matched)
 98		for(i = 0; i < ntags; i++)
 99			c->tags[i] = seltag[i];
100}
101
102void
103tag(const char *arg) {
104	int i;
105
106	if(!sel)
107		return;
108	for(i = 0; i < ntags; i++)
109		sel->tags[i] = arg == NULL;
110	i = arg ? atoi(arg) : 0;
111	if(i >= 0 && i < ntags)
112		sel->tags[i] = True;
113	lt->arrange();
114}
115
116void
117toggletag(const char *arg) {
118	int i, j;
119
120	if(!sel)
121		return;
122	i = arg ? atoi(arg) : 0;
123	sel->tags[i] = !sel->tags[i];
124	for(j = 0; j < ntags && !sel->tags[j]; j++);
125	if(j == ntags)
126		sel->tags[i] = True;
127	lt->arrange();
128}
129
130void
131toggleview(const char *arg) {
132	int i, j;
133
134	i = arg ? atoi(arg) : 0;
135	seltag[i] = !seltag[i];
136	for(j = 0; j < ntags && !seltag[j]; j++);
137	if(j == ntags)
138		seltag[i] = True; /* cannot toggle last view */
139	lt->arrange();
140}
141
142void
143view(const char *arg) {
144	int i;
145
146	for(i = 0; i < ntags; i++)
147		seltag[i] = arg == NULL;
148	i = arg ? atoi(arg) : 0;
149	if(i >= 0 && i < ntags)
150		seltag[i] = True;
151	lt->arrange();
152}