summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ClientPattern.cc28
-rw-r--r--src/ClientPattern.hh3
2 files changed, 21 insertions, 10 deletions
diff --git a/src/ClientPattern.cc b/src/ClientPattern.cc
index 3cb9e9f..937d96b 100644
--- a/src/ClientPattern.cc
+++ b/src/ClientPattern.cc
@@ -99,6 +99,11 @@ ClientPattern::ClientPattern(const char *str, bool default_no_transient):
99 memstr.assign(match, 0, eq); // memstr = our identifier 99 memstr.assign(match, 0, eq); // memstr = our identifier
100 expr.assign(match, eq+1, match.length()); 100 expr.assign(match, eq+1, match.length());
101 } 101 }
102 bool negate = false;
103 if (!memstr.empty() && memstr[memstr.length()-1] == '!') {
104 negate = true;
105 memstr.assign(memstr, 0, memstr.length()-1);
106 }
102 if (strcasecmp(memstr.c_str(), "name") == 0) { 107 if (strcasecmp(memstr.c_str(), "name") == 0) {
103 prop = NAME; 108 prop = NAME;
104 } else if (strcasecmp(memstr.c_str(), "class") == 0) { 109 } else if (strcasecmp(memstr.c_str(), "class") == 0) {
@@ -132,7 +137,7 @@ ClientPattern::ClientPattern(const char *str, bool default_no_transient):
132 prop = NAME; 137 prop = NAME;
133 expr = match; 138 expr = match;
134 } 139 }
135 had_error = !addTerm(expr, prop); 140 had_error = !addTerm(expr, prop, negate);
136 pos += err; 141 pos += err;
137 } 142 }
138 } 143 }
@@ -266,13 +271,15 @@ bool ClientPattern::match(const Focusable &win) const {
266 // workspaces don't necessarily have unique names, so we want to 271 // workspaces don't necessarily have unique names, so we want to
267 // compare numbers instead of strings 272 // compare numbers instead of strings
268 if ((*it)->prop == WORKSPACE && (!win.fbwindow() || 273 if ((*it)->prop == WORKSPACE && (!win.fbwindow() ||
269 win.fbwindow()->workspaceNumber() != 274 !((*it)->negate ^
270 win.screen().currentWorkspaceID())) 275 (win.fbwindow()->workspaceNumber() ==
276 win.screen().currentWorkspaceID()))))
271 return false; 277 return false;
272 else { 278 else {
273 WinClient *focused = FocusControl::focusedWindow(); 279 WinClient *focused = FocusControl::focusedWindow();
274 if (!focused || getProperty((*it)->prop, win) != 280 if (!focused || !((*it)->negate ^
275 getProperty((*it)->prop, *focused)) 281 (getProperty((*it)->prop, win) ==
282 getProperty((*it)->prop, *focused))))
276 return false; 283 return false;
277 } 284 }
278 } else if ((*it)->prop == HEAD && 285 } else if ((*it)->prop == HEAD &&
@@ -291,10 +298,11 @@ bool ClientPattern::match(const Focusable &win) const {
291 } 298 }
292 char num[32]; 299 char num[32];
293 sprintf(num, "%d", win.screen().getHead(x, y)); 300 sprintf(num, "%d", win.screen().getHead(x, y));
294 if (getProperty((*it)->prop, win) != num) 301 if (!(*it)->negate ^ (getProperty((*it)->prop, win) == num))
295 return false; 302 return false;
296 303
297 } else if (!(*it)->regexp.match(getProperty((*it)->prop, win))) 304 } else if (!(*it)->negate ^
305 (*it)->regexp.match(getProperty((*it)->prop, win)))
298 return false; 306 return false;
299 } 307 }
300 return true; 308 return true;
@@ -303,11 +311,12 @@ bool ClientPattern::match(const Focusable &win) const {
303// add an expression to match against 311// add an expression to match against
304// The first argument is a regular expression, the second is the member 312// The first argument is a regular expression, the second is the member
305// function that we wish to match against. 313// function that we wish to match against.
306bool ClientPattern::addTerm(const string &str, WinProperty prop) { 314bool ClientPattern::addTerm(const string &str, WinProperty prop, bool negate) {
307 315
308 Term *term = new Term(str, true); 316 Term *term = new Term(str, true);
309 term->orig = str; 317 term->orig = str;
310 term->prop = prop; 318 term->prop = prop;
319 term->negate = negate;
311 320
312 if (term->regexp.error()) { 321 if (term->regexp.error()) {
313 delete term; 322 delete term;
@@ -386,7 +395,8 @@ bool ClientPattern::equals(const ClientPattern &pat) const {
386 Terms::const_iterator other_it = pat.m_terms.begin(); 395 Terms::const_iterator other_it = pat.m_terms.begin();
387 Terms::const_iterator other_it_end = pat.m_terms.end(); 396 Terms::const_iterator other_it_end = pat.m_terms.end();
388 for (; it != it_end && other_it != other_it_end; ++it, ++other_it) { 397 for (; it != it_end && other_it != other_it_end; ++it, ++other_it) {
389 if ((*it)->orig != (*other_it)->orig) 398 if ((*it)->orig != (*other_it)->orig ||
399 (*it)->negate != (*other_it)->negate)
390 return false; 400 return false;
391 } 401 }
392 if (it != it_end || other_it != other_it_end) 402 if (it != it_end || other_it != other_it_end)
diff --git a/src/ClientPattern.hh b/src/ClientPattern.hh
index e5f4944..4e9f1ac 100644
--- a/src/ClientPattern.hh
+++ b/src/ClientPattern.hh
@@ -68,7 +68,7 @@ public:
68 * @param prop is the member function that we wish to match against 68 * @param prop is the member function that we wish to match against
69 * @return false if the regexp wasn't valid 69 * @return false if the regexp wasn't valid
70 */ 70 */
71 bool addTerm(const std::string &str, WinProperty prop); 71 bool addTerm(const std::string &str, WinProperty prop, bool negate = false);
72 72
73 inline void addMatch() { ++m_nummatches; } 73 inline void addMatch() { ++m_nummatches; }
74 74
@@ -99,6 +99,7 @@ private:
99 std::string orig; 99 std::string orig;
100 RegExp regexp; 100 RegExp regexp;
101 WinProperty prop; 101 WinProperty prop;
102 bool negate;
102 }; 103 };
103 104
104 105