0

This question is very similar to my OP "What's so special about and ". Mostly, I have just adjusted the main .TeX code a little bit for clarity.

This question is about the following characters:

  • the characters from the roman alphabet (a.k.a. "A to Z"), for example a.

and

I use the particular code that will follow for Chinese text, and as my favorite font allows the two characters above to be used without any fuss, please, if you'd like, install the font HanWangKaiMediumChuIn_wp010-08.ttf (download link here or if not here).

What else do we need? We will need:

OK. If they are all in the same folder as our TeX-file, we are set to go. The TeX-file should look as follows (to be compiled twice with LuaLaTeX):

The TeX-file

% !TEX TS-program = lualatexmk

\documentclass{scrreprt}

\usepackage{silence}
\ErrorFilter{latex}{File}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Chinese splitter
\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\bgroup \catcode`!=3 \catcode`?=3
\gdef\replacestrings#1#2{\long\def\replacestringsA##1#1{\def\tmpb{##1}\replacestringsB}%
   \long\def\replacestringsB##1#1{\ifx!##1\relax \else\addto\tmpb{#2##1}%
      \expandafter\replacestringsB\fi}% improved version <May 2016> inspired 
   \expandafter\replacestringsA\tmpb?#1!#1% from pysyntax.tex by Petr Krajnik
   \long\def\replacestringsA##1?{\def\tmpb{##1}}\expandafter\replacestringsA\tmpb
}
\egroup
%
\def\Chinese#1{\def\tmpb{#1}%
   \replacestrings {\\}  {&\\}%
   \replacestrings {\endgraf}  {&\endgraf}%
   \replacestrings {★}  {&★}%
   \replacestrings {【}  {&【}%
   \replacestrings {】}  {&】}%
   \replacestrings {(}  {&(}%
   \replacestrings {)}  {&)}%
   \replacestrings {:} {&:}%
   \replacestrings {。}  {&。}%
   \replacestrings {,}  {&,}%
   \replacestrings {「}  {&「}%
   \replacestrings {」}  {&」}%
   \replacestrings {《}  {&《}%
   \replacestrings {》}  {&》}%
   \replacestrings {、}  {&、}%
   \replacestrings {;}  {&;}%
   \replacestrings {~}  {&~}%
   \replacestrings {〈}  {&〈}%
   \replacestrings {〉}  {&〉}%
   \replacestrings {·}  {&·}%
   \replacestrings {.}  {&.}%
   \replacestrings {﹑} {&、}%
   \replacestrings {\scriptsize}  {&\scriptsize}%
   \replacestrings {\footnotesize}  {&\footnotesize}%
   \replacestrings {\small}  {&\small}%
   \replacestrings {\normalsize}  {&\normalsize}%
   \replacestrings {\large}  {&\large}%
   \replacestrings {\Large}  {&\Large}%
   \replacestrings {\LARGE}  {&\LARGE}%
   \replacestrings {\huge}  {&\huge}%
   \replacestrings {\Huge}  {&\Huge}%
   \expandafter\anyA\tmpb&{}%
}
\def\anyA#1&#2{\anyX{#1}#2\ifx&#2&\else\expandafter\anyB\fi}
\def\anyB{\futurelet\next\anyC}
\def\anyC{\expandafter\ifx\space\next\space\fi\anyA}
%
\def\anyX#1{\tooltips[height=10cm]{#1} \space}
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% For the Chinese font
\usepackage{fontspec}
\usepackage{luatexja-fontspec}
\setmainjfont{HanWangKaiMediumChuIn_wp010-08}
\ltjsetparameter{kanjiskip=1em}
\ltjsetparameter{xkanjiskip=1em}
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Encoding converter and tooltipper
\tracinglostchars=2
\directlua{require('big5.lua')}
\directlua{print('The big5 version of 高 is: ' .. big5FromChar('高'))}
\newcommand{\bigfive}[1]{\directlua{tex.sprint(big5FromChar('#1'))}}
%
% tooltips with LaTeX
%
% optimized for Adobe Reader (visible on mouse-over)
%     usage: \tooltip[<link colour>]{<link text>}[<tip box colour>]{<tip text>}
%   non-draggable version:
%     usage: \tooltip*[<link colour>]{<link text>}[<tip box colour>]{<tip text>}
%
% for Evince (visible on click, not draggable)
%   usage: \tooltip**[<link colour>]{<link text>}[<tip box colour>]{<tip text>}
%
%
\usepackage{pdfbase}[2017/03/16]
\usepackage{xparse,ocgbase}
\usepackage{xcolor,calc}
\usepackage{tikz}
\usetikzlibrary{calc}
%
\ExplSyntaxOn
\let\tpPdfLink\pbs_pdflink:nn
\let\tpPdfAnnot\pbs_pdfannot:nnnn\let\tpPdfLastAnn\pbs_pdflastann:
\let\tpAppendToFields\pbs_appendtofields:n
\def\tpPdfXform{\pbs_pdfxform:nnnnn{1}{1}{}{}}
\let\tpPdfLastXform\pbs_pdflastxform:
\ExplSyntaxOff
%
\makeatletter
\NewDocumentCommand{\tooltip}{ssO{black}mO{black}m}{{%
  \leavevmode%
  \IfBooleanT{#1}{%
    \ocgbase@new@ocg{tipOCG.\thetcnt}{%
      /Print<</PrintState/OFF>>/Export<</ExportState/OFF>>%
    }{false}%
    \xdef\tpTipOcg{\ocgbase@last@ocg}%
  }%
  \tpPdfLink{%
    \IfBooleanTF{#2}{%
      /Subtype/Link/Border [0 0 0]/A <</S/SetOCGState/State [/Toggle \tpTipOcg]>>
    }{%
      /Subtype/Screen%
      \IfBooleanTF{#1}{%
        /AA<<%
          /E<</S/SetOCGState/State [/ON \tpTipOcg]>>%
          /X<</S/SetOCGState/State [/OFF \tpTipOcg]>>%
        >>%
      }{
        /AA<<%
          /E<</S/JavaScript/JS(%
            var fd=this.getField('tip.\thetcnt');%
            \IfBooleanF{#1}{%
              if(typeof(click\thetcnt)=='undefined'){%
                var click\thetcnt=false;%
                var fdor\thetcnt=fd.rect;var dragging\thetcnt=false;%
              }%
            }%
            if(fd.display==display.hidden){%
              fd.delay=true;fd.display=display.visible;fd.delay=false;%
            }%
           this.dirty=false;%
          )>>%
          /X<</S/JavaScript/JS(%
            if(!click\thetcnt&&!dragging\thetcnt){fd.display=display.hidden;}%
            if(!dragging\thetcnt){click\thetcnt=false;}%
            this.dirty=false;%
          )>>%
          /U<</S/JavaScript/JS(click\thetcnt=true;this.dirty=false;)>>%
          /PC<</S/JavaScript/JS (%
            var fd=this.getField('tip.\thetcnt');%
            try{fd.rect=fdor\thetcnt;}catch(e){}%
            fd.display=display.hidden;this.dirty=false;%
          )>>%
          /PO<</S/JavaScript/JS(this.dirty=false;)>>%
        >>%
      }
    }%
  }{{\color{#3}#4}}%
  \sbox\tiptext{\fcolorbox{black}{#5}{#6}}%
  \edef\twd{\the\wd\tiptext}%
  \edef\tht{\the\ht\tiptext}%
  \edef\tdp{\the\dp\tiptext}%
  \tpPdfXform{\tiptext}%
  %tip box placed at top left page corner
  \begin{tikzpicture}[remember picture,overlay]
    \node [inner sep=0pt, anchor=base] at (current page.north west) {%
      \raisebox{-1.5cm-\tht}[0pt][0pt]{%
        \tpPdfAnnot{\twd}{\tht}{\tdp}{%
          /Subtype/Widget/FT/Btn/T (tip.\thetcnt)%
          /AP<</N \tpPdfLastXform>>%
          /MK<</TP 1/I \tpPdfLastXform/IF<</S/A/FB true/A [0.0 0.0]>>>>%
          \IfBooleanTF{#1}{%
            /Ff 65537/OC \tpTipOcg%
          }{%
            /Ff 65536/F 3%
            /AA <<%
              /U <<%
                /S/JavaScript/JS(%
                  var fd=event.target;%
                  var mX=this.mouseX;var mY=this.mouseY;%
                  var drag=function(){%
                    var nX=this.mouseX;var nY=this.mouseY;%
                    var dX=nX-mX;var dY=nY-mY;%
                    var fdr=fd.rect;%
                    fdr[0]+=dX;fdr[1]+=dY;fdr[2]+=dX;fdr[3]+=dY;%
                    fd.rect=fdr;mX=nX;mY=nY;%
                  };%
                  if(!dragging\thetcnt){%
                    dragging\thetcnt=true;Int=app.setInterval("drag()",1);%
                  }%
                  else{app.clearInterval(Int);dragging\thetcnt=false;}%
                  this.dirty=false;%
                )%
              >>%
            >>%
          }%
        }%
        \tpAppendToFields{\tpPdfLastAnn}%
      }%
    };
  \end{tikzpicture}
  \stepcounter{tcnt}%
}}
\makeatother
\newsavebox\tiptext\newcounter{tcnt}
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
\ExplSyntaxOn
\NewDocumentCommand{\tooltips}{sO{}m+O{}}
 {
  \tl_map_inline:nn { #3 }
   {
    \IfBooleanTF{#1}{\tooltip*}{\tooltip*}{##1}{\includegraphics[#2]{\bigfive{##1}}}#4
   }
 }
\ExplSyntaxOff
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document} \catcode`\﹑=12 \catcode`\~=12
%%%%%%%%%
%All of this works fine
\Chinese{疊}
\Chinese{疊。。【疊    ,疊;【疊   疊《疊(疊疊···疊疊】疊\footnotesize 疊疊\Large 疊;〈疊\endgraf}
a
ㄅ
aㄅa
ㄅaㄅ
%
%%%%%%%%%

%%%%%%%%%
%All of this doesn't work ... why?
%
%\Chinese{a,a}
%
%
%\Chinese{ㄅ。ㄅ}
%
%%%%%%%%%

\end{document}

The questions

Why does

\Chinese{a,a}

not "work", and why does

\Chinese{ㄅ。ㄅ}

not "work"?

Why do they produce other and more errors than for example another character (not part of the "roman" alphabet, and not part of the "bopomofo" alphabet), of which there is also no image included, such as:

\Chinese{式。式}
  • Maybe you could change to XeCJK, see tex.stackexchange.com/questions/17611/… – BlackBird Oct 5 '17 at 3:46
  • @Joseph I am not sure if that would solve the problem? But please note that I am compiling LuaLaTeX, not XeTeX. – Vincent Mia Edie Verheyen Oct 5 '17 at 5:07
  • I am beginning to think it's because of the incompleteness in the map.txt file. Yep, I am quite sure. – Vincent Mia Edie Verheyen Oct 5 '17 at 5:48
  • Surely a font with those characters compiling with XeTeX + XeCJK would "solve the problem" without much of a fuss. – BlackBird Oct 5 '17 at 11:01
0

It's because the incompleteness of the characters included in the map.txt file.

Traditional Chinese characters like and are included but characters like a and aren't.

Changing the big5.lua's code linked in this answer by user ShreevatsaR will solve the problem (since it accounts for characters not included in the file map.txt):

function ucsFromChar(s)
   -- UTF-8 decoder. Given a valid UTF-8-encoded character s, returns the number (codepoint) it encodes.
   -- A stricter version is at https://gist.github.com/shreevatsa/6aef61aafd4ccfe2149ddacdc5c5855d
   local n = string.byte(s, 1)
   if n < 128 then return n end -- Starts with a 0
   if n < 224 then              -- Starts with 110, so get remaining 5 bits, then 6 bits from next byte
      return (n - 192) * 64 + string.byte(s, 2) - 128
   elseif n < 240 then          -- Starts with 1110, so get remaining 4 bits, then 6 bits each from next 2 bytes
      return ((n - 224) * 64 + string.byte(s, 2) - 128) * 64 + string.byte(s, 3) - 128
   else                         -- Starts with 11110, so get remaining 3 bits, then 6 bits each from next 3 bytes
      return (((n - 240) * 64 + string.byte(s, 2) - 128) * 64 + string.byte(s, 3) - 128) * 64 + string.byte(s, 4) - 128
   end
end

map = nil  -- Populated and used by getMap() below.
function getMap()
   -- Returns map from a file containing a space-separated key-value pair per line.
   if map ~= nil then return map end
   map = {}
   for line in io.open('map.txt', 'r'):lines() do
      local key = nil
      for s in string.gmatch(line, "%S+") do
         if key ~= nil then map[key] = s else key = s end
      end
   end
   return map
end

function big5FromChar(s)
   local u = string.upper(string.format('U+%x', ucsFromChar(s)))
   -- return getMap()[u]
   local v = getMap()[u]
   if v ~= nil then return v else return s end
end
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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