I don't like the concept. Better teach the users about proper use
instead of "fixing" it behind their backs.
I don't understand your concerns. I listed the 3 possibilities to fix this and why I have chosen the
one I implemented. There is not other way to fix this, see also the last sentence of this mail. We
also do this all the time: When you enter a "#" in normal text, it becomes in the background a "\#".
The same is here, when you enter a "\" it becomes in the background now a "%5C% - valid LaTeX.
> /home/juergen/test\test/somefile.pdf is valid on Unix. How am I supposed to
> enter such a path?
\href has nothing to do with paths of OSes. It follows the definitions of URLs. So everything you
can enter in this field is an URL, not a file path. When you use the option that a URL is a path to
a file it is still an URL and therefore the resulting link will open the file via a URL browser and
not the usual file explorer.
(Just for my interest: is /home/juergen/test\test/somefile.pdf equivalent to
/home/juergen/test\test\somefile.pdf ?)
> I'm not sure it's sound to just transcribe all the '\' to '/' without at
least a warning. If for
> instance I'm pasting the name of a file, the '\' in the actual path should be
really be
> transcribed as %5C.
You are completely right. I made a mistake that I escaped the "%" character in the URL field while
it is allowed there. The attached patch fixes this and I also now correctly translate "\" to "%5C"
so that
D:\TEst\1.jpg
leads now to
\href{file:D:%TEst%5C1.jpg}{D:\textbackslash{}TEst\textbackslash{}1.jpg}
This can be handled by IE and Firefox. Interestingly they both translate the "%5C" to "/". So in the
end they do the same I did in my first patch and am now wondering why I was not allowed to.
regards Uwe
Index: insets/InsetHyperlink.cpp
===================================================================
--- insets/InsetHyperlink.cpp (revision 28166)
+++ insets/InsetHyperlink.cpp (working copy)
@@ -67,24 +67,39 @@
int InsetHyperlink::latex(odocstream & os, OutputParams const & runparams) const
{
docstring url = getParam("target");
+ docstring name = getParam("name");
static docstring const backslash = from_ascii("\\");
static docstring const braces = from_ascii("{}");
- static char_type const chars_url[2] = {'%', '#'};
static char_type const chars_name[6] = {
'&', '_', '$', '%', '#', '^'};
+ // For the case there is no name given, the target is set as name.
+ // Do this before !url.empty() and !name.empty() to handle characters
+ // like the "%" correctly.
+ if (name.empty())
+ name = url;
+
// The characters in chars_url[] need to be changed to a command when
// they are in the url field.
if (!url.empty()) {
- // the chars_url[] characters must be handled for both, url and href
- for (int k = 0; k < 2; k++) {
- for (size_t i = 0, pos;
- (pos = url.find(chars_url[k], i)) != string::npos;
- i = pos + 2) {
- url.replace(pos, 1, backslash + chars_url[k]);
- }
+ // Replace the "\" character by its ASCII code according to the URL specifications
+ // because "\" is not allowed in URLs and by \href. Only do this when the
+ // following character is not also a "\", because "\\" is valid code
+ for (size_t i = 0, pos;
+ (pos = url.find('\\', i)) != string::npos;
+ i = pos + 2) {
+ if (url[pos + 1] != '\\')
+ url.replace(pos, 1, from_ascii("%5C"));
}
-
+ // "#" needs to be escapes to "\#", therefore the treatment
+ // of "\" must be done before
+ for (size_t i = 0, pos;
+ (pos = url.find('#', i)) != string::npos;
+ i = pos + 2) {
+ if (url[pos + 1] != '\\')
+ url.replace(pos, 1, from_ascii("\\#"));
+ }
+
// add "http://" when the type is web (type = empty)
// and no "://" or "run:" is given
docstring type = getParam("type");
@@ -95,12 +110,9 @@
} // end if (!url.empty())
- docstring name = getParam("name");
-
// The characters in chars_name[] need to be changed to a command when
// they are in the name field.
if (!name.empty()) {
-
// handle the "\" character, but only when the following character
// is not also a "\", because "\\" is valid code
docstring const textbackslash = from_ascii("\\textbackslash{}");
@@ -110,6 +122,9 @@
if (name[pos + 1] != '\\')
name.replace(pos, 1, textbackslash);
}
+ // The characters in chars_name[] need to be changed to a command when
+ // they are in the name field.
+ // Therefore the treatment of "\" must be the first thing
for (int k = 0; k < 6; k++) {
for (size_t i = 0, pos;
(pos = name.find(chars_name[k], i)) != string::npos;
@@ -130,9 +145,8 @@
if (runparams.moving_arg)
os << "\\protect";
- //for the case there is no name given, the target is set as name
- os << "\\href{" << getParam("type") << url << "}{"
- << (name.empty()? url : name) << '}';
+ // output the ready \href command
+ os << "\\href{" << getParam("type") << url << "}{" << name << '}';
return 0;
}