all repos — dwm @ 50be6c8b67c500ee4aa07919609fa80785fd389d

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