texlive[74879] Master/texmf-dist: l3kernel (8apr25)
commits+karl at tug.org
commits+karl at tug.org
Tue Apr 8 22:12:12 CEST 2025
Revision: 74879
https://tug.org/svn/texlive?view=revision&revision=74879
Author: karl
Date: 2025-04-08 22:12:11 +0200 (Tue, 08 Apr 2025)
Log Message:
-----------
l3kernel (8apr25)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md
trunk/Master/texmf-dist/doc/latex/l3kernel/README.md
trunk/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.tex
trunk/Master/texmf-dist/doc/latex/l3kernel/l3doc.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3news.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3news01.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3news02.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3news03.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3news04.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3news05.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3news06.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3news07.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3news08.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3news09.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3news10.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3news11.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3news12.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.csv
trunk/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex
trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex
trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex
trunk/Master/texmf-dist/doc/latex/l3kernel/source3.pdf
trunk/Master/texmf-dist/doc/latex/l3kernel/source3.tex
trunk/Master/texmf-dist/doc/latex/l3kernel/source3body.tex
trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3.ins
trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3bitset.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3color.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-functions.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-symbolic.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-types.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3text-map.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-build.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx
trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx
trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex
trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex
trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx
trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty
trunk/Master/texmf-dist/tex/latex/l3kernel/l3debug.def
trunk/Master/texmf-dist/tex/latex/l3kernel/l3doc.cls
Added Paths:
-----------
trunk/Master/texmf-dist/source/latex/l3kernel/l3graphics.dtx
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md 2025-04-08 20:12:11 UTC (rev 74879)
@@ -7,6 +7,33 @@
## [Unreleased]
+## [2025-03-26]
+
+### Added
+- Module `l3graphics`, moved from `l3experimental` to stable status
+
+### Fixed
+- Correct scope for `\prg_gset_conditional:Nnn`
+
+## [2025-03-10]
+
+### Added
+- `\text_words_map_function:nN`
+- Variants `\tl_head:e` and `\tl_tail:e`
+- `l3tl` functions (and variants) which trim spaces from only one side
+ (issue \#1673):
+ - `\tl_trim_left_spaces:n`, `\tl_trim_left_spaces_apply:nN`,
+ `\tl_(g)trim_left_spaces:N`
+ - `\tl_trim_right_spaces:n`, `\tl_trim_right_spaces_apply:nN`,
+ `\tl_(g)trim_right_spaces:N`
+
+### Changed
+- `\fp_set_function:nnn` and `\fp_set_variable:nn` now raise errors on
+ undefined (fp) identifiers (issue \#1700)
+
+### Fixed
+- Avoid low-level error if keys are given without a module (issue \#1254)
+
## [2025-01-18]
### Changed
@@ -330,10 +357,10 @@
- Switch generally from `x`- to `e`-type variants
- Convert `\file_if_exist:n(TF)` to expandable status,
adding predicate version
-- Standardise variants for `\prop_(g)pop:NnN(TF)`
-- Standardise variants for `\prop_(g)put:Nnn`
-- Standardise variants for `\prop_(g)put_if_new:Nnn`
-- Standardise variants for `\prop_(g)remove:Nn`
+- Standardize variants for `\prop_(g)pop:NnN(TF)`
+- Standardize variants for `\prop_(g)put:Nnn`
+- Standardize variants for `\prop_(g)put_if_new:Nnn`
+- Standardize variants for `\prop_(g)remove:Nn`
### Deprecated
- `\iow_shipout_x:Nn` in favor of `e`-type naming
@@ -1846,7 +1873,9 @@
- Step functions have been added for dim variables,
e.g. `\dim_step_inline:nnnn`
-[Unreleased]: https://github.com/latex3/latex3/compare/2025-01-18...HEAD
+[Unreleased]: https://github.com/latex3/latex3/compare/2025-03-26...HEAD
+[2025-03-26]: https://github.com/latex3/latex3/compare/2025-03-10...2025-03-26
+[2025-03-10]: https://github.com/latex3/latex3/compare/2025-01-18...2025-03-10
[2025-01-18]: https://github.com/latex3/latex3/compare/2025-01-14...2025-01-18
[2025-01-14]: https://github.com/latex3/latex3/compare/2024-12-25...2025-01-14
[2024-12-25]: https://github.com/latex3/latex3/compare/2024-12-09...2024-12-25
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/README.md 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/README.md 2025-04-08 20:12:11 UTC (rev 74879)
@@ -1,7 +1,7 @@
LaTeX3 Programming Conventions
==============================
-Release 2025-01-18
+Release 2025-03-26
Overview
--------
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.tex 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.tex 2025-04-08 20:12:11 UTC (rev 74879)
@@ -58,7 +58,7 @@
{latex-team at latex-project.org}%
}%
}
-\date{Released 2025-01-18}
+\date{Released 2025-03-26}
\pagenumbering{roman}
\maketitle
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3doc.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news01.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news02.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news03.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news04.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news05.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news06.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news07.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news08.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news09.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news10.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news11.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news12.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.csv
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.csv 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.csv 2025-04-08 20:12:11 UTC (rev 74879)
@@ -30,6 +30,7 @@
cascade,cascade,F. Pantigny,,,,2020-07-21,2020-07-21,
catcode,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
cctab,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-28,2012-09-28,
+cdhh,codehigh,Jianrui Lyu,https://github.com/lvjr/codehigh,https://github.com/lvjr/codehigh.git,https://github.com/lvjr/codehigh/issues,2025-02-16,2025-02-16,
cellprops,cellprops,Julien Rivaud,,,,2018-06-13,2018-06-13,
chaos,"chaos,schleuderpackung",Marei Peischl,https://ds.ccc.de/,,,2021-05-28,2021-05-28,
char,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
@@ -249,6 +250,7 @@
sort,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2017-02-13,
space,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
spath,spath3,Andrew Stacey,https://github.com/loopspace/spath3,https://github.com/loopspace/spath3.git,https://github.com/loopspace/spath3/issues,2024-07-18,2024-07-18,
+speg,pegmatch,Jianrui Lyu,https://github.com/lvjr/pegmatch,https://github.com/lvjr/pegmatch.git,https://github.com/lvjr/pegmatch/issues,2025-02-16,2025-02-16,
starray,starray,Alceu Frigeri,https://github.com/alceu-frigeri/starray,https://github.com/alceu-frigeri/starray,https://github.com/alceu-frigeri/starray/issues,2023-05-15,2023-05-15,
statistics,statistics,Julien Rivaud,https://gitlab.com/frnchfrgg-latex/statistics,https://gitlab.com/frnchfrgg-latex/statistics.git,https://gitlab.com/frnchfrgg-latex/statistics/issues,2018-06-25,2018-06-25,
stm,lt3-stm,CV Radhakrishnan,http://www.cvr.cc/,,,2014-02-26,2014-02-26,
@@ -275,6 +277,7 @@
tmpa,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
tmpb,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12,
token,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+tpeg,pegmatch,Jianrui Lyu,https://github.com/lvjr/pegmatch,https://github.com/lvjr/pegmatch.git,https://github.com/lvjr/pegmatch/issues,2025-02-16,2025-02-16,
true,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2021-04-23,2021-04-23,
twmk,menukeys,Tobias Weh,https://github.com/tweh/menukeys,git@github.com:tweh/menukeys.git,https://github.com/tweh/menukeys/issues,2020-10-31,2020-10-31,“classic” L2 package using only some expl3 code
ufcombo,combofont,Ulrike Fischer,https://github.com/u-fischer/combofont,https://github.com/u-fischer/combofont,https://github.com/u-fischer/combofont/issues,2020-04-24,2020-04-24,
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex 2025-04-08 20:12:11 UTC (rev 74879)
@@ -32,7 +32,7 @@
{latex-team at latex-project.org}%
}%
}
-\date{Released 2025-01-18}
+\date{Released 2025-03-26}
\begin{document}
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex 2025-04-08 20:12:11 UTC (rev 74879)
@@ -32,7 +32,7 @@
{latex-team at latex-project.org}%
}%
}
-\date{Released 2025-01-18}
+\date{Released 2025-03-26}
\newcommand{\TF}{\textit{(TF)}}
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex 2025-04-08 20:12:11 UTC (rev 74879)
@@ -32,7 +32,7 @@
{latex-team at latex-project.org}%
}%
}
-\date{Released 2025-01-18}
+\date{Released 2025-03-26}
\newcommand{\TF}{\textit{(TF)}}
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/source3.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/source3.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/source3.tex 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/source3.tex 2025-04-08 20:12:11 UTC (rev 74879)
@@ -57,7 +57,7 @@
{latex-team at latex-project.org}%
}%
}
-\date{Released 2025-01-18}
+\date{Released 2025-03-26}
\pagenumbering{roman}
\maketitle
Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/source3body.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/source3body.tex 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/source3body.tex 2025-04-08 20:12:11 UTC (rev 74879)
@@ -637,6 +637,7 @@
\DocInput{l3box.dtx}
\DocInput{l3coffins.dtx}
\DocInput{l3color.dtx}
+\DocInput{l3graphics.dtx}
\DocInput{l3pdf.dtx}
% implementation part only
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -24,7 +24,7 @@
%
%<*driver|generic|package|2ekernel>
%</driver|generic|package|2ekernel>
-\def\ExplFileDate{2025-01-18}%
+\def\ExplFileDate{2025-03-26}%
%<*driver>
\documentclass[full]{l3doc}
\usepackage{graphicx}
@@ -51,7 +51,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -254,7 +254,7 @@
% \begin{quote}
% \meta{module} and \meta{description}
% \end{quote}
-% these both give information about the command.
+% and these two both give information about the command.
%
% A \emph{module} is a collection of closely related functions and
% variables. Typical module names include~|int| for integer parameters
@@ -543,9 +543,8 @@
% documented in \href{interface3.pdf}{interface3.pdf}%^^A
% \footnote{If a primitive offers a functionality not yet in the
% kernel, programmers and users are encouraged to write to the
-% \texttt{LaTeX-L} mailing list
-% (\url{mailto:LATEX-L at listserv.uni-heidelberg.de}) describing
-% their use-case and intended behaviour, so that a possible
+% team describing
+% their use-case and intended behavior, so that a possible
% interface can be discussed. Temporarily, while an interface is
% not provided, programmers may use the procedure described in the
% \href{l3styleguide.pdf}{l3styleguide.pdf}.}.
@@ -896,8 +895,7 @@
% \item Use long, descriptive names for functions and variables,
% and for auxiliary functions use the parent function name plus
% |aux|, |auxi|, |auxii| and so on.
-% \item If in doubt, ask the team via the LaTeX-L list: someone will
-% soon get back to you!
+% \item If in doubt, ask the team: someone will soon get back to you!
% \end{itemize}
%
% \section{Load-time options for \pkg{expl3}}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3.ins 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3.ins 2025-04-08 20:12:11 UTC (rev 74879)
@@ -105,6 +105,7 @@
\from{l3regex.dtx} {package}
\from{l3box.dtx} {package}
\from{l3color.dtx} {package}
+ \from{l3graphics.dtx} {package}
\from{l3pdf.dtx} {package,tex}
\from{l3coffins.dtx} {package}
\from{l3luatex.dtx} {package,tex}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -2014,7 +2014,7 @@
\cs_gset_protected:Npn \prg_set_conditional:Nnn
{ \@@_generate_conditional_count:NNNnn \cs_set:Npn e }
\cs_gset_protected:Npn \prg_gset_conditional:Nnn
- { \@@_generate_conditional_count:NNNnn \cs_set:Npn e }
+ { \@@_generate_conditional_count:NNNnn \cs_gset:Npn e }
\cs_gset_protected:Npn \prg_new_conditional:Nnn
{ \@@_generate_conditional_count:NNNnn \cs_new:Npn e }
\cs_gset_protected:Npn \prg_set_protected_conditional:Nnn
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3bitset.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3bitset.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3bitset.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -42,7 +42,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -2185,9 +2185,9 @@
% \begin{macro}{\@@_rand_item:nn}
% The |N|-type function is not implemented through the |n|-type
% function for efficiency: for instance comma-list variables do not
-% require space-trimming of their items. Even testing for emptyness
+% require space-trimming of their items. Even testing for emptiness
% of an |n|-type comma-list is slow, so we count items first and use
-% that both for the emptyness test and the pseudo-random integer.
+% that both for the emptiness test and the pseudo-random integer.
% Importantly, \cs{clist_item:Nn} and \cs{clist_item:nn} only evaluate
% their argument once.
% \begin{macrocode}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3color.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3color.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3color.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -2440,14 +2440,14 @@
% \begin{macro}[EXP]{\@@_model_devicen_mix:nw}
% \begin{macro}{\@@_model_devicen_init:nnn}
% \begin{macro}{\@@_model_devicen_init:nnnn}
-% \begin{macro}{\@@_model_devicen_tranform:w}
+% \begin{macro}{\@@_model_devicen_transform:w}
% \begin{macro}
% {
-% \@@_model_devicen_tranform_1:nnnnn ,
-% \@@_model_devicen_tranform_3:nnnnn ,
-% \@@_model_devicen_tranform_4:nnnnn ,
+% \@@_model_devicen_transform_1:nnnnn ,
+% \@@_model_devicen_transform_3:nnnnn ,
+% \@@_model_devicen_transform_4:nnnnn ,
% }
-% \begin{macro}{\@@_model_devicen_tranform:nnn}
+% \begin{macro}{\@@_model_devicen_transform:nnn}
% \begin{macro}[EXP]{\@@_model_devicen_colorant:n}
% \begin{macro}{\@@_model_devicen_convert:nnn}
% \begin{macro}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -69,7 +69,7 @@
%
% Standard file identification.
% \begin{macrocode}
-\ProvidesExplFile{l3debug.def}{2025-01-18}{}{L3 Debugging support}
+\ProvidesExplFile{l3debug.def}{2025-03-26}{}{L3 Debugging support}
% \end{macrocode}
%
% \begin{variable}{\s_@@_stop}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -71,7 +71,7 @@
% This isn't included in the typeset documentation because it's a bit
% ugly:
%<*class>
-\ProvidesExplClass{l3doc}{2025-01-18}{}
+\ProvidesExplClass{l3doc}{2025-03-26}{}
{L3 Experimental documentation class}
%</class>
% \fi
@@ -84,7 +84,7 @@
% require you to do updates, if the class changes.}}
%
% \author{\Team}
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
% \maketitle
% \tableofcontents
%
@@ -4716,7 +4716,7 @@
% \begin{macrocode}
\tl_const:Nn \Team
{
- The~\LaTeX~Project~team\thanks
+ The~\LaTeX{}~Project~team\thanks
{\url{https://www.latex-project.org/latex3/}}
}
% \end{macrocode}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -63,7 +63,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -4010,7 +4010,7 @@
% \begin{variable}{\c_sys_platform_str}
% Detecting the platform on \LuaTeX{} is easy: for other engines, we use
% the fact that the two common cases have special null files. It is possible
-% to probe further (see package \pkg{platform}), but that requires shell
+% to probe further (see package \pkg{ifplatform}), but that requires shell
% escape and seems unlikely to be useful. This is set up here as it requires
% file searching.
% \begin{macrocode}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -42,7 +42,7 @@
% {latex-team at latex-project.org}^^A
% }^^A
% }
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
% \maketitle
%
% \begin{documentation}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -161,16 +161,16 @@
% \toprule
% \multicolumn{1}{c}{Representation} & Meaning \\
% \midrule
-% 0 0 \cs[no-index]{s_@@_\ldots} \texttt{;} & Positive zero. \\
-% 0 2 \cs[no-index]{s_@@_\ldots} \texttt{;} & Negative zero. \\
-% 1 0 \Arg{exponent} \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \texttt{;}
+% 0 0 \cs[no-index]{s_@@_\ldots} \cs{@@_sep:} & Positive zero. \\
+% 0 2 \cs[no-index]{s_@@_\ldots} \cs{@@_sep:} & Negative zero. \\
+% 1 0 \Arg{exponent} \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \cs{@@_sep:}
% & Positive floating point. \\
-% 1 2 \Arg{exponent} \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \texttt{;}
+% 1 2 \Arg{exponent} \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \cs{@@_sep:}
% & Negative floating point. \\
-% 2 0 \cs[no-index]{s_@@_\ldots} \texttt{;} & Positive infinity. \\
-% 2 2 \cs[no-index]{s_@@_\ldots} \texttt{;} & Negative infinity. \\
-% 3 1 \cs[no-index]{s_@@_\ldots} \texttt{;} & Quiet \texttt{nan}. \\
-% 3 1 \cs[no-index]{s_@@_\ldots} \texttt{;} & Signalling \texttt{nan}. \\
+% 2 0 \cs[no-index]{s_@@_\ldots} \cs{@@_sep:} & Positive infinity. \\
+% 2 2 \cs[no-index]{s_@@_\ldots} \cs{@@_sep:} & Negative infinity. \\
+% 3 1 \cs[no-index]{s_@@_\ldots} \cs{@@_sep:} & Quiet \texttt{nan}. \\
+% 3 1 \cs[no-index]{s_@@_\ldots} \cs{@@_sep:} & Signalling \texttt{nan}. \\
% \bottomrule
% \end{tabular}
% \end{table}
@@ -731,9 +731,9 @@
% following trick splits it into two blocks of $4$ digits, padding
% with zeros on the left.
% \begin{verbatim}
-% \cs_new:Npn \pack:NNNNNw #1 #2#3#4#5 #6; { {#2#3#4#5} {#6} }
-% \exp_after:wN \pack:NNNNNw
-% \__fp_int_value:w \__fp_int_eval:w 1 0000 0000 + #1 ;
+% \cs_new:Npn \__fp_pack:NNNNNw #1 #2#3#4#5 #6 \__fp_sep: { {#2#3#4#5} {#6} }
+% \exp_after:wN \__fp_pack:NNNNNw
+% \__fp_int_value:w \__fp_int_eval:w 1 0000 0000 + #1 \__fp_sep:
% \end{verbatim}
% The idea is that adding $10^8$ to the number ensures that it has
% exactly $9$ digits, and can then easily find which digits correspond
@@ -742,7 +742,7 @@
% \TeX{}'s integers). This method is very heavily relied upon in
% \texttt{l3fp-basics}.
%
-% More specifically, the auxiliary inserts |+ #1#2#3#4#5 ; {#6}|, which
+% More specifically, the auxiliary inserts |+ #1#2#3#4#5| \cs{@@_sep:} |{#6}|, which
% allows us to compute several blocks of $4$ digits in a nested manner,
% performing carries on the fly. Say we want to compute $1\,2345 \times
% 6677\,8899$. With simplified names, we would do
@@ -749,12 +749,12 @@
% \begin{verbatim}
% \exp_after:wN \post_processing:w
% \__fp_int_value:w \__fp_int_eval:w - 5 0000
-% \exp_after:wN \pack:NNNNNw
+% \exp_after:wN \__fp_pack:NNNNNw
% \__fp_int_value:w \__fp_int_eval:w 4 9995 0000
% + 12345 * 6677
-% \exp_after:wN \pack:NNNNNw
+% \exp_after:wN \__fp_pack:NNNNNw
% \__fp_int_value:w \__fp_int_eval:w 5 0000 0000
-% + 12345 * 8899 ;
+% + 12345 * 8899 \__fp_sep:
% \end{verbatim}
% The \cs{exp_after:wN} triggers \cs{int_value:w} \cs{@@_int_eval:w}, which
% starts a first computation, whose initial value is $- 5\,0000$ (the
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -42,7 +42,7 @@
% {latex-team at latex-project.org}^^A
% }^^A
% }
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -42,7 +42,7 @@
% {latex-team at latex-project.org}^^A
% }^^A
% }
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -494,7 +494,7 @@
% + T \left(\frac{1}{7} + T \left( \frac{1}{9} + \cdots
% \right)\right)\right)\right)\right)
% \]
-% The process looks as follows
+% The process looks as follows (\cs{@@_sep:} represented by |;|)
% \begin{verbatim}
% \loop 5; A;
% \div_int 5; 1.0; \add A; \mul T; {\loop \eval 5-2;}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -42,7 +42,7 @@
% {latex-team at latex-project.org}^^A
% }^^A
% }
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-functions.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-functions.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-functions.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -42,7 +42,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -159,7 +159,7 @@
% \cs{fp_set_function:nnn} \Arg{identifier}
% \Arg{comma-list of variables} \Arg{expression}
% \end{syntax}
-% Defines the \meta{identifier} to stand for a function which expects
+% Sets the \meta{identifier} to stand for a function which expects
% some arguments defined by the \meta{comma-list of variables}, and
% evaluates to the \meta{expression}.
% \begin{macrocode}
@@ -174,7 +174,10 @@
{ \msg_error:nnn { fp } { id-invalid } {#2} }
{
\cs_if_exist:cF { @@_parse_word_#2:N }
- { \@@_function_set_parsing:Nn \cs_set_eq:NN {#2} }
+ {
+ \msg_error:nnn {fp} { id-undefined } {#2}
+ \@@_function_set_parsing:Nn \cs_set_eq:NN {#2}
+ }
\group_begin:
\int_zero:N \l_@@_function_arg_int
\exp_args:No \clist_map_inline:nn { \tl_to_str:n {#3} }
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -42,7 +42,7 @@
% {latex-team at latex-project.org}^^A
% }^^A
% }
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -42,7 +42,7 @@
% {latex-team at latex-project.org}^^A
% }^^A
% }
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -202,17 +202,17 @@
% number, and a semicolon in the input stream. Once |\operand:w| is
% done expanding, we obtain essentially
% \begin{syntax}
-% \cs{exp_after:wN} |\add:ww| \cs{int_value:w} 12345 ;
-% \cs{exp:w} \cs{exp_end:} 333444 ;
+% \cs{exp_after:wN} |\add:ww| \cs{int_value:w} 12345 \cs{@@_sep:}
+% \cs{exp:w} \cs{exp_end:} 333444 \cs{@@_sep:}
% \end{syntax}
% where in fact \cs{exp_after:wN} has already been expanded,
% \cs{int_value:w} has already seen |12345|, and
% \cs{exp:w} is still looking for a number. It finds
% \cs{exp_end:}, hence expands to nothing. Now, \cs{int_value:w} sees
-% the \texttt{;}, which cannot be part of a number. The expansion
+% the \cs{@@_sep:}, which cannot be part of a number. The expansion
% stops, and we are left with
% \begin{syntax}
-% |\add:ww| 12345 ; 333444 ;
+% |\add:ww| 12345 \cs{@@_sep:} 333444 \cs{@@_sep:}
% \end{syntax}
% which can safely perform the addition by grabbing two arguments
% delimited by~\cs{@@_sep:}.
@@ -1447,8 +1447,8 @@
% small or large). It should appear in an integer expression. This
% function reads digits one by one, until reaching a non-digit, and
% adds~$1$ to the integer expression for each digit. If all digits
-% found are~$0$, the function ends the expression by |;0|,
-% otherwise by |;1|. This is done by switching the loop to
+% found are~$0$, the function ends the expression by \cs{@@_sep:}|0|,
+% otherwise by \cs{@@_sep:}|1|. This is done by switching the loop to
% |round_up| at the first non-zero digit, thus we avoid to test
% whether digits are~$0$ or not once we see a first non-zero digit.
% \begin{macrocode}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -42,7 +42,7 @@
% {latex-team at latex-project.org}^^A
% }^^A
% }
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -525,7 +525,8 @@
% rather than $R$ to avoid overflow.
%
% Then we have \cs{@@_randint_wide_aux:w} \meta{X_1}\cs{@@_sep:}\meta{X_0}\cs{@@_sep:}
-% \meta{Y_1}\cs{@@_sep:}\meta{Y_0}\cs{@@_sep:} \meta{R_2}\cs{@@_sep:}\meta{R_1}\cs{@@_sep:}\meta{R_0}|;.|
+% \meta{Y_1}\cs{@@_sep:}\meta{Y_0}\cs{@@_sep:}
+% \meta{R_2}\cs{@@_sep:}\meta{R_1}\cs{@@_sep:}\meta{R_0}\cs{@@_sep:}|.|
% and we apply the algorithm described earlier.
% \begin{macrocode}
\cs_new:Npn \__kernel_randint:nn #1#2
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -144,7 +144,8 @@
% \item \cs{@@_round:NNN} \meta{sign} \meta{digit_1} \meta{digit_2}
% can expand to |0\exp_stop_f:| or |1\exp_stop_f:|.
% \item \cs{@@_round_s:NNNw} \meta{sign} \meta{digit_1} \meta{digit_2}
-% \meta{more digits}\cs{@@_sep:} can expand to |0\exp_stop_f:;| or |1\exp_stop_f:;|.
+% \meta{more digits}\cs{@@_sep:} can expand to
+% |0\exp_stop_f:|\cs{@@_sep:} or |1\exp_stop_f:|\cs{@@_sep:}.
% \item \cs{@@_round_neg:NNN} \meta{sign} \meta{digit_1} \meta{digit_2}
% can expand to |0\exp_stop_f:| or |1\exp_stop_f:|.
% \end{itemize}
@@ -270,9 +271,10 @@
% \cs{@@_round_s:NNNw} \meta{final sign} \meta{digit} \meta{more digits} \cs{@@_sep:}
% \end{syntax}
% Similar to \cs{@@_round:NNN}, but with an extra semicolon, this
-% function expands to |0\exp_stop_f:;| if rounding $\meta{final sign}
-% \meta{digit}.\meta{more digits}$ to an integer truncates, and to
-% |1\exp_stop_f:;| otherwise. The \meta{more digits} part must be a digit,
+% function expands to |0\exp_stop_f:|\cs{@@_sep:} if rounding
+% $\meta{final sign}\meta{digit}.\meta{more digits}$ to an integer
+% truncates, and to |1\exp_stop_f:|\cs{@@_sep:} otherwise.
+% The \meta{more digits} part must be a digit,
% followed by something that does not overflow a \cs{int_use:N}
% \cs{@@_int_eval:w} construction. The only relevant information about
% this piece is whether it is zero or not.
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-symbolic.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-symbolic.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-symbolic.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -1,6 +1,6 @@
% \iffalse
%
-%% File l3fp-symbolic.dtx (C) Copyright 2012-2015,2017,2018,2020,2021,2023 The LaTeX Project
+%% File l3fp-symbolic.dtx (C) Copyright 2012-2025 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -42,7 +42,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -115,20 +115,20 @@
% \__fp_types_binary:Nww \__fp_+_o:ww ,
% {
% \s__fp_symbolic \__fp_symbolic_chk:w
-% \__fp_variable_o:w a , { } ;
+% \__fp_variable_o:w a , { } \__fp_sep:
% \s__fp_symbolic \__fp_symbolic_chk:w
% \__fp_types_binary:Nww \__fp_*_o:ww ,
% {
% \s__fp_symbolic \__fp_symbolic_chk:w
-% \__fp_variable_o:w b , { } ;
+% \__fp_variable_o:w b , { } \__fp_sep:
% \s__fp_symbolic \__fp_symbolic_chk:w
% \__fp_types_unary:NNw \__fp_sin_o:w \use_i:nn ,
% {
% \s__fp_symbolic \__fp_symbolic_chk:w
-% \__fp_variable_o:w c , { } ;
-% } ;
-% } ;
-% } ;
+% \__fp_variable_o:w c , { } \__fp_sep:
+% } \__fp_sep:
+% } \__fp_sep:
+% } \__fp_sep:
% \end{verbatim}
%
% \begin{variable}{\s_@@_symbolic}
@@ -299,10 +299,12 @@
% \@@_symbolic_cot_o:w ,
% \@@_symbolic_csc_o:w ,
% \@@_symbolic_exp_o:w ,
+% \@@_symbolic_fact_o:w ,
% \@@_symbolic_ln_o:w ,
% \@@_symbolic_not_o:w ,
% \@@_symbolic_sec_o:w ,
% \@@_symbolic_set_sign_o:w ,
+% \@@_symbolic_sign_o:w ,
% \@@_symbolic_sin_o:w ,
% \@@_symbolic_tan_o:w ,
% }
@@ -309,8 +311,8 @@
% \begin{macrocode}
\tl_map_inline:nn
{
- {acos} {acsc} {asec} {asin} {cos} {cot} {csc} {exp} {ln}
- {not} {sec} {set_sign} {sin} {sqrt} {tan}
+ {acos} {acsc} {asec} {asin} {cos} {cot} {csc} {exp} {fact} {ln}
+ {not} {sec} {set_sign} {sin} {sign} {sqrt} {tan}
}
{
\cs_new:cpe { @@_symbolic_#1_o:w }
@@ -586,12 +588,12 @@
{ \msg_error:nnn { fp } { id-invalid } {#1} }
{
\cs_if_exist:cT { @@_parse_word_#1:N }
- {
- \msg_error:nnn
- { fp } { id-already-defined } {#1}
- \cs_undefine:c { @@_parse_word_#1:N }
- \cs_set_eq:cN { l_@@_variable_#1_fp } \tex_undefined:D
- }
+ {
+ \msg_error:nnn
+ { fp } { id-already-defined } {#1}
+ \cs_undefine:c { @@_parse_word_#1:N }
+ \cs_set_eq:cN { l_@@_variable_#1_fp } \tex_undefined:D
+ }
\@@_variable_set_parsing:Nn \cs_gset_eq:NN {#1}
}
}
@@ -602,8 +604,9 @@
% \begin{variable}{\l_@@_symbolic_flag}
% \begin{macro}{\fp_set_variable:nn, \@@_set_variable:nn}
% Refuse invalid identifiers. If the variable does not exist yet,
-% define it just as in \cs{fp_new_variable:n} (but without unnecessary
-% checks). Then evaluate~|#2|. If the result contains the
+% raise an error and define it just as in \cs{fp_new_variable:n}
+% (but without unnecessary checks).
+% Then evaluate~|#2|. If the result contains the
% identifier~|#1|, we would later get a loop in cases such as
% \begin{quote}
% \cs{fp_set_variable:nn} |{A}| |{A}|\\
@@ -625,7 +628,11 @@
\@@_id_if_invalid:nTF {#1}
{ \msg_error:nnn { fp } { id-invalid } {#1} }
{
- \@@_variable_set_parsing:Nn \cs_set_eq:NN {#1}
+ \cs_if_exist:cF { @@_parse_word_#1:N }
+ {
+ \msg_error:nnn {fp} { id-undefined } {#1}
+ \@@_variable_set_parsing:Nn \cs_set_eq:NN {#1}
+ }
\fp_set:Nn \l_@@_symbolic_fp {#2}
\cs_set_nopar:cpn { l_@@_variable_#1_fp }
{ \flag_ensure_raised:N \l_@@_symbolic_flag \c_nan_fp }
@@ -659,6 +666,12 @@
LaTeX~has~been~asked~to~create~a~new~floating~point~identifier~'#1'~
but~this~name~has~already~been~used~elsewhere.
}
+\msg_new:nnnn { fp } { id-undefined }
+ { Floating~point~identifier~'#1'~is~undefined. }
+ {
+ LaTeX~has~been~asked~to~set~a~floating~point~identifier~'#1'~
+ but~this~name~has~not~been~declared.
+ }
\msg_new:nnnn { fp } { id-used-elsewhere }
{ Floating~point~identifier~'#1'~already~used~for~something~else. }
{
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -42,7 +42,7 @@
% {latex-team at latex-project.org}^^A
% }^^A
% }
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
% \maketitle
%
% \begin{documentation}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -42,7 +42,7 @@
% {latex-team at latex-project.org}^^A
% }^^A
% }
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-types.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-types.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-types.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -42,7 +42,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -49,7 +49,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -694,6 +694,14 @@
% be set with \cs{fp_set_variable:nn} to arbitrary floating point
% expressions including other variables.
%
+% At present, the following operations and functions are \emph{not} supported
+% \begin{itemize}
+% \item infix binary comparisons like |>|, |=|, |<|
+% \item infix ternary operator like |?:|
+% \item prefix variable-ary functions like |round| and friends,
+% |min|, |max|, |atan|, |acot|, |atand|, |acotd|
+% \end{itemize}
+%
% \begin{function}[added = 2023-10-19]{\fp_new_variable:n}
% \begin{syntax}
% \cs{fp_new_variable:n} \Arg{identifier}
@@ -714,10 +722,12 @@
% \begin{syntax}
% \cs{fp_set_variable:nn} \Arg{identifier} \Arg{fp expr}
% \end{syntax}
-% Defines the \meta{identifier} to stand in any further expression for
+% Sets the \meta{identifier} to stand in any further expression for
% the result of evaluating the \meta{floating point expression} as
-% much as possible. The result may contain other variables, which are
-% then replaced by their values if they have any. For instance,
+% much as possible. The \meta{identifier} must be declared by
+% \cs{fp_new_function:n} first. The result may contain other
+% variables, which are then replaced by their values if they have any.
+% For instance,
% \begin{quote}\let\obeyedline=\newline\obeylines^^A
% \cs{fp_new_variable:n} |{ A }|
% \cs{fp_new_variable:n} |{ B }|
@@ -775,10 +785,11 @@
% \begin{syntax}
% \cs{fp_set_function:nnn} \Arg{identifier} \Arg{vars} \Arg{fp expr}
% \end{syntax}
-% Defines the \meta{identifier} to stand in any further expression for
+% Sets the \meta{identifier} to stand in any further expression for
% the result of evaluating the \meta{floating point expression}, with
% the \meta{identifier} accepting the \meta{vars} (a non-empty
-% comma-separated list).
+% comma-separated list). The \meta{identifier} must be declared by
+% \cs{fp_new_function:n} first.
% The result may contain other functions, which are
% then replaced by their results if they have any. For instance,
% \begin{quote}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Added: trunk/Master/texmf-dist/source/latex/l3kernel/l3graphics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3graphics.dtx (rev 0)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3graphics.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -0,0 +1,786 @@
+% \iffalse meta-comment
+%
+%% File: l3graphics.dtx
+%
+% Copyright (C) 2017-2025 The LaTeX Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version. The latest version
+% of this license is in the file
+%
+% http://www.latex-project.org/lppl.txt
+%
+% This file is part of the "l3kernel bundle" (The Work in LPPL)
+% and all files in that bundle must be distributed together.
+%
+% -----------------------------------------------------------------------
+%
+% The development version of the bundle can be found at
+%
+% https://github.com/latex3/latex3
+%
+% for those people who are interested.
+%
+%<*driver>
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \pkg{l3graphics} module\\ Graphics inclusion support^^A
+% }
+%
+% \author{^^A
+% The \LaTeX{} Project\thanks
+% {^^A
+% E-mail:
+% \href{mailto:latex-team at latex-project.org}
+% {latex-team at latex-project.org}^^A
+% }^^A
+% }
+%
+% \date{Released 2025-03-26}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \section{Graphics keys}
+%
+% Inclusion of graphic files requires a range of low-level data be passed to
+% the backend. This is set up using a small number of key--value settings,
+% which are stored in the |graphics| tree.
+%
+% \begin{variable}{decodearray}
+% Array to decode color in bitmap graphic: when non-empty, this should
+% be in the form of one, two or three pairs of real numbers in the range
+% $[0,1]$, separated by spaces.
+% \end{variable}
+%
+% \begin{variable}{draft}
+% Switch to enable draft mode: graphics are read but not included when this is
+% true.
+% \end{variable}
+%
+% \begin{variable}{interpolate}
+% Switch which indicates whether interpolation should be applied to bitmap
+% graphic files.
+% \end{variable}
+%
+% \begin{variable}{page}
+% The page to extract from a multi-page graphic file: used for |.pdf| files
+% which may contain multiple pages.
+% \end{variable}
+%
+% \begin{variable}{pdf-attr}
+% Additional PDF-focussed attributes: available to allow control of
+% extended |.pdf| structures beyond those needed for graphic inclusion.
+% Due to backend restrictions, this key is only functional with direct
+% PDF mode (pdf\TeX{} and Lua\TeX{}).
+% \end{variable}
+%
+% \begin{variable}{pagebox}
+% The nature of the page box setting used to determine the bounding box of
+% material: used for |.pdf| files which feature multiple page box
+% specifications. A choice from |art|, |bleed|, |crop|, |media|, |trim|.
+% The standard setting is |crop|.
+% \end{variable}
+%
+% \begin{variable}{type}
+% The type of graphic file being included: if this key is not set, the
+% \emph{type} is determined from the file extension.
+% \end{variable}
+%
+% \section{Including graphics}
+%
+% \begin{function}[added = 2025-03-14]
+% {\graphics_include:nn, \graphics_include:nV}
+% \begin{syntax}
+% \cs{graphics_include:nn} \Arg{keys} \Arg{file}
+% \end{syntax}
+% Horizontal-mode command which includes the \meta{file} as a graphic
+% at the current location. The file \meta{type} may be given as one of the
+% \meta{keys}, or will otherwise be determined from file extension. The
+% \meta{keys} is used to pass settings as detailed above.
+% \end{function}
+%
+% \begin{variable}[added = 2025-03-14]{\l_graphics_ext_type_prop}
+% Defines mapping between file extensions and file types; where there is
+% no entry for an extension, the type is assumed to be the extension
+% with the leading |.| removed. Entries should be made in lower case, and
+% the key should be an extension including the leading |.|, for example
+% \begin{verbatim}
+% \prop_put:Nnn \l_graphics_ext_type_prop { .ps } { eps }
+% \end{verbatim}
+% \end{variable}
+%
+% \begin{variable}[added = 2025-03-14]{\l_graphics_search_ext_seq}
+% Extensions to use for graphic searching when the given \meta{file} name is not
+% found by \cs{graphics_get_full_name:nN}.
+% \end{variable}
+%
+% \begin{variable}[added = 2025-03-14]{\l_graphics_search_path_seq}
+% Each entry is the path to a directory which should be searched when
+% seeking a graphic file. Each path can be relative or absolute, and should
+% not include the trailing slash. The entries are not expanded when
+% used so may contain active characters but should not feature any
+% variable content. Spaces need not be quoted.
+% \end{variable}
+%
+% \section{Utility functions}
+%
+% \begin{function}[noTF, added = 2025-03-14]{\graphics_get_full_name:nN}
+% \begin{syntax}
+% \cs{graphics_get_full_name:nN} \Arg{file} \meta{tl~var}
+% \cs{graphics_get_full_name:nNTF} \Arg{file} \meta{tl~var} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Searches for \meta{file} first as given and then using the extensions
+% listed in \cs{l_graphics_search_ext_seq}. The search path used will be
+% the entries of \cs{l_graphics_search_path_seq}. If found, the full file
+% name including any path and extension will be returned in the
+% \meta{tl~var}. In the non-branching version, the \meta{tl var} will be
+% set to \cs{q_no_value} in the case that the graphics is not found.
+% \end{function}
+%
+% \begin{function}[added = 2025-03-14]{\graphics_get_pagecount:nN}
+% \begin{syntax}
+% \cs{graphics_get_pagecount:nn} \Arg{file} \meta{tl~var}
+% \end{syntax}
+% Reads the graphics \meta{file} and extracts the number of pages, which
+% are stored in the \meta{tl~var}.
+% \end{function}
+%
+% \section{Showing and logging included graphics}
+%
+% \begin{function}[added = 2025-03-14]
+% {\graphics_show_list:, \graphics_log_list:}
+% \begin{syntax}
+% \cs{graphics_show_list:}
+% \cs{graphics_log_list:}
+% \end{syntax}
+% These functions list all graphic files loaded in a similar manner to
+% \cs{file_show_list:} and \cs{file_log_list:}. While
+% \cs{graphics_show_list:} displays the list in the terminal,
+% \cs{graphics_log_list:} outputs it to the log file only. In both cases, only
+% graphics loaded by \pkg{l3graphics} are listed.
+% \end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3graphics} implementation}
+%
+% \begin{macrocode}
+%<*package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=graphics>
+% \end{macrocode}
+%
+% Transitional support.
+% \begin{macrocode}
+\cs_if_exist:NT \@expl at finalise@setup@@@@
+ {
+ \tl_gput_right:Nn \@expl at finalise@setup@@@@
+ { \declare at file@substitution { l3graphics.sty } { null.tex } }
+ }
+% \end{macrocode}
+%
+% \begin{variable}{\l_@@_internal_dim, \l_@@_internal_ior, \l_@@_internal_tl}
+% Scratch space.
+% \begin{macrocode}
+\dim_new:N \l_@@_internal_dim
+\ior_new:N \l_@@_internal_ior
+\tl_new:N \l_@@_internal_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\s_@@_stop}
+% Internal scan marks.
+% \begin{macrocode}
+\scan_new:N \s_@@_stop
+% \end{macrocode}
+% \end{variable}
+%
+% \subsection{Graphics keys}
+%
+% \begin{macro}
+% {
+% \l_@@_decodearray_str ,
+% \l__@@_draft_bool ,
+% \l_@@_interpolate_bool ,
+% \l_@@_page_int ,
+% \l_@@_pagebox_tl ,
+% \l_@@_pdf_str ,
+% \l_@@_type_str
+% }
+% Keys which control features of graphics. The standard value of |pagebox|
+% set up here should match the default for the backends themselves: in
+% the absence of any other setting the |crop| should be used. Note that
+% the variable \cs{l_@@_pagebox_str} can be empty internally, as backends
+% which do not support |pagebox| are set up to clear it entirely. The
+% store for |pagebox| is a |tl| as that makes extracting the data
+% easier for some backends.
+% \begin{macrocode}
+\tl_new:N \l_@@_pagebox_tl
+\keys_define:nn { graphics }
+ {
+ decodearray .str_set:N =
+ \l_@@_decodearray_str ,
+ draft .bool_set:N =
+ \l_@@_draft_bool ,
+ interpolate .bool_set:N =
+ \l_@@_interpolate_bool ,
+ pagebox .choices:nn =
+ { art , bleed , crop , media , trim }
+ {
+ \tl_set:Ne \l_@@_pagebox_tl
+ { \l_keys_choice_tl box }
+ } ,
+ pagebox .initial:n =
+ crop ,
+ page .int_set:N =
+ \l_@@_page_int ,
+ pdf-attr .str_set:N =
+ \l_@@_pdf_str ,
+ type . str_set:N =
+ \l_@@_type_str
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Obtaining bounding box data}
+%
+% \begin{variable}
+% {
+% \l_@@_llx_dim , \l_@@_lly_dim,
+% \l_@@_urx_dim , \l_@@_ury_dim
+% }
+% Storage for the return of bounding box.
+% \begin{macrocode}
+\dim_new:N \l_@@_llx_dim
+\dim_new:N \l_@@_lly_dim
+\dim_new:N \l_@@_urx_dim
+\dim_new:N \l_@@_ury_dim
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_bb_save:n, \@@_bb_save:e}
+% \begin{macro}{\@@_bb_restore:nF, \@@_bb_restore:eF}
+% Caching graphic bounding boxes is sensible, and these functions are needed both
+% here and for drive-specific work. So they are made available as documented
+% functions. To save on registers, the \enquote{origin} is only saved if it is
+% not at zero.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_bb_save:n #1
+ {
+ \dim_if_exist:cTF { c_@@_ #1 _urx_dim }
+ { \msg_error:nnn { graphic } { bb-already-cached } {#1} }
+ {
+ \dim_compare:nNnF \l_@@_llx_dim = { 0pt }
+ { \dim_const:cn { c_@@_ #1 _llx_dim } { \l_@@_llx_dim } }
+ \dim_compare:nNnF \l_@@_lly_dim = { 0pt }
+ { \dim_const:cn { c_@@_ #1 _lly_dim } { \l_@@_lly_dim } }
+ \dim_const:cn { c_@@_ #1 _urx_dim } { \l_@@_urx_dim }
+ \dim_const:cn { c_@@_ #1 _ury_dim } { \l_@@_ury_dim }
+ }
+ }
+\cs_generate_variant:Nn \@@_bb_save:n { e }
+\cs_new_protected:Npn \@@_bb_restore:nF #1#2
+ {
+ \dim_if_exist:cTF { c_@@_ #1 _urx_dim }
+ {
+ \dim_set_eq:Nc \l_@@_urx_dim { c_@@_ #1 _urx_dim }
+ \dim_set_eq:Nc \l_@@_ury_dim { c_@@_ #1 _ury_dim }
+ \dim_if_exist:cTF { c_@@_ #1 _llx_dim }
+ { \dim_set_eq:Nc \l_@@_llx_dim { c_@@_ #1 _llx_dim } }
+ { \dim_zero:N \l_@@_llx_dim }
+ \dim_if_exist:cTF { c_@@_ #1 _lly_dim }
+ { \dim_set_eq:Nc \l_@@_lly_dim { c_@@_ #1 _lly_dim } }
+ { \dim_zero:N \l_@@_lly_dim }
+ }
+ {#2}
+ }
+\cs_generate_variant:Nn \@@_bb_restore:nF { e }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_extract_bb:n, \@@_read_bb:n}
+% \begin{macro}{\@@_extract_bb_auix:nn, \@@_extract_bb_auix:Vn}
+% \begin{macro}{\@@_extract_bb_auxii:nnn}
+% \begin{macro}{\@@_extract_bb_auxiii:nnnn, \@@_extract_bb_auxiii:Vnnn}
+% \begin{macro}{\@@_extract_bb_auxiv:nnn}
+% \begin{macro}{\@@_read_bb_auxi:nnnn, \@@_read_bb_auxii:Vnnn}
+% \begin{macro}
+% {
+% \@@_read_bb_auxii:w ,
+% \@@_read_bb_auxiv:w ,
+% \@@_read_bb_auxv:w
+% }
+% Extracting the bounding box from an |.eps| or |.bb| file is done by
+% reading each line and searching for the marker text |%%BoundingBox:|.
+% The data is read as a string with a mapping over
+% the lines: as there is a colon involved, a little bit of work is needed to
+% get the matching correct. The same approach covers cases where the bounding
+% box has to be calculated by |extractbb|, with just the initial phase
+% different.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_extract_bb:n #1
+ {
+ \int_compare:nNnTF \l_@@_page_int > 0
+ { \@@_extract_bb_auxi:Vn \l_@@_page_int {#1} }
+ { \@@_extract_bb_auxii:nnn {#1} { } { } }
+ }
+\cs_new_protected:Npn \@@_extract_bb_auxi:nn #1#2
+ { \@@_extract_bb_auxii:nnn {#2} { :P #1 } { -p~#1~ } }
+\cs_generate_variant:Nn \@@_extract_bb_auxi:nn { Vn }
+\cs_new_protected:Npn \@@_extract_bb_auxii:nnn #1#2#3
+ {
+ \tl_if_empty:NTF \l_@@_pagebox_tl
+ { \@@_extract_bb_auxiv:nnn }
+ { \@@_extract_bb_auxiii:Vnnn \l_@@_pagebox_tl }
+ {#1} {#2} {#3}
+ }
+\cs_new_protected:Npn \@@_extract_bb_auxiii:nnnn #1#2#3#4
+ { \@@_extract_bb_auxiv:nnn {#2} { : #1 #3 } { #4 -B~#1~ } }
+\cs_generate_variant:Nn \@@_extract_bb_auxiii:nnnn { V }
+\cs_new_protected:Npn \@@_extract_bb_auxiv:nnn #1#2#3
+ {
+ \@@_read_bb_auxi:nnnn {#1} {#2}
+ { \ior_shell_open:Nn \l_@@_internal_ior { extractbb~#3-O~#1 } }
+ { pipe-failed }
+ }
+\cs_new_protected:Npn \@@_read_bb:n #1
+ {
+ \@@_read_bb_auxi:nnnn {#1} { }
+ { \ior_open:Nn \l_@@_internal_ior {#1} }
+ { graphic-not-found }
+ }
+% \end{macrocode}
+% Before any real searching, a check to see if there are cached values
+% available. The name of each graphic will be unique and so it's sensible to
+% store the bounding box data in \TeX{}: this avoids multiple file operations.
+% As bounding boxes here start away from the lower-left origin, we need to
+% store all four values (contrast with for example the \texttt{pdfmode}
+% driver). Here |#2| is a potential page identifier: used to allow caching of
+% individual pages in a multi-page document. Caching is applied to the
+% upper-right position in all cases, but as the lower-left will often be
+% $(0,0)$ it is only cached if required.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_read_bb_auxi:nnnn #1#2#3#4
+ {
+ \@@_bb_restore:nF {#1#2}
+ { \@@_read_bb_auxii:nnnn {#3} {#4} {#1} {#2} }
+ }
+\cs_new_protected:Npe \@@_read_bb_auxii:nnnn #1#2#3#4
+ {
+ #1
+ \exp_not:N \ior_if_eof:NTF \exp_not:N \l_@@_internal_ior
+ { \msg_error:nnn { graphics } {#2} {#3} }
+ {
+ \ior_str_map_inline:Nn \exp_not:N \l_@@_internal_ior
+ {
+ \exp_not:N \@@_read_bb_auxiii:w
+ ##1 ~ \c_colon_str \s_@@_stop
+ }
+ \@@_bb_save:n {#3#4}
+ }
+ \ior_close:N \exp_not:N \l_@@_internal_ior
+ }
+\use:e
+ {
+ \cs_new_protected:Npn \exp_not:N \@@_read_bb_auxiii:w
+ #1 \c_colon_str #2 \s_@@_stop
+ {
+ \exp_not:N \str_if_eq:nnT
+ { \c_percent_str \c_percent_str BoundingBox }
+ {#1}
+ { \exp_not:N \@@_read_bb_auxiv:w #2 ( ) \s_@@_stop }
+ }
+ }
+% \end{macrocode}
+% If the bounding box is |atend|, just ignore the current one and keep going.
+% Otherwise, we need to allow for tabs and multiple spaces (as the line has
+% been read as a string). The easiest way to deal with that is to scan the
+% tokens: at this stage the line fragment should be just numbers and
+% whitespace. \TeX{} will then tidy up for us, with just a leading space to
+% worry about: that is taken out by the |\use:n| here.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_read_bb_auxiv:w #1 ( #2 ) #3 \s_@@_stop
+ {
+ \str_if_eq:nnF {#2} { atend }
+ {
+ \tl_set_rescan:Nne \l_@@_internal_tl
+ {
+ \char_set_catcode_space:n { 9 }
+ \char_set_catcode_space:n { 32 }
+ }
+ { \use:n #1 }
+ \exp_after:wN \@@_read_bb_auxv:w \l_@@_internal_tl \s_@@_stop
+ }
+ }
+% \end{macrocode}
+% A trailing space was deliberately added earlier so we know that the final
+% data point is terminated by a space.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_read_bb_auxv:w #1~#2~#3~#4~#5 \s_@@_stop
+ {
+ \dim_set:Nn \l_@@_llx_dim { #1 bp }
+ \dim_set:Nn \l_@@_lly_dim { #2 bp }
+ \dim_set:Nn \l_@@_urx_dim { #3 bp }
+ \dim_set:Nn \l_@@_ury_dim { #4 bp }
+ \ior_map_break:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_final_name_str, \l_@@_full_name_str}
+% The full name is as you'd expect the name including path and extension.
+% The final name here reflects any conversions carried out by the backend,
+% for example if an |.eps| is converted to |.pdf|.
+% \begin{macrocode}
+\str_new:N \l_@@_final_name_str
+\str_new:N \l_@@_full_name_str
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_internal_box}
+% \begin{macrocode}
+\box_new:N \l_@@_internal_box
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_dir_str \l_@@_name_str \l_@@_ext_str}
+% \begin{macrocode}
+\str_new:N \l_@@_dir_str
+\str_new:N \l_@@_name_str
+\str_new:N \l_@@_ext_str
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_graphics_search_path_seq}
+% \begin{macrocode}
+\seq_new:N \l_graphics_search_path_seq
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_graphics_search_ext_seq}
+% Used to specify fall-back extensions: actually set on a per-backend basis.
+% \begin{macrocode}
+\seq_new:N \l_graphics_search_ext_seq
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_graphics_ext_type_prop}
+% Mapping between extensions and types for non-standard mappings
+% \begin{macrocode}
+\prop_new:N \l_graphics_ext_type_prop
+\prop_put:Nnn \l_graphics_ext_type_prop { .ps } { eps }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_record_seq}
+% A list of graphic files used.
+% \begin{macrocode}
+\seq_new:N \g_@@_record_seq
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\graphics_include:nn, \graphics_include:nV}
+% \begin{macro}{\@@_include_search:n}
+% \begin{macro}{\@@_include:}
+% \begin{macro}
+% {
+% \@@_include_auxi:n, \@@_include_auxi:e, \@@_include_auxii:n,
+% \@@_include_auxiii:n, \@@_include_auxiv:n
+% }
+% Actually including an graphic is relatively straight-forward: most of the
+% work is done by the backend. We only have to deal with making sure the
+% box has no apparent depth. Where the first given name is not found, we
+% search based on extension only if the \meta{type} was not given. The one
+% wrinkle is that we may have found a \texttt{.tex} file matching the file
+% name stem: that's not what we want, so we have to filter out.
+% \begin{macrocode}
+\cs_new_protected:Npn \graphics_include:nn #1#2
+ {
+ \group_begin:
+ \keys_set:nn { graphics } {#1}
+ \seq_set_eq:NN \l_file_search_path_seq \l_graphics_search_path_seq
+ \file_get_full_name:nNTF {#2} \l_@@_full_name_str
+ {
+ \str_if_eq:eeTF { \l_@@_full_name_str } { #2 .tex }
+ { \msg_error:nnn { graphics } { graphic-not-found } {#2} }
+ { \@@_include: }
+ }
+ { \msg_error:nnn { graphics } { graphic-not-found } {#2} }
+ \group_end:
+ }
+\cs_generate_variant:Nn \graphics_include:nn { nV }
+\cs_new_protected:Npn \@@_include:
+ {
+ \str_if_empty:NTF \l_@@_type_str
+ {
+ \file_parse_full_name:VNNN \l_@@_full_name_str
+ \l_@@_dir_str \l_@@_name_str \l_@@_ext_str
+ \@@_include_auxi:e
+ {
+ \exp_args:Ne \str_tail:n
+ { \str_casefold:V \l_@@_ext_str }
+ }
+ }
+ { \@@_include_auxi:e { \l_@@_type_str } }
+ }
+\cs_new_protected:Npn \@@_include_auxi:n #1
+ {
+ \prop_get:NnNF \l_graphics_ext_type_prop { .#1 } \l_@@_internal_tl
+ { \tl_set:Nn \l_@@_internal_tl {#1} }
+ \exp_args:NV \@@_include_auxii:n \l_@@_internal_tl
+ }
+\cs_generate_variant:Nn \@@_include_auxi:n { e }
+\cs_new_protected:Npn \@@_include_auxii:n #1
+ {
+ \mode_leave_vertical:
+ \cs_if_exist:cTF { @@_backend_include_ #1 :n }
+ {
+ \tl_set_eq:NN \l_@@_final_name_str \l_@@_full_name_str
+ \str_set:Ne \l_@@_full_name_str
+ { \exp_args:NV \__kernel_file_name_quote:n \l_@@_full_name_str }
+ \exp_args:NnV \use:c { @@_backend_getbb_ #1 :n }
+ \l_@@_full_name_str
+ \seq_gput_right:NV \g_@@_record_seq \l_@@_final_name_str
+ \clist_if_exist:NT \@filelist
+ { \exp_args:NV \@addtofilelist \l_@@_final_name_str }
+ \bool_if:NTF \l_@@_draft_bool
+ { \@@_include_auxiii:n }
+ { \@@_include_auxiv:n }
+ {#1}
+ }
+ { \msg_error:nnn { graphics } { unsupported-graphic-type } {#1} }
+ }
+\cs_new_protected:Npn \@@_include_auxiii:n #1
+ {
+ \hbox_to_wd:nn { \l_@@_urx_dim - \l_@@_llx_dim }
+ {
+ \tex_vrule:D
+ \tex_hss:D
+ \vbox_to_ht:nn
+ { \l_@@_ury_dim - \l_@@_lly_dim }
+ {
+ \tex_hrule:D width
+ \dim_eval:n { \l_@@_urx_dim - \l_@@_llx_dim }
+ \tex_vss:D
+ \hbox_to_wd:nn
+ { \l_@@_urx_dim - \l_@@_llx_dim }
+ {
+ \ttfamily
+ \tex_hss:D \l_@@_full_name_str \tex_hss:D
+ }
+ \tex_vss:D
+ \tex_hrule:D
+ }
+ \tex_hss:D
+ \tex_vrule:D
+ }
+ }
+\cs_new_protected:Npn \@@_include_auxiv:n #1
+ {
+ \hbox_set:Nn \l_@@_internal_box
+ {
+ \exp_args:NnV \use:c { @@_backend_include_ #1 :n }
+ \l_@@_full_name_str
+ }
+ \box_set_dp:Nn \l_@@_internal_box { 0pt }
+ \box_set_ht:Nn \l_@@_internal_box
+ { \l_@@_ury_dim - \l_@@_lly_dim }
+ \box_set_wd:Nn \l_@@_internal_box
+ { \l_@@_urx_dim - \l_@@_llx_dim }
+ \box_use_drop:N \l_@@_internal_box
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\graphics_show_list:, \graphics_log_list:, \@@_list:N}
+% \begin{macro}[EXP]{\@@_list_aux:n}
+% A function to list all graphic files used.
+% \begin{macrocode}
+\cs_new_protected:Npn \graphics_show_list: { \@@_list:N \msg_show:nneeee }
+\cs_new_protected:Npn \graphics_log_list: { \@@_list:N \msg_log:nneeee }
+\cs_new_protected:Npn \@@_list:N #1
+ {
+ \seq_remove_duplicates:N \g_@@_record_seq
+ #1 { kernel } { file-list }
+ { \seq_map_function:NN \g_@@_record_seq \@@_list_aux:n }
+ { } { } { }
+ }
+\cs_new:Npn \@@_list_aux:n #1 { \iow_newline: #1 }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Utility functions}
+%
+% \begin{macro}{\graphics_get_full_name:nN}
+% \begin{macro}[TF]{\graphics_get_full_name:nN}
+% \begin{macro}{\@@_get_full_name:n}
+% As well as searching by path, etc., there is a need here to check that
+% we do not trip over |foo.bar| if |.bar| is not a known extension for
+% the current backend.
+% \begin{macrocode}
+\cs_new_protected:Npn \graphics_get_full_name:nN #1#2
+ {
+ \graphics_get_full_name:nNF {#1} #2
+ { \tl_set:Nn #2 { \q_no_value } }
+ }
+\prg_new_protected_conditional:Npnn \graphics_get_full_name:nN #1#2
+ { T , F , TF }
+ {
+ \group_begin:
+ \seq_set_eq:NN \l_file_search_path_seq \l_graphics_search_path_seq
+ \file_get_full_name:nNTF {#1} \l_@@_full_name_str
+ {
+ \str_if_eq:eeTF { \l_@@_full_name_str } { #1 .tex }
+ { \@@_get_full_name:n {#1} }
+ {
+ \file_parse_full_name:VNNN \l_@@_full_name_str
+ \l_@@_dir_str \l_@@_name_str \l_@@_ext_str
+ \seq_map_inline:Nn \l_graphics_search_ext_seq
+ {
+ \str_if_eq:nVT {##1} \l_@@_ext_str
+ { \seq_map_break:n { \use_none:nn } }
+ }
+ \@@_get_full_name:n {#1}
+ }
+ }
+ { \@@_get_full_name:n {#1} }
+ \exp_args:NNNV \group_end:
+ \tl_set:Nn #2 \l_@@_full_name_str
+ \tl_if_empty:NTF #2
+ { \prg_return_false: }
+ { \prg_return_true: }
+ }
+\cs_new_protected:Npn \@@_get_full_name:n #1
+ {
+ \str_clear:N \l_@@_full_name_str
+ \seq_map_inline:Nn \l_graphics_search_ext_seq
+ {
+ \file_get_full_name:nNT { #1 ##1 } \l_@@_full_name_str
+ { \seq_map_break:n { \use_none:nn } }
+ }
+ \use:n
+ { \str_clear:N \l_@@_full_name_str }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\graphics_get_pagecount:nN}
+% \begin{macro}{\@@_get_pagecount:n}
+% \begin{macro}{\@@_get_pagecount:nw}
+% A generic function to read the number of pages in a graphic file. This is
+% used by all of the backend where there is not a dedicated primitive. The
+% plan is essentially the same as reading the bounding box. To avoid multiple
+% calls, the value is cached either here or in the backend.
+% \begin{macrocode}
+\cs_new_protected:Npn \graphics_get_pagecount:nN #1#2
+ {
+ \group_begin:
+ \seq_set_eq:NN \l_file_search_path_seq \l_graphics_search_path_seq
+ \file_get_full_name:nNTF {#1} \l_@@_full_name_str
+ {
+ \int_if_exist:cF { c_@@_ \l_@@_full_name_str _pages_int }
+ {
+ \exp_args:NV \@@_backend_get_pagecount:n
+ \l_@@_full_name_str
+ }
+ \tl_set:Nv #2 { c_@@_ \l_@@_full_name_str _pages_int }
+ }
+ {
+ \tl_set:Nn #2 { 0 }
+ \msg_error:nnn { graphics } { graphic-not-found } {#1}
+ }
+ \exp_args:NNNV \group_end:
+ \tl_set:Nn #2 #2
+ }
+\cs_new_protected:Npe \@@_get_pagecount:n #1
+ {
+ \exp_not:N \ior_shell_open:Nn \exp_not:N \l_@@_internal_ior
+ { extractbb~-O~#1 }
+ \exp_not:N \ior_if_eof:NTF \exp_not:N \l_@@_internal_ior
+ { \msg_error:nnn { graphics } { pipe-failed } }
+ {
+ \ior_str_map_inline:Nn \exp_not:N \l_@@_internal_ior
+ {
+ \exp_not:N \@@_get_pagecount:nw {#1}
+ ##1 ~ \c_colon_str \c_colon_str \s_@@_stop
+ }
+ \exp_not:N \int_if_exist:cF { c_@@_ #1 _pages_int }
+ { \int_const:cn { c_@@_ #1 _pages_int } { 1 } }
+ }
+ \ior_close:N \exp_not:N \l_@@_internal_ior
+ }
+\use:e
+ {
+ \cs_new_protected:Npn \exp_not:N \@@_get_pagecount:nw
+ #1#2 \c_colon_str #3 \c_colon_str #4 \s_@@_stop
+ {
+ \exp_not:N \str_if_eq:nnT
+ { \c_percent_str \c_percent_str Pages }
+ {#2}
+ {
+ \int_const:cn { c_@@_ #1 _pages_int } {#3}
+ \exp_not:N \ior_map_break:
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Messages}
+%
+% \begin{macrocode}
+\msg_new:nnnn { graphics } { graphic-not-found }
+ { Image~file~'#1'~not~found. }
+ {
+ LaTeX~tried~to~open~graphic~file~'#1',~
+ but~the~file~could~not~be~read.
+ }
+\msg_new:nnnn { graphics } { pipe-failed }
+ { Cannot~run~piped~system~commands. }
+ {
+ LaTeX~tried~to~call~a~system~process~but~this~was~not~possible.\\
+ Try~the~"--shell-escape"~(or~"--enable-pipes")~option.
+ }
+\msg_new:nnnn { graphics } { unsupported-graphic-type }
+ { Image~type~'#1'~not~supported~by~current~driver. }
+ {
+ LaTeX~was~asked~to~include~an~graphic~of~type~'#1',~
+ but~this~is~not~supported~by~the~current~driver~(production~route).
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex
Property changes on: trunk/Master/texmf-dist/source/latex/l3kernel/l3graphics.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -177,6 +177,22 @@
% and |#3| and |#4| empty.
% \end{function}
%
+% \begin{function}[EXP]
+% {
+% \__kernel_codepoint_to_grapheme_class:n,
+% \__kernel_codepoint_to_wordbreak_class:n
+% }
+% \begin{syntax}
+% \cs{__kernel_codepoint_to_grapheme_class:n} \Arg{codepoint}
+% \cs{__kernel_codepoint_to_wordbreak_class:n} \Arg{codepoint}
+% \end{syntax}
+% Expands to the Unicode properties |Grapheme_Cluster_Break| and
+% |Word_Break|, respectively, of the \meta{codepoint}. Here,
+% |Grapheme_Cluster_Break| and |Word_Break| are strings matching
+% exactly the descriptors given in
+% \url{https://www.unicode.org/reports/tr29/}.
+% \end{function}
+%
% \begin{function}{\__kernel_cs_parm_from_arg_count:nnF}
% \begin{syntax}
% \cs{__kernel_cs_parm_from_arg_count:nnF} \Arg{follow-on} \Arg{args} \Arg{false code}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -2365,6 +2365,7 @@
% \begin{macro}{\@@_usage:n}
% \begin{macro}{\@@_usage:NN}
% \begin{macro}{\@@_usage:w}
+% \begin{macro}{\@@_usage_aux:w}
% Save the relevant data.
% \begin{macrocode}
\cs_new_protected:Npn \@@_usage:n #1
@@ -2405,7 +2406,11 @@
\prop_get:NVNF #1 \l_@@_module_str \l_@@_tmpa_tl
{ \tl_clear:N \l_@@_tmpa_tl }
\tl_set:Ne \l_@@_tmpb_tl
- { \exp_after:wN \@@_usage:w \l_keys_path_str \s_@@_stop }
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN \@@_usage:w \exp_after:wN
+ \l_keys_path_str \exp_after:wN / \exp_after:wN \s_@@_stop
+ \exp_after:wN { \l_keys_path_str }
+ }
\bool_if:NTF #2
{ \clist_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl }
{ \clist_remove_all:NV \l_@@_tmpa_tl \l_@@_tmpb_tl }
@@ -2412,11 +2417,18 @@
\prop_put:NVV #1 \l_@@_module_str
\l_@@_tmpa_tl
}
-\cs_new:Npn \@@_usage:w #1 / #2 \s_@@_stop {#2}
+\cs_new:Npn \@@_usage:w #1 / #2 \s_@@_stop #3
+ {
+ \tl_if_blank:nTF {#2}
+ {#1}
+ { \@@_usage_aux:w #3 \s_@@_stop }
+ }
+\cs_new:Npn \@@_usage_aux:w #1 / #2 \s_@@_stop {#2}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
+% \end{macro}
%
% \begin{macro}{\@@_variable_set:NnnN, \@@_variable_set:cnnN}
% \begin{macro}{\@@_variable_set_required:NnnN, \@@_variable_set_required:cnnN}
@@ -3539,35 +3551,59 @@
% \end{macro}
%
% \begin{macro}[EXP,pTF]{\keys_if_exist:nn}
+% \begin{macro}[EXP]{\@@_if_exist:nn, \@@_if_exist:ee}
% A utility for others to see if a key exists.
% \begin{macrocode}
\prg_new_conditional:Npnn \keys_if_exist:nn #1#2 { p , T , F , TF }
{
+ \@@_if_exist:ee
+ { \@@_trim_spaces:n {#1} }
+ { \@@_trim_spaces:n {#2} }
+ }
+\prg_generate_conditional_variant:Nnn \keys_if_exist:nn { ne } { p , T , F , TF }
+\cs_new:Npn \@@_if_exist:nn #1#2
+ {
\cs_if_exist:cTF
- { \c_@@_code_root_str \@@_trim_spaces:n { #1 / #2 } }
+ { \c_@@_code_root_str #1 \tl_if_blank:nF {#1} { / } #2 }
{ \prg_return_true: }
{ \prg_return_false: }
}
-\prg_generate_conditional_variant:Nnn \keys_if_exist:nn { ne } { p , T , F , TF }
+\cs_generate_variant:Nn \@@_if_exist:nn { ee }
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \begin{macro}[EXP,pTF]{\keys_if_choice_exist:nnn}
+% \begin{macro}[EXP]{\@@_if_exist:nnn, \@@_if_exist:eee}
% Just an alternative view on \cs{keys_if_exist:nnTF}.
% \begin{macrocode}
\prg_new_conditional:Npnn \keys_if_choice_exist:nnn #1#2#3
{ p , T , F , TF }
{
+ \@@_if_exist:eee
+ { \@@_trim_spaces:n {#1} }
+ { \@@_trim_spaces:n {#2} }
+ { \@@_trim_spaces:n {#3} }
+ }
+\cs_new:Npn \@@_if_exist:nnn #1#2#3
+ {
\cs_if_exist:cTF
- { \c_@@_code_root_str \@@_trim_spaces:n { #1 / #2 / #3 } }
+ {
+ \c_@@_code_root_str
+ #1 \tl_if_blank:nF {#1} { / }
+ #2 \tl_if_blank:nF {#2} { / }
+ #3
+ }
{ \prg_return_true: }
{ \prg_return_false: }
}
+\cs_generate_variant:Nn \@@_if_exist:nnn { eee }
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \begin{macro}{\keys_show:nn, \keys_log:nn}
-% \begin{macro}{\@@_show:Nnn}
+% \begin{macro}{\@@_show:Nnn, \@@_show_aux:Nnn, , \@@_show_aux:Nee}
% \begin{macro}{\@@_show:n}
% \begin{macro}{\@@_show:w}
% \begin{macro}{\@@_show:Nw}
@@ -3579,8 +3615,15 @@
{ \@@_show:Nnn \msg_log:nneeee }
\cs_new_protected:Npn \@@_show:Nnn #1#2#3
{
+ \@@_show_aux:Nee
+ #1
+ { \@@_trim_spaces:n {#2} }
+ { \@@_trim_spaces:n {#3} }
+ }
+\cs_new_protected:Npn \@@_show_aux:Nnn #1#2#3
+ {
#1 { keys } { show-key }
- { \@@_trim_spaces:n { #2 / #3 } }
+ { #2 \tl_if_blank:nF {#2} { / } #3 }
{
\keys_if_exist:nnT {#2} {#3}
{
@@ -3591,7 +3634,7 @@
\exp_args:Nc \cs_replacement_spec:N
{
\c_@@_code_root_str
- \@@_trim_spaces:n { #2 / #3 }
+ #2 \tl_if_blank:nF {#2} { / } #3
}
}
}
@@ -3599,6 +3642,7 @@
}
{ } { }
}
+\cs_generate_variant:Nn \@@_show_aux:Nnn { Nee }
\cs_new:Npe \@@_show:n #1
{
\exp_not:N \@@_show:w
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -584,6 +584,7 @@
\@@_primitive:NN \pdfpageref \tex_pdfpageref:D
\@@_primitive:NN \pdfpageresources \tex_pdfpageresources:D
\@@_primitive:NN \pdfpagesattr \tex_pdfpagesattr:D
+ \@@_primitive:NN \pdfptexuseunderscore \tex_pdfptexuseunderscore:D
\@@_primitive:NN \pdfrefobj \tex_pdfrefobj:D
\@@_primitive:NN \pdfrefxform \tex_pdfrefxform:D
\@@_primitive:NN \pdfrefximage \tex_pdfrefximage:D
@@ -896,6 +897,7 @@
\@@_primitive:NN \mathdisplayskipmode \tex_mathdisplayskipmode:D
\@@_primitive:NN \matheqdirmode \tex_matheqdirmode:D
\@@_primitive:NN \matheqnogapstep \tex_matheqnogapstep:D
+ \@@_primitive:NN \mathemptydisplaymode \tex_mathemptydisplaymode:D
\@@_primitive:NN \mathflattenmode \tex_mathflattenmode:D
\@@_primitive:NN \mathitalicsmode \tex_mathitalicsmode:D
\@@_primitive:NN \mathnolimitsmode \tex_mathnolimitsmode:D
@@ -1262,6 +1264,7 @@
% \end{macrocode}
% Newer cross-engine primitives.
% \begin{macrocode}
+ \@@_primitive:NN \ignoreprimitiveerror \tex_ignoreprimitiveerror:D
\@@_primitive:NN \partokencontext \tex_partokencontext:D
\@@_primitive:NN \partokenname \tex_partokenname:D
\@@_primitive:NN \showstream \tex_showstream:D
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -769,7 +769,7 @@
% Searches for the \meta{regex} in the contents of the
% \meta{tl~var} and replaces the first match with the
% \meta{replacement}. In the \meta{replacement},
-% |\0| represents the full match, |\1| represent the contents of the
+% |\0| represents the full match, |\1| represents the contents of the
% first capturing group, |\2| of the second, \emph{etc.}
% The result is assigned locally to \meta{tl~var}.
% \end{function}
@@ -786,7 +786,7 @@
% Replaces all occurrences of the \meta{regex} in the
% contents of the \meta{tl~var}
% by the \meta{replacement}, where |\0| represents
-% the full match, |\1| represent the contents of the first capturing
+% the full match, |\1| represents the contents of the first capturing
% group, |\2| of the second, \emph{etc.} Every match is treated
% independently, and matches cannot overlap. The result is assigned
% locally to \meta{tl~var}.
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -289,7 +289,7 @@
% \begin{function}[added = 2013-07-24, updated = 2022-03-21, EXP, noTF]
% {
% \str_case:nn, \str_case:Vn, \str_case:Nn, \str_case:on, \str_case:en,
-% \str_case:nV, \str_case:nv
+% \str_case:nV, \str_case:nv, \str_case:ne
% }
% \begin{syntax}
% \cs{str_case:nnTF} \Arg{test string} \\
@@ -1253,7 +1253,8 @@
%
% \begin{macro}[EXP, noTF]
% {
-% \str_case:nn, \str_case:Vn, \str_case:Nn, \str_case:on, \str_case:en, \str_case:nV, \str_case:nv,
+% \str_case:nn, \str_case:Vn, \str_case:Nn, \str_case:on, \str_case:en,
+% \str_case:nV, \str_case:nv, \str_case:ne,
% \str_case_e:nn, \str_case_e:en
% }
% \begin{macro}[EXP]{\@@_case:nnTF, \@@_case_e:nnTF}
@@ -1289,9 +1290,9 @@
}
\cs_new:Npn \@@_case:nnTF #1#2#3#4
{ \@@_case:nw {#1} #2 {#1} { } \s_@@_mark {#3} \s_@@_mark {#4} \s_@@_stop }
-\cs_generate_variant:Nn \str_case:nn { V , o , e , nV , nv }
+\cs_generate_variant:Nn \str_case:nn { V , o , e , nV , nv , ne }
\prg_generate_conditional_variant:Nnn \str_case:nn
- { V , o , e , nV , nv } { T , F , TF }
+ { V , o , e , nV , nv , ne } { T , F , TF }
\cs_new_eq:NN \str_case:Nn \str_case:Vn
\cs_new_eq:NN \str_case:NnT \str_case:VnT
\cs_new_eq:NN \str_case:NnF \str_case:VnF
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -1097,7 +1097,7 @@
%
% \begin{macro}[EXP]{\sys_timer:, \@@_elapsedtime:}
% \begin{macro}[EXP, pTF]{\sys_if_timer_exist:}
-% In \LuaTeX{}, create a pseudo-primitve, otherwise try to
+% In \LuaTeX{}, create a pseudo-primitive, otherwise try to
% locate the real primitive. The elapsed time will be
% available if this succeeds.
% \begin{macrocode}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3text-map.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3text-map.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3text-map.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -65,150 +65,100 @@
%
% \subsection{Mapping to text}
%
-% \begin{macro}[EXP]{\text_map_function:nN}
-% \begin{macro}[EXP]{\@@_map_function:nN}
-% \begin{macro}[EXP]{\@@_map_loop:Nnw}
-% \begin{macro}[EXP]{\@@_map_group:Nnn}
-% \begin{macro}[EXP]{\@@_map_space:Nnw}
-% \begin{macro}[EXP]{\@@_map_N_type:NnN}
-% \begin{macro}[EXP]{\@@_map_codepoint:Nnn}
-% \begin{macro}[EXP]{\@@_map_CR:Nnw}
-% \begin{macro}[EXP]{\@@_map_CR:NnN}
+% \subsubsection{Common code}
+%
+% \begin{macro}[EXP]{\@@_map_function:nnN, \@@_map_function:enN}
+% \begin{macro}[EXP]{\@@_map_loop:Nnnw}
+% \begin{macro}[EXP]{\@@_map_group:Nnnn}
+% \begin{macro}[EXP]{\@@_map_space:Nnnw}
+% \begin{macro}[EXP]{\@@_map_N_type:NnnN}
+% \begin{macro}[EXP]{\@@_map_codepoint:Nnnn}
+% \begin{macro}[EXP]{\@@_map_CR:Nnnw}
+% \begin{macro}[EXP]{\@@_map_CR:NnnN}
% \begin{macro}[EXP]{\@@_map_class:Nnnn}
-% \begin{macro}[EXP]{\@@_map_class:nNnnn}
-% \begin{macro}[EXP]{\@@_map_class_loop:Nnnnw}
-% \begin{macro}[EXP]{\@@_map_class_end:nw}
-% \begin{macro}[EXP]
-% {
-% \@@_map_Control:Nnn ,
-% \@@_map_Extend:Nnn ,
-% \@@_map_SpacingMark:Nnn ,
-% \@@_map_Prepend:Nnn ,
-% \@@_map_Prepend_aux:Nnn
-% }
-% \begin{macro}[EXP]{\@@_map_Prepend:nNnn}
-% \begin{macro}[EXP]{\@@_map_Prepend_loop:Nnnw}
-% \begin{macro}[EXP]
-% {
-% \@@_map_not_Control:Nnn ,
-% \@@_map_not_Extend:Nnn ,
-% \@@_map_not_SpacingMark:Nnn ,
-% \@@_map_not_Prepend:Nnn ,
-% \@@_map_not_L:Nnn ,
-% \@@_map_not_LV:Nnn ,
-% \@@_map_not_V:Nnn ,
-% \@@_map_not_LVT:Nnn ,
-% \@@_map_not_T:Nnn
-% }
-% \begin{macro}[EXP]
-% {
-% \@@_map_L:Nnn ,
-% \@@_map_LV:Nnn ,
-% \@@_map_V:Nnn ,
-% \@@_map_LVT:Nnn ,
-% \@@_map_T:Nnn
-% }
-% \begin{macro}[EXP]{\@@_map_hangul:Nnnw}
-% \begin{macro}[EXP]{\@@_map_hangul:NnnN}
-% \begin{macro}[EXP]{\@@_map_hangul:Nnnn}
-% \begin{macro}[EXP]{\@@_map_hangul_aux:Nnnnw}
-% \begin{macro}[EXP]{\@@_map_hangul:nNnnnw}
-% \begin{macro}[EXP]{\@@_map_hangul_loop:Nnnnnw}
-% \begin{macro}[EXP]{\@@_map_hangul_next:Nnnn}
-% \begin{macro}[EXP]{\@@_map_hangul_end:nw}
-% \begin{macro}[EXP]
-% {
-% \@@_map_hangul_L:Nnn ,
-% \@@_map_hangul_LV:Nnn ,
-% \@@_map_hangul_V:Nnn ,
-% \@@_map_hangul_LVT:Nnn ,
-% \@@_map_hangul_T:Nnn
-% }
-% \begin{macro}[EXP]
-% {\@@_map_Regional_Indicator:Nnn, \@@_map_Regional_Indicator_aux:Nnn}
-% \begin{macro}[EXP]{\@@_map_lookahead:NnNw}
-% \begin{macro}[EXP]{\@@_map_lookahead:NnNN}
+% \begin{macro}[EXP]{\@@_map_class:Nnnnn}
+% \begin{macro}[EXP]{\@@_map_lookahead:Nnnnnw}
+% \begin{macro}[EXP]{\@@_map_lookahead:NnnnnN}
+% \begin{macro}[TF,EXP]{\@@_map_if_ignorable:n}
% \begin{macro}[EXP]{\@@_map_output:Nn}
% \begin{macro}[EXP]{\text_map_break:}
% \begin{macro}[EXP]{\text_map_break:n}
-% The standard lead-off for an action loop.
+% Mapping to text all works the same way: using standard \enquote{action}
+% loop on expanded text. There are different ways to determine the boundary
+% conditions for breaking: to avoid duplication, the common ideas are covered
+% here with the specifics split out. In all cases, anything which is not a
+% character token is treated as a boundary.
% \begin{macrocode}
-\cs_new:Npn \text_map_function:nN #1#2
- { \exp_args:Ne \@@_map_function:nN { \text_expand:n {#1} } #2 }
-\cs_new:Npn \@@_map_function:nN #1#2
+\cs_new:Npn \@@_map_function:nnN #1#2#3
{
- \@@_map_loop:Nnw #2 { } #1
+ \@@_map_loop:Nnnw #3 {#2} { } #1
\q_@@_recursion_tail \q_@@_recursion_stop
\prg_break_point:Nn \text_map_break: { }
}
-% \end{macrocode}
-% The standard set up for an \enquote{action} loop. Groups are handled by
-% recursion, spaces are treated similarly: both count as grapheme boundaries.
-% For \texttt{N}-type tokens, we filter out control sequences (again
-% a boundary), then move on to further analysis.
-% \begin{macrocode}
-\cs_new:Npn \@@_map_loop:Nnw #1#2#3 \q_@@_recursion_stop
+\cs_generate_variant:Nn \@@_map_function:nnN { e }
+\cs_new:Npn \@@_map_loop:Nnnw #1#2#3#4 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#3}
- { \@@_map_N_type:NnN }
+ \tl_if_head_is_N_type:nTF {#4}
+ { \@@_map_N_type:NnnN }
{
- \tl_if_head_is_group:nTF {#3}
- { \@@_map_group:Nnn }
- { \@@_map_space:Nnw }
+ \tl_if_head_is_group:nTF {#4}
+ { \@@_map_group:Nnnn }
+ { \@@_map_space:Nnnw }
}
- #1 {#2} #3 \q_@@_recursion_stop
+ #1 {#2} {#3} #4 \q_@@_recursion_stop
}
-\cs_new:Npn \@@_map_group:Nnn #1#2#3
+\cs_new:Npn \@@_map_group:Nnnn #1#2#3#4
{
- \@@_map_output:Nn #1 {#2}
+ \@@_map_output:Nn #1 {#3}
{
- \@@_map_loop:Nnw #1 { } #2
+ \@@_map_loop:Nnnw #1 {#2} { } #4
\q_@@_recursion_tail \q_@@_recursion_stop
\prg_break_point:Nn \text_map_break: { }
}
- \@@_map_loop:Nnw #1 { }
+ \@@_map_loop:Nnnw #1 {#2} { }
}
\use:e
- { \cs_new:Npn \exp_not:N \@@_map_space:Nnw #1#2 \c_space_tl }
+ { \cs_new:Npn \exp_not:N \@@_map_space:Nnnw #1#2#3 \c_space_tl }
{
- \@@_map_output:Nn #1 {#2}
+ \@@_map_output:Nn #1 {#3}
#1 { ~ }
- \@@_map_loop:Nnw #1 { }
+ \@@_map_loop:Nnnw #1 {#2} { }
}
-\cs_new:Npn \@@_map_N_type:NnN #1#2#3
+\cs_new:Npn \@@_map_N_type:NnnN #1#2#3#4
{
- \@@_if_q_recursion_tail_stop_do:Nn #3
+ \@@_if_q_recursion_tail_stop_do:Nn #4
{
- \@@_map_output:Nn #1 {#2}
+ \@@_map_output:Nn #1 {#3}
\text_map_break:
}
- \token_if_cs:NTF #3
+ \token_if_cs:NTF #4
{
- \@@_map_output:Nn #1 {#2}
- #1 {#3}
- \@@_map_loop:Nnw #1 { }
+ \@@_map_output:Nn #1 {#3}
+ #1 {#4}
+ \@@_map_loop:Nnnw #1 {#2} { }
}
{
\@@_codepoint_process:nN
- { \@@_map_codepoint:Nnn #1 {#2} } #3
+ { \@@_map_codepoint:Nnnn #1 {#2} {#3} } #4
}
}
% \end{macrocode}
% We pull out a few special cases here. Carriage returns case needs a bit of
% context handling so has an auxiliary. Codepoint U+200D is the zero-width
-% joiner, which has no context to concern us: just don't break.
+% joiner, which has no context to concern us: just don't break. (These special
+% cases apply to all forms of text mapping.)
% \begin{macrocode}
-\cs_new:Npn \@@_map_codepoint:Nnn #1#2#3
+\cs_new:Npn \@@_map_codepoint:Nnnn #1#2#3#4
{
- \@@_codepoint_compare:nNnTF {#3} = { "0D }
+ \@@_codepoint_compare:nNnTF {#4} = { "000D }
{
- \@@_map_output:Nn #1 {#2}
- \@@_map_CR:Nnw #1 {#3}
+ \@@_map_output:Nn #1 {#3}
+ \@@_map_CR:Nnnw #1 {#2} {#4}
}
{
- \@@_codepoint_compare:nNnTF {#3} = { "200D }
- { \@@_map_loop:Nnw #1 {#2#3} }
- { \@@_map_class:Nnnn #1 {#2} {#3} { Control } }
+ \@@_codepoint_compare:nNnTF {#4} = { "200D }
+ { \@@_map_loop:Nnnw #1 {#2} {#3#4} }
+ { \@@_map_class:Nnnn #1 {#2} {#3} {#4} }
}
}
% \end{macrocode}
@@ -215,157 +165,264 @@
% A carriage return is a boundary unless it is immediately followed by
% a line feed, in which case that pair is a boundary.
% \begin{macrocode}
-\cs_new:Npn \@@_map_CR:Nnw #1#2#3 \q_@@_recursion_stop
+\cs_new:Npn \@@_map_CR:Nnnw #1#2#3#4 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#3}
- { \@@_map_CR:NnN #1 {#2} }
+ \tl_if_head_is_N_type:nTF {#4}
+ { \@@_map_CR:NnnN #1 {#2} {#3} }
{
- #1 {#2}
- \@@_map_loop:Nnw #1 { }
+ #1 {#3}
+ \@@_map_loop:Nnnw #1 {#2} { }
}
- #3 \q_@@_recursion_stop
+ #4 \q_@@_recursion_stop
}
-\cs_new:Npn \@@_map_CR:NnN #1#2#3
+\cs_new:Npn \@@_map_CR:NnnN #1#2#3#4
{
- \@@_if_q_recursion_tail_stop_do:Nn #3
+ \@@_if_q_recursion_tail_stop_do:Nn #4
{
- #1 {#2}
+ #1 {#3}
\text_map_break:
}
\bool_lazy_and:nnTF
- { ! \token_if_cs_p:N #3 }
- { \int_compare_p:nNn { `#3 } = { "0A } }
+ { ! \token_if_cs_p:N #4 }
+ { \int_compare_p:nNn { `#4 } = { "000A } }
{
- \@@_map_output:Nn #1 {#2#3}
- \@@_map_loop:Nnw #1 { }
+ \@@_map_output:Nn #1 {#3#4}
+ \@@_map_loop:Nnnw #1 {#2} { }
}
- { \@@_map_loop:Nnw #1 { } #3 }
+ { \@@_map_loop:Nnnw #1 {#2} { } #3 }
}
% \end{macrocode}
% There are various classes of character, and we deal with them all in
% the same general way. We need to example the relevant list of codepoints:
-% if we get a hit, then we do whatever the relevant action is. Otherwise
-% we loop, but only if the current codepoint could still match: the
-% loop stops early otherwise and we move forward.
+% if we get a hit, then we do whatever the relevant action is. To keep names
+% short and to allow code sharing, we have two ways of naming the functions:
+% most class names are unique, so it's only where we see the same name used
+% in both break classes that we need more control.
% \begin{macrocode}
\cs_new:Npn \@@_map_class:Nnnn #1#2#3#4
{
- \exp_args:Nv \@@_map_class:nNnnn { c_@@_grapheme_ #4 _clist }
- #1 {#2} {#3} {#4}
+ \exp_args:Nnnne \@@_map_class:Nnnnn #1 {#2} {#3} {#4}
+ {
+ \use:c { __kernel_codepoint_to_ #2 _class:n }
+ { \@@_codepoint_from_chars:Nw #4 }
+ }
}
-\cs_new:Npn \@@_map_class:nNnnn #1#2#3#4#5
+\cs_new:Npn \@@_map_class:Nnnnn #1#2#3#4#5
{
- \@@_map_class_loop:Nnnnw #2 {#3} {#4} {#5}
- #1 , \q_@@_recursion_tail .. , \q_@@_recursion_stop
+ \cs_if_exist_use:cF { @@_map_ #5 :Nnnn }
+ { \@@_map_Other:Nnnn }
+ #1 {#2} {#3} {#4}
}
-\cs_new:Npn \@@_map_class_loop:Nnnnw #1#2#3#4 #5 .. #6 ,
+% \end{macrocode}
+% A generic loop-ahead setup: we need to handle both the previously collected
+% tokens and any \enquote{conditional} ones. The latter occur when looking
+% ahead for word-breaking: these \emph{may} be combined with the collected
+% tokens, but if we hit the end-of-loop, need to be output separately.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_lookahead:Nnnnnw #1#2#3#4#5#6 \q_@@_recursion_stop
{
- \@@_if_q_recursion_tail_stop_do:nn {#5}
- { \use:c { @@_map_not_ #4 :Nnn } #1 {#2} {#3} }
- \@@_codepoint_compare:nNnTF {#3} < { "#5 }
+ \tl_if_head_is_N_type:nTF {#6}
+ { \@@_map_lookahead:NnnnnN #1 {#2} {#3} {#4} {#5} }
+ { \@@_map_loop:Nnnw #1 {#2} {#3} #4 }
+ #6 \q_@@_recursion_stop
+ }
+\cs_new:Npn \@@_map_lookahead:NnnnnN #1#2#3#4#5#6
+ {
+ \@@_if_q_recursion_tail_stop_do:Nn #6
{
- \@@_map_class_end:nw
- { \use:c { @@_map_not_ #4 :Nnn } #1 {#2} {#3} }
+ #1 {#3}
+ \tl_if_blank:nF {#4} { #1 {#4} }
}
+ \token_if_cs:NTF #6
{
- \@@_codepoint_compare:nNnTF {#3} > { "#6 }
- { \@@_map_class_loop:Nnnnw #1 {#2} {#3} {#4} }
- {
- \@@_map_class_end:nw
- { \use:c { @@_map_ #4 :Nnn } #1 {#2} {#3} }
- }
+ #1 {#3}
+ \@@_map_loop:Nnnw #1 {#2} { } #4
}
+ { \@@_codepoint_process:nN { #5 #1 {#2} {#3} {#4} } }
+ #6
}
-\cs_new:Npn \@@_map_class_end:nw #1#2 \q_@@_recursion_stop {#1}
% \end{macrocode}
-% Break before \emph{and} after.
+% To deal with \enquote{ignored} characters for word break mapping: needed
+% for generic |Regional_Indicator| function, so set up here.
% \begin{macrocode}
-\cs_new:Npn \@@_map_Control:Nnn #1#2#3
+\prg_new_conditional:Npnn \@@_map_if_ignorable:n #1 { TF }
{
- \@@_map_output:Nn #1 {#2}
- \@@_map_output:Nn #1 {#3}
- \@@_map_loop:Nnw #1 { }
+ \str_case:nnTF {#1}
+ {
+ { Extend } { }
+ { Format } { }
+ { ZWJ } { }
+ }
+ \prg_return_true:
+ \prg_return_false:
}
% \end{macrocode}
-% Keep collecting.
+% For the end of the process.
% \begin{macrocode}
-\cs_new:Npn \@@_map_Extend:Nnn #1#2#3
- { \@@_map_loop:Nnw #1 {#2#3} }
-\cs_new_eq:NN \@@_map_SpacingMark:Nnn \@@_map_Extend:Nnn
+\cs_new:Npn \@@_map_output:Nn #1#2
+ { \tl_if_blank:nF {#2} { #1 {#2} } }
+\cs_new:Npn \text_map_break:
+ { \prg_map_break:Nn \text_map_break: { } }
+\cs_new:Npn \text_map_break:n
+ { \prg_map_break:Nn \text_map_break: }
% \end{macrocode}
-% Outputting anything earlier, the combine with what follows. The only
-% exclusions are control characters.
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+% {
+% \@@_map_Control:Nnnn ,
+% \@@_map_Newline:Nnnn ,
+% \@@_map_Extend:Nnnn ,
+% \@@_map_Format:Nnnn ,
+% \@@_map_SpacingMark:Nnnn ,
+% \@@_map_Other:Nnnn ,
+% \@@_map_Regional_Indicator:Nnnn
+% }
+% \begin{macro}[EXP]{\@@_map_Regional_Indicator_aux:Nnnnn}
+% A small number of classes appear in both forms of breaking and have the
+% same behavior. For |Control| and |Newline|, we set up here as they are the
+% same outcome. We have the same story for |Format|, which is functionally
+% the same as |Newline|.
% \begin{macrocode}
-\cs_new:Npn \@@_map_Prepend:Nnn #1#2#3
+\cs_new:Npn \@@_map_Control:Nnnn #1#2#3#4
{
- \@@_map_output:Nn #1 {#2}
- \@@_map_lookahead:NnNw #1 {#3} \@@_map_Prepend_aux:Nnn
+ \@@_map_output:Nn #1 {#3}
+ \@@_map_output:Nn #1 {#4}
+ \@@_map_loop:Nnnw #1 {#2} { }
}
-\cs_new:Npn \@@_map_Prepend_aux:Nnn #1#2#3
+\cs_new_eq:NN \@@_map_Newline:Nnnn \@@_map_Control:Nnnn
+\cs_new:Npn \@@_map_Extend:Nnnn #1#2#3#4
+ { \@@_map_loop:Nnnw #1 {#2} {#3#4} }
+\cs_new_eq:NN \@@_map_Format:Nnnn \@@_map_Extend:Nnnn
+\cs_new_eq:NN \@@_map_SpacingMark:Nnnn \@@_map_Extend:Nnnn
+\cs_new:Npn \@@_map_Other:Nnnn #1#2#3#4
{
- \bool_lazy_or:nnTF
- { \@@_codepoint_compare_p:nNn {#3} = { "0A } }
- { \@@_codepoint_compare_p:nNn {#3} = { "0D } }
- {
- #1 {#2}
- \@@_map_loop:Nnw #1 {#3}
- }
- {
- \exp_args:NV \@@_map_Prepend:nNnn
- \c_@@_grapheme_Control_clist
- #1 {#2} {#3}
- }
+ \@@_map_output:Nn #1 {#3}
+ \@@_map_loop:Nnnw #1 {#2} {#4}
}
-\cs_new:Npn \@@_map_Prepend:nNnn #1#2#3#4
+% \end{macrocode}
+% The Regional Indicator rule means looking ahead and dealing with the
+% case where there are two in a row. So we use a look ahead to pick them
+% off. As there is only one range the values are hard-coded. For
+% word breaking, we also need to allow for the various extenders.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_Regional_Indicator:Nnnn #1#2#3#4
{
- \@@_map_Prepend_loop:Nnnw #2 {#3} {#4}
- #1 , \q_@@_recursion_tail .. , \q_@@_recursion_stop
+ \@@_map_output:Nn #1 {#3}
+ \@@_map_lookahead:Nnnnnw #1 {#2} {#4} { }
+ \@@_map_Regional_Indicator_aux:Nnnnn
}
-\cs_new:Npn \@@_map_Prepend_loop:Nnnw #1#2#3 #4 .. #5 ,
+\cs_new:Npn \@@_map_Regional_Indicator_aux:Nnnnn #1#2#3#4#5
{
- \@@_if_q_recursion_tail_stop_do:nn {#4}
- { \@@_map_loop:Nnw #1 {#2#3} }
- \@@_codepoint_compare:nNnTF {#3} < { "#4 }
+ \bool_lazy_or:nnTF
+ { \@@_codepoint_compare_p:nNn {#5} < { "1F1E6 } }
+ { \@@_codepoint_compare_p:nNn {#5} > { "1F1FF } }
{
- \@@_map_class_end:nw
- { \@@_map_loop:Nnw #1 {#2#3} }
- }
- {
- \@@_codepoint_compare:nNnTF {#3} > { "#5 }
- { \@@_map_Prepend_loop:Nnnw #1 {#2} {#3} }
+ \str_if_eq:nnTF {#2} { wordbreak }
{
- \@@_map_class_end:nw
- { \@@_map_loop:Nnw #1 {#2} #3 }
+ \exp_args:Ne \@@_map_if_ignorable:nTF
+ {
+ \__kernel_codepoint_to_grapheme_class:n
+ { \@@_codepoint_from_chars:Nw #5 }
+ }
+ {
+ \@@_map_lookahead:Nnnnnw #1 {#2} {#3#5} { }
+ \@@_map_Regional_Indicator_aux:Nnnnn
+ }
+ { \@@_map_loop:Nnnw #1 {#2} {#3} #5 }
}
+ { \@@_map_loop:Nnnw #1 {#2} {#3} #5 }
}
+ { \@@_map_loop:Nnnw #1 {#2} {#3#5} }
}
% \end{macrocode}
-% Dealing with end-of-class is done such that we can be flexible.
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Grapheme mapping}
+%
+% \begin{macro}[EXP]{\text_map_function:nN}
+% \begin{macro}[EXP]{\@@_map_Prepend:Nnnn}
+% \begin{macro}[EXP]{\@@_map_Prepend_aux:Nnnnn}
+% \begin{macro}[EXP]{\@@_map_Prepend:Nnn}
+% \begin{macro}[EXP]
+% {
+% \@@_map_L:Nnnn ,
+% \@@_map_LV:Nnnn ,
+% \@@_map_V:Nnnn ,
+% \@@_map_LVT:Nnnn ,
+% \@@_map_T:Nnnn
+% }
+% \begin{macro}[EXP]{\@@_map_hangul:Nnnw}
+% \begin{macro}[EXP]{\@@_map_hangul:NnnN}
+% \begin{macro}[EXP]{\@@_map_hangul:Nnnn}
+% \begin{macro}[EXP]{\@@_map_hangul_aux:Nnnnw}
+% \begin{macro}[EXP]{\@@_map_hangul:Nnnnw}
+% \begin{macro}[EXP]{\@@_map_hangul_next:Nnnnn}
+% \begin{macro}[EXP]{\@@_map_hangul_end:nw}
+% \begin{macro}[EXP]
+% {
+% \@@_map_hangul_L:Nnn ,
+% \@@_map_hangul_LV:Nnn ,
+% \@@_map_hangul_V:Nnn ,
+% \@@_map_hangul_LVT:Nnn ,
+% \@@_map_hangul_T:Nnn
+% }
+% The standard lead-off for an action loop.
% \begin{macrocode}
-\cs_new:Npn \@@_map_not_Control:Nnn #1#2#3
- { \@@_map_class:Nnnn #1 {#2} {#3} { Extend } }
-\cs_new:Npn \@@_map_not_Extend:Nnn #1#2#3
- { \@@_map_class:Nnnn #1 {#2} {#3} { SpacingMark } }
-\cs_new:Npn \@@_map_not_SpacingMark:Nnn #1#2#3
- { \@@_map_class:Nnnn #1 {#2} {#3} { Prepend } }
-\cs_new:Npn \@@_map_not_Prepend:Nnn #1#2#3
- { \@@_map_class:Nnnn #1 {#2} {#3} { L } }
-\cs_new:Npn \@@_map_not_L:Nnn #1#2#3
- { \@@_map_class:Nnnn #1 {#2} {#3} { LV } }
-\cs_new:Npn \@@_map_not_LV:Nnn #1#2#3
- { \@@_map_class:Nnnn #1 {#2} {#3} { V } }
-\cs_new:Npn \@@_map_not_V:Nnn #1#2#3
- { \@@_map_class:Nnnn #1 {#2} {#3} { LVT } }
-\cs_new:Npn \@@_map_not_LVT:Nnn #1#2#3
- { \@@_map_class:Nnnn #1 {#2} {#3} { T } }
-\cs_new:Npn \@@_map_not_T:Nnn #1#2#3
- { \@@_map_class:Nnnn #1 {#2} {#3} { Regional_Indicator } }
-\cs_new:Npn \@@_map_not_Regional_Indicator:Nnn #1#2#3
+\cs_new:Npn \text_map_function:nN #1#2
{
- \@@_map_output:Nn #1 {#2}
- \@@_map_loop:Nnw #1 {#3}
+ \@@_map_function:enN { \text_expand:n {#1} }
+ { grapheme } #2
}
% \end{macrocode}
+% Outputting anything earlier, the combine with what follows. The only
+% exclusions are control characters.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_Prepend:Nnnn #1#2#3#4
+ {
+ \@@_map_output:Nn #1 {#3}
+ \@@_map_lookahead:Nnnnnw #1 { grapheme } {#4} { }
+ \@@_map_Prepend_aux:Nnnnn
+ }
+\cs_new:Npn \@@_map_Prepend_aux:Nnnnn #1#2#3#4#5
+ {
+ \bool_lazy_or:nnTF
+ { \@@_codepoint_compare_p:nNn {#5} = { "000A } }
+ { \@@_codepoint_compare_p:nNn {#5} = { "000D } }
+ {
+ #1 {#3}
+ \@@_map_loop:Nnnw #1 { grapheme } {#5}
+ }
+ { \@@_map_Prepend:Nnn #1 {#3} {#5} }
+ }
+\cs_new:Npn \@@_map_Prepend:Nnn #1#2#3
+ {
+ \str_if_eq:eeTF
+ { Control }
+ {
+ \__kernel_codepoint_to_grapheme_class:n
+ { \@@_codepoint_from_chars:Nw #3 }
+ }
+ { \@@_map_loop:Nnnw #1 { grapheme } {#2} #3 }
+ { \@@_map_loop:Nnnw #1 { grapheme } {#2#3} }
+ }
+% \end{macrocode}
% Hangul needs additional treatment. First we have to deal with
% the start-of-Hangul position: output what we had up to now, then
% move the specialist handler. The idea here is to pick off the
@@ -374,26 +431,26 @@
% Other than that, we just keep building up the Hangul codepoints
% using a dedicated version of the loop from above.
% \begin{macrocode}
-\cs_new:Npn \@@_map_L:Nnn #1#2#3
+\cs_new:Npn \@@_map_L:Nnnn #1#2#3#4
{
- \@@_map_output:Nn #1 {#2}
+ \@@_map_output:Nn #1 {#3}
\@@_map_hangul:Nnnw
- #1 {#3} { L ; V ; LV ; LVT }
+ #1 {#4} { L ; V ; LV ; LVT }
}
-\cs_new:Npn \@@_map_LV:Nnn #1#2#3
+\cs_new:Npn \@@_map_LV:Nnnn #1#2#3#4
{
- \@@_map_output:Nn #1 {#2}
+ \@@_map_output:Nn #1 {#3}
\@@_map_hangul:Nnnw
- #1 {#3} { V ; T }
+ #1 {#4} { V ; T }
}
-\cs_new_eq:NN \@@_map_V:Nnn \@@_map_LV:Nnn
-\cs_new:Npn \@@_map_LVT:Nnn #1#2#3
+\cs_new_eq:NN \@@_map_V:Nnnn \@@_map_LV:Nnnn
+\cs_new:Npn \@@_map_LVT:Nnnn #1#2#3#4
{
- \@@_map_output:Nn #1 {#2}
+ \@@_map_output:Nn #1 {#3}
\@@_map_hangul:Nnnw
- #1 {#3} { T }
+ #1 {#4} { T }
}
-\cs_new_eq:NN \@@_map_T:Nnn \@@_map_LVT:Nnn
+\cs_new_eq:NN \@@_map_T:Nnnn \@@_map_LVT:Nnnn
\cs_new:Npn \@@_map_hangul:Nnnw #1#2#3#4 \q_@@_recursion_stop
{
\tl_if_head_is_N_type:nTF {#4}
@@ -400,7 +457,7 @@
{ \@@_map_hangul:NnnN #1 {#2} {#3} }
{
#1 {#2}
- \@@_map_loop:Nnw #1 { }
+ \@@_map_loop:Nnnw #1 { grapheme } { }
}
#4 \q_@@_recursion_stop
}
@@ -414,7 +471,7 @@
\token_if_cs:NTF #4
{
#1 {#2}
- \@@_map_loop:Nnw #1 { }
+ \@@_map_loop:Nnnw #1 { grapheme } { }
}
{
\@@_codepoint_process:nN
@@ -421,43 +478,31 @@
{ \@@_map_hangul:Nnnn #1 {#2} {#3} } #4
}
}
+\exp_args_generate:n { Nnne }
\cs_new:Npn \@@_map_hangul:Nnnn #1#2#3#4
{
- \@@_map_hangul_aux:Nnnw #1 {#2} {#4}
+ \exp_args:NNnne \@@_map_hangul_aux:Nnnnw #1 {#2} {#4}
+ {
+ \__kernel_codepoint_to_grapheme_class:n
+ { \@@_codepoint_from_chars:Nw #4 }
+ }
#3 ; \q_recursion_tail ; \q_recursion_stop
}
-\cs_new:Npn \@@_map_hangul_aux:Nnnw #1#2#3#4 ;
+\cs_new:Npn \@@_map_hangul_aux:Nnnnw #1#2#3#4#5 ;
{
- \quark_if_recursion_tail_stop_do:nn {#4}
- { \@@_map_loop:Nnw #1 {#2} #3 }
- \exp_args:Nv \@@_map_hangul:nNnnnw { c_@@_grapheme_ #4 _clist }
- #1 {#2} {#3} {#4}
+ \quark_if_recursion_tail_stop_do:nn {#5}
+ { \@@_map_loop:Nnnw #1 { grapheme } {#2} #3 }
+ \@@_map_hangul:Nnnnnw #1 {#2} {#3} {#4} {#5}
}
-\cs_new:Npn \@@_map_hangul:nNnnnw #1#2#3#4#5#6 \q_recursion_stop
+\cs_generate_variant:Nn \@@_map_hangul_aux:Nnnnw { Nnne }
+\cs_new:Npn \@@_map_hangul:Nnnnnw #1#2#3#4#5#6 \q_recursion_stop
{
- \@@_map_hangul_loop:Nnnnnw #2 {#3} {#4} {#5} {#6}
- #1 , \q_@@_recursion_tail .. , \q_@@_recursion_stop
+ \str_if_eq:nnTF {#4} {#5}
+ { \use:c { @@_map_hangul_ #5 :Nnn } #1 {#2} {#3} }
+ { \@@_map_hangul_next:Nnnnn #1 {#2} {#3} {#4} {#6} }
}
-\cs_new:Npn \@@_map_hangul_loop:Nnnnnw #1#2#3#4#5 #6 .. #7 ,
- {
- \@@_if_q_recursion_tail_stop_do:nn {#6}
- { \@@_map_hangul_next:Nnnn #1 {#2} {#3} {#5} }
- \@@_codepoint_compare:nNnTF {#3} < { "#6 }
- {
- \@@_map_hangul_end:nw
- { \@@_map_hangul_next:Nnnn #1 {#2} {#3} {#5} }
- }
- {
- \@@_codepoint_compare:nNnTF {#3} > { "#7 }
- { \@@_map_hangul_loop:Nnnnnw #1 {#2} {#3} {#4} {#5} }
- {
- \@@_map_hangul_end:nw
- { \use:c { @@_map_hangul_ #4 :Nnn } #1 {#2} {#3} }
- }
- }
- }
-\cs_new:Npn \@@_map_hangul_next:Nnnn #1#2#3#4
- { \@@_map_hangul_aux:Nnnw #1 {#2} {#3} #4 \q_recursion_stop }
+\cs_new:Npn \@@_map_hangul_next:Nnnnn #1#2#3#4#5
+ { \@@_map_hangul_aux:Nnnnw #1 {#2} {#3} {#4} #5 \q_recursion_stop }
\cs_new:Npn \@@_map_hangul_end:nw #1#2 \q_@@_recursion_stop {#1}
\cs_new:Npn \@@_map_hangul_L:Nnn #1#2#3
{
@@ -477,56 +522,235 @@
}
\cs_new_eq:NN \@@_map_hangul_T:Nnn \@@_map_hangul_LVT:Nnn
% \end{macrocode}
-% The Regional Indicator rule means looking ahead and dealing with the
-% case where there are two in a row. So we use a look ahead to pick them
-% off. As there is only one range the values are hard-coded.
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Word break mapping}
+%
+% \begin{macro}[EXP]{\text_map_function:nN}
+% \begin{macro}[EXP]{\@@_map_collect:Nnnnn}
+% \begin{macro}[EXP]{\@@_map_collect_auxi:nnnNnnnn}
+% \begin{macro}[EXP]{\@@_map_collect_auxii:nNnnnnn}
+% \begin{macro}[EXP]{\@@_map_collect_auxiii:n}
+% \begin{macro}[EXP]{\@@_map_collect_auxiv:nnNnnnn}
+% \begin{macro}[EXP]{\@@_map_collect_auxv:nNnnnnn}
+% \begin{macro}[EXP]
+% {
+% \@@_map_ALetter:Nnnn ,
+% \@@_map_Hebrew_Letter:Nnnn ,
+% \@@_map_Katakana:Nnnn ,
+% \@@_map_Numeric:Nnnn ,
+% \@@_map_WSegSpace:Nnnn ,
+% \@@_map_ExtendNumLet:Nnnn
+% }
+% \begin{macro}[EXP]{\@@_map_ExtendNumLet_auxi::Nnnnn}
+% \begin{macro}[EXP]{\@@_map_ExtendNumLet_auxii:nNnn}
+% The standard lead-off for an action loop.
% \begin{macrocode}
-\cs_new:Npn \@@_map_Regional_Indicator:Nnn #1#2#3
+\cs_new:Npn \text_words_map_function:nN #1#2
{
- \@@_map_output:Nn #1 {#2}
- \@@_map_lookahead:NnNw #1 {#3} \@@_map_Regional_Indicator_aux:Nnn
+ \@@_map_function:enN { \text_expand:n {#1} }
+ { wordbreak } #2
}
-\cs_new:Npn \@@_map_Regional_Indicator_aux:Nnn #1#2#3
+% \end{macrocode}
+% The main rule for word breaking is that characters bind to following
+% ones, potentially either allowing for \emph{or} totally ignoring
+% intervening ones. For each class, we are passed a list of classes that
+% bind and ones that we should allow in between. In all cases, the classes
+% |Extend|, |Format| and |ZWJ| need to be entirely ignored: they are hard
+% coded and handled separately from the in-between ones. Notice that we use
+% \cs{str_case:nnTF} to make our boolean here: that way, all that needs to be
+% passed internally are lists of classes.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_collect:Nnnnn #1#2#3#4#5
{
- \bool_lazy_or:nnTF
- { \@@_codepoint_compare_p:nNn {#3} < { "1F1E6 } }
- { \@@_codepoint_compare_p:nNn {#3} > { "1F1FF } }
+ \@@_map_lookahead:Nnnnnw #1 { wordbreak } {#2} { }
+ { \@@_map_collect_auxi:nnnNnnnn {#3} {#4} {#5} }
+ }
+\cs_new:Npn \@@_map_collect_auxi:nnnNnnnn #1#2#3#4#5#6#7#8
+ {
+ \exp_args:Ne \@@_map_collect_auxii:nNnnnnn
{
- \@@_map_loop:Nnw #1 {#2} #3
+ \__kernel_codepoint_to_wordbreak_class:n
+ { \@@_codepoint_from_chars:Nw #8 }
}
- { \@@_map_loop:Nnw #1 {#2#3} }
+ #4 {#6} {#1} {#2} {#3} {#8}
}
% \end{macrocode}
-% A generic loop-ahead setup.
+% We now need to deal with the three possible positive outcomes of examining
+% the next character. The first is that we have found one of the binding
+% characters that ends the current cycle: we then pass on to the appropriate
+% function. Second, we have the ignored characters: if we find these, we
+% loop back around. Finally, we look at the \enquote{in-between} characters:
+% if one is found, we need a further look ahead to reach a decision. Rather
+% than have extra complexity in the setup, we have a hard-coded skipping of
+% |ExtendNumLet| for |WSegSpace| (as |ExtendNumLet| only applies to
+% |ALetter|, |Hebrew_Letter|, |Numeric| and |Katakana|).
% \begin{macrocode}
-\cs_new:Npn \@@_map_lookahead:NnNw #1#2#3#4 \q_@@_recursion_stop
+\cs_new:Npn \@@_map_collect_auxii:nNnnnnn #1#2#3#4#5#6#7
{
- \tl_if_head_is_N_type:nTF {#4}
- { \@@_map_lookahead:NnNN #1 {#2} #3 }
- { \@@_map_loop:Nnw #1 {#2} }
- #4 \q_@@_recursion_stop
+ \str_case:neTF {#1}
+ {
+ \tl_map_function:eN
+ {
+ #4
+ \str_if_eq:nnF {#4} { { WSegSpace } } { { ExtendNumLet } }
+ }
+ \@@_map_collect_auxiii:n
+ }
+ {
+ \cs_if_exist_use:cF { @@_map_ #1 :Nnnn }
+ { \@@_map_Other:Nnnn }
+ #2 { wordbreak } { } {#3#7}
+ }
+ {
+ \@@_map_if_ignorable:nTF {#1}
+ { \@@_map_collect:Nnnnn #2 {#3#7} {#4} {#5} {#6} }
+ {
+ \str_case:neTF {#1}
+ { \tl_map_function:nN {#5} \@@_map_collect_auxiii:n }
+ {
+ \@@_map_lookahead:Nnnnnw #2 { wordbreak } {#3} {#7}
+ { \@@_map_collect_auxiv:nnNnnnn {#5} {#6} }
+ }
+ {
+ \@@_map_output:Nn #2 {#3}
+ \@@_map_loop:Nnnw #2 { wordbreak } { } #7
+ }
+ }
+ }
}
-\cs_new:Npn \@@_map_lookahead:NnNN #1#2#3#4
+\cs_new:Npn \@@_map_collect_auxiii:n #1
+ { \exp_not:n { {#1} { } } }
+% \end{macrocode}
+% We are now have a character which \emph{may} bind to the previous one if
+% the next character is of the correct class also. So we carry forward the
+% collected material and the conditional character, then look ahead again.
+% If successful, combine together and move on using the new class, otherwise
+% output and restart where we were.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_collect_auxiv:nnNnnnn #1#2#3#4#5#6#7
{
- \@@_if_q_recursion_tail_stop_do:Nn #4 { #1 {#2} }
- \token_if_cs:NTF #4
+ \exp_args:Ne \@@_map_collect_auxv:nNnnnnn
{
- #1 {#2}
- \@@_map_loop:Nnw #1 { }
+ \__kernel_codepoint_to_wordbreak_class:n
+ { \@@_codepoint_from_chars:Nw #7 }
}
- { \@@_codepoint_process:nN { #3 #1 {#2} } }
- #4
+ #3 {#5} {#6} {#1} {#2} {#7}
}
+\cs_new:Npn \@@_map_collect_auxv:nNnnnnn #1#2#3#4#5#6#7
+ {
+ \str_case:neTF {#1}
+ { \tl_map_function:nN {#6} \@@_map_collect_auxiii:n }
+ { \use:c { @@_map_ #1 :Nnnn } #2 { wordbreak } { } {#3#4#7} }
+ {
+ \@@_map_if_ignorable:nTF {#1}
+ {
+ \@@_map_lookahead:Nnnnnw #2 { wordbreak } {#3} {#4#7}
+ { \@@_map_collect_auxiv:nnNnnnn {#5} {#6} }
+ }
+ {
+ \@@_map_output:Nn #2 {#3}
+ \@@_map_loop:Nnnw #2 { wordbreak } { } #4#7
+ }
+ }
+ }
% \end{macrocode}
-% For the end of the process.
+% Use the generic collector.
% \begin{macrocode}
-\cs_new:Npn \@@_map_output:Nn #1#2
- { \tl_if_blank:nF {#2} { #1 {#2} } }
-\cs_new:Npn \text_map_break:
- { \prg_map_break:Nn \text_map_break: { } }
-\cs_new:Npn \text_map_break:n
- { \prg_map_break:Nn \text_map_break: }
+\cs_new:Npn \@@_map_ALetter:Nnnn #1#2#3#4
+ {
+ \@@_map_output:Nn #1 {#3}
+ \@@_map_collect:Nnnnn #1 {#4}
+ { { ALetter } { Hebrew_Letter } { Numeric } }
+ { { MidLetter } { MidNumLet } { Single_Quote } }
+ { { ALetter } { Hebrew_Letter } }
+ }
+\cs_new:Npn \@@_map_Hebrew_Letter:Nnnn #1#2#3#4
+ {
+ \@@_map_output:Nn #1 {#3}
+ \@@_map_collect:Nnnnn #1 {#4}
+ { { ALetter } { Hebrew_Letter } { Numeric } { Single_Quote } }
+ { { MidLetter } { MidNumLet } { Double_Quote } }
+ { { Hebrew_Letter } }
+ }
+\cs_new:Npn \@@_map_Katakana:Nnnn #1#2#3#4
+ {
+ \@@_map_output:Nn #1 {#3}
+ \@@_map_collect:Nnnnn #1 {#4} { { Katakana } } { } { }
+ }
+\cs_new:Npn \@@_map_Numeric:Nnnn #1#2#3#4
+ {
+ \@@_map_output:Nn #1 {#3}
+ \@@_map_collect:Nnnnn #1 {#4}
+ { { ALetter } { Hebrew_Letter } { Numeric } }
+ { { MidNum } { MidNumLet } { Single_Quote } }
+ { { Numeric } }
+ }
+\cs_new:Npn \@@_map_WSegSpace:Nnnn #1#2#3#4
+ {
+ \@@_map_output:Nn #1 {#3}
+ \@@_map_collect:Nnnnn #1 {#4} { { WSegSpace } } { } { }
+ }
% \end{macrocode}
+% We should only get here in the case we have a \enquote{dangling} extender.
+% If so, look ahead for characters to bind to, then for the set of three
+% that we need to skip over.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_ExtendNumLet:Nnnn #1#2#3#4
+ {
+ \@@_map_output:Nn #1 {#3}
+ \@@_map_lookahead:Nnnnnw #1 { wordbreak } {#4} { }
+ \@@_map_ExtendNumLet_auxi:Nnnnn
+ }
+\cs_new:Npn \@@_map_ExtendNumLet_auxi:Nnnnn #1#2#3#4#5
+ {
+ \exp_args:Ne \@@_map_ExtendNumLet_auxii:nNnn
+ {
+ \__kernel_codepoint_to_wordbreak_class:n
+ { \@@_codepoint_from_chars:Nw #5 }
+ }
+ #1 {#3} {#5}
+ }
+\cs_new:Npn \@@_map_ExtendNumLet_auxii:nNnn #1#2#3#4
+ {
+ \str_case:nnTF {#1}
+ {
+ { ALetter } { }
+ { Hebrew_Letter } { }
+ { Numeric } { }
+ { Katakana } { }
+ { ExtendNumLet } { }
+ }
+ {
+ \cs_if_exist_use:cF { @@_map_ #1 :Nnnn } % TEMP?
+ { \@@_map_Other:Nnnn }
+ #2 { wordbreak } { } {#3#4}
+ }
+ {
+ \@@_map_if_ignorable:nTF {#1}
+ {
+ \@@_map_lookahead:Nnnnnw #2 { wordbreak } {#3#4} { }
+ \@@_map_ExtendNumLet_auxi:Nnnnn
+ }
+ {
+ \@@_map_output:Nn #2 {#3}
+ \@@_map_loop:Nnnw #2 { wordbreak } { } #4
+ }
+ }
+ }
+% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
@@ -537,31 +761,10 @@
% \end{macro}
% \end{macro}
% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
%
-% \begin{macro}{\text_map_inline:nn}
+% \subsection{Inline mappings}
+%
+% \begin{macro}{\text_map_inline:nn, \text_words_map_inline:nn}
% The standard non-expandable inline version.
% \begin{macrocode}
\cs_new_protected:Npn \text_map_inline:nn #1#2
@@ -574,6 +777,16 @@
\prg_break_point:Nn \text_map_break:
{ \int_gdecr:N \g__kernel_prg_map_int }
}
+\cs_new_protected:Npn \text_words_map_inline:nn #1#2
+ {
+ \int_gincr:N \g__kernel_prg_map_int
+ \cs_gset_protected:cpn
+ { @@_map_ \int_use:N \g__kernel_prg_map_int :w } ##1 {#2}
+ \exp_args:Nnc \text_words_map_function:nN {#1}
+ { @@_map_ \int_use:N \g__kernel_prg_map_int :w }
+ \prg_break_point:Nn \text_map_break:
+ { \int_gdecr:N \g__kernel_prg_map_int }
+ }
% \end{macrocode}
% \end{macro}
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -296,26 +296,28 @@
% \texttt{true}.
% \end{variable}
%
-% \section{Mapping to graphemes}
+% \section{Mapping to text}
%
% Grapheme splitting is implemented using the algorithm described in Unicode
% Standard Annex \#29. This includes support for extended grapheme clusters.
-% Text starting with a line feed or carriage return character will drop this
-% due to standard \TeX{} processing. At present extended pictograms are
-% not supported: these may be added in a future release.
+% Leading line feeds or carriage returns will be dropped due to standard
+% \TeX{} processing. At present extended pictograms are
+% not supported: these may be added in a future release. Some aspects of Indic
+% grapheme breaking, introduced in Unicode~15, are also currently absent.
%
% \begin{function}[rEXP, added = 2022-08-04]{\text_map_function:nN}
% \begin{syntax}
% \cs{text_map_function:nN} \Arg{text} \meta{function}
% \end{syntax}
-% Takes user input \meta{text} and expands as described for
-% \cs{text_expand:n}, then maps over the \emph{graphemes} within the
+% This takes the user input in \meta{text} and expands it as with
+% \cs{text_expand:n}; it then maps over the \emph{graphemes} within the
% result, passing each grapheme to the \meta{function}.
% Broadly a grapheme is a \enquote{user perceived character}:
% the Unicode Consortium describe the decomposition of input to
% graphemes in depth, and the approach used here implements that
-% algorithm. The \meta{function} should accept one argument as \meta{balanced
-% text}: this may be comprise codepoints or may be a control sequence.
+% algorithm. The \meta{function} should accept one argument as
+% \meta{balanced text}: this may comprise codepoints or it may be a
+% control sequence.
% With $8$-bit engines, the codepoint(s) themselves may of course be
% made up of multiple bytes: the mapping will pass the correct codepoints
% independent of the engine in use.
@@ -326,15 +328,15 @@
% \begin{syntax}
% \cs{text_map_inline:nn} \Arg{text} \Arg{inline function}
% \end{syntax}
-% Takes user input \meta{text} and expands as described for
-% \cs{text_expand:n}, then maps over the \emph{graphemes} within the
+% This takes the user input in \meta{text} and expands it as with
+% \cs{text_expand:n}; it then maps over the \emph{graphemes} within the
% result, passing each grapheme to the \meta{inline function}.
% Broadly a grapheme is a \enquote{user perceived character}:
% the Unicode Consortium describe the decomposition of input to
% graphemes in depth, and the approach used here implements that
% algorithm. The \meta{inline function} should consist of code which
-% receives the grapheme as \meta{balanced
-% text}: this may be comprise codepoints or may be a control sequence.
+% receives the grapheme as \meta{balanced text}: this may comprise
+% codepoints or it may be a control sequence.
% With $8$-bit engines, the codepoint(s) themselves may of course be
% made up of multiple bytes: the mapping will pass the correct codepoints
% independent of the engine in use.
@@ -341,6 +343,46 @@
% See also \cs{text_map_function:nN}.
% \end{function}
%
+% Word breaking is implemented using the standard algorithm described in Unicode
+% Standard Annex \#29. Leading line feeds or carriage returns will be dropped due
+% to standard \TeX{} processing. Spaces are always
+% considered a break even if immediately followed by an extending character.
+% At present extended pictograms are not supported: these may be added in a future
+% release. Language-based tailoring may be added in a future release: at present
+% the algorithm is exactly that described in the annex.
+%
+% \begin{function}[rEXP, added = 2025-02-12]{\text_words_map_function:nN}
+% \begin{syntax}
+% \cs{text_words_map_function:nN} \Arg{text} \meta{function}
+% \end{syntax}
+% This takes the user input in \meta{text} and expands it as with
+% \cs{text_expand:n}; it then maps over the \emph{words} within the
+% result, passing each word to the \meta{function}. Word boundaries are
+% determined using the standard algorithm described by the Unicode
+% Consortium. The \meta{function} should accept one argument as
+% \meta{balanced text}: this may comprise codepoints or it may be a
+% control sequence. With $8$-bit engines, the codepoint(s) themselves
+% may of course be made up of multiple bytes: the mapping will pass the
+% correct codepoints independent of the engine in use.
+% See also \cs{text_words_map_inline:nn}.
+% \end{function}
+%
+% \begin{function}[rEXP, added = 2025-02-12]{\text_words_map_inline:nn}
+% \begin{syntax}
+% \cs{text_words_map_inline:nn} \Arg{text} \Arg{inline function}
+% \end{syntax}
+% This takes the user input in \meta{text} and expands it as with
+% \cs{text_expand:n}; it then maps over the \emph{words} within the
+% result, passing each word to the \meta{function}. Word boundaries are
+% determined using the standard algorithm described by the Unicode
+% Consortium. The \meta{inline function} should consist of code that will
+% accept one argument as \meta{balanced text}: this may comprise codepoints
+% or it may be a control sequence. With $8$-bit engines, the codepoint(s)
+% themselves may of course be made up of multiple bytes: the mapping will
+% pass the correct codepoints independent of the engine in use.
+% See also \cs{text_words_map_function:nN}.
+% \end{function}
+%
% \begin{function}[rEXP, added = 2022-08-04]
% {\text_map_break:, \text_map_break:n}
% \begin{syntax}
@@ -347,7 +389,8 @@
% \cs{text_map_break:}
% \cs{text_map_break:n} \Arg{code}
% \end{syntax}
-% Used to terminate a \cs[no-index]{text_map_\ldots} function before all
+% Used to terminate a \cs[no-index]{text_map_\ldots} or
+% \cs[no-index]{text_words_map_\ldots} function before all
% entries in the \meta{text} have been processed. This
% normally takes place within a conditional statement.
% \end{function}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-build.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-build.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-build.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -655,8 +655,7 @@
% \begin{function}[added = 2011-07-09, updated = 2012-06-25, EXP]
% {
% \tl_trim_spaces:n, \tl_trim_spaces:V, \tl_trim_spaces:v,
-% \tl_trim_spaces:e,
-% \tl_trim_spaces:o
+% \tl_trim_spaces:e, \tl_trim_spaces:o,
% }
% \begin{syntax}
% \cs{tl_trim_spaces:n} \Arg{token list}
@@ -672,6 +671,28 @@
% \end{texnote}
% \end{function}
%
+% \begin{function}[added = 2025-02-02, EXP]
+% {
+% \tl_trim_left_spaces:n, \tl_trim_left_spaces:V, \tl_trim_left_spaces:v,
+% \tl_trim_left_spaces:e, \tl_trim_left_spaces:o,
+% \tl_trim_right_spaces:n, \tl_trim_right_spaces:V, \tl_trim_right_spaces:v,
+% \tl_trim_right_spaces:e, \tl_trim_right_spaces:o
+% }
+% \begin{syntax}
+% \cs{tl_trim_left_spaces:n} \Arg{token list}
+% \end{syntax}
+% Analogue of \cs{tl_trim_spaces:n} which removes any leading \emph{or}
+% trailing explicit space characters
+% (explicit tokens with character code~$32$ and category code~$10$)
+% from the \meta{token list} and leaves the result in the input
+% stream.
+% \begin{texnote}
+% The result is returned within \tn{unexpanded}, which means that the token
+% list does not expand further when appearing in an \texttt{e}-type
+% or \texttt{x}-type argument expansion.
+% \end{texnote}
+% \end{function}
+%
% \begin{function}[added = 2018-04-12, EXP]
% {\tl_trim_spaces_apply:nN, \tl_trim_spaces_apply:oN}
% \begin{syntax}
@@ -683,6 +704,21 @@
% \texttt{n}-type argument.
% \end{function}
%
+% \begin{function}[added = 2025-02-02, EXP]
+% {
+% \tl_trim_left_spaces_apply:nN, \tl_trim_left_spaces_apply:oN,
+% \tl_trim_right_spaces_apply:nN, \tl_trim_right_spaces_apply:oN
+% }
+% \begin{syntax}
+% \cs{tl_trim_left_spaces_apply:nN} \Arg{token list} \meta{function}
+% \end{syntax}
+% Analogue of \cs{tl_trim_spaces_apply:nN} which removes any leading
+% \emph{or} trailing explicit space characters (explicit
+% tokens with character code~$32$ and category code~$10$) from the
+% \meta{token list} and passes the result to the \meta{function} as an
+% \texttt{n}-type argument.
+% \end{function}
+%
% \begin{function}[added = 2011-07-09]
% {
% \tl_trim_spaces:N, \tl_trim_spaces:c,
@@ -696,6 +732,22 @@
% character code~$32$ and category code~$10$) from its contents.
% \end{function}
%
+% \begin{function}[added = 2025-02-02]
+% {
+% \tl_trim_left_spaces:N, \tl_trim_left_spaces:c,
+% \tl_trim_right_spaces:N, \tl_trim_right_spaces:c,
+% \tl_gtrim_left_spaces:N, \tl_gtrim_left_spaces:c,
+% \tl_gtrim_right_spaces:N, \tl_gtrim_right_spaces:c
+% }
+% \begin{syntax}
+% \cs{tl_trim_left_spaces:N} \meta{tl~var}
+% \end{syntax}
+% Analogue of \cs{tl_trim_spaces:N} which sets the \meta{tl~var} to
+% contain the result of removing any leading
+% \emph{or} trailing explicit space characters (explicit tokens with
+% character code~$32$ and category code~$10$) from its contents.
+% \end{function}
+%
% \subsection{Viewing token lists}
%
% \begin{function}[updated = 2021-04-29]{\tl_show:N, \tl_show:c}
@@ -757,7 +809,8 @@
% \texttt{n}-type arguments. See also \cs{tl_map_function:nN}.
% \end{function}
%
-% \begin{function}[updated = 2012-06-29, rEXP]{\tl_map_function:nN}
+% \begin{function}[updated = 2012-06-29, rEXP]
+% {\tl_map_function:nN, \tl_map_function:eN}
% \begin{syntax}
% \cs{tl_map_function:nN} \Arg{token list} \meta{function}
% \end{syntax}
@@ -890,7 +943,7 @@
% text or single normal token) in a token list, or the remaining tokens.
%
% \begin{function}[updated = 2012-09-09, EXP]
-% {\tl_head:N, \tl_head:n, \tl_head:V, \tl_head:v, \tl_head:f}
+% {\tl_head:N, \tl_head:n, \tl_head:V, \tl_head:v, \tl_head:f, \tl_head:e}
% \begin{syntax}
% \cs{tl_head:n} \Arg{token list}
% \end{syntax}
@@ -942,7 +995,7 @@
% \end{function}
%
% \begin{function}[updated = 2012-09-01, EXP]
-% {\tl_tail:N, \tl_tail:n, \tl_tail:V, \tl_tail:v, \tl_tail:f}
+% {\tl_tail:N, \tl_tail:n, \tl_tail:V, \tl_tail:v, \tl_tail:f, \tl_tail:e}
% \begin{syntax}
% \cs{tl_tail:n} \Arg{token list}
% \end{syntax}
@@ -1194,7 +1247,7 @@
% Searches for the \meta{regular expression} in the contents of the
% \meta{tl~var} and replaces the first match with the
% \meta{replacement}. In the \meta{replacement},
-% |\0| represents the full match, |\1| represent the contents of the
+% |\0| represents the full match, |\1| represents the contents of the
% first capturing group, |\2| of the second, \emph{etc.}
% Theses are alternative names for \cs{regex_replace_once:nnN} and friends,
% with arguments re-ordered for \meta{tl~var} setting;
@@ -2195,7 +2248,7 @@
% as our~\meta{A}. The argument~|#2| only serves to collect~|?|
% characters for~|#1|. Note that the order of the tests means that
% the first two are done every time, which is wasteful (for instance,
-% we repeatedly test for the emptyness of~|#6|). However, this is
+% we repeatedly test for the emptiness of~|#6|). However, this is
% rare enough not to matter. Finally, choose~\meta{B} to be
% \cs{q_@@_nil} or~\cs{q_@@_stop} such that it is not equal to~|#6|.
%
@@ -2493,7 +2546,7 @@
% \TeX{} skips spaces when reading a non-delimited arguments. Thus,
% a \meta{token list} is blank if and only if \cs{use_none:n}
% \meta{token list} |?| is empty after one expansion. The auxiliary
-% \cs{@@_if_empty_if:o} is a fast emptyness test, converting its
+% \cs{@@_if_empty_if:o} is a fast emptiness test, converting its
% argument to a string (after one expansion) and using the test
% \cs{if:w} \cs{scan_stop:} |...| \cs{scan_stop:}.
% \begin{macrocode}
@@ -2638,7 +2691,7 @@
% starts with |-NoValue-|, while the second argument is empty if |##1|
% is exactly |-NoValue-| or if it has a question mark just following
% |-NoValue-|. In this second case, however, the material after the
-% first |?!| remains and makes the emptyness test return
+% first |?!| remains and makes the emptiness test return
% \texttt{false}.
% \begin{macrocode}
\cs_set_protected:Npn \@@_tmp:w #1
@@ -2756,7 +2809,8 @@
%
% \begin{macro}
% {
-% \tl_map_function:nN, \tl_map_function:NN, \tl_map_function:cN,
+% \tl_map_function:nN, \tl_map_function:eN,
+% \tl_map_function:NN, \tl_map_function:cN,
% \@@_map_function:Nnnnnnnnn, \@@_map_function_end:w,
% \@@_use_none_delimit_by_s_stop:w
% }
@@ -2779,6 +2833,7 @@
\s_@@_stop \s_@@_stop \s_@@_stop \s_@@_stop
\prg_break_point:Nn \tl_map_break: { }
}
+\cs_generate_variant:Nn \tl_map_function:nN { e }
\cs_new:Npn \tl_map_function:NN
{ \exp_args:No \tl_map_function:nN }
\cs_generate_variant:Nn \tl_map_function:NN { c }
@@ -3014,18 +3069,30 @@
% \begin{macro}
% {
% \tl_trim_spaces:n, \tl_trim_spaces:V, \tl_trim_spaces:v,
-% \tl_trim_spaces:e,
-% \tl_trim_spaces:o,
+% \tl_trim_spaces:e, \tl_trim_spaces:o,
+% \tl_trim_left_spaces:n, \tl_trim_left_spaces:V, \tl_trim_left_spaces:v,
+% \tl_trim_left_spaces:e, \tl_trim_left_spaces:o,
+% \tl_trim_right_spaces:n, \tl_trim_right_spaces:V, \tl_trim_right_spaces:v,
+% \tl_trim_right_spaces:e, \tl_trim_right_spaces:o
% }
-% \begin{macro}{\tl_trim_spaces_apply:nN, \tl_trim_spaces_apply:oN}
% \begin{macro}
% {
+% \tl_trim_spaces_apply:nN, \tl_trim_spaces_apply:oN,
+% \tl_trim_left_spaces_apply:nN, \tl_trim_left_spaces_apply:oN,
+% \tl_trim_right_spaces_apply:nN, \tl_trim_right_spaces_apply:oN
+% }
+% \begin{macro}
+% {
% \tl_trim_spaces:N, \tl_trim_spaces:c,
-% \tl_gtrim_spaces:N, \tl_gtrim_spaces:c
+% \tl_trim_left_spaces:N, \tl_trim_left_spaces:c,
+% \tl_trim_right_spaces:N, \tl_trim_right_spaces:c,
+% \tl_gtrim_spaces:N, \tl_gtrim_spaces:c,
+% \tl_gtrim_left_spaces:N, \tl_gtrim_left_spaces:c,
+% \tl_gtrim_right_spaces:N, \tl_gtrim_right_spaces:c
% }
% Trimming spaces from around the input is deferred to an internal
-% function whose first argument is the token list to trim, augmented
-% by an initial \cs{@@_trim_mark:}, and whose second argument is a
+% function whose first argument is the token list to trim,
+% and whose second argument is a
% \meta{continuation}, which receives as a braced argument
% \cs{@@_trim_mark:} \meta{trimmed token list}. The control sequence
% \cs{@@_trim_mark:} expands to nothing in a single expansion. In the case
@@ -3033,31 +3100,56 @@
% continuation, so that space trimming behaves correctly within an
% \texttt{e}-type or \texttt{x}-type expansion.
% \begin{macrocode}
-\cs_new:Npn \tl_trim_spaces:n #1
- {
- \@@_trim_spaces:nn
- { \@@_trim_mark: #1 }
- { \__kernel_exp_not:w \exp_after:wN }
- }
-\cs_generate_variant:Nn \tl_trim_spaces:n { V , v , e , o }
+\cs_new:Npn \tl_trim_spaces:n
+ { \@@_trim_spaces:nn { \__kernel_exp_not:w \exp_after:wN } }
+\cs_new:Npn \tl_trim_left_spaces:n
+ { \@@_trim_left_spaces:nn { \__kernel_exp_not:w \exp_after:wN } }
+\cs_new:Npn \tl_trim_right_spaces:n
+ { \@@_trim_right_spaces:nn { \__kernel_exp_not:w \exp_after:wN } }
+\cs_generate_variant:Nn \tl_trim_spaces:n { V , v , e , o }
+\cs_generate_variant:Nn \tl_trim_left_spaces:n { V , v , e , o }
+\cs_generate_variant:Nn \tl_trim_right_spaces:n { V , v , e , o }
\cs_new:Npn \tl_trim_spaces_apply:nN #1#2
- { \@@_trim_spaces:nn { \@@_trim_mark: #1 } { \exp_args:No #2 } }
+ { \@@_trim_spaces:nn { \exp_args:No #2 } { #1 } }
+\cs_new:Npn \tl_trim_left_spaces_apply:nN #1#2
+ { \@@_trim_left_spaces:nn { \exp_args:No #2 } { #1 } }
+\cs_new:Npn \tl_trim_right_spaces_apply:nN #1#2
+ { \@@_trim_right_spaces:nn { \exp_args:No #2 } { #1 } }
\cs_generate_variant:Nn \tl_trim_spaces_apply:nN { o }
+\cs_generate_variant:Nn \tl_trim_left_spaces_apply:nN { o }
+\cs_generate_variant:Nn \tl_trim_right_spaces_apply:nN { o }
\cs_new_protected:Npn \tl_trim_spaces:N #1
{ \__kernel_tl_set:Nx #1 { \exp_args:No \tl_trim_spaces:n {#1} } }
+\cs_new_protected:Npn \tl_trim_left_spaces:N #1
+ { \__kernel_tl_set:Nx #1 { \exp_args:No \tl_trim_left_spaces:n {#1} } }
+\cs_new_protected:Npn \tl_trim_right_spaces:N #1
+ { \__kernel_tl_set:Nx #1 { \exp_args:No \tl_trim_right_spaces:n {#1} } }
\cs_new_protected:Npn \tl_gtrim_spaces:N #1
{ \__kernel_tl_gset:Nx #1 { \exp_args:No \tl_trim_spaces:n {#1} } }
+\cs_new_protected:Npn \tl_gtrim_left_spaces:N #1
+ { \__kernel_tl_gset:Nx #1 { \exp_args:No \tl_trim_left_spaces:n {#1} } }
+\cs_new_protected:Npn \tl_gtrim_right_spaces:N #1
+ { \__kernel_tl_gset:Nx #1 { \exp_args:No \tl_trim_right_spaces:n {#1} } }
\cs_generate_variant:Nn \tl_trim_spaces:N { c }
+\cs_generate_variant:Nn \tl_trim_left_spaces:N { c }
+\cs_generate_variant:Nn \tl_trim_right_spaces:N { c }
\cs_generate_variant:Nn \tl_gtrim_spaces:N { c }
+\cs_generate_variant:Nn \tl_gtrim_left_spaces:N { c }
+\cs_generate_variant:Nn \tl_gtrim_right_spaces:N { c }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\@@_trim_spaces:nn}
% \begin{macro}
% {
+% \@@_trim_spaces:nn,
+% \@@_trim_left_spaces:nn, \@@_trim_right_spaces:nn
+% }
+% \begin{macro}
+% {
% \@@_trim_spaces_auxi:w, \@@_trim_spaces_auxii:w,
-% \@@_trim_spaces_auxiii:w, \@@_trim_spaces_auxiv:w
+% \@@_trim_spaces_auxiii:w, \@@_trim_spaces_auxiv:w,
+% \@@_trim_spaces_auxv:w
% }
% \begin{macro}{\@@_trim_mark:}
% Trimming spaces from around the input is done using delimited
@@ -3069,50 +3161,72 @@
% list: then |##1| is the token list and |##3| is
% \cs{@@_trim_spaces_auxii:w}. This hands the relevant tokens to the
% loop \cs{@@_trim_spaces_auxiii:w}, responsible for trimming
-% trailing spaces. The end is reached when \verb*+ + \cs{s_@@_nil}
+% trailing spaces. The end is reached when \verb*+ +\cs{s_@@_nil}
% matches the one present in the definition of \cs{tl_trim_spaces:n}.
% Then \cs{@@_trim_spaces_auxiv:w} puts the token list into a group,
% with a lingering \cs{@@_trim_mark:} at the start (which will expand to
% nothing in one step of expansion), and feeds this to the
% \meta{continuation}.
+%
+% Trimming just leading spaces (see \cs{@@_trim_left_spaces:nn}) also
+% starts with \cs{@@_trim_spaces_auxi:w}, but when it loops until
+% \cs{@@_trim_mark:}\verb*+ + matches the end of the token list, |##1|
+% is the token list \emph{but} |##3| is \cs{@@_trim_spaces_auxv:w}.
+% Like \cs{@@_trim_spaces_auxiv:w}, this directly hands the relevant
+% tokens to the exit \meta{continuation}.
+% Trimming just trailing spaces (see \cs{@@_trim_right_spaces:nn})
+% starts with the (second) loop \cs{@@_trim_spaces_auxiii:w}.
% \begin{macrocode}
\cs_set_protected:Npn \@@_tmp:w #1
{
- \cs_new:Npn \@@_trim_spaces:nn ##1
+ \cs_new:Npn \@@_trim_spaces:nn ##1##2
{
\@@_trim_spaces_auxi:w
- ##1
- \s_@@_nil
- \@@_trim_mark: #1 { }
+ \@@_trim_mark: ##2 \s_@@_nil
+ \@@_trim_mark: \@@_trim_spaces_auxi:w
+ \@@_trim_mark: #1
\@@_trim_mark: \@@_trim_spaces_auxii:w
- \@@_trim_spaces_auxiii:w
- #1 \s_@@_nil
- \@@_trim_spaces_auxiv:w
- \s_@@_stop
+ {##1}
}
- \cs_new:Npn
- \@@_trim_spaces_auxi:w ##1 \@@_trim_mark: #1 ##2 \@@_trim_mark: ##3
+ \cs_new:Npn \@@_trim_left_spaces:nn ##1##2
{
- ##3
\@@_trim_spaces_auxi:w
- \@@_trim_mark:
- ##2
- \@@_trim_mark: #1 {##1}
+ \@@_trim_mark: ##2 \s_@@_nil
+ \@@_trim_mark: \@@_trim_spaces_auxi:w
+ \@@_trim_mark: #1
+ \@@_trim_mark: \@@_trim_spaces_auxv:w
+ {##1}
}
+ \cs_new:Npn \@@_trim_right_spaces:nn ##1##2
+ {
+ \@@_trim_spaces_auxiii:w
+ \@@_trim_mark: ##2 \s_@@_nil \@@_trim_spaces_auxiii:w
+ #1 \s_@@_nil \@@_trim_spaces_auxiv:w
+ {##1}
+ }
+ \cs_new:Npn \@@_trim_spaces_auxi:w
+ ##1 \@@_trim_mark: #1 ##2 \@@_trim_mark: ##3
+ { ##3 ##1 \@@_trim_mark: ##2 \@@_trim_mark: \@@_trim_spaces_auxi:w }
\cs_new:Npn \@@_trim_spaces_auxii:w
- \@@_trim_spaces_auxi:w \@@_trim_mark: \@@_trim_mark: ##1
+ \@@_trim_mark: ##1 \@@_trim_mark: ##2 \@@_trim_spaces_auxi:w
+ \@@_trim_mark: \@@_trim_mark: \@@_trim_spaces_auxi:w
{
\@@_trim_spaces_auxiii:w
- ##1
+ \@@_trim_mark: ##1 \@@_trim_spaces_auxiii:w
+ #1 \s_@@_nil \@@_trim_spaces_auxiv:w
}
\cs_new:Npn \@@_trim_spaces_auxiii:w ##1 #1 \s_@@_nil ##2
- {
+ { ##2 ##1 \s_@@_nil \@@_trim_spaces_auxiii:w }
+ \cs_new:Npn \@@_trim_spaces_auxiv:w
+ ##1 \s_@@_nil
+ \@@_trim_spaces_auxiii:w \s_@@_nil \@@_trim_spaces_auxiii:w
##2
+ { ##2 {##1} }
+ \cs_new:Npn \@@_trim_spaces_auxv:w
##1 \s_@@_nil
- \@@_trim_spaces_auxiii:w
- }
- \cs_new:Npn \@@_trim_spaces_auxiv:w ##1 \s_@@_nil ##2 \s_@@_stop ##3
- { ##3 { ##1 } }
+ \@@_trim_mark: \@@_trim_spaces_auxi:w \@@_trim_mark:
+ \@@_trim_mark: \@@_trim_spaces_auxi:w ##2
+ { ##2 {##1} }
\cs_new:Npn \@@_trim_mark: {}
}
\@@_tmp:w { ~ }
@@ -3129,10 +3243,10 @@
%
% \subsection{The first token from a token list}
%
-% \begin{macro}{\tl_head:N, \tl_head:n, \tl_head:V, \tl_head:v, \tl_head:f}
+% \begin{macro}{\tl_head:N, \tl_head:n, \tl_head:V, \tl_head:v, \tl_head:f, \tl_head:e}
% \begin{macro}{\@@_head_auxi:nw, \@@_head_auxii:n}
% \begin{macro}{\tl_head:w,\@@_tl_head:w}
-% \begin{macro}{\tl_tail:N, \tl_tail:n, \tl_tail:V, \tl_tail:v, \tl_tail:f}
+% \begin{macro}{\tl_tail:N, \tl_tail:n, \tl_tail:V, \tl_tail:v, \tl_tail:f, \tl_tail:e}
% Finding the head of a token list expandably always strips braces, which
% is fine as this is consistent with for example mapping over a list. The
% empty brace groups in \cs{tl_head:n} ensure that a blank argument gives an
@@ -3152,7 +3266,7 @@
\__kernel_exp_not:w {#1}
\exp_after:wN \use_none:n \exp_after:wN { \if_false: } \fi:
}
-\cs_generate_variant:Nn \tl_head:n { V , v , f }
+\cs_generate_variant:Nn \tl_head:n { V , v , f , e }
\cs_new:Npn \tl_head:w #1#2 \q_stop {#1}
\cs_new:Npn \@@_tl_head:w #1#2 \s_@@_stop {#1}
\cs_new:Npn \tl_head:N { \exp_args:No \tl_head:n }
@@ -3179,7 +3293,7 @@
{ { } }
{ \exp_after:wN { \use_none:n #1 } }
}
-\cs_generate_variant:Nn \tl_tail:n { V , v , f }
+\cs_generate_variant:Nn \tl_tail:n { V , v , f , e }
\cs_new:Npn \tl_tail:N { \exp_args:No \tl_tail:n }
% \end{macrocode}
% \end{macro}
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2025-01-18}
+% \date{Released 2025-03-26}
%
% \maketitle
%
@@ -485,38 +485,42 @@
%
% Notice that in the standard \pkg{expl3} way we are indexes position not
% offset: that does mean a little work later.
+%
+% For integer values, everything is done using token lists to avoid loosing
+% registers or making global names.
% \begin{macrocode}
\group_begin:
\clist_map_inline:nn
- { category , uppercase , lowercase }
+ { category , grapheme , lowercase , uppercase , wordbreak }
{
\cs_set_nopar:cpn { l_@@_ #1 _block_clist } { }
\cs_set_nopar:cpn { l_@@_ #1 _block_tl } { 1 }
\cs_set_nopar:cpn { l_@@_ #1 _pos_tl } { 0 }
+ \cs_set_nopar:cpn { l_@@_ #1 _next_tl } { 0 }
\intarray_new:cn { g_@@_ #1 _index_intarray }
{ \int_div_truncate:nn { "110000 } \c_@@_block_size_int }
}
% \end{macrocode}
-% We need an integer value when matching the current block to those we have
-% already seen, and a way to track codepoints for handling ranges. Again,
-% we avoid using up registers or creating global names.
+% We also need to track the matched block: this is used dynamically so we
+% only require one variable.
% \begin{macrocode}
- \cs_set_nopar:Npn \l_@@_next_codepoint_fint_tl { 0 }
\cs_set_nopar:Npn \l_@@_matched_block_tl { 0 }
% \end{macrocode}
-% For Unicode general category, there needs to be numerical representation of
-% each possible value. As we need to go from string to number here, but the
-% other way elsewhere, we set up fast mappings both ways, but one set local
-% and the other as constants.
+% For Unicode general category and the various breaking properties, there needs
+% to be numerical representation of each possible value. As we need to go from
+% string to number here, but the other way elsewhere, we set up fast mappings
+% both ways, but one set local and the other as constants.
% \begin{macrocode}
- \cs_set_protected:Npn \@@_data_auxi:w #1#2
+ \cs_set_nopar:Npn \l_@@_uppercase_default_tl { 0 }
+ \cs_set_nopar:Npn \l_@@_lowercase_default_tl { 0 }
+ \cs_set_protected:Npn \@@_data_auxi:w #1#2#3
{
- \quark_if_recursion_tail_stop:n {#2}
- \cs_set_nopar:cpn { l_@@_category_ #2 _tl } {#1}
- \str_const:cn { c_@@_category_ \tex_romannumeral:D #1 _str } {#2}
- \exp_args:Ne \@@_data_auxi:w { \int_eval:n { #1 + 1 } }
+ \quark_if_recursion_tail_stop:n {#3}
+ \cs_set_nopar:cpn { l_@@_ #2 _ #3 _tl } {#1}
+ \str_const:cn { c_@@_ #2 _ \tex_romannumeral:D #1 _str } {#3}
+ \exp_args:Ne \@@_data_auxi:w { \int_eval:n { #1 + 1 } } {#2}
}
- \@@_data_auxi:w { 1 }
+ \@@_data_auxi:w { 1 } { category }
{ Lu } { Ll } { Lt } { Lm } { Lo }
{ Mn } { Me } { Mc }
{ Nd } { Nl } { No }
@@ -526,7 +530,88 @@
{ Sm } { Sc } { Sk } { So }
\q_recursion_tail
\q_recursion_stop
+ \cs_set_eq:NN \l_@@_category_default_tl \l_@@_category_Cn_tl
+ \@@_data_auxi:w { 1 } { grapheme }
+ { Control }
+ { CR } { LF } { ZWJ }
+ { Extend }
+ { L } { LV } { LVT } { T } { V }
+ { Prepend }
+ { Regional_Indicator }
+ { SpacingMark }
+ { Other }
+ \q_recursion_tail
+ \q_recursion_stop
+ \cs_set_eq:NN \l_@@_grapheme_default_tl \l_@@_grapheme_Other_tl
+ \@@_data_auxi:w { 1 } { wordbreak }
+ { Double_Quote } { Single_Quote }
+ { CR } { LF } { Newline }
+ { WSegSpace } { ZWJ }
+ { Extend } { ExtendNumLet }
+ { Regional_Indicator }
+ { Format }
+ { Katakana }
+ { ALetter } { MidLetter } { Hebrew_Letter }
+ { Numeric }{ MidNum } { MidNumLet }
+ { Other }
+ \q_recursion_tail
+ \q_recursion_stop
+ \cs_set_eq:NN \l_@@_wordbreak_default_tl \l_@@_wordbreak_Other_tl
% \end{macrocode}
+% For the the property fields, we need to use a two-step procedure
+% as the file is ordered by class not codepoint. First, we parse the content
+% into the hash table locally: there are around $1400$ codepoints to handle,
+% which is workable. Reading this is quite easy: we store any end-of-range
+% codepoint and the class that applies. Conversion to a two-stage table
+% is deferred to later.
+% \begin{macrocode}
+ \cs_set_protected:Npn \@@_data_auxi:w #1 ;~ #2 ~ #3 \q_stop
+ { \@@_data_auxii:w #1 .. \q_stop {#2} }
+ \cs_set_protected:Npn \@@_data_auxii:w #1 .. #2 \q_stop
+ { \@@_data_auxiii:w #1 ~ .. #2 ~ \q_stop }
+ \cs_set_protected:Npn \@@_data_auxiii:w #1 ~ #2 .. #3 ~ #4 \q_stop #5#6
+ {
+ \cs_set_nopar:cpe { l_@@_ #6 _ \tex_romannumeral:D "#1 _tl }
+ {
+ {#3}
+ { \use:c { l_@@_ #6 _ #5 _tl } }
+ }
+ }
+ \cs_set_protected:Npn \@@_data_auxvi:w #1#2
+ {
+ \ior_open:Nn \g_@@_data_ior {#1}
+ \ior_str_map_inline:Nn \g_@@_data_ior
+ {
+ \str_if_eq:eeF { \tl_head:w ##1 \c_hash_str \q_stop } { \c_hash_str }
+ {
+ \tl_if_blank:nF {##1}
+ { \@@_data_auxi:w ##1 \q_stop {#2} }
+ }
+ }
+ \ior_close:N \g_@@_data_ior
+ }
+ \@@_data_auxvi:w { GraphemeBreakProperty.txt } { grapheme }
+ \@@_data_auxvi:w { WordBreakProperty.txt } { wordbreak }
+% \end{macrocode}
+% The set up for adding property data is now sorted.
+% \begin{macrocode}
+ \cs_set_protected:Npn \@@_data_property:nnnn #1#2#3#4
+ {
+ \int_compare:nNnT {#3} > { \use:c { l_@@_ #4 _next_tl } }
+ {
+ \@@_range:nnv {#3} {#4}
+ { l_@@_ #4 _default_tl }
+ }
+ \@@_add:nn {#4} {#2}
+ \tl_set:ce { l_@@_ #4 _next_tl } { \int_eval:n { #3 + 1 } }
+ \tl_if_blank:nF {#1}
+ {
+ \@@_range:nnn {"#1} {#4} {#2}
+ \@@_add:nn {#4} {#2}
+ \tl_set:ce { l_@@_ #4 _next_tl } { \int_eval:n { "#1 + 1 } }
+ }
+ }
+% \end{macrocode}
% Parse the main Unicode data file and pull out the NFD and case changing
% data. The NFD data is stored on using the hash table approach and can yield
% a predictable number of codepoints: one or two. We also need the case data,
@@ -593,7 +678,7 @@
% \begin{macrocode}
\cs_set_protected:Npn \@@_data_auxiv:w #1 ; #2 ; #3 ; #4 ; #5 ; #6 ;
{
- \int_compare:nNnT {"#1} > \l_@@_next_codepoint_fint_tl
+ \int_compare:nNnT {"#1} > \l_@@_category_next_tl
{
\@@_data_auxv:nnnnw {#1} {#3} {#4} {#5}
#2 Last> \q_stop
@@ -607,8 +692,26 @@
{ c_@@_titlecase_ \codepoint_str_generate:n {"#1} _tl }
{ {"#6} { } { } }
}
- \tl_set:Ne \l_@@_next_codepoint_fint_tl
+ \@@_data_auxvi:nn { grapheme } {"#1}
+ \@@_data_auxvi:nn { wordbreak } {"#1}
+% \end{macrocode}
+% To deal with the property data, we need to recover stored information and
+% build the table. Generally we can assume that all codepoints in these
+% files are in |UnicodeData.txt|, but there is one place
+% a bit more work is needed. For Hangul syllables, the main file lists a range
+% but within that we have different classifications for breaking: that needs to
+% be handled with a second loop. The values for this range are hard-coded,
+% skipping the end-of-range as that will be mopped up by the main loop.
+% \begin{macrocode}
+ \int_compare:nNnT {"#1} = { "AC00 }
+ {
+ \int_step_inline:nnn { "AC01 } { "D7A2 }
+ { \@@_data_auxvi:nn { grapheme } {##1} }
+ }
+ \tl_set:Ne \l_@@_category_next_tl
{ \int_eval:n { "#1 + 1 } }
+ \tl_set_eq:NN \l_@@_lowercase_next_tl \l_@@_category_next_tl
+ \tl_set_eq:NN \l_@@_uppercase_next_tl \l_@@_category_next_tl
}
\cs_set_protected:Npn \@@_add:nn #1#2
{
@@ -622,30 +725,47 @@
% The general category for unassigned characters is \texttt{Cn}, so we
% find the correct value once and then use that.
% \begin{macrocode}
- \cs_set_protected:Npe \@@_data_auxv:nnnnw #1#2#3#4#5 Last> #6 \q_stop
+ \cs_set_protected:Npn \@@_data_auxv:nnnnw #1#2#3#4#5 Last> #6 \q_stop
{
- \exp_not:N \tl_if_blank:nTF {#6}
+ \tl_if_blank:nTF {#6}
{
- \exp_not:N \@@_range:nnn {#1} { category }
- { \exp_not:V \l_@@_category_Cn_tl }
- \exp_not:N \@@_range:nnn {#1} { uppercase } { 0 }
- \exp_not:N \@@_range:nnn {#1} { lowercase } { 0 }
+ \@@_range:nno {"#1} { category }
+ \l_@@_category_default_tl
+ \@@_range:nnn {"#1} { uppercase } { 0 }
+ \@@_range:nnn {"#1} { lowercase } { 0 }
}
{
- \exp_not:N \@@_range:nnn {#1} { category } {#2}
- \exp_not:N \@@_range:nnn {#1} { uppercase } {#3}
- \exp_not:N \@@_range:nnn {#1} { lowercase } {#4}
+ \@@_range:nnn {"#1} { category } {#2}
+ \@@_range:nnn {"#1} { uppercase } {#3}
+ \@@_range:nnn {"#1} { lowercase } {#4}
}
}
% \end{macrocode}
+% Recover and process grapheme data.
+% \begin{macrocode}
+ \cs_set_protected:Npn \@@_data_auxvi:nn #1#2
+ {
+ \cs_if_exist:cT
+ { l_@@_ #1 _ \tex_romannumeral:D #2 _tl }
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN \@@_data_property:nnnn
+ \cs:w
+ l_@@_ #1 _ \tex_romannumeral:D #2 _tl
+ \cs_end: {#2} {#1}
+ }
+ }
+% \end{macrocode}
% Calculated the length of the range and the space remaining in the current
% block.
% \begin{macrocode}
- \cs_set_protected:Npn \@@_range:nnn #1
+ \cs_set_protected:Npn \@@_range:nnn #1#2
{
\exp_args:Nf \@@_range_aux:nnn
- { \int_eval:n { "#1 - \l_@@_next_codepoint_fint_tl } }
+ { \int_eval:n { #1 - \use:c { l_@@_ #2 _next_tl } } }
+ {#2}
}
+ \cs_set_protected:Npn \@@_range:nno { \exp_args:Nnno \@@_range:nnn }
+ \cs_set_protected:Npn \@@_range:nnv { \exp_args:Nnnv \@@_range:nnn }
\cs_set_protected:Npn \@@_range_aux:nnn #1#2
{
\exp_args:Nf \@@_range:nnnn
@@ -666,7 +786,7 @@
% single codepoint, so the middle step is optimised.
% \begin{macrocode}
\cs_set_protected:Npn \@@_range:nnnn #1#2#3#4
- {
+ {
\prg_replicate:nn {#1}
{ \clist_put_right:cn { l_@@_ #3 _block_clist } {#4} }
\int_compare:nNnT { \clist_count:c { l_@@_ #3 _block_clist } }
@@ -730,7 +850,7 @@
\l_@@_matched_block_tl
}
\tl_set:ce { l_@@_ #1 _pos_tl }
- { \int_eval:n { \tl_use:c { l_@@_ #1 _pos_tl } + #2 } }
+ { \int_eval:n { \tl_use:c { l_@@_ #1 _pos_tl } + #2 } }
\clist_clear:c { l_@@_ #1 _block_clist }
}
% \end{macrocode}
@@ -738,15 +858,16 @@
% of the block comma-lists into one large second-stage table with offsets.
% As we use an index not an offset, there is a little back-and-forward to do.
% \begin{macrocode}
- \cs_set_protected:Npn \@@_finalise_blocks:
+ \cs_set_protected:Npn \@@_finalise_blocks:n #1
{
- \clist_map_inline:nn { category , uppercase , lowercase }
+ \clist_map_inline:nn {#1}
{
- \@@_range:nnn { 110000 } {##1} { 0 }
- \@@_finalise_blocks:n {##1}
+ \exp_args:Nnnv \@@_range:nnn { "110000 } {##1}
+ { l_@@_ ##1 _default_tl }
+ \@@_finalise_blocks_aux:n {##1}
}
}
- \cs_set_protected:Npn \@@_finalise_blocks:n #1
+ \cs_set_protected:Npn \@@_finalise_blocks_aux:n #1
{
\cs_gset_eq:cc { c_@@_ #1 _index_intarray } { g_@@_ #1 _index_intarray }
\cs_undefine:c { g_@@_ #1 _index_intarray }
@@ -783,17 +904,22 @@
% a token list with spaces retained.
% \begin{macrocode}
\ior_open:Nn \g_@@_data_ior { UnicodeData.txt }
- \group_begin:
- \char_set_catcode_space:n { `\ }%
- \ior_map_variable:NNn \g_@@_data_ior \l_@@_tmpa_tl
- {%
- \if_meaning:w \l_@@_tmpa_tl \c_space_tl
- \exp_after:wN \ior_map_break:
- \fi:
- \exp_after:wN \@@_data_auxi:w \l_@@_tmpa_tl \q_stop
- }%
- \@@_finalise_blocks:
- \group_end:
+ \char_set_catcode_space:n { `\ }%
+ \ior_map_variable:NNn \g_@@_data_ior \l_@@_tmpa_tl
+ {%
+ \if_meaning:w \l_@@_tmpa_tl \c_space_tl
+ \exp_after:wN \ior_map_break:
+ \fi:
+ \exp_after:wN \@@_data_auxi:w \l_@@_tmpa_tl \q_stop
+ }%
+ \char_set_catcode_ignore:n { `\ }%
+% \end{macrocode}
+% Blocks need to be finalised once they have been read as this relies on
+% knowing the last real codepoint. So the tables for |UnicodeData.txt|
+% are closed out before reading additional files.
+% \begin{macrocode}
+ \@@_finalise_blocks:n
+ { category , grapheme , lowercase , uppercase , wordbreak }
\group_end:
% \end{macrocode}
%
@@ -961,6 +1087,35 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}[EXP]
+% {
+% \__kernel_codepoint_to_grapheme_class:n,
+% \__kernel_codepoint_to_wordbreak_class:n
+% }
+% Get the value and convert back to the string: not currently
+% public but otherwise very similar to \cs{codepoint_to_category:n}.
+% \begin{macrocode}
+\cs_new:Npn \__kernel_codepoint_to_grapheme_class:n #1
+ {
+ \cs:w
+ c_@@_grapheme_
+ \tex_romannumeral:D
+ \__kernel_codepoint_data:nn { grapheme } {#1}
+ _str
+ \cs_end:
+ }
+\cs_new:Npn \__kernel_codepoint_to_wordbreak_class:n #1
+ {
+ \cs:w
+ c_@@_wordbreak_
+ \tex_romannumeral:D
+ \__kernel_codepoint_data:nn { wordbreak } {#1}
+ _str
+ \cs_end:
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}[EXP]{\@@_nfd:n}
% \begin{macro}[EXP]{\@@_nfd:nn}
% A simple interface.
@@ -978,54 +1133,6 @@
% \end{macro}
%
% \begin{macrocode}
-%<@@=text>
-% \end{macrocode}
-%
-% Read the Unicode grapheme data. This is quite easy to handle and we only need
-% codepoints, not characters, so there is no need to worry about the engine in use.
-% As reading as a string is most convenient, we have to do some work to remove
-% spaces: the hardest part of the entire process!
-% \begin{macrocode}
-\ior_new:N \g_@@_data_ior
-\group_begin:
- \ior_open:Nn \g_@@_data_ior { GraphemeBreakProperty.txt }
- \cs_set_nopar:Npn \l_@@_tmpa_str { }
- \cs_set_nopar:Npn \l_@@_tmpb_str { }
- \cs_set_protected:Npn \@@_data_auxi:w #1 ;~ #2 ~ #3 \q_stop
- {
- \str_if_eq:VnF \l_@@_tmpb_str {#2}
- {
- \str_if_empty:NF \l_@@_tmpb_str
- {
- \clist_const:ce { c_@@_grapheme_ \l_@@_tmpb_str _clist }
- { \exp_after:wN \use_none:n \l_@@_tmpa_str }
- \cs_set_nopar:Npn \l_@@_tmpa_str { }
- }
- \cs_set_nopar:Npn \l_@@_tmpb_str {#2}
- }
- \@@_data_auxii:w #1 .. #1 .. #1 \q_stop
- }
- \cs_set_protected:Npn \@@_data_auxii:w #1 .. #2 .. #3 \q_stop
- {
- \cs_set_nopar:Npe \l_@@_tmpa_str
- {
- \l_@@_tmpa_str ,
- \tl_trim_spaces:n {#1} .. \tl_trim_spaces:n {#2}
- }
- }
- \ior_str_map_inline:Nn \g_@@_data_ior
- {
- \str_if_eq:eeF { \tl_head:w #1 \c_hash_str \q_stop } { \c_hash_str }
- {
- \tl_if_blank:nF {#1}
- { \@@_data_auxi:w #1 \q_stop }
- }
- }
- \ior_close:N \g_@@_data_ior
-\group_end:
-% \end{macrocode}
-%
-% \begin{macrocode}
%</package>
% \end{macrocode}
%
Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex 2025-04-08 20:12:11 UTC (rev 74879)
@@ -51,6 +51,7 @@
%% l3regex.dtx (with options: `package')
%% l3box.dtx (with options: `package')
%% l3color.dtx (with options: `package')
+%% l3graphics.dtx (with options: `package')
%% l3pdf.dtx (with options: `package,tex')
%% l3coffins.dtx (with options: `package')
%% l3luatex.dtx (with options: `package,tex')
@@ -75,7 +76,7 @@
%% and all files in that bundle must be distributed together.
%%
%% File: expl3.dtx
-\def\ExplFileDate{2025-01-18}%
+\def\ExplFileDate{2025-03-26}%
\begingroup
\def\next{\endgroup}%
\expandafter\ifx\csname PackageError\endcsname\relax
@@ -720,6 +721,7 @@
\__kernel_primitive:NN \pdfpageref \tex_pdfpageref:D
\__kernel_primitive:NN \pdfpageresources \tex_pdfpageresources:D
\__kernel_primitive:NN \pdfpagesattr \tex_pdfpagesattr:D
+ \__kernel_primitive:NN \pdfptexuseunderscore \tex_pdfptexuseunderscore:D
\__kernel_primitive:NN \pdfrefobj \tex_pdfrefobj:D
\__kernel_primitive:NN \pdfrefxform \tex_pdfrefxform:D
\__kernel_primitive:NN \pdfrefximage \tex_pdfrefximage:D
@@ -986,6 +988,7 @@
\__kernel_primitive:NN \mathdisplayskipmode \tex_mathdisplayskipmode:D
\__kernel_primitive:NN \matheqdirmode \tex_matheqdirmode:D
\__kernel_primitive:NN \matheqnogapstep \tex_matheqnogapstep:D
+ \__kernel_primitive:NN \mathemptydisplaymode \tex_mathemptydisplaymode:D
\__kernel_primitive:NN \mathflattenmode \tex_mathflattenmode:D
\__kernel_primitive:NN \mathitalicsmode \tex_mathitalicsmode:D
\__kernel_primitive:NN \mathnolimitsmode \tex_mathnolimitsmode:D
@@ -1326,6 +1329,7 @@
\__kernel_primitive:NN \omathchardef \tex_omathchardef:D
\__kernel_primitive:NN \omathcode \tex_omathcode:D
\__kernel_primitive:NN \oradical \tex_oradical:D
+ \__kernel_primitive:NN \ignoreprimitiveerror \tex_ignoreprimitiveerror:D
\__kernel_primitive:NN \partokencontext \tex_partokencontext:D
\__kernel_primitive:NN \partokenname \tex_partokenname:D
\__kernel_primitive:NN \showstream \tex_showstream:D
@@ -1670,7 +1674,7 @@
\cs_gset_protected:Npn \prg_set_conditional:Nnn
{ \__prg_generate_conditional_count:NNNnn \cs_set:Npn e }
\cs_gset_protected:Npn \prg_gset_conditional:Nnn
- { \__prg_generate_conditional_count:NNNnn \cs_set:Npn e }
+ { \__prg_generate_conditional_count:NNNnn \cs_gset:Npn e }
\cs_gset_protected:Npn \prg_new_conditional:Nnn
{ \__prg_generate_conditional_count:NNNnn \cs_new:Npn e }
\cs_gset_protected:Npn \prg_set_protected_conditional:Nnn
@@ -4078,6 +4082,7 @@
\s__tl_stop \s__tl_stop \s__tl_stop \s__tl_stop
\prg_break_point:Nn \tl_map_break: { }
}
+\cs_generate_variant:Nn \tl_map_function:nN { e }
\cs_new:Npn \tl_map_function:NN
{ \exp_args:No \tl_map_function:nN }
\cs_generate_variant:Nn \tl_map_function:NN { c }
@@ -4201,59 +4206,92 @@
}
\cs_new:Npn \__tl_reverse_items:wn #1 \s__tl_stop #2
{ \__kernel_exp_not:w \exp_after:wN { \use_none:nn #2 } }
-\cs_new:Npn \tl_trim_spaces:n #1
- {
- \__tl_trim_spaces:nn
- { \__tl_trim_mark: #1 }
- { \__kernel_exp_not:w \exp_after:wN }
- }
-\cs_generate_variant:Nn \tl_trim_spaces:n { V , v , e , o }
+\cs_new:Npn \tl_trim_spaces:n
+ { \__tl_trim_spaces:nn { \__kernel_exp_not:w \exp_after:wN } }
+\cs_new:Npn \tl_trim_left_spaces:n
+ { \__tl_trim_left_spaces:nn { \__kernel_exp_not:w \exp_after:wN } }
+\cs_new:Npn \tl_trim_right_spaces:n
+ { \__tl_trim_right_spaces:nn { \__kernel_exp_not:w \exp_after:wN } }
+\cs_generate_variant:Nn \tl_trim_spaces:n { V , v , e , o }
+\cs_generate_variant:Nn \tl_trim_left_spaces:n { V , v , e , o }
+\cs_generate_variant:Nn \tl_trim_right_spaces:n { V , v , e , o }
\cs_new:Npn \tl_trim_spaces_apply:nN #1#2
- { \__tl_trim_spaces:nn { \__tl_trim_mark: #1 } { \exp_args:No #2 } }
+ { \__tl_trim_spaces:nn { \exp_args:No #2 } { #1 } }
+\cs_new:Npn \tl_trim_left_spaces_apply:nN #1#2
+ { \__tl_trim_left_spaces:nn { \exp_args:No #2 } { #1 } }
+\cs_new:Npn \tl_trim_right_spaces_apply:nN #1#2
+ { \__tl_trim_right_spaces:nn { \exp_args:No #2 } { #1 } }
\cs_generate_variant:Nn \tl_trim_spaces_apply:nN { o }
+\cs_generate_variant:Nn \tl_trim_left_spaces_apply:nN { o }
+\cs_generate_variant:Nn \tl_trim_right_spaces_apply:nN { o }
\cs_new_protected:Npn \tl_trim_spaces:N #1
{ \__kernel_tl_set:Nx #1 { \exp_args:No \tl_trim_spaces:n {#1} } }
+\cs_new_protected:Npn \tl_trim_left_spaces:N #1
+ { \__kernel_tl_set:Nx #1 { \exp_args:No \tl_trim_left_spaces:n {#1} } }
+\cs_new_protected:Npn \tl_trim_right_spaces:N #1
+ { \__kernel_tl_set:Nx #1 { \exp_args:No \tl_trim_right_spaces:n {#1} } }
\cs_new_protected:Npn \tl_gtrim_spaces:N #1
{ \__kernel_tl_gset:Nx #1 { \exp_args:No \tl_trim_spaces:n {#1} } }
+\cs_new_protected:Npn \tl_gtrim_left_spaces:N #1
+ { \__kernel_tl_gset:Nx #1 { \exp_args:No \tl_trim_left_spaces:n {#1} } }
+\cs_new_protected:Npn \tl_gtrim_right_spaces:N #1
+ { \__kernel_tl_gset:Nx #1 { \exp_args:No \tl_trim_right_spaces:n {#1} } }
\cs_generate_variant:Nn \tl_trim_spaces:N { c }
+\cs_generate_variant:Nn \tl_trim_left_spaces:N { c }
+\cs_generate_variant:Nn \tl_trim_right_spaces:N { c }
\cs_generate_variant:Nn \tl_gtrim_spaces:N { c }
+\cs_generate_variant:Nn \tl_gtrim_left_spaces:N { c }
+\cs_generate_variant:Nn \tl_gtrim_right_spaces:N { c }
\cs_set_protected:Npn \__tl_tmp:w #1
{
- \cs_new:Npn \__tl_trim_spaces:nn ##1
+ \cs_new:Npn \__tl_trim_spaces:nn ##1##2
{
\__tl_trim_spaces_auxi:w
- ##1
- \s__tl_nil
- \__tl_trim_mark: #1 { }
+ \__tl_trim_mark: ##2 \s__tl_nil
+ \__tl_trim_mark: \__tl_trim_spaces_auxi:w
+ \__tl_trim_mark: #1
\__tl_trim_mark: \__tl_trim_spaces_auxii:w
- \__tl_trim_spaces_auxiii:w
- #1 \s__tl_nil
- \__tl_trim_spaces_auxiv:w
- \s__tl_stop
+ {##1}
}
- \cs_new:Npn
- \__tl_trim_spaces_auxi:w ##1 \__tl_trim_mark: #1 ##2 \__tl_trim_mark: ##3
+ \cs_new:Npn \__tl_trim_left_spaces:nn ##1##2
{
- ##3
\__tl_trim_spaces_auxi:w
- \__tl_trim_mark:
- ##2
- \__tl_trim_mark: #1 {##1}
+ \__tl_trim_mark: ##2 \s__tl_nil
+ \__tl_trim_mark: \__tl_trim_spaces_auxi:w
+ \__tl_trim_mark: #1
+ \__tl_trim_mark: \__tl_trim_spaces_auxv:w
+ {##1}
}
+ \cs_new:Npn \__tl_trim_right_spaces:nn ##1##2
+ {
+ \__tl_trim_spaces_auxiii:w
+ \__tl_trim_mark: ##2 \s__tl_nil \__tl_trim_spaces_auxiii:w
+ #1 \s__tl_nil \__tl_trim_spaces_auxiv:w
+ {##1}
+ }
+ \cs_new:Npn \__tl_trim_spaces_auxi:w
+ ##1 \__tl_trim_mark: #1 ##2 \__tl_trim_mark: ##3
+ { ##3 ##1 \__tl_trim_mark: ##2 \__tl_trim_mark: \__tl_trim_spaces_auxi:w }
\cs_new:Npn \__tl_trim_spaces_auxii:w
- \__tl_trim_spaces_auxi:w \__tl_trim_mark: \__tl_trim_mark: ##1
+ \__tl_trim_mark: ##1 \__tl_trim_mark: ##2 \__tl_trim_spaces_auxi:w
+ \__tl_trim_mark: \__tl_trim_mark: \__tl_trim_spaces_auxi:w
{
\__tl_trim_spaces_auxiii:w
- ##1
+ \__tl_trim_mark: ##1 \__tl_trim_spaces_auxiii:w
+ #1 \s__tl_nil \__tl_trim_spaces_auxiv:w
}
\cs_new:Npn \__tl_trim_spaces_auxiii:w ##1 #1 \s__tl_nil ##2
- {
+ { ##2 ##1 \s__tl_nil \__tl_trim_spaces_auxiii:w }
+ \cs_new:Npn \__tl_trim_spaces_auxiv:w
+ ##1 \s__tl_nil
+ \__tl_trim_spaces_auxiii:w \s__tl_nil \__tl_trim_spaces_auxiii:w
##2
+ { ##2 {##1} }
+ \cs_new:Npn \__tl_trim_spaces_auxv:w
##1 \s__tl_nil
- \__tl_trim_spaces_auxiii:w
- }
- \cs_new:Npn \__tl_trim_spaces_auxiv:w ##1 \s__tl_nil ##2 \s__tl_stop ##3
- { ##3 { ##1 } }
+ \__tl_trim_mark: \__tl_trim_spaces_auxi:w \__tl_trim_mark:
+ \__tl_trim_mark: \__tl_trim_spaces_auxi:w ##2
+ { ##2 {##1} }
\cs_new:Npn \__tl_trim_mark: {}
}
\__tl_tmp:w { ~ }
@@ -4267,7 +4305,7 @@
\__kernel_exp_not:w {#1}
\exp_after:wN \use_none:n \exp_after:wN { \if_false: } \fi:
}
-\cs_generate_variant:Nn \tl_head:n { V , v , f }
+\cs_generate_variant:Nn \tl_head:n { V , v , f , e }
\cs_new:Npn \tl_head:w #1#2 \q_stop {#1}
\cs_new:Npn \__tl_tl_head:w #1#2 \s__tl_stop {#1}
\cs_new:Npn \tl_head:N { \exp_args:No \tl_head:n }
@@ -4278,7 +4316,7 @@
{ { } }
{ \exp_after:wN { \use_none:n #1 } }
}
-\cs_generate_variant:Nn \tl_tail:n { V , v , f }
+\cs_generate_variant:Nn \tl_tail:n { V , v , f , e }
\cs_new:Npn \tl_tail:N { \exp_args:No \tl_tail:n }
\prg_new_conditional:Npnn \tl_if_head_eq_charcode:nN #1#2 { p , T , F , TF }
{
@@ -4987,9 +5025,9 @@
}
\cs_new:Npn \__str_case:nnTF #1#2#3#4
{ \__str_case:nw {#1} #2 {#1} { } \s__str_mark {#3} \s__str_mark {#4} \s__str_stop }
-\cs_generate_variant:Nn \str_case:nn { V , o , e , nV , nv }
+\cs_generate_variant:Nn \str_case:nn { V , o , e , nV , nv , ne }
\prg_generate_conditional_variant:Nnn \str_case:nn
- { V , o , e , nV , nv } { T , F , TF }
+ { V , o , e , nV , nv , ne } { T , F , TF }
\cs_new_eq:NN \str_case:Nn \str_case:Vn
\cs_new_eq:NN \str_case:NnT \str_case:VnT
\cs_new_eq:NN \str_case:NnF \str_case:VnF
@@ -14315,7 +14353,11 @@
\prop_get:NVNF #1 \l__keys_module_str \l__keys_tmpa_tl
{ \tl_clear:N \l__keys_tmpa_tl }
\tl_set:Ne \l__keys_tmpb_tl
- { \exp_after:wN \__keys_usage:w \l_keys_path_str \s__keys_stop }
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN \__keys_usage:w \exp_after:wN
+ \l_keys_path_str \exp_after:wN / \exp_after:wN \s__keys_stop
+ \exp_after:wN { \l_keys_path_str }
+ }
\bool_if:NTF #2
{ \clist_put_right:NV \l__keys_tmpa_tl \l__keys_tmpb_tl }
{ \clist_remove_all:NV \l__keys_tmpa_tl \l__keys_tmpb_tl }
@@ -14322,7 +14364,13 @@
\prop_put:NVV #1 \l__keys_module_str
\l__keys_tmpa_tl
}
-\cs_new:Npn \__keys_usage:w #1 / #2 \s__keys_stop {#2}
+\cs_new:Npn \__keys_usage:w #1 / #2 \s__keys_stop #3
+ {
+ \tl_if_blank:nTF {#2}
+ {#1}
+ { \__keys_usage_aux:w #3 \s__keys_stop }
+ }
+\cs_new:Npn \__keys_usage_aux:w #1 / #2 \s__keys_stop {#2}
\cs_new_protected:Npn \__keys_variable_set:NnnN #1#2#3#4
{
\use:c { #2_if_exist:NF } #1 { \use:c { #2 _new:N } #1 }
@@ -14977,20 +15025,40 @@
}
\prg_new_conditional:Npnn \keys_if_exist:nn #1#2 { p , T , F , TF }
{
+ \__keys_if_exist:ee
+ { \__keys_trim_spaces:n {#1} }
+ { \__keys_trim_spaces:n {#2} }
+ }
+\prg_generate_conditional_variant:Nnn \keys_if_exist:nn { ne } { p , T , F , TF }
+\cs_new:Npn \__keys_if_exist:nn #1#2
+ {
\cs_if_exist:cTF
- { \c__keys_code_root_str \__keys_trim_spaces:n { #1 / #2 } }
+ { \c__keys_code_root_str #1 \tl_if_blank:nF {#1} { / } #2 }
{ \prg_return_true: }
{ \prg_return_false: }
}
-\prg_generate_conditional_variant:Nnn \keys_if_exist:nn { ne } { p , T , F , TF }
+\cs_generate_variant:Nn \__keys_if_exist:nn { ee }
\prg_new_conditional:Npnn \keys_if_choice_exist:nnn #1#2#3
{ p , T , F , TF }
{
+ \__keys_if_exist:eee
+ { \__keys_trim_spaces:n {#1} }
+ { \__keys_trim_spaces:n {#2} }
+ { \__keys_trim_spaces:n {#3} }
+ }
+\cs_new:Npn \__keys_if_exist:nnn #1#2#3
+ {
\cs_if_exist:cTF
- { \c__keys_code_root_str \__keys_trim_spaces:n { #1 / #2 / #3 } }
+ {
+ \c__keys_code_root_str
+ #1 \tl_if_blank:nF {#1} { / }
+ #2 \tl_if_blank:nF {#2} { / }
+ #3
+ }
{ \prg_return_true: }
{ \prg_return_false: }
}
+\cs_generate_variant:Nn \__keys_if_exist:nnn { eee }
\cs_new_protected:Npn \keys_show:nn
{ \__keys_show:Nnn \msg_show:nneeee }
\cs_new_protected:Npn \keys_log:nn
@@ -14997,8 +15065,15 @@
{ \__keys_show:Nnn \msg_log:nneeee }
\cs_new_protected:Npn \__keys_show:Nnn #1#2#3
{
+ \__keys_show_aux:Nee
+ #1
+ { \__keys_trim_spaces:n {#2} }
+ { \__keys_trim_spaces:n {#3} }
+ }
+\cs_new_protected:Npn \__keys_show_aux:Nnn #1#2#3
+ {
#1 { keys } { show-key }
- { \__keys_trim_spaces:n { #2 / #3 } }
+ { #2 \tl_if_blank:nF {#2} { / } #3 }
{
\keys_if_exist:nnT {#2} {#3}
{
@@ -15009,7 +15084,7 @@
\exp_args:Nc \cs_replacement_spec:N
{
\c__keys_code_root_str
- \__keys_trim_spaces:n { #2 / #3 }
+ #2 \tl_if_blank:nF {#2} { / } #3
}
}
}
@@ -15017,6 +15092,7 @@
}
{ } { }
}
+\cs_generate_variant:Nn \__keys_show_aux:Nnn { Nee }
\cs_new:Npe \__keys_show:n #1
{
\exp_not:N \__keys_show:w
@@ -21744,7 +21820,7 @@
{ \__fp_invalid_operation_o:Nww #2 }
{#1}
}
-%% File l3fp-symbolic.dtx (C) Copyright 2012-2015,2017,2018,2020,2021,2023 The LaTeX Project
+%% File l3fp-symbolic.dtx (C) Copyright 2012-2025 The LaTeX Project
\fp_new:N \l__fp_symbolic_fp
\scan_new:N \s__fp_symbolic
\cs_new_protected:Npn \__fp_symbolic_chk:w #1,#2#3\__fp_sep:
@@ -21821,8 +21897,8 @@
}
\tl_map_inline:nn
{
- {acos} {acsc} {asec} {asin} {cos} {cot} {csc} {exp} {ln}
- {not} {sec} {set_sign} {sin} {sqrt} {tan}
+ {acos} {acsc} {asec} {asin} {cos} {cot} {csc} {exp} {fact} {ln}
+ {not} {sec} {set_sign} {sin} {sign} {sqrt} {tan}
}
{
\cs_new:cpe { __fp_symbolic_#1_o:w }
@@ -22008,12 +22084,12 @@
{ \msg_error:nnn { fp } { id-invalid } {#1} }
{
\cs_if_exist:cT { __fp_parse_word_#1:N }
- {
- \msg_error:nnn
- { fp } { id-already-defined } {#1}
- \cs_undefine:c { __fp_parse_word_#1:N }
- \cs_set_eq:cN { l__fp_variable_#1_fp } \tex_undefined:D
- }
+ {
+ \msg_error:nnn
+ { fp } { id-already-defined } {#1}
+ \cs_undefine:c { __fp_parse_word_#1:N }
+ \cs_set_eq:cN { l__fp_variable_#1_fp } \tex_undefined:D
+ }
\__fp_variable_set_parsing:Nn \cs_gset_eq:NN {#1}
}
}
@@ -22027,7 +22103,11 @@
\__fp_id_if_invalid:nTF {#1}
{ \msg_error:nnn { fp } { id-invalid } {#1} }
{
- \__fp_variable_set_parsing:Nn \cs_set_eq:NN {#1}
+ \cs_if_exist:cF { __fp_parse_word_#1:N }
+ {
+ \msg_error:nnn {fp} { id-undefined } {#1}
+ \__fp_variable_set_parsing:Nn \cs_set_eq:NN {#1}
+ }
\fp_set:Nn \l__fp_symbolic_fp {#2}
\cs_set_nopar:cpn { l__fp_variable_#1_fp }
{ \flag_ensure_raised:N \l__fp_symbolic_flag \c_nan_fp }
@@ -22054,6 +22134,12 @@
LaTeX~has~been~asked~to~create~a~new~floating~point~identifier~'#1'~
but~this~name~has~already~been~used~elsewhere.
}
+\msg_new:nnnn { fp } { id-undefined }
+ { Floating~point~identifier~'#1'~is~undefined. }
+ {
+ LaTeX~has~been~asked~to~set~a~floating~point~identifier~'#1'~
+ but~this~name~has~not~been~declared.
+ }
\msg_new:nnnn { fp } { id-used-elsewhere }
{ Floating~point~identifier~'#1'~already~used~for~something~else. }
{
@@ -22142,7 +22228,10 @@
{ \msg_error:nnn { fp } { id-invalid } {#2} }
{
\cs_if_exist:cF { __fp_parse_word_#2:N }
- { \__fp_function_set_parsing:Nn \cs_set_eq:NN {#2} }
+ {
+ \msg_error:nnn {fp} { id-undefined } {#2}
+ \__fp_function_set_parsing:Nn \cs_set_eq:NN {#2}
+ }
\group_begin:
\int_zero:N \l__fp_function_arg_int
\exp_args:No \clist_map_inline:nn { \tl_to_str:n {#3} }
@@ -32048,6 +32137,385 @@
{ is~undefined. }
{ has~the~properties: #2 }
}
+%% File: l3graphics.dtx
+\cs_if_exist:NT \@expl at finalise@setup@@
+ {
+ \tl_gput_right:Nn \@expl at finalise@setup@@
+ { \declare at file@substitution { l3graphics.sty } { null.tex } }
+ }
+\dim_new:N \l__graphics_internal_dim
+\ior_new:N \l__graphics_internal_ior
+\tl_new:N \l__graphics_internal_tl
+\scan_new:N \s__graphics_stop
+\tl_new:N \l__graphics_pagebox_tl
+\keys_define:nn { graphics }
+ {
+ decodearray .str_set:N =
+ \l__graphics_decodearray_str ,
+ draft .bool_set:N =
+ \l__graphics_draft_bool ,
+ interpolate .bool_set:N =
+ \l__graphics_interpolate_bool ,
+ pagebox .choices:nn =
+ { art , bleed , crop , media , trim }
+ {
+ \tl_set:Ne \l__graphics_pagebox_tl
+ { \l_keys_choice_tl box }
+ } ,
+ pagebox .initial:n =
+ crop ,
+ page .int_set:N =
+ \l__graphics_page_int ,
+ pdf-attr .str_set:N =
+ \l__graphics_pdf_str ,
+ type . str_set:N =
+ \l__graphics_type_str
+ }
+\dim_new:N \l__graphics_llx_dim
+\dim_new:N \l__graphics_lly_dim
+\dim_new:N \l__graphics_urx_dim
+\dim_new:N \l__graphics_ury_dim
+\cs_new_protected:Npn \__graphics_bb_save:n #1
+ {
+ \dim_if_exist:cTF { c__graphics_ #1 _urx_dim }
+ { \msg_error:nnn { graphic } { bb-already-cached } {#1} }
+ {
+ \dim_compare:nNnF \l__graphics_llx_dim = { 0pt }
+ { \dim_const:cn { c__graphics_ #1 _llx_dim } { \l__graphics_llx_dim } }
+ \dim_compare:nNnF \l__graphics_lly_dim = { 0pt }
+ { \dim_const:cn { c__graphics_ #1 _lly_dim } { \l__graphics_lly_dim } }
+ \dim_const:cn { c__graphics_ #1 _urx_dim } { \l__graphics_urx_dim }
+ \dim_const:cn { c__graphics_ #1 _ury_dim } { \l__graphics_ury_dim }
+ }
+ }
+\cs_generate_variant:Nn \__graphics_bb_save:n { e }
+\cs_new_protected:Npn \__graphics_bb_restore:nF #1#2
+ {
+ \dim_if_exist:cTF { c__graphics_ #1 _urx_dim }
+ {
+ \dim_set_eq:Nc \l__graphics_urx_dim { c__graphics_ #1 _urx_dim }
+ \dim_set_eq:Nc \l__graphics_ury_dim { c__graphics_ #1 _ury_dim }
+ \dim_if_exist:cTF { c__graphics_ #1 _llx_dim }
+ { \dim_set_eq:Nc \l__graphics_llx_dim { c__graphics_ #1 _llx_dim } }
+ { \dim_zero:N \l__graphics_llx_dim }
+ \dim_if_exist:cTF { c__graphics_ #1 _lly_dim }
+ { \dim_set_eq:Nc \l__graphics_lly_dim { c__graphics_ #1 _lly_dim } }
+ { \dim_zero:N \l__graphics_lly_dim }
+ }
+ {#2}
+ }
+\cs_generate_variant:Nn \__graphics_bb_restore:nF { e }
+\cs_new_protected:Npn \__graphics_extract_bb:n #1
+ {
+ \int_compare:nNnTF \l__graphics_page_int > 0
+ { \__graphics_extract_bb_auxi:Vn \l__graphics_page_int {#1} }
+ { \__graphics_extract_bb_auxii:nnn {#1} { } { } }
+ }
+\cs_new_protected:Npn \__graphics_extract_bb_auxi:nn #1#2
+ { \__graphics_extract_bb_auxii:nnn {#2} { :P #1 } { -p~#1~ } }
+\cs_generate_variant:Nn \__graphics_extract_bb_auxi:nn { Vn }
+\cs_new_protected:Npn \__graphics_extract_bb_auxii:nnn #1#2#3
+ {
+ \tl_if_empty:NTF \l__graphics_pagebox_tl
+ { \__graphics_extract_bb_auxiv:nnn }
+ { \__graphics_extract_bb_auxiii:Vnnn \l__graphics_pagebox_tl }
+ {#1} {#2} {#3}
+ }
+\cs_new_protected:Npn \__graphics_extract_bb_auxiii:nnnn #1#2#3#4
+ { \__graphics_extract_bb_auxiv:nnn {#2} { : #1 #3 } { #4 -B~#1~ } }
+\cs_generate_variant:Nn \__graphics_extract_bb_auxiii:nnnn { V }
+\cs_new_protected:Npn \__graphics_extract_bb_auxiv:nnn #1#2#3
+ {
+ \__graphics_read_bb_auxi:nnnn {#1} {#2}
+ { \ior_shell_open:Nn \l__graphics_internal_ior { extractbb~#3-O~#1 } }
+ { pipe-failed }
+ }
+\cs_new_protected:Npn \__graphics_read_bb:n #1
+ {
+ \__graphics_read_bb_auxi:nnnn {#1} { }
+ { \ior_open:Nn \l__graphics_internal_ior {#1} }
+ { graphic-not-found }
+ }
+\cs_new_protected:Npn \__graphics_read_bb_auxi:nnnn #1#2#3#4
+ {
+ \__graphics_bb_restore:nF {#1#2}
+ { \__graphics_read_bb_auxii:nnnn {#3} {#4} {#1} {#2} }
+ }
+\cs_new_protected:Npe \__graphics_read_bb_auxii:nnnn #1#2#3#4
+ {
+ #1
+ \exp_not:N \ior_if_eof:NTF \exp_not:N \l__graphics_internal_ior
+ { \msg_error:nnn { graphics } {#2} {#3} }
+ {
+ \ior_str_map_inline:Nn \exp_not:N \l__graphics_internal_ior
+ {
+ \exp_not:N \__graphics_read_bb_auxiii:w
+ ##1 ~ \c_colon_str \s__graphics_stop
+ }
+ \__graphics_bb_save:n {#3#4}
+ }
+ \ior_close:N \exp_not:N \l__graphics_internal_ior
+ }
+\use:e
+ {
+ \cs_new_protected:Npn \exp_not:N \__graphics_read_bb_auxiii:w
+ #1 \c_colon_str #2 \s__graphics_stop
+ {
+ \exp_not:N \str_if_eq:nnT
+ { \c_percent_str \c_percent_str BoundingBox }
+ {#1}
+ { \exp_not:N \__graphics_read_bb_auxiv:w #2 ( ) \s__graphics_stop }
+ }
+ }
+\cs_new_protected:Npn \__graphics_read_bb_auxiv:w #1 ( #2 ) #3 \s__graphics_stop
+ {
+ \str_if_eq:nnF {#2} { atend }
+ {
+ \tl_set_rescan:Nne \l__graphics_internal_tl
+ {
+ \char_set_catcode_space:n { 9 }
+ \char_set_catcode_space:n { 32 }
+ }
+ { \use:n #1 }
+ \exp_after:wN \__graphics_read_bb_auxv:w \l__graphics_internal_tl \s__graphics_stop
+ }
+ }
+\cs_new_protected:Npn \__graphics_read_bb_auxv:w #1~#2~#3~#4~#5 \s__graphics_stop
+ {
+ \dim_set:Nn \l__graphics_llx_dim { #1 bp }
+ \dim_set:Nn \l__graphics_lly_dim { #2 bp }
+ \dim_set:Nn \l__graphics_urx_dim { #3 bp }
+ \dim_set:Nn \l__graphics_ury_dim { #4 bp }
+ \ior_map_break:
+ }
+\str_new:N \l__graphics_final_name_str
+\str_new:N \l__graphics_full_name_str
+\box_new:N \l__graphics_internal_box
+\str_new:N \l__graphics_dir_str
+\str_new:N \l__graphics_name_str
+\str_new:N \l__graphics_ext_str
+\seq_new:N \l_graphics_search_path_seq
+\seq_new:N \l_graphics_search_ext_seq
+\prop_new:N \l_graphics_ext_type_prop
+\prop_put:Nnn \l_graphics_ext_type_prop { .ps } { eps }
+\seq_new:N \g__graphics_record_seq
+\cs_new_protected:Npn \graphics_include:nn #1#2
+ {
+ \group_begin:
+ \keys_set:nn { graphics } {#1}
+ \seq_set_eq:NN \l_file_search_path_seq \l_graphics_search_path_seq
+ \file_get_full_name:nNTF {#2} \l__graphics_full_name_str
+ {
+ \str_if_eq:eeTF { \l__graphics_full_name_str } { #2 .tex }
+ { \msg_error:nnn { graphics } { graphic-not-found } {#2} }
+ { \__graphics_include: }
+ }
+ { \msg_error:nnn { graphics } { graphic-not-found } {#2} }
+ \group_end:
+ }
+\cs_generate_variant:Nn \graphics_include:nn { nV }
+\cs_new_protected:Npn \__graphics_include:
+ {
+ \str_if_empty:NTF \l__graphics_type_str
+ {
+ \file_parse_full_name:VNNN \l__graphics_full_name_str
+ \l__graphics_dir_str \l__graphics_name_str \l__graphics_ext_str
+ \__graphics_include_auxi:e
+ {
+ \exp_args:Ne \str_tail:n
+ { \str_casefold:V \l__graphics_ext_str }
+ }
+ }
+ { \__graphics_include_auxi:e { \l__graphics_type_str } }
+ }
+\cs_new_protected:Npn \__graphics_include_auxi:n #1
+ {
+ \prop_get:NnNF \l_graphics_ext_type_prop { .#1 } \l__graphics_internal_tl
+ { \tl_set:Nn \l__graphics_internal_tl {#1} }
+ \exp_args:NV \__graphics_include_auxii:n \l__graphics_internal_tl
+ }
+\cs_generate_variant:Nn \__graphics_include_auxi:n { e }
+\cs_new_protected:Npn \__graphics_include_auxii:n #1
+ {
+ \mode_leave_vertical:
+ \cs_if_exist:cTF { __graphics_backend_include_ #1 :n }
+ {
+ \tl_set_eq:NN \l__graphics_final_name_str \l__graphics_full_name_str
+ \str_set:Ne \l__graphics_full_name_str
+ { \exp_args:NV \__kernel_file_name_quote:n \l__graphics_full_name_str }
+ \exp_args:NnV \use:c { __graphics_backend_getbb_ #1 :n }
+ \l__graphics_full_name_str
+ \seq_gput_right:NV \g__graphics_record_seq \l__graphics_final_name_str
+ \clist_if_exist:NT \@filelist
+ { \exp_args:NV \@addtofilelist \l__graphics_final_name_str }
+ \bool_if:NTF \l__graphics_draft_bool
+ { \__graphics_include_auxiii:n }
+ { \__graphics_include_auxiv:n }
+ {#1}
+ }
+ { \msg_error:nnn { graphics } { unsupported-graphic-type } {#1} }
+ }
+\cs_new_protected:Npn \__graphics_include_auxiii:n #1
+ {
+ \hbox_to_wd:nn { \l__graphics_urx_dim - \l__graphics_llx_dim }
+ {
+ \tex_vrule:D
+ \tex_hss:D
+ \vbox_to_ht:nn
+ { \l__graphics_ury_dim - \l__graphics_lly_dim }
+ {
+ \tex_hrule:D width
+ \dim_eval:n { \l__graphics_urx_dim - \l__graphics_llx_dim }
+ \tex_vss:D
+ \hbox_to_wd:nn
+ { \l__graphics_urx_dim - \l__graphics_llx_dim }
+ {
+ \ttfamily
+ \tex_hss:D \l__graphics_full_name_str \tex_hss:D
+ }
+ \tex_vss:D
+ \tex_hrule:D
+ }
+ \tex_hss:D
+ \tex_vrule:D
+ }
+ }
+\cs_new_protected:Npn \__graphics_include_auxiv:n #1
+ {
+ \hbox_set:Nn \l__graphics_internal_box
+ {
+ \exp_args:NnV \use:c { __graphics_backend_include_ #1 :n }
+ \l__graphics_full_name_str
+ }
+ \box_set_dp:Nn \l__graphics_internal_box { 0pt }
+ \box_set_ht:Nn \l__graphics_internal_box
+ { \l__graphics_ury_dim - \l__graphics_lly_dim }
+ \box_set_wd:Nn \l__graphics_internal_box
+ { \l__graphics_urx_dim - \l__graphics_llx_dim }
+ \box_use_drop:N \l__graphics_internal_box
+ }
+\cs_new_protected:Npn \graphics_show_list: { \__graphics_list:N \msg_show:nneeee }
+\cs_new_protected:Npn \graphics_log_list: { \__graphics_list:N \msg_log:nneeee }
+\cs_new_protected:Npn \__graphics_list:N #1
+ {
+ \seq_remove_duplicates:N \g__graphics_record_seq
+ #1 { kernel } { file-list }
+ { \seq_map_function:NN \g__graphics_record_seq \__graphics_list_aux:n }
+ { } { } { }
+ }
+\cs_new:Npn \__graphics_list_aux:n #1 { \iow_newline: #1 }
+\cs_new_protected:Npn \graphics_get_full_name:nN #1#2
+ {
+ \graphics_get_full_name:nNF {#1} #2
+ { \tl_set:Nn #2 { \q_no_value } }
+ }
+\prg_new_protected_conditional:Npnn \graphics_get_full_name:nN #1#2
+ { T , F , TF }
+ {
+ \group_begin:
+ \seq_set_eq:NN \l_file_search_path_seq \l_graphics_search_path_seq
+ \file_get_full_name:nNTF {#1} \l__graphics_full_name_str
+ {
+ \str_if_eq:eeTF { \l__graphics_full_name_str } { #1 .tex }
+ { \__graphics_get_full_name:n {#1} }
+ {
+ \file_parse_full_name:VNNN \l__graphics_full_name_str
+ \l__graphics_dir_str \l__graphics_name_str \l__graphics_ext_str
+ \seq_map_inline:Nn \l_graphics_search_ext_seq
+ {
+ \str_if_eq:nVT {##1} \l__graphics_ext_str
+ { \seq_map_break:n { \use_none:nn } }
+ }
+ \__graphics_get_full_name:n {#1}
+ }
+ }
+ { \__graphics_get_full_name:n {#1} }
+ \exp_args:NNNV \group_end:
+ \tl_set:Nn #2 \l__graphics_full_name_str
+ \tl_if_empty:NTF #2
+ { \prg_return_false: }
+ { \prg_return_true: }
+ }
+\cs_new_protected:Npn \__graphics_get_full_name:n #1
+ {
+ \str_clear:N \l__graphics_full_name_str
+ \seq_map_inline:Nn \l_graphics_search_ext_seq
+ {
+ \file_get_full_name:nNT { #1 ##1 } \l__graphics_full_name_str
+ { \seq_map_break:n { \use_none:nn } }
+ }
+ \use:n
+ { \str_clear:N \l__graphics_full_name_str }
+ }
+\cs_new_protected:Npn \graphics_get_pagecount:nN #1#2
+ {
+ \group_begin:
+ \seq_set_eq:NN \l_file_search_path_seq \l_graphics_search_path_seq
+ \file_get_full_name:nNTF {#1} \l__graphics_full_name_str
+ {
+ \int_if_exist:cF { c__graphics_ \l__graphics_full_name_str _pages_int }
+ {
+ \exp_args:NV \__graphics_backend_get_pagecount:n
+ \l__graphics_full_name_str
+ }
+ \tl_set:Nv #2 { c__graphics_ \l__graphics_full_name_str _pages_int }
+ }
+ {
+ \tl_set:Nn #2 { 0 }
+ \msg_error:nnn { graphics } { graphic-not-found } {#1}
+ }
+ \exp_args:NNNV \group_end:
+ \tl_set:Nn #2 #2
+ }
+\cs_new_protected:Npe \__graphics_get_pagecount:n #1
+ {
+ \exp_not:N \ior_shell_open:Nn \exp_not:N \l__graphics_internal_ior
+ { extractbb~-O~#1 }
+ \exp_not:N \ior_if_eof:NTF \exp_not:N \l__graphics_internal_ior
+ { \msg_error:nnn { graphics } { pipe-failed } }
+ {
+ \ior_str_map_inline:Nn \exp_not:N \l__graphics_internal_ior
+ {
+ \exp_not:N \__graphics_get_pagecount:nw {#1}
+ ##1 ~ \c_colon_str \c_colon_str \s__graphics_stop
+ }
+ \exp_not:N \int_if_exist:cF { c__graphics_ #1 _pages_int }
+ { \int_const:cn { c__graphics_ #1 _pages_int } { 1 } }
+ }
+ \ior_close:N \exp_not:N \l__graphics_internal_ior
+ }
+\use:e
+ {
+ \cs_new_protected:Npn \exp_not:N \__graphics_get_pagecount:nw
+ #1#2 \c_colon_str #3 \c_colon_str #4 \s__graphics_stop
+ {
+ \exp_not:N \str_if_eq:nnT
+ { \c_percent_str \c_percent_str Pages }
+ {#2}
+ {
+ \int_const:cn { c__graphics_ #1 _pages_int } {#3}
+ \exp_not:N \ior_map_break:
+ }
+ }
+ }
+\msg_new:nnnn { graphics } { graphic-not-found }
+ { Image~file~'#1'~not~found. }
+ {
+ LaTeX~tried~to~open~graphic~file~'#1',~
+ but~the~file~could~not~be~read.
+ }
+\msg_new:nnnn { graphics } { pipe-failed }
+ { Cannot~run~piped~system~commands. }
+ {
+ LaTeX~tried~to~call~a~system~process~but~this~was~not~possible.\\
+ Try~the~"--shell-escape"~(or~"--enable-pipes")~option.
+ }
+\msg_new:nnnn { graphics } { unsupported-graphic-type }
+ { Image~type~'#1'~not~supported~by~current~driver. }
+ {
+ LaTeX~was~asked~to~include~an~graphic~of~type~'#1',~
+ but~this~is~not~supported~by~the~current~driver~(production~route).
+ }
%% File: l3pdf.dtx
\scan_new:N \s__pdf_stop
\bool_new:N \g__pdf_init_bool
@@ -33832,24 +34300,26 @@
\ior_new:N \g__codepoint_data_ior
\group_begin:
\clist_map_inline:nn
- { category , uppercase , lowercase }
+ { category , grapheme , lowercase , uppercase , wordbreak }
{
\cs_set_nopar:cpn { l__codepoint_ #1 _block_clist } { }
\cs_set_nopar:cpn { l__codepoint_ #1 _block_tl } { 1 }
\cs_set_nopar:cpn { l__codepoint_ #1 _pos_tl } { 0 }
+ \cs_set_nopar:cpn { l__codepoint_ #1 _next_tl } { 0 }
\intarray_new:cn { g__codepoint_ #1 _index_intarray }
{ \int_div_truncate:nn { "110000 } \c__codepoint_block_size_int }
}
- \cs_set_nopar:Npn \l__codepoint_next_codepoint_fint_tl { 0 }
\cs_set_nopar:Npn \l__codepoint_matched_block_tl { 0 }
- \cs_set_protected:Npn \__codepoint_data_auxi:w #1#2
+ \cs_set_nopar:Npn \l__codepoint_uppercase_default_tl { 0 }
+ \cs_set_nopar:Npn \l__codepoint_lowercase_default_tl { 0 }
+ \cs_set_protected:Npn \__codepoint_data_auxi:w #1#2#3
{
- \quark_if_recursion_tail_stop:n {#2}
- \cs_set_nopar:cpn { l__codepoint_category_ #2 _tl } {#1}
- \str_const:cn { c__codepoint_category_ \tex_romannumeral:D #1 _str } {#2}
- \exp_args:Ne \__codepoint_data_auxi:w { \int_eval:n { #1 + 1 } }
+ \quark_if_recursion_tail_stop:n {#3}
+ \cs_set_nopar:cpn { l__codepoint_ #2 _ #3 _tl } {#1}
+ \str_const:cn { c__codepoint_ #2 _ \tex_romannumeral:D #1 _str } {#3}
+ \exp_args:Ne \__codepoint_data_auxi:w { \int_eval:n { #1 + 1 } } {#2}
}
- \__codepoint_data_auxi:w { 1 }
+ \__codepoint_data_auxi:w { 1 } { category }
{ Lu } { Ll } { Lt } { Lm } { Lo }
{ Mn } { Me } { Mc }
{ Nd } { Nl } { No }
@@ -33859,6 +34329,76 @@
{ Sm } { Sc } { Sk } { So }
\q_recursion_tail
\q_recursion_stop
+ \cs_set_eq:NN \l__codepoint_category_default_tl \l__codepoint_category_Cn_tl
+ \__codepoint_data_auxi:w { 1 } { grapheme }
+ { Control }
+ { CR } { LF } { ZWJ }
+ { Extend }
+ { L } { LV } { LVT } { T } { V }
+ { Prepend }
+ { Regional_Indicator }
+ { SpacingMark }
+ { Other }
+ \q_recursion_tail
+ \q_recursion_stop
+ \cs_set_eq:NN \l__codepoint_grapheme_default_tl \l__codepoint_grapheme_Other_tl
+ \__codepoint_data_auxi:w { 1 } { wordbreak }
+ { Double_Quote } { Single_Quote }
+ { CR } { LF } { Newline }
+ { WSegSpace } { ZWJ }
+ { Extend } { ExtendNumLet }
+ { Regional_Indicator }
+ { Format }
+ { Katakana }
+ { ALetter } { MidLetter } { Hebrew_Letter }
+ { Numeric }{ MidNum } { MidNumLet }
+ { Other }
+ \q_recursion_tail
+ \q_recursion_stop
+ \cs_set_eq:NN \l__codepoint_wordbreak_default_tl \l__codepoint_wordbreak_Other_tl
+ \cs_set_protected:Npn \__codepoint_data_auxi:w #1 ;~ #2 ~ #3 \q_stop
+ { \__codepoint_data_auxii:w #1 .. \q_stop {#2} }
+ \cs_set_protected:Npn \__codepoint_data_auxii:w #1 .. #2 \q_stop
+ { \__codepoint_data_auxiii:w #1 ~ .. #2 ~ \q_stop }
+ \cs_set_protected:Npn \__codepoint_data_auxiii:w #1 ~ #2 .. #3 ~ #4 \q_stop #5#6
+ {
+ \cs_set_nopar:cpe { l__codepoint_ #6 _ \tex_romannumeral:D "#1 _tl }
+ {
+ {#3}
+ { \use:c { l__codepoint_ #6 _ #5 _tl } }
+ }
+ }
+ \cs_set_protected:Npn \__codepoint_data_auxvi:w #1#2
+ {
+ \ior_open:Nn \g__codepoint_data_ior {#1}
+ \ior_str_map_inline:Nn \g__codepoint_data_ior
+ {
+ \str_if_eq:eeF { \tl_head:w ##1 \c_hash_str \q_stop } { \c_hash_str }
+ {
+ \tl_if_blank:nF {##1}
+ { \__codepoint_data_auxi:w ##1 \q_stop {#2} }
+ }
+ }
+ \ior_close:N \g__codepoint_data_ior
+ }
+ \__codepoint_data_auxvi:w { GraphemeBreakProperty.txt } { grapheme }
+ \__codepoint_data_auxvi:w { WordBreakProperty.txt } { wordbreak }
+ \cs_set_protected:Npn \__codepoint_data_property:nnnn #1#2#3#4
+ {
+ \int_compare:nNnT {#3} > { \use:c { l__codepoint_ #4 _next_tl } }
+ {
+ \__codepoint_range:nnv {#3} {#4}
+ { l__codepoint_ #4 _default_tl }
+ }
+ \__codepoint_add:nn {#4} {#2}
+ \tl_set:ce { l__codepoint_ #4 _next_tl } { \int_eval:n { #3 + 1 } }
+ \tl_if_blank:nF {#1}
+ {
+ \__codepoint_range:nnn {"#1} {#4} {#2}
+ \__codepoint_add:nn {#4} {#2}
+ \tl_set:ce { l__codepoint_ #4 _next_tl } { \int_eval:n { "#1 + 1 } }
+ }
+ }
\cs_set_protected:Npn \__codepoint_data_auxi:w
#1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ; #8 ; #9 ;
{
@@ -33901,7 +34441,7 @@
}
\cs_set_protected:Npn \__codepoint_data_auxiv:w #1 ; #2 ; #3 ; #4 ; #5 ; #6 ;
{
- \int_compare:nNnT {"#1} > \l__codepoint_next_codepoint_fint_tl
+ \int_compare:nNnT {"#1} > \l__codepoint_category_next_tl
{
\__codepoint_data_auxv:nnnnw {#1} {#3} {#4} {#5}
#2 Last> \q_stop
@@ -33915,8 +34455,17 @@
{ c__codepoint_titlecase_ \codepoint_str_generate:n {"#1} _tl }
{ {"#6} { } { } }
}
- \tl_set:Ne \l__codepoint_next_codepoint_fint_tl
+ \__codepoint_data_auxvi:nn { grapheme } {"#1}
+ \__codepoint_data_auxvi:nn { wordbreak } {"#1}
+ \int_compare:nNnT {"#1} = { "AC00 }
+ {
+ \int_step_inline:nnn { "AC01 } { "D7A2 }
+ { \__codepoint_data_auxvi:nn { grapheme } {##1} }
+ }
+ \tl_set:Ne \l__codepoint_category_next_tl
{ \int_eval:n { "#1 + 1 } }
+ \tl_set_eq:NN \l__codepoint_lowercase_next_tl \l__codepoint_category_next_tl
+ \tl_set_eq:NN \l__codepoint_uppercase_next_tl \l__codepoint_category_next_tl
}
\cs_set_protected:Npn \__codepoint_add:nn #1#2
{
@@ -33925,26 +34474,40 @@
= \c__codepoint_block_size_int
{ \__codepoint_save_blocks:nn {#1} { 1 } }
}
- \cs_set_protected:Npe \__codepoint_data_auxv:nnnnw #1#2#3#4#5 Last> #6 \q_stop
+ \cs_set_protected:Npn \__codepoint_data_auxv:nnnnw #1#2#3#4#5 Last> #6 \q_stop
{
- \exp_not:N \tl_if_blank:nTF {#6}
+ \tl_if_blank:nTF {#6}
{
- \exp_not:N \__codepoint_range:nnn {#1} { category }
- { \exp_not:V \l__codepoint_category_Cn_tl }
- \exp_not:N \__codepoint_range:nnn {#1} { uppercase } { 0 }
- \exp_not:N \__codepoint_range:nnn {#1} { lowercase } { 0 }
+ \__codepoint_range:nno {"#1} { category }
+ \l__codepoint_category_default_tl
+ \__codepoint_range:nnn {"#1} { uppercase } { 0 }
+ \__codepoint_range:nnn {"#1} { lowercase } { 0 }
}
{
- \exp_not:N \__codepoint_range:nnn {#1} { category } {#2}
- \exp_not:N \__codepoint_range:nnn {#1} { uppercase } {#3}
- \exp_not:N \__codepoint_range:nnn {#1} { lowercase } {#4}
+ \__codepoint_range:nnn {"#1} { category } {#2}
+ \__codepoint_range:nnn {"#1} { uppercase } {#3}
+ \__codepoint_range:nnn {"#1} { lowercase } {#4}
}
}
- \cs_set_protected:Npn \__codepoint_range:nnn #1
+ \cs_set_protected:Npn \__codepoint_data_auxvi:nn #1#2
{
+ \cs_if_exist:cT
+ { l__codepoint_ #1 _ \tex_romannumeral:D #2 _tl }
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN \__codepoint_data_property:nnnn
+ \cs:w
+ l__codepoint_ #1 _ \tex_romannumeral:D #2 _tl
+ \cs_end: {#2} {#1}
+ }
+ }
+ \cs_set_protected:Npn \__codepoint_range:nnn #1#2
+ {
\exp_args:Nf \__codepoint_range_aux:nnn
- { \int_eval:n { "#1 - \l__codepoint_next_codepoint_fint_tl } }
+ { \int_eval:n { #1 - \use:c { l__codepoint_ #2 _next_tl } } }
+ {#2}
}
+ \cs_set_protected:Npn \__codepoint_range:nno { \exp_args:Nnno \__codepoint_range:nnn }
+ \cs_set_protected:Npn \__codepoint_range:nnv { \exp_args:Nnnv \__codepoint_range:nnn }
\cs_set_protected:Npn \__codepoint_range_aux:nnn #1#2
{
\exp_args:Nf \__codepoint_range:nnnn
@@ -34014,15 +34577,16 @@
{ \int_eval:n { \tl_use:c { l__codepoint_ #1 _pos_tl } + #2 } }
\clist_clear:c { l__codepoint_ #1 _block_clist }
}
- \cs_set_protected:Npn \__codepoint_finalise_blocks:
+ \cs_set_protected:Npn \__codepoint_finalise_blocks:n #1
{
- \clist_map_inline:nn { category , uppercase , lowercase }
+ \clist_map_inline:nn {#1}
{
- \__codepoint_range:nnn { 110000 } {##1} { 0 }
- \__codepoint_finalise_blocks:n {##1}
+ \exp_args:Nnnv \__codepoint_range:nnn { "110000 } {##1}
+ { l__codepoint_ ##1 _default_tl }
+ \__codepoint_finalise_blocks_aux:n {##1}
}
}
- \cs_set_protected:Npn \__codepoint_finalise_blocks:n #1
+ \cs_set_protected:Npn \__codepoint_finalise_blocks_aux:n #1
{
\cs_gset_eq:cc { c__codepoint_ #1 _index_intarray } { g__codepoint_ #1 _index_intarray }
\cs_undefine:c { g__codepoint_ #1 _index_intarray }
@@ -34055,17 +34619,17 @@
{ \int_eval:n { #1 + 1 } } {#2} {#3}
}
\ior_open:Nn \g__codepoint_data_ior { UnicodeData.txt }
- \group_begin:
- \char_set_catcode_space:n { `\ }%
- \ior_map_variable:NNn \g__codepoint_data_ior \l__codepoint_tmpa_tl
- {%
- \if_meaning:w \l__codepoint_tmpa_tl \c_space_tl
- \exp_after:wN \ior_map_break:
- \fi:
- \exp_after:wN \__codepoint_data_auxi:w \l__codepoint_tmpa_tl \q_stop
- }%
- \__codepoint_finalise_blocks:
- \group_end:
+ \char_set_catcode_space:n { `\ }%
+ \ior_map_variable:NNn \g__codepoint_data_ior \l__codepoint_tmpa_tl
+ {%
+ \if_meaning:w \l__codepoint_tmpa_tl \c_space_tl
+ \exp_after:wN \ior_map_break:
+ \fi:
+ \exp_after:wN \__codepoint_data_auxi:w \l__codepoint_tmpa_tl \q_stop
+ }%
+ \char_set_catcode_ignore:n { `\ }%
+ \__codepoint_finalise_blocks:n
+ { category , grapheme , lowercase , uppercase , wordbreak }
\group_end:
\cs_new:Npn \__kernel_codepoint_data:nn #1#2
{
@@ -34185,6 +34749,24 @@
{ }
{ }
}
+\cs_new:Npn \__kernel_codepoint_to_grapheme_class:n #1
+ {
+ \cs:w
+ c__codepoint_grapheme_
+ \tex_romannumeral:D
+ \__kernel_codepoint_data:nn { grapheme } {#1}
+ _str
+ \cs_end:
+ }
+\cs_new:Npn \__kernel_codepoint_to_wordbreak_class:n #1
+ {
+ \cs:w
+ c__codepoint_wordbreak_
+ \tex_romannumeral:D
+ \__kernel_codepoint_data:nn { wordbreak } {#1}
+ _str
+ \cs_end:
+ }
\cs_new:Npn \__codepoint_nfd:n #1
{ \exp_args:Ne \__codepoint_nfd:nn { \codepoint_str_generate:n {#1} } {#1} }
\cs_new:Npn \__codepoint_nfd:nn #1#2
@@ -34193,43 +34775,6 @@
{ \tl_use:c { c__codepoint_nfd_ #1 _tl } }
{ {#2} { } }
}
-\ior_new:N \g__text_data_ior
-\group_begin:
- \ior_open:Nn \g__text_data_ior { GraphemeBreakProperty.txt }
- \cs_set_nopar:Npn \l__text_tmpa_str { }
- \cs_set_nopar:Npn \l__text_tmpb_str { }
- \cs_set_protected:Npn \__text_data_auxi:w #1 ;~ #2 ~ #3 \q_stop
- {
- \str_if_eq:VnF \l__text_tmpb_str {#2}
- {
- \str_if_empty:NF \l__text_tmpb_str
- {
- \clist_const:ce { c__text_grapheme_ \l__text_tmpb_str _clist }
- { \exp_after:wN \use_none:n \l__text_tmpa_str }
- \cs_set_nopar:Npn \l__text_tmpa_str { }
- }
- \cs_set_nopar:Npn \l__text_tmpb_str {#2}
- }
- \__text_data_auxii:w #1 .. #1 .. #1 \q_stop
- }
- \cs_set_protected:Npn \__text_data_auxii:w #1 .. #2 .. #3 \q_stop
- {
- \cs_set_nopar:Npe \l__text_tmpa_str
- {
- \l__text_tmpa_str ,
- \tl_trim_spaces:n {#1} .. \tl_trim_spaces:n {#2}
- }
- }
- \ior_str_map_inline:Nn \g__text_data_ior
- {
- \str_if_eq:eeF { \tl_head:w #1 \c_hash_str \q_stop } { \c_hash_str }
- {
- \tl_if_blank:nF {#1}
- { \__text_data_auxi:w #1 \q_stop }
- }
- }
- \ior_close:N \g__text_data_ior
-\group_end:
%% File: l3text.dtx
\cs_generate_variant:Nn \tl_if_head_eq_meaning_p:nN { o }
\scan_new:N \s__text_stop
@@ -36540,223 +37085,249 @@
\text_declare_uppercase_mapping:nn { "01F0 } { \v { J } }
}
%% File: l3text-map.dtx
-\cs_new:Npn \text_map_function:nN #1#2
- { \exp_args:Ne \__text_map_function:nN { \text_expand:n {#1} } #2 }
-\cs_new:Npn \__text_map_function:nN #1#2
+\cs_new:Npn \__text_map_function:nnN #1#2#3
{
- \__text_map_loop:Nnw #2 { } #1
+ \__text_map_loop:Nnnw #3 {#2} { } #1
\q__text_recursion_tail \q__text_recursion_stop
\prg_break_point:Nn \text_map_break: { }
}
-\cs_new:Npn \__text_map_loop:Nnw #1#2#3 \q__text_recursion_stop
+\cs_generate_variant:Nn \__text_map_function:nnN { e }
+\cs_new:Npn \__text_map_loop:Nnnw #1#2#3#4 \q__text_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#3}
- { \__text_map_N_type:NnN }
+ \tl_if_head_is_N_type:nTF {#4}
+ { \__text_map_N_type:NnnN }
{
- \tl_if_head_is_group:nTF {#3}
- { \__text_map_group:Nnn }
- { \__text_map_space:Nnw }
+ \tl_if_head_is_group:nTF {#4}
+ { \__text_map_group:Nnnn }
+ { \__text_map_space:Nnnw }
}
- #1 {#2} #3 \q__text_recursion_stop
+ #1 {#2} {#3} #4 \q__text_recursion_stop
}
-\cs_new:Npn \__text_map_group:Nnn #1#2#3
+\cs_new:Npn \__text_map_group:Nnnn #1#2#3#4
{
- \__text_map_output:Nn #1 {#2}
+ \__text_map_output:Nn #1 {#3}
{
- \__text_map_loop:Nnw #1 { } #2
+ \__text_map_loop:Nnnw #1 {#2} { } #4
\q__text_recursion_tail \q__text_recursion_stop
\prg_break_point:Nn \text_map_break: { }
}
- \__text_map_loop:Nnw #1 { }
+ \__text_map_loop:Nnnw #1 {#2} { }
}
\use:e
- { \cs_new:Npn \exp_not:N \__text_map_space:Nnw #1#2 \c_space_tl }
+ { \cs_new:Npn \exp_not:N \__text_map_space:Nnnw #1#2#3 \c_space_tl }
{
- \__text_map_output:Nn #1 {#2}
+ \__text_map_output:Nn #1 {#3}
#1 { ~ }
- \__text_map_loop:Nnw #1 { }
+ \__text_map_loop:Nnnw #1 {#2} { }
}
-\cs_new:Npn \__text_map_N_type:NnN #1#2#3
+\cs_new:Npn \__text_map_N_type:NnnN #1#2#3#4
{
- \__text_if_q_recursion_tail_stop_do:Nn #3
+ \__text_if_q_recursion_tail_stop_do:Nn #4
{
- \__text_map_output:Nn #1 {#2}
+ \__text_map_output:Nn #1 {#3}
\text_map_break:
}
- \token_if_cs:NTF #3
+ \token_if_cs:NTF #4
{
- \__text_map_output:Nn #1 {#2}
- #1 {#3}
- \__text_map_loop:Nnw #1 { }
+ \__text_map_output:Nn #1 {#3}
+ #1 {#4}
+ \__text_map_loop:Nnnw #1 {#2} { }
}
{
\__text_codepoint_process:nN
- { \__text_map_codepoint:Nnn #1 {#2} } #3
+ { \__text_map_codepoint:Nnnn #1 {#2} {#3} } #4
}
}
-\cs_new:Npn \__text_map_codepoint:Nnn #1#2#3
+\cs_new:Npn \__text_map_codepoint:Nnnn #1#2#3#4
{
- \__text_codepoint_compare:nNnTF {#3} = { "0D }
+ \__text_codepoint_compare:nNnTF {#4} = { "000D }
{
- \__text_map_output:Nn #1 {#2}
- \__text_map_CR:Nnw #1 {#3}
+ \__text_map_output:Nn #1 {#3}
+ \__text_map_CR:Nnnw #1 {#2} {#4}
}
{
- \__text_codepoint_compare:nNnTF {#3} = { "200D }
- { \__text_map_loop:Nnw #1 {#2#3} }
- { \__text_map_class:Nnnn #1 {#2} {#3} { Control } }
+ \__text_codepoint_compare:nNnTF {#4} = { "200D }
+ { \__text_map_loop:Nnnw #1 {#2} {#3#4} }
+ { \__text_map_class:Nnnn #1 {#2} {#3} {#4} }
}
}
-\cs_new:Npn \__text_map_CR:Nnw #1#2#3 \q__text_recursion_stop
+\cs_new:Npn \__text_map_CR:Nnnw #1#2#3#4 \q__text_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#3}
- { \__text_map_CR:NnN #1 {#2} }
+ \tl_if_head_is_N_type:nTF {#4}
+ { \__text_map_CR:NnnN #1 {#2} {#3} }
{
- #1 {#2}
- \__text_map_loop:Nnw #1 { }
+ #1 {#3}
+ \__text_map_loop:Nnnw #1 {#2} { }
}
- #3 \q__text_recursion_stop
+ #4 \q__text_recursion_stop
}
-\cs_new:Npn \__text_map_CR:NnN #1#2#3
+\cs_new:Npn \__text_map_CR:NnnN #1#2#3#4
{
- \__text_if_q_recursion_tail_stop_do:Nn #3
+ \__text_if_q_recursion_tail_stop_do:Nn #4
{
- #1 {#2}
+ #1 {#3}
\text_map_break:
}
\bool_lazy_and:nnTF
- { ! \token_if_cs_p:N #3 }
- { \int_compare_p:nNn { `#3 } = { "0A } }
+ { ! \token_if_cs_p:N #4 }
+ { \int_compare_p:nNn { `#4 } = { "000A } }
{
- \__text_map_output:Nn #1 {#2#3}
- \__text_map_loop:Nnw #1 { }
+ \__text_map_output:Nn #1 {#3#4}
+ \__text_map_loop:Nnnw #1 {#2} { }
}
- { \__text_map_loop:Nnw #1 { } #3 }
+ { \__text_map_loop:Nnnw #1 {#2} { } #3 }
}
\cs_new:Npn \__text_map_class:Nnnn #1#2#3#4
{
- \exp_args:Nv \__text_map_class:nNnnn { c__text_grapheme_ #4 _clist }
- #1 {#2} {#3} {#4}
+ \exp_args:Nnnne \__text_map_class:Nnnnn #1 {#2} {#3} {#4}
+ {
+ \use:c { __kernel_codepoint_to_ #2 _class:n }
+ { \__text_codepoint_from_chars:Nw #4 }
+ }
}
-\cs_new:Npn \__text_map_class:nNnnn #1#2#3#4#5
+\cs_new:Npn \__text_map_class:Nnnnn #1#2#3#4#5
{
- \__text_map_class_loop:Nnnnw #2 {#3} {#4} {#5}
- #1 , \q__text_recursion_tail .. , \q__text_recursion_stop
+ \cs_if_exist_use:cF { __text_map_ #5 :Nnnn }
+ { \__text_map_Other:Nnnn }
+ #1 {#2} {#3} {#4}
}
-\cs_new:Npn \__text_map_class_loop:Nnnnw #1#2#3#4 #5 .. #6 ,
+\cs_new:Npn \__text_map_lookahead:Nnnnnw #1#2#3#4#5#6 \q__text_recursion_stop
{
- \__text_if_q_recursion_tail_stop_do:nn {#5}
- { \use:c { __text_map_not_ #4 :Nnn } #1 {#2} {#3} }
- \__text_codepoint_compare:nNnTF {#3} < { "#5 }
+ \tl_if_head_is_N_type:nTF {#6}
+ { \__text_map_lookahead:NnnnnN #1 {#2} {#3} {#4} {#5} }
+ { \__text_map_loop:Nnnw #1 {#2} {#3} #4 }
+ #6 \q__text_recursion_stop
+ }
+\cs_new:Npn \__text_map_lookahead:NnnnnN #1#2#3#4#5#6
+ {
+ \__text_if_q_recursion_tail_stop_do:Nn #6
{
- \__text_map_class_end:nw
- { \use:c { __text_map_not_ #4 :Nnn } #1 {#2} {#3} }
+ #1 {#3}
+ \tl_if_blank:nF {#4} { #1 {#4} }
}
+ \token_if_cs:NTF #6
{
- \__text_codepoint_compare:nNnTF {#3} > { "#6 }
- { \__text_map_class_loop:Nnnnw #1 {#2} {#3} {#4} }
- {
- \__text_map_class_end:nw
- { \use:c { __text_map_ #4 :Nnn } #1 {#2} {#3} }
- }
+ #1 {#3}
+ \__text_map_loop:Nnnw #1 {#2} { } #4
}
+ { \__text_codepoint_process:nN { #5 #1 {#2} {#3} {#4} } }
+ #6
}
-\cs_new:Npn \__text_map_class_end:nw #1#2 \q__text_recursion_stop {#1}
-\cs_new:Npn \__text_map_Control:Nnn #1#2#3
+\prg_new_conditional:Npnn \__text_map_if_ignorable:n #1 { TF }
{
- \__text_map_output:Nn #1 {#2}
+ \str_case:nnTF {#1}
+ {
+ { Extend } { }
+ { Format } { }
+ { ZWJ } { }
+ }
+ \prg_return_true:
+ \prg_return_false:
+ }
+\cs_new:Npn \__text_map_output:Nn #1#2
+ { \tl_if_blank:nF {#2} { #1 {#2} } }
+\cs_new:Npn \text_map_break:
+ { \prg_map_break:Nn \text_map_break: { } }
+\cs_new:Npn \text_map_break:n
+ { \prg_map_break:Nn \text_map_break: }
+\cs_new:Npn \__text_map_Control:Nnnn #1#2#3#4
+ {
\__text_map_output:Nn #1 {#3}
- \__text_map_loop:Nnw #1 { }
+ \__text_map_output:Nn #1 {#4}
+ \__text_map_loop:Nnnw #1 {#2} { }
}
-\cs_new:Npn \__text_map_Extend:Nnn #1#2#3
- { \__text_map_loop:Nnw #1 {#2#3} }
-\cs_new_eq:NN \__text_map_SpacingMark:Nnn \__text_map_Extend:Nnn
-\cs_new:Npn \__text_map_Prepend:Nnn #1#2#3
+\cs_new_eq:NN \__text_map_Newline:Nnnn \__text_map_Control:Nnnn
+\cs_new:Npn \__text_map_Extend:Nnnn #1#2#3#4
+ { \__text_map_loop:Nnnw #1 {#2} {#3#4} }
+\cs_new_eq:NN \__text_map_Format:Nnnn \__text_map_Extend:Nnnn
+\cs_new_eq:NN \__text_map_SpacingMark:Nnnn \__text_map_Extend:Nnnn
+\cs_new:Npn \__text_map_Other:Nnnn #1#2#3#4
{
- \__text_map_output:Nn #1 {#2}
- \__text_map_lookahead:NnNw #1 {#3} \__text_map_Prepend_aux:Nnn
+ \__text_map_output:Nn #1 {#3}
+ \__text_map_loop:Nnnw #1 {#2} {#4}
}
-\cs_new:Npn \__text_map_Prepend_aux:Nnn #1#2#3
+\cs_new:Npn \__text_map_Regional_Indicator:Nnnn #1#2#3#4
{
+ \__text_map_output:Nn #1 {#3}
+ \__text_map_lookahead:Nnnnnw #1 {#2} {#4} { }
+ \__text_map_Regional_Indicator_aux:Nnnnn
+ }
+\cs_new:Npn \__text_map_Regional_Indicator_aux:Nnnnn #1#2#3#4#5
+ {
\bool_lazy_or:nnTF
- { \__text_codepoint_compare_p:nNn {#3} = { "0A } }
- { \__text_codepoint_compare_p:nNn {#3} = { "0D } }
+ { \__text_codepoint_compare_p:nNn {#5} < { "1F1E6 } }
+ { \__text_codepoint_compare_p:nNn {#5} > { "1F1FF } }
{
- #1 {#2}
- \__text_map_loop:Nnw #1 {#3}
+ \str_if_eq:nnTF {#2} { wordbreak }
+ {
+ \exp_args:Ne \__text_map_if_ignorable:nTF
+ {
+ \__kernel_codepoint_to_grapheme_class:n
+ { \__text_codepoint_from_chars:Nw #5 }
+ }
+ {
+ \__text_map_lookahead:Nnnnnw #1 {#2} {#3#5} { }
+ \__text_map_Regional_Indicator_aux:Nnnnn
+ }
+ { \__text_map_loop:Nnnw #1 {#2} {#3} #5 }
+ }
+ { \__text_map_loop:Nnnw #1 {#2} {#3} #5 }
}
- {
- \exp_args:NV \__text_map_Prepend:nNnn
- \c__text_grapheme_Control_clist
- #1 {#2} {#3}
- }
+ { \__text_map_loop:Nnnw #1 {#2} {#3#5} }
}
-\cs_new:Npn \__text_map_Prepend:nNnn #1#2#3#4
+\cs_new:Npn \text_map_function:nN #1#2
{
- \__text_map_Prepend_loop:Nnnw #2 {#3} {#4}
- #1 , \q__text_recursion_tail .. , \q__text_recursion_stop
+ \__text_map_function:enN { \text_expand:n {#1} }
+ { grapheme } #2
}
-\cs_new:Npn \__text_map_Prepend_loop:Nnnw #1#2#3 #4 .. #5 ,
+\cs_new:Npn \__text_map_Prepend:Nnnn #1#2#3#4
{
- \__text_if_q_recursion_tail_stop_do:nn {#4}
- { \__text_map_loop:Nnw #1 {#2#3} }
- \__text_codepoint_compare:nNnTF {#3} < { "#4 }
+ \__text_map_output:Nn #1 {#3}
+ \__text_map_lookahead:Nnnnnw #1 { grapheme } {#4} { }
+ \__text_map_Prepend_aux:Nnnnn
+ }
+\cs_new:Npn \__text_map_Prepend_aux:Nnnnn #1#2#3#4#5
+ {
+ \bool_lazy_or:nnTF
+ { \__text_codepoint_compare_p:nNn {#5} = { "000A } }
+ { \__text_codepoint_compare_p:nNn {#5} = { "000D } }
{
- \__text_map_class_end:nw
- { \__text_map_loop:Nnw #1 {#2#3} }
+ #1 {#3}
+ \__text_map_loop:Nnnw #1 { grapheme } {#5}
}
+ { \__text_map_Prepend:Nnn #1 {#3} {#5} }
+ }
+\cs_new:Npn \__text_map_Prepend:Nnn #1#2#3
+ {
+ \str_if_eq:eeTF
+ { Control }
{
- \__text_codepoint_compare:nNnTF {#3} > { "#5 }
- { \__text_map_Prepend_loop:Nnnw #1 {#2} {#3} }
- {
- \__text_map_class_end:nw
- { \__text_map_loop:Nnw #1 {#2} #3 }
- }
+ \__kernel_codepoint_to_grapheme_class:n
+ { \__text_codepoint_from_chars:Nw #3 }
}
+ { \__text_map_loop:Nnnw #1 { grapheme } {#2} #3 }
+ { \__text_map_loop:Nnnw #1 { grapheme } {#2#3} }
}
-\cs_new:Npn \__text_map_not_Control:Nnn #1#2#3
- { \__text_map_class:Nnnn #1 {#2} {#3} { Extend } }
-\cs_new:Npn \__text_map_not_Extend:Nnn #1#2#3
- { \__text_map_class:Nnnn #1 {#2} {#3} { SpacingMark } }
-\cs_new:Npn \__text_map_not_SpacingMark:Nnn #1#2#3
- { \__text_map_class:Nnnn #1 {#2} {#3} { Prepend } }
-\cs_new:Npn \__text_map_not_Prepend:Nnn #1#2#3
- { \__text_map_class:Nnnn #1 {#2} {#3} { L } }
-\cs_new:Npn \__text_map_not_L:Nnn #1#2#3
- { \__text_map_class:Nnnn #1 {#2} {#3} { LV } }
-\cs_new:Npn \__text_map_not_LV:Nnn #1#2#3
- { \__text_map_class:Nnnn #1 {#2} {#3} { V } }
-\cs_new:Npn \__text_map_not_V:Nnn #1#2#3
- { \__text_map_class:Nnnn #1 {#2} {#3} { LVT } }
-\cs_new:Npn \__text_map_not_LVT:Nnn #1#2#3
- { \__text_map_class:Nnnn #1 {#2} {#3} { T } }
-\cs_new:Npn \__text_map_not_T:Nnn #1#2#3
- { \__text_map_class:Nnnn #1 {#2} {#3} { Regional_Indicator } }
-\cs_new:Npn \__text_map_not_Regional_Indicator:Nnn #1#2#3
+\cs_new:Npn \__text_map_L:Nnnn #1#2#3#4
{
- \__text_map_output:Nn #1 {#2}
- \__text_map_loop:Nnw #1 {#3}
- }
-\cs_new:Npn \__text_map_L:Nnn #1#2#3
- {
- \__text_map_output:Nn #1 {#2}
+ \__text_map_output:Nn #1 {#3}
\__text_map_hangul:Nnnw
- #1 {#3} { L ; V ; LV ; LVT }
+ #1 {#4} { L ; V ; LV ; LVT }
}
-\cs_new:Npn \__text_map_LV:Nnn #1#2#3
+\cs_new:Npn \__text_map_LV:Nnnn #1#2#3#4
{
- \__text_map_output:Nn #1 {#2}
+ \__text_map_output:Nn #1 {#3}
\__text_map_hangul:Nnnw
- #1 {#3} { V ; T }
+ #1 {#4} { V ; T }
}
-\cs_new_eq:NN \__text_map_V:Nnn \__text_map_LV:Nnn
-\cs_new:Npn \__text_map_LVT:Nnn #1#2#3
+\cs_new_eq:NN \__text_map_V:Nnnn \__text_map_LV:Nnnn
+\cs_new:Npn \__text_map_LVT:Nnnn #1#2#3#4
{
- \__text_map_output:Nn #1 {#2}
+ \__text_map_output:Nn #1 {#3}
\__text_map_hangul:Nnnw
- #1 {#3} { T }
+ #1 {#4} { T }
}
-\cs_new_eq:NN \__text_map_T:Nnn \__text_map_LVT:Nnn
+\cs_new_eq:NN \__text_map_T:Nnnn \__text_map_LVT:Nnnn
\cs_new:Npn \__text_map_hangul:Nnnw #1#2#3#4 \q__text_recursion_stop
{
\tl_if_head_is_N_type:nTF {#4}
@@ -36763,7 +37334,7 @@
{ \__text_map_hangul:NnnN #1 {#2} {#3} }
{
#1 {#2}
- \__text_map_loop:Nnw #1 { }
+ \__text_map_loop:Nnnw #1 { grapheme } { }
}
#4 \q__text_recursion_stop
}
@@ -36777,7 +37348,7 @@
\token_if_cs:NTF #4
{
#1 {#2}
- \__text_map_loop:Nnw #1 { }
+ \__text_map_loop:Nnnw #1 { grapheme } { }
}
{
\__text_codepoint_process:nN
@@ -36784,43 +37355,31 @@
{ \__text_map_hangul:Nnnn #1 {#2} {#3} } #4
}
}
+\exp_args_generate:n { Nnne }
\cs_new:Npn \__text_map_hangul:Nnnn #1#2#3#4
{
- \__text_map_hangul_aux:Nnnw #1 {#2} {#4}
+ \exp_args:NNnne \__text_map_hangul_aux:Nnnnw #1 {#2} {#4}
+ {
+ \__kernel_codepoint_to_grapheme_class:n
+ { \__text_codepoint_from_chars:Nw #4 }
+ }
#3 ; \q_recursion_tail ; \q_recursion_stop
}
-\cs_new:Npn \__text_map_hangul_aux:Nnnw #1#2#3#4 ;
+\cs_new:Npn \__text_map_hangul_aux:Nnnnw #1#2#3#4#5 ;
{
- \quark_if_recursion_tail_stop_do:nn {#4}
- { \__text_map_loop:Nnw #1 {#2} #3 }
- \exp_args:Nv \__text_map_hangul:nNnnnw { c__text_grapheme_ #4 _clist }
- #1 {#2} {#3} {#4}
+ \quark_if_recursion_tail_stop_do:nn {#5}
+ { \__text_map_loop:Nnnw #1 { grapheme } {#2} #3 }
+ \__text_map_hangul:Nnnnnw #1 {#2} {#3} {#4} {#5}
}
-\cs_new:Npn \__text_map_hangul:nNnnnw #1#2#3#4#5#6 \q_recursion_stop
+\cs_generate_variant:Nn \__text_map_hangul_aux:Nnnnw { Nnne }
+\cs_new:Npn \__text_map_hangul:Nnnnnw #1#2#3#4#5#6 \q_recursion_stop
{
- \__text_map_hangul_loop:Nnnnnw #2 {#3} {#4} {#5} {#6}
- #1 , \q__text_recursion_tail .. , \q__text_recursion_stop
+ \str_if_eq:nnTF {#4} {#5}
+ { \use:c { __text_map_hangul_ #5 :Nnn } #1 {#2} {#3} }
+ { \__text_map_hangul_next:Nnnnn #1 {#2} {#3} {#4} {#6} }
}
-\cs_new:Npn \__text_map_hangul_loop:Nnnnnw #1#2#3#4#5 #6 .. #7 ,
- {
- \__text_if_q_recursion_tail_stop_do:nn {#6}
- { \__text_map_hangul_next:Nnnn #1 {#2} {#3} {#5} }
- \__text_codepoint_compare:nNnTF {#3} < { "#6 }
- {
- \__text_map_hangul_end:nw
- { \__text_map_hangul_next:Nnnn #1 {#2} {#3} {#5} }
- }
- {
- \__text_codepoint_compare:nNnTF {#3} > { "#7 }
- { \__text_map_hangul_loop:Nnnnnw #1 {#2} {#3} {#4} {#5} }
- {
- \__text_map_hangul_end:nw
- { \use:c { __text_map_hangul_ #4 :Nnn } #1 {#2} {#3} }
- }
- }
- }
-\cs_new:Npn \__text_map_hangul_next:Nnnn #1#2#3#4
- { \__text_map_hangul_aux:Nnnw #1 {#2} {#3} #4 \q_recursion_stop }
+\cs_new:Npn \__text_map_hangul_next:Nnnnn #1#2#3#4#5
+ { \__text_map_hangul_aux:Nnnnw #1 {#2} {#3} {#4} #5 \q_recursion_stop }
\cs_new:Npn \__text_map_hangul_end:nw #1#2 \q__text_recursion_stop {#1}
\cs_new:Npn \__text_map_hangul_L:Nnn #1#2#3
{
@@ -36839,45 +37398,162 @@
#1 {#2#3} { T }
}
\cs_new_eq:NN \__text_map_hangul_T:Nnn \__text_map_hangul_LVT:Nnn
-\cs_new:Npn \__text_map_Regional_Indicator:Nnn #1#2#3
+\cs_new:Npn \text_words_map_function:nN #1#2
{
- \__text_map_output:Nn #1 {#2}
- \__text_map_lookahead:NnNw #1 {#3} \__text_map_Regional_Indicator_aux:Nnn
+ \__text_map_function:enN { \text_expand:n {#1} }
+ { wordbreak } #2
}
-\cs_new:Npn \__text_map_Regional_Indicator_aux:Nnn #1#2#3
+\cs_new:Npn \__text_map_collect:Nnnnn #1#2#3#4#5
{
- \bool_lazy_or:nnTF
- { \__text_codepoint_compare_p:nNn {#3} < { "1F1E6 } }
- { \__text_codepoint_compare_p:nNn {#3} > { "1F1FF } }
+ \__text_map_lookahead:Nnnnnw #1 { wordbreak } {#2} { }
+ { \__text_map_collect_auxi:nnnNnnnn {#3} {#4} {#5} }
+ }
+\cs_new:Npn \__text_map_collect_auxi:nnnNnnnn #1#2#3#4#5#6#7#8
+ {
+ \exp_args:Ne \__text_map_collect_auxii:nNnnnnn
{
- \__text_map_loop:Nnw #1 {#2} #3
+ \__kernel_codepoint_to_wordbreak_class:n
+ { \__text_codepoint_from_chars:Nw #8 }
}
- { \__text_map_loop:Nnw #1 {#2#3} }
+ #4 {#6} {#1} {#2} {#3} {#8}
}
-\cs_new:Npn \__text_map_lookahead:NnNw #1#2#3#4 \q__text_recursion_stop
+\cs_new:Npn \__text_map_collect_auxii:nNnnnnn #1#2#3#4#5#6#7
{
- \tl_if_head_is_N_type:nTF {#4}
- { \__text_map_lookahead:NnNN #1 {#2} #3 }
- { \__text_map_loop:Nnw #1 {#2} }
- #4 \q__text_recursion_stop
+ \str_case:neTF {#1}
+ {
+ \tl_map_function:eN
+ {
+ #4
+ \str_if_eq:nnF {#4} { { WSegSpace } } { { ExtendNumLet } }
+ }
+ \__text_map_collect_auxiii:n
+ }
+ {
+ \cs_if_exist_use:cF { __text_map_ #1 :Nnnn }
+ { \__text_map_Other:Nnnn }
+ #2 { wordbreak } { } {#3#7}
+ }
+ {
+ \__text_map_if_ignorable:nTF {#1}
+ { \__text_map_collect:Nnnnn #2 {#3#7} {#4} {#5} {#6} }
+ {
+ \str_case:neTF {#1}
+ { \tl_map_function:nN {#5} \__text_map_collect_auxiii:n }
+ {
+ \__text_map_lookahead:Nnnnnw #2 { wordbreak } {#3} {#7}
+ { \__text_map_collect_auxiv:nnNnnnn {#5} {#6} }
+ }
+ {
+ \__text_map_output:Nn #2 {#3}
+ \__text_map_loop:Nnnw #2 { wordbreak } { } #7
+ }
+ }
+ }
}
-\cs_new:Npn \__text_map_lookahead:NnNN #1#2#3#4
+\cs_new:Npn \__text_map_collect_auxiii:n #1
+ { \exp_not:n { {#1} { } } }
+\cs_new:Npn \__text_map_collect_auxiv:nnNnnnn #1#2#3#4#5#6#7
{
- \__text_if_q_recursion_tail_stop_do:Nn #4 { #1 {#2} }
- \token_if_cs:NTF #4
+ \exp_args:Ne \__text_map_collect_auxv:nNnnnnn
{
- #1 {#2}
- \__text_map_loop:Nnw #1 { }
+ \__kernel_codepoint_to_wordbreak_class:n
+ { \__text_codepoint_from_chars:Nw #7 }
}
- { \__text_codepoint_process:nN { #3 #1 {#2} } }
- #4
+ #3 {#5} {#6} {#1} {#2} {#7}
}
-\cs_new:Npn \__text_map_output:Nn #1#2
- { \tl_if_blank:nF {#2} { #1 {#2} } }
-\cs_new:Npn \text_map_break:
- { \prg_map_break:Nn \text_map_break: { } }
-\cs_new:Npn \text_map_break:n
- { \prg_map_break:Nn \text_map_break: }
+\cs_new:Npn \__text_map_collect_auxv:nNnnnnn #1#2#3#4#5#6#7
+ {
+ \str_case:neTF {#1}
+ { \tl_map_function:nN {#6} \__text_map_collect_auxiii:n }
+ { \use:c { __text_map_ #1 :Nnnn } #2 { wordbreak } { } {#3#4#7} }
+ {
+ \__text_map_if_ignorable:nTF {#1}
+ {
+ \__text_map_lookahead:Nnnnnw #2 { wordbreak } {#3} {#4#7}
+ { \__text_map_collect_auxiv:nnNnnnn {#5} {#6} }
+ }
+ {
+ \__text_map_output:Nn #2 {#3}
+ \__text_map_loop:Nnnw #2 { wordbreak } { } #4#7
+ }
+ }
+ }
+\cs_new:Npn \__text_map_ALetter:Nnnn #1#2#3#4
+ {
+ \__text_map_output:Nn #1 {#3}
+ \__text_map_collect:Nnnnn #1 {#4}
+ { { ALetter } { Hebrew_Letter } { Numeric } }
+ { { MidLetter } { MidNumLet } { Single_Quote } }
+ { { ALetter } { Hebrew_Letter } }
+ }
+\cs_new:Npn \__text_map_Hebrew_Letter:Nnnn #1#2#3#4
+ {
+ \__text_map_output:Nn #1 {#3}
+ \__text_map_collect:Nnnnn #1 {#4}
+ { { ALetter } { Hebrew_Letter } { Numeric } { Single_Quote } }
+ { { MidLetter } { MidNumLet } { Double_Quote } }
+ { { Hebrew_Letter } }
+ }
+\cs_new:Npn \__text_map_Katakana:Nnnn #1#2#3#4
+ {
+ \__text_map_output:Nn #1 {#3}
+ \__text_map_collect:Nnnnn #1 {#4} { { Katakana } } { } { }
+ }
+\cs_new:Npn \__text_map_Numeric:Nnnn #1#2#3#4
+ {
+ \__text_map_output:Nn #1 {#3}
+ \__text_map_collect:Nnnnn #1 {#4}
+ { { ALetter } { Hebrew_Letter } { Numeric } }
+ { { MidNum } { MidNumLet } { Single_Quote } }
+ { { Numeric } }
+ }
+\cs_new:Npn \__text_map_WSegSpace:Nnnn #1#2#3#4
+ {
+ \__text_map_output:Nn #1 {#3}
+ \__text_map_collect:Nnnnn #1 {#4} { { WSegSpace } } { } { }
+ }
+\cs_new:Npn \__text_map_ExtendNumLet:Nnnn #1#2#3#4
+ {
+ \__text_map_output:Nn #1 {#3}
+ \__text_map_lookahead:Nnnnnw #1 { wordbreak } {#4} { }
+ \__text_map_ExtendNumLet_auxi:Nnnnn
+ }
+\cs_new:Npn \__text_map_ExtendNumLet_auxi:Nnnnn #1#2#3#4#5
+ {
+ \exp_args:Ne \__text_map_ExtendNumLet_auxii:nNnn
+ {
+ \__kernel_codepoint_to_wordbreak_class:n
+ { \__text_codepoint_from_chars:Nw #5 }
+ }
+ #1 {#3} {#5}
+ }
+\cs_new:Npn \__text_map_ExtendNumLet_auxii:nNnn #1#2#3#4
+ {
+ \str_case:nnTF {#1}
+ {
+ { ALetter } { }
+ { Hebrew_Letter } { }
+ { Numeric } { }
+ { Katakana } { }
+ { ExtendNumLet } { }
+ }
+ {
+ \cs_if_exist_use:cF { __text_map_ #1 :Nnnn } % TEMP?
+ { \__text_map_Other:Nnnn }
+ #2 { wordbreak } { } {#3#4}
+ }
+ {
+ \__text_map_if_ignorable:nTF {#1}
+ {
+ \__text_map_lookahead:Nnnnnw #2 { wordbreak } {#3#4} { }
+ \__text_map_ExtendNumLet_auxi:Nnnnn
+ }
+ {
+ \__text_map_output:Nn #2 {#3}
+ \__text_map_loop:Nnnw #2 { wordbreak } { } #4
+ }
+ }
+ }
\cs_new_protected:Npn \text_map_inline:nn #1#2
{
\int_gincr:N \g__kernel_prg_map_int
@@ -36888,6 +37564,16 @@
\prg_break_point:Nn \text_map_break:
{ \int_gdecr:N \g__kernel_prg_map_int }
}
+\cs_new_protected:Npn \text_words_map_inline:nn #1#2
+ {
+ \int_gincr:N \g__kernel_prg_map_int
+ \cs_gset_protected:cpn
+ { __text_map_ \int_use:N \g__kernel_prg_map_int :w } ##1 {#2}
+ \exp_args:Nnc \text_words_map_function:nN {#1}
+ { __text_map_ \int_use:N \g__kernel_prg_map_int :w }
+ \prg_break_point:Nn \text_map_break:
+ { \int_gdecr:N \g__kernel_prg_map_int }
+ }
%% File: l3text-purify.dtx
\__kernel_quark_new_test:N \__text_if_recursion_tail_stop:N
\cs_new:Npn \text_purify:n #1
Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex 2025-04-08 20:12:11 UTC (rev 74879)
@@ -19,7 +19,7 @@
%% and all files in that bundle must be distributed together.
%%
%% File: expl3.dtx
-\def\ExplFileDate{2025-01-18}%
+\def\ExplFileDate{2025-03-26}%
\let\ExplLoaderFileDate\ExplFileDate
\begingroup
\catcode`\_=11
Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx 2025-04-08 20:12:11 UTC (rev 74879)
@@ -19,7 +19,7 @@
%% and all files in that bundle must be distributed together.
%%
%% File: expl3.dtx
-\def\ExplFileDate{2025-01-18}%
+\def\ExplFileDate{2025-03-26}%
\let\ExplLoaderFileDate\ExplFileDate
\begingroup
\catcode`\_=11
Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty 2025-04-08 20:12:11 UTC (rev 74879)
@@ -19,7 +19,7 @@
%% and all files in that bundle must be distributed together.
%%
%% File: expl3.dtx
-\def\ExplFileDate{2025-01-18}%
+\def\ExplFileDate{2025-03-26}%
\let\ExplLoaderFileDate\ExplFileDate
\ProvidesPackage{expl3}
[%
Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/l3debug.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/l3debug.def 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/l3debug.def 2025-04-08 20:12:11 UTC (rev 74879)
@@ -19,7 +19,7 @@
%% and all files in that bundle must be distributed together.
%%
%% File: l3debug.dtx
-\ProvidesExplFile{l3debug.def}{2025-01-18}{}{L3 Debugging support}
+\ProvidesExplFile{l3debug.def}{2025-03-26}{}{L3 Debugging support}
\scan_new:N \s__debug_stop
\cs_new:Npn \__debug_use_i_delimit_by_s_stop:nw #1 #2 \s__debug_stop {#1}
\quark_new:N \q__debug_recursion_tail
Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/l3doc.cls
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/l3doc.cls 2025-04-08 20:11:39 UTC (rev 74878)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/l3doc.cls 2025-04-08 20:12:11 UTC (rev 74879)
@@ -20,7 +20,7 @@
%%
%% File: l3doc.dtx
\RequirePackage{calc}
-\ProvidesExplClass{l3doc}{2025-01-18}{}
+\ProvidesExplClass{l3doc}{2025-03-26}{}
{L3 Experimental documentation class}
\clist_new:N \g_docinput_clist
\seq_new:N \g_doc_functions_seq
More information about the tex-live-commits
mailing list.