texlive[74566] Master/texmf-dist: babel (11mar25)
commits+karl at tug.org
commits+karl at tug.org
Tue Mar 11 21:05:14 CET 2025
Revision: 74566
https://tug.org/svn/texlive?view=revision&revision=74566
Author: karl
Date: 2025-03-11 21:05:14 +0100 (Tue, 11 Mar 2025)
Log Message:
-----------
babel (11mar25)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/latex/babel/README.md
trunk/Master/texmf-dist/doc/latex/babel/babel-code.pdf
trunk/Master/texmf-dist/doc/latex/babel/babel.pdf
trunk/Master/texmf-dist/source/latex/babel/babel.dtx
trunk/Master/texmf-dist/source/latex/babel/babel.ins
trunk/Master/texmf-dist/source/latex/babel/bbcompat.dtx
trunk/Master/texmf-dist/source/latex/babel/locale.zip
trunk/Master/texmf-dist/tex/generic/babel/babel-bidi-basic.lua
trunk/Master/texmf-dist/tex/generic/babel/babel.def
trunk/Master/texmf-dist/tex/generic/babel/babel.sty
trunk/Master/texmf-dist/tex/generic/babel/hyphen.cfg
trunk/Master/texmf-dist/tex/generic/babel/locale/cs/babel-cs.ini
trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-1901.ini
trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-1996.ini
trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-AT-1901.ini
trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-AT-1996.ini
trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-AT.ini
trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-CH-1901.ini
trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-CH-1996.ini
trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-CH.ini
trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de.ini
trunk/Master/texmf-dist/tex/generic/babel/locale/nl/babel-nl.ini
trunk/Master/texmf-dist/tex/generic/babel/locale/sk/babel-sk.ini
trunk/Master/texmf-dist/tex/generic/babel/luababel.def
trunk/Master/texmf-dist/tex/generic/babel/nil.ldf
trunk/Master/texmf-dist/tex/generic/babel/txtbabel.def
trunk/Master/texmf-dist/tex/generic/babel/xebabel.def
Added Paths:
-----------
trunk/Master/texmf-dist/tex/generic/babel/babel-bidi-basic-0.lua
trunk/Master/texmf-dist/tex/generic/babel/babel-bidi-basic-1.lua
trunk/Master/texmf-dist/tex/generic/babel/tests-babel-bidi-basic.lua
Modified: trunk/Master/texmf-dist/doc/latex/babel/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/babel/README.md 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/doc/latex/babel/README.md 2025-03-11 20:05:14 UTC (rev 74566)
@@ -1,6 +1,6 @@
-## Babel 25.4
+## Babel 25.5
-2025-02-14
+2025-03-10
`Babel` is the multilingual framework to localize documents. It fully
supports pdfLaTeX and the Unicode engines LuaLaTeX and XeLaTeX. A few
@@ -21,9 +21,9 @@
The latest stable version is available on <https://ctan.org/pkg/babel>.
-Changes in version 25.4 are described in:
+Changes in version 25.5 are described in:
-https://latex3.github.io/babel/news/whats-new-in-babel-25.4.html
+https://latex3.github.io/babel/news/whats-new-in-babel-25.5.html
Apart from the manual, you can find information and examples in:
@@ -59,9 +59,14 @@
### Summary of latest changes
```
-25.4 2025-02-14
- New locales for ancient languages: Etruscan, Old Persian,
- Old Irish, Ugaritic, Carian, Lycian, Lydian, Sabaean.
+25.5 2025-03-10
+ * German: new transform longs.unifraktur, with heuristic rules
+ for long s.
+ * Dutch: new transform diaeresis.hyphen.
+ * Fixes:
+ - Some wrong bidi text in \hbox.
+ - Extra space with CJK and lazy loading.
+ - LaTeX hook for newly defined font families.
```
### Previous changes
Modified: trunk/Master/texmf-dist/doc/latex/babel/babel-code.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/babel/babel.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/source/latex/babel/babel.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/babel/babel.dtx 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/source/latex/babel/babel.dtx 2025-03-11 20:05:14 UTC (rev 74566)
@@ -37,7 +37,7 @@
lang = en-001,
}
\ProvidesFile{babel.dtx}%
- [2025/02/14 v25.4
+ [2025/03/10 v25.5
The multilingual framework for pdfLaTeX, LuaLaTeX and XeLaTeX]
\documentclass{ltxdoc}
\GetFileInfo{babel.dtx}
@@ -373,8 +373,10 @@
\begin{note}
Now that the recommend engine for \LaTeX\ is \luatex, you can read
- \href{https://latex3.github.io/babel/guides/migrating-pdftex-luatex.html}{Migrating
- from pdfTeX to LuaTeX}.
+ \href{https://latex3.github.io/babel/guides/migrating-pdftex-luatex.html}%
+ {Migrating from pdfTeX to LuaTeX} and
+ \href{https://latex3.github.io/babel/guides/migrating-xetex-luatex.html}%
+ {Migrating from XeTeX to LuaTeX}.
\end{note}
\section{The basic user interface}\label{U-I}
@@ -1962,15 +1964,18 @@
which may break the vertical spacing in some cases (for example,
between lists or at the beginning of a table cell). \New{3.64} The
behavior can be adjusted with
- |\babeladjust{select.write=<mode>}|, where \m{mode} is |shift|
- (which shifts the skips down and adds a |\penalty|); |keep| (the
- default -- with it the |\write| and the skips are kept in the order
- they are written), and |omit| (which may seem a too drastic
- solution, because nothing is written, but more often than not this
- command is applied to more or less shorts texts with no sectioning
- or similar commands, and therefore no language synchronization is
- necessary). In a table cell, a |\leavevmode| just before the
- selector may be enough.
+ |\babeladjust{select.write=<mode>}|, where \m{mode} is:
+ \begin{itemize}
+ \item |keep|, the default – with it the |\write| and the skips are
+ kept in the order they are written);
+ \item |shift|, which shifts the skips down and adds a |\penalty|;
+ \item |omit|, which may seem a too drastic solution, because
+ nothing is written, but more often than not this command is applied
+ to more or less shorts texts with no sectioning or similar
+ commands, and therefore no language synchronization is necessary.
+ In a table cell, a |\leavevmode| just before the selector may be
+ enough.
+ \end{itemize}
\end{itemize}
\end{warning}
@@ -4292,6 +4297,9 @@
\trans{Czech, Polish, Slovak}{oneletter.nobreak}{Converts a space after
a non-syllabic preposition or conjunction into a non-breaking space.}
+\trans{Dutch}{diaeresis.hyphen}{Removes the diaeresis above a vowel if
+hyphenated just before.}
+
\trans{Finnish}{prehyphen.nobreak}{Line breaks just after hyphens
prepended to words are prevented, as in “pakastekaapit ja -arkut”.}
@@ -4298,6 +4306,13 @@
\trans{French}{punctuation.space}{Rules for proper spacing with
characters \textit{;:!?«»} are applied.}
+\trans{German}{longs.unifraktur}{Implements the basic heuristic rules
+for the long s (ſ) from those in Unifraktur Maguntia. Although
+discretionaries aren’t taken into account, the transform is declared in
+the posthyphenation group, to ease if necessary fine tuning the rules
+for, e.g., prefixes and compound words. They are available in all
+German locales. See \New{25.5} for further details and an example.}
+
\trans{Greek}{diaeresis.hyphen}{Removes the diaeresis above iota and
upsilon if hyphenated just before. It works with the three variants.}
@@ -4320,8 +4335,8 @@
\trans{Hindi, Sanskrit}{transliteration.hk}{The Harvard-Kyoto system to
romanize Devanagari.}
-\trans{Hindi, Sanskrit}{punctuation.space}{Inserts a space before the following
-four characters: \textit{!?:;}\,.}
+\trans{Hindi, Sanskrit}{punctuation.space}{Inserts a space before the
+following four characters: \textit{!?:;}\,.}
\trans{Hungarian}{digraphs.hyphen}{Hyphenates the long digraphs
\textit{ccs}, \textit{ddz}, \textit{ggy}, \textit{lly}, \textit{nny},
@@ -4332,6 +4347,9 @@
danda or double danda if there is a space. For Assamese, Bengali,
Gujarati, Hindi, Kannada, Malayalam, Marathi, Odia, Tamil, Telugu.}
+\trans{Japanese}{linebreak.strict}{Prevents line breaks before small
+kana variants.}
+
\trans{Latin}{digraphs.ligatures}{Replaces the groups \textit{ae},
\textit{AE}, \textit{oe}, \textit{OE} with \textit{æ}, \textit{Æ},
\textit{œ}, \textit{Œ}.}
@@ -4502,7 +4520,8 @@
\DescribeOther{\disablelocaletransform}{\marg{label}}
\New{3.85} Enables and disables the transform with the given label in
-the current language.
+the current language. Font dependent transforms are always enabled and
+cannot be disabled.
\subsection{Support for \xetex{} interchar}
\label{interchar}
@@ -6050,8 +6069,8 @@
% \section{Tools}
%
% \begin{macrocode}
-%<<version=25.4>>
-%<<date=2025/02/14>>
+%<<version=25.5>>
+%<<date=2025/03/10>>
% \end{macrocode}
%
% \textbf{Do not use the following macros in \texttt{ldf} files. They
@@ -6248,6 +6267,18 @@
\def\bbl at foreach#1{\expandafter\bbl at vforeach\expandafter{#1}}
% \end{macrocode}
%
+% Some code should be executed once. The first argument is a flag.
+%
+% \begin{macrocode}
+\global\let\bbl at done\@empty
+\def\bbl at once#1#2{%
+ \bbl at xin@{,#1,}{,\bbl at done,}%
+ \ifin@\else
+ #2%
+ \xdef\bbl at done{\bbl at done,#1,}%
+ \fi}
+% \end{macrode}
+%
% \macro{\bbl at replace}
%
% Returns implicitly |\toks@| with the modified string.
@@ -6296,7 +6327,8 @@
\def\bbl at tempc{% Expanded an executed below as 'uplevel'
\\\makeatletter % "internal" macros with @ are assumed
\\\scantokens{%
- \bbl at tempa\\\@namedef{\bbl at stripslash#1}\bbl at tempb{\bbl at tempe}}%
+ \bbl at tempa\\\@namedef{\bbl at stripslash#1}\bbl at tempb{\bbl at tempe}%
+ \noexpand\noexpand}%
\catcode64=\the\catcode64\relax}% Restore @
\else
\let\bbl at tempc\@empty % Not \relax
@@ -8693,7 +8725,11 @@
% change in casing to fix it in the same way languages names are fixed.
%
% \begin{macrocode}
-\def\languageshorthands#1{\def\language at group{#1}}
+\def\languageshorthands#1{%
+ \bbl at ifsamestring{none}{#1}{}{%
+ \bbl at once{short-\localename-#1}{%
+ \bbl at info{'\localename' activates '#1' shorthands.\\Reported }}}%
+ \def\language at group{#1}}
% \end{macrocode}
%
% \macro{\aliasshorthand}
@@ -11211,8 +11247,8 @@
\global\let\bbl at patchchapter\relax
\gdef\bbl at chfmt{%
\bbl at ifunset{bbl@\bbl at chaptype fmt@\languagename}%
- {\@chapapp\space\thechapter}
- {\@nameuse{bbl@\bbl at chaptype fmt@\languagename}}}
+ {\@chapapp\space\thechapter}%
+ {\@nameuse{bbl@\bbl at chaptype fmt@\languagename}}}%
\bbl at add\appendix{\def\bbl at chaptype{appendix}}% Not harmful, I hope
\bbl at sreplace\ps at headings{\@chapapp\ \thechapter}{\bbl at chfmt}%
\bbl at sreplace\chaptermark{\@chapapp\ \thechapter}{\bbl at chfmt}%
@@ -11230,8 +11266,8 @@
\global\let\bbl at patchpart\relax
\gdef\bbl at partformat{%
\bbl at ifunset{bbl at partfmt@\languagename}%
- {\partname\nobreakspace\thepart}
- {\@nameuse{bbl at partfmt@\languagename}}}
+ {\partname\nobreakspace\thepart}%
+ {\@nameuse{bbl at partfmt@\languagename}}}%
\bbl at sreplace\@part{\partname\nobreakspace\thepart}{\bbl at partformat}%
\bbl at toglobal\@part}
\fi
@@ -11277,6 +11313,11 @@
{\@nameuse{bbl at date@\languagename @\bbl at calendar}%
\bbl at they\bbl at them\bbl at thed}%
\endgroup}
+\def\bbl at printdate#1{%
+ \@ifnextchar[{\bbl at printdate@i{#1}}{\bbl at printdate@i{#1}[]}}
+\def\bbl at printdate@i#1[#2]#3#4#5{%
+ \bbl at usedategrouptrue
+ \@nameuse{bbl at ensure@#1}{\localedate[#2]{#3}{#4}{#5}}}
% e.g.: 1=months, 2=wide, 3=1, 4=dummy, 5=value, 6=calendar
\def\bbl at inidate#1.#2.#3.#4\relax#5#6{% TODO - ignore with 'captions'
\bbl at trim@def\bbl at tempa{#1.#2}%
@@ -11304,34 +11345,8 @@
{\\\the\year}{\\\the\month}{\\\the\day}}}}%
\fi}%
{}}}
-\def\bbl at printdate#1{%
- \@ifnextchar[{\bbl at printdate@i{#1}}{\bbl at printdate@i{#1}[]}}
-\def\bbl at printdate@i#1[#2]#3#4#5{%
- \bbl at usedategrouptrue
- \@nameuse{bbl at ensure@#1}{\localedate[#2]{#3}{#4}{#5}}}
% \end{macrocode}
%
-% \subsection{French spacing (again)}
-%
-% For the following declarations, see issue \#240. |\nonfrenchspacing|
-% is set by |document| too early, so it’s a hack.
-%
-% \begin{macrocode}
-\AddToHook{begindocument/before}{%
- \let\bbl at normalsf\normalsfcodes
- \let\normalsfcodes\relax}
-\AtBeginDocument{%
- \ifx\bbl at normalsf\@empty
- \ifnum\sfcode`\.=\@m
- \let\normalsfcodes\frenchspacing
- \else
- \let\normalsfcodes\nonfrenchspacing
- \fi
- \else
- \let\normalsfcodes\bbl at normalsf
- \fi}
-% \end{macrocode}
-%
% \textbf{Dates} will require some macros for the basic formatting.
% They may be redefined by language, so ``semi-public'' names (camel
% case) are used. Oddly enough, the CLDR places particles like “de”
@@ -11386,6 +11401,27 @@
\def\bbl at xdatecntr[#1|#2]{\localenumeral{#2}{#1}}
% \end{macrocode}
%
+% \subsection{French spacing (again)}
+%
+% For the following declarations, see issue \#240. |\nonfrenchspacing|
+% is set by |document| too early, so it’s a hack.
+%
+% \begin{macrocode}
+\AddToHook{begindocument/before}{%
+ \let\bbl at normalsf\normalsfcodes
+ \let\normalsfcodes\relax}
+\AtBeginDocument{%
+ \ifx\bbl at normalsf\@empty
+ \ifnum\sfcode`\.=\@m
+ \let\normalsfcodes\frenchspacing
+ \else
+ \let\normalsfcodes\nonfrenchspacing
+ \fi
+ \else
+ \let\normalsfcodes\bbl at normalsf
+ \fi}
+% \end{macrocode}
+%
% \textbf{Transforms.}
%
% \begin{macrocode}
@@ -13780,11 +13816,12 @@
\bbl at exp{%
\\\newcommand\<#1default>{}% Just define it
\\\bbl at add@list\\\bbl at font@fams{#1}%
+ \\\NewHook{#1family}%
\\\DeclareRobustCommand\<#1family>{%
\\\not at math@alphabet\<#1family>\relax
% \\\prepare at family@series at update{#1}\<#1default>% TODO. Fails
\\\fontfamily\<#1default>%
- \<ifx>\\\UseHooks\\\@undefined\<else>\\\UseHook{#1family}\<fi>%
+ \\\UseHook{#1family}%
\\\selectfont}%
\\\DeclareTextFontCommand{\<text#1>}{\<#1family>}}}
% \end{macrocode}
@@ -13907,7 +13944,13 @@
% \end{macrocode}
%
% Loaded locally, which does its job, but very must be global. The
-% problem is how.
+% problem is how. This actually defines a font predeclared with
+% |\babelfont|, making sure |Script| and |Language| names are defined.
+% If they are not, the corresponding data in the ini file is used. The
+% font is actually set temporarily to get the family name
+% (|\f at family|). There is also a hack because by default some
+% replacements related to the bold series are sometimes assigned to the
+% wrong font (see issue \#92).
%
% \begin{macrocode}
\def\bbl at fontspec@set#1#2#3#4{% eg \bbl at rmdflt@lang fnt-opt fnt-nme \xxfamily
@@ -14263,8 +14306,6 @@
%<*xetex|texxet>
\providecommand\bbl at provide@intraspace{}
\bbl at trace{Redefinitions for bidi layout}
-\def\bbl at sspre@caption{% TODO: Unused!
- \bbl at exp{\everyhbox{\\\bbl at textdir\bbl at cs{wdir@\bbl at main@language}}}}
\ifx\bbl at opt@layout\@nnil\else % if layout=..
\def\bbl at startskip{\ifcase\bbl at thepardir\leftskip\else\rightskip\fi}
\def\bbl at endskip{\ifcase\bbl at thepardir\rightskip\else\leftskip\fi}
@@ -15049,8 +15090,7 @@
end
end,
'Babel.hyphenate')
- }
-}
+ }}
\endgroup
\def\bbl at provide@intraspace{%
\bbl at ifunset{bbl at intsp@\languagename}{}%
@@ -15260,7 +15300,9 @@
end
end
- % Tatwil
+ % Tatwil. First create a list of nodes marked with kashida. The
+ % rest of nodes can be ignored. The list of used weigths is build
+ % when transforms with the key kashida= are declared.
if Babel.kashida_wts then
local k_wt = node.get_attribute(n, KASHIDA)
if k_wt > 0 then % todo. parameter for multi inserts
@@ -15295,6 +15337,11 @@
end
% == Tatwil ==
+ % Traverse the kashida node list so many times as required, until
+ % the line if filled. The first pass adds a tatweel after each
+ % node with kashida in the line, the second pass adds another one,
+ % and so on. In each pass, add first the kashida with the highest
+ % weight, then with lower weight and so on.
if #k_list == 0 then goto next_line end
width = node.dimensions(line.head) % The 'natural' width
@@ -15378,7 +15425,7 @@
,Greek,Latin,Old Church Slavonic Cyrillic,}
\ifnum\bbl at bidimode=102 % bidi-r
\bbl at add\bbl at scr@node at list{Arabic,Hebrew,Syriac}
-\fi
+\fi
\def\bbl at set@renderer{%
\bbl at xin@{\bbl at cl{sname}}{\bbl at scr@node at list}%
\ifin@
@@ -16092,7 +16139,7 @@
\let\@eqnnum\bbl at eqnum
\fi
\fi}
- % Hack. YA luatex bug?:
+ % Hack for wrong vertical spacing with \[ \]. YA luatex bug?:
\expandafter\bbl at sreplace\csname] \endcsname{$$}{\eqno\kern.001pt$$}%
\else % amstex
\bbl at exp{% Hack to hide maybe undefined conditionals:
@@ -16237,7 +16284,7 @@
% TODO - catch non-valid values
\fi
% == mapfont ==
- % For bidi texts, to switch the font based on direction
+ % For bidi texts, to switch the font based on direction. Old.
\ifx\bbl at KVP@mapfont\@nnil\else
\bbl at ifsamestring{\bbl at KVP@mapfont}{direction}{}%
{\bbl at error{unknown-mapfont}{}{}{}}%
@@ -16260,7 +16307,7 @@
\fi
\bbl at exp{\\\bbl at add\\\bbl at mapselect{\\\bbl at mapdir{\languagename}}}%
\fi
- % == Line breaking: CJK quotes ==
+ % == Line breaking: CJK quotes ==
\ifcase\bbl at engine\or
\bbl at xin@{/c}{/\bbl at cl{lnbrk}}%
\ifin@
@@ -23490,25 +23537,23 @@
local has_hyperlink = false
local ATDIR = Babel.attr_dir
- local attr_d
+ local attr_d, temp
+ local locale_d
local save_outer
- local temp = node.get_attribute(head, ATDIR)
- if temp then
- temp = temp & 0x3
- save_outer = (temp == 0 and 'l') or
- (temp == 1 and 'r') or
- (temp == 2 and 'al')
- elseif ispar then -- Or error? Shouldn't happen
+ local locale_d = node.get_attribute(head, ATDIR)
+ if locale_d then
+ locale_d = locale_d & 0x3
+ save_outer = (locale_d == 0 and 'l') or
+ (locale_d == 1 and 'r') or
+ (locale_d == 2 and 'al')
+ elseif ispar then -- Or error? Shouldn't happen
+ -- when the callback is called, we are just _after_ the box,
+ -- and the textdir is that of the surrounding text
save_outer = ('TRT' == tex.pardir) and 'r' or 'l'
- else -- Or error? Shouldn't happen
+ else -- Empty box
save_outer = ('TRT' == hdir) and 'r' or 'l'
end
- -- when the callback is called, we are just _after_ the box,
- -- and the textdir is that of the surrounding text
- -- if not ispar and hdir ~= tex.textdir then
- -- save_outer = ('TRT' == hdir) and 'r' or 'l'
- -- end
local outer = save_outer
local last = outer
-- 'al' is only taken into account in the first, current loop
@@ -23517,15 +23562,18 @@
local fontmap = Babel.fontmap
for item in node.traverse(head) do
-
+
+ -- Mask: DxxxPPTT (Done, Pardir [0-2], Textdir [0-2])
+ locale_d = node.get_attribute(item, ATDIR)
+ node.set_attribute(item, ATDIR, 0x80)
+
-- In what follows, #node is the last (previous) node, because the
-- current one is not added until we start processing the neutrals.
-
-- three cases: glyph, dir, otherwise
if glyph_not_symbol_font(item)
or (item.id == 7 and item.subtype == 2) then
- if node.get_attribute(item, ATDIR) == 128 then goto nextnode end
+ if locale_d == 0x80 then goto nextnode end
local d_font = nil
local item_r
@@ -23552,6 +23600,7 @@
d = d or 'l'
-- A short 'pause' in bidi for mapfont
+ -- %%%% TODO. move if fontmap here
d_font = d_font or d
d_font = (d_font == 'l' and 0) or
(d_font == 'nsm' and 0) or
@@ -23567,8 +23616,7 @@
if inmath then
attr_d = 0
else
- attr_d = node.get_attribute(item, ATDIR)
- attr_d = attr_d & 0x3
+ attr_d = locale_d & 0x3
end
if attr_d == 1 then
outer_first = 'r'
@@ -23596,9 +23644,8 @@
elseif item.id == DIR then
d = nil
+ new_d = true
- if head ~= item then new_d = true end
-
elseif item.id == node.id'glue' and item.subtype == 13 then
glue_d = d
glue_i = item
@@ -23678,7 +23725,6 @@
table.insert(nodes, {item, d, outer_first})
end
- node.set_attribute(item, ATDIR, 128)
outer_first = nil
::nextnode::
@@ -23864,12 +23910,13 @@
return head
end
--- Make sure anything is marked as 'bidi done' (including nodes inserted
--- after the babel algorithm). 128 = 1000 0000.
+% \end{macrocode}
+%
+% \begin{macrocode}
function Babel.unset_atdir(head)
local ATDIR = Babel.attr_dir
for item in node.traverse(head) do
- node.set_attribute(item, ATDIR, 128)
+ node.set_attribute(item, ATDIR, 0x80)
end
return head
end
Modified: trunk/Master/texmf-dist/source/latex/babel/babel.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex/babel/babel.ins 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/source/latex/babel/babel.ins 2025-03-11 20:05:14 UTC (rev 74566)
@@ -26,7 +26,7 @@
%% and covered by LPPL is defined by the unpacking scripts (with
%% extension .ins) which are part of the distribution.
%%
-\def\filedate{2025/02/14}
+\def\filedate{2025/03/10}
\def\batchfile{babel.ins}
\input docstrip.tex
Modified: trunk/Master/texmf-dist/source/latex/babel/bbcompat.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/babel/bbcompat.dtx 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/source/latex/babel/bbcompat.dtx 2025-03-11 20:05:14 UTC (rev 74566)
@@ -30,7 +30,7 @@
%
% \iffalse
%<*dtx>
-\ProvidesFile{bbcompat.dtx}[2025/02/14 v25.4]
+\ProvidesFile{bbcompat.dtx}[2025/03/10 v25.5]
%</dtx>
%
%% File 'bbcompat.dtx'
Modified: trunk/Master/texmf-dist/source/latex/babel/locale.zip
===================================================================
(Binary files differ)
Added: trunk/Master/texmf-dist/tex/generic/babel/babel-bidi-basic-0.lua
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/babel-bidi-basic-0.lua (rev 0)
+++ trunk/Master/texmf-dist/tex/generic/babel/babel-bidi-basic-0.lua 2025-03-11 20:05:14 UTC (rev 74566)
@@ -0,0 +1,504 @@
+--
+-- This is file `babel-bidi-basic.lua',
+-- generated with the docstrip utility.
+--
+-- The original source files were:
+--
+-- babel.dtx (with options: `basic')
+--
+--
+-- Copyright (C) 2012-2025 Javier Bezos and Johannes L. Braams.
+-- Copyright (C) 1989-2012 Johannes L. Braams and
+-- any individual authors listed elsewhere in this file.
+-- All rights reserved.
+--
+--
+-- This file is part of the Babel system.
+-- --------------------------------------
+--
+-- It may be distributed and/or modified under the
+-- conditions of the LaTeX Project Public License, either version 1.3
+-- of this license or (at your option) any later version.
+-- The latest version of this license is in
+-- http://www.latex-project.org/lppl.txt
+-- and version 1.3 or later is part of all distributions of LaTeX
+-- version 2003/12/01 or later.
+--
+-- This work has the LPPL maintenance status "maintained".
+--
+-- The Current Maintainer of this work is Javier Bezos.
+--
+-- The list of derived (unpacked) files belonging to the distribution
+-- and covered by LPPL is defined by the unpacking scripts (with
+-- extension |.ins|) which are part of the distribution.
+--
+-- e.g., Babel.fontmap[1][<prefontid>]=<dirfontid>
+
+Babel.fontmap = Babel.fontmap or {}
+Babel.fontmap[0] = {} -- l
+Babel.fontmap[1] = {} -- r
+Babel.fontmap[2] = {} -- al/an
+
+-- To cancel mirroring. Also OML, OMS, U?
+Babel.symbol_fonts = Babel.symbol_fonts or {}
+Babel.symbol_fonts[font.id('tenln')] = true
+Babel.symbol_fonts[font.id('tenlnw')] = true
+Babel.symbol_fonts[font.id('tencirc')] = true
+Babel.symbol_fonts[font.id('tencircw')] = true
+
+Babel.bidi_enabled = true
+Babel.mirroring_enabled = true
+
+require('babel-data-bidi.lua')
+
+local characters = Babel.characters
+local ranges = Babel.ranges
+
+local DIR = node.id('dir')
+local GLYPH = node.id('glyph')
+
+local function insert_implicit(head, state, outer)
+ local new_state = state
+ if state.sim and state.eim and state.sim ~= state.eim then
+ dir = ((outer == 'r') and 'TLT' or 'TRT') -- i.e., reverse
+ local d = node.new(DIR)
+ d.dir = '+' .. dir
+ node.insert_before(head, state.sim, d)
+ local d = node.new(DIR)
+ d.dir = '-' .. dir
+ node.insert_after(head, state.eim, d)
+ end
+ new_state.sim, new_state.eim = nil, nil
+ return head, new_state
+end
+
+local function insert_numeric(head, state)
+ local new
+ local new_state = state
+ if state.san and state.ean and state.san ~= state.ean then
+ local d = node.new(DIR)
+ d.dir = '+TLT'
+ _, new = node.insert_before(head, state.san, d)
+ if state.san == state.sim then state.sim = new end
+ local d = node.new(DIR)
+ d.dir = '-TLT'
+ _, new = node.insert_after(head, state.ean, d)
+ if state.ean == state.eim then state.eim = new end
+ end
+ new_state.san, new_state.ean = nil, nil
+ return head, new_state
+end
+
+local function glyph_not_symbol_font(node)
+ if node.id == GLYPH then
+ return not Babel.symbol_fonts[node.font]
+ else
+ return false
+ end
+end
+
+-- TODO - \hbox with an explicit dir can lead to wrong results
+-- <R \hbox dir TLT{<R>}> and <L \hbox dir TRT{<L>}>. A small attempt
+-- was made to improve the situation, but the problem is the 3-dir
+-- model in babel/Unicode and the 2-dir model in LuaTeX don't fit
+-- well.
+
+function Babel.bidi(head, ispar, hdir)
+ local d -- d is used mainly for computations in a loop
+ local prev_d = ''
+ local new_d = false
+
+ local nodes = {}
+ local outer_first = nil
+ local inmath = false
+
+ local glue_d = nil
+ local glue_i = nil
+
+ local has_en = false
+ local first_et = nil
+
+ local has_hyperlink = false
+
+ local ATDIR = Babel.attr_dir
+ local attr_d, temp
+ local locale_d
+
+ local save_outer
+ local locale_d = node.get_attribute(head, ATDIR)
+ if locale_d then
+ locale_d = locale_d & 0x3
+ save_outer = (locale_d == 0 and 'l') or
+ (locale_d == 1 and 'r') or
+ (locale_d == 2 and 'al')
+ elseif ispar then -- Or error? Shouldn't happen
+ save_outer = ('TRT' == tex.pardir) and 'r' or 'l'
+ else -- Or error? Shouldn't happen
+ save_outer = ('TRT' == hdir) and 'r' or 'l'
+ end
+ -- when the callback is called, we are just _after_ the box,
+ -- and the textdir is that of the surrounding text
+ -- if not ispar and hdir ~= tex.textdir then
+ -- save_outer = ('TRT' == hdir) and 'r' or 'l'
+ -- end
+ local outer = save_outer
+ local last = outer
+ -- 'al' is only taken into account in the first, current loop
+ if save_outer == 'al' then save_outer = 'r' end
+
+ local fontmap = Babel.fontmap
+
+ for item in node.traverse(head) do
+
+ -- Mask: DxxxPPTT (Done, Pardir, Textdir)
+ locale_d = node.get_attribute(item, ATDIR)
+ texio.write_nl(locale_d or '???')
+ node.set_attribute(item, ATDIR, 0x80)
+
+ -- In what follows, #node is the last (previous) node, because the
+ -- current one is not added until we start processing the neutrals.
+ -- three cases: glyph, dir, otherwise
+ if glyph_not_symbol_font(item)
+ or (item.id == 7 and item.subtype == 2) then
+
+ if locale_d == 0x80 then goto nextnode end
+
+ local d_font = nil
+ local item_r
+ if item.id == 7 and item.subtype == 2 then
+ item_r = item.replace -- automatic discs have just 1 glyph
+ else
+ item_r = item
+ end
+
+ local chardata = characters[item_r.char]
+ d = chardata and chardata.d or nil
+ if not d or d == 'nsm' then
+ for nn, et in ipairs(ranges) do
+ if item_r.char < et[1] then
+ break
+ elseif item_r.char <= et[2] then
+ if not d then d = et[3]
+ elseif d == 'nsm' then d_font = et[3]
+ end
+ break
+ end
+ end
+ end
+ d = d or 'l'
+
+ -- A short 'pause' in bidi for mapfont
+ -- %%%% TODO. move if fontmap here
+ d_font = d_font or d
+ d_font = (d_font == 'l' and 0) or
+ (d_font == 'nsm' and 0) or
+ (d_font == 'r' and 1) or
+ (d_font == 'al' and 2) or
+ (d_font == 'an' and 2) or nil
+ if d_font and fontmap and fontmap[d_font][item_r.font] then
+ item_r.font = fontmap[d_font][item_r.font]
+ end
+
+ if new_d then
+ table.insert(
+ nodes, {nil, (outer == 'l') and 'l' or 'r', nil, locale_d})
+ if inmath then
+ attr_d = 0
+ else
+ attr_d = locale_d & 0x3
+ end
+ if attr_d == 1 then
+ outer_first = 'r'
+ last = 'r'
+ elseif attr_d == 2 then
+ outer_first = 'r'
+ last = 'al'
+ else
+ outer_first = 'l'
+ last = 'l'
+ end
+ outer = last
+ has_en = false
+ first_et = nil
+ new_d = false
+ end
+
+ if glue_d then
+ if (d == 'l' and 'l' or 'r') ~= glue_d then
+ table.insert(nodes, {glue_i, 'on', nil, locale_d})
+ end
+ glue_d = nil
+ glue_i = nil
+ end
+
+ elseif item.id == DIR then
+ d = nil
+
+ if head ~= item then new_d = true end
+
+ elseif item.id == node.id'glue' and item.subtype == 13 then
+ glue_d = d
+ glue_i = item
+ d = nil
+
+ elseif item.id == node.id'math' then
+ inmath = (item.subtype == 0)
+
+ elseif item.id == 8 and item.subtype == 19 then
+ has_hyperlink = true
+
+ else
+ d = nil
+ end
+
+ -- AL <= EN/ET/ES -- W2 + W3 + W6
+ if last == 'al' and d == 'en' then
+ d = 'an' -- W3
+ elseif last == 'al' and (d == 'et' or d == 'es') then
+ d = 'on' -- W6
+ end
+
+ -- EN + CS/ES + EN -- W4
+ if d == 'en' and #nodes >= 2 then
+ if (nodes[#nodes][2] == 'es' or nodes[#nodes][2] == 'cs')
+ and nodes[#nodes-1][2] == 'en' then
+ nodes[#nodes][2] = 'en'
+ end
+ end
+
+ -- AN + CS + AN -- W4 too, because uax9 mixes both cases
+ if d == 'an' and #nodes >= 2 then
+ if (nodes[#nodes][2] == 'cs')
+ and nodes[#nodes-1][2] == 'an' then
+ nodes[#nodes][2] = 'an'
+ end
+ end
+
+ -- ET/EN -- W5 + W7->l / W6->on
+ if d == 'et' then
+ first_et = first_et or (#nodes + 1)
+ elseif d == 'en' then
+ has_en = true
+ first_et = first_et or (#nodes + 1)
+ elseif first_et then -- d may be nil here !
+ if has_en then
+ if last == 'l' then
+ temp = 'l' -- W7
+ else
+ temp = 'en' -- W5
+ end
+ else
+ temp = 'on' -- W6
+ end
+ for e = first_et, #nodes do
+ if glyph_not_symbol_font(nodes[e][1]) then nodes[e][2] = temp end
+ end
+ first_et = nil
+ has_en = false
+ end
+
+ -- Force mathdir in math if ON (currently works as expected only
+ -- with 'l')
+
+ if inmath and d == 'on' then
+ d = ('TRT' == tex.mathdir) and 'r' or 'l'
+ end
+
+ if d then
+ if d == 'al' then
+ d = 'r'
+ last = 'al'
+ elseif d == 'l' or d == 'r' then
+ last = d
+ end
+ prev_d = d
+ table.insert(nodes, {item, d, outer_first, locale_d})
+ end
+
+ outer_first = nil
+
+ ::nextnode::
+
+ end -- for each node
+
+ -- TODO -- repeated here in case EN/ET is the last node. Find a
+ -- better way of doing things:
+ if first_et then -- dir may be nil here !
+ if has_en then
+ if last == 'l' then
+ temp = 'l' -- W7
+ else
+ temp = 'en' -- W5
+ end
+ else
+ temp = 'on' -- W6
+ end
+ for e = first_et, #nodes do
+ if glyph_not_symbol_font(nodes[e][1]) then nodes[e][2] = temp end
+ end
+ end
+
+ -- dummy node, to close things
+ table.insert(
+ nodes, {nil, (outer == 'l') and 'l' or 'r', nil, locale_d})
+
+ --------------- NEUTRAL -----------------
+
+ outer = save_outer
+ last = outer
+
+ local first_on = nil
+
+ for q = 1, #nodes do
+ local item
+
+ local outer_first = nodes[q][3]
+ outer = outer_first or outer
+ last = outer_first or last
+
+ local d = nodes[q][2]
+ if d == 'an' or d == 'en' then d = 'r' end
+ if d == 'cs' or d == 'et' or d == 'es' then d = 'on' end --- W6
+
+ if d == 'on' then
+ first_on = first_on or q
+ elseif first_on then
+ if last == d then
+ temp = d
+ else
+ temp = outer
+ end
+ for r = first_on, q - 1 do
+ nodes[r][2] = temp
+ item = nodes[r][1] -- MIRRORING
+ if Babel.mirroring_enabled and glyph_not_symbol_font(item)
+ and temp == 'r' and characters[item.char] then
+ local font_mode = ''
+ if item.font > 0 and font.fonts[item.font].properties then
+ font_mode = font.fonts[item.font].properties.mode
+ end
+ if font_mode ~= 'harf' and font_mode ~= 'plug' and
+ (nodes[r][4] or 0) & 0x3 > 0 then
+ item.char = characters[item.char].m or item.char
+ end
+ end
+ end
+ first_on = nil
+ end
+
+ if d == 'r' or d == 'l' then last = d end
+ end
+
+ -------------- IMPLICIT, REORDER ----------------
+
+ outer = save_outer
+ last = outer
+
+ local state = {}
+ state.has_r = false
+
+ for q = 1, #nodes do
+
+ local item = nodes[q][1]
+
+ outer = nodes[q][3] or outer
+
+ local d = nodes[q][2]
+
+ if d == 'nsm' then d = last end -- W1
+ if d == 'en' then d = 'an' end
+ local isdir = (d == 'r' or d == 'l')
+
+ if outer == 'l' and d == 'an' then
+ state.san = state.san or item
+ state.ean = item
+ elseif state.san then
+ head, state = insert_numeric(head, state)
+ end
+
+ if outer == 'l' then
+ if d == 'an' or d == 'r' then -- im -> implicit
+ if d == 'r' then state.has_r = true end
+ state.sim = state.sim or item
+ state.eim = item
+ elseif d == 'l' and state.sim and state.has_r then
+ head, state = insert_implicit(head, state, outer)
+ elseif d == 'l' then
+ state.sim, state.eim, state.has_r = nil, nil, false
+ end
+ else
+ if d == 'an' or d == 'l' then
+ if nodes[q][3] then -- nil except after an explicit dir
+ state.sim = item -- so we move sim 'inside' the group
+ else
+ state.sim = state.sim or item
+ end
+ state.eim = item
+ elseif d == 'r' and state.sim then
+ head, state = insert_implicit(head, state, outer)
+ elseif d == 'r' then
+ state.sim, state.eim = nil, nil
+ end
+ end
+
+ if isdir then
+ last = d -- Don't search back - best save now
+ elseif d == 'on' and state.san then
+ state.san = state.san or item
+ state.ean = item
+ end
+
+ end
+
+ head = node.prev(head) or head
+ --- FIXES ---
+ if has_hyperlink then
+ local flag, linking = 0, 0
+ for item in node.traverse(head) do
+ if item.id == DIR then
+ if item.dir == '+TRT' or item.dir == '+TLT' then
+ flag = flag + 1
+ elseif item.dir == '-TRT' or item.dir == '-TLT' then
+ flag = flag - 1
+ end
+ elseif item.id == 8 and item.subtype == 19 then
+ linking = flag
+ elseif item.id == 8 and item.subtype == 20 then
+ if linking > 0 then
+ if item.prev.id == DIR and
+ (item.prev.dir == '-TRT' or item.prev.dir == '-TLT') then
+ d = node.new(DIR)
+ d.dir = item.prev.dir
+ node.remove(head, item.prev)
+ node.insert_after(head, item, d)
+ end
+ end
+ linking = 0
+ end
+ end
+ end
+
+ for item in node.traverse_id(10, head) do
+ local p = item
+ local flag = false
+ while p.prev and p.prev.id == 14 do
+ flag = true
+ p = p.prev
+ end
+ if flag then
+ node.insert_before(head, p, node.copy(item))
+ node.remove(head,item)
+ end
+ end
+
+ return head
+end
+-- Make sure anything is marked as 'bidi done' (including nodes inserted
+-- after the babel algorithm). 128 = 1000 0000.
+function Babel.unset_atdir(head)
+ local ATDIR = Babel.attr_dir
+ for item in node.traverse(head) do
+ node.set_attribute(item, ATDIR, 128)
+ end
+ return head
+end
Property changes on: trunk/Master/texmf-dist/tex/generic/babel/babel-bidi-basic-0.lua
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/generic/babel/babel-bidi-basic-1.lua
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/babel-bidi-basic-1.lua (rev 0)
+++ trunk/Master/texmf-dist/tex/generic/babel/babel-bidi-basic-1.lua 2025-03-11 20:05:14 UTC (rev 74566)
@@ -0,0 +1,522 @@
+--
+-- This is file `babel-bidi-basic.lua',
+-- generated with the docstrip utility.
+--
+-- The original source files were:
+--
+-- babel.dtx (with options: `basic')
+--
+--
+-- Copyright (C) 2012-2025 Javier Bezos and Johannes L. Braams.
+-- Copyright (C) 1989-2012 Johannes L. Braams and
+-- any individual authors listed elsewhere in this file.
+-- All rights reserved.
+--
+--
+-- This file is part of the Babel system.
+-- --------------------------------------
+--
+-- It may be distributed and/or modified under the
+-- conditions of the LaTeX Project Public License, either version 1.3
+-- of this license or (at your option) any later version.
+-- The latest version of this license is in
+-- http://www.latex-project.org/lppl.txt
+-- and version 1.3 or later is part of all distributions of LaTeX
+-- version 2003/12/01 or later.
+--
+-- This work has the LPPL maintenance status "maintained".
+--
+-- The Current Maintainer of this work is Javier Bezos.
+--
+-- The list of derived (unpacked) files belonging to the distribution
+-- and covered by LPPL is defined by the unpacking scripts (with
+-- extension |.ins|) which are part of the distribution.
+--
+-- e.g., Babel.fontmap[1][<prefontid>]=<dirfontid>
+
+Babel.fontmap = Babel.fontmap or {}
+Babel.fontmap[0] = {} -- l
+Babel.fontmap[1] = {} -- r
+Babel.fontmap[2] = {} -- al/an
+
+-- To cancel mirroring. Also OML, OMS, U?
+Babel.symbol_fonts = Babel.symbol_fonts or {}
+Babel.symbol_fonts[font.id('tenln')] = true
+Babel.symbol_fonts[font.id('tenlnw')] = true
+Babel.symbol_fonts[font.id('tencirc')] = true
+Babel.symbol_fonts[font.id('tencircw')] = true
+
+Babel.bidi_enabled = true
+Babel.mirroring_enabled = true
+
+require('babel-data-bidi.lua')
+
+local characters = Babel.characters
+local ranges = Babel.ranges
+
+local DIR = node.id('dir')
+local GLYPH = node.id('glyph')
+
+local function insert_implicit(head, state, outer)
+ local new_state = state
+ if state.sim and state.eim and state.sim ~= state.eim then
+ dir = ((outer == 'r') and 'TLT' or 'TRT') -- i.e., reverse
+ local d = node.new(DIR)
+ d.dir = '+' .. dir
+ node.insert_before(head, state.sim, d)
+ local d = node.new(DIR)
+ d.dir = '-' .. dir
+ node.insert_after(head, state.eim, d)
+ end
+ new_state.sim, new_state.eim = nil, nil
+ return head, new_state
+end
+
+local function insert_numeric(head, state)
+ local new
+ local new_state = state
+ if state.san and state.ean and state.san ~= state.ean then
+ local d = node.new(DIR)
+ d.dir = '+TLT'
+ _, new = node.insert_before(head, state.san, d)
+ if state.san == state.sim then state.sim = new end
+ local d = node.new(DIR)
+ d.dir = '-TLT'
+ _, new = node.insert_after(head, state.ean, d)
+ if state.ean == state.eim then state.eim = new end
+ end
+ new_state.san, new_state.ean = nil, nil
+ return head, new_state
+end
+
+local function glyph_not_symbol_font(node)
+ if node.id == GLYPH then
+ return not Babel.symbol_fonts[node.font]
+ else
+ return false
+ end
+end
+
+-- TODO - \hbox with an explicit dir can lead to wrong results
+-- <R \hbox dir TLT{<R>}> and <L \hbox dir TRT{<L>}>. A small attempt
+-- was made to improve the situation, but the problem is the 3-dir
+-- model in babel/Unicode and the 2-dir model in LuaTeX don't fit
+-- well.
+
+function Babel.bidi(head, ispar, hdir)
+ local d -- d is used mainly for computations in a loop
+ local prev_d = ''
+ local new_d = false
+
+ local nodes = {}
+ local outer_first = nil
+ local inmath = false
+
+ local glue_d = nil
+ local glue_i = nil
+
+ local has_en = false
+ local first_et = nil
+
+ local has_hyperlink = false
+
+ local ATDIR = Babel.attr_dir
+ local attr_d, temp
+ local locale_d
+
+ local save_outer
+ local locale_d = node.get_attribute(head, ATDIR)
+ if locale_d then
+ locale_d = locale_d & 0x3
+ save_outer = (locale_d == 0 and 'l') or
+ (locale_d == 1 and 'r') or
+ (locale_d == 2 and 'al')
+ texio.write_nl('++ ' .. save_outer)
+ elseif ispar then -- Or error? Shouldn't happen
+ texio.write_nl('++ P')
+ save_outer = ('TRT' == tex.pardir) and 'r' or 'l'
+ else
+ texio.write_nl('++ H') -- Or error? Shouldn't happen
+ save_outer = ('TRT' == hdir) and 'r' or 'l'
+ end
+ -- texio.write('hdir=' .. tex.pardir)
+ texio.write(save_outer)
+ -- when the callback is called, we are just _after_ the box,
+ -- and the textdir is that of the surrounding text
+ -- if not ispar and hdir ~= tex.textdir then
+ -- save_outer = ('TRT' == hdir) and 'r' or 'l'
+ -- end
+ local outer = save_outer
+ local last = outer
+ if head.id == DIR then
+ outer = 'l'
+ end
+ -- 'al' is only taken into account in the first, current loop
+ if save_outer == 'al' then save_outer = 'r' end
+
+ local fontmap = Babel.fontmap
+
+ for item in node.traverse(head) do
+
+ -- Mask: DxxxPPTT (Done, Pardir [0-2], Textdir [0-2])
+ locale_d = node.get_attribute(item, ATDIR)
+ --texio.write_nl('ld=' .. (locale_d or '?'))
+ node.set_attribute(item, ATDIR, 0x80)
+
+ -- In what follows, #node is the last (previous) node, because the
+ -- current one is not added until we start processing the neutrals.
+ -- three cases: glyph, dir, otherwise
+ if glyph_not_symbol_font(item)
+ or (item.id == 7 and item.subtype == 2) then
+
+ if locale_d == 0x80 then goto nextnode end
+
+ local d_font = nil
+ local item_r
+ if item.id == 7 and item.subtype == 2 then
+ item_r = item.replace -- automatic discs have just 1 glyph
+ else
+ item_r = item
+ end
+
+ local chardata = characters[item_r.char]
+ d = chardata and chardata.d or nil
+ if not d or d == 'nsm' then
+ for nn, et in ipairs(ranges) do
+ if item_r.char < et[1] then
+ break
+ elseif item_r.char <= et[2] then
+ if not d then d = et[3]
+ elseif d == 'nsm' then d_font = et[3]
+ end
+ break
+ end
+ end
+ end
+ d = d or 'l'
+
+ -- A short 'pause' in bidi for mapfont
+ -- %%%% TODO. move if fontmap here
+ d_font = d_font or d
+ d_font = (d_font == 'l' and 0) or
+ (d_font == 'nsm' and 0) or
+ (d_font == 'r' and 1) or
+ (d_font == 'al' and 2) or
+ (d_font == 'an' and 2) or nil
+ if d_font and fontmap and fontmap[d_font][item_r.font] then
+ item_r.font = fontmap[d_font][item_r.font]
+ end
+
+ if new_d then
+ table.insert(
+ nodes, {nil, (outer == 'l') and 'l' or 'r', nil, locale_d})
+ if inmath then
+ attr_d = 0
+ else
+ attr_d = locale_d & 0x3
+ end
+ if attr_d == 1 then
+ outer_first = 'r'
+ last = 'r'
+ elseif attr_d == 2 then
+ outer_first = 'r'
+ last = 'al'
+ else
+ outer_first = 'l'
+ last = 'l'
+ end
+ outer = last
+ has_en = false
+ first_et = nil
+ new_d = false
+ end
+
+ if glue_d then
+ if (d == 'l' and 'l' or 'r') ~= glue_d then
+ table.insert(nodes, {glue_i, 'on', nil, locale_d})
+ end
+ glue_d = nil
+ glue_i = nil
+ end
+
+ elseif item.id == DIR then
+ d = nil
+
+ if head ~= item then new_d = true end
+ -- new_d = true
+
+ elseif item.id == node.id'glue' and item.subtype == 13 then
+ glue_d = d
+ glue_i = item
+ d = nil
+
+ elseif item.id == node.id'math' then
+ inmath = (item.subtype == 0)
+
+ elseif item.id == 8 and item.subtype == 19 then
+ has_hyperlink = true
+
+ else
+ d = nil
+ end
+
+ -- AL <= EN/ET/ES -- W2 + W3 + W6
+ if last == 'al' and d == 'en' then
+ d = 'an' -- W3
+ elseif last == 'al' and (d == 'et' or d == 'es') then
+ d = 'on' -- W6
+ end
+
+ -- EN + CS/ES + EN -- W4
+ if d == 'en' and #nodes >= 2 then
+ if (nodes[#nodes][2] == 'es' or nodes[#nodes][2] == 'cs')
+ and nodes[#nodes-1][2] == 'en' then
+ nodes[#nodes][2] = 'en'
+ end
+ end
+
+ -- AN + CS + AN -- W4 too, because uax9 mixes both cases
+ if d == 'an' and #nodes >= 2 then
+ if (nodes[#nodes][2] == 'cs')
+ and nodes[#nodes-1][2] == 'an' then
+ nodes[#nodes][2] = 'an'
+ end
+ end
+
+ -- ET/EN -- W5 + W7->l / W6->on
+ if d == 'et' then
+ first_et = first_et or (#nodes + 1)
+ elseif d == 'en' then
+ has_en = true
+ first_et = first_et or (#nodes + 1)
+ elseif first_et then -- d may be nil here !
+ if has_en then
+ if last == 'l' then
+ temp = 'l' -- W7
+ else
+ temp = 'en' -- W5
+ end
+ else
+ temp = 'on' -- W6
+ end
+ for e = first_et, #nodes do
+ if glyph_not_symbol_font(nodes[e][1]) then nodes[e][2] = temp end
+ end
+ first_et = nil
+ has_en = false
+ end
+
+ -- Force mathdir in math if ON (currently works as expected only
+ -- with 'l')
+
+ if inmath and d == 'on' then
+ d = ('TRT' == tex.mathdir) and 'r' or 'l'
+ end
+
+ if d then
+ if d == 'al' then
+ d = 'r'
+ last = 'al'
+ elseif d == 'l' or d == 'r' then
+ last = d
+ end
+ prev_d = d
+ table.insert(nodes, {item, d, outer_first, locale_d})
+ end
+
+ outer_first = nil
+
+ ::nextnode::
+
+ end -- for each node
+
+ -- TODO -- repeated here in case EN/ET is the last node. Find a
+ -- better way of doing things:
+ if first_et then -- dir may be nil here !
+ if has_en then
+ if last == 'l' then
+ temp = 'l' -- W7
+ else
+ temp = 'en' -- W5
+ end
+ else
+ temp = 'on' -- W6
+ end
+ for e = first_et, #nodes do
+ if glyph_not_symbol_font(nodes[e][1]) then nodes[e][2] = temp end
+ end
+ end
+
+ -- dummy node, to close things
+ table.insert(
+ nodes, {nil, (outer == 'l') and 'l' or 'r', nil, locale_d})
+
+ --------------- NEUTRAL -----------------
+
+ outer = save_outer
+ last = outer
+
+ local first_on = nil
+
+ for q = 1, #nodes do
+ local item
+
+ local outer_first = nodes[q][3]
+ outer = outer_first or outer
+ last = outer_first or last
+
+ local d = nodes[q][2]
+ if d == 'an' or d == 'en' then d = 'r' end
+ if d == 'cs' or d == 'et' or d == 'es' then d = 'on' end --- W6
+
+ if d == 'on' then
+ first_on = first_on or q
+ elseif first_on then
+ if last == d then
+ temp = d
+ else
+ temp = outer
+ end
+ for r = first_on, q - 1 do
+ nodes[r][2] = temp
+ item = nodes[r][1] -- MIRRORING
+ if Babel.mirroring_enabled and glyph_not_symbol_font(item)
+ and temp == 'r' and characters[item.char] then
+ local font_mode = ''
+ if item.font > 0 and font.fonts[item.font].properties then
+ font_mode = font.fonts[item.font].properties.mode
+ end
+ texio.write_nl('id=' .. node.get_attribute(
+ item, Babel.attr_locale) or '?')
+ texio.write(' from= ' .. item.char or '?')
+ texio.write(' dir=' .. ((nodes[r][4] or 3)))
+ texio.write(' nodedir=' .. (nodes[r][2]))
+ if font_mode ~= 'harf' and font_mode ~= 'plug' then
+ -- if Babel.locale_props[tonumber(node.get_attribute(
+ -- item, Babel.attr_locale))].textdir ~= 'x' then
+ -- item.char = characters[item.char].m or item.char
+ -- end
+ -- if (nodes[r][4] or 0) & 0x3 > 0 then
+ item.char = characters[item.char].m or item.char
+ texio.write(' to= ' .. item.char or '?')
+ -- end
+ end
+ end
+ end
+ first_on = nil
+ end
+
+ if d == 'r' or d == 'l' then last = d end
+ end
+
+ -------------- IMPLICIT, REORDER ----------------
+
+ outer = save_outer
+ last = outer
+
+ local state = {}
+ state.has_r = false
+
+ for q = 1, #nodes do
+
+ local item = nodes[q][1]
+
+ outer = nodes[q][3] or outer
+
+ local d = nodes[q][2]
+
+ if d == 'nsm' then d = last end -- W1
+ if d == 'en' then d = 'an' end
+ local isdir = (d == 'r' or d == 'l')
+
+ if outer == 'l' and d == 'an' then
+ state.san = state.san or item
+ state.ean = item
+ elseif state.san then
+ head, state = insert_numeric(head, state)
+ end
+
+ if outer == 'l' then
+ if d == 'an' or d == 'r' then -- im -> implicit
+ if d == 'r' then state.has_r = true end
+ state.sim = state.sim or item
+ state.eim = item
+ elseif d == 'l' and state.sim and state.has_r then
+ head, state = insert_implicit(head, state, outer)
+ elseif d == 'l' then
+ state.sim, state.eim, state.has_r = nil, nil, false
+ end
+ else
+ if d == 'an' or d == 'l' then
+ if nodes[q][3] then -- nil except after an explicit dir
+ state.sim = item -- so we move sim 'inside' the group
+ else
+ state.sim = state.sim or item
+ end
+ state.eim = item
+ elseif d == 'r' and state.sim then
+ head, state = insert_implicit(head, state, outer)
+ elseif d == 'r' then
+ state.sim, state.eim = nil, nil
+ end
+ end
+
+ if isdir then
+ last = d -- Don't search back - best save now
+ elseif d == 'on' and state.san then
+ state.san = state.san or item
+ state.ean = item
+ end
+
+ end
+
+ head = node.prev(head) or head
+ --- FIXES ---
+ if has_hyperlink then
+ local flag, linking = 0, 0
+ for item in node.traverse(head) do
+ if item.id == DIR then
+ if item.dir == '+TRT' or item.dir == '+TLT' then
+ flag = flag + 1
+ elseif item.dir == '-TRT' or item.dir == '-TLT' then
+ flag = flag - 1
+ end
+ elseif item.id == 8 and item.subtype == 19 then
+ linking = flag
+ elseif item.id == 8 and item.subtype == 20 then
+ if linking > 0 then
+ if item.prev.id == DIR and
+ (item.prev.dir == '-TRT' or item.prev.dir == '-TLT') then
+ d = node.new(DIR)
+ d.dir = item.prev.dir
+ node.remove(head, item.prev)
+ node.insert_after(head, item, d)
+ end
+ end
+ linking = 0
+ end
+ end
+ end
+
+ for item in node.traverse_id(10, head) do
+ local p = item
+ local flag = false
+ while p.prev and p.prev.id == 14 do
+ flag = true
+ p = p.prev
+ end
+ if flag then
+ node.insert_before(head, p, node.copy(item))
+ node.remove(head,item)
+ end
+ end
+
+ return head
+end
+function Babel.unset_atdir(head)
+ local ATDIR = Babel.attr_dir
+ for item in node.traverse(head) do
+ node.set_attribute(item, ATDIR, 0x80)
+ end
+ return head
+end
Property changes on: trunk/Master/texmf-dist/tex/generic/babel/babel-bidi-basic-1.lua
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/tex/generic/babel/babel-bidi-basic.lua
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/babel-bidi-basic.lua 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/babel-bidi-basic.lua 2025-03-11 20:05:14 UTC (rev 74566)
@@ -121,25 +121,23 @@
local has_hyperlink = false
local ATDIR = Babel.attr_dir
- local attr_d
+ local attr_d, temp
+ local locale_d
local save_outer
- local temp = node.get_attribute(head, ATDIR)
- if temp then
- temp = temp & 0x3
- save_outer = (temp == 0 and 'l') or
- (temp == 1 and 'r') or
- (temp == 2 and 'al')
- elseif ispar then -- Or error? Shouldn't happen
+ local locale_d = node.get_attribute(head, ATDIR)
+ if locale_d then
+ locale_d = locale_d & 0x3
+ save_outer = (locale_d == 0 and 'l') or
+ (locale_d == 1 and 'r') or
+ (locale_d == 2 and 'al')
+ elseif ispar then -- Or error? Shouldn't happen
+ -- when the callback is called, we are just _after_ the box,
+ -- and the textdir is that of the surrounding text
save_outer = ('TRT' == tex.pardir) and 'r' or 'l'
- else -- Or error? Shouldn't happen
+ else -- Empty box
save_outer = ('TRT' == hdir) and 'r' or 'l'
end
- -- when the callback is called, we are just _after_ the box,
- -- and the textdir is that of the surrounding text
- -- if not ispar and hdir ~= tex.textdir then
- -- save_outer = ('TRT' == hdir) and 'r' or 'l'
- -- end
local outer = save_outer
local last = outer
-- 'al' is only taken into account in the first, current loop
@@ -149,14 +147,17 @@
for item in node.traverse(head) do
+ -- Mask: DxxxPPTT (Done, Pardir [0-2], Textdir [0-2])
+ locale_d = node.get_attribute(item, ATDIR)
+ node.set_attribute(item, ATDIR, 0x80)
+
-- In what follows, #node is the last (previous) node, because the
-- current one is not added until we start processing the neutrals.
-
-- three cases: glyph, dir, otherwise
if glyph_not_symbol_font(item)
or (item.id == 7 and item.subtype == 2) then
- if node.get_attribute(item, ATDIR) == 128 then goto nextnode end
+ if locale_d == 0x80 then goto nextnode end
local d_font = nil
local item_r
@@ -183,6 +184,7 @@
d = d or 'l'
-- A short 'pause' in bidi for mapfont
+ -- %%%% TODO. move if fontmap here
d_font = d_font or d
d_font = (d_font == 'l' and 0) or
(d_font == 'nsm' and 0) or
@@ -198,8 +200,7 @@
if inmath then
attr_d = 0
else
- attr_d = node.get_attribute(item, ATDIR)
- attr_d = attr_d & 0x3
+ attr_d = locale_d & 0x3
end
if attr_d == 1 then
outer_first = 'r'
@@ -227,9 +228,8 @@
elseif item.id == DIR then
d = nil
+ new_d = true
- if head ~= item then new_d = true end
-
elseif item.id == node.id'glue' and item.subtype == 13 then
glue_d = d
glue_i = item
@@ -309,7 +309,6 @@
table.insert(nodes, {item, d, outer_first})
end
- node.set_attribute(item, ATDIR, 128)
outer_first = nil
::nextnode::
@@ -486,12 +485,10 @@
return head
end
--- Make sure anything is marked as 'bidi done' (including nodes inserted
--- after the babel algorithm). 128 = 1000 0000.
function Babel.unset_atdir(head)
local ATDIR = Babel.attr_dir
for item in node.traverse(head) do
- node.set_attribute(item, ATDIR, 128)
+ node.set_attribute(item, ATDIR, 0x80)
end
return head
end
Modified: trunk/Master/texmf-dist/tex/generic/babel/babel.def
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/babel.def 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/babel.def 2025-03-11 20:05:14 UTC (rev 74566)
@@ -39,7 +39,7 @@
\wlog{File: #1 #4 #3 <#2>}%
\let\ProvidesFile\@undefined}
\fi
-\ProvidesFile{babel.def}[2025/02/14 v25.4 Babel common definitions]
+\ProvidesFile{babel.def}[2025/03/10 v25.5 Babel common definitions]
\ifx\AtBeginDocument\@undefined
\def\@empty{}
\def\loadlocalcfg#1{%
@@ -505,6 +505,13 @@
\expandafter\bbl at fornext
\fi}
\def\bbl at foreach#1{\expandafter\bbl at vforeach\expandafter{#1}}
+\global\let\bbl at done\@empty
+\def\bbl at once#1#2{%
+ \bbl at xin@{,#1,}{,\bbl at done,}%
+ \ifin@\else
+ #2%
+ \xdef\bbl at done{\bbl at done,#1,}%
+ \fi}
\def\bbl at replace#1#2#3{% in #1 -> repl #2 by #3
\toks@{}%
\def\bbl at replace@aux##1#2##2#2{%
@@ -535,7 +542,8 @@
\def\bbl at tempc{% Expanded an executed below as 'uplevel'
\\\makeatletter % "internal" macros with @ are assumed
\\\scantokens{%
- \bbl at tempa\\\@namedef{\bbl at stripslash#1}\bbl at tempb{\bbl at tempe}}%
+ \bbl at tempa\\\@namedef{\bbl at stripslash#1}\bbl at tempb{\bbl at tempe}%
+ \noexpand\noexpand}%
\catcode64=\the\catcode64\relax}% Restore @
\else
\let\bbl at tempc\@empty % Not \relax
@@ -595,8 +603,8 @@
\toks@\expandafter{\bbl at tempc#3}%
\expandafter\edef\csname extras\languagename\endcsname{\the\toks@}%
\fi}
-\def\bbl at version{25.4}
-\def\bbl at date{2025/02/14}
+\def\bbl at version{25.5}
+\def\bbl at date{2025/03/10}
\ifx\language\@undefined
\csname newcount\endcsname\language
\fi
@@ -1515,7 +1523,11 @@
\bbl at set@user at generic{\expandafter\string\@car#2\@nil}\bbl at tempb
\fi
\declare at shorthand{\bbl at tempb}{#2}{#3}}}
-\def\languageshorthands#1{\def\language at group{#1}}
+\def\languageshorthands#1{%
+ \bbl at ifsamestring{none}{#1}{}{%
+ \bbl at once{short-\localename-#1}{%
+ \bbl at info{'\localename' activates '#1' shorthands.\\Reported }}}%
+ \def\language at group{#1}}
\def\aliasshorthand#1#2{%
\bbl at ifshorthand{#2}%
{\expandafter\ifx\csname active at char\string#2\endcsname\relax
Modified: trunk/Master/texmf-dist/tex/generic/babel/babel.sty
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/babel.sty 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/babel.sty 2025-03-11 20:05:14 UTC (rev 74566)
@@ -34,7 +34,7 @@
%%
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{babel}%
- [2025/02/14 v25.4
+ [2025/03/10 v25.5
The multilingual framework for pdfLaTeX, LuaLaTeX and XeLaTeX]
\@ifpackagewith{babel}{debug}
{\providecommand\bbl at trace[1]{\message{^^J[ #1 ]}}%
@@ -170,6 +170,13 @@
\expandafter\bbl at fornext
\fi}
\def\bbl at foreach#1{\expandafter\bbl at vforeach\expandafter{#1}}
+\global\let\bbl at done\@empty
+\def\bbl at once#1#2{%
+ \bbl at xin@{,#1,}{,\bbl at done,}%
+ \ifin@\else
+ #2%
+ \xdef\bbl at done{\bbl at done,#1,}%
+ \fi}
\def\bbl at replace#1#2#3{% in #1 -> repl #2 by #3
\toks@{}%
\def\bbl at replace@aux##1#2##2#2{%
@@ -200,7 +207,8 @@
\def\bbl at tempc{% Expanded an executed below as 'uplevel'
\\\makeatletter % "internal" macros with @ are assumed
\\\scantokens{%
- \bbl at tempa\\\@namedef{\bbl at stripslash#1}\bbl at tempb{\bbl at tempe}}%
+ \bbl at tempa\\\@namedef{\bbl at stripslash#1}\bbl at tempb{\bbl at tempe}%
+ \noexpand\noexpand}%
\catcode64=\the\catcode64\relax}% Restore @
\else
\let\bbl at tempc\@empty % Not \relax
@@ -466,8 +474,8 @@
\expandafter\@secondoftwo
\fi}
\fi
-\def\bbl at version{25.4}
-\def\bbl at date{2025/02/14}
+\def\bbl at version{25.5}
+\def\bbl at date{2025/03/10}
\ifx\language\@undefined
\csname newcount\endcsname\language
\fi
@@ -1386,7 +1394,11 @@
\bbl at set@user at generic{\expandafter\string\@car#2\@nil}\bbl at tempb
\fi
\declare at shorthand{\bbl at tempb}{#2}{#3}}}
-\def\languageshorthands#1{\def\language at group{#1}}
+\def\languageshorthands#1{%
+ \bbl at ifsamestring{none}{#1}{}{%
+ \bbl at once{short-\localename-#1}{%
+ \bbl at info{'\localename' activates '#1' shorthands.\\Reported }}}%
+ \def\language at group{#1}}
\def\aliasshorthand#1#2{%
\bbl at ifshorthand{#2}%
{\expandafter\ifx\csname active at char\string#2\endcsname\relax
@@ -2941,8 +2953,8 @@
\global\let\bbl at patchchapter\relax
\gdef\bbl at chfmt{%
\bbl at ifunset{bbl@\bbl at chaptype fmt@\languagename}%
- {\@chapapp\space\thechapter}
- {\@nameuse{bbl@\bbl at chaptype fmt@\languagename}}}
+ {\@chapapp\space\thechapter}%
+ {\@nameuse{bbl@\bbl at chaptype fmt@\languagename}}}%
\bbl at add\appendix{\def\bbl at chaptype{appendix}}% Not harmful, I hope
\bbl at sreplace\ps at headings{\@chapapp\ \thechapter}{\bbl at chfmt}%
\bbl at sreplace\chaptermark{\@chapapp\ \thechapter}{\bbl at chfmt}%
@@ -2960,8 +2972,8 @@
\global\let\bbl at patchpart\relax
\gdef\bbl at partformat{%
\bbl at ifunset{bbl at partfmt@\languagename}%
- {\partname\nobreakspace\thepart}
- {\@nameuse{bbl at partfmt@\languagename}}}
+ {\partname\nobreakspace\thepart}%
+ {\@nameuse{bbl at partfmt@\languagename}}}%
\bbl at sreplace\@part{\partname\nobreakspace\thepart}{\bbl at partformat}%
\bbl at toglobal\@part}
\fi
@@ -3000,6 +3012,11 @@
{\@nameuse{bbl at date@\languagename @\bbl at calendar}%
\bbl at they\bbl at them\bbl at thed}%
\endgroup}
+\def\bbl at printdate#1{%
+ \@ifnextchar[{\bbl at printdate@i{#1}}{\bbl at printdate@i{#1}[]}}
+\def\bbl at printdate@i#1[#2]#3#4#5{%
+ \bbl at usedategrouptrue
+ \@nameuse{bbl at ensure@#1}{\localedate[#2]{#3}{#4}{#5}}}
\def\bbl at inidate#1.#2.#3.#4\relax#5#6{% TODO - ignore with 'captions'
\bbl at trim@def\bbl at tempa{#1.#2}%
\bbl at ifsamestring{\bbl at tempa}{months.wide}% to savedate
@@ -3026,24 +3043,6 @@
{\\\the\year}{\\\the\month}{\\\the\day}}}}%
\fi}%
{}}}
-\def\bbl at printdate#1{%
- \@ifnextchar[{\bbl at printdate@i{#1}}{\bbl at printdate@i{#1}[]}}
-\def\bbl at printdate@i#1[#2]#3#4#5{%
- \bbl at usedategrouptrue
- \@nameuse{bbl at ensure@#1}{\localedate[#2]{#3}{#4}{#5}}}
-\AddToHook{begindocument/before}{%
- \let\bbl at normalsf\normalsfcodes
- \let\normalsfcodes\relax}
-\AtBeginDocument{%
- \ifx\bbl at normalsf\@empty
- \ifnum\sfcode`\.=\@m
- \let\normalsfcodes\frenchspacing
- \else
- \let\normalsfcodes\nonfrenchspacing
- \fi
- \else
- \let\normalsfcodes\bbl at normalsf
- \fi}
\let\bbl at calendar\@empty
\newcommand\babelcalendar[2][\the\year-\the\month-\the\day]{%
\@nameuse{bbl at ca@#2}#1\@@}
@@ -3087,6 +3086,19 @@
\bbl at replace@finish at iii\bbl at toreplace}
\def\bbl at datecntr{\expandafter\bbl at xdatecntr\expandafter}
\def\bbl at xdatecntr[#1|#2]{\localenumeral{#2}{#1}}
+\AddToHook{begindocument/before}{%
+ \let\bbl at normalsf\normalsfcodes
+ \let\normalsfcodes\relax}
+\AtBeginDocument{%
+ \ifx\bbl at normalsf\@empty
+ \ifnum\sfcode`\.=\@m
+ \let\normalsfcodes\frenchspacing
+ \else
+ \let\normalsfcodes\nonfrenchspacing
+ \fi
+ \else
+ \let\normalsfcodes\bbl at normalsf
+ \fi}
\bbl at csarg\let{inikv at transforms.prehyphenation}\bbl at inikv
\bbl at csarg\let{inikv at transforms.posthyphenation}\bbl at inikv
\def\bbl at transforms@aux#1#2#3#4,#5\relax{%
Modified: trunk/Master/texmf-dist/tex/generic/babel/hyphen.cfg
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/hyphen.cfg 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/hyphen.cfg 2025-03-11 20:05:14 UTC (rev 74566)
@@ -37,10 +37,10 @@
\wlog{File: #1 #4 #3 <#2>}%
\let\ProvidesFile\@undefined}
\fi
-\ProvidesFile{hyphen.cfg}[2025/02/14 v25.4 Babel hyphens]
+\ProvidesFile{hyphen.cfg}[2025/03/10 v25.5 Babel hyphens]
\xdef\bbl at format{\jobname}
-\def\bbl at version{25.4}
-\def\bbl at date{2025/02/14}
+\def\bbl at version{25.5}
+\def\bbl at date{2025/03/10}
\ifx\AtBeginDocument\@undefined
\def\@empty{}
\fi
Modified: trunk/Master/texmf-dist/tex/generic/babel/locale/cs/babel-cs.ini
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/locale/cs/babel-cs.ini 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/locale/cs/babel-cs.ini 2025-03-11 20:05:14 UTC (rev 74566)
@@ -9,8 +9,8 @@
[identification]
charset = utf8
-version = 1.4
-date = 2022-07-02
+version = 1.5
+date = 2025-03-04
name.local = čeština
name.english = Czech
name.babel = czech
@@ -183,7 +183,7 @@
[counters]
[transforms.prehyphenation]
-oneletter.nobreak.1.0 = { |[AIiVvOoUuSsZzKk]()|() }
+oneletter.nobreak.1.0 = { |[AaIiVvOoUuSsZzKk]()|() }
oneletter.nobreak.1.1 = { insert, penalty=10000 }
oneletter.nobreak.1.2 = {}
Modified: trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-1901.ini
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-1901.ini 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-1901.ini 2025-03-11 20:05:14 UTC (rev 74566)
@@ -9,8 +9,8 @@
[identification]
charset = utf8
-version = 1.5
-date = 2022-07-02
+version = 1.6
+date = 2025-03-08
name.local = Deutsch
name.english = German
name.babel = german german-traditional
@@ -180,4 +180,16 @@
plusSign = +
superscriptingExponent = ·
-[counters]
+[transforms.posthyphenation]
+longs.unifraktur.1.0 = { g|?()s()|?[act] }
+longs.unifraktur.1.1 = {string = ſ }
+longs.unifraktur.2.0 = { [AEOUYaeioyäöüı]|?()s()|?[acteiouyäöüpſs] }
+longs.unifraktur.2.1 = { string = ſ }
+longs.unifraktur.3.0 = { [bdfhklrſtu]|?()s()|?[acteiouyäöüp] }
+longs.unifraktur.3.1 = {string = ſ}
+longs.unifraktur.4.0 = { [cjmnpqvw]|?()s()|?[acteiouyäöüpkr] }
+longs.unifraktur.4.1 = {string = ſ}
+longs.unifraktur.5.0 = { [ßsxz]|?()s()|?[acteiouyäöüpkrbdfghjlmnqvwßſxz] }
+longs.unifraktur.5.1 = { string = ſ}
+longs.unifraktur.6.0 = { ^{A}*()s() }
+longs.unifraktur.6.1 = { string = ſ }
Modified: trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-1996.ini
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-1996.ini 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-1996.ini 2025-03-11 20:05:14 UTC (rev 74566)
@@ -9,8 +9,8 @@
[identification]
charset = utf8
-version = 1.5
-date = 2022-07-02
+version = 1.6
+date = 2025-03-08
name.local = Deutsch
name.english = German
name.babel = ngerman german
@@ -179,4 +179,16 @@
plusSign = +
superscriptingExponent = ·
-[counters]
+[transforms.posthyphenation]
+longs.unifraktur.1.0 = { g|?()s()|?[act] }
+longs.unifraktur.1.1 = {string = ſ }
+longs.unifraktur.2.0 = { [AEOUYaeioyäöüı]|?()s()|?[acteiouyäöüpſs] }
+longs.unifraktur.2.1 = { string = ſ }
+longs.unifraktur.3.0 = { [bdfhklrſtu]|?()s()|?[acteiouyäöüp] }
+longs.unifraktur.3.1 = {string = ſ}
+longs.unifraktur.4.0 = { [cjmnpqvw]|?()s()|?[acteiouyäöüpkr] }
+longs.unifraktur.4.1 = {string = ſ}
+longs.unifraktur.5.0 = { [ßsxz]|?()s()|?[acteiouyäöüpkrbdfghjlmnqvwßſxz] }
+longs.unifraktur.5.1 = { string = ſ}
+longs.unifraktur.6.0 = { ^{A}*()s() }
+longs.unifraktur.6.1 = { string = ſ }
Modified: trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-AT-1901.ini
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-AT-1901.ini 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-AT-1901.ini 2025-03-11 20:05:14 UTC (rev 74566)
@@ -9,8 +9,8 @@
[identification]
charset = utf8
-version = 1.5
-date = 2022-07-02
+version = 1.6
+date = 2025-03-08
name.local = Österreichisches Deutsch
name.english = Austrian German
name.babel = austrian-traditional german-austria-traditional german-at-traditional austriangerman-traditional austrian
@@ -185,4 +185,16 @@
plusSign = +
superscriptingExponent = ·
-[counters]
+[transforms.posthyphenation]
+longs.unifraktur.1.0 = { g|?()s()|?[act] }
+longs.unifraktur.1.1 = {string = ſ }
+longs.unifraktur.2.0 = { [AEOUYaeioyäöüı]|?()s()|?[acteiouyäöüpſs] }
+longs.unifraktur.2.1 = { string = ſ }
+longs.unifraktur.3.0 = { [bdfhklrſtu]|?()s()|?[acteiouyäöüp] }
+longs.unifraktur.3.1 = {string = ſ}
+longs.unifraktur.4.0 = { [cjmnpqvw]|?()s()|?[acteiouyäöüpkr] }
+longs.unifraktur.4.1 = {string = ſ}
+longs.unifraktur.5.0 = { [ßsxz]|?()s()|?[acteiouyäöüpkrbdfghjlmnqvwßſxz] }
+longs.unifraktur.5.1 = { string = ſ}
+longs.unifraktur.6.0 = { ^{A}*()s() }
+longs.unifraktur.6.1 = { string = ſ }
Modified: trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-AT-1996.ini
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-AT-1996.ini 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-AT-1996.ini 2025-03-11 20:05:14 UTC (rev 74566)
@@ -9,8 +9,8 @@
[identification]
charset = utf8
-version = 1.5
-date = 2022-07-02
+version = 1.6
+date = 2025-03-08
name.local = Österreichisches Deutsch
name.english = Austrian German
name.babel = austrian german-austria german-at austriangerman naustrian
@@ -185,4 +185,16 @@
plusSign = +
superscriptingExponent = ·
-[counters]
+[transforms.posthyphenation]
+longs.unifraktur.1.0 = { g|?()s()|?[act] }
+longs.unifraktur.1.1 = {string = ſ }
+longs.unifraktur.2.0 = { [AEOUYaeioyäöüı]|?()s()|?[acteiouyäöüpſs] }
+longs.unifraktur.2.1 = { string = ſ }
+longs.unifraktur.3.0 = { [bdfhklrſtu]|?()s()|?[acteiouyäöüp] }
+longs.unifraktur.3.1 = {string = ſ}
+longs.unifraktur.4.0 = { [cjmnpqvw]|?()s()|?[acteiouyäöüpkr] }
+longs.unifraktur.4.1 = {string = ſ}
+longs.unifraktur.5.0 = { [ßsxz]|?()s()|?[acteiouyäöüpkrbdfghjlmnqvwßſxz] }
+longs.unifraktur.5.1 = { string = ſ}
+longs.unifraktur.6.0 = { ^{A}*()s() }
+longs.unifraktur.6.1 = { string = ſ }
Modified: trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-AT.ini
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-AT.ini 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-AT.ini 2025-03-11 20:05:14 UTC (rev 74566)
@@ -9,8 +9,8 @@
[identification]
charset = utf8
-version = 1.4
-date = 2022-07-02
+version = 1.5
+date = 2025-03-08
name.local = Österreichisches Deutsch
name.english = Austrian German
name.babel = austrian german-austria german-at austriangerman naustrian
@@ -184,4 +184,16 @@
plusSign = +
superscriptingExponent = ·
-[counters]
+[transforms.posthyphenation]
+longs.unifraktur.1.0 = { g|?()s()|?[act] }
+longs.unifraktur.1.1 = {string = ſ }
+longs.unifraktur.2.0 = { [AEOUYaeioyäöüı]|?()s()|?[acteiouyäöüpſs] }
+longs.unifraktur.2.1 = { string = ſ }
+longs.unifraktur.3.0 = { [bdfhklrſtu]|?()s()|?[acteiouyäöüp] }
+longs.unifraktur.3.1 = {string = ſ}
+longs.unifraktur.4.0 = { [cjmnpqvw]|?()s()|?[acteiouyäöüpkr] }
+longs.unifraktur.4.1 = {string = ſ}
+longs.unifraktur.5.0 = { [ßsxz]|?()s()|?[acteiouyäöüpkrbdfghjlmnqvwßſxz] }
+longs.unifraktur.5.1 = { string = ſ}
+longs.unifraktur.6.0 = { ^{A}*()s() }
+longs.unifraktur.6.1 = { string = ſ }
Modified: trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-CH-1901.ini
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-CH-1901.ini 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-CH-1901.ini 2025-03-11 20:05:14 UTC (rev 74566)
@@ -9,8 +9,8 @@
[identification]
charset = utf8
-version = 1.6
-date = 2022-07-02
+version = 1.7
+date = 2025-03-08
name.local = Schweizer Hochdeutsch
name.english = Swiss High German
name.babel = german-switzerland-traditional german-ch-traditional swisshighgerman-traditional
@@ -185,4 +185,16 @@
plusSign = +
superscriptingExponent = ·
-[counters]
+[transforms.posthyphenation]
+longs.unifraktur.1.0 = { g|?()s()|?[act] }
+longs.unifraktur.1.1 = {string = ſ }
+longs.unifraktur.2.0 = { [AEOUYaeioyäöüı]|?()s()|?[acteiouyäöüpſs] }
+longs.unifraktur.2.1 = { string = ſ }
+longs.unifraktur.3.0 = { [bdfhklrſtu]|?()s()|?[acteiouyäöüp] }
+longs.unifraktur.3.1 = {string = ſ}
+longs.unifraktur.4.0 = { [cjmnpqvw]|?()s()|?[acteiouyäöüpkr] }
+longs.unifraktur.4.1 = {string = ſ}
+longs.unifraktur.5.0 = { [ßsxz]|?()s()|?[acteiouyäöüpkrbdfghjlmnqvwßſxz] }
+longs.unifraktur.5.1 = { string = ſ}
+longs.unifraktur.6.0 = { ^{A}*()s() }
+longs.unifraktur.6.1 = { string = ſ }
Modified: trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-CH-1996.ini
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-CH-1996.ini 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-CH-1996.ini 2025-03-11 20:05:14 UTC (rev 74566)
@@ -9,8 +9,8 @@
[identification]
charset = utf8
-version = 1.6
-date = 2022-07-02
+version = 1.7
+date = 2025-03-08
name.local = Schweizer Hochdeutsch
name.english = Swiss High German
name.babel = german-switzerland german-ch nswissgerman swisshighgerman
@@ -187,4 +187,16 @@
plusSign = +
superscriptingExponent = ·
-[counters]
+[transforms.posthyphenation]
+longs.unifraktur.1.0 = { g|?()s()|?[act] }
+longs.unifraktur.1.1 = {string = ſ }
+longs.unifraktur.2.0 = { [AEOUYaeioyäöüı]|?()s()|?[acteiouyäöüpſs] }
+longs.unifraktur.2.1 = { string = ſ }
+longs.unifraktur.3.0 = { [bdfhklrſtu]|?()s()|?[acteiouyäöüp] }
+longs.unifraktur.3.1 = {string = ſ}
+longs.unifraktur.4.0 = { [cjmnpqvw]|?()s()|?[acteiouyäöüpkr] }
+longs.unifraktur.4.1 = {string = ſ}
+longs.unifraktur.5.0 = { [ßsxz]|?()s()|?[acteiouyäöüpkrbdfghjlmnqvwßſxz] }
+longs.unifraktur.5.1 = { string = ſ}
+longs.unifraktur.6.0 = { ^{A}*()s() }
+longs.unifraktur.6.1 = { string = ſ }
Modified: trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-CH.ini
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-CH.ini 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de-CH.ini 2025-03-11 20:05:14 UTC (rev 74566)
@@ -9,8 +9,8 @@
[identification]
charset = utf8
-version = 1.7
-date = 2022-07-02
+version = 1.8
+date = 2025-03-08
name.local = Schweizer Hochdeutsch
name.english = Swiss High German
name.babel = german-switzerland german-ch swisshighgerman nswissgerman
@@ -184,4 +184,16 @@
plusSign = +
superscriptingExponent = ·
-[counters]
+[transforms.posthyphenation]
+longs.unifraktur.1.0 = { g|?()s()|?[act] }
+longs.unifraktur.1.1 = {string = ſ }
+longs.unifraktur.2.0 = { [AEOUYaeioyäöüı]|?()s()|?[acteiouyäöüpſs] }
+longs.unifraktur.2.1 = { string = ſ }
+longs.unifraktur.3.0 = { [bdfhklrſtu]|?()s()|?[acteiouyäöüp] }
+longs.unifraktur.3.1 = {string = ſ}
+longs.unifraktur.4.0 = { [cjmnpqvw]|?()s()|?[acteiouyäöüpkr] }
+longs.unifraktur.4.1 = {string = ſ}
+longs.unifraktur.5.0 = { [ßsxz]|?()s()|?[acteiouyäöüpkrbdfghjlmnqvwßſxz] }
+longs.unifraktur.5.1 = { string = ſ}
+longs.unifraktur.6.0 = { ^{A}*()s() }
+longs.unifraktur.6.1 = { string = ſ }
Modified: trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de.ini
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de.ini 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/locale/de/babel-de.ini 2025-03-11 20:05:14 UTC (rev 74566)
@@ -9,8 +9,8 @@
[identification]
charset = utf8
-version = 1.4
-date = 2022-07-02
+version = 1.5
+date = 2025-03-08
name.local = Deutsch
name.english = German
name.babel = ngerman german
@@ -180,4 +180,17 @@
plusSign = +
superscriptingExponent = ·
-[counters]
+[transforms.posthyphenation]
+longs.unifraktur.1.0 = { g|?()s()|?[act] }
+longs.unifraktur.1.1 = {string = ſ }
+longs.unifraktur.2.0 = { [AEOUYaeioyäöüı]|?()s()|?[acteiouyäöüpſs] }
+longs.unifraktur.2.1 = { string = ſ }
+longs.unifraktur.3.0 = { [bdfhklrſtu]|?()s()|?[acteiouyäöüp] }
+longs.unifraktur.3.1 = {string = ſ}
+longs.unifraktur.4.0 = { [cjmnpqvw]|?()s()|?[acteiouyäöüpkr] }
+longs.unifraktur.4.1 = {string = ſ}
+longs.unifraktur.5.0 = { [ßsxz]|?()s()|?[acteiouyäöüpkrbdfghjlmnqvwßſxz] }
+longs.unifraktur.5.1 = { string = ſ}
+longs.unifraktur.6.0 = { ^{A}*()s() }
+longs.unifraktur.6.1 = { string = ſ }
+
Modified: trunk/Master/texmf-dist/tex/generic/babel/locale/nl/babel-nl.ini
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/locale/nl/babel-nl.ini 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/locale/nl/babel-nl.ini 2025-03-11 20:05:14 UTC (rev 74566)
@@ -9,8 +9,8 @@
[identification]
charset = utf8
-version = 1.4
-date = 2022-09-24
+version = 1.5
+date = 2025-03-05
name.local = Nederlands
name.english = Dutch
name.babel = dutch
@@ -180,4 +180,9 @@
plusSign = +
superscriptingExponent = ×
-[counters]
+[transforms.posthyphenation]
+diaeresis.hyphen.1.0 = { [aeiou]|([äëïöü]) }
+diaeresis.hyphen.1.1 = {}
+diaeresis.hyphen.1.2 = { remove }
+diaeresis.hyphen.1.3 = { no = {1}, pre = - , post = {1|äëïöü|aeiou} }
+
Modified: trunk/Master/texmf-dist/tex/generic/babel/locale/sk/babel-sk.ini
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/locale/sk/babel-sk.ini 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/locale/sk/babel-sk.ini 2025-03-11 20:05:14 UTC (rev 74566)
@@ -9,8 +9,8 @@
[identification]
charset = utf8
-version = 1.4
-date = 2022-10-12
+version = 1.5
+date = 2025-03-04
name.local = slovenčina
name.english = Slovak
name.babel = slovak
@@ -183,7 +183,7 @@
[counters]
[transforms.prehyphenation]
-oneletter.nobreak.1.0 = { |[AIiVvOoUuSsZzKk]()|() }
+oneletter.nobreak.1.0 = { |[AaIiVvOoUuSsZzKk]()|() }
oneletter.nobreak.1.1 = { insert, penalty=10000 }
oneletter.nobreak.1.2 = {}
Modified: trunk/Master/texmf-dist/tex/generic/babel/luababel.def
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/luababel.def 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/luababel.def 2025-03-11 20:05:14 UTC (rev 74566)
@@ -569,8 +569,7 @@
end
end,
'Babel.hyphenate')
- }
-}
+ }}
\endgroup
\def\bbl at provide@intraspace{%
\bbl at ifunset{bbl at intsp@\languagename}{}%
@@ -753,7 +752,9 @@
end
end
- % Tatwil
+ % Tatwil. First create a list of nodes marked with kashida. The
+ % rest of nodes can be ignored. The list of used weigths is build
+ % when transforms with the key kashida= are declared.
if Babel.kashida_wts then
local k_wt = node.get_attribute(n, KASHIDA)
if k_wt > 0 then % todo. parameter for multi inserts
@@ -788,6 +789,11 @@
end
% == Tatwil ==
+ % Traverse the kashida node list so many times as required, until
+ % the line if filled. The first pass adds a tatweel after each
+ % node with kashida in the line, the second pass adds another one,
+ % and so on. In each pass, add first the kashida with the highest
+ % weight, then with lower weight and so on.
if #k_list == 0 then goto next_line end
width = node.dimensions(line.head) % The 'natural' width
@@ -902,11 +908,12 @@
\bbl at exp{%
\\\newcommand\<#1default>{}% Just define it
\\\bbl at add@list\\\bbl at font@fams{#1}%
+ \\\NewHook{#1family}%
\\\DeclareRobustCommand\<#1family>{%
\\\not at math@alphabet\<#1family>\relax
% \\\prepare at family@series at update{#1}\<#1default>% TODO. Fails
\\\fontfamily\<#1default>%
- \<ifx>\\\UseHooks\\\@undefined\<else>\\\UseHook{#1family}\<fi>%
+ \\\UseHook{#1family}%
\\\selectfont}%
\\\DeclareTextFontCommand{\<text#1>}{\<#1family>}}}
\def\bbl at nostdfont#1{%
@@ -1596,7 +1603,7 @@
\let\@eqnnum\bbl at eqnum
\fi
\fi}
- % Hack. YA luatex bug?:
+ % Hack for wrong vertical spacing with \[ \]. YA luatex bug?:
\expandafter\bbl at sreplace\csname] \endcsname{$$}{\eqno\kern.001pt$$}%
\else % amstex
\bbl at exp{% Hack to hide maybe undefined conditionals:
@@ -1741,7 +1748,7 @@
% TODO - catch non-valid values
\fi
% == mapfont ==
- % For bidi texts, to switch the font based on direction
+ % For bidi texts, to switch the font based on direction. Old.
\ifx\bbl at KVP@mapfont\@nnil\else
\bbl at ifsamestring{\bbl at KVP@mapfont}{direction}{}%
{\bbl at error{unknown-mapfont}{}{}{}}%
Modified: trunk/Master/texmf-dist/tex/generic/babel/nil.ldf
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/nil.ldf 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/nil.ldf 2025-03-11 20:05:14 UTC (rev 74566)
@@ -32,7 +32,7 @@
%% and covered by LPPL is defined by the unpacking scripts (with
%% extension |.ins|) which are part of the distribution.
%%
-\ProvidesLanguage{nil}[2025/02/14 v25.4 Nil language]
+\ProvidesLanguage{nil}[2025/03/10 v25.5 Nil language]
\LdfInit{nil}{datenil}
\ifx\l at nil\@undefined
\newlanguage\l at nil
Added: trunk/Master/texmf-dist/tex/generic/babel/tests-babel-bidi-basic.lua
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/tests-babel-bidi-basic.lua (rev 0)
+++ trunk/Master/texmf-dist/tex/generic/babel/tests-babel-bidi-basic.lua 2025-03-11 20:05:14 UTC (rev 74566)
@@ -0,0 +1,519 @@
+--
+-- This is file `babel-bidi-basic.lua',
+-- generated with the docstrip utility.
+--
+-- The original source files were:
+--
+-- babel.dtx (with options: `basic')
+--
+--
+-- Copyright (C) 2012-2025 Javier Bezos and Johannes L. Braams.
+-- Copyright (C) 1989-2012 Johannes L. Braams and
+-- any individual authors listed elsewhere in this file.
+-- All rights reserved.
+--
+--
+-- This file is part of the Babel system.
+-- --------------------------------------
+--
+-- It may be distributed and/or modified under the
+-- conditions of the LaTeX Project Public License, either version 1.3
+-- of this license or (at your option) any later version.
+-- The latest version of this license is in
+-- http://www.latex-project.org/lppl.txt
+-- and version 1.3 or later is part of all distributions of LaTeX
+-- version 2003/12/01 or later.
+--
+-- This work has the LPPL maintenance status "maintained".
+--
+-- The Current Maintainer of this work is Javier Bezos.
+--
+-- The list of derived (unpacked) files belonging to the distribution
+-- and covered by LPPL is defined by the unpacking scripts (with
+-- extension |.ins|) which are part of the distribution.
+--
+-- e.g., Babel.fontmap[1][<prefontid>]=<dirfontid>
+
+Babel.fontmap = Babel.fontmap or {}
+Babel.fontmap[0] = {} -- l
+Babel.fontmap[1] = {} -- r
+Babel.fontmap[2] = {} -- al/an
+
+-- To cancel mirroring. Also OML, OMS, U?
+Babel.symbol_fonts = Babel.symbol_fonts or {}
+Babel.symbol_fonts[font.id('tenln')] = true
+Babel.symbol_fonts[font.id('tenlnw')] = true
+Babel.symbol_fonts[font.id('tencirc')] = true
+Babel.symbol_fonts[font.id('tencircw')] = true
+
+Babel.bidi_enabled = true
+Babel.mirroring_enabled = true
+
+require('babel-data-bidi.lua')
+
+local characters = Babel.characters
+local ranges = Babel.ranges
+
+local DIR = node.id('dir')
+local GLYPH = node.id('glyph')
+
+local function insert_implicit(head, state, outer)
+ local new_state = state
+ if state.sim and state.eim and state.sim ~= state.eim then
+ dir = ((outer == 'r') and 'TLT' or 'TRT') -- i.e., reverse
+ local d = node.new(DIR)
+ d.dir = '+' .. dir
+ node.insert_before(head, state.sim, d)
+ local d = node.new(DIR)
+ d.dir = '-' .. dir
+ node.insert_after(head, state.eim, d)
+ end
+ new_state.sim, new_state.eim = nil, nil
+ return head, new_state
+end
+
+local function insert_numeric(head, state)
+ local new
+ local new_state = state
+ if state.san and state.ean and state.san ~= state.ean then
+ local d = node.new(DIR)
+ d.dir = '+TLT'
+ _, new = node.insert_before(head, state.san, d)
+ if state.san == state.sim then state.sim = new end
+ local d = node.new(DIR)
+ d.dir = '-TLT'
+ _, new = node.insert_after(head, state.ean, d)
+ if state.ean == state.eim then state.eim = new end
+ end
+ new_state.san, new_state.ean = nil, nil
+ return head, new_state
+end
+
+local function glyph_not_symbol_font(node)
+ if node.id == GLYPH then
+ return not Babel.symbol_fonts[node.font]
+ else
+ return false
+ end
+end
+
+-- TODO - \hbox with an explicit dir can lead to wrong results
+-- <R \hbox dir TLT{<R>}> and <L \hbox dir TRT{<L>}>. A small attempt
+-- was made to improve the situation, but the problem is the 3-dir
+-- model in babel/Unicode and the 2-dir model in LuaTeX don't fit
+-- well.
+
+function Babel.bidi(head, ispar, hdir)
+ local d -- d is used mainly for computations in a loop
+ local prev_d = ''
+ local new_d = false
+
+ local nodes = {}
+ local outer_first = nil
+ local inmath = false
+
+ local glue_d = nil
+ local glue_i = nil
+
+ local has_en = false
+ local first_et = nil
+
+ local has_hyperlink = false
+
+ local ATDIR = Babel.attr_dir
+ local attr_d
+
+ local save_outer
+ local temp = node.get_attribute(head, ATDIR)
+ if temp then
+ temp = temp & 0x3
+ save_outer = (temp == 0 and 'l') or
+ (temp == 1 and 'r') or
+ (temp == 2 and 'al')
+ elseif ispar then -- Or error? Shouldn't happen
+ save_outer = ('TRT' == tex.pardir) and 'r' or 'l'
+ else -- Or error? Shouldn't happen
+ save_outer = ('TRT' == hdir) and 'r' or 'l'
+ end
+ -- when the callback is called, we are just _after_ the box,
+ -- and the textdir is that of the surrounding text
+ -- if not ispar and hdir ~= tex.textdir then
+ -- save_outer = ('TRT' == hdir) and 'r' or 'l'
+ -- end
+ local outer = save_outer
+ local last = outer
+ -- 'al' is only taken into account in the first, current loop
+ if save_outer == 'al' then save_outer = 'r' end
+
+ local fontmap = Babel.fontmap
+
+ for item in node.traverse(head) do
+
+ -- In what follows, #node is the last (previous) node, because the
+ -- current one is not added until we start processing the neutrals.
+
+ -- three cases: glyph, dir, otherwise
+ if glyph_not_symbol_font(item)
+ or (item.id == 7 and item.subtype == 2) then
+
+ if node.get_attribute(item, ATDIR) == 128 then goto nextnode end
+
+ local d_font = nil
+ local item_r
+ if item.id == 7 and item.subtype == 2 then
+ item_r = item.replace -- automatic discs have just 1 glyph
+ else
+ item_r = item
+ end
+
+ local chardata = characters[item_r.char]
+ d = chardata and chardata.d or nil
+ if not d or d == 'nsm' then
+ for nn, et in ipairs(ranges) do
+ if item_r.char < et[1] then
+ break
+ elseif item_r.char <= et[2] then
+ if not d then d = et[3]
+ elseif d == 'nsm' then d_font = et[3]
+ end
+ break
+ end
+ end
+ end
+ d = d or 'l'
+
+ -- A short 'pause' in bidi for mapfont
+ d_font = d_font or d
+ d_font = (d_font == 'l' and 0) or
+ (d_font == 'nsm' and 0) or
+ (d_font == 'r' and 1) or
+ (d_font == 'al' and 2) or
+ (d_font == 'an' and 2) or nil
+ if d_font and fontmap and fontmap[d_font][item_r.font] then
+ item_r.font = fontmap[d_font][item_r.font]
+ end
+
+ if new_d then
+ table.insert(nodes, {nil, (outer == 'l') and 'l' or 'r', nil})
+ if inmath then
+ attr_d = 0
+ else
+ attr_d = node.get_attribute(item, ATDIR)
+ attr_d = attr_d & 0x3
+ end
+ if attr_d == 1 then
+ outer_first = 'r'
+ last = 'r'
+ elseif attr_d == 2 then
+ outer_first = 'r'
+ last = 'al'
+ else
+ outer_first = 'l'
+ last = 'l'
+ end
+ outer = last
+ has_en = false
+ first_et = nil
+ new_d = false
+ end
+
+ if glue_d then
+ if (d == 'l' and 'l' or 'r') ~= glue_d then
+ table.insert(nodes, {glue_i, 'on', nil})
+ end
+ glue_d = nil
+ glue_i = nil
+ end
+
+ elseif item.id == DIR then
+ d = nil
+
+ if head ~= item then new_d = true end
+
+ elseif item.id == node.id'glue' and item.subtype == 13 then
+ glue_d = d
+ glue_i = item
+ d = nil
+
+ elseif item.id == node.id'math' then
+ inmath = (item.subtype == 0)
+
+ elseif item.id == 8 and item.subtype == 19 then
+ has_hyperlink = true
+
+ else
+ d = nil
+ end
+
+ -- AL <= EN/ET/ES -- W2 + W3 + W6
+ if last == 'al' and d == 'en' then
+ d = 'an' -- W3
+ elseif last == 'al' and (d == 'et' or d == 'es') then
+ d = 'on' -- W6
+ end
+
+ -- EN + CS/ES + EN -- W4
+ if d == 'en' and #nodes >= 2 then
+ if (nodes[#nodes][2] == 'es' or nodes[#nodes][2] == 'cs')
+ and nodes[#nodes-1][2] == 'en' then
+ nodes[#nodes][2] = 'en'
+ end
+ end
+
+ -- AN + CS + AN -- W4 too, because uax9 mixes both cases
+ if d == 'an' and #nodes >= 2 then
+ if (nodes[#nodes][2] == 'cs')
+ and nodes[#nodes-1][2] == 'an' then
+ nodes[#nodes][2] = 'an'
+ end
+ end
+
+ -- ET/EN -- W5 + W7->l / W6->on
+ if d == 'et' then
+ first_et = first_et or (#nodes + 1)
+ elseif d == 'en' then
+ has_en = true
+ first_et = first_et or (#nodes + 1)
+ elseif first_et then -- d may be nil here !
+ if has_en then
+ if last == 'l' then
+ temp = 'l' -- W7
+ else
+ temp = 'en' -- W5
+ end
+ else
+ temp = 'on' -- W6
+ end
+ for e = first_et, #nodes do
+ if glyph_not_symbol_font(nodes[e][1]) then nodes[e][2] = temp end
+ end
+ first_et = nil
+ has_en = false
+ end
+
+ -- Force mathdir in math if ON (currently works as expected only
+ -- with 'l')
+
+ if inmath and d == 'on' then
+ d = ('TRT' == tex.mathdir) and 'r' or 'l'
+ end
+
+ if d then
+ if d == 'al' then
+ d = 'r'
+ last = 'al'
+ elseif d == 'l' or d == 'r' then
+ last = d
+ end
+ prev_d = d
+ table.insert(nodes, {item, d, outer_first})
+ end
+
+ -- node.set_attribute(item, ATDIR, 128)
+ outer_first = nil
+
+ ::nextnode::
+
+ end -- for each node
+
+ -- TODO -- repeated here in case EN/ET is the last node. Find a
+ -- better way of doing things:
+ if first_et then -- dir may be nil here !
+ if has_en then
+ if last == 'l' then
+ temp = 'l' -- W7
+ else
+ temp = 'en' -- W5
+ end
+ else
+ temp = 'on' -- W6
+ end
+ for e = first_et, #nodes do
+ if glyph_not_symbol_font(nodes[e][1]) then nodes[e][2] = temp end
+ end
+ end
+
+ -- dummy node, to close things
+ table.insert(nodes, {nil, (outer == 'l') and 'l' or 'r', nil})
+
+ --------------- NEUTRAL -----------------
+
+ outer = save_outer
+ last = outer
+
+ local first_on = nil
+
+ for q = 1, #nodes do
+ local item
+
+ local outer_first = nodes[q][3]
+ outer = outer_first or outer
+ last = outer_first or last
+
+ texio.write_nl('****')
+ texio.write_nl(outer)
+ if nodes[q][1] then
+ texio.write_nl('char = ' .. nodes[q][1].char)
+ texio.write_nl('dirtext = ' .. (node.get_attribute(nodes[q][1], ATDIR)
+ & 0x3))
+ texio.write(', dir = ' .. nodes[q][2])
+ texio.write(', outer = ' .. (nodes[q][3] or '?'))
+ else
+ texio.write_nl('Ø')
+ end
+ -- outer = 'l'
+
+
+ local d = nodes[q][2]
+ if d == 'an' or d == 'en' then d = 'r' end
+ if d == 'cs' or d == 'et' or d == 'es' then d = 'on' end --- W6
+
+ if d == 'on' then
+ first_on = first_on or q
+ elseif first_on then
+ if last == d then
+ temp = d
+ else
+ temp = outer
+ end
+ for r = first_on, q - 1 do
+ nodes[r][2] = temp
+ item = nodes[r][1] -- MIRRORING
+ if Babel.mirroring_enabled and glyph_not_symbol_font(item)
+ and temp == 'r' and characters[item.char] then
+ texio.write_nl('==== ' .. item.char)
+ texio.write_nl('dir = ' .. node.get_attribute(item, ATDIR))
+ texio.write_nl('dirtext = ' .. (node.get_attribute(item, ATDIR)
+ & 0x3))
+ local font_mode = ''
+ if item.font > 0 and font.fonts[item.font].properties then
+ font_mode = font.fonts[item.font].properties.mode
+ end
+ if font_mode ~= 'harf' and font_mode ~= 'plug' and
+ node.get_attribute(item, ATDIR) & 0x3 ~= 0 then
+ texio.write_nl('change ' .. item.char .. ' -> '
+ .. (characters[item.char].m
+ or item.char))
+ item.char = characters[item.char].m or item.char
+ end
+ end
+ end
+ first_on = nil
+ end
+
+ if d == 'r' or d == 'l' then last = d end
+ end
+
+ -------------- IMPLICIT, REORDER ----------------
+
+ outer = save_outer
+ last = outer
+
+ local state = {}
+ state.has_r = false
+
+ for q = 1, #nodes do
+
+ local item = nodes[q][1]
+
+ outer = nodes[q][3] or outer
+
+ local d = nodes[q][2]
+
+ if d == 'nsm' then d = last end -- W1
+ if d == 'en' then d = 'an' end
+ local isdir = (d == 'r' or d == 'l')
+
+ if outer == 'l' and d == 'an' then
+ state.san = state.san or item
+ state.ean = item
+ elseif state.san then
+ head, state = insert_numeric(head, state)
+ end
+
+ if outer == 'l' then
+ if d == 'an' or d == 'r' then -- im -> implicit
+ if d == 'r' then state.has_r = true end
+ state.sim = state.sim or item
+ state.eim = item
+ elseif d == 'l' and state.sim and state.has_r then
+ head, state = insert_implicit(head, state, outer)
+ elseif d == 'l' then
+ state.sim, state.eim, state.has_r = nil, nil, false
+ end
+ else
+ if d == 'an' or d == 'l' then
+ if nodes[q][3] then -- nil except after an explicit dir
+ state.sim = item -- so we move sim 'inside' the group
+ else
+ state.sim = state.sim or item
+ end
+ state.eim = item
+ elseif d == 'r' and state.sim then
+ head, state = insert_implicit(head, state, outer)
+ elseif d == 'r' then
+ state.sim, state.eim = nil, nil
+ end
+ end
+
+ if isdir then
+ last = d -- Don't search back - best save now
+ elseif d == 'on' and state.san then
+ state.san = state.san or item
+ state.ean = item
+ end
+
+ end
+
+ head = node.prev(head) or head
+ --- FIXES ---
+ if has_hyperlink then
+ local flag, linking = 0, 0
+ for item in node.traverse(head) do
+ if item.id == DIR then
+ if item.dir == '+TRT' or item.dir == '+TLT' then
+ flag = flag + 1
+ elseif item.dir == '-TRT' or item.dir == '-TLT' then
+ flag = flag - 1
+ end
+ elseif item.id == 8 and item.subtype == 19 then
+ linking = flag
+ elseif item.id == 8 and item.subtype == 20 then
+ if linking > 0 then
+ if item.prev.id == DIR and
+ (item.prev.dir == '-TRT' or item.prev.dir == '-TLT') then
+ d = node.new(DIR)
+ d.dir = item.prev.dir
+ node.remove(head, item.prev)
+ node.insert_after(head, item, d)
+ end
+ end
+ linking = 0
+ end
+ end
+ end
+
+ for item in node.traverse_id(10, head) do
+ local p = item
+ local flag = false
+ while p.prev and p.prev.id == 14 do
+ flag = true
+ p = p.prev
+ end
+ if flag then
+ node.insert_before(head, p, node.copy(item))
+ node.remove(head,item)
+ end
+ end
+
+ return head
+end
+-- Make sure anything is marked as 'bidi done' (including nodes inserted
+-- after the babel algorithm). 128 = 1000 0000.
+function Babel.unset_atdir(head)
+ local ATDIR = Babel.attr_dir
+ for item in node.traverse(head) do
+ node.set_attribute(item, ATDIR, 128)
+ end
+ return head
+end
Property changes on: trunk/Master/texmf-dist/tex/generic/babel/tests-babel-bidi-basic.lua
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/tex/generic/babel/txtbabel.def
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/txtbabel.def 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/txtbabel.def 2025-03-11 20:05:14 UTC (rev 74566)
@@ -34,8 +34,6 @@
%%
\providecommand\bbl at provide@intraspace{}
\bbl at trace{Redefinitions for bidi layout}
-\def\bbl at sspre@caption{% TODO: Unused!
- \bbl at exp{\everyhbox{\\\bbl at textdir\bbl at cs{wdir@\bbl at main@language}}}}
\ifx\bbl at opt@layout\@nnil\else % if layout=..
\def\bbl at startskip{\ifcase\bbl at thepardir\leftskip\else\rightskip\fi}
\def\bbl at endskip{\ifcase\bbl at thepardir\rightskip\else\leftskip\fi}
Modified: trunk/Master/texmf-dist/tex/generic/babel/xebabel.def
===================================================================
--- trunk/Master/texmf-dist/tex/generic/babel/xebabel.def 2025-03-11 20:03:36 UTC (rev 74565)
+++ trunk/Master/texmf-dist/tex/generic/babel/xebabel.def 2025-03-11 20:05:14 UTC (rev 74566)
@@ -126,11 +126,12 @@
\bbl at exp{%
\\\newcommand\<#1default>{}% Just define it
\\\bbl at add@list\\\bbl at font@fams{#1}%
+ \\\NewHook{#1family}%
\\\DeclareRobustCommand\<#1family>{%
\\\not at math@alphabet\<#1family>\relax
% \\\prepare at family@series at update{#1}\<#1default>% TODO. Fails
\\\fontfamily\<#1default>%
- \<ifx>\\\UseHooks\\\@undefined\<else>\\\UseHook{#1family}\<fi>%
+ \\\UseHook{#1family}%
\\\selectfont}%
\\\DeclareTextFontCommand{\<text#1>}{\<#1family>}}}
\def\bbl at nostdfont#1{%
@@ -365,8 +366,6 @@
{\bbl at csarg\let{ic@#1@\languagename}\@gobble}}
\providecommand\bbl at provide@intraspace{}
\bbl at trace{Redefinitions for bidi layout}
-\def\bbl at sspre@caption{% TODO: Unused!
- \bbl at exp{\everyhbox{\\\bbl at textdir\bbl at cs{wdir@\bbl at main@language}}}}
\ifx\bbl at opt@layout\@nnil\else % if layout=..
\def\bbl at startskip{\ifcase\bbl at thepardir\leftskip\else\rightskip\fi}
\def\bbl at endskip{\ifcase\bbl at thepardir\rightskip\else\leftskip\fi}
More information about the tex-live-commits
mailing list.