summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaciej Niedzielski <machekku@uaznia.net>2012-12-21 19:58:24 (GMT)
committerMaciej Niedzielski <machekku@uaznia.net>2013-01-09 12:34:06 (GMT)
commit4ed137080a3d80d20a2cead47f741e3dd2f2d42e (patch)
treef030f0d9b8e61733de4e2bec9cef7715d380af8f /Swift/Controllers/HighlightRule.cpp
parenta8e2d82a1be5e94ac39523fc3e0606fcc261e913 (diff)
downloadswift-4ed137080a3d80d20a2cead47f741e3dd2f2d42e.zip
swift-4ed137080a3d80d20a2cead47f741e3dd2f2d42e.tar.bz2
Highlighting support
Change-Id: Ib6bd42cecff018998117bc1e7db279a62b3af434 License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details.
Diffstat (limited to 'Swift/Controllers/HighlightRule.cpp')
-rw-r--r--Swift/Controllers/HighlightRule.cpp200
1 files changed, 200 insertions, 0 deletions
diff --git a/Swift/Controllers/HighlightRule.cpp b/Swift/Controllers/HighlightRule.cpp
new file mode 100644
index 0000000..01d1228
--- /dev/null
+++ b/Swift/Controllers/HighlightRule.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2012 Maciej Niedzielski
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <algorithm>
+#include <boost/algorithm/string.hpp>
+#include <boost/lambda/lambda.hpp>
+
+#include <Swiften/Base/foreach.h>
+#include <Swift/Controllers/HighlightRule.h>
+
+namespace Swift {
+
+HighlightRule::HighlightRule()
+ : nickIsKeyword_(false)
+ , matchCase_(false)
+ , matchWholeWords_(false)
+ , matchChat_(false)
+ , matchMUC_(false)
+{
+}
+
+boost::regex HighlightRule::regexFromString(const std::string & s) const
+{
+ // escape regex special characters: ^.$| etc
+ // these need to be escaped: [\^\$\|.........]
+ // and then C++ requires '\' to be escaped, too....
+ static const boost::regex esc("([\\^\\.\\$\\|\\(\\)\\[\\]\\*\\+\\?\\/\\{\\}\\\\])");
+ // matched character should be prepended with '\'
+ // replace matched special character with \\\1
+ // and escape once more for C++ rules...
+ static const std::string rep("\\\\\\1");
+ std::string escaped = boost::regex_replace(s , esc, rep);
+
+ std::string word = matchWholeWords_ ? "\\b" : "";
+ boost::regex::flag_type flags = boost::regex::normal;
+ if (!matchCase_) {
+ flags |= boost::regex::icase;
+ }
+ return boost::regex(word + escaped + word, flags);
+}
+
+void HighlightRule::updateRegex() const
+{
+ keywordRegex_.clear();
+ foreach (const std::string & k, keywords_) {
+ keywordRegex_.push_back(regexFromString(k));
+ }
+ senderRegex_.clear();
+ foreach (const std::string & s, senders_) {
+ senderRegex_.push_back(regexFromString(s));
+ }
+}
+
+std::string HighlightRule::boolToString(bool b)
+{
+ return b ? "1" : "0";
+}
+
+bool HighlightRule::boolFromString(const std::string& s)
+{
+ return s == "1";
+}
+
+std::string HighlightRule::toString() const
+{
+ std::vector<std::string> v;
+ v.push_back(boost::join(senders_, "\t"));
+ v.push_back(boost::join(keywords_, "\t"));
+ v.push_back(boolToString(nickIsKeyword_));
+ v.push_back(boolToString(matchChat_));
+ v.push_back(boolToString(matchMUC_));
+ v.push_back(boolToString(matchCase_));
+ v.push_back(boolToString(matchWholeWords_));
+ v.push_back(boolToString(action_.highlightText()));
+ v.push_back(action_.getTextColor());
+ v.push_back(action_.getTextBackground());
+ v.push_back(boolToString(action_.playSound()));
+ v.push_back(action_.getSoundFile());
+ return boost::join(v, "\n");
+}
+
+HighlightRule HighlightRule::fromString(const std::string& s)
+{
+ std::vector<std::string> v;
+ boost::split(v, s, boost::is_any_of("\n"));
+
+ HighlightRule r;
+ int i = 0;
+ try {
+ boost::split(r.senders_, v.at(i++), boost::is_any_of("\t"));
+ r.senders_.erase(std::remove_if(r.senders_.begin(), r.senders_.end(), boost::lambda::_1 == ""), r.senders_.end());
+ boost::split(r.keywords_, v.at(i++), boost::is_any_of("\t"));
+ r.keywords_.erase(std::remove_if(r.keywords_.begin(), r.keywords_.end(), boost::lambda::_1 == ""), r.keywords_.end());
+ r.nickIsKeyword_ = boolFromString(v.at(i++));
+ r.matchChat_ = boolFromString(v.at(i++));
+ r.matchMUC_ = boolFromString(v.at(i++));
+ r.matchCase_ = boolFromString(v.at(i++));
+ r.matchWholeWords_ = boolFromString(v.at(i++));
+ r.action_.setHighlightText(boolFromString(v.at(i++)));
+ r.action_.setTextColor(v.at(i++));
+ r.action_.setTextBackground(v.at(i++));
+ r.action_.setPlaySound(boolFromString(v.at(i++)));
+ r.action_.setSoundFile(v.at(i++));
+ }
+ catch (std::out_of_range) {
+ // this may happen if more properties are added to HighlightRule object, etc...
+ // in such case, default values (set by default constructor) will be used
+ }
+
+ r.updateRegex();
+
+ return r;
+}
+
+bool HighlightRule::isMatch(const std::string& body, const std::string& sender, const std::string& nick, MessageType messageType) const
+{
+ if ((messageType == HighlightRule::ChatMessage && matchChat_) || (messageType == HighlightRule::MUCMessage && matchMUC_)) {
+
+ bool matchesKeyword = keywords_.empty() && (nick.empty() || !nickIsKeyword_);
+ bool matchesSender = senders_.empty();
+
+ foreach (const boost::regex & rx, keywordRegex_) {
+ if (boost::regex_search(body, rx)) {
+ matchesKeyword = true;
+ break;
+ }
+ }
+
+ if (!matchesKeyword && nickIsKeyword_ && !nick.empty()) {
+ if (boost::regex_search(body, regexFromString(nick))) {
+ matchesKeyword = true;
+ }
+ }
+
+ foreach (const boost::regex & rx, senderRegex_) {
+ if (boost::regex_search(sender, rx)) {
+ matchesSender = true;
+ break;
+ }
+ }
+
+ if (matchesKeyword && matchesSender) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void HighlightRule::setSenders(const std::vector<std::string>& senders)
+{
+ senders_ = senders;
+ updateRegex();
+}
+
+void HighlightRule::setKeywords(const std::vector<std::string>& keywords)
+{
+ keywords_ = keywords;
+ updateRegex();
+}
+
+void HighlightRule::setNickIsKeyword(bool nickIsKeyword)
+{
+ nickIsKeyword_ = nickIsKeyword;
+ updateRegex();
+}
+
+void HighlightRule::setMatchCase(bool matchCase)
+{
+ matchCase_ = matchCase;
+ updateRegex();
+}
+
+void HighlightRule::setMatchWholeWords(bool matchWholeWords)
+{
+ matchWholeWords_ = matchWholeWords;
+ updateRegex();
+}
+
+void HighlightRule::setMatchChat(bool matchChat)
+{
+ matchChat_ = matchChat;
+ updateRegex();
+}
+
+void HighlightRule::setMatchMUC(bool matchMUC)
+{
+ matchMUC_ = matchMUC;
+ updateRegex();
+}
+
+bool HighlightRule::isEmpty() const
+{
+ return senders_.empty() && keywords_.empty() && !nickIsKeyword_ && !matchChat_ && !matchMUC_ && action_.isEmpty();
+}
+
+}