% \iffalse meta-comment % % Copyright 2013-2017 Javier Bezos and any individual authors % listed elsewhere in this file. All rights reserved. % % This file is part of the Babel system. % -------------------------------------- % % It may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of LaTeX % version 2003/12/01 or later. % % This work has the LPPL maintenance status "maintained". % % The Current Maintainer of this work is Javier Bezos. % % The list of all files belonging to the Babel system is % given in the file `manifest.bbl. See also `legal.bbl' for additional % information. % % The list of derived (unpacked) files belonging to the distribution % and covered by LPPL is defined by the unpacking scripts (with % extension .ins) which are part of the distribution. % \fi % \CheckSum{795} % % \iffalse %<*dtx> \ProvidesFile{bbunicode.dtx} [2017/06/26 v3.11 Babel hooks for Unicode engines] % % %% File `bbunicode.dtx' %% Babel package for LaTeX version 2e %% Copyright (C) 2103-2017 %% by Javier Bezos % %<*filedriver> \documentclass{ltxdoc} \font\manual=logo10 % font used for the METAFONT logo, etc. \newcommand*\MF{{\manual META}\-{\manual FONT}} \newcommand*{\babel}{\textsf{babel}} \newcommand*{\langvar}{$\langle \it lang \rangle$} \newcommand*{\note}[1]{} \newcommand*{\pkg}[1]{\textsf{#1}} \newcommand*{\Lopt}[1]{\textsf{#1}} \newcommand*{\file}[1]{\texttt{#1}} \begin{document} \DocInput{bbunicode.dtx} \end{document} % % \fi % % \GetFileInfo{bbunicode.dtx} % \StopEventually{} % % \section{Tentative font handling} % % A general solution is far from trivial: % \begin{itemize} % \item |\addfontfeature| only sets it for the current family and it's % not very efficient, and % \item |\defaultfontfeatures| requires to redefine the font (and the % opti\texttt{}ons aren't ``orthogonal''). % \end{itemize} % % \begin{macrocode} %<<*Font selection>> \def\babelFSstore#1{% \bbl@for\bbl@tempa{#1}{% \edef\bbl@tempb{\noexpand\bbl@FSstore{\bbl@tempa}} \bbl@tempb{rm}\rmdefault\bbl@save@rmdefault \bbl@tempb{sf}\sfdefault\bbl@save@sfdefault \bbl@tempb{tt}\ttdefault\bbl@save@ttdefault}} \def\bbl@FSstore#1#2#3#4{% \bbl@csarg\edef{#2default#1}{#3}% \expandafter\addto\csname extras#1\endcsname{% \let#4#3% \ifx#3\f@family \edef#3{\csname bbl@#2default#1\endcsname}% \fontfamily{#3}\selectfont \else \edef#3{\csname bbl@#2default#1\endcsname}% \fi}% \expandafter\addto\csname noextras#1\endcsname{% \ifx#3\f@family \fontfamily{#4}\selectfont \fi \let#3#4}} \let\bbl@langfeatures\@empty \def\babelFSfeatures{% \let\bbl@ori@fontspec\fontspec \renewcommand\fontspec[1][]{% \bbl@ori@fontspec[\bbl@langfeatures##1]} \let\babelFSfeatures\bbl@FSfeatures \babelFSfeatures} \def\bbl@FSfeatures#1#2{% \expandafter\addto\csname extras#1\endcsname{% \babel@save\bbl@langfeatures \edef\bbl@langfeatures{#2,}}} %<> % \end{macrocode} % \section{Hooks for XeTeX and LuaTeX} % % \subsection{XeTeX} % % Unfortunately, the current encoding cannot be retrieved and % therefore it is reset always to |utf8|, which seems a sensible % default. % % \LaTeX{} sets many ``codes'' just before loading % \verb|hyphen.cfg|. That is not a problem in luatex, but in xetex % they must be reset to the proper value. Most of the work is done in % \textsf{xe(la)tex.ini}, so here we just ``undo'' some of the % changes done by \LaTeX. Anyway, for consistency Lua\TeX{} also % resets the catcodes. % \changes{bbunicode~1.0c}{2014/03/10}{Reset ``codes'' set by \cs{LaTeX} % to what xetex expects. Used also in luatex.} % \changes{bbunicode~1.0f}{2015/12/06}{This block was assigned to % xetex, even in luatex. Fixed here and below.} % \begin{macrocode} %<<*Restore Unicode catcodes before loading patterns>> \begingroup % Reset chars "80-"C0 to category "other", no case mapping: \catcode`\@=11 \count@=128 \loop\ifnum\count@<192 \global\uccode\count@=0 \global\lccode\count@=0 \global\catcode\count@=12 \global\sfcode\count@=1000 \advance\count@ by 1 \repeat % Other: \def\O ##1 {% \global\uccode"##1=0 \global\lccode"##1=0 \global\catcode"##1=12 \global\sfcode"##1=1000 }% % Letter: \def\L ##1 ##2 ##3 {\global\catcode"##1=11 \global\uccode"##1="##2 \global\lccode"##1="##3 % Uppercase letters have sfcode=999: \ifnum"##1="##3 \else \global\sfcode"##1=999 \fi }% % Letter without case mappings: \def\l ##1 {\L ##1 ##1 ##1 }% \l 00AA \L 00B5 039C 00B5 \l 00BA \O 00D7 \l 00DF \O 00F7 \L 00FF 0178 00FF \endgroup \input #1\relax %<> % \end{macrocode} % % Now, the code. % % \begin{macrocode} %<*xetex> \def\BabelStringsDefault{unicode} \let\xebbl@stop\relax \AddBabelHook{xetex}{encodedcommands}{% \def\bbl@tempa{#1}% \ifx\bbl@tempa\@empty \XeTeXinputencoding"bytes"% \else \XeTeXinputencoding"#1"% \fi \def\xebbl@stop{\XeTeXinputencoding"utf8"}} \AddBabelHook{xetex}{stopcommands}{% \xebbl@stop \let\xebbl@stop\relax} \AddBabelHook{xetex}{loadkernel}{% <@Restore Unicode catcodes before loading patterns@>} <@Font selection@> % % \end{macrocode} % % \subsection{LuaTeX} % % The new loader for luatex is based solely on |language.dat|, which % is read on the fly. The code shouldn't be executed when the format % is build, so we check if |\AddBabelHook| is defined. Then comes a % modified version of the loader in |hyphen.cfg| (without the % hyphenmins stuff, which is under the direct control of \babel). % % The names |\l@| are defined and take some value from the % beginning because all \texttt{ldf} files assume this for the % corresponding language to be considered valid, but patterns are not % loaded (except the first one). This is done later, when the language % is first selected (which usually means when the \texttt{ldf} % finishes). If a language has been loaded, |\bbl@hyphendata@| % exists (with the names of the files read). % % The default setup preloads the first language into the format. This % is intended mainly for `english', so that it's available without % further intervention from the user. To avoid duplicating it, the % following rule applies: if the ``0th'' language and the first % language in |language.dat| have the same name then just ignore the % latter. If there are new synonymous, the are added, but note if the % language patterns have not been preloaded they won't at run time. % % Other preloaded languages could be read twice, if they has been % preloaded into the format. This is not optimal, but it shouldn't % happen very often -- with \luatex{} patterns are best loaded when % the document is typeset, and the ``0th'' language is preloaded just % for backwards compatibility. % % As of 1.1b, lua(e)tex is taken into account. Formerly, loading of % patterns on the fly didn't work in this format, but with the new % loader it does. Unfortunately, the format is not based on \babel, % and data could be duplicated, because languages are reassigned above % those in the format (nothing serious, anyway). Note even with this % format |language.dat| is used (under the principle of a single % source), instead of |language.def|. % % Of course, there is room for improvements, like tools to read and % reassign languages, which would require modifying the language list, % and better error handling. % % We need catcode tables, but no format (targeted by \babel) provide a % command to allocate them (although there are packages like % \textsf{ctablestack}). For the moment, a dangerous approach is used % -- just allocate a high random number and cross the fingers. To % complicate things, \textsf{etex.sty} changes the way languages are % allocated. % % \changes{bbunicode~1.0b}{2013/04/22}{luatex-hyphen is loaded with % require. Changes supplied by \'{E}lie Roux.} % \changes{bbunicode~1.0c}{2014/03/10}{Defined hook for % `initiateactive', to fetch the next token and continue only if % letter or other.} % \changes{bbunicode~1.0d}{2014/03/21}{Removed the `misfeature' for % `initiateactive'.} % \changes{bbunicode~1.0e}{2015/05/10}{Use brackets instead of % \cs{luaescapestring}.} % \changes{bbunicode~1.0e}{2015/07/26}{Added function addpattern % and modified the patterns hook.} % \changes{bbunicode~1.1a}{2016/01/26}{New hyphenation loader for % luatex.} % \changes{bbunicode~1.1b}{2016/02/05}{Also lua(e)tex.} % \changes{bbunicode~1.1c}{2016/02/08}{Base reading of patterns on % number, not in name.} % \changes{bbunicode~1.1c}{2016/02/08}{Some hacks for polyglossia. To % be improved.} % \changes{bbunicode~1.1c}{2016/02/23}{Thoroughly revised.} % \changes{bbunicode~1.1d}{2016/4/22}{Lua: Fixed a line break at % \cs{foreignlanguage} with unloaded patterns. Added % \cs{babelcatcodetablenum}, just in case.} % % \begin{macrocode} %<*luatex> \ifx\AddBabelHook\@undefined \begingroup \toks@{} \count@\z@ % 0=start, 1=0th, 2=normal \def\bbl@process@line#1#2 #3 #4 {% \ifx=#1% \bbl@process@synonym{#2}% \else \bbl@process@language{#1#2}{#3}{#4}% \fi \ignorespaces} \def\bbl@manylang{% \ifnum\bbl@last>\@ne \bbl@info{Non-standard hyphenation setup}% \fi \let\bbl@manylang\relax} \def\bbl@process@language#1#2#3{% \ifcase\count@ \@ifundefined{zth@#1}{\count@\tw@}{\count@\@ne}% \or \count@\tw@ \fi \ifnum\count@=\tw@ \expandafter\addlanguage\csname l@#1\endcsname \language\allocationnumber \chardef\bbl@last\allocationnumber \bbl@manylang \let\bbl@elt\relax \xdef\bbl@languages{% \bbl@languages\bbl@elt{#1}{\the\language}{#2}{#3}}% \fi \the\toks@ \toks@{}} \def\bbl@process@synonym@aux#1#2{% \global\expandafter\chardef\csname l@#1\endcsname#2\relax \let\bbl@elt\relax \xdef\bbl@languages{% \bbl@languages\bbl@elt{#1}{#2}{}{}}}% \def\bbl@process@synonym#1{% \ifcase\count@ \toks@\expandafter{\the\toks@\relax\bbl@process@synonym{#1}}% \or \@ifundefined{zth@#1}{\bbl@process@synonym@aux{#1}{0}}{}% \else \bbl@process@synonym@aux{#1}{\the\bbl@last}% \fi} \ifx\bbl@languages\@undefined % Just a (sensible?) guess \chardef\l@english\z@ \chardef\l@USenglish\z@ \chardef\bbl@last\z@ \global\@namedef{bbl@hyphendata@0}{{hyphen.tex}{}} \gdef\bbl@languages{% \bbl@elt{english}{0}{hyphen.tex}{}% \bbl@elt{USenglish}{0}{}{}} \else \global\let\bbl@languages@format\bbl@languages \def\bbl@elt#1#2#3#4{% Remove all except language 0 \ifnum#2>\z@\else \noexpand\bbl@elt{#1}{#2}{#3}{#4}% \fi}% \xdef\bbl@languages{\bbl@languages}% \fi \def\bbl@elt#1#2#3#4{\@namedef{zth@#1}{}} % Define flags \bbl@languages \openin1=language.dat \ifeof1 \bbl@warning{I couldn't find language.dat. No additional\\% patterns loaded. Reported}% \else \loop \endlinechar\m@ne \read1 to \bbl@line \endlinechar`\^^M \if T\ifeof1F\fi T\relax \ifx\bbl@line\@empty\else \edef\bbl@line{\bbl@line\space\space\space}% \expandafter\bbl@process@line\bbl@line\relax \fi \repeat \fi \endgroup \def\bbl@get@enc#1:#2:#3\@@@{\def\bbl@hyph@enc{#2}} \ifx\babelcatcodetablenum\@undefined \def\babelcatcodetablenum{5211} \fi \def\bbl@luapatterns#1#2{% \bbl@get@enc#1::\@@@ \setbox\z@\hbox\bgroup \begingroup \ifx\catcodetable\@undefined \let\savecatcodetable\luatexsavecatcodetable \let\initcatcodetable\luatexinitcatcodetable \let\catcodetable\luatexcatcodetable \fi \savecatcodetable\babelcatcodetablenum\relax \initcatcodetable\numexpr\babelcatcodetablenum+1\relax \catcodetable\numexpr\babelcatcodetablenum+1\relax \catcode`\#=6 \catcode`\$=3 \catcode`\&=4 \catcode`\^=7 \catcode`\_=8 \catcode`\{=1 \catcode`\}=2 \catcode`\~=13 \catcode`\@=11 \catcode`\^^I=10 \catcode`\^^J=12 \catcode`\<=12 \catcode`\>=12 \catcode`\*=12 \catcode`\.=12 \catcode`\-=12 \catcode`\/=12 \catcode`\[=12 \catcode`\]=12 \catcode`\`=12 \catcode`\'=12 \catcode`\"=12 \input #1\relax \catcodetable\babelcatcodetablenum\relax \endgroup \def\bbl@tempa{#2}% \ifx\bbl@tempa\@empty\else \input #2\relax \fi \egroup}% \def\bbl@patterns@lua#1{% \language=\expandafter\ifx\csname l@#1:\f@encoding\endcsname\relax \csname l@#1\endcsname \edef\bbl@tempa{#1}% \else \csname l@#1:\f@encoding\endcsname \edef\bbl@tempa{#1:\f@encoding}% \fi\relax \@namedef{lu@texhyphen@loaded@\the\language}{}% Temp \@ifundefined{bbl@hyphendata@\the\language}% {\def\bbl@elt##1##2##3##4{% \ifnum##2=\csname l@\bbl@tempa\endcsname % #2=spanish, dutch:OT1... \def\bbl@tempb{##3}% \ifx\bbl@tempb\@empty\else % if not a synonymous \def\bbl@tempc{{##3}{##4}}% \fi \bbl@csarg\xdef{hyphendata@##2}{\bbl@tempc}% \fi}% \bbl@languages \@ifundefined{bbl@hyphendata@\the\language}% {\bbl@info{No hyphenation patterns were set for\\% language ‘\bbl@tempa’. Reported}}% {\expandafter\expandafter\expandafter\bbl@luapatterns \csname bbl@hyphendata@\the\language\endcsname}}{}} \endinput\fi \begingroup \catcode`\%=12 \catcode`\'=12 \catcode`\"=12 \catcode`\:=12 \directlua{ Babel = {} function Babel.bytes(line) return line:gsub("(.)", function (chr) return unicode.utf8.char(string.byte(chr)) end) end function Babel.begin_process_input() if luatexbase and luatexbase.add_to_callback then luatexbase.add_to_callback('process_input_buffer', Babel.bytes,'Babel.bytes') else Babel.callback = callback.find('process_input_buffer') callback.register('process_input_buffer',Babel.bytes) end end function Babel.end_process_input () if luatexbase and luatexbase.remove_from_callback then luatexbase.remove_from_callback('process_input_buffer','Babel.bytes') else callback.register('process_input_buffer',Babel.callback) end end function Babel.addpatterns(pp, lg) local lg = lang.new(lg) local pats = lang.patterns(lg) or '' lang.clear_patterns(lg) for p in pp:gmatch('[^%s]+') do ss = '' for i in string.utfcharacters(p:gsub('%d', '')) do ss = ss .. '%d?' .. i end ss = ss:gsub('^%%d%?%.', '%%.') .. '%d?' ss = ss:gsub('%.%%d%?$', '%%.') pats, n = pats:gsub('%s' .. ss .. '%s', ' ' .. p .. ' ') if n == 0 then tex.sprint( [[\string\csname\space bbl@info\endcsname{New pattern: ]] .. p .. [[}]]) pats = pats .. ' ' .. p else tex.sprint( [[\string\csname\space bbl@info\endcsname{Renew pattern: ]] .. p .. [[}]]) end end lang.patterns(lg, pats) end } \endgroup \def\BabelStringsDefault{unicode} \let\luabbl@stop\relax \AddBabelHook{luatex}{encodedcommands}{% \def\bbl@tempa{utf8}\def\bbl@tempb{#1}% \ifx\bbl@tempa\bbl@tempb\else \directlua{Babel.begin_process_input()}% \def\luabbl@stop{% \directlua{Babel.end_process_input()}}% \fi}% \AddBabelHook{luatex}{stopcommands}{% \luabbl@stop \let\luabbl@stop\relax} \AddBabelHook{luatex}{patterns}{% \@ifundefined{bbl@hyphendata@\the\language}% {\def\bbl@elt##1##2##3##4{% \ifnum##2=\csname l@#2\endcsname % #2=spanish, dutch:OT1... \def\bbl@tempb{##3}% \ifx\bbl@tempb\@empty\else % if not a synonymous \def\bbl@tempc{{##3}{##4}}% \fi \bbl@csarg\xdef{hyphendata@##2}{\bbl@tempc}% \fi}% \bbl@languages \@ifundefined{bbl@hyphendata@\the\language}% {\bbl@info{No hyphenation patterns were set for\\% language ‘#2’. Reported}}% {\expandafter\expandafter\expandafter\bbl@luapatterns \csname bbl@hyphendata@\the\language\endcsname}}{}% \@ifundefined{bbl@patterns@}{}{% \begingroup \@expandtwoargs\in@{,\number\language,}{,\bbl@pttnlist}% \ifin@\else \ifx\bbl@patterns@\@empty\else \directlua{ Babel.addpatterns( [[\bbl@patterns@]], \number\language) }% \fi \@ifundefined{bbl@patterns@#1}% \@empty {\directlua{ Babel.addpatterns( [[\space\csname bbl@patterns@#1\endcsname]], \number\language) }}% \xdef\bbl@pttnlist{\bbl@pttnlist\number\language,}% \fi \endgroup}} \AddBabelHook{luatex}{everylanguage}{% \def\process@language##1##2##3{% \def\process@line####1####2 ####3 ####4 {}}} \AddBabelHook{luatex}{loadpatterns}{% \input #1\relax \expandafter\gdef\csname bbl@hyphendata@\the\language\endcsname {{#1}{}}} \AddBabelHook{luatex}{loadexceptions}{% \input #1\relax \def\bbl@tempb##1##2{{##1}{#1}}% \expandafter\xdef\csname bbl@hyphendata@\the\language\endcsname {\expandafter\expandafter\expandafter\bbl@tempb \csname bbl@hyphendata@\the\language\endcsname}} % \end{macrocode} % % \begin{macro}{\babelpatterns} % % This macro adds patterns. Two macros are used to store them: % |\bbl@patterns@| for the global ones and |\bbl@patterns@| % for language ones. We make sure there is a space between words % when multiple commands are used. % \changes{bbunicode~1.0e}{2015/07/26}{Macro \cs{babelpatterns} added} % % \begin{macrocode} \@onlypreamble\babelpatterns \AtEndOfPackage{% \newcommand\babelpatterns[2][\@empty]{% \ifx\bbl@patterns@\relax \let\bbl@patterns@\@empty \fi \ifx\bbl@pttnlist\@empty\else \bbl@warning{% You must not intermingle \string\selectlanguage\space and\\% \string\babelpatterns\space or some patterns will not\\% be taken into account. Reported}% \fi \ifx\@empty#1% \protected@edef\bbl@patterns@{\bbl@patterns@\space#2}% \else \edef\bbl@tempb{\zap@space#1 \@empty}% \bbl@for\bbl@tempa\bbl@tempb{% \bbl@fixname\bbl@tempa \bbl@iflanguage\bbl@tempa{% \bbl@csarg\protected@edef{patterns@\bbl@tempa}{% \@ifundefined{bbl@patterns@\bbl@tempa}% \@empty {\csname bbl@patterns@\bbl@tempa\endcsname\space}% #2}}}% \fi}} % \end{macrocode} % \end{macro} % % Common stuff. % % \begin{macrocode} \AddBabelHook{luatex}{loadkernel}{% <@Restore Unicode catcodes before loading patterns@>} <@Font selection@> % % \end{macrocode} % \endinput %% %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~}