%% iftex TeX engine tests

%% LaTeX3 Project
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either
%% version 1.3c of this license or (at your option) any later
%% version.
%%
%% Using ideas from:
%%
%% ifetex Martin Scharrer
%% ifxetex Will Robertson
%% iftex 0.2 Persian TeX Group / Vafa Khalighi
%% ifluatex ifvtex Heiko Oberdiek
%% ifptex Takayuki YATO
%% ifpdf Heiko Oberdiek and LaTeX3 Project

% Only load once (not needed in LaTeX, but does no harm).
\csname IFTEX\string @loaded\endcsname
\expandafter\let\csname IFTEX\string @loaded\endcsname\endinput

% File loadable in initex
% require { } # with standard catcodes.
\catcode123=1
\catcode125=2
\catcode35=6


% ProvidesPackage declaration in LaTeX
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname ProvidesPackage\endcsname\relax\else
  \ProvidesPackage{iftex}[2024/12/12 v1.0g TeX engine tests]
\fi

% Save @ catcode, to restore at end, not needed in LaTeX.
\expandafter\chardef\csname IFTEX\string @atcatcode\endcsname\catcode64
\catcode 64 11

% Message format used in several pre-existing if*tex packages
% Modified here to do a hard stop and not show any error context lines.
\def\IFTEX@Require#1#2#3{%
  #1\else
      \newlinechar 64\relax
      \errorcontextlines -1\relax
      \immediate\write20{@
      ********************************************@
      * #2 is required to compile this document.@
      * Sorry!@
      ********************************************}%
    \batchmode\read -1 to \@tempa
    #3%
}


% eTeX \protected if available.
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname protected\endcsname\relax
  \let\IFTEX@protected\relax
\else
  \let\IFTEX@protected\protected
\fi

% make sure \detokenize and \protected are available in lualatex,
% but avoid defining them after the package if not already defined.
  {
  \catcode34 12 % "
  \catcode40 12 % (
  \catcode41 12 % )
  \catcode44 12 % ,
  \catcode46 12 % .
  \expandafter\ifx\csname directlua\endcsname\relax\else
    \directlua{tex.enableprimitives("IFTEX@", {"detokenize","protected"})}
  \fi
  }

% \Require... commands that stop if the wrong engine detected.
\IFTEX@protected\def\RequireeTeX{\IFTEX@Require\ifetex{eTeX}\fi}
\IFTEX@protected\def\RequirePDFTeX{\IFTEX@Require\ifpdftex{pdfTeX}\fi}
\IFTEX@protected\def\RequireXeTeX{\IFTEX@Require\ifxetex{XeTeX}\fi}
\IFTEX@protected\def\RequireLuaTeX{\IFTEX@Require\ifluatex{LuaTeX}\fi}
\IFTEX@protected\def\RequireLuaHBTeX{\IFTEX@Require\ifluahbtex{LuaHBTeX}\fi}
\IFTEX@protected\def\RequireLuaMetaTeX{\IFTEX@Require\ifluahbtex{LuaMetaTeX}\fi}
\IFTEX@protected\def\RequirepTeX{\IFTEX@Require\ifptex{pTeX}\fi}
\IFTEX@protected\def\RequireupTeX{\IFTEX@Require\ifuptex{upTeX}\fi}
\IFTEX@protected\def\RequirepTeXng{\IFTEX@Require\ifptexng{pTeX-ng}\fi}
\IFTEX@protected\def\RequireVTeX{\IFTEX@Require\ifvtex{VTeX}\fi}
% alephtex as aleph name too generic
\IFTEX@protected\def\RequireAlephTeX{\IFTEX@Require\ifalephtex{Aleph}\fi}
% tutex == has \Umathchardef == XeTeX or Lua(HB)TeX currently
\IFTEX@protected\def\RequireTUTeX{\IFTEX@Require\iftutex{LuaTeX or XeTeX}\fi}
% TeXpad TeX
\IFTEX@protected\def\RequireTexpadTeX{\IFTEX@Require\iftexpadtex{TexpadTeX}\fi}
% HiTeX/HINT
\IFTEX@protected\def\RequireHINT{\IFTEX@Require\ifhint{HINT}\fi}
% Prote
\IFTEX@protected\def\RequireProte{\IFTEX@Require\ifprote{Prote}\fi}

% As a matter of policy over-write any existing \if*tex macro and set
% by the tests here.

% \csname and \let construct useful for hiding \ifzzz tokens from
% outer level \if tests.
\def\IFTEX@let#1#2{%
  \expandafter\let\csname if#1\expandafter\endcsname
  \csname if#2\endcsname}

% etex (should always be true in latex based formats)
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname numexpr\endcsname\relax
  \IFTEX@let{etex}{false}
\else
  \IFTEX@let{etex}{true}
\fi
\IFTEX@let{eTeX}{etex}

% pdftex (including in dvi mode)
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname pdftexversion\endcsname\relax
  \IFTEX@let{pdftex}{false}
\else
  \IFTEX@let{pdftex}{true}
\fi
\IFTEX@let{PDFTeX}{pdftex}

% xetex
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname XeTeXrevision\endcsname\relax
  \IFTEX@let{xetex}{false}
\else
  \IFTEX@let{xetex}{true}
\fi
\IFTEX@let{XeTeX}{xetex}


% luatex (including luahbtex and luametatex)
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname directlua\endcsname\relax
  \IFTEX@let{luatex}{false}
\else
  \IFTEX@let{luatex}{true}
\fi
\IFTEX@let{LuaTeX}{luatex}


% luahbtex (or luatex + luaharfbuzz)
% Use luaharfbuzz test rather than status.luatex_engine=="luahbtex"
% for issue #2.
\IFTEX@let{luahbtex}{false}
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname directlua\endcsname\relax
\else
  \directlua{\IFTEX@detokenize{
   if(pcall(require, 'luaharfbuzz')) then
     tex.print("\\let\\ifluahbtex\\iftrue ")
   end
  }}

\fi
\IFTEX@let{LuaHBTeX}{luahbtex}


% luametatex
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname directlua\endcsname\relax
  \IFTEX@let{luametatex}{false}
\else
  \ifnum\luatexversion<200
    \IFTEX@let{luametatex}{false}
  \else
    \IFTEX@let{luametatex}{true}
  \fi
\fi
\IFTEX@let{LuaMetaTeX}{luametatex}


% ptex (including all variants) (note that the ptex command uses uptex in current releases)
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname kanjiskip\endcsname\relax
  \IFTEX@let{ptex}{false}
\else
  \IFTEX@let{ptex}{true}
\fi
\IFTEX@let{pTeX}{ptex}

% uptex (including euptex)
\ifx\enablecjktoken \@undefined
  \IFTEX@let{uptex}{false}
\else
  \IFTEX@let{uptex}{true}
\fi
\IFTEX@let{upTeX}{uptex}

% ptex-ng
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname ngbanner\endcsname\relax
  \IFTEX@let{ptexng}{false}
\else
  \IFTEX@let{ptexng}{true}
\fi
\IFTEX@let{pTeXng}{ptexng}

% vtex
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname VTeXversion\endcsname\relax
  \IFTEX@let{vtex}{false}
\else
  \IFTEX@let{vtex}{true}
\fi
\IFTEX@let{VTeX}{vtex}

% aleph
\IFTEX@let{alephtex}{false}
\ifptex\else
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname omathchardef\endcsname\relax
\else
  \IFTEX@let{alephtex}{true}
\fi
\fi
\IFTEX@let{AlephTeX}{alephtex}


% tutex (LuaTeX or XeTeX)
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname Umathchardef\endcsname\relax
  \IFTEX@let{tutex}{false}
\else
  \IFTEX@let{tutex}{true}
\fi
\IFTEX@let{TUTeX}{tutex}


% texpadtex
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname TexpadTeXMode\endcsname\relax
  \IFTEX@let{texpadtex}{false}
\else
  \IFTEX@let{texpadtex}{true}
  \ifcase\TexpadTeXMode\relax
    % This is 8 bit mode
  \or
    \IFTEX@let{tutex}{true}
  \fi
\fi
\IFTEX@let{TexpadTeX}{texpadtex}

% HiTeX
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname HINTversion\endcsname\relax
  \IFTEX@let{hint}{false}
\else
  \IFTEX@let{hint}{true}
\fi
\IFTEX@let{HINT}{hint}

% Prote
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname Proteversion\endcsname\relax
  \IFTEX@let{prote}{false}
\else
  \IFTEX@let{prote}{true}
\fi
\IFTEX@let{Prote}{prote}
 

% Output mode
% declare as if with \newif
\def\pdftrue{\let\ifpdf\iftrue}
\def\pdffalse{\let\ifpdf\iffalse}
\pdffalse
\ifluatex
\directlua{\IFTEX@detokenize{
if (tex.outputmode or tex.pdfoutput or 0) > 0 then
  tex.print('\\pdftrue')
end
}}
\else
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname pdfoutput\endcsname\relax
\ifvtex
  \ifnum\OpMode=3 %
    \pdftrue
  \fi
\else
  \iftexpadtex
    \pdftrue
  \fi
\fi
\else
  \ifnum\pdfoutput>0 %
    \pdftrue
  \fi
\fi
\fi


% restore things
\catcode64 \IFTEX@atcatcode
