From 54aad4467142079f74471da6396ad31c9df389df Mon Sep 17 00:00:00 2001
From: Catalin Badea <catalin.badea392@gmail.com>
Date: Fri, 13 Apr 2012 22:52:51 +0300
Subject: Fix correction from breaking /me actions

Check if the new message is an action when using correct last message.

Resolves: #1053

License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details.

diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 610c8e8..5602dcd 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -197,7 +197,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_));
-		chatWindow_->replaceMessage(body, myLastMessageUIID_, boost::posix_time::microsec_clock::universal_time());
+		replaceMessage(body, myLastMessageUIID_, boost::posix_time::microsec_clock::universal_time());
 	} else {
 		myLastMessageUIID_ = addMessage(body, QT_TRANSLATE_NOOP("", "me"), true, labelsEnabled_ ? chatWindow_->getSelectedSecurityLabel().getLabel() : boost::shared_ptr<SecurityLabel>(), std::string(avatarManager_->getAvatarPath(selfJID_).string()), boost::posix_time::microsec_clock::universal_time());
 	}
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp
index 8523591..16ff885 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.cpp
+++ b/Swift/Controllers/Chat/ChatControllerBase.cpp
@@ -165,6 +165,14 @@ std::string ChatControllerBase::addMessage(const std::string& message, const std
 	}
 }
 
+void ChatControllerBase::replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time) {
+	if (boost::starts_with(message, "/me ")) {
+		chatWindow_->replaceWithAction(String::getSplittedAtFirst(message, ' ').second, id, time);
+	} else {
+		chatWindow_->replaceMessage(message, id, time);
+	}
+}
+
 bool ChatControllerBase::isFromContact(const JID& from) {
 	return from.toBare() == toJID_.toBare();
 }
@@ -221,7 +229,7 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m
 			std::map<JID, std::string>::iterator lastMessage;
 			lastMessage = lastMessagesUIID_.find(from);
 			if (lastMessage != lastMessagesUIID_.end()) {
-				chatWindow_->replaceMessage(body, lastMessagesUIID_[from], timeStamp);
+				replaceMessage(body, lastMessagesUIID_[from], timeStamp);
 			}
 		}
 		else {
diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h
index a4d23c0..8a8161d 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.h
+++ b/Swift/Controllers/Chat/ChatControllerBase.h
@@ -46,6 +46,7 @@ namespace Swift {
 			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 std::string& avatarPath, const boost::posix_time::ptime& time);
+			void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time);
 			virtual void setOnline(bool online);
 			virtual void setEnabled(bool enabled);
 			virtual void setToJID(const JID& jid) {toJID_ = jid;};
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index 9305314..2986de1 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -52,6 +52,7 @@ namespace Swift {
 			virtual void addPresenceMessage(const std::string& message) = 0;
 			virtual void addErrorMessage(const std::string& message) = 0;
 			virtual void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time) = 0;
+			virtual void replaceWithAction(const std::string& message, const std::string& id, const boost::posix_time::ptime& time) = 0;
 			
 			// File transfer related stuff
 			virtual std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes) = 0;
diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h
index f92bd8b..800a5dd 100644
--- a/Swift/Controllers/UnitTest/MockChatWindow.h
+++ b/Swift/Controllers/UnitTest/MockChatWindow.h
@@ -42,6 +42,7 @@ namespace Swift {
 			virtual void setTabComplete(TabComplete*) {};
 			virtual void replaceLastMessage(const std::string&) {};
 			virtual void replaceMessage(const std::string&, const std::string&, const boost::posix_time::ptime&) {};
+			virtual void replaceWithAction(const std::string& message, const std::string& id, const boost::posix_time::ptime& time) {};
 			void setAckState(const std::string& /*id*/, AckState /*state*/) {};
 			virtual void flash() {};
 			virtual void setAlert(const std::string& /*alertText*/, const std::string& /*buttonText*/) {};
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index 5223ddb..e4cb004 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -658,11 +658,24 @@ void QtChatWindow::addSystemMessage(const std::string& message) {
 	previousMessageKind_ = PreviousMessageWasSystem;
 }
 
+void QtChatWindow::replaceWithAction(const std::string& message, const std::string& id, const boost::posix_time::ptime& time) {
+	replaceMessage(" *" + message + "*", id, time, "font-style:italic ");
+}
+
 void QtChatWindow::replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time) {
+	replaceMessage(message, id, time, "");
+}
+
+void QtChatWindow::replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time, const QString& style) {
 	if (!id.empty()) {
 		QString messageHTML(Qt::escape(P2QSTRING(message)));
 		messageHTML = P2QSTRING(Linkify::linkify(Q2PSTRING(messageHTML)));
 		messageHTML.replace("\n","<br/>");
+
+		QString styleSpanStart = style == "" ? "" : "<span style=\"" + style + "\">";
+		QString styleSpanEnd = style == "" ? "" : "</span>";
+		messageHTML = styleSpanStart + messageHTML + styleSpanEnd;
+
 		messageLog_->replaceMessage(messageHTML, P2QSTRING(id), B2QDATE(time));
 	}
 	else {
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index 9db1884..1d1959d 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -54,6 +54,7 @@ namespace Swift {
 			void addPresenceMessage(const std::string& message);
 			void addErrorMessage(const std::string& errorMessage);
 			void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time);
+			void replaceWithAction(const std::string& message, const std::string& id, const boost::posix_time::ptime& time);
 			// File transfer related stuff
 			std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes);
 			void setFileTransferProgress(std::string id, const int percentageDone);
@@ -144,6 +145,7 @@ namespace Swift {
 			void beginCorrection();
 			void cancelCorrection();
 			std::string addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const QString& style, const boost::posix_time::ptime& time);
+			void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time, const QString& style);
 			void handleOccupantSelectionChanged(RosterItem* item);
 			bool appendToPreviousCheck(PreviousMessageKind messageKind, const std::string& senderName, bool senderIsSelf) const;
 
-- 
cgit v0.10.2-6-g49f6