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.
This commit is contained in:
Richard Heck 2014-02-23 11:20:47 -05:00
parent fabf507902
commit e5ea535952
5 changed files with 66 additions and 7 deletions

View File

@ -73,6 +73,7 @@
#include "support/lstrings.h" #include "support/lstrings.h"
#include "support/lyxtime.h" #include "support/lyxtime.h"
#include "support/os.h" #include "support/os.h"
#include "support/regex.h"
#include "mathed/InsetMathHull.h" #include "mathed/InsetMathHull.h"
#include "mathed/MathMacroTemplate.h" #include "mathed/MathMacroTemplate.h"
@ -1668,15 +1669,46 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
} }
case LFUN_HREF_INSERT: { case LFUN_HREF_INSERT: {
InsetCommandParams p(HYPERLINK_CODE); // FIXME If we're actually given an argument, shouldn't
docstring content; // we use it, whether or not we have a selection?
docstring content = cmd.argument();
if (cur.selection()) { if (cur.selection()) {
content = cur.selectionAsString(false); content = cur.selectionAsString(false);
cutSelection(cur, true, 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); 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()) { if (p["target"].empty()) {
bv->showDialog("href", data); bv->showDialog("href", data);
} else { } else {

View File

@ -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 docstring GuiHyperlink::dialogToParams() const
{ {
InsetCommandParams params(insetCode()); InsetCommandParams params(insetCode());
@ -75,11 +92,11 @@ docstring GuiHyperlink::dialogToParams() const
params["target"] = qstring_to_ucs4(targetED->text()); params["target"] = qstring_to_ucs4(targetED->text());
params["name"] = qstring_to_ucs4(nameED->text()); params["name"] = qstring_to_ucs4(nameED->text());
if (webRB->isChecked()) if (webRB->isChecked())
params["type"] = qstring_to_ucs4(""); params["type"] = from_utf8("");
else if (emailRB->isChecked()) else if (emailRB->isChecked())
params["type"] = qstring_to_ucs4("mailto:"); params["type"] = from_utf8("mailto:");
else if (fileRB->isChecked()) else if (fileRB->isChecked())
params["type"] = qstring_to_ucs4("file:"); params["type"] = from_utf8("file:");
params.setCmdName("href"); params.setCmdName("href");
return from_utf8(InsetHyperlink::params2string(params)); return from_utf8(InsetHyperlink::params2string(params));
} }

View File

@ -35,6 +35,7 @@ private:
void paramsToDialog(Inset const *); void paramsToDialog(Inset const *);
docstring dialogToParams() const; docstring dialogToParams() const;
bool checkWidgets() const; bool checkWidgets() const;
bool initialiseParams(std::string const & data);
//@} //@}
}; };

View File

@ -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 const uppercase(docstring const & a)
{ {
docstring tmp(a); docstring tmp(a);

View File

@ -96,6 +96,7 @@ docstring const ascii_lowercase(docstring const &);
/// Changes the case of \p s to lowercase. /// Changes the case of \p s to lowercase.
/// Does not depend on the locale. /// Does not depend on the locale.
std::string const lowercase(std::string const & s);
docstring const lowercase(docstring const & s); docstring const lowercase(docstring const & s);
/// Changes the case of \p s to uppercase. /// Changes the case of \p s to uppercase.