Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I am searching for a macro/package that would give the name of characters. Here are a few examples of a possible behaviour:

\namethatchar{A} → A
\namethatchar{À} → Agrave
\namethatchar{a} → a
\namethatchar{\`A} → Agrave

The names do not have to be these specifically, just unique identifiers using ASCII characters only. Is there a basic macro or a package that would do that already?

Edit:

To clarify, this need comes from the lettrine.4ht setting for TeX4HT. Currently, when typesetting a drop cap, it creates a lettrine-<letter> CSS class, for example lettrine-A. This works well, as long as the character is not accentuated, in which case you get something like a lettrine-À CSS class. Since I compile with LuaTeX and the browsers I use seem to have implemented support for accents in CSS classes (ahead of the spec), it works for me. But it fails for others and is not acceptable globally speaking.

For this reason, the output of the command is aimed to be used by both machines and humans. The former because it generates CSS classes, which are clearly used by machines. The latter because human beings might want to tune the rendering of their HTML document by modifying the CSS properties of the generated CSS classes.

Ideally, all the CSS settings could be done using the lettrine options, mapped through lettrine.4ht, but we're not there yet.

share|improve this question
    
Is this just to differentiate between different characters, or "for human consumption"? In the first case, would, simply, the Unicode hex value be sufficient? –  Brent.Longborough Oct 1 '12 at 8:46
    
Good question @Brent.Longborough. I'd say, both. I'll clarify in the question. –  ℝaphink Oct 1 '12 at 9:16

2 Answers 2

up vote 18 down vote accepted

If the Unicode value is known, then there is a mapping from glyph name to Unicode in glyphlist.txt that can quite easily parsed (with # as comment char) to get the hex string of the Unicode value. However this method is quite limited, because there are lots of Unicode characters without proper glyph name in this list.

If the name does not care, then the Unicode hex value can be used directly. Because you also want to support LICRs (`A), this is a bit tricky. Package hyperref has to do a similar job, when it converts arbitrary TeX strings to PDF strings. Thus the main work is done by \pdfstringdef in the following example:

\documentclass{article}
\usepackage{ifluatex}
\usepackage{ifxetex}
\ifluatex
\else
  \ifxetex
  \else
    \usepackage[utf8]{inputenc}
  \fi
\fi
\usepackage[pdfencoding=auto]{hyperref}
\usepackage{pdfescape}
\newcommand*{\namethatchar}[2][]{%
  \begingroup
    \hypersetup{unicode}%
    \pdfstringdef\gcharname{#2}%
  \endgroup
  \EdefUnescapeString\charname{\gcharname}%
  \EdefEscapeHex\charname{\charname}%
  \edef\charname{%
    \expandafter\stripBOM\charname\@empty\@empty\@empty\@empty
  }%
  \ifx\relax#1\relax
    \expandafter\charname
  \else
    \let#1\charname
  \fi
}
\newcommand*{\stripBOM}[4]{%
  \ifnum"0#1#2#3#4="FEFF %
  \else
    #1#2#3#4%
  \fi
}
\begin{document}
\namethatchar{A}
\namethatchar{À}
\namethatchar{a}
\namethatchar{\`A}
\namethatchar{\texteuro}
\namethatchar{\textpertenthousand}
\end{document}

Result

  • If the optional argument is specified, the result is stored in the macro instead of printing the result.

    \namethatchar[\result]{\`A}
    
  • \stripBOM strips the byte order mark that is not needed here.

  • The result is actually UTF-16BE, that means surrogates are used for higher Unicode values that does not fit in the first plane (Basic Multilingual Plane).

  • Because hyperref's \pdfstringdef supports the big chars of XeTeX and LuaTeX, the solution works with XeTeX and LuaTeX. Then the line `\usepackage[utf8]{inputenc}' should be removed.

Extended solution with glyph names

This solution additionally looks for glyph names in glyphlist.txt and glyphtounicode.tex. Care is needed to make the mapping unique. Therefore I have left lots of \typeout and \@latex@warning lines to show the assignments and dropped mappings. It makes sense for an application to provide its own unique mapping file to get a faster loading and better control of the mappings.

\documentclass{article}
\usepackage{ifluatex}
\usepackage{ifxetex}
\ifluatex
\else
  \ifxetex
  \else
    \usepackage[utf8]{inputenc}
  \fi
\fi
\usepackage[T1]{fontenc}
\usepackage[pdfencoding=auto]{hyperref}
\usepackage{pdfescape}
\usepackage{ltxcmds}
\makeatletter
\def\GlyphlistLine#1;#2;#3\@nil{%
  \ifx\\#2\\%
  \else
    \ltx@ifundefined{glyphlist@#2}{%
      \ltx@ifundefined{listglyph@#1}{%
        \typeout{Defining #2 -> #1}%
        \expandafter\gdef\csname glyphlist@#2\endcsname{#1}%
        \expandafter\gdef\csname listglyph@#1\endcsname{#2}%
      }{%
        \@latex@warning{%
          #2 -> #1 ignored, because of\MessageBreak
          \@nameuse{listglyph@#1} -> #1%
        }%
      }%
    }{%
      \edef\ua{\@nameuse{glyphlist@#2}}%
      \edef\ub{#1}%
      \ifx\ua\ub
      \else
        \@latex@warning{%
          #2 -> #1 ignored, because\MessageBreak
          #2 -> \ua\space exists
        }%
      \fi
    }%
  \fi
}%
\IfFileExists{glyphlist.txt}\@firstoftwo\@secondoftwo{%
  \typeout{* Glyph mapping: glyphlist.txt}%
  \begingroup
    \catcode`\#=14 % comment
    \catcode`\ =9 % ignore spaces
    \endlinechar=-1 % ignore line ends
    % misusing \@inputcheck to save a read register
    \openin\@inputcheck=glyphlist.txt\relax
    \loop
      \read\@inputcheck to\mapline
      \ifeof\@inputcheck
      \else
        \expandafter\GlyphlistLine\mapline;;\@nil
    \repeat
    \immediate\closein\@inputcheck
  \endgroup
}{%
  \@latex@warning@no@line{Missing `glyphlist.txt'}%
}
\IfFileExists{glyphtounicode}\@firstoftwo\@secondoftwo{%
  \typeout{* Glyph mapping: glyphtounicode.tex}%
  \begingroup
    \def\pdfglyphtounicode#1#2{%
      \GlyphlistLine#1;#2;\@nil
    }%
    \endlinechar=-1 %
    \catcode`\ =9 %  
    \input{glyphtounicode.tex}%
  \endgroup
}{%
  \@latex@warning@no@line{Missing `glyphtounicode.tex'}%
}
\newcommand*{\namethatchar}[2][]{%
  \begingroup
    \hypersetup{unicode}%
    \pdfstringdef\gcharname{#2}%
  \endgroup
  \EdefUnescapeString\charname{\gcharname}%
  \EdefEscapeHex\charname{\charname}%
  \edef\charname{%
    \expandafter\stripBOM\charname\@empty\@empty\@empty\@empty
  }%
  \ltx@IfUndefined{glyphlist@\charname}{%
  }{%
    \expandafter\let\expandafter\charname
    \csname glyphlist@\charname\endcsname
  }%
  \ifx\relax#1\relax
    \expandafter\charname
  \else
    \let#1\charname
  \fi
}
\newcommand*{\stripBOM}[4]{%
  \ifnum"0#1#2#3#4="FEFF %  
  \else
    #1#2#3#4%
  \fi
}
\makeatother

\begin{document}
\newcommand*{\test}[2][]{%
  \texttt{\ifx\\#1\\\detokenize{#2}\else#1\fi}
  & \texttt{\namethatchar{#2}}\\
}
\begin{tabular}{ll}
  \test{A}
  \test[Ã@]{Ã@}
  \test{a}
  \test{\`A}
  \test{\texteuro}
  \test{\textpertenthousand}
  \test{\textsucceqq}% needs hyperref 2012/08/18 or later
  \test{\textBicycle}% needs hyperref 2012/08/18 or later
  \test{\textcopyleft}% needs hyperref 2012/08/18 or later
\end{tabular}
\end{document}

Result

share|improve this answer
    
+1: a minute faster than me and more complete but I'll leave mine there as it's a simpler and might be useful:-) –  David Carlisle Oct 1 '12 at 9:09
    
This is a very nice solution which will work for any character. It might just make it harder for people to tune the CSS (see my edited question) if need be. Maybe combining with glyphlist.txt would help. –  ℝaphink Oct 1 '12 at 9:22
    
Your edited solution is great! I'll try with that! –  ℝaphink Oct 1 '12 at 12:13
    
Somehow it doesn't work with XeLaTeX. –  ℝaphink Oct 1 '12 at 18:42
    
Thanks fixed. \pdfglyphtounicode does not exist in XeTeX, but it is anyway redefined, thus using \def instead of \renewcommand fixed this. Also the call of \stripBOM needs some \@empty guards, because the string returned by \pdfstringdef might be encoded in US-ASCII if possible. It's a workaround for XeTeX, because XeTeX/xdvipdfmx have trouble with 8bit characters. –  Heiko Oberdiek Oct 1 '12 at 19:23

Not sure if you want it typeset or in the log, this version uses \typeout and produces

A is A
À is A grave
a is a
\`A is A grave

\documentclass{article}

\usepackage[utf8]{inputenc}

\makeatletter
\def\namethatchar#1{{%
\let\IeC\@firstofone
\def\'##1{##1 acute}%
\def\`##1{##1 grave}%
\protected@edef\zzz{#1}%
\typeout{\unexpanded{#1} is \zzz}}}

\makeatother

\namethatchar{A}
\namethatchar{À}
\namethatchar{a}
\namethatchar{\`A}

\stop
share|improve this answer
    
That is nice, but I can't afford to list all kinds of accents manually. I need something that will work for all unicode characters without manually entering a map. –  ℝaphink Oct 1 '12 at 9:15
    
Heiko's your friend then:-) But actually their are not so many accent commands, and for the unicode input (as in your second example line) If there are packages loaded so that it typesets then it will be translated to a traditional internal command and so this naming does not need any additional unicode mapping over and above the support you need to define the characters anyway for classic tex. –  David Carlisle Oct 1 '12 at 9:20

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.