% File load-unicode-data.tex % % Copyright 2015-2023 The LaTeX Project % % It may be distributed and/or modified under the conditions of % the LaTeX Project Public License (LPPL), either version 1.3c of % this license or (at your option) any later version. The latest % version of this license is in the file % http://www.latex-project.org/lppl.txt. % % Issues with this file should be reported at % https://github.com/latex3/unicode-data % % This file parses a number of data files provided by the Unicode Consortium % and when used with used Unicode-capable engine sets up a range of TeX-related % parameters based on the extracted information. % % From the file UnicodeData.txt the following properties are set: % - \catcode 11 for all letters (Unicode class "L") % - \catcode 11 for all combining marks (Unicode class "M") % - \sfcode 999 for all code points of class "Lu" (upper case letters) % - \lccode for all of class "Ll" (lower case letters) to the code point % itself, and \uccode to the upper case mapping (or if not given % to the code point itself) % - \uccode for all of class "Lu" (upper case letters) to the code point % itself, and \lccode to the lower case mapping (or if not given % to the code point itself) % - \lccode and \uccode for all of class "Lt" (title case letters) to the % lower and upper case mappings (or if not given to the code point itself) % - \lccode and \uccode for all other letter code points are set to % the code point itself % - \lccode and/or \uccode for non-letter code points for which an upper % or lower case mapping is given % - \sfcode 0 (ignored) for code points of Unicode classes "Pe" (closing % punctuation marks) and "Pf" (final quotation marks) % - \Umathcode for all letters as math type 7 (var) % % ============================================================================= % % The data can only be loaded by Unicode engines. Currently this is limited to % XeTeX and LuaTeX, both of which define \Umathcode. \ifx\Umathcode\undefined \expandafter\endinput \fi % Just in case, check for the e-TeX extensions. \ifx\eTeXversion\undefined \expandafter\endinput \fi % This file can be loaded in IniTeX mode so the category codes of |{|, |}| and % |#| may not be correct. Everything is done in a group so that only the % settings we want to propagate are made available generally. \begingroup \catcode`\{=1 % \catcode`\}=2 % \catcode`\#=6 % % Write some basic information to the log. \catcode`\^=7 % \newlinechar=`\^^J % \message{^^J}% \message{load-unicode-data.tex v1.17 (2023-09-18)^^J}% \message{Reading Unicode data^^J}% % The first stage of parsing is dealing with the fact that there are lots of % data items separated by |;|. Of those, only a few are needed so they are % picked out and everything else is dropped. There is one complication: there % are a few cases in the data file of ranges which are marked by the descriptor % |First| and a matching |Last|. A separate routine is used to handle these % cases. \def\parseunicodedataI#1;#2;#3;#4;#5;#6;#7;#8;#9;{% \parseunicodedataII#1;#3;#2 First>\relax }% \def\parseunicodedataII#1;#2;#3 First>#4\relax{% \ifx\relax#4\relax \expandafter\parseunicodedataIII \else \expandafter\parseunicodedataVII \fi #1;#2;% }% \def\parseunicodedataIII#1;#2;#3;#4;#5;#6;#7;#8\relax{% \parseunicodedataIV{#1}{#2}{#6}{#7}% }% % At this stage we have a `normal' data line with four pieces of information: % the code point, the Unicode class and the (possibly empty) upper and lower % case mappings. A few utility macros are defined, then we branch based on the % Unicode class. Notice that for all letter-like code points we first set the % |\lccode| and |\uccode| values to the code point itself then test for the % classes where a different setting might be appropriate. For non-letters % there is a check to see if any mappings are available, and also for trailing % punctuation to set the appropriate |\sfcode|. \def\Ll{Ll}% \def\Lt{Lt}% \def\Lu{Lu}% \def\Pe{Pe}% \def\Pf{Pf}% \def\firsttoken#1#2\relax{#1}% \def\parseunicodedataIV#1#2#3#4{% \ifnum 0% \if L\firsttoken#2?\relax 1\fi \if M\firsttoken#2?\relax 1\fi >0 % \parseunicodedataV{"#1}% \def\temp{#2}% \ifx\Ll\temp \parseunicodedataVI\uccode{#1}{#3}% \fi \ifx\Lt\temp \parseunicodedataVI\uccode{#1}{#3}% \parseunicodedataVI\lccode{#1}{#4}% \fi \ifx\Lu\temp \parseunicodedataVI\lccode{#1}{#4}% \global\sfcode"#1=999 % \fi % All letters in math mode should be variables. \global\Umathcode"#1="7"01"#1 % \else \def\temp{#2}% \ifnum 0\ifx\temp\Pe 1\fi\ifx\temp\Pf 1\fi>0 % \global\sfcode"#1=0 % \fi \ifx\relax#3\relax \else \global\uccode"#1="#3 % \fi \ifx\relax#4\relax \else \global\lccode"#1="#4 % \fi \fi }% % A simple auxiliary for all letter-like code points: the |\lccode| and % |\uccode| may get reset for cased letters but this means the initial % setting can't be forgotten. \def\parseunicodedataV#1{% \global\catcode#1=11 % \global\lccode#1=#1 % \global\uccode#1=#1 % }% % An auxiliary to deal with the fact that some cased letters don't actually % have a case mapping available. \def\parseunicodedataVI#1#2#3{% \ifx\relax#3\relax \else \global#1"#2="#3 % \fi }% % For lines that were the |First>| of a range, read the data source again for % last line. Lines for letters then trigger a loop over the entire range. These % are always non-cased letters. \def\parseunicodedataVII#1;#2;#3\relax{% \read0 to \unicodedataline \expandafter\parseunicodedataXII\unicodedataline\relax#1;#2\relax }% \def\parseunicodedataXII#1;#2\relax#3;#4\relax{% \if L\firsttoken#4?\relax \begingroup \count0="#3 % \loop \unless\ifnum\count0>"#1 % \parseunicodedataV{\count0 }% \advance\count0 by 1 % \repeat \endgroup \fi }% % From plain: may not be defined (yet). \def\loop#1\repeat{\def\body{#1}\iterate}% \def\iterate{% \body \let\next\iterate \else \let\next\relax \fi \next }% \let\repeat\fi % There is no version data in |UnicodeData.txt|: log that it is being used with % a hard-coded date (the modification date from ftp.unicode.org). This obviously % needs to be updated when a new download takes place! \message{\string# UnicodeData-15.1.0.txt^^J}% \message{\string# Modified 2023-09-18 08:45:00 GMT [JAW]^^J}% % Actually loading the file requires an input stream, done directly. % There is a blank line at the end of the data source so there is a check % here for a |\par|. \def\storedpar{\par}% \openin0=UnicodeData.txt % \loop\unless\ifeof0 % \read0 to \unicodedataline \unless\ifx\unicodedataline\storedpar \expandafter\parseunicodedataI\unicodedataline\relax \fi \repeat \closein0 % \endgroup