summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swift/Controllers')
-rw-r--r--Swift/Controllers/Chat/ChatController.cpp2
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.cpp8
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.h2
-rw-r--r--Swift/Controllers/Chat/ChatMessageParser.cpp137
-rw-r--r--Swift/Controllers/Chat/ChatMessageParser.h4
-rw-r--r--Swift/Controllers/HighlightRule.h3
6 files changed, 110 insertions, 46 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 13fd22b..af35984 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -303,7 +303,7 @@ void ChatController::postSendMessage(const std::string& body, boost::shared_ptr<
boost::shared_ptr<Replace> replace = sentStanza->getPayload<Replace>();
if (replace) {
eraseIf(unackedStanzas_, PairSecondEquals<boost::shared_ptr<Stanza>, std::string>(myLastMessageUIID_));
- replaceMessage(body, myLastMessageUIID_, boost::posix_time::microsec_clock::universal_time(), HighlightAction());
+ replaceMessage(body, myLastMessageUIID_, true, boost::posix_time::microsec_clock::universal_time(), HighlightAction());
} else {
myLastMessageUIID_ = addMessage(body, QT_TRANSLATE_NOOP("", "me"), true, labelsEnabled_ ? chatWindow_->getSelectedSecurityLabel().getLabel() : boost::shared_ptr<SecurityLabel>(), avatarManager_->getAvatarPath(selfJID_), boost::posix_time::microsec_clock::universal_time(), HighlightAction());
}
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp
index 23137dc..272a0fb 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.cpp
+++ b/Swift/Controllers/Chat/ChatControllerBase.cpp
@@ -201,15 +201,15 @@ std::string ChatControllerBase::addMessage(const std::string& message, const std
if (boost::starts_with(message, "/me ")) {
return chatWindow_->addAction(chatMessageParser_->parseMessageBody(String::getSplittedAtFirst(message, ' ').second), senderName, senderIsSelf, label, pathToString(avatarPath), time, highlight);
} else {
- return chatWindow_->addMessage(chatMessageParser_->parseMessageBody(message), senderName, senderIsSelf, label, pathToString(avatarPath), time, highlight);
+ return chatWindow_->addMessage(chatMessageParser_->parseMessageBody(message,senderIsSelf), senderName, senderIsSelf, label, pathToString(avatarPath), time, highlight);
}
}
-void ChatControllerBase::replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight) {
+void ChatControllerBase::replaceMessage(const std::string& message, const std::string& id, bool senderIsSelf, const boost::posix_time::ptime& time, const HighlightAction& highlight) {
if (boost::starts_with(message, "/me ")) {
chatWindow_->replaceWithAction(chatMessageParser_->parseMessageBody(String::getSplittedAtFirst(message, ' ').second), id, time, highlight);
} else {
- chatWindow_->replaceMessage(chatMessageParser_->parseMessageBody(message), id, time, highlight);
+ chatWindow_->replaceMessage(chatMessageParser_->parseMessageBody(message,senderIsSelf), id, time, highlight);
}
}
@@ -280,7 +280,7 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m
std::map<JID, std::string>::iterator lastMessage;
lastMessage = lastMessagesUIID_.find(from);
if (lastMessage != lastMessagesUIID_.end()) {
- replaceMessage(body, lastMessagesUIID_[from], timeStamp, highlight);
+ replaceMessage(body, lastMessagesUIID_[from], isIncomingMessageFromMe(message), timeStamp, highlight);
}
}
else {
diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h
index 7db94a4..0a955e6 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.h
+++ b/Swift/Controllers/Chat/ChatControllerBase.h
@@ -55,7 +55,7 @@ namespace Swift {
virtual void setAvailableServerFeatures(boost::shared_ptr<DiscoInfo> info);
void handleIncomingMessage(boost::shared_ptr<MessageEvent> message);
std::string addMessage(const std::string& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const boost::filesystem::path& avatarPath, const boost::posix_time::ptime& time, const HighlightAction& highlight);
- void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time, const HighlightAction& highlight);
+ void replaceMessage(const std::string& message, const std::string& id, bool senderIsSelf, const boost::posix_time::ptime& time, const HighlightAction& highlight);
virtual void setOnline(bool online);
virtual void setEnabled(bool enabled);
virtual void setToJID(const JID& jid) {toJID_ = jid;}
diff --git a/Swift/Controllers/Chat/ChatMessageParser.cpp b/Swift/Controllers/Chat/ChatMessageParser.cpp
index 8449901..de4abb1 100644
--- a/Swift/Controllers/Chat/ChatMessageParser.cpp
+++ b/Swift/Controllers/Chat/ChatMessageParser.cpp
@@ -27,7 +27,7 @@ namespace Swift {
typedef std::pair<std::string, std::string> StringPair;
- ChatWindow::ChatMessage ChatMessageParser::parseMessageBody(const std::string& body) {
+ ChatWindow::ChatMessage ChatMessageParser::parseMessageBody(const std::string& body, bool senderIsSelf) {
ChatWindow::ChatMessage parsedMessage;
std::string remaining = body;
/* Parse one, URLs */
@@ -52,9 +52,20 @@ namespace Swift {
}
}
}
-
+ /* do emoticon substitution */
+ parsedMessage = emoticonHighlight(parsedMessage);
+ if (!senderIsSelf) { /* do not highlight our own messsages */
+ /* do word-based color highlighting */
+ parsedMessage = splitHighlight(parsedMessage);
+ }
+
+ return parsedMessage;
+ }
+
+ ChatWindow::ChatMessage ChatMessageParser::emoticonHighlight(const ChatWindow::ChatMessage& message)
+ {
std::string regexString;
/* Parse two, emoticons */
foreach (StringPair emoticon, emoticons_) {
@@ -62,52 +73,100 @@ namespace Swift {
regexString += regexString.empty() ? "(" : "|";
regexString += Regex::escape(emoticon.first);
}
- if (!regexString.empty()) {
- regexString += ")";
- boost::regex emoticonRegex(regexString);
-
- ChatWindow::ChatMessage newMessage;
- foreach (boost::shared_ptr<ChatWindow::ChatMessagePart> part, parsedMessage.getParts()) {
- boost::shared_ptr<ChatWindow::ChatTextMessagePart> textPart;
- if ((textPart = boost::dynamic_pointer_cast<ChatWindow::ChatTextMessagePart>(part))) {
- try {
- boost::match_results<std::string::const_iterator> match;
- const std::string& text = textPart->text;
- std::string::const_iterator start = text.begin();
- while (regex_search(start, text.end(), match, emoticonRegex)) {
- std::string::const_iterator matchStart = match[0].first;
- std::string::const_iterator matchEnd = match[0].second;
- if (start != matchStart) {
- /* If we're skipping over plain text since the previous emoticon, record it as plain text */
- newMessage.append(boost::make_shared<ChatWindow::ChatTextMessagePart>(std::string(start, matchStart)));
- }
- boost::shared_ptr<ChatWindow::ChatEmoticonMessagePart> emoticonPart = boost::make_shared<ChatWindow::ChatEmoticonMessagePart>();
- std::map<std::string, std::string>::const_iterator emoticonIterator = emoticons_.find(match.str());
- assert (emoticonIterator != emoticons_.end());
- const StringPair& emoticon = *emoticonIterator;
- emoticonPart->imagePath = emoticon.second;
- emoticonPart->alternativeText = emoticon.first;
- newMessage.append(emoticonPart);
- start = matchEnd;
- }
- if (start != text.end()) {
- /* If there's plain text after the last emoticon, record it */
- newMessage.append(boost::make_shared<ChatWindow::ChatTextMessagePart>(std::string(start, text.end())));
- }
+ if (regexString.empty()) {
+ return message;
+ }
+
+ regexString += ")";
+ boost::regex emoticonRegex(regexString);
+
+ ChatWindow::ChatMessage newMessage;
+ foreach (boost::shared_ptr<ChatWindow::ChatMessagePart> part, message.getParts()) {
+ boost::shared_ptr<ChatWindow::ChatTextMessagePart> textPart;
+ if ((textPart = boost::dynamic_pointer_cast<ChatWindow::ChatTextMessagePart>(part))) {
+ try {
+ boost::match_results<std::string::const_iterator> match;
+ const std::string& text = textPart->text;
+ std::string::const_iterator start = text.begin();
+ while (regex_search(start, text.end(), match, emoticonRegex)) {
+ std::string::const_iterator matchStart = match[0].first;
+ std::string::const_iterator matchEnd = match[0].second;
+ if (start != matchStart) {
+ /* If we're skipping over plain text since the previous emoticon, record it as plain text */
+ newMessage.append(boost::make_shared<ChatWindow::ChatTextMessagePart>(std::string(start, matchStart)));
+ }
+ boost::shared_ptr<ChatWindow::ChatEmoticonMessagePart> emoticonPart = boost::make_shared<ChatWindow::ChatEmoticonMessagePart>();
+ std::map<std::string, std::string>::const_iterator emoticonIterator = emoticons_.find(match.str());
+ assert (emoticonIterator != emoticons_.end());
+ const StringPair& emoticon = *emoticonIterator;
+ emoticonPart->imagePath = emoticon.second;
+ emoticonPart->alternativeText = emoticon.first;
+ newMessage.append(emoticonPart);
+ start = matchEnd;
}
- catch (std::runtime_error) {
- /* Basically too expensive to compute the regex results and it gave up, so pass through as text */
- newMessage.append(part);
+ if (start != text.end()) {
+ /* If there's plain text after the last emoticon, record it */
+ newMessage.append(boost::make_shared<ChatWindow::ChatTextMessagePart>(std::string(start, text.end())));
}
}
- else {
+ catch (std::runtime_error) {
+ /* Basically too expensive to compute the regex results and it gave up, so pass through as text */
newMessage.append(part);
}
+ } else {
+ newMessage.append(part);
}
- parsedMessage = newMessage;
+ }
+
+ return newMessage;
+ }
+ ChatWindow::ChatMessage ChatMessageParser::splitHighlight(const ChatWindow::ChatMessage& message)
+ {
+ ChatWindow::ChatMessage parsedMessage = message;
+
+ foreach(const HighlightRule &rule, highlightRules_) {
+ foreach(const boost::regex &regex, rule.getKeywordRegex()) {
+ ChatWindow::ChatMessage newMessage;
+ foreach (boost::shared_ptr<ChatWindow::ChatMessagePart> part, parsedMessage.getParts()) {
+ boost::shared_ptr<ChatWindow::ChatTextMessagePart> textPart;
+ if ((textPart = boost::dynamic_pointer_cast<ChatWindow::ChatTextMessagePart>(part))) {
+ try {
+ boost::match_results<std::string::const_iterator> match;
+ const std::string& text = textPart->text;
+ std::string::const_iterator start = text.begin();
+ while (regex_search(start, text.end(), match, regex)) {
+ std::string::const_iterator matchStart = match[0].first;
+ std::string::const_iterator matchEnd = match[0].second;
+ if (start != matchStart) {
+ /* If we're skipping over plain text since the previous emoticon, record it as plain text */
+ newMessage.append(boost::make_shared<ChatWindow::ChatTextMessagePart>(std::string(start, matchStart)));
+ }
+ boost::shared_ptr<ChatWindow::ChatHighlightingMessagePart> highlightPart = boost::make_shared<ChatWindow::ChatHighlightingMessagePart>();
+ highlightPart->text = match.str();
+ highlightPart->foregroundColor = rule.getAction().getTextColor();
+ highlightPart->backgroundColor = rule.getAction().getTextBackground();
+ newMessage.append(highlightPart);
+ start = matchEnd;
+ }
+ if (start != text.end()) {
+ /* If there's plain text after the last emoticon, record it */
+ newMessage.append(boost::make_shared<ChatWindow::ChatTextMessagePart>(std::string(start, text.end())));
+ }
+ }
+ catch (std::runtime_error) {
+ /* Basically too expensive to compute the regex results and it gave up, so pass through as text */
+ newMessage.append(part);
+ }
+ } else {
+ newMessage.append(part);
+ }
+ }
+ parsedMessage = newMessage;
+ }
}
+
return parsedMessage;
}
}
diff --git a/Swift/Controllers/Chat/ChatMessageParser.h b/Swift/Controllers/Chat/ChatMessageParser.h
index dd0d1bd..e899246 100644
--- a/Swift/Controllers/Chat/ChatMessageParser.h
+++ b/Swift/Controllers/Chat/ChatMessageParser.h
@@ -15,8 +15,10 @@ namespace Swift {
class ChatMessageParser {
public:
ChatMessageParser(const std::map<std::string, std::string>& emoticons, const std::vector<HighlightRule>& highlightRules);
- ChatWindow::ChatMessage parseMessageBody(const std::string& body);
+ ChatWindow::ChatMessage parseMessageBody(const std::string& body, bool senderIsSelf = false);
private:
+ ChatWindow::ChatMessage emoticonHighlight(const ChatWindow::ChatMessage& parsedMessage);
+ ChatWindow::ChatMessage splitHighlight(const ChatWindow::ChatMessage& parsedMessage);
std::map<std::string, std::string> emoticons_;
std::vector<HighlightRule> highlightRules_;
diff --git a/Swift/Controllers/HighlightRule.h b/Swift/Controllers/HighlightRule.h
index 523be47..ac1b6be 100644
--- a/Swift/Controllers/HighlightRule.h
+++ b/Swift/Controllers/HighlightRule.h
@@ -30,9 +30,11 @@ namespace Swift {
const std::vector<std::string>& getSenders() const { return senders_; }
void setSenders(const std::vector<std::string>&);
+ const std::vector<boost::regex>& getSenderRegex() const { return senderRegex_; }
const std::vector<std::string>& getKeywords() const { return keywords_; }
void setKeywords(const std::vector<std::string>&);
+ const std::vector<boost::regex>& getKeywordRegex() const { return keywordRegex_; }
bool getNickIsKeyword() const { return nickIsKeyword_; }
void setNickIsKeyword(bool);
@@ -87,6 +89,7 @@ namespace Swift {
ar & matchCase_;
ar & matchWholeWords_;
ar & action_;
+ updateRegex();
}
}