linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #05438
[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2877: switch to Rich Edit 4.1, handle friendly name links
------------------------------------------------------------
revno: 2877
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Sun 2012-03-11 17:34:55 +0100
message:
switch to Rich Edit 4.1, handle friendly name links
modified:
dwt/include/dwt/widgets/RichTextBox.h
dwt/src/widgets/RichTextBox.cpp
win32/HtmlToRtf.cpp
win32/RichTextBox.cpp
win32/RichTextBox.h
win32/WinUtil.cpp
win32/WinUtil.h
--
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 'dwt/include/dwt/widgets/RichTextBox.h'
--- dwt/include/dwt/widgets/RichTextBox.h 2012-01-29 18:05:27 +0000
+++ dwt/include/dwt/widgets/RichTextBox.h 2012-03-11 16:34:55 +0000
@@ -81,6 +81,7 @@
FontPtr font;
bool scrollBarHorizontallyFlag;
bool scrollBarVerticallyFlag;
+ int events; /// additional events caught by this control; see the EM_SETEVENTMASK doc.
/// Fills with default parameters
Seed();
=== modified file 'dwt/src/widgets/RichTextBox.cpp'
--- dwt/src/widgets/RichTextBox.cpp 2012-02-09 19:45:38 +0000
+++ dwt/src/widgets/RichTextBox.cpp 2012-03-11 16:34:55 +0000
@@ -44,19 +44,20 @@
namespace dwt {
-const TCHAR RichTextBox::windowClass[] = RICHEDIT_CLASS;
+const TCHAR RichTextBox::windowClass[] = MSFTEDIT_CLASS;
RichTextBox::Seed::Seed() :
BaseType::Seed(WS_CHILD | WS_TABSTOP | WS_VSCROLL | ES_LEFT | ES_AUTOVSCROLL | ES_MULTILINE | ES_NOHIDESEL),
font(0),
scrollBarHorizontallyFlag(false),
- scrollBarVerticallyFlag(false)
+ scrollBarVerticallyFlag(false),
+ events(ENM_LINK)
{
}
Dispatcher& RichTextBox::makeDispatcher() {
- // Need to load up RichEdit library!
- static LibraryLoader richEditLibrary(_T("riched20.dll"));
+ // msftedit is the DLL containing Rich Edit 4.1, available from XP SP1 onwards.
+ static LibraryLoader richEditLibrary(_T("msftedit.dll"));
return ChainingDispatcher::superClass<RichTextBox>();
}
@@ -68,7 +69,7 @@
setScrollBarHorizontally(cs.scrollBarHorizontallyFlag);
setScrollBarVertically(cs.scrollBarVerticallyFlag);
-
+ sendMessage(EM_SETEVENTMASK, 0, cs.events);
sendMessage(EM_AUTOURLDETECT, FALSE);
/* unlike other common controls, Rich Edits ignore WM_PRINTCLIENT messages. as per
=== modified file 'win32/HtmlToRtf.cpp'
--- win32/HtmlToRtf.cpp 2012-03-05 20:48:24 +0000
+++ win32/HtmlToRtf.cpp 2012-03-11 16:34:55 +0000
@@ -22,6 +22,7 @@
#include "HtmlToRtf.h"
#include <boost/algorithm/string/trim.hpp>
+#include <boost/scoped_array.hpp>
#include <dcpp/debug.h>
#include <dcpp/Flags.h>
@@ -47,11 +48,14 @@
int fontSize;
size_t textColor; // index in the "colors" table
size_t bgColor; // index in the "colors" table
+ string link;
+
Context(dwt::RichTextBox* box, Parser& parser);
+
+ tstring getBegin() const;
+ tstring getEnd() const;
};
- void write(Context& context);
-
size_t addFont(string&& font);
static int rtfFontSize(float px);
size_t addColor(COLORREF color);
@@ -78,7 +82,6 @@
Parser::Parser(dwt::RichTextBox* box) {
// create a default context with the Rich Edit control's current formatting.
contexts.emplace_back(box, *this);
- write(contexts.back());
}
void Parser::startTag(const string& name_, StringPairList& attribs, bool simple) {
@@ -93,7 +96,7 @@
}
contexts.push_back(contexts.back());
- ScopedFunctor([this] { write(contexts.back()); });
+ ScopedFunctor([this] { ret += contexts.back().getBegin(); });
if(name == "b") {
contexts.back().setFlag(Context::Bold);
@@ -107,6 +110,16 @@
return;
}
+ if(name == "a") {
+ const auto& link = getAttrib(attribs, "href", 0);
+ if(!link.empty()) {
+ auto& context = contexts.back();
+ context.link = link;
+ context.setFlag(Context::Underlined);
+ /// @todo custom color
+ }
+ }
+
const auto& style = getAttrib(attribs, "style", 0);
enum { Declaration, Font, Decoration, TextColor, BgColor, Unknown } state = Declaration;
@@ -172,7 +185,7 @@
}
void Parser::endTag(const string& name) {
- ret += _T("}");
+ ret += contexts.back().getEnd();
contexts.pop_back();
}
@@ -193,14 +206,25 @@
bgColor = parser.addColor(box->getBgColor());
}
-void Parser::write(Context& context) {
- string header;
- if(context.isSet(Context::Bold)) { header += "\\b"; }
- if(context.isSet(Context::Italic)) { header += "\\i"; }
- if(context.isSet(Context::Underlined)) { header += "\\ul"; }
- ret += Text::toT("{\\f" + Util::toString(context.font) + "\\fs" + Util::toString(context.fontSize) +
- "\\cf" + Util::toString(context.textColor) + "\\highlight" + Util::toString(context.bgColor) +
- header + " ");
+tstring Parser::Context::getBegin() const {
+ string ret = "{";
+
+ if(!link.empty()) {
+ ret += "\\field{\\*\\fldinst HYPERLINK \"" + link + "\"}{\\fldrslt";
+ }
+
+ ret += "\\f" + Util::toString(font) + "\\fs" + Util::toString(fontSize) +
+ "\\cf" + Util::toString(textColor) + "\\highlight" + Util::toString(bgColor);
+ if(isSet(Bold)) { ret += "\\b"; }
+ if(isSet(Italic)) { ret += "\\i"; }
+ if(isSet(Underlined)) { ret += "\\ul"; }
+
+ ret += " ";
+ return Text::toT(ret);
+}
+
+tstring Parser::Context::getEnd() const {
+ return link.empty() ? _T("}") : _T("}}");
}
size_t Parser::addFont(string&& font) {
=== modified file 'win32/RichTextBox.cpp'
--- win32/RichTextBox.cpp 2012-01-22 20:27:14 +0000
+++ win32/RichTextBox.cpp 2012-03-11 16:34:55 +0000
@@ -21,13 +21,23 @@
#include "RichTextBox.h"
#include "ParamDlg.h"
+#include "WinUtil.h"
RichTextBox::Seed::Seed() :
BaseType::Seed()
{
}
-RichTextBox::RichTextBox(dwt::Widget* parent) : BaseType(parent) {
+RichTextBox::RichTextBox(dwt::Widget* parent) : BaseType(parent), linkF(0) {
+}
+
+void RichTextBox::create(const Seed& seed) {
+ BaseType::create(seed);
+
+ if((seed.events & ENM_LINK) == ENM_LINK) {
+ onRaw([this](WPARAM, LPARAM lParam) { return handleLink(*reinterpret_cast<ENLINK*>(lParam)); },
+ dwt::Message(WM_NOTIFY, EN_LINK));
+ }
}
bool RichTextBox::handleMessage(const MSG& msg, LRESULT& retVal) {
@@ -69,12 +79,11 @@
}
tstring RichTextBox::findTextPopup() {
- tstring param = Util::emptyStringT;
- ParamDlg lineFind(this, T_("Search"), T_("Specify search string"), Util::emptyStringT, false);
+ ParamDlg lineFind(this, T_("Search"), T_("Specify search string"));
if(lineFind.run() == IDOK) {
- param = lineFind.getValue();
+ return lineFind.getValue();
}
- return param;
+ return Util::emptyStringT;
}
void RichTextBox::findTextNew() {
@@ -98,3 +107,39 @@
}
return false;
}
+
+void RichTextBox::onLink(LinkF f) {
+ linkF = f;
+}
+
+LRESULT RichTextBox::handleLink(ENLINK& link) {
+ /* the control doesn't handle click events, just "mouse down" & "mouse up". so we have to make
+ sure the mouse hasn't moved between "down" & "up". */
+ static LPARAM clickPos = 0;
+
+ switch(link.msg) {
+ case WM_LBUTTONDOWN:
+ {
+ clickPos = link.lParam;
+ break;
+ }
+
+ case WM_LBUTTONUP:
+ {
+ if(link.lParam != clickPos)
+ break;
+
+ boost::scoped_array<TCHAR> buf(new TCHAR[link.chrg.cpMax - link.chrg.cpMin + 1]);
+ TEXTRANGE text = { link.chrg, buf.get() };
+ sendMessage(EM_GETTEXTRANGE, 0, reinterpret_cast<LPARAM>(&text));
+ if(!linkF || !linkF(buf.get())) {
+ WinUtil::parseLink(buf.get());
+ }
+ break;
+ }
+
+ /// @todo context menu on rbuttonup
+ /// @todo tooltip on mouseover
+ }
+ return 0;
+}
=== modified file 'win32/RichTextBox.h'
--- win32/RichTextBox.h 2012-01-13 20:55:20 +0000
+++ win32/RichTextBox.h 2012-03-11 16:34:55 +0000
@@ -25,10 +25,13 @@
#include "forward.h"
-/// our rich text boxes that provide find functions
+/// our rich text boxes that provide find functions and handle links
class RichTextBox : public dwt::RichTextBox {
typedef dwt::RichTextBox BaseType;
friend class dwt::WidgetCreator<RichTextBox>;
+
+ typedef std::function<bool (const tstring&)> LinkF;
+
public:
typedef RichTextBox ThisType;
@@ -41,6 +44,7 @@
};
explicit RichTextBox(dwt::Widget* parent);
+ void create(const Seed& seed);
bool handleMessage(const MSG& msg, LRESULT& retVal);
@@ -50,8 +54,14 @@
void findTextNew();
void findTextNext();
+ /// provides a chance to handle links differently
+ void onLink(LinkF f);
+
private:
bool handleKeyDown(int c);
+ LRESULT handleLink(ENLINK& link);
+
+ LinkF linkF;
};
typedef RichTextBox::ObjectType RichTextBoxPtr;
=== modified file 'win32/WinUtil.cpp'
--- win32/WinUtil.cpp 2012-03-03 19:33:45 +0000
+++ win32/WinUtil.cpp 2012-03-11 16:34:55 +0000
@@ -516,11 +516,7 @@
}
void WinUtil::handleDblClicks(dwt::TextBoxBase* box) {
- box->onLeftMouseDblClick([box](const dwt::MouseEvent &me) { return WinUtil::handleBoxDblClick(box, me); });
-}
-
-bool WinUtil::handleBoxDblClick(dwt::TextBoxBase* box, const dwt::MouseEvent& ev) {
- return parseDBLClick(box->textUnderCursor(ev.pos));
+ box->onLeftMouseDblClick([box](const dwt::MouseEvent& me) { return parseLink(box->textUnderCursor(me.pos)); });
}
#define LINE2 _T("-- http://dcplusplus.sourceforge.net <DC++ ") _T(VERSIONSTRING) _T(">")
@@ -977,6 +973,7 @@
seed.style |= ES_MULTILINE;
seed.exStyle = WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE | WS_EX_CLIENTEDGE;
seed.location.size.x = std::min(getParent()->getDesktopSize().width(), static_cast<long>(maxWidth * dwt::util::dpiFactor()));
+ seed.events |= ENM_REQUESTRESIZE;
create(seed);
const auto margins = sendMessage(EM_GETMARGINS);
@@ -984,7 +981,6 @@
// let the control figure out what the best size is.
onRaw([this, pt](WPARAM, LPARAM l) { return this->resize(l, pt); }, dwt::Message(WM_NOTIFY, EN_REQUESTRESIZE));
- sendMessage(EM_SETEVENTMASK, 0, ENM_REQUESTRESIZE); ///@todo move to dwt
setText(text);
}
@@ -1378,7 +1374,7 @@
::ShellExecute(NULL, NULL, url.c_str(), NULL, NULL, SW_SHOWNORMAL);
}
-bool WinUtil::parseDBLClick(const tstring& str) {
+bool WinUtil::parseLink(const tstring& str) {
auto url = Text::fromT(str);
string proto, host, port, file, query, fragment;
Util::decodeUrl(url, proto, host, port, file, query, fragment);
=== modified file 'win32/WinUtil.h'
--- win32/WinUtil.h 2012-01-29 18:05:27 +0000
+++ win32/WinUtil.h 2012-03-11 16:34:55 +0000
@@ -292,7 +292,7 @@
static bool getUCParams(dwt::Widget* parent, const UserCommand& cmd, ParamMap& params) noexcept;
- static bool parseDBLClick(const tstring& aString);
+ static bool parseLink(const tstring& aString);
static void parseMagnetUri(const tstring& /*aUrl*/, bool aOverride = false);
static void help(dwt::Control* widget);
@@ -322,8 +322,6 @@
static dwt::IconPtr toolbarIcon(unsigned id);
private:
- static bool handleBoxDblClick(dwt::TextBoxBase* box, const dwt::MouseEvent& ev);
-
static void initUserMatching();
static void initHelpPath();