%
% 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
  \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
  \ifnum0\ifx\luatexversion\@undefined1\fi\ifx\luatexversion\relax1\fi>0
    % luainputenc 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
    % 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
  \@tempcnta128 \loop\ifnum\@tempcnta<159 \ifnum\lccode\@tempcnta=0
    \lccode\@tempcnta\@tempcnta\fi \advance\@tempcnta1 \repeat
  \@tempcnta160 \loop\ifnum\@tempcnta<190 \ifnum\lccode\@tempcnta=0
    \lccode\@tempcnta\@tempcnta\fi \advance\@tempcnta1 \repeat
  \@tempcnta192 \loop\ifnum\@tempcnta<256 \ifnum\lccode\@tempcnta=0
    \lccode\@tempcnta\@tempcnta\fi \advance\@tempcnta1 \repeat

  % Make loadhyph-hu.tex loaded by babel.sty in TeX Live 2019 load
  % hyph-hu.ec.tex rather than hyph-hu.tex in lualatex.
  %
  % This magic is based on https://tex.stackexchange.com/a/469909/820
  \let\kanjiskip\hsize
  % Without loading babel, hyphenation \language macros such as \l@english and
  % \l@hungarian wouldn't be defined in lualatex.
  \RequirePackage{babel}
  \let\kanjkiskip\@undefined  % Undo our hack above.
\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, that 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
