latex3 / hyperref

Hypertext support for LaTeX
168 stars 37 forks source link

problems with commands let to a char. #63

Open u-fischer opened 6 years ago

u-fischer commented 6 years ago

hyperref has problems with commands which have been let to a char.

With pdflatex one gets e.g. wrong bookmarks:

\documentclass{article}
\usepackage{hyperref}
\let\mychar!
\begin{document}

\tableofcontents
\section{\mychar}
\section{!}
\end{document}

image

With unicode engines and pdfencoding=auto the problem is more serious

\documentclass{article}
\usepackage[pdfencoding=auto]{hyperref}
\let\mychar!
\begin{document}

\tableofcontents
\section{\mychar}
\section{!}
\end{document}

gives the error

! Improper alphabetic constant.
<to be read again> 
                   \mychar 
l.21 \section{\mychar}

The problem is this definition which is used for the unicode engines.

  \def\HyPsd@Char#1{%
    \ifnum`#1<128 %
      \@backslashchar 000#1%
    \else
      \ifnum`#1<65536 %
        \expandafter\HyPsd@CharTwoByte\number`#1!%
      \else
        \expandafter\expandafter\expandafter\HyPsd@CharSurrogate
        \intcalcSub{`#1}{65536}!%
      \fi
    \fi
  }%

It is called with \mychar as argument and so basically does \ifnum`\mychar < 128 .

The error can be avoided by adding \pdfstringdefDisableCommands{\def\mychar{!}} but as e.g. unicode-math lets a lot commands to chars (e.g. \euro (https://github.com/wspr/unicode-math/issues/402) and \omega) some better solution is imho needed.

(I tried to replace the `#1 with a counter along this answer https://tex.stackexchange.com/a/148307/2388, but it looks as if \HyPsd@Char should be expandable and also I'm not sure how to replace 000#1).

u-fischer commented 5 years ago

Probably not solvable easily in hyperref for all engines. For luatex something like this could work:

\documentclass{article}
\usepackage{luacode}
\usepackage[pdfencoding=unicode]{hyperref}

\begin{luacode}
 function getcharactercode ()
  local t=token.get_next()
   tex.print(t.mode)
 end
\end{luacode}

\makeatletter
\def\HyPsd@Char#1{%
    \ifnum\directlua{getcharactercode ()}#1<128 %
      \@backslashchar 000\Uchar\directlua{getcharactercode ()}#1%
    \else
      \ifnum\directlua{getcharactercode ()}#1<65536 %
        \expandafter\HyPsd@CharTwoByte\directlua{getcharactercode ()}#1!%
      \else
        \expandafter\expandafter\expandafter\HyPsd@CharSurrogate
        \intcalcSub{\directlua{getcharactercode ()}#1}{65536}!%
      \fi
    \fi
  }%
\makeatother

\begin{document}
\let\mychar!
\tableofcontents

\section{\mychar äüö€ ɑН}

\end{document}