% % uni8.sty: Universal inputenc, fontenc and babel for pdflatex + lualatex % by pts@fazekas.hu at Fri Jan 11 15:48:05 CET 2019 % % License for uni8.sty: LPPL (https://opensource.org/licenses/LPPL) % % See the project page https://github.com/pts/latex-uni8 for example files % and the latest updates. % % uni8.sty does these: % % * It sets up hyphenation patterns correctly for pdflatex and lualatex, % with or without fontspec. % * It works with pdflatex and lualatex. % * It works with hyperref.sty. % * It works with color.sty and xcolor.sty. % * It defines \ul for underlining text. % * It sets the default fonts with [font=...] options. % * It sets the input encoding with [inputenc=...] options. % * It loads fontspec.sty with the [fontspec] option. % * It sets the page size based on [a4paper] etc. to \documentclass. % * It hides useless warnings about inputenc.sty or t1enc.sty by magyar.ldf. % % See README.txt for more features and detailed documentation. % \ProvidesPackage{uni8}[2019/01/14 v0.03 Universal inputenc, fontenc and babel for pdflatex + lualatex] % Extra customization from .tex: \PassOptionsToPackage{hungarian}{babel} % Defaults. \def\@univ@font{cm} \def\@univ@inputenc{utf8}\def\@univ@inputenc@isutfe{1} \def\@univ@fontspec{0} \DeclareOption{fontspec}{\def\@univ@fontspec{1}} \DeclareOption{fontspec=yes}{\def\@univ@fontspec{1}} \DeclareOption{fontspec=no}{\def\@univ@fontspec{0}} \DeclareOption{inputenc=utf8}{\def\@univ@inputenc{utf8}\def\@univ@inputenc@isutfe{1}} \DeclareOption{inputenc=utf8x}{\def\@univ@inputenc{utf8x}\def\@univ@inputenc@isutfe{1}} \DeclareOption{inputenc=latin1}{\def\@univ@inputenc{latin1}\def\@univ@inputenc@isutfe{0}} \DeclareOption{inputenc=latin2}{\def\@univ@inputenc{latin2}\def\@univ@inputenc@isutfe{0}} \DeclareOption{font=cm}{\def\@univ@font{cm}} % Preferred. \DeclareOption{font=lm}{\def\@univ@font{cm}} \DeclareOption{font=ec}{\def\@univ@font{cm}} \DeclareOption{font=lmodern}{\def\@univ@font{cm}} \DeclareOption{font=tg}{\def\@univ@font{times}} \DeclareOption{font=times}{\def\@univ@font{times}} % Preferred. \DeclareOption{font=old-times}{\def\@univ@font{oldtimes}} % Preferred. \DeclareOption{font=oldtimes}{\def\@univ@font{oldtimes}} \DeclareOption{nop}{} \ProcessOptions\relax \def\@univ@fatal@ifpackage#1{% \expandafter\ifx\csname ver@#1.sty\endcsname\relax\else \PackageError{uni8}{Package #1 is already loaded.\MessageBreak Solution: remove \string\usepackage...{#1}}{}\expandafter\@@end \fi} % We fail early if any of these packages are already loaded, because we % want to load them, in the correct order. \@univ@fatal@ifpackage{t1enc} \@univ@fatal@ifpackage{fontenc} \@univ@fatal@ifpackage{inputenc} \@univ@fatal@ifpackage{luainputenc} \@univ@fatal@ifpackage{fontspec} \@univ@fatal@ifpackage{babel} \def\@univ@fatal@ifpackageopt#1{% \expandafter\ifx\csname opt@#1.sty\endcsname\relax\else \PackageError{uni8}{Package #1 already has options.\MessageBreak Solution: remove \string\PassOptionsToPackage{...}{#1}}{}% \expandafter\@@end \fi} % We fail early if any of these packages already have options, becase we % want to specify and control the correct options for them. \@univ@fatal@ifpackageopt{t1enc} \@univ@fatal@ifpackageopt{fontenc} \@univ@fatal@ifpackageopt{inputenc} \@univ@fatal@ifpackageopt{luainputenc} %\@univ@fatal@ifpackageopt{fontspec} % Passing options to fontspec.sty is OK. %\@univ@fatal@ifpackageopt{babel} % Passing options to babel.sty is OK. % if #1 specifies an UTF-8 encoding, runs #2, otherwise runs #3. % @param #1 a control sequence. \def\@univ@ifutfe#1#2#3{% \ifx#1\@univ@ifutfe@a #2% \else \ifx#1\@univ@ifutfe@b#2\else#3\fi \fi} \def\@univ@ifutfe@a{utf8} \def\@univ@ifutfe@b{utf8x} \expandafter\ifx\csname opt@babel.sty\endcsname\relax % english is the default language (including default hyphenation) if % \PassOptionsToPackage{...}{babel} was not specified. \expandafter\def\csname opt@babel.sty\endcsname{english}\fi \if1\@univ@fontspec \ifnum0\ifx\luatexversion\@undefined1\fi\ifx\luatexversion\relax1\fi>0 \PackageError{uni8}{[fontspec] needs to be run with lualatex}{} \def\@univ@fontspec{0}% Disable [fontspec] as a fallback. \fi \fi \if1\@univ@fontspec % [fontspec] is selected, use TU (Unicode) encoding. \RequirePackage{babel} % It's important to load luainputenc.sty after babel.sty, otherwise % loadhyph-hu.tex loaded by babel.sty would load hyphenation patterns % (e.g. hyph-hu.tex) with conv-utf8-ec.tex. But we are using TU font % encoding, and conv-utf8-ec.tex would make hyphenation patterns use the % T1 font encoding. \@univ@ifutfe\@univ@inputenc{}{ \expandafter\RequirePackage\expandafter[\@univ@inputenc]{luainputenc}} \RequirePackage{fontspec} % lmodern font is the default for fontspec. % Override magyar.ldf loaded by babel.sty to prevent useless warning about % \usepackage{t1enc}. \def\magyar@sugg@to#1{} \def\@univ@font@cm{% Latin Modern fonts, bettern than CM and EC for international text in T1 encoding. % Even though Latin Modern is the default text font for lualatex (see % fonttext.cfg in format generation time, it loads tulmr.fd), cmr is % still the default math font. By loading lmodern.sty we also change the % default math font to (non-Unicode) Latin Modern (e.g. lmmi10.pfb). \RequirePackage{lmodern} } \def\@univ@font@times{% TeX Gyre fonts, great alternative for Times, Helvetica and Courier. \RequirePackage{unicode-math} \setmainfont{TeX Gyre Termes} \setsansfont{TeX Gyre Heros}[Scale=MatchLowercase] \setmonofont{TeX Gyre Cursor}[Scale=MatchLowercase] \setmathfont{TeX Gyre Termes Math} } \def\@univ@font@oldtimes{% Times, Helvetica and Courier. \@univ@font@times % old-times is not available in Unicode, using times. } \csname @univ@font@\@univ@font\endcsname \normalfont\selectfont \else % [fontspec] is not selected: use T1 font encoding. \ifnum0\ifx\luatexversion\@undefined1\fi\ifx\luatexversion\relax1\fi>0 \def\@univ@fix@topatterns{} % luainputenc.sty would also work, but we don't want to depend on it, to % remain compatible with earlier versions of pdflatex. \expandafter\RequirePackage\expandafter[\@univ@inputenc]{inputenc} \else \begingroup % To undef temporary \L and \P definitions. \def\L#1{\expandafter\@gobble\string#1}% Useful for escaping. % \P is a substitution table: a concatenation of XY characters pairs, % where X is a Unicode character, and Y is the corresponding code point % in T1 encoding. In this source file both X and Y are UTF-8 encoding. % When lualatex executes \def\P{...}, both X and and Y will be added to % \P as a character token (after UTF-8 decoding). Character values of % X are at least 128, character values of Y are between 128 and 255. % % Define this this before importing luainputenc so we will get a single % token per character, passed as UTF-8 bytes to \directlua. \def\P{Ă Ą¡Ć¢Č£Ď¤Ě¥Ę¦Ğ§Ĺ¨Ľ©ŁªŃ«Ň¬Ŋ­Ő®Ŕ¯Ř°Ś±Š²Ş³Ť´ŢµŰ¶Ů·Ÿ¸Ź¹ŽºŻ»IJ¼İ½ÀàÁáÂâÃ% ãÄäÅåÆæÇçÈèÉéÊêËëÌìÍíÎîÏïÐðĐðÑñÒòÓóÔôÕõÖöŒ÷ØøÙùÚúÛûÜüÝýÞþẞÿđžă ą¡ć¢č£% ď¤ě¥ę¦ğ§ĺ¨ľ©łªń«ň¬ŋ­ő®ŕ¯ř°ś±š²ş³ť´ţµű¶ů·ÿ¸ź¹žºż»ij¼ààááââããääååææççèèééêê% ëëììííîîïïððññòòóóôôõõööœ÷øøùùúúûûüüýýþþßÿ}% % This defines Lua code which converts hyphenation patterns of all % languages from Unicode (UTF-8) to T1 encoding. We need this conversion % because hyphenation patterns need to be in font encoding, which is T1 % in our case. \edef\P{\noexpand\directlua{% local r = {} local n = 0 % Lua string pattern which matches a Unicode character encoded as % UTF-8. Using \DDD (decimal) because Lua 5.1 used in lualatex in % TeX Live 2010 has \DDD but not \xHH. local u = '[\L\\192-\L\\253][\L\\128-\L\\191]+', p, k for p in string.gmatch('\expandafter\strip@prefix\meaning\P', u) do if n \L\% 2 == 0 then k = p else r[k] = p end n = n + 1 end if n \L\~= 250 then error('bad t1pat count: ' .. n) end for n=0,\noexpand\the\noexpand\last@language+0 do local l = lang.new(n) p = lang.patterns(l) if p then texio.write(' [t1fix:' .. n .. '] ') % TODO(pts): No line breaks. lang.clear_patterns(l) lang.patterns(l, p:gsub(u, function (s) return r[s] or '?' end)) end end texio.write(' [/t1fix] ')}} \expandafter\endgroup\expandafter\def\expandafter\@univ@fix@topatterns \expandafter{\P} % Needed for ő and ű in non-fontspec fonts. \expandafter\RequirePackage\expandafter[\@univ@inputenc]{luainputenc} \fi \def\encodingdefault{T1} % Part of t1enc.sty \fontencoding{T1} % Part of t1enc.sty. % We don't run \selectfont here (t1enc.sty does), to avoid loading % ecrm1000.tfm here when it is not available (e.g. no % sudo apt-get install texlive-fonts-recommended). % TODO(pts): Add [font=tnr] for Times New Roman, Helvetica, Courier New. \def\@univ@font@cm{% Latin Modern fonts, bettern than CM and EC for international text in T1 encoding. \RequirePackage{lmodern} } \def\@univ@font@times{% TeX Gyre fonts, great alternative for Times, Helvetica and Courier. % Also changes math fonts. Load before tgtermes so that tgtermes can % change text fonts back. % % TODO(pts): Better with newtxtext and newtxmath? % https://tex.stackexchange.com/q/469726/820 % TODO(pts): Check txfonts.sty aand https://ctan.org/pkg/newtx as well. \RequirePackage{mathptmx} \RequirePackage{tgtermes} \RequirePackage{tgheros} \RequirePackage{tgcursor} } \def\@univ@font@oldtimes{% Times, Helvetica and Courier. % Ugly spacing of the accent in \H{o}. Use [font=times] instead. % % Doesn't affect math fonts. %\RequirePackage{times} % Also changes math fonts. \RequirePackage{mathptmx} } \csname @univ@font@\@univ@font\endcsname % Without this \cf@encoding would remain TU (Unicode), but we want both % \cf@encoding and \f@encoding T1. \normalfont\selectfont % Without this lualatex wouldn't consider the characters ő and ű in font % encoding T1 as letters during hyphenation. % % This magic is based on https://tex.stackexchange.com/a/469909/820 % Also using https://en.wikipedia.org/wiki/Cork_encoding \@tempcnta128 \loop\ifnum\@tempcnta<158 \@tempcntb\@tempcnta \advance\@tempcntb32 \lccode\@tempcnta\@tempcntb \advance\@tempcnta\@ne \repeat \lccode158 158 \lccode159 0 \@tempcnta160 \loop\ifnum\@tempcnta<189 \lccode\@tempcnta\@tempcnta \advance\@tempcnta\@ne \repeat \catcode189 0 \lccode190 0 \lccode191 0 \@tempcnta192 \loop\ifnum\@tempcnta<224 \@tempcntb\@tempcnta \advance\@tempcntb32 \lccode\@tempcnta\@tempcntb \advance\@tempcnta1 \repeat \@tempcnta224 \loop\ifnum\@tempcnta<256 \lccode\@tempcnta\@tempcnta \advance\@tempcnta1 \repeat \ifnum0\ifx\luatexversion\@undefined1\fi\ifx\luatexversion\relax1\fi>0 % For latex and pdflatex, just load babel without magic hacks for % hyphanation pattern encoding. \RequirePackage{babel} \else\ifnum\last@language=\z@ % \last@language is defined even in tetex1. % Hyphanation patterns will be loaded new this way: we load babel.sty, % which loads luababel.def, which loads language.dat and then % loadhyph-hu.tex, which loads either hyph-hu.tex or hyph-hu.ec.tex. % We want hyph-hu.ec.tex (because that contains the hyphenation patterns % in T1 encoding), and we get this by defining \kanjiskip, because % loadhyph-hu.tex decides based on that. This \kanjiskip trick was % tested in TeX Live 2015--2019 (babel.sty >= 3.9q). % % This magic is based on https://tex.stackexchange.com/a/469909/820 % % Without this magic, lualatex, [inputenc=utf8] would have incorrect % hyphenation because of the way loadhyph-hu.tex detects whether % conv-utf8-ec.tex should be loaded, and \usepackage[utf8]{luainputenc} is % treated specially: differently from other encodings. % % Alternatively to the \let\kanjiskip\hsize hack, we could set up active % characters to convert from Unicde to T1 like this below, just for the % scope of \RequirePackage{babel}, especially for loadhyph-hu.tex: % % \catcode`á=13 \begingroup\lccode`~=`á\lowercase{\endgroup\edef~}{\string^^e1} % \catcode`ő=13 \begingroup\lccode`~=`ő\lowercase{\endgroup\edef~}{\string^^ae} % % However, that doesn't work, because \bbl@luapatterns in luababel.def % resets catcode of ő to 12 before the `\input #1' call to % loadhyph-hu.tex. Also we'd need to change the catcodes and definitions back % after \RequirePackage{babel}. \let\@univ@old@kanjiskip\kanjiskip \let\kanjiskip\hsize % Without loading babel, hyphenation \language macros such as \l@english and % \l@hungarian wouldn't be defined in lualatex. \RequirePackage{babel} %\ifnum0\ifx\bbl@luapatterns\@undefined1\fi\ifx\bbl@luapatterns\relax1\fi>0 \else % \PackageWarningNoLine{uni8}{\string\bbl@luapatterns\space is missing}\fi \let\kanjkiskip\@univ@old@kanjiskip % Undo our hack above. \let\@univ@old@kanjiskip\@undefined \bbbb \else % Older versions of Babel (e.g. babel.sty <= 3.9l) load hyphenation % patterns at format generation time. It's too late to load them with % the proper encoding, so we use Lua code in \@univ@fix@topatterns to % fix the encoding of the already loaded patterns. \RequirePackage{babel} \@univ@fix@topatterns \fi\fi \let\@univ@fix@topatterns\relax % Save memory. \fi % Override magyar.ldf loaded by babel.sty to prevent useless warning about % \usepackage[...]{inputenc}. \def\magyar@sugg@ie#1{} \edef\reserved@a{\csname inputencodingname\endcsname} \@univ@ifutfe\reserved@a{\def\@univ@inputenc@isutfe{1}}{} \ifnum10=\@univ@inputenc@isutfe\@univ@fontspec \IfFileExists{soulutf8.sty}{\IfFileExists{soul.sty}{ % For non-utf8 input encodings, use \usepackage{soul}. \RequirePackage{soulutf8} \def\underline{\ul} % \underline is built-in. Let's use soul's. \def\uline{\ul} % \uline is from ulem. Let's use soul's. }{}}{} \else \IfFileExists{soul.sty}{ \usepackage{soul} \def\underline{\ul} % \underline is built-in. Let's use soul's. \def\uline{\ul} % \uline is from ulem. Let's use soul's. }{} \fi % Propagate a4paper, a5paper, b5paper, letterpaper, legalpaper, % executivepaper, landscape documentclass options to actual paper size % as understood by dvips (\special{papersize=...}), pdflatex (\pdfpagewidth) % and lualatex (\pagewidth). \def\UnivFixPaperSize{% \ifx\pdfpagewidth\undefined \ifx\pagewidth\undefined\special{papersize=\paperwidth,\paperheight}\else \pagewidth\paperwidth \pageheight\paperheight \fi\else \pdfpagewidth\paperwidth \pdfpageheight\paperheight \fi} \UnivFixPaperSize % Display a warning if the user calls \fontencoding{...} unexpectedly in the % preamble. \def\@univ@sugg@fontenc{% % We want T1 font encoding, because hyphenation patterns are in T1 % encoding. \edef\reserved@a{% \expandafter\ifx\csname ver@fontspec.sty\endcsname\relax T1\else TU\fi}% \edef\reserved@b{\f@encoding}% \ifx\reserved@a\reserved@b\else \PackageWarningNoLine{uni8}{The font encoding is \expandafter\strip@prefix\meaning\reserved@b, should be \expandafter\strip@prefix\meaning\reserved@a}% \fi} % Display a warning if the user loads a package in the preamble which would % break what uni8.sty has set up. \def\@univ@sugg@fontspec@package#1{% \expandafter\ifx\csname ver@fontspec.sty\endcsname\relax\else \expandafter\ifx\csname ver@#1.sty\endcsname\relax\else \PackageWarningNoLine{uni8}{[fontspec] conflicts with #1.sty\MessageBreak Solution: remove \string\usepackage...{#1}}% \fi \fi} \def\@univ@sugg@inputencoding{% \if1\@univ@inputenc@isutfe \expandafter\ifx\csname ver@fontspec.sty\endcsname\relax\else \expandafter\ifx\csname inputencodingname\endcsname\relax\else % Actually, if \inputencodingname is lutf8, it would work here, % but we display the warning anyway to discourage the user to do % \usepackage[...]{luainputenc} manually. By doing so we we make % things less diverse, thus less likely to fail. \PackageError{uni8}{[fontspec] conflicts with input encoding: \expandafter\strip@prefix\meaning\inputencodingname\MessageBreak Solution: remove \string\usepackage...{luainputenc}}{}\@@end \fi \fi \fi} \AtBeginDocument{% \selectfont % Make \f@encoding and \cf@encoding match. \@univ@sugg@fontspec@package{t1enc}% \@univ@sugg@fontspec@package{fontenc}% \@univ@sugg@fontspec@package{inputenc}% \@univ@sugg@fontenc \@univ@sugg@inputencoding } \endinput