% Babelbidi: Bidi extensions for Babel. % % Copyright (C) 2026 Amer Amikhteh % % This file is part of the Babelbidi package. % % This work is free software: you may redistribute it and/or modify % it under the terms of the LaTeX Project Public License as published % by the LaTeX Project, either version 1.3c of the License, or % (at your option) any later version. % % This work is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. % % The full license text is available at: % https://www.latex-project.org/lppl/ % % This work is "maintained" by Amer Amikhteh. % % The current maintainer of this work is Amer Amikhteh. \ProvidesFile{babelbidi-api.def}[2026/11/01 v0.2.0 Bidi API for Babelbidi] \makeatletter % ------------------------------------------ % Determining text direction % ------------------------------------------ \providecommand{\if@RTL}{\ifnum\bbl@thetextdir>\z@} \providecommand{\@RTLtrue}{\chardef\bbl@thetextdir\@ne} \providecommand{\@RTLfalse}{\chardef\bbl@thetextdir\z@} \providecommand{\bbd@main@dir}{0} \providecommand{\if@RTLmain}{% \ifnum\bbd@main@dir>\z@ } \providecommand{\@RTLmaintrue}{% \gdef\bbd@main@dir{1}% } \providecommand{\@RTLmainfalse}{% \gdef\bbd@main@dir{0}% } \AddToHook{begindocument}{% \ifnum\bbl@thetextdir>\z@ \@RTLmaintrue \else \@RTLmainfalse \fi }% % ------------------------------------------ % basic bidi commands % ------------------------------------------ \def\bbd@setdir#1{% \bbl@bodydir{#1}% \bbl@pardir{#1}% Must precede the text direction. \bbl@textdir{#1}% } \ProvideDocumentCommand{\setLTR}{}{\bbd@setdir{0}} \ProvideDocumentCommand{\setRTL}{}{\bbd@setdir{1}} % On TeXXeT engines beginL/R are primitives used by Babel itself. \ifLuaTeX \ProvideDocumentCommand{\beginR}{}{% \begingroup \bbl@textdir{1}% }% \ProvideDocumentCommand{\beginL}{}{% \begingroup \bbl@textdir{0}% }% \ProvideDocumentCommand{\endR}{}{\endgroup} \ProvideDocumentCommand{\endL}{}{\endgroup} \fi % ------------------------------------------ % Core APIs % ------------------------------------------ \long\def\bbd@inline#1#2{% \leavevmode {% \bbl@textdir{#1}% #2% }% } \ProvideDocumentCommand{\RLE}{+m}{\bbd@inline{1}{#1}} \ProvideDocumentCommand{\LRE}{+m}{\bbd@inline{0}{#1}} \ProvideDocumentEnvironment{RTL}{} {% \par \begingroup \bbl@pardir{1}% \bbl@textdir{1}% \bbl@bodydir{1} } {% \par \endgroup }% \ProvideDocumentEnvironment{LTR}{} {% \par \begingroup \bbl@pardir{0}% \bbl@textdir{0}% \bbl@bodydir{0} } {% \par \endgroup }% % ------------------------------------------ % Aliases % ------------------------------------------ \DeclareCommandCopy{\RL}{\RLE} \DeclareCommandCopy{\LR}{\LRE} \DeclareCommandCopy{\setRL}{\setRTL} \DeclareCommandCopy{\unsetLTR}{\setRTL} \DeclareCommandCopy{\setLR}{\setLTR} \DeclareCommandCopy{\unsetRTL}{\setLTR} % ------------------------------------------ % Primitive-style boxes: retain to/spread, \setbox and verbatim scanning. % The content must not be read as a macro argument. % ------------------------------------------ \def\bbd@box#1#2#3#{% % Babel has no box-direction setter. Set the box's own direction % while scanning it, then synchronize its content through Babel. #1\ifLuaTeX bdir #2 \fi#3\bgroup \bbd@setdir{#2}\let\bbd@box@brace } \ProvideDocumentCommand{\hboxL}{}{\bbd@box\hbox{0}} \ProvideDocumentCommand{\hboxR}{}{\bbd@box\hbox{1}} \ProvideDocumentCommand{\vboxL}{}{\bbd@box\vbox{0}} \ProvideDocumentCommand{\vboxR}{}{\bbd@box\vbox{1}} \ProvideDocumentCommand{\vtopL}{}{\bbd@box\vtop{0}} \ProvideDocumentCommand{\vtopR}{}{\bbd@box\vtop{1}} % ------------------------------------------ % Explicit footnote direction, independent of the surrounding language. % Resolve footnotemark/text at use time, including later hyperref patches. % ------------------------------------------ % luabidi's Polyglossia compatibility fallback; preserve any real formatter. \ProvideDocumentCommand{\localnumeral}{s m}{% \IfBooleanTF{#1}% {\expandafter\@arabic\csname c@#2\endcsname}% {#2}% } \def\bbd@footnotemark#1{% \IfNoValueTF{#1}% {\footnotemark}% {\footnotemark[#1]}% } \ProvideDocumentCommand{\bbd@fn@mark@lr}{o}{% \bbd@footnotemark{#1}% } \ProvideDocumentCommand{\bbd@fn@mark@rl}{o}{% \bbd@footnotemark{#1}% } \def\bbd@footnote@dir#1{% \ifPDFTeX % The paragraph direction is set before \@makefntext starts it. % Do not open a TeXXeT run spanning several footnote paragraphs. \bbl@pardir{#1}% \ifnum#1=\z@ \@RTLfalse \else \@RTLtrue \fi \else \bbd@setdir{#1}% \fi } \long\def\bbd@footnote#1#2#3{% \begingroup % Remember the first explicit footnote direction in pdfTeX. \ifPDFTeX \bbd@pdf@remember@fn@dir{#1}% \fi % Select the footnote mark. \ifnum#1=\z@ \let\bbd@mark\bbd@fn@mark@lr \else \let\bbd@mark\bbd@fn@mark@rl \fi \IfNoValueTF{#2}% {\bbd@mark}% {\bbd@mark[#2]}% % Apply the requested direction to the footnote text. \let\bbd@explicit@makefntext\@makefntext \long\def\@makefntext##1{% \bbd@setdir{#1}% \bbd@explicit@makefntext{##1}% }% \IfNoValueTF{#2}% {\footnotetext{{\bbd@footnote@dir{#1}#3}}}% {\footnotetext[#2]{{\bbd@footnote@dir{#1}#3}}}% \endgroup } \ProvideDocumentCommand{\LTRfootnote}{o +m}{% \bbd@footnote{0}{#1}{#2}% } \ProvideDocumentCommand{\RTLfootnote}{o +m}{% \bbd@footnote{1}{#1}{#2}% } % ------------------------------------------ % Footnote rules % ------------------------------------------ \let\bbd@default@footnoterule\footnoterule \newlength\bbd@fn@rulewidth \setlength\bbd@fn@rulewidth{.4\columnwidth} % An expandable register alias also supports \the and direct assignment. \providecommand{\footnoterulewidth}{\bbd@fn@rulewidth} \def\bbd@fn@rule#1{% \kern-3\p@ \nointerlineskip \hboxL to \columnwidth{% \ifnum#1=\@ne \hfil \fi \vrule width \footnoterulewidth height .4\p@ depth \z@ \ifnum#1=\z@ \hfil \fi }% \kern2.6\p@ } \def\bbd@fn@rule@left{% \bbd@fn@rule{0}% } \def\bbd@fn@rule@right{% \bbd@fn@rule{1}% } \def\bbd@fn@rule@full{% \kern-3\p@ \hrule\@width\textwidth \kern2.6\p@ } \ProvideDocumentCommand{\leftfootnoterule}{}{% \global\let\footnoterule\bbd@fn@rule@left } \ProvideDocumentCommand{\rightfootnoterule}{}{% \global\let\footnoterule\bbd@fn@rule@right } \ProvideDocumentCommand{\textwidthfootnoterule}{}{% \global\let\footnoterule\bbd@fn@rule@full } % ------------------------------------------ % Automatic footnote rule % ------------------------------------------ % pdfTeX fallback: % remember the first explicitly directed footnote inserted for the page. \ifPDFTeX % -1 means that no explicitly directed footnote has been seen yet. \newcount\bbd@pdf@fn@dir \bbd@pdf@fn@dir=-1 \def\bbd@pdf@remember@fn@dir#1{% \ifnum\bbd@pdf@fn@dir<\z@ \global\bbd@pdf@fn@dir=#1\relax \fi } \def\bbd@pdf@reset@fn@dir{% \global\bbd@pdf@fn@dir=-1\relax } % Reset after the current page has been shipped out. \AddToHook{shipout/after}{% \bbd@pdf@reset@fn@dir } \def\bbd@fn@rule@auto{% \ifnum\bbd@pdf@fn@dir=\@ne \bbd@fn@rule{1}% \else \bbd@fn@rule{0}% \fi } \ProvideDocumentCommand{\autofootnoterule}{}{% \global\let\footnoterule\bbd@fn@rule@auto } \fi % LuaTeX: % inspect the first hlist line in the footins node list. \ifLuaTeX \newcount\bbd@fn@rule@dir \def\bbd@fn@rule@auto{% \bbd@fn@rule@dir=\z@ \directlua{ local box = tex.box['footins'] local line = table.swapped(node.subtypes('hlist')).line if box and box.list then for n in node.traverse(box.list) do if n.id == node.id('hlist') and n.subtype == line then tex.count['bbd@fn@rule@dir'] = n.direction break end end end }% \bbd@fn@rule{\the\bbd@fn@rule@dir}% } \ProvideDocumentCommand{\autofootnoterule}{}{% \global\let\footnoterule\bbd@fn@rule@auto } \fi % XeTeX deliberately has no definition here. % \autofootnoterule is supplied by bidi. \makeatother \endinput