From c849d3c7ffc518d85a365664530f1faa102cf83f Mon Sep 17 00:00:00 2001 From: markt Date: Tue, 23 Oct 2007 17:30:49 +0000 Subject: allow negated patterns --- ChangeLog | 3 +++ src/ClientPattern.cc | 28 +++++++++++++++++++--------- src/ClientPattern.hh | 3 ++- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index e4024fc..2b9d305 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ (Format: Year/Month/Day) Changes for 1.0.1: +*07/10/23: + * Allow negated patterns, e.g. (name!=xterm) (Mark) + ClientPattern.cc/hh *07/10/22: * Added option "mouse" to client pattern ( Henrik ) This is usefull for xinerama. For example: 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): memstr.assign(match, 0, eq); // memstr = our identifier expr.assign(match, eq+1, match.length()); } + bool negate = false; + if (!memstr.empty() && memstr[memstr.length()-1] == '!') { + negate = true; + memstr.assign(memstr, 0, memstr.length()-1); + } if (strcasecmp(memstr.c_str(), "name") == 0) { prop = NAME; } else if (strcasecmp(memstr.c_str(), "class") == 0) { @@ -132,7 +137,7 @@ ClientPattern::ClientPattern(const char *str, bool default_no_transient): prop = NAME; expr = match; } - had_error = !addTerm(expr, prop); + had_error = !addTerm(expr, prop, negate); pos += err; } } @@ -266,13 +271,15 @@ bool ClientPattern::match(const Focusable &win) const { // workspaces don't necessarily have unique names, so we want to // compare numbers instead of strings if ((*it)->prop == WORKSPACE && (!win.fbwindow() || - win.fbwindow()->workspaceNumber() != - win.screen().currentWorkspaceID())) + !((*it)->negate ^ + (win.fbwindow()->workspaceNumber() == + win.screen().currentWorkspaceID())))) return false; else { WinClient *focused = FocusControl::focusedWindow(); - if (!focused || getProperty((*it)->prop, win) != - getProperty((*it)->prop, *focused)) + if (!focused || !((*it)->negate ^ + (getProperty((*it)->prop, win) == + getProperty((*it)->prop, *focused)))) return false; } } else if ((*it)->prop == HEAD && @@ -291,10 +298,11 @@ bool ClientPattern::match(const Focusable &win) const { } char num[32]; sprintf(num, "%d", win.screen().getHead(x, y)); - if (getProperty((*it)->prop, win) != num) + if (!(*it)->negate ^ (getProperty((*it)->prop, win) == num)) return false; - } else if (!(*it)->regexp.match(getProperty((*it)->prop, win))) + } else if (!(*it)->negate ^ + (*it)->regexp.match(getProperty((*it)->prop, win))) return false; } return true; @@ -303,11 +311,12 @@ bool ClientPattern::match(const Focusable &win) const { // add an expression to match against // The first argument is a regular expression, the second is the member // function that we wish to match against. -bool ClientPattern::addTerm(const string &str, WinProperty prop) { +bool ClientPattern::addTerm(const string &str, WinProperty prop, bool negate) { Term *term = new Term(str, true); term->orig = str; term->prop = prop; + term->negate = negate; if (term->regexp.error()) { delete term; @@ -386,7 +395,8 @@ bool ClientPattern::equals(const ClientPattern &pat) const { Terms::const_iterator other_it = pat.m_terms.begin(); Terms::const_iterator other_it_end = pat.m_terms.end(); for (; it != it_end && other_it != other_it_end; ++it, ++other_it) { - if ((*it)->orig != (*other_it)->orig) + if ((*it)->orig != (*other_it)->orig || + (*it)->negate != (*other_it)->negate) return false; } 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: * @param prop is the member function that we wish to match against * @return false if the regexp wasn't valid */ - bool addTerm(const std::string &str, WinProperty prop); + bool addTerm(const std::string &str, WinProperty prop, bool negate = false); inline void addMatch() { ++m_nummatches; } @@ -99,6 +99,7 @@ private: std::string orig; RegExp regexp; WinProperty prop; + bool negate; }; -- cgit v0.11.2