commit e5ea53595239ef05a352e142ded5f4eed03a4fa0
Author: Richard Heck <[email protected]>
Date: Sun Feb 23 11:20:47 2014 -0500
If the selection is some sort of URL, then make it the target, not
the name, in the hyperlink. Fixes bug #8792.
This also fixes a bug discovered while working on this code: The
params passed to GuiHyperlink were never used.
diff --git a/src/Text3.cpp b/src/Text3.cpp
index 1dead38..f54e8f4 100644
--- a/src/Text3.cpp
+++ b/src/Text3.cpp
@@ -73,6 +73,7 @@
#include "support/lstrings.h"
#include "support/lyxtime.h"
#include "support/os.h"
+#include "support/regex.h"
#include "mathed/InsetMathHull.h"
#include "mathed/MathMacroTemplate.h"
@@ -1668,15 +1669,46 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
}
case LFUN_HREF_INSERT: {
- InsetCommandParams p(HYPERLINK_CODE);
- docstring content;
+ // FIXME If we're actually given an argument, shouldn't
+ // we use it, whether or not we have a selection?
+ docstring content = cmd.argument();
if (cur.selection()) {
content = cur.selectionAsString(false);
cutSelection(cur, true, false);
}
- p["target"] = (cmd.argument().empty()) ?
- content : cmd.argument();
+
+ InsetCommandParams p(HYPERLINK_CODE);
+ if (!content.empty()){
+ // if it looks like a link, we'll put it as target,
+ // otherwise as name (bug #8792).
+
+ // We can't do:
+ // regex_match(to_utf8(content), matches, link_re)
+ // because smatch stores pointers to the substrings
rather
+ // than making copies of them. And those pointers become
+ // invalid after regex_match returns, since it is then
+ // being given a temporary object. (Thanks to Georg for
+ // figuring that out.)
+ regex const link_re("^([a-zA-Z]+):.*");
+ smatch matches;
+ string const c = to_utf8(content);
+
+ if (content.substr(0,7) == "mailto:") {
+ p["target"] = content;
+ p["type"] = from_ascii("mailto:");
+ } else if (regex_match(c, matches, link_re)) {
+ p["target"] = content;
+ string protocol = matches.str(1);
+ if (protocol == "file")
+ p["type"] = from_ascii("file:");
+ } else
+ p["name"] = content;
+ }
string const data = InsetCommand::params2string(p);
+
+ // we need to have a target. if we already have one, then
+ // that gets used at the default for the name, too, which
+ // is probably what is wanted.
if (p["target"].empty()) {
bv->showDialog("href", data);
} else {
diff --git a/src/frontends/qt4/GuiHyperlink.cpp
b/src/frontends/qt4/GuiHyperlink.cpp
index 7cb9cc6..6cd9262 100644
--- a/src/frontends/qt4/GuiHyperlink.cpp
+++ b/src/frontends/qt4/GuiHyperlink.cpp
@@ -68,6 +68,23 @@ void GuiHyperlink::paramsToDialog(Inset const * inset)
}
+bool GuiHyperlink::initialiseParams(std::string const & data)
+{
+ InsetCommandParams params(insetCode());
+ if (!InsetCommand::string2params(data, params))
+ return false;
+ targetED->setText(toqstr(params["target"]));
+ nameED->setText(toqstr(params["name"]));
+ if (params["type"] == from_utf8("mailto:"))
+ emailRB->setChecked(true);
+ else if (params["type"] == from_utf8("file:"))
+ fileRB->setChecked(true);
+ else
+ webRB->setChecked(true);
+ return true;
+}
+
+
docstring GuiHyperlink::dialogToParams() const
{
InsetCommandParams params(insetCode());
@@ -75,11 +92,11 @@ docstring GuiHyperlink::dialogToParams() const
params["target"] = qstring_to_ucs4(targetED->text());
params["name"] = qstring_to_ucs4(nameED->text());
if (webRB->isChecked())
- params["type"] = qstring_to_ucs4("");
+ params["type"] = from_utf8("");
else if (emailRB->isChecked())
- params["type"] = qstring_to_ucs4("mailto:");
+ params["type"] = from_utf8("mailto:");
else if (fileRB->isChecked())
- params["type"] = qstring_to_ucs4("file:");
+ params["type"] = from_utf8("file:");
params.setCmdName("href");
return from_utf8(InsetHyperlink::params2string(params));
}
diff --git a/src/frontends/qt4/GuiHyperlink.h b/src/frontends/qt4/GuiHyperlink.h
index 2134ca8..d2dd0ee 100644
--- a/src/frontends/qt4/GuiHyperlink.h
+++ b/src/frontends/qt4/GuiHyperlink.h
@@ -35,6 +35,7 @@ private:
void paramsToDialog(Inset const *);
docstring dialogToParams() const;
bool checkWidgets() const;
+ bool initialiseParams(std::string const & data);
//@}
};
diff --git a/src/support/lstrings.cpp b/src/support/lstrings.cpp
index dbf629c..2d483e6 100644
--- a/src/support/lstrings.cpp
+++ b/src/support/lstrings.cpp
@@ -481,6 +481,14 @@ docstring const lowercase(docstring const & a)
}
+string const lowercase(string const & a)
+{
+ string tmp(a);
+ transform(tmp.begin(), tmp.end(), tmp.begin(), local_lowercase());
+ return tmp;
+}
+
+
docstring const uppercase(docstring const & a)
{
docstring tmp(a);
diff --git a/src/support/lstrings.h b/src/support/lstrings.h
index 2606546..89450c7 100644
--- a/src/support/lstrings.h
+++ b/src/support/lstrings.h
@@ -96,6 +96,7 @@ docstring const ascii_lowercase(docstring const &);
/// Changes the case of \p s to lowercase.
/// Does not depend on the locale.
+std::string const lowercase(std::string const & s);
docstring const lowercase(docstring const & s);
/// Changes the case of \p s to uppercase.