linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #05450
[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2881: Format chat links
------------------------------------------------------------
revno: 2881
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Sun 2012-03-18 16:21:56 +0100
message:
Format chat links
modified:
changelog.txt
dcpp/ChatMessage.cpp
win32/AspectChat.h
win32/HtmlToRtf.cpp
win32/HubFrame.cpp
--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk
Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'changelog.txt'
--- changelog.txt 2012-03-11 16:36:44 +0000
+++ changelog.txt 2012-03-18 15:21:56 +0000
@@ -25,6 +25,7 @@
* Fix discrepancies in the /conn chat command (poy)
* Update boost to version 1.49
* [L#947895] Move the "follow redirect" command to inline chat links (poy)
+* Format chat links (poy)
-- 0.791 2012-01-14 --
* Update translations
=== modified file 'dcpp/ChatMessage.cpp'
--- dcpp/ChatMessage.cpp 2012-03-11 18:06:18 +0000
+++ dcpp/ChatMessage.cpp 2012-03-18 15:21:56 +0000
@@ -26,8 +26,14 @@
#include "SimpleXML.h"
#include "Util.h"
+#include <boost/range/adaptor/reversed.hpp>
+
namespace dcpp {
+using std::make_pair;
+using std::map;
+using std::pair;
+
ChatMessage::ChatMessage(const string& text, const OnlineUser* from,
const OnlineUser* to, const OnlineUser* replyTo,
bool thirdPerson, time_t messageTimestamp) :
@@ -91,7 +97,101 @@
}
message += tmp;
- htmlMessage += addSpan("text", tmp, Util::emptyString) + "</span>";
+
+ /* format the message; this will involve adding custom tags. this table holds the tags to be
+ added along with their position. */
+ struct Tag { string s; bool opening; size_t otherTag; };
+ map<size_t, Tag> tags;
+
+ /* link formatting - optimize the lookup a bit by using the fact that every link identifier
+ (except www ones) contains a colon. */
+ /// @todo add support for spaces within links enclosed by brackets / quotes (see URI RFC)
+ /// @todo friendly magnet links
+ auto addLink = [&tmp, &xmlTmp, &tags](size_t begin, size_t end) {
+ Tag openingTag = { "<a href=\"" + SimpleXML::escape(tmp.substr(begin, end - begin), xmlTmp, true) + "\">", true, end },
+ closingTag = { "</a>", false, begin };
+ tags.emplace(begin, std::move(openingTag));
+ tags.emplace(end, std::move(closingTag));
+ };
+
+ static const string delimiters = " \t\r\n<>\"";
+
+ i = 0;
+ size_t begin, end;
+ const auto n = tmp.size();
+ while((i = tmp.find(':', i)) != string::npos) {
+
+ if((begin = tmp.find_last_of(delimiters, i)) == string::npos) begin = 0; else ++begin;
+ if((end = tmp.find_first_of(delimiters, i + 1)) == string::npos) end = n;
+
+ if(i > 0 &&
+ (i + 4 < n && tmp[i + 1] == '/' && tmp[i + 2] == '/') || // "http://", etc
+ (i >= begin + 6 && !tmp.compare(begin, 6, "magnet")) ||
+ (i >= begin + 6 && !tmp.compare(begin, 6, "mailto")))
+ {
+ addLink(begin, end);
+ i = end;
+
+ } else {
+ ++i;
+ }
+ }
+
+ // check for www links.
+ i = 0;
+ while((i = tmp.find("www.", i)) != string::npos) {
+ if(i + 5 <= n && (i == 0 || delimiters.find(tmp[i - 1]) != string::npos)) {
+ if((end = tmp.find_first_of(delimiters, i + 4)) == string::npos) end = n;
+ if(i + 5 <= end) {
+ addLink(i, end);
+ i = end;
+ }
+ }
+ i += 5;
+ }
+
+ htmlMessage += "<span id=\"text\">";
+
+ /* write tags and the message data. support entangled tags, such as:
+ <a> <b> </a> </b> -> <a> <b> </b></a><b> </b> */
+
+ size_t pos = 0;
+ vector<size_t> openTags;
+
+ for(auto& tag: tags) {
+ htmlMessage += SimpleXML::escape(tmp.substr(pos, tag.first - pos), xmlTmp, false);
+ pos = tag.first;
+
+ if(tag.second.opening) {
+ htmlMessage += tag.second.s;
+ openTags.push_back(tag.first);
+
+ } else {
+ if(openTags.back() == tag.second.otherTag) {
+ // common case: no entangled tag; just write the closing tag.
+ htmlMessage += tag.second.s;
+ openTags.pop_back();
+
+ } else {
+ // there are entangled tags: write closing & opening tags of currently open tags.
+ for(auto key: openTags | boost::adaptors::reversed) { if(key >= tag.second.otherTag) {
+ htmlMessage += tags[tags[key].otherTag].s;
+ } }
+ openTags.erase(remove(openTags.begin(), openTags.end(), tag.second.otherTag), openTags.end());
+ for(auto key: openTags) { if(key >= tag.second.otherTag) {
+ htmlMessage += tags[key].s;
+ } }
+ }
+ }
+ }
+
+ if(pos != n) {
+ htmlMessage += SimpleXML::escape(tmp.substr(pos), xmlTmp, false);
+ }
+
+ htmlMessage += "</span></span>";
+
+ dcdebug("html: %s\n", htmlMessage.c_str());
/// @todo send this to plugins
}
=== modified file 'win32/AspectChat.h'
--- win32/AspectChat.h 2012-03-11 18:06:18 +0000
+++ win32/AspectChat.h 2012-03-18 15:21:56 +0000
@@ -52,7 +52,6 @@
cs.style |= ES_READONLY;
chat = dwt::WidgetCreator<RichTextBox>::create(parent, cs);
chat->setTextLimit(65536);
- WinUtil::handleDblClicks(chat);
}
{
=== modified file 'win32/HtmlToRtf.cpp'
--- win32/HtmlToRtf.cpp 2012-03-11 18:06:18 +0000
+++ win32/HtmlToRtf.cpp 2012-03-18 15:21:56 +0000
@@ -26,6 +26,7 @@
#include <dcpp/debug.h>
#include <dcpp/Flags.h>
#include <dcpp/ScopedFunctor.h>
+#include <dcpp/SettingsManager.h>
#include <dcpp/SimpleXML.h>
#include <dcpp/StringTokenizer.h>
#include <dcpp/Text.h>
@@ -115,6 +116,7 @@
auto& context = contexts.back();
context.link = link;
context.setFlag(Context::Underlined);
+ context.textColor = addColor(SETTING(LINK_COLOR)); /// @todo move to styles
}
}
@@ -218,6 +220,10 @@
if(isSet(Underlined)) { ret += "\\ul"; }
ret += " ";
+
+ // add an invisible space; otherwise link formatting may get lost...
+ if(!link.empty()) { ret += "{\\v }"; }
+
return Text::toT(ret);
}
=== modified file 'win32/HubFrame.cpp'
--- win32/HubFrame.cpp 2012-03-11 18:06:18 +0000
+++ win32/HubFrame.cpp 2012-03-18 15:21:56 +0000
@@ -903,8 +903,7 @@
string tmp;
addStatus(msgT, false);
/// @todo change to "javascript: external.redirect" when switching to an HTML control
- addChatHTML("<span>*** </span><a href=\"redirect: " + SimpleXML::escape(line, tmp, true) +
- "\" style=\"color: #" + Util::cssColor(SETTING(LINK_COLOR)) + ";\">" +
+ addChatHTML("<span>*** </span><a href=\"redirect: " + SimpleXML::escape(line, tmp, true) + "\">" +
SimpleXML::escape(msg, tmp, false) + "</a>");
addedChat(_T("*** ") + msgT);
}