% \iffalse meta-comment
%
%% File: l3candidates.dtx Copyright(C) 2012 The LaTeX3 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 released version of this bundle is available from CTAN.
%%
%% -----------------------------------------------------------------------
%%
%% The development version of the bundle can be found at
%%
%%    http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
%%%%%%%%%%%
%% NOTE: %%
%%%%%%%%%%%
%%
%%   Snapshots taken from the repository represent work in progress and may
%%   not work or may contain conflicting material!  We therefore ask
%%   people _not_ to put them into distributions, archives, etc. without
%%   prior consultation with the LaTeX Project Team.
%%
%% -----------------------------------------------------------------------
%%
%
%<*driver|package>
\RequirePackage{l3bootstrap}
\GetIdInfo$Id: l3candidates.dtx 3633 2012-05-12 20:11:32Z joseph $
  {L3 Experimental additions to l3kernel}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{^^A
%   The \textsf{l3candidates} package\\ Experimental additions to
%   \pkg{l3kernel}^^A
%   \thanks{This file describes v\ExplFileVersion,
%     last revised \ExplFileDate.}^^A
% }
%
% \author{^^A
%  The \LaTeX3 Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Released \ExplFileDate}
%
% \maketitle
%
% \begin{documentation}
%
% This module provides a space in which functions can be added to
% \pkg{l3kernel} (\pkg{expl3}) while still being experimental. As such, the
% functions here may not remain in their current form, or indeed at all,
% in \pkg{l3kernel} in the future. In contrast to the material in
% \pkg{l3experimental}, the functions here are all \emph{small} additions to
% the kernel. We encourage programmers to test them out and report back on
% the \texttt{LaTeX-L} mailing list.
%
% \section{Additions to \pkg{l3basics}}
%
% \begin{function}[EXP,TF]{\cs_if_exist_use:N, \cs_if_exist_use:c}
%   \begin{syntax}
%     \cs{cs_if_exist_use:NTF} \meta{control sequence} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   If the \meta{control sequence} exists, leave it in the input stream,
%   followed by the \meta{true code} (unbraced). Otherwise, leave the
%   \meta{false} code in the input stream. For example,
%   \begin{verbatim}
%     \cs_set:Npn \mypkg_use_character:N #1
%       { \cs_if_exist_use:cF { mypkg_#1:n } { \mypkg_default:N #1 } }
%   \end{verbatim}
%   calls the function |\mypkg_#1:n| if it exists, and falls back to
%   a default action otherwise. This could also be done (more slowly)
%   using \cs{str_case_x:nnn}.
%   \begin{texnote}
%     The \texttt{c} variants do not introduce the \meta{control sequence}
%     in the hash table if it is not there.
%   \end{texnote}
% \end{function}
%
% \section{Additions to \pkg{l3box}}
%
% \subsection{Affine transformations}
%
% Affine transformations are changes which (informally) preserve straight
% lines. Simple translations are affine transformations, but are better handled
% in \TeX{} by doing the translation first, then inserting an unmodified box.
% On the other hand, rotation and resizing of boxed material can best be
% handled by modifying boxes. These transformations are described here.
%
% \begin{function}{\box_resize:Nnn, \box_resize:cnn}
%   \begin{syntax}
%     \cs{box_resize:Nnn} \meta{box} \Arg{x-size} \Arg{y-size}
%   \end{syntax}
%   Resize the \meta{box} to \meta{x-size} horizontally and \meta{y-size}
%   vertically (both of the sizes are dimension expressions).
%   The \meta{y-size} is the vertical size (height plus depth) of
%   the box. The updated \meta{box} will be an hbox, irrespective of the nature
%   of the \meta{box}  before the resizing is applied. Negative sizes will
%   cause the material in the \meta{box} to be reversed in direction, but the
%   reference point of the \meta{box} will be unchanged. The resizing applies
%   within the current \TeX{} group level.
% \end{function}
%
% \begin{function}
%   {\box_resize_to_ht_plus_dp:Nn, \box_resize_to_ht_plus_dp:cn}
%   \begin{syntax}
%     \cs{box_resize_to_ht_plus_dp:Nn} \meta{box} \Arg{y-size}
%   \end{syntax}
%   Resize the \meta{box} to \meta{y-size} vertically, scaling the horizontal
%   size by the same amount (\meta{y-size} is a dimension expression).
%   The \meta{y-size} is the vertical size (height plus depth) of
%   the box.
%   The updated \meta{box} will be an hbox, irrespective of the nature
%   of the \meta{box}  before the resizing is applied. A negative size will
%   cause the material in the \meta{box} to be reversed in direction, but the
%   reference point of the \meta{box} will be unchanged. The resizing applies
%   within the current \TeX{} group level.
% \end{function}
%
% \begin{function}{\box_resize_to_wd:Nn, \box_resize_to_wd:cn}
%   \begin{syntax}
%     \cs{box_resize_to_wd:Nn} \meta{box} \Arg{x-size}
%   \end{syntax}
%   Resize the \meta{box} to \meta{x-size} horizontally, scaling the vertical
%   size by the same amount (\meta{x-size} is a dimension expression).
%   The updated \meta{box} will be an hbox, irrespective of the nature
%   of the \meta{box}  before the resizing is applied. A negative size will
%   cause the material in the \meta{box} to be reversed in direction, but the
%   reference point of the \meta{box} will be unchanged. The resizing applies
%   within the current \TeX{} group level.
% \end{function}
%
% \begin{function}{\box_rotate:Nn, \box_rotate:cn}
%   \begin{syntax}
%     \cs{box_rotate:Nn} \meta{box} \Arg{angle}
%   \end{syntax}
%   Rotates the \meta{box} by \meta{angle} (in degrees) anti-clockwise about
%   its reference point. The reference point of the updated box will be moved
%   horizontally such that it is at the left side of the smallest rectangle
%   enclosing the rotated material.
%   The updated \meta{box} will be an hbox, irrespective of the nature
%   of the \meta{box} before the rotation is applied. The rotation applies
%   within the current \TeX{} group level.
% \end{function}
%
% \begin{function}{\box_scale:Nnn, \box_scale:cnn}
%   \begin{syntax}
%     \cs{box_scale:Nnn} \meta{box} \Arg{x-scale} \Arg{y-scale}
%   \end{syntax}
%   Scales the \meta{box} by factors \meta{x-scale} and \meta{y-scale} in
%   the horizontal and vertical directions, respectively (both scales are
%   integer expressions). The updated \meta{box} will be an hbox, irrespective
%   of the nature of the \meta{box} before the scaling is applied. Negative
%   scalings will cause the material in the \meta{box} to be reversed in
%   direction, but the reference point of the \meta{box} will be unchanged.
%   The scaling applies within the current \TeX{} group level.
% \end{function}
%
% \subsection{Viewing part of a box}
%
% \begin{function}{\box_clip:N, \box_clip:c}
%   \begin{syntax}
%     \cs{box_clip:N} \meta{box}
%   \end{syntax}
%   Clips the \meta{box} in the output so that only material inside the
%   bounding box is displayed in the output. The updated \meta{box} will be an
%   hbox, irrespective of the nature of the \meta{box} before the clipping is
%   applied. The clipping applies within the current \TeX{} group level.
%
%   \textbf{These functions require the \LaTeX3 native drivers: they will
%   not work with the \LaTeXe{} \pkg{graphics} drivers!}
%
%   \begin{texnote}
%     Clipping is implemented by the driver, and as such the full content of
%     the box is places in the output file. Thus clipping does not remove
%     any information from the raw output, and hidden material can therefore
%     be viewed by direct examination of the file.
%   \end{texnote}
% \end{function}
%
% \begin{function}{\box_trim:Nnnnn, \box_trim:cnnnn}
%   \begin{syntax}
%     \cs{box_trim:Nnnnn} \meta{box} \Arg{left} \Arg{bottom} \Arg{right} \Arg{top}
%   \end{syntax}
%   Adjusts the bounding box of the \meta{box} \meta{left} is removed from
%   the left-hand edge of the bounding box, \meta{right} from the right-hand
%   edge and so fourth. All adjustments are \meta{dimension expressions}.
%   Material output of the bounding box will still be displayed in the output
%   unless \cs{box_clip:N} is subsequently applied.
%   The updated \meta{box} will be an
%   hbox, irrespective of the nature of the \meta{box} before the viewport
%   operation is applied. The adjustment applies within the current \TeX{}
%   group level.
% \end{function}
%
% \begin{function}{\box_viewport:Nnnnn, \box_viewport:cnnnn}
%   \begin{syntax}
%     \cs{box_viewport:Nnnnn} \meta{box} \Arg{llx} \Arg{lly} \Arg{urx} \Arg{ury}
%   \end{syntax}
%   Adjusts the bounding box of the \meta{box} such that it has lower-left
%   co-ordinates (\meta{llx}, \meta{lly}) and upper-right co-ordinates
%   (\meta{urx}, \meta{ury}). All four co-ordinate positions are
%   \meta{dimension expressions}. Material output of the bounding box will
%   still be displayed in the output unless \cs{box_clip:N} is
%   subsequently applied.
%   The updated \meta{box} will be an
%   hbox, irrespective of the nature of the \meta{box} before the viewport
%   operation is applied. The adjustment applies within the current \TeX{}
%   group level.
% \end{function}
%
% \subsection{Internal variables}
%
% \begin{variable}{\l__box_angle_fp}
%   The angle through which a box is rotated by \cs{box_rotate:Nn}, given in
%   degrees counter-clockwise. This value is required by the underlying
%   driver code in \pkg{l3driver} to carry out the driver-dependent part
%   of box rotation.
% \end{variable}
%
% \begin{variable}{\l__box_cos_fp, \l__box_sin_fp}
%   The sine and cosine of the angle through which a box is rotated by
%   \cs{box_rotate:Nn}: the values refer to the angle counter-clockwise. These
%   values are required by the underlying driver code in \pkg{l3driver} to
%   carry out the driver-dependent part of box rotation.
% \end{variable}
%
% \begin{variable}{\l__box_scale_x_fp, \l__box_scale_y_fp}
%   The scaling factors by which a box is scaled by \cs{box_scale:Nnn}
%   or \cs{box_resize:Nnn}. These values are required by the underlying
%   driver code in \pkg{l3driver} to carry out the driver-dependent part
%   of box rotation.
% \end{variable}
%
% \begin{variable}{\l__box_internal_box}
%   Box used for affine transformations, which is used to contain rotated
%   material when applying \cs{box_rotate:Nn}. This box must be correctly
%   constructed for the driver-dependent code in \pkg{l3driver} to function
%   correctly.
% \end{variable}
%
% \section{Additions to \pkg{l3clist}}
%
% \begin{function}{\clist_item:Nn, \clist_item:cn, \clist_item:nn}
%   \begin{syntax}
%     \cs{clist_item:Nn} \meta{comma list} \Arg{integer expression}
%   \end{syntax}
%   Indexing items in the \meta{comma list} from~$1$ at the top (left), this
%   function will evaluate the \meta{integer expression} and leave the
%   appropriate item from the comma list in the input stream. If the
%   \meta{integer expression} is negative, indexing occurs from the
%   bottom (right) of the comma list. When the \meta{integer expression}
%   is larger than the number of items in the \meta{comma list} (as
%   calculated by \cs{clist_count:N}) then the function will expand to
%   nothing.
%   \begin{texnote}
%     The result is returned within the \tn{unexpanded}
%     primitive (\cs{exp_not:n}), which means that the \meta{item}
%     will not expand further when appearing in an \texttt{x}-type
%     argument expansion.
%   \end{texnote}
% \end{function}
%
% \begin{function}
%   {
%     \clist_set_from_seq:NN,  \clist_set_from_seq:cN,
%     \clist_set_from_seq:Nc,  \clist_set_from_seq:cc,
%     \clist_gset_from_seq:NN, \clist_gset_from_seq:cN,
%     \clist_gset_from_seq:Nc, \clist_gset_from_seq:cc
%   }
%   \begin{syntax}
%     \cs{clist_set_from_seq:NN} \meta{comma list} \meta{sequence}
%   \end{syntax}
%   Sets the \meta{comma list} to be equal to the content of the
%   \meta{sequence}.
%   Items which contain either spaces or commas are surrounded by braces.
% \end{function}
%
% \begin{function}
%   {
%     \clist_const:Nn, \clist_const:Nx,
%     \clist_const:cn, \clist_const:cx
%   }
%   \begin{syntax}
%     \cs{clist_const:Nn} \meta{clist~var} \Arg{comma list}
%   \end{syntax}
%   Creates a new constant \meta{clist~var} or raises an error
%   if the name is already taken. The value of the
%   \meta{clist~var} will be set globally to the
%   \meta{comma list}.
% \end{function}
%
% \begin{function}[EXP, pTF]{\clist_if_empty:n}
%   \begin{syntax}
%     \cs{clist_if_empty_p:n} \Arg{comma list}
%     \cs{clist_if_empty:nTF} \Arg{comma list} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests if the \meta{comma list} is empty (containing no items).
%   The rules for space trimming are as for other \texttt{n}-type
%   comma-list functions, hence the comma list |{~,~,,~}| (without
%   outer braces) is empty, while |{~,{},}| (without outer braces)
%   contains one element, which happens to be empty: the comma-list
%   is not empty.
% \end{function}
%
% \begin{function}[EXP, added = 2012-06-26]{\clist_use:Nnnn}
%   \begin{syntax}
%     \cs{clist_use:Nnnn} \meta{clist~var} \Arg{separator~between~two} \Arg{separator~between~more~than~two} \Arg{separator~between~final~two}
%   \end{syntax}
%   Places the contents of the \meta{clist~var} in the input stream,
%   with the appropriate \meta{separator} between the items.  Namely, if
%   the comma list has more than $2$ items, the \meta{separator between
%     more than two} is placed between each pair of items except the
%   last, for which the \meta{separator between final two} is used.  If
%   the comma list has $2$ items, then they are placed in the input
%   stream separated by the \meta{separator between two}.  If the comma
%   list has $1$ item, it is placed in the input stream, and a comma
%   list with no items produces no output.  An error will be raised if
%   the variable does not exist or if it is invalid.
%
%   For example,
%   \begin{verbatim}
%     \clist_set:Nn \l_tmpa_clist { a , b , , c , {de} , f }
%     \clist_use:Nnnn \l_tmpa_clist { ~and~ } { ,~ } { ,~and~ }
%   \end{verbatim}
%   will insert \enquote{\texttt{a, b, c, de, and f}} in the input
%   stream.  The first separator argument is not used in this case
%   because the comma list has more than $2$ items.
%   \begin{texnote}
%     The result is returned within the \tn{unexpanded}
%     primitive (\cs{exp_not:n}), which means that the \meta{items}
%     will not expand further when appearing in an \texttt{x}-type
%     argument expansion.
%   \end{texnote}
% \end{function}
%
% \section{Additions to \pkg{l3coffins}}
%
% \begin{function}{\coffin_resize:Nnn, \coffin_resize:cnn}
%   \begin{syntax}
%     \cs{coffin_resize:Nnn} \meta{coffin} \Arg{width} \Arg{total-height}
%   \end{syntax}
%   Resized the \meta{coffin} to \meta{width} and \meta{total-height},
%   both of which should be given as dimension expressions.
% \end{function}
%
% \begin{function}{\coffin_rotate:Nn, \coffin_rotate:cn}
%   \begin{syntax}
%     \cs{coffin_rotate:Nn} \meta{coffin} \Arg{angle}
%   \end{syntax}
%   Rotates the \meta{coffin} by the given \meta{angle} (given in
%   degrees counter-clockwise). This process will rotate both the
%   coffin content and poles. Multiple rotations will not result in
%   the bounding box of the coffin growing unnecessarily.
% \end{function}
%
% \begin{function}{\coffin_scale:Nnn, \coffin_scale:cnn}
%   \begin{syntax}
%     \cs{coffin_scale:Nnn} \meta{coffin} \Arg{x-scale} \Arg{y-scale}
%   \end{syntax}
%   Scales the \meta{coffin} by a factors \meta{x-scale} and
%   \meta{y-scale} in the horizontal and vertical directions,
%   respectively. The two scale factors should be given as real numbers.
% \end{function}
%
% \section{Additions to \pkg{l3file}}
%
% \begin{function}[added = 2012-02-11]{\ior_map_inline:Nn}
%   \begin{syntax}
%     \cs{ior_map_inline:Nn} \meta{stream} \Arg{inline function}
%   \end{syntax}
%   Applies the \meta{inline function} to \meta{lines} obtained by
%   reading one or more lines (until an equal number of left and right
%   braces are found) from the \meta{stream}. The \meta{inline function}
%   should consist of code which will receive the \meta{line} as |#1|.
%   Note that \TeX{} removes trailing space and tab characters
%   (character codes 32 and 9) from every line upon input.  \TeX{} also
%   ignores any trailing new-line marker from the file it reads.
% \end{function}
%
% \begin{function}[added = 2012-02-11]{\ior_str_map_inline:Nn}
%   \begin{syntax}
%     \cs{ior_str_map_inline:Nn} \Arg{stream} \Arg{inline function}
%   \end{syntax}
%   Applies the \meta{inline function} to every \meta{line}
%   in the \meta{sream}. The material is read from the \meta{stream}
%   as a series of tokens with category code $12$ (other), with the
%   exception of space characters which are given category code $10$
%   (space). The \meta{inline function} should consist of code which
%   will receive the \meta{line} as |#1|.
%   Note that \TeX{} removes trailing space and tab characters
%   (character codes 32 and 9) from every line upon input.  \TeX{} also
%   ignores any trailing new-line marker from the file it reads.
% \end{function}
%
% \begin{function}[added = 2012-06-29]{\ior_map_break:}
%   \begin{syntax}
%     \cs{ior_map_break:}
%   \end{syntax}
%   Used to terminate a \cs{ior_map_\ldots} function before all
%   lines from the \meta{stream} have been processed. This will
%   normally take place within a conditional statement, for example
%   \begin{verbatim}
%     \ior_map_inline:Nn \l_my_ior
%       {
%         \str_if_eq:nnTF { #1 } { bingo }
%           { \ior_map_break: }
%           {
%             % Do something useful
%           }
%       }
%   \end{verbatim}
%   Use outside of a \cs{ior_map_\ldots} scenario will lead to low
%   level \TeX{} errors.
%   \begin{texnote}
%     When the mapping is broken, additional tokens may be inserted by the
%     internal macro \cs{__prg_break_point:Nn} before further items are taken
%     from the input stream. This will depend on the design of the mapping
%     function.
%   \end{texnote}
% \end{function}
%
% \begin{function}[added = 2012-06-29]{\ior_map_break:n}
%   \begin{syntax}
%     \cs{ior_map_break:n} \Arg{tokens}
%   \end{syntax}
%   Used to terminate a \cs{ior_map_\ldots} function before all
%   lines in the \meta{stream} have been processed, inserting
%   the \meta{tokens} after the mapping has ended. This will
%   normally take place within a conditional statement, for example
%   \begin{verbatim}
%     \ior_map_inline:Nn \l_my_ior
%       {
%         \str_if_eq:nnTF { #1 } { bingo }
%           { \ior_map_break:n { <tokens> } }
%           {
%             % Do something useful
%           }
%       }
%   \end{verbatim}
%   Use outside of a \cs{ior_map_\ldots} scenario will lead to low
%   level \TeX{} errors.
%   \begin{texnote}
%     When the mapping is broken, additional tokens may be inserted by the
%     internal macro \cs{__prg_break_point:Nn} before the \meta{tokens} are
%     inserted into the input stream.
%     This will depend on the design of the mapping function.
%   \end{texnote}
% \end{function}
%
% \section{Additions to \pkg{l3fp}}
%
% \begin{function}
%   {
%     \fp_set_from_dim:Nn,  \fp_set_from_dim:cn,
%     \fp_gset_from_dim:Nn, \fp_gset_from_dim:cn
%   }
%   \begin{syntax}
%     \cs{fp_set_from_dim:Nn} \meta{floating point variable} \Arg{dimexpr}
%   \end{syntax}
%   Sets the \meta{floating point variable} to the distance represented
%   by the \meta{dimension expression} in the units points. This means
%   that distances given in other units are first converted to points
%   before being assigned to the \meta{floating point variable}.
% \end{function}
%
% \section{Additions to \pkg{l3prop}}
%
% \begin{function}[rEXP]
%   {\prop_map_tokens:Nn, \prop_map_tokens:cn}
%   \begin{syntax}
%     \cs{prop_map_tokens:Nn} \meta{property list} \Arg{code}
%   \end{syntax}
%   Analogue of \cs{prop_map_function:NN} which maps several tokens
%   instead of a single function.  The \meta{code} receives each
%   key--value pair in the \meta{property list} as two trailing brace
%   groups. For instance,
%   \begin{verbatim}
%     \prop_map_tokens:Nn \l_my_prop { \str_if_eq:nnT { mykey } }
%   \end{verbatim}
%   will expand to the value corresponding to \texttt{mykey}: for each
%   pair in \cs{l_my_prop} the function \cs{str_if_eq:nnT} receives
%   \texttt{mykey}, the \meta{key} and the \meta{value} as its three
%   arguments.  For that specific task, \cs{prop_get:Nn} is faster.
% \end{function}
%
% \begin{function}[EXP]{\prop_get:Nn, \prop_get:cn}
%   \begin{syntax}
%     \cs{prop_get:Nn} \meta{property list} \Arg{key}
%   \end{syntax}
%   Expands to the \meta{value} corresponding to the \meta{key} in
%   the \meta{property list}. If the \meta{key} is missing, this has
%   an empty expansion.
%   \begin{texnote}
%     This function is slower than the non-expandable analogue
%     \cs{prop_get:NnN}.
%     The result is returned within the \tn{unexpanded}
%     primitive (\cs{exp_not:n}), which means that the \meta{value}
%     will not expand further when appearing in an \texttt{x}-type
%     argument expansion.
%   \end{texnote}
% \end{function}
%
% \section{Additions to \pkg{l3seq}}
%
% \begin{function}[EXP]{\seq_item:Nn, \seq_item:cn}
%   \begin{syntax}
%     \cs{seq_item:Nn} \meta{sequence} \Arg{integer expression}
%   \end{syntax}
%   Indexing items in the \meta{sequence} from~$1$ at the top (left), this
%   function will evaluate the \meta{integer expression} and leave the
%   appropriate item from the sequence in the input stream. If the
%   \meta{integer expression} is negative, indexing occurs from the
%   bottom (right) of the sequence. When the \meta{integer expression}
%   is larger than the number of items in the \meta{sequence} (as
%   calculated by \cs{seq_count:N}) then the function will expand to
%   nothing.
%   \begin{texnote}
%     The result is returned within the \tn{unexpanded}
%     primitive (\cs{exp_not:n}), which means that the \meta{item}
%     will not expand further when appearing in an \texttt{x}-type
%     argument expansion.
%   \end{texnote}
% \end{function}
%
% \begin{function}[rEXP]
%   {
%     \seq_mapthread_function:NNN, \seq_mapthread_function:NcN,
%     \seq_mapthread_function:cNN, \seq_mapthread_function:ccN
%   }
%   \begin{syntax}
%     \cs{seq_mapthread_function:NNN} \meta{seq_1} \meta{seq_2} \meta{function}
%   \end{syntax}
%   Applies \meta{function} to every pair of items
%   \meta{seq_1-item}--\meta{seq_2-item} from the two sequences, returning
%   items from both sequences from left to right.   The \meta{function} will
%   receive two \texttt{n}-type arguments for each iteration. The  mapping
%   will terminate when
%   the end of either sequence is reached (\emph{i.e.}~whichever sequence has
%   fewer items determines how many iterations
%   occur).
% \end{function}
%
% \begin{function}
%   {
%     \seq_set_from_clist:NN,  \seq_set_from_clist:cN,
%     \seq_set_from_clist:Nc,  \seq_set_from_clist:cc,
%     \seq_set_from_clist:Nn,  \seq_set_from_clist:cn,
%     \seq_gset_from_clist:NN, \seq_gset_from_clist:cN,
%     \seq_gset_from_clist:Nc, \seq_gset_from_clist:cc,
%     \seq_gset_from_clist:Nn, \seq_gset_from_clist:cn
%   }
%   \begin{syntax}
%     \cs{seq_set_from_clist:NN} \meta{sequence} \meta{comma-list}
%   \end{syntax}
%   Sets the \meta{sequence} within the current \TeX{} group to be equal
%   to the content of the \meta{comma-list}.
% \end{function}
%
% \begin{function}{\seq_reverse:N, \seq_greverse:N}
%   \begin{syntax}
%     \cs{seq_reverse:N} \meta{sequence}
%   \end{syntax}
%   Reverses the order of items in the \meta{sequence}, and
%   assigns the result to \meta{sequence}, locally or globally
%   according to the variant chosen.
% \end{function}
%
% \begin{function}{\seq_set_filter:NNn, \seq_gset_filter:NNn}
%   \begin{syntax}
%     \cs{seq_set_filter:NNn} \meta{sequence_1} \meta{sequence_2} \Arg{inline boolexpr}
%   \end{syntax}
%   Evaluates the \meta{inline boolexpr} for every \meta{item} stored
%   within the \meta{sequence_2}. The \meta{inline boolexpr} will
%   receive the \meta{item} as |#1|. The sequence of all \meta{items}
%   for which the \meta{inline boolexpr} evaluated to \texttt{true}
%   is assigned to \meta{sequence_1}.
%   \begin{texnote}
%     Contrarily to other mapping functions, \cs{seq_map_break:} cannot
%     be used in this function, and will lead to low-level \TeX{} errors.
%   \end{texnote}
% \end{function}
%
% \begin{function}[added = 2011-12-22]
%   {\seq_set_map:NNn, \seq_gset_map:NNn}
%   \begin{syntax}
%     \cs{seq_set_map:NNn} \meta{sequence_1} \meta{sequence_2} \Arg{inline function}
%   \end{syntax}
%   Applies \meta{inline function} to every \meta{item} stored
%   within the \meta{sequence_2}. The \meta{inline function} should
%   consist of code which will receive the \meta{item} as |#1|.
%   The sequence resulting from \texttt{x}-expanding
%   \meta{inline function} applied to each \meta{item}
%   is assigned to \meta{sequence_1}. As such, the code
%   in \meta{inline function} should be expandable.
%   \begin{texnote}
%     Contrarily to other mapping functions, \cs{seq_map_break:} cannot
%     be used in this function, and will lead to low-level \TeX{} errors.
%   \end{texnote}
% \end{function}
%
% \begin{function}[EXP, added = 2012-06-26]{\seq_use:Nnnn}
%   \begin{syntax}
%     \cs{seq_use:Nnnn} \meta{seq~var} \Arg{separator~between~two} \Arg{separator~between~more~than~two} \Arg{separator~between~final~two}
%   \end{syntax}
%   Places the contents of the \meta{seq~var} in the input stream, with
%   the appropriate \meta{separator} between the items.  Namely, if the
%   sequence has more than $2$ items, the \meta{separator between more
%     than two} is placed between each pair of items except the last,
%   for which the \meta{separator between final two} is used.  If the
%   sequence has $2$ items, then they are placed in the input stream
%   separated by the \meta{separator between two}.  If the sequence has
%   $1$ item, it is placed in the input stream, and an empty sequence
%   produces no output.  An error will be raised if the variable does
%   not exist or if it is invalid.
%
%   For example,
%   \begin{verbatim}
%     \seq_set_split:Nnn \l_tmpa_seq { | } { a | b | c | {de} | f }
%     \seq_use:Nnnn \l_tmpa_seq { ~and~ } { ,~ } { ,~and~ }
%   \end{verbatim}
%   will insert \enquote{\texttt{a, b, c, de, and f}} in the input
%   stream.  The first separator argument is not used in this case
%   because the sequence has more than $2$ items.
%   \begin{texnote}
%     The result is returned within the \tn{unexpanded}
%     primitive (\cs{exp_not:n}), which means that the \meta{items}
%     will not expand further when appearing in an \texttt{x}-type
%     argument expansion.
%   \end{texnote}
% \end{function}
%
% \section{Additions to \pkg{l3skip}}
%
% \begin{function}{\skip_split_finite_else_action:nnNN}
%   \begin{syntax}
%     \cs{skip_split_finite_else_action:nnNN} \Arg{skipexpr} \Arg{action}
%     ~~\meta{dimen_1} \meta{dimen_2}
%   \end{syntax}
%   Checks if the \meta{skipexpr} contains finite glue. If it does then it
%   assigns
%   \meta{dimen_1} the stretch component and \meta{dimen_2} the shrink
%   component. If
%   it contains infinite glue set \meta{dimen_1} and \meta{dimen_2} to $0$\,pt
%   and place |#2| into the input stream: this is usually an error or
%   warning message of some sort.
% \end{function}
%
% \section{Additions to \pkg{l3tl}}
%
% \begin{function}[EXP,pTF]{\tl_if_single_token:n}
%   \begin{syntax}
%   \cs{tl_if_single_token_p:n} \Arg{token list}
%   \cs{tl_if_single_token:nTF} \Arg{token list} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests if the token list consists of exactly one token, \emph{i.e.}~is
%   either a single space character or a single \enquote{normal} token.
%   Token groups (|{|\ldots|}|) are not single tokens.
% \end{function}
%
% \begin{function}[EXP]{\tl_reverse_tokens:n}
%   \begin{syntax}
%     \cs{tl_reverse_tokens:n} \Arg{tokens}
%   \end{syntax}
%   This function, which works directly on \TeX{} tokens, reverses
%   the order of the \meta{tokens}: the first will be the last and
%   the last will become first. Spaces are preserved. The reversal
%   also operates within brace groups, but the braces themselves
%   are not exchanged, as this would lead to an unbalanced token
%   list. For instance, \cs{tl_reverse_tokens:n} |{a~{b()}}|
%   leaves |{)(b}~a| in the input stream. This function requires
%   two steps of expansion.
%   \begin{texnote}
%     The result is returned within the \tn{unexpanded}
%     primitive (\cs{exp_not:n}), which means that the token
%     list will not expand further when appearing in an \texttt{x}-type
%     argument expansion.
%   \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\tl_count_tokens:n}
%   \begin{syntax}
%     \cs{tl_count_tokens:n} \Arg{tokens}
%   \end{syntax}
%   Counts the number of \TeX{} tokens in the \meta{tokens} and leaves
%   this information in the input stream. Every token, including spaces and
%   braces, contributes one to the total; thus for instance, the token count of
%   |a~{bc}| is $6$.
%   This function requires three expansions,
%   giving an \meta{integer denotation}.
% \end{function}
%
% \begin{function}[EXP]{\tl_expandable_uppercase:n,\tl_expandable_lowercase:n}
%   \begin{syntax}
%     \cs{tl_expandable_uppercase:n} \Arg{tokens}
%     \cs{tl_expandable_lowercase:n} \Arg{tokens}
%   \end{syntax}
%   The \cs{tl_expandable_uppercase:n} function works through all of
%   the \meta{tokens}, replacing characters in the range |a|--|z|
%   (with arbitrary category code) by the corresponding letter
%   in the range |A|--|Z|, with category code $11$ (letter). Similarly,
%   \cs{tl_expandable_lowercase:n} replaces characters in the range
%   |A|--|Z| by letters in the range |a|--|z|, and leaves other tokens
%   unchanged. This function requires two steps of expansion.
%   \begin{texnote}
%     Begin-group and end-group characters are normalized and become
%     |{| and |}|, respectively.
%     The result is returned within the \tn{unexpanded}
%     primitive (\cs{exp_not:n}), which means that the token
%     list will not expand further when appearing in an \texttt{x}-type
%     argument expansion.
%   \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\tl_item:nn, \tl_item:Nn, \tl_item:cn}
%   \begin{syntax}
%     \cs{tl_item:nn} \Arg{token list} \Arg{integer expression}
%   \end{syntax}
%   Indexing items in the \meta{token list} from~$1$ on the left, this
%   function will evaluate the \meta{integer expression} and leave the
%   appropriate item from the \meta{token list} in the input stream.
%   If the \meta{integer expression} is negative, indexing occurs from
%   the right of the token list, starting at $-1$ for the right-most item.
%   If the index is out of bounds, then thr function expands to nothing.
%   \begin{texnote}
%     The result is returned within the \tn{unexpanded}
%     primitive (\cs{exp_not:n}), which means that the \meta{item}
%     will not expand further when appearing in an \texttt{x}-type
%     argument expansion.
%   \end{texnote}
% \end{function}
%
% \section{Additions to \pkg{l3tokens}}
%
% \begin{function}{\char_set_active:Npn,  \char_set_active:Npx}
%   \begin{syntax}
%      \cs{char_set_active:Npn} \meta{char} \meta{parameters} \Arg{code}
%   \end{syntax}
%   Makes \meta{char} an active character to expand to \meta{code} as
%   replacement text.
%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
%   \emph{etc.}) will be replaced by those absorbed. The \meta{char} is
%   made active within the current \TeX{} group level, and the definition
%   is also local.
% \end{function}
%
% \begin{function}{\char_gset_active:Npn, \char_gset_active:Npx}
%   \begin{syntax}
%      \cs{char_gset_active:Npn} \meta{char} \meta{parameters} \Arg{code}
%   \end{syntax}
%   Makes \meta{char} an active character to expand to \meta{code} as
%   replacement text.
%   Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
%   \emph{etc.}) will be replaced by those absorbed. The \meta{char} is
%   made active within the current \TeX{} group level, but the definition
%   is global. This function is therefore suited to cases where an active
%   character definition should be applied only in some context (where the
%   \meta{char} is again made active).
% \end{function}
%
% \begin{function}{\char_set_active_eq:NN}
%   \begin{syntax}
%      \cs{char_set_active_eq:NN} \meta{char} \meta{function}
%   \end{syntax}
%   Makes \meta{char} an active character equivalent in meaning to the
%   \meta{function} (which may itself be an active character). The \meta{char}
%   is made active within the current \TeX{} group level, and the definition
%   is also local.
% \end{function}
%
% \begin{function}{\char_gset_active_eq:NN}
%   \begin{syntax}
%      \cs{char_gset_active_eq:NN} \meta{char} \meta{function}
%   \end{syntax}
%   Makes \meta{char} an active character equivalent in meaning to the
%   \meta{function} (which may itself be an active character). The \meta{char}
%   is made active within the current \TeX{} group level, but the definition
%   is global. This function is therefore suited to cases where an active
%   character definition should be applied only in some context (where the
%   \meta{char} is again made active).
% \end{function}
%
% \begin{function}[TF]{\peek_N_type:}
%   \begin{syntax}
%     \cs{peek_N_type:TF} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests if the next \meta{token} in the input stream can be safely
%   grabbed as an \texttt{N}-type argument. The test will be \meta{false}
%   if the next \meta{token} is either an explicit or implicit
%   begin-group or end-group token (with any character code), or
%   an explicit or implicit space character (with character code $32$
%   and category code $10$), and \meta{true} in all other cases.
%   Note that a \meta{true} result ensures that the next \meta{token} is
%   a valid \texttt{N}-type argument. However, if the next \meta{token}
%   is for instance \cs{c_space_token}, the test will take the
%   \meta{false} branch, even though the next \meta{token} is in fact
%   a valid \texttt{N}-type argument. The \meta{token} will be left
%   in the input stream after the \meta{true code} or \meta{false code}
%   (as appropriate to the result of the test).
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3candidates} Implementation}
%
%    \begin{macrocode}
%<*initex|package>
%    \end{macrocode}
%
%    \begin{macrocode}
%<*package>
\ProvidesExplPackage
  {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
\__expl_package_check:
%</package>
%    \end{macrocode}
%
% \subsection{Additions to \pkg{l3box}}
%
%    \begin{macrocode}
%<@@=box>
%    \end{macrocode}
%
% \subsection{Affine transformations}
%
% \begin{variable}{\l_@@_angle_fp}
%   When rotating boxes, the angle itself may be needed by the
%   engine-dependent code. This is done using the \pkg{fp} module so
%   that the value is tidied up properly.
%    \begin{macrocode}
\fp_new:N \l_@@_angle_fp
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_cos_fp, \l_@@_sin_fp}
%   These are used to hold the calculated sine and cosine values while
%   carrying out a rotation.
%    \begin{macrocode}
\fp_new:N \l_@@_cos_fp
\fp_new:N \l_@@_sin_fp
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}
%   {\l_@@_top_dim, \l_@@_bottom_dim, \l_@@_left_dim, \l_@@_right_dim}
%   These are the positions of the four edges of a box before
%   manipulation.
%    \begin{macrocode}
\dim_new:N \l_@@_top_dim
\dim_new:N \l_@@_bottom_dim
\dim_new:N \l_@@_left_dim
\dim_new:N \l_@@_right_dim
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}
%  {
%    \l_@@_top_new_dim,  \l_@@_bottom_new_dim ,
%    \l_@@_left_new_dim, \l_@@_right_new_dim
%  }
%   These are the positions of the four edges of a box after
%   manipulation.
%    \begin{macrocode}
\dim_new:N \l_@@_top_new_dim
\dim_new:N \l_@@_bottom_new_dim
\dim_new:N \l_@@_left_new_dim
\dim_new:N \l_@@_right_new_dim
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_internal_box}
%   Scratch space, but also needed by some parts of the driver.
%    \begin{macrocode}
\box_new:N \l_@@_internal_box
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}{\box_rotate:Nn}
% \begin{macro}[aux]{\@@_rotate:N}
% \begin{macro}[aux]{\@@_rotate_x:nnN, \@@_rotate_y:nnN}
% \begin{macro}[aux]
%   {
%     \@@_rotate_quadrant_one:,   \@@_rotate_quadrant_two:,
%     \@@_rotate_quadrant_three:, \@@_rotate_quadrant_four:
%   }
%   Rotation of a box starts with working out the relevant sine and
%   cosine. The actual rotation is in an auxiliary to keep the flow slightly
%   clearer
%    \begin{macrocode}
\cs_new_protected:Npn \box_rotate:Nn #1#2
  {
    \hbox_set:Nn #1
      {
        \group_begin:
          \fp_set:Nn \l_@@_angle_fp {#2}
          \fp_set:Nn \l_@@_sin_fp { sin ( \l_@@_angle_fp * deg ) }
          \fp_set:Nn \l_@@_cos_fp { cos ( \l_@@_angle_fp * deg ) }
          \@@_rotate:N #1
        \group_end:
    }
  }
%    \end{macrocode}
%   The edges of the box are then recorded: the left edge will
%   always be at zero. Rotation of the four edges then takes place: this is
%   most efficiently done on a quadrant by quadrant basis.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_rotate:N #1
  {
    \dim_set:Nn \l_@@_top_dim    {  \box_ht:N #1 }
    \dim_set:Nn \l_@@_bottom_dim { -\box_dp:N #1 }
    \dim_set:Nn \l_@@_right_dim  {  \box_wd:N #1 }
    \dim_zero:N \l_@@_left_dim
%    \end{macrocode}
%   The next step is to work out the $x$ and $y$ coordinates of vertices of
%   the rotated box in relation to its original coordinates. The box can be
%   visualized with vertices $B$, $C$, $D$ and $E$ is illustrated
%   (Figure~\ref{fig:rotation}). The vertex $O$ is the reference point on the
%   baseline, and in this implementation is also the centre of rotation.
%   \begin{figure}
%     \centering
%     \setlength{\unitlength}{3pt}^^A
%     \begin{picture}(34,36)(12,44)
%       \thicklines
%       \put(20,52){\dashbox{1}(20,21){}}
%       \put(20,80){\line(0,-1){36}}
%       \put(12,58){\line(1, 0){34}}
%       \put(41,59){A}
%       \put(40,74){B}
%       \put(21,74){C}
%       \put(21,49){D}
%       \put(40,49){E}
%       \put(21,59){O}
%     \end{picture}
%     \caption{Co-ordinates of a box prior to rotation.}
%     \label{fig:rotation}
%   \end{figure}
%   The formulae are, for a point $P$ and angle $\alpha$:
%   \[
%     \begin{array}{l}
%       P'_x = P_x - O_x \\
%       P'_y = P_y - O_y \\
%       P''_x =  ( P'_x \cos(\alpha)) - ( P'_y \sin(\alpha) ) \\
%       P''_y =  ( P'_x \sin(\alpha)) + ( P'_y \cos(\alpha) ) \\
%       P'''_x = P''_x + O_x + L_x \\
%       P'''_y = P''_y + O_y
%    \end{array}
%   \]
%   The \enquote{extra} horizontal translation $L_x$ at the end is calculated
%   so that the leftmost point of the resulting box has $x$-coordinate $0$.
%   This is desirable as \TeX{} boxes must have the reference point at
%   the left edge of the box. (As $O$ is always $(0,0)$, this part of the
%   calculation is omitted here.)
%    \begin{macrocode}
    \fp_compare:nNnTF \l_@@_sin_fp > \c_zero_fp
      {
        \fp_compare:nNnTF \l_@@_cos_fp > \c_zero_fp
          { \@@_rotate_quadrant_one: }
          { \@@_rotate_quadrant_two: }
      }
      {
        \fp_compare:nNnTF \l_@@_cos_fp < \c_zero_fp
          { \@@_rotate_quadrant_three: }
          { \@@_rotate_quadrant_four: }
      }
%    \end{macrocode}
%   The position of the box edges are now known, but the box at this
%   stage be misplaced relative to the current \TeX{} reference point. So the
%   content of the box is moved such that the reference point of the
%   rotated box will be in the same place as the original.
%    \begin{macrocode}
    \hbox_set:Nn \l_@@_internal_box { \box_use:N #1 }
    \hbox_set:Nn \l_@@_internal_box
      {
        \tex_kern:D -\l_@@_left_new_dim
        \hbox:n
          {
            \__driver_box_rotate_begin:
            \box_use:N \l_@@_internal_box
            \__driver_box_rotate_end:
          }
      }
%    \end{macrocode}
%   Tidy up the size of the box so that the material is actually inside
%   the bounding box. The result can then be used to reset the original
%   box.
%    \begin{macrocode}
    \box_set_ht:Nn \l_@@_internal_box {  \l_@@_top_new_dim }
    \box_set_dp:Nn \l_@@_internal_box { -\l_@@_bottom_new_dim }
    \box_set_wd:Nn \l_@@_internal_box
      { \l_@@_right_new_dim - \l_@@_left_new_dim }
    \box_use:N \l_@@_internal_box
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%   These functions take a general point $(|#1|, |#2|)$ and rotate its
%   location about the origin, using the previously-set sine and cosine
%   values. Each function gives only one component of the location of the
%   updated point. This is because for rotation of a box each step needs
%   only one value, and so performance is gained by avoiding working
%   out both $x'$ and $y'$ at the same time. Contrast this with
%   the equivalent function in the \pkg{l3coffins} module, where both parts
%   are needed.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_rotate_x:nnN #1#2#3
  {
    \dim_set:Nn #3
      {
        \fp_to_dim:n
          {
                \l_@@_cos_fp * \dim_to_fp:n {#1}
            - ( \l_@@_sin_fp * \dim_to_fp:n {#2} )
          }
      }
  }
\cs_new_protected:Npn \@@_rotate_y:nnN #1#2#3
  {
    \dim_set:Nn #3
      {
        \fp_to_dim:n
          {
              \l_@@_sin_fp * \dim_to_fp:n {#1}
            + \l_@@_cos_fp * \dim_to_fp:n {#2}
          }
      }
  }
%    \end{macrocode}
%   Rotation of the edges is done using a different formula for each
%   quadrant. In every case, the top and bottom edges only need the
%   resulting $y$-values, whereas the left and right edges need the
%   $x$-values. Each case is a question of picking out which corner
%   ends up at with the maximum top, bottom, left and right value. Doing
%   this by hand means a lot less calculating and avoids lots of
%   comparisons.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_rotate_quadrant_one:
  {
    \@@_rotate_y:nnN \l_@@_right_dim \l_@@_top_dim
      \l_@@_top_new_dim
    \@@_rotate_y:nnN \l_@@_left_dim  \l_@@_bottom_dim
      \l_@@_bottom_new_dim
    \@@_rotate_x:nnN \l_@@_left_dim  \l_@@_top_dim
      \l_@@_left_new_dim
    \@@_rotate_x:nnN \l_@@_right_dim \l_@@_bottom_dim
      \l_@@_right_new_dim
  }
\cs_new_protected:Npn \@@_rotate_quadrant_two:
  {
    \@@_rotate_y:nnN \l_@@_right_dim \l_@@_bottom_dim
      \l_@@_top_new_dim
    \@@_rotate_y:nnN \l_@@_left_dim  \l_@@_top_dim
      \l_@@_bottom_new_dim
    \@@_rotate_x:nnN \l_@@_right_dim  \l_@@_top_dim
      \l_@@_left_new_dim
    \@@_rotate_x:nnN \l_@@_left_dim   \l_@@_bottom_dim
      \l_@@_right_new_dim
  }
\cs_new_protected:Npn \@@_rotate_quadrant_three:
  {
    \@@_rotate_y:nnN \l_@@_left_dim  \l_@@_bottom_dim
      \l_@@_top_new_dim
    \@@_rotate_y:nnN \l_@@_right_dim \l_@@_top_dim
      \l_@@_bottom_new_dim
    \@@_rotate_x:nnN \l_@@_right_dim \l_@@_bottom_dim
      \l_@@_left_new_dim
    \@@_rotate_x:nnN \l_@@_left_dim   \l_@@_top_dim
      \l_@@_right_new_dim
  }
\cs_new_protected:Npn \@@_rotate_quadrant_four:
  {
    \@@_rotate_y:nnN \l_@@_left_dim  \l_@@_top_dim
      \l_@@_top_new_dim
    \@@_rotate_y:nnN \l_@@_right_dim \l_@@_bottom_dim
      \l_@@_bottom_new_dim
    \@@_rotate_x:nnN \l_@@_left_dim  \l_@@_bottom_dim
      \l_@@_left_new_dim
    \@@_rotate_x:nnN \l_@@_right_dim \l_@@_top_dim
      \l_@@_right_new_dim
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{variable}{\l_@@_scale_x_fp, \l_@@_scale_y_fp}
%   Scaling is potentially-different in the two axes.
%    \begin{macrocode}
\fp_new:N \l_@@_scale_x_fp
\fp_new:N \l_@@_scale_y_fp
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}{\box_resize:Nnn, \box_resize:cnn}
% \begin{macro}[aux]{\@@_resize:Nnn}
%   Resizing a box starts by working out the various dimensions of the
%   existing box.
%    \begin{macrocode}
\cs_new_protected:Npn \box_resize:Nnn #1#2#3
  {
    \hbox_set:Nn #1
      {
        \group_begin:
          \dim_set:Nn \l_@@_top_dim    {  \box_ht:N #1 }
          \dim_set:Nn \l_@@_bottom_dim { -\box_dp:N #1 }
          \dim_set:Nn \l_@@_right_dim  {  \box_wd:N #1 }
          \dim_zero:N \l_@@_left_dim
%    \end{macrocode}
%   The $x$-scaling and resulting box size is easy enough to work
%   out: the dimension is that given as |#2|, and the scale is simply the
%   new width divided by the old one.
%    \begin{macrocode}
          \fp_set:Nn \l_@@_scale_x_fp
            { \dim_to_fp:n {#2} / ( \dim_to_fp:n \l_@@_right_dim ) }
%    \end{macrocode}
%   The $y$-scaling needs both the height and the depth of the current box.
%    \begin{macrocode}
          \fp_set:Nn \l_@@_scale_y_fp
            {
              \dim_to_fp:n {#3} /
                ( \dim_to_fp:n { \l_@@_top_dim - \l_@@_bottom_dim } )
            }
%    \end{macrocode}
%   Hand off to the auxiliary which does the work.
%    \begin{macrocode}
          \@@_resize:Nnn #1 {#2} {#3}
        \group_end:
      }
  }
\cs_generate_variant:Nn \box_resize:Nnn { c }
%    \end{macrocode}
%   With at least one real scaling to do, the next phase is to find the new
%   edge co-ordinates. In the $x$~direction this is relatively easy: just
%   scale the right edge. This is done using the absolute value of the
%   scale so that the new edge is in the correct place. In the $y$~direction,
%   both dimensions have to be scaled, and this again needs the absolute
%   scale value. Once that is all done, the common resize/rescale code can
%   be employed.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_resize:Nnn #1#2#3
  {
    \dim_set:Nn \l_@@_right_new_dim { \dim_abs:n {#2} }
    \dim_set:Nn \l_@@_bottom_new_dim
      { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_bottom_dim }
    \dim_set:Nn \l_@@_top_new_dim
      { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_top_dim }
    \@@_resize_common:N #1
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\box_resize_to_ht_plus_dp:Nn, \box_resize_to_ht_plus_dp:cn}
% \begin{macro}{\box_resize_to_wd:Nn, \box_resize_to_wd:cn}
%   Scaling to a total height or to a width is a simplified version of the main
%   resizing operation, with the scale simply copied between the two parts. The
%   internal auxiliary is called using the scaling value twice, as the sign for
%   both parts is needed (as this allows the same internal code to be used as
%   for the general case).
%    \begin{macrocode}
\cs_new_protected:Npn \box_resize_to_ht_plus_dp:Nn #1#2
  {
    \hbox_set:Nn #1
      {
        \group_begin:
          \dim_set:Nn \l_@@_top_dim    {  \box_ht:N #1 }
          \dim_set:Nn \l_@@_bottom_dim { -\box_dp:N #1 }
          \dim_set:Nn \l_@@_right_dim  {  \box_wd:N #1 }
          \dim_zero:N \l_@@_left_dim
          \fp_set:Nn \l_@@_scale_y_fp
            {
              \dim_to_fp:n {#2} /
                ( \dim_to_fp:n { \l_@@_top_dim - \l_@@_bottom_dim } )
            }
          \fp_set_eq:NN \l_@@_scale_x_fp \l_@@_scale_y_fp
          \@@_resize:Nnn #1 {#2} {#2}
        \group_end:
      }
  }
\cs_generate_variant:Nn \box_resize_to_ht_plus_dp:Nn { c }
\cs_new_protected:Npn \box_resize_to_wd:Nn #1#2
  {
    \hbox_set:Nn #1
      {
        \group_begin:
          \dim_set:Nn \l_@@_top_dim    {  \box_ht:N #1 }
          \dim_set:Nn \l_@@_bottom_dim { -\box_dp:N #1 }
          \dim_set:Nn \l_@@_right_dim  {  \box_wd:N #1 }
          \dim_zero:N \l_@@_left_dim
          \fp_set:Nn \l_@@_scale_x_fp
            { \dim_to_fp:n {#2} / ( \dim_to_fp:n \l_@@_right_dim ) }
          \fp_set_eq:NN \l_@@_scale_y_fp \l_@@_scale_x_fp
          \@@_resize:Nnn #1 {#2} {#2}
        \group_end:
      }
  }
\cs_generate_variant:Nn \box_resize_to_wd:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\box_scale:Nnn, \box_scale:cnn}
%   When scaling a box, setting the scaling itself is easy enough. The
%   new dimensions are also relatively easy to find, allowing only for
%   the need to keep them positive in all cases. Once that is done then
%   after a check for the trivial scaling a hand-off can be made to the
%   common code. The dimension scaling operations are carried out using
%   the \TeX{} mechanism as it avoids needing to use too many \texttt{fp}
%   operations.
%    \begin{macrocode}
\cs_new_protected:Npn \box_scale:Nnn #1#2#3
  {
    \hbox_set:Nn #1
      {
        \group_begin:
          \fp_set:Nn \l_@@_scale_x_fp {#2}
          \fp_set:Nn \l_@@_scale_y_fp {#3}
          \dim_set:Nn \l_@@_top_dim    {  \box_ht:N #1 }
          \dim_set:Nn \l_@@_bottom_dim { -\box_dp:N #1 }
          \dim_set:Nn \l_@@_right_dim  {  \box_wd:N #1 }
          \dim_zero:N \l_@@_left_dim
          \dim_set:Nn \l_@@_top_new_dim
            { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_top_dim }
          \dim_set:Nn \l_@@_bottom_new_dim
            { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_bottom_dim }
          \dim_set:Nn \l_@@_right_new_dim
              { \fp_abs:n { \l_@@_scale_x_fp } \l_@@_right_dim }
           \@@_resize_common:N #1
        \group_end:
      }
  }
\cs_generate_variant:Nn \box_scale:Nnn { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\@@_resize_common:N}
%   The main resize function places in input into a box which will start
%   of with zero width, and includes the handles for engine rescaling.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_resize_common:N #1
  {
    \hbox_set:Nn \l_@@_internal_box
      {
        \__driver_box_scale_begin:
        \hbox_overlap_right:n { \box_use:N #1 }
        \__driver_box_scale_end:
      }
%    \end{macrocode}
%   The new height and depth can be applied directly.
%    \begin{macrocode}
    \box_set_ht:Nn \l_@@_internal_box { \l_@@_top_new_dim }
    \box_set_dp:Nn \l_@@_internal_box { \l_@@_bottom_new_dim }
%    \end{macrocode}
%   Things are not quite as obvious for the width, as the reference point
%   needs to remain unchanged. For positive scaling factors resizing the
%   box is all that is needed. However, for case of a negative scaling
%   the material must be shifted such that the reference point ends up in
%   the right place.
%    \begin{macrocode}
    \fp_compare:nNnTF \l_@@_scale_x_fp < \c_zero_fp
      {
        \hbox_to_wd:nn { \l_@@_right_new_dim }
          {
            \tex_kern:D \l_@@_right_new_dim
            \box_use:N \l_@@_internal_box
            \tex_hss:D
          }
      }
      {
        \box_set_wd:Nn \l_@@_internal_box { \l_@@_right_new_dim }
        \box_use:N \l_@@_internal_box
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Viewing part of a box}
%
% \begin{macro}{\box_clip:N, \box_clip:c}
%   A wrapper around the driver-dependent code.
%    \begin{macrocode}
\cs_new_protected:Npn \box_clip:N #1
  { \hbox_set:Nn #1 { \__driver_box_use_clip:N #1 } }
\cs_generate_variant:Nn \box_clip:N { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\box_trim:Nnnnn, \box_trim:cnnnn}
%   Trimming from the left- and right-hand edges of the box is easy. The total
%   width is set to remove from the right, and a skip will shift the material
%   to remove from the left.
%    \begin{macrocode}
\cs_new_protected:Npn \box_trim:Nnnnn #1#2#3#4#5
  {
    \box_set_wd:Nn #1 { \box_wd:N #1 - (#4) - (#2) }
    \hbox_set:Nn #1
      {
        \skip_horizontal:n { - \dim_eval:n {#2} }
        \box_use:N #1
      }
%    \end{macrocode}
%   For the height and depth, there is a need to watch the baseline is
%   respected. Material always has to stay on the correct side, so trimming
%   has to check that there is enough material to trim.
%    \begin{macrocode}
    \dim_compare:nNnTF { \box_dp:N #1 } > {#3}
      { \box_set_dp:Nn #1 { \box_dp:N #1 - (#3) } }
      {
        \hbox_set:Nn #1
          { \box_move_down:nn { #3 - \box_dp:N #1 } { \box_use:N #1 } }
        \box_set_dp:Nn #1 \c_zero_dim
      }
    \dim_compare:nNnTF { \box_ht:N #1 } > {#5}
      { \box_set_ht:Nn #1 { \box_ht:N #1 - (#5) } }
      {
        \hbox_set:Nn #1
          { \box_move_up:nn { #5 - \box_ht:N #1 } { \box_use:N #1 } }
        \box_set_ht:Nn #1 \c_zero_dim
      }
  }
\cs_generate_variant:Nn \box_trim:Nnnnn { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\box_viewport:Nnnnn, \box_viewport:cnnnn}
%   The same general logic as for clipping, but with absolute dimensions.
%   Thus again width is easy and height is harder.
%    \begin{macrocode}
\cs_new_protected:Npn \box_viewport:Nnnnn #1#2#3#4#5
  {
    \box_set_wd:Nn #1 { (#4) - (#2) }
    \hbox_set:Nn #1
      {
        \skip_horizontal:n { - \dim_eval:n {#2} }
        \box_use:N #1
      }
    \dim_compare:nNnTF {#3} > \c_zero_dim
      {
        \hbox_set:Nn #1 { \box_move_down:nn {#3} { \box_use:N #1 } }
        \box_set_dp:Nn #1 \c_zero_dim
      }
      { \box_set_dp:Nn #1 { - \dim_eval:n {#3} } }
    \dim_compare:nNnTF {#5} > \c_zero_dim
      { \box_set_ht:Nn #1 {#5} }
      {
        \hbox_set:Nn #1
          { \box_move_up:nn { -\dim_eval:n {#5} } { \box_use:N #1 } }
        \box_set_ht:Nn #1 \c_zero_dim
      }
  }
\cs_generate_variant:Nn \box_viewport:Nnnnn { c }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Additions to \pkg{l3clist}}
%
%    \begin{macrocode}
%<@@=clist>
%    \end{macrocode}
%
% \begin{macro}{\clist_item:Nn, \clist_item:cn}
% \begin{macro}[aux]{\@@_item:nnNn}
% \begin{macro}[aux]{\@@_item_N_loop:nw}
%   To avoid needing to test the end of the list at each step,
%   we first compute the \meta{length} of the list. If the item number
%   is~$0$, less than $-\meta{length}$, or more than $\meta{length}$,
%   the result is empty. If it is negative, but not less than $-\meta{length}$,
%   add $\meta{length}+1$ to the item number before performing the loop.
%   The loop itself is very simple, return the item if the counter
%   reached~$1$, otherwise, decrease the counter and repeat.
%    \begin{macrocode}
\cs_new:Npn \clist_item:Nn #1#2
  {
    \exp_args:Nfo \@@_item:nnNn
      { \clist_count:N #1 }
      #1
      \@@_item_N_loop:nw
      {#2}
  }
\cs_new:Npn \@@_item:nnNn #1#2#3#4
  {
    \int_compare:nNnTF {#4} < \c_zero
      {
        \int_compare:nNnTF {#4} < { - #1 }
          { \use_none_delimit_by_q_stop:w }
          { \exp_args:Nf #3 { \int_eval:n { #4 + \c_one + #1 } } }
      }
      {
        \int_compare:nNnTF {#4} > {#1}
          { \use_none_delimit_by_q_stop:w }
          { #3 {#4} }
      }
    { } , #2 , \q_stop
  }
\cs_new:Npn \@@_item_N_loop:nw #1 #2,
  {
    \int_compare:nNnTF {#1} = \c_zero
      { \use_i_delimit_by_q_stop:nw { \exp_not:n {#2} } }
      { \exp_args:Nf \@@_item_N_loop:nw { \int_eval:n { #1 - 1 } } }
  }
\cs_generate_variant:Nn \clist_item:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\clist_item:nn}
% \begin{macro}[aux]{
%     \@@_item_n:nw,
%     \@@_item_n_loop:nw,
%     \@@_item_n_end:n,
%     \@@_item_n_strip:w}
%   This starts in the same way as \cs{clist_item:Nn} by counting the items
%   of the comma list. The final item should be space-trimmed before being
%   brace-stripped, hence we insert a couple of odd-looking
%   \cs{prg_do_nothing:} to avoid losing braces. Blank items are ignored.
%    \begin{macrocode}
\cs_new:Npn \clist_item:nn #1#2
  {
    \exp_args:Nf \@@_item:nnNn
      { \clist_count:n {#1} }
      {#1}
      \@@_item_n:nw
      {#2}
  }
\cs_new:Npn \@@_item_n:nw #1
  { \@@_item_n_loop:nw {#1} \prg_do_nothing: }
\cs_new:Npn \@@_item_n_loop:nw #1 #2,
  {
    \exp_args:No \tl_if_blank:nTF {#2}
      { \@@_item_n_loop:nw {#1} \prg_do_nothing: }
      {
        \int_compare:nNnTF {#1} = \c_zero
          { \exp_args:No \@@_item_n_end:n {#2} }
          {
            \exp_args:Nf \@@_item_n_loop:nw
              { \int_eval:n { #1 - 1 } }
              \prg_do_nothing:
          }
      }
  }
\cs_new:Npn \@@_item_n_end:n #1 #2 \q_stop
  {
    \__tl_trim_spaces:nn { \q_mark #1 }
      { \exp_last_unbraced:No \@@_item_n_strip:w } ,
  }
\cs_new:Npn \@@_item_n_strip:w #1 , { \exp_not:n {#1} }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \clist_set_from_seq:NN, \clist_set_from_seq:cN,
%     \clist_set_from_seq:Nc, \clist_set_from_seq:cc
%   }
% \UnitTested
% \begin{macro}
%   {
%     \clist_gset_from_seq:NN, \clist_gset_from_seq:cN,
%     \clist_gset_from_seq:Nc, \clist_gset_from_seq:cc
%   }
% \UnitTested
% \begin{macro}[aux]{\@@_set_from_seq:NNNN}
% \begin{macro}[aux]{\@@_wrap_item:n}
% \begin{macro}[aux]{\@@_set_from_seq:w}
%   Setting a comma list from a comma-separated list is done using a simple
%   mapping. We wrap most items with \cs{exp_not:n}, and a comma. Items which
%   contain a comma or a space are surrounded by an extra set of braces. The
%   first comma must be removed, except in the case of an empty comma-list.
%    \begin{macrocode}
\cs_new_protected:Npn \clist_set_from_seq:NN
  { \@@_set_from_seq:NNNN \clist_clear:N  \tl_set:Nx  }
\cs_new_protected:Npn \clist_gset_from_seq:NN
  { \@@_set_from_seq:NNNN \clist_gclear:N \tl_gset:Nx }
\cs_new_protected:Npn \@@_set_from_seq:NNNN #1#2#3#4
  {
    \seq_if_empty:NTF #4
      { #1 #3 }
      {
        #2 #3
          {
            \exp_last_unbraced:Nf \use_none:n
              { \seq_map_function:NN #4 \@@_wrap_item:n }
          }
      }
  }
\cs_new:Npn \@@_wrap_item:n #1
  {
    ,
    \tl_if_empty:oTF { \@@_set_from_seq:w #1 ~ , #1 ~ }
      { \exp_not:n   {#1}   }
      { \exp_not:n { {#1} } }
  }
\cs_new:Npn \@@_set_from_seq:w #1 , #2 ~ { }
\cs_generate_variant:Nn \clist_set_from_seq:NN  {     Nc }
\cs_generate_variant:Nn \clist_set_from_seq:NN  { c , cc }
\cs_generate_variant:Nn \clist_gset_from_seq:NN {     Nc }
\cs_generate_variant:Nn \clist_gset_from_seq:NN { c , cc }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \clist_const:Nn, \clist_const:cn,
%     \clist_const:Nx, \clist_const:cx
%   }
%   Creating and initializing a constant comma list is done in a way
%   similar to \cs{clist_set:Nn} and \cs{clist_gset:Nn}, being careful
%   to strip spaces.
%    \begin{macrocode}
\cs_new_protected:Npn \clist_const:Nn #1#2
  { \tl_const:Nx #1 { \@@_trim_spaces:n {#2} } }
\cs_generate_variant:Nn \clist_const:Nn { c , Nx , cx }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP, pTF]{\clist_if_empty:n}
% \begin{macro}[aux, EXP]{\@@_if_empty_n:w}
% \begin{macro}[aux, EXP]{\@@_if_empty_n:wNw}
%   As usual, we insert a token (here |?|) before grabbing
%   any argument: this avoids losing braces. The argument
%   of \cs{tl_if_empty:oTF} is empty if |#1| is |?| followed
%   by blank spaces (besides, this particular variant of
%   the emptyness test is optimized). If the item of the
%   comma list is blank, grab the next one. As soon as one
%   item is non-blank, exit: the second auxiliary will grab
%   \cs{prg_return_false:} as |#2|, unless every item in
%   the comma list was blank and the loop actually got broken
%   by the trailing |\q_mark \prg_return_false:| item.
%    \begin{macrocode}
\prg_new_conditional:Npnn \clist_if_empty:n #1 { p , T , F , TF }
  {
    \@@_if_empty_n:w ? #1
    , \q_mark \prg_return_false:
    , \q_mark \prg_return_true:
    \q_stop
  }
\cs_new:Npn \@@_if_empty_n:w #1 ,
  {
    \tl_if_empty:oTF { \use_none:nn #1 ? }
      { \@@_if_empty_n:w ? }
      { \@@_if_empty_n:wNw }
  }
\cs_new:Npn \@@_if_empty_n:wNw #1 \q_mark #2#3 \q_stop {#2}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\clist_use:Nnnn}
% \begin{macro}[EXP, aux]
%   {\@@_use:wwn, \@@_use_ii:nwwwwnwn, \@@_use_iii:nwwn}
%   First check that the variable exists.  Then count the items in the
%   comma list.  If it has none, output nothing.  If it has one item,
%   output that item, brace stripped (note that space-trimming has
%   already been done when the comma list was assigned).  If it has two,
%   place the \meta{separator~between~two} in the middle.
%
%   Otherwise, \cs{@@_use_ii:nwwwwnwn} takes the following arguments; 1:
%   a \meta{separator}, 2, 3, 4: three items from the comma list (or
%   quarks), 5: the rest of the comma list, 6: a \meta{continuation}
%   function (\texttt{use_ii} or \texttt{use_iii} with its
%   \meta{separator} argument), 7: junk, and 8: the temporary result,
%   which is built in a brace group following \cs{q_stop}.  The
%   \meta{separator} and the first of the three items are placed in the
%   result, then we use the \meta{continuation}, placing the remaining
%   two items after it.  When we begin this loop, the three items really
%   belong to the comma list, the first \cs{q_mark} is taken as a
%   delimiter to the \texttt{use_ii} function, and the continuation is
%   \texttt{use_ii} itself.  When we reach the last two items of the
%   original token list, \cs{q_mark} is taken as a third item, and now
%   the seconf \cs{q_mark} serves as a delimiter to \texttt{use_ii},
%   switching to the other \meta{continuation}, \texttt{use_iii}, which
%   uses the \meta{separator between final two}.
%    \begin{macrocode}
\cs_new:Npn \clist_use:Nnnn #1#2#3#4
  {
    \clist_if_exist:NTF #1
      {
        \int_case:nnn { \clist_count:N #1 }
          {
            { 0 } { }
            { 1 } { \exp_after:wN \@@_use:wwn #1 , , { } }
            { 2 } { \exp_after:wN \@@_use:wwn #1 , {#2} }
          }
          {
            \exp_after:wN \@@_use_ii:nwwwwnwn
            \exp_after:wN { \exp_after:wN } #1 ,
            \q_mark , { \@@_use_ii:nwwwwnwn {#3} }
            \q_mark , { \@@_use_iii:nwwn {#4} }
            \q_stop { }
          }
      }
      { \__msg_kernel_expandable_error:nnn { kernel } { bad-variable } {#1} }
  }
\cs_new:Npn \@@_use:wwn #1 , #2 , #3 { \exp_not:n { #1 #3 #2 } }
\cs_new:Npn \@@_use_ii:nwwwwnwn
    #1#2 , #3 , #4 , #5 \q_mark , #6#7 \q_stop #8
  { #6 {#3} , {#4} , #5 \q_mark , {#6} #7 \q_stop { #8 #1 #2 } }
\cs_new:Npn \@@_use_iii:nwwn #1#2 , #3 \q_stop #4
  { \exp_not:n { #4 #1 #2 } }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Additions to \pkg{l3coffins}}
%
%    \begin{macrocode}
%<@@=coffin>
%    \end{macrocode}
%
% \subsection{Rotating coffins}
%
% \begin{variable}{\l_@@_sin_fp}
% \begin{variable}{\l_@@_cos_fp}
%   Used for rotations to get the sine and cosine values.
%    \begin{macrocode}
\fp_new:N \l_@@_sin_fp
\fp_new:N \l_@@_cos_fp
%    \end{macrocode}
% \end{variable}
% \end{variable}
%
% \begin{variable}{\l_@@_bounding_prop}
%   A property list for the bounding box of a coffin. This is only needed
%   during the rotation, so there is just the one.
%    \begin{macrocode}
\prop_new:N \l_@@_bounding_prop
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_bounding_shift_dim}
%   The shift of the bounding box of a coffin from the real content.
%    \begin{macrocode}
\dim_new:N \l_@@_bounding_shift_dim
%    \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_left_corner_dim}
% \begin{variable}{\l_@@_right_corner_dim}
% \begin{variable}{\l_@@_bottom_corner_dim}
% \begin{variable}{\l_@@_top_corner_dim}
%   These are used to hold maxima for the various corner values: these
%   thus define the minimum size of the bounding box after rotation.
%    \begin{macrocode}
\dim_new:N \l_@@_left_corner_dim
\dim_new:N \l_@@_right_corner_dim
\dim_new:N \l_@@_bottom_corner_dim
\dim_new:N \l_@@_top_corner_dim
%    \end{macrocode}
% \end{variable}
% \end{variable}
% \end{variable}
% \end{variable}
%
% \begin{macro}{\coffin_rotate:Nn, \coffin_rotate:cn}
%   Rotating a coffin requires several steps which can be conveniently
%   run together. The first step is to convert the angle given in degrees
%   to one in radians. This is then used to set \cs{l_@@_sin_fp} and
%   \cs{l_@@_cos_fp}, which are carried through unchanged for the rest
%   of the procedure.
%    \begin{macrocode}
\cs_new_protected:Npn \coffin_rotate:Nn #1#2
  {
    \fp_set:Nn \l_@@_sin_fp { sin ( ( #2 ) * deg ) }
    \fp_set:Nn \l_@@_cos_fp { cos ( ( #2 ) * deg ) }
%    \end{macrocode}
%   The corners and poles of the coffin can now be rotated around the
%    origin. This is best achieved using mapping functions.
%    \begin{macrocode}
    \prop_map_inline:cn { l_@@_corners_ \__int_value:w #1 _prop }
      { \@@_rotate_corner:Nnnn #1 {##1} ##2 }
    \prop_map_inline:cn { l_@@_poles_ \__int_value:w #1 _prop }
      { \@@_rotate_pole:Nnnnnn #1 {##1} ##2 }
%    \end{macrocode}
%   The bounding box of the coffin needs to be rotated, and to do this
%   the corners have to be found first. They are then rotated in the same
%   way as the corners of the coffin material itself.
%    \begin{macrocode}
    \@@_set_bounding:N #1
    \prop_map_inline:Nn \l_@@_bounding_prop
      { \@@_rotate_bounding:nnn {##1} ##2 }
%    \end{macrocode}
%   At this stage, there needs to be a calculation to find where the
%   corners of the content and the box itself will end up.
%    \begin{macrocode}
    \@@_find_corner_maxima:N #1
    \@@_find_bounding_shift:
    \box_rotate:Nn #1 {#2}
%    \end{macrocode}
%   The correction of the box position itself takes place here. The idea
%   is that the bounding box for a coffin is tight up to the content, and
%   has the reference point at the bottom-left. The $x$-direction is
%   handled by moving the content by the difference in the positions of
%   the bounding box and the content left edge. The $y$-direction is
%   dealt with by moving the box down by any depth it has acquired.
%    \begin{macrocode}
    \hbox_set:Nn #1
      {
        \tex_kern:D \l_@@_bounding_shift_dim
        \tex_kern:D -\l_@@_left_corner_dim
        \box_move_down:nn { \l_@@_bottom_corner_dim }
          { \box_use:N #1 }
      }
%    \end{macrocode}
%   If there have been any previous rotations then the size of the
%   bounding box will be bigger than the contents. This can be corrected
%   easily by setting the size of the box to the height and width of the
%   content.
%    \begin{macrocode}
    \box_set_ht:Nn #1
      { \l_@@_top_corner_dim - \l_@@_bottom_corner_dim }
    \box_set_dp:Nn #1 { 0 pt }
    \box_set_wd:Nn #1
      { \l_@@_right_corner_dim - \l_@@_left_corner_dim }
%    \end{macrocode}
%   The final task is to move the poles and corners such that they are
%   back in alignment with the box reference point.
%    \begin{macrocode}
    \prop_map_inline:cn { l_@@_corners_ \__int_value:w #1 _prop }
      { \@@_shift_corner:Nnnn #1 {##1} ##2 }
    \prop_map_inline:cn { l_@@_poles_ \__int_value:w #1 _prop }
      { \@@_shift_pole:Nnnnnn #1 {##1} ##2 }
  }
\cs_generate_variant:Nn \coffin_rotate:Nn { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_set_bounding:N}
%   The bounding box corners for a coffin are easy enough to find: this
%   is the same code as for the corners of the material itself, but
%   using a dedicated property list.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_bounding:N #1
  {
    \prop_put:Nnx \l_@@_bounding_prop { tl }
      { { 0 pt } { \dim_use:N \box_ht:N #1 } }
    \prop_put:Nnx \l_@@_bounding_prop { tr }
      { { \dim_use:N \box_wd:N #1 } { \dim_use:N \box_ht:N #1 } }
    \dim_set:Nn \l_@@_internal_dim { - \box_dp:N #1 }
    \prop_put:Nnx \l_@@_bounding_prop { bl }
      { { 0 pt } { \dim_use:N \l_@@_internal_dim } }
    \prop_put:Nnx \l_@@_bounding_prop { br }
      { { \dim_use:N \box_wd:N #1 } { \dim_use:N \l_@@_internal_dim } }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_rotate_bounding:nnn}
% \begin{macro}{\@@_rotate_corner:Nnnn}
%   Rotating the position of the corner of the coffin is just a case
%   of treating this as a vector from the reference point. The same
%   treatment is used for the corners of the material itself and the
%   bounding box.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_rotate_bounding:nnn #1#2#3
  {
    \@@_rotate_vector:nnNN {#2} {#3} \l_@@_x_dim \l_@@_y_dim
    \prop_put:Nnx \l_@@_bounding_prop {#1}
      { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } }
  }
\cs_new_protected:Npn \@@_rotate_corner:Nnnn #1#2#3#4
  {
    \@@_rotate_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim
    \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _prop } {#2}
      { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_rotate_pole:Nnnnnn}
%   Rotating a single pole simply means shifting the co-ordinate of
%   the pole and its direction. The rotation here is about the bottom-left
%   corner of the coffin.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_rotate_pole:Nnnnnn #1#2#3#4#5#6
  {
    \@@_rotate_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim
    \@@_rotate_vector:nnNN {#5} {#6}
      \l_@@_x_prime_dim \l_@@_y_prime_dim
    \@@_set_pole:Nnx #1 {#2}
      {
        { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim }
        { \dim_use:N \l_@@_x_prime_dim }
        { \dim_use:N \l_@@_y_prime_dim }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_rotate_vector:nnNN}
%   A rotation function, which needs only an input vector (as dimensions)
%   and an output space. The values \cs{l_@@_cos_fp} and
%   \cs{l_@@_sin_fp} should previously have been set up correctly.
%   Working this way means that the floating point work is kept to a
%   minimum: for any given rotation the sin and cosine values do no
%   change, after all.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_rotate_vector:nnNN #1#2#3#4
  {
    \dim_set:Nn #3
      {
        \fp_to_dim:n
          {
                \dim_to_fp:n {#1} * \l_@@_cos_fp
            - ( \dim_to_fp:n {#2} * \l_@@_sin_fp )
          }
      }
    \dim_set:Nn #4
      {
        \fp_to_dim:n
          {
                \dim_to_fp:n {#1} * \l_@@_sin_fp
            + ( \dim_to_fp:n {#2} * \l_@@_cos_fp )
          }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_find_corner_maxima:N}
% \begin{macro}[aux]{\@@_find_corner_maxima_aux:nn}
%   The idea here is to find the extremities of the content of the
%   coffin. This is done by looking for the smallest values for the bottom
%   and left corners, and the largest values for the top and right
%   corners. The values start at the maximum dimensions so that the
%   case where all are positive or all are negative works out correctly.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_find_corner_maxima:N #1
  {
    \dim_set:Nn \l_@@_top_corner_dim   { -\c_max_dim }
    \dim_set:Nn \l_@@_right_corner_dim { -\c_max_dim }
    \dim_set:Nn \l_@@_bottom_corner_dim { \c_max_dim }
    \dim_set:Nn \l_@@_left_corner_dim   { \c_max_dim }
    \prop_map_inline:cn { l_@@_corners_ \__int_value:w #1 _prop }
      { \@@_find_corner_maxima_aux:nn ##2 }
  }
\cs_new_protected:Npn \@@_find_corner_maxima_aux:nn #1#2
  {
    \dim_set:Nn \l_@@_left_corner_dim
     { \dim_min:nn { \l_@@_left_corner_dim } {#1} }
    \dim_set:Nn \l_@@_right_corner_dim
     { \dim_max:nn { \l_@@_right_corner_dim } {#1} }
    \dim_set:Nn \l_@@_bottom_corner_dim
     { \dim_min:nn { \l_@@_bottom_corner_dim } {#2} }
    \dim_set:Nn \l_@@_top_corner_dim
     { \dim_max:nn { \l_@@_top_corner_dim } {#2} }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_find_bounding_shift:}
% \begin{macro}[aux]{\@@_find_bounding_shift_aux:nn}
%   The approach to finding the shift for the bounding box is similar to
%   that for the corners. However, there is only one value needed here and
%   a fixed input property list, so things are a bit clearer.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_find_bounding_shift:
  {
    \dim_set:Nn \l_@@_bounding_shift_dim { \c_max_dim }
    \prop_map_inline:Nn \l_@@_bounding_prop
      { \@@_find_bounding_shift_aux:nn ##2 }
  }
\cs_new_protected:Npn \@@_find_bounding_shift_aux:nn #1#2
  {
    \dim_set:Nn \l_@@_bounding_shift_dim
      { \dim_min:nn { \l_@@_bounding_shift_dim } {#1} }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_shift_corner:Nnnn}
% \begin{macro}{\@@_shift_pole:Nnnnnn}
%   Shifting the corners and poles of a coffin means subtracting the
%   appropriate values from the $x$- and $y$-components. For
%   the poles, this means that the direction vector is unchanged.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_shift_corner:Nnnn #1#2#3#4
  {
    \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _ prop } {#2}
      {
        { \dim_eval:n { #3 - \l_@@_left_corner_dim } }
        { \dim_eval:n { #4 - \l_@@_bottom_corner_dim } }
      }
  }
\cs_new_protected:Npn \@@_shift_pole:Nnnnnn #1#2#3#4#5#6
  {
    \prop_put:cnx { l_@@_poles_ \__int_value:w #1 _ prop } {#2}
      {
        { \dim_eval:n { #3 - \l_@@_left_corner_dim } }
        { \dim_eval:n { #4 - \l_@@_bottom_corner_dim } }
        {#5} {#6}
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Resizing coffins}
%
% \begin{variable}{\l_@@_scale_x_fp}
% \begin{variable}{\l_@@_scale_y_fp}
%   Storage for the scaling factors in $x$ and $y$, respectively.
%    \begin{macrocode}
\fp_new:N \l_@@_scale_x_fp
\fp_new:N \l_@@_scale_y_fp
%    \end{macrocode}
% \end{variable}
% \end{variable}
%
% \begin{variable}{\l_@@_scaled_total_height_dim}
% \begin{variable}{\l_@@_scaled_width_dim}
%   When scaling, the values given have to be turned into absolute values.
%    \begin{macrocode}
\dim_new:N \l_@@_scaled_total_height_dim
\dim_new:N \l_@@_scaled_width_dim
%    \end{macrocode}
% \end{variable}
% \end{variable}
%
% \begin{macro}{\coffin_resize:Nnn, \coffin_resize:cnn}
%   Resizing a coffin begins by setting up the user-friendly names for
%   the dimensions of the coffin box. The new sizes are then turned into
%   scale factor. This is the same operation as takes place for the
%   underlying box, but that operation is grouped and so the same
%   calculation is done here.
%    \begin{macrocode}
\cs_new_protected:Npn \coffin_resize:Nnn #1#2#3
  {
    \fp_set:Nn \l_@@_scale_x_fp
      { \dim_to_fp:n {#2} / \dim_to_fp:n { \coffin_wd:N #1 } }
    \fp_set:Nn \l_@@_scale_y_fp
      {
        \dim_to_fp:n {#3} / \dim_to_fp:n { \coffin_ht:N #1 + \coffin_dp:N #1 }
      }
    \box_resize:Nnn #1 {#2} {#3}
    \@@_resize_common:Nnn #1 {#2} {#3}
  }
\cs_generate_variant:Nn \coffin_resize:Nnn { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_resize_common:Nnn}
%   The poles and corners of the coffin are scaled to the appropriate
%   places before actually resizing the underlying box.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_resize_common:Nnn #1#2#3
  {
    \prop_map_inline:cn { l_@@_corners_ \__int_value:w #1 _prop }
      { \@@_scale_corner:Nnnn #1 {##1} ##2 }
    \prop_map_inline:cn { l_@@_poles_ \__int_value:w #1 _prop }
      { \@@_scale_pole:Nnnnnn #1 {##1} ##2 }
%    \end{macrocode}
%   Negative $x$-scaling values will place the poles in the wrong
%   location: this is corrected here.
%    \begin{macrocode}
    \fp_compare:nNnT \l_@@_scale_x_fp < \c_zero_fp
      {
        \prop_map_inline:cn { l_@@_corners_ \__int_value:w #1 _prop }
          { \@@_x_shift_corner:Nnnn #1 {##1} ##2 }
        \prop_map_inline:cn { l_@@_poles_ \__int_value:w #1 _prop }
          { \@@_x_shift_pole:Nnnnnn #1 {##1} ##2 }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\coffin_scale:Nnn, \coffin_scale:cnn}
%   For scaling, the opposite calculation is done to find the new
%   dimensions for the coffin. Only the total height is needed, as this
%   is the shift required for corners and poles. The scaling is done
%   the \TeX{} way as this works properly with floating point values
%   without needing to use the \texttt{fp} module.
%    \begin{macrocode}
\cs_new_protected:Npn \coffin_scale:Nnn #1#2#3
  {
    \fp_set:Nn \l_@@_scale_x_fp {#2}
    \fp_set:Nn \l_@@_scale_y_fp {#3}
    \box_scale:Nnn #1 { \l_@@_scale_x_fp } { \l_@@_scale_y_fp }
    \dim_set:Nn \l_@@_internal_dim
      { \coffin_ht:N #1 + \coffin_dp:N #1 }
    \dim_set:Nn \l_@@_scaled_total_height_dim
      { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_internal_dim }
    \dim_set:Nn \l_@@_scaled_width_dim
      { -\fp_abs:n { \l_@@_scale_x_fp  } \coffin_wd:N #1 }
    \@@_resize_common:Nnn #1
      { \l_@@_scaled_width_dim } { \l_@@_scaled_total_height_dim }
  }
\cs_generate_variant:Nn \coffin_scale:Nnn { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_scale_vector:nnNN}
%   This functions scales a vector from the origin using the pre-set scale
%   factors in $x$ and $y$. This is a much less complex operation
%   than rotation, and as a result the code is a lot clearer.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_scale_vector:nnNN #1#2#3#4
  {
    \dim_set:Nn #3
      { \fp_to_dim:n { \dim_to_fp:n {#1} * \l_@@_scale_x_fp } }
    \dim_set:Nn #4
      { \fp_to_dim:n { \dim_to_fp:n {#2} * \l_@@_scale_y_fp } }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_scale_corner:Nnnn}
% \begin{macro}{\@@_scale_pole:Nnnnnn}
%   Scaling both corners and poles is a simple calculation using the
%   preceding vector scaling.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_scale_corner:Nnnn #1#2#3#4
  {
    \@@_scale_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim
    \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _prop } {#2}
      { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } }
  }
\cs_new_protected:Npn \@@_scale_pole:Nnnnnn #1#2#3#4#5#6
  {
    \@@_scale_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim
    \@@_set_pole:Nnx #1 {#2}
      {
        { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim }
        {#5} {#6}
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_x_shift_corner:Nnnn}
% \begin{macro}{\@@_x_shift_pole:Nnnnnn}
%   These functions correct for the $x$ displacement that takes
%   place with a negative horizontal scaling.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_x_shift_corner:Nnnn #1#2#3#4
  {
    \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _prop } {#2}
      {
        { \dim_eval:n { #3 + \box_wd:N #1 } } {#4}
      }
  }
\cs_new_protected:Npn \@@_x_shift_pole:Nnnnnn #1#2#3#4#5#6
  {
    \prop_put:cnx { l_@@_poles_ \__int_value:w #1 _prop } {#2}
      {
        { \dim_eval:n #3 + \box_wd:N #1 } {#4}
        {#5} {#6}
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Additions to \pkg{l3file}}
%
%    \begin{macrocode}
%<@@=ior>
%    \end{macrocode}
%
% \begin{macro}[EXP]{\ior_map_break:, \ior_map_break:n}
%   Usual map breaking functions.  Those are not yet in \pkg{l3kernel}
%   proper since the mapping below is the first of its kind.
%    \begin{macrocode}
\cs_new_nopar:Npn \ior_map_break:
  { \__prg_map_break:Nn \ior_map_break: { } }
\cs_new_nopar:Npn \ior_map_break:n
  { \__prg_map_break:Nn \ior_map_break: }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ior_map_inline:Nn, \ior_str_map_inline:Nn}
% \begin{macro}[aux]{\@@_map_inline:NNn}
% \begin{macro}[aux]{\@@_map_inline:NNNn}
% \begin{macro}[aux]{\@@_map_inline_loop:NNN}
% \begin{variable}{\l_@@_internal_tl}
%   Mapping to an input stream can be done on either a token or a string
%   basis, hence the set up. Within that, there is a check to avoid reading
%   past the end of a file, hence the two applications of \cs{ior_if_eof:N}.
%   This mapping cannot be nested as the stream has only one \enquote{current
%   line}.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \ior_map_inline:Nn
  { \@@_map_inline:NNn \ior_get:NN }
\cs_new_protected_nopar:Npn \ior_str_map_inline:Nn
  { \@@_map_inline:NNn \ior_get_str:NN }
\cs_new_protected_nopar:Npn \@@_map_inline:NNn
  {
    \int_gincr:N \g__prg_map_int
    \exp_args:Nc \@@_map_inline:NNNn
      { __prg_map_ \int_use:N \g__prg_map_int :n }
  }
\cs_new_protected:Npn \@@_map_inline:NNNn #1#2#3#4
  {
    \cs_set:Npn #1 ##1 {#4}
    \ior_if_eof:NF #3 { \@@_map_inline_loop:NNN #1#2#3 }
    \__prg_break_point:Nn \ior_map_break:
      { \int_gdecr:N \g__prg_map_int }
  }
\cs_new_protected:Npn \@@_map_inline_loop:NNN #1#2#3
  {
    #2 #3 \l_@@_internal_tl
    \ior_if_eof:NF #3
      {
        \exp_args:No #1 \l_@@_internal_tl
        \@@_map_inline_loop:NNN #1#2#3
      }
  }
\tl_new:N  \l_@@_internal_tl
%    \end{macrocode}
% \end{variable}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Additions to \pkg{l3fp}}
%
%    \begin{macrocode}
%<@@=fp>
%    \end{macrocode}
%
% \begin{macro}
%   {
%     \fp_set_from_dim:Nn,  \fp_set_from_dim:cn,
%     \fp_gset_from_dim:Nn, \fp_gset_from_dim:cn
%   }
%   Use the appropriate function from \pkg{l3fp-convert}.
%    \begin{macrocode}
\cs_new_protected:Npn \fp_set_from_dim:Nn #1#2
  { \tl_set:Nx #1 { \dim_to_fp:n {#2} } }
\cs_new_protected:Npn \fp_gset_from_dim:Nn #1#2
  { \tl_gset:Nx #1 { \dim_to_fp:n {#2} } }
\cs_generate_variant:Nn \fp_set_from_dim:Nn  { c }
\cs_generate_variant:Nn \fp_gset_from_dim:Nn { c }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Additions to \pkg{l3prop}}
%
%    \begin{macrocode}
%<@@=prop>
%    \end{macrocode}
%
% \begin{macro}[rEXP]{\prop_map_tokens:Nn, \prop_map_tokens:cn}
% \begin{macro}[aux]{\@@_map_tokens:nwn}
%   The mapping grabs one key--value pair at a time, and stops when
%   reaching the marker key \cs{q_recursion_tail}, which
%   cannot appear in normal keys since those are strings. The odd
%   construction |\use:n {#1}| allows |#1| to contain any token.
%    \begin{macrocode}
\cs_new:Npn \prop_map_tokens:Nn #1#2
  {
    \exp_last_unbraced:Nno \@@_map_tokens:nwn {#2} #1
    \q_recursion_tail \q__prop { }
    \__prg_break_point:Nn \prop_map_break: { }
  }
\cs_new:Npn \@@_map_tokens:nwn #1 \q__prop #2 \q__prop #3
  {
    \__quark_if_recursion_tail_break:NN #2 \prop_map_break:
    \use:n {#1} {#2} {#3}
    \@@_map_tokens:nwn {#1}
  }
\cs_generate_variant:Nn \prop_map_tokens:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\prop_get:Nn, \prop_get:cn}
% \begin{macro}[aux]{\@@_get_Nn:nwn}
%   Getting the value corresponding to a key in a property list in an
%   expandable fashion is a simple instance of mapping some tokens.
%   Map the function \cs{prop_get:nnn} which takes as its three
%   arguments the \meta{key} that we are looking for, the current
%   \meta{key} and the current \meta{value}. If the \meta{keys} match,
%   the \meta{value} is returned. If none of the keys match, this expands
%   to nothing.
%    \begin{macrocode}
\cs_new:Npn \prop_get:Nn #1#2
  {
    \exp_last_unbraced:Noo \@@_get_Nn:nwn
      { \tl_to_str:n {#2} } #1
      \tl_to_str:n {#2} \q__prop { }
    \__prg_break_point:
  }
\cs_new:Npn \@@_get_Nn:nwn #1 \q__prop #2 \q__prop #3
  {
    \str_if_eq_x:nnTF {#1} {#2}
      { \__prg_break:n { \exp_not:n {#3} } }
      { \@@_get_Nn:nwn {#1} }
  }
\cs_generate_variant:Nn \prop_get:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Additions to \pkg{l3seq}}
%
%    \begin{macrocode}
%<@@=seq>
%    \end{macrocode}
%
% \begin{macro}{\seq_item:Nn, \seq_item:cn}
% \begin{macro}[aux]{\@@_item:nnn}
%   The idea here is to find the offset of the item from the left, then use
%   a loop to grab the correct item. If the resulting offset is too large,
%   then the stop code |{ ? \__prg_break: } { }| will be used by the auxiliary,
%   terminating the loop and returning nothing at all.
%    \begin{macrocode}
\cs_new:Npn \seq_item:Nn #1#2
  {
    \exp_last_unbraced:Nfo \@@_item:nnn
      {
        \int_eval:n
          {
            \int_compare:nNnT {#2} < \c_zero
              { \seq_count:N #1 + \c_one + }
            #2
          }
      }
    #1
    { ? \__prg_break: }
    { }
    \__prg_break_point:
  }
\cs_new:Npn \@@_item:nnn #1#2#3
  {
    \use_none:n #2
    \int_compare:nNnTF {#1} = \c_one
      { \__prg_break:n { \exp_not:n {#3} } }
      { \exp_args:Nf \@@_item:nnn { \int_eval:n { #1 - 1 } } }
  }
\cs_generate_variant:Nn \seq_item:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \seq_mapthread_function:NNN, \seq_mapthread_function:NcN,
%     \seq_mapthread_function:cNN, \seq_mapthread_function:ccN
%   }
% \begin{macro}[aux]{\@@_mapthread_function:NN}
% \begin{macro}[aux]{\@@_mapthread_function:Nnnwnn}
%   The idea here is to first expand both of the sequences, adding the usual
%   |{ ? \__prg_break: } { }| to the end of each one. This is most conveniently
%   done in two steps using an auxiliary function. The mapping then throws
%   away the first token of |#2| and |#5|, which for items in the sequences
%   will both be \cs{@@_item:n}. The function to be mapped will then be
%   applied to the two entries. When the code hits the end of one of the
%   sequences, the break material will stop the entire loop and tidy up. This
%   avoids needing to find the count of the two sequences, or worrying about
%   which is longer.
%    \begin{macrocode}
\cs_new:Npn \seq_mapthread_function:NNN #1#2#3
  {
    \exp_after:wN \@@_mapthread_function:NN
      \exp_after:wN #3
      \exp_after:wN #1
      #2
      { ? \__prg_break: } { }
    \__prg_break_point:
  }
\cs_new:Npn \@@_mapthread_function:NN #1#2
  {
    \exp_after:wN \@@_mapthread_function:Nnnwnn
      \exp_after:wN #1
      #2
      { ? \__prg_break: } { }
      \q_stop
  }
\cs_new:Npn \@@_mapthread_function:Nnnwnn #1#2#3#4 \q_stop #5#6
  {
    \use_none:n #2
    \use_none:n #5
    #1 {#3} {#6}
    \@@_mapthread_function:Nnnwnn #1 #4 \q_stop
  }
\cs_generate_variant:Nn \seq_mapthread_function:NNN {     Nc }
\cs_generate_variant:Nn \seq_mapthread_function:NNN { c , cc }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \seq_set_from_clist:NN, \seq_set_from_clist:cN,
%     \seq_set_from_clist:Nc, \seq_set_from_clist:cc,
%     \seq_set_from_clist:Nn, \seq_set_from_clist:cn
%   }
% \begin{macro}
%   {
%     \seq_gset_from_clist:NN, \seq_gset_from_clist:cN,
%     \seq_gset_from_clist:Nc, \seq_gset_from_clist:cc,
%     \seq_gset_from_clist:Nn, \seq_gset_from_clist:cn
%   }
%   Setting a sequence from a comma-separated list is done using a simple
%   mapping.
%    \begin{macrocode}
\cs_new_protected:Npn \seq_set_from_clist:NN #1#2
  {
    \tl_set:Nx #1
      { \clist_map_function:NN #2 \@@_wrap_item:n }
  }
\cs_new_protected:Npn \seq_set_from_clist:Nn #1#2
  {
    \tl_set:Nx #1
      { \clist_map_function:nN {#2} \@@_wrap_item:n }
  }
\cs_new_protected:Npn \seq_gset_from_clist:NN #1#2
  {
    \tl_gset:Nx #1
      { \clist_map_function:NN #2 \@@_wrap_item:n }
  }
\cs_new_protected:Npn \seq_gset_from_clist:Nn #1#2
  {
    \tl_gset:Nx #1
      { \clist_map_function:nN {#2} \@@_wrap_item:n }
  }
\cs_generate_variant:Nn \seq_set_from_clist:NN  {     Nc }
\cs_generate_variant:Nn \seq_set_from_clist:NN  { c , cc }
\cs_generate_variant:Nn \seq_set_from_clist:Nn  { c      }
\cs_generate_variant:Nn \seq_gset_from_clist:NN {     Nc }
\cs_generate_variant:Nn \seq_gset_from_clist:NN { c , cc }
\cs_generate_variant:Nn \seq_gset_from_clist:Nn { c      }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {\seq_reverse:N, \seq_reverse:c, \seq_greverse:N, \seq_greverse:c}
% \begin{macro}[aux]{\@@_tmp:w}
% \begin{macro}[aux]{\@@_reverse:NN}
% \begin{macro}[aux]{\@@_reverse_item:nwn}
%   Previously, \cs{seq_reverse:N} was coded by collecting the items
%   in reverse order after an \cs{exp_stop_f:} marker.
%   \begin{verbatim}
%     \cs_new_protected:Npn \seq_reverse:N #1
%       {
%         \cs_set_eq:NN \@@_item:n \@@_reverse_item:nw
%         \tl_set:Nf #2 { #2 \exp_stop_f: }
%       }
%     \cs_new:Npn \@@_reverse_item:nw #1 #2 \exp_stop_f:
%       {
%         #2 \exp_stop_f:
%         \@@_item:n {#1}
%       }
%   \end{verbatim}
%   At first, this seems optimal, since we can forget about each item
%   as soon as it is placed after \cs{exp_stop_f:}. Unfortunately,
%   \TeX{}'s usual tail recursion does not take place in this case:
%   since the following \cs{@@_reverse_item:nw} only reads
%   tokens until \cs{exp_stop_f:}, and never reads the
%   |\@@_item:n {#1}| left by the previous call, \TeX{} cannot
%   remove that previous call from the stack, and in particular
%   must retain the various macro parameters in memory, until the
%   end of the replacement text is reached. The stack is thus
%   only flushed after all the \cs{@@_reverse_item:nw} are
%   expanded. Keeping track of the arguments of all those calls
%   uses up a memory quadratic in the length of the sequence.
%   \TeX{} can then not cope with more than a few thousand items.
%
%   Instead, we collect the items in the argument
%   of \cs{exp_not:n}. The previous calls are cleanly removed
%   from the stack, and the memory consumption becomes linear.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_tmp:w { }
\cs_new_protected_nopar:Npn \seq_reverse:N
  { \@@_reverse:NN \tl_set:Nx }
\cs_new_protected_nopar:Npn \seq_greverse:N
  { \@@_reverse:NN \tl_gset:Nx }
\cs_new_protected:Npn \@@_reverse:NN #1 #2
  {
    \cs_set_eq:NN \@@_tmp:w \@@_item:n
    \cs_set_eq:NN \@@_item:n \@@_reverse_item:nwn
    #1 #2 { #2 \exp_not:n { } }
    \cs_set_eq:NN \@@_item:n \@@_tmp:w
  }
\cs_new:Npn \@@_reverse_item:nwn #1 #2 \exp_not:n #3
  {
    #2
    \exp_not:n { \@@_item:n {#1} #3 }
  }
\cs_generate_variant:Nn \seq_reverse:N  { c }
\cs_generate_variant:Nn \seq_greverse:N { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\seq_set_filter:NNn, \seq_gset_filter:NNn}
% \begin{macro}[aux]{\@@_set_filter:NNNn}
%   Similar to \cs{seq_map_inline:Nn}, without a
%   \cs{__prg_break_point:} because the user's code
%   is performed within the evaluation of a boolean expression,
%   and skipping out of that would break horribly.
%   The \cs{@@_wrap_item:n} function inserts the relevant
%   \cs{@@_item:n} without expansion in the input stream,
%   hence in the \texttt{x}-expanding assignment.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_set_filter:NNn
  { \@@_set_filter:NNNn \tl_set:Nx }
\cs_new_protected_nopar:Npn \seq_gset_filter:NNn
  { \@@_set_filter:NNNn \tl_gset:Nx }
\cs_new_protected:Npn \@@_set_filter:NNNn #1#2#3#4
  {
    \@@_push_item_def:n { \bool_if:nT {#4} { \@@_wrap_item:n {##1} } }
    #1 #2 { #3 }
    \@@_pop_item_def:
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\seq_set_map:NNn,\seq_gset_map:NNn}
% \begin{macro}[aux]{\@@_set_map:NNNn}
%   Very similar to \cs{seq_set_filter:NNn}. We could actually
%   merge the two within a single function, but it would have weird
%   semantics.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_set_map:NNn
  { \@@_set_map:NNNn \tl_set:Nx }
\cs_new_protected_nopar:Npn \seq_gset_map:NNn
  { \@@_set_map:NNNn \tl_gset:Nx }
\cs_new_protected:Npn \@@_set_map:NNNn #1#2#3#4
  {
    \@@_push_item_def:n { \exp_not:N \@@_item:n {#4} }
    #1 #2 { #3 }
    \@@_pop_item_def:
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\seq_use:Nnnn}
% \begin{macro}[EXP, aux]
%   {\@@_use:NnNnn, \@@_use_ii:nwwwwnwn, \@@_use_iii:nwwn}
%   See \cs{clist_use:Nnnn} for a general explanation.  The main
%   difference is that we use \cs{@@_item:n} as a delimiter rather than
%   commas.  We also need to add \cs{@@_item:n} at various places.
%    \begin{macrocode}
\cs_new:Npn \seq_use:Nnnn #1#2#3#4
  {
    \seq_if_exist:NTF #1
      {
        \int_case:nnn { \seq_count:N #1 }
          {
            { 0 } { }
            { 1 } { \exp_after:wN \@@_use:NnNnn #1 \@@_item:n { } { } }
            { 2 } { \exp_after:wN \@@_use:NnNnn #1 {#2} }
          }
          {
            \exp_after:wN \@@_use_ii:nwwwwnwn
            \exp_after:wN { \exp_after:wN } #1 \@@_item:n
            \q_mark { \@@_use_ii:nwwwwnwn {#3} }
            \q_mark { \@@_use_iii:nwwn {#4} }
            \q_stop { }
          }
      }
      { \__msg_kernel_expandable_error:nnn { kernel } { bad-variable } {#1} }
  }
\cs_new:Npn \@@_use:NnNnn \@@_item:n #1 \@@_item:n #2#3
  { \exp_not:n { #1 #3 #2 } }
\cs_new:Npn \@@_use_ii:nwwwwnwn
    #1 \@@_item:n #2 \@@_item:n #3 \@@_item:n #4#5
    \q_mark #6#7 \q_stop #8
  {
    #6 \@@_item:n {#3} \@@_item:n {#4} #5
    \q_mark {#6} #7 \q_stop { #8 #1 #2 }
  }
\cs_new:Npn \@@_use_iii:nwwn #1 \@@_item:n #2 #3 \q_stop #4
  { \exp_not:n { #4 #1 #2 } }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Additions to \pkg{l3skip}}
%
%    \begin{macrocode}
%<@@=skip>
%    \end{macrocode}
%
% \begin{macro}{\skip_split_finite_else_action:nnNN}
%   This macro is useful when performing error checking in certain
%   circumstances. If the \meta{skip} register holds finite glue it sets
%   |#3| and |#4| to the stretch and shrink component, resp. If it holds
%   infinite glue set |#3| and |#4| to zero and issue the special action
%   |#2| which is probably an error message.
%   Assignments are local.
%    \begin{macrocode}
\cs_new:Npn \skip_split_finite_else_action:nnNN #1#2#3#4
  {
    \skip_if_finite:nTF {#1}
      {
        #3 = \etex_gluestretch:D #1 \scan_stop:
        #4 = \etex_glueshrink:D  #1 \scan_stop:
      }
      {
        #3 = \c_zero_skip
        #4 = \c_zero_skip
        #2
      }
  }
%    \end{macrocode}
%  \end{macro}
%
%  \subsection{Additions to \pkg{l3tl}}
%
%    \begin{macrocode}
%<@@=tl>
%    \end{macrocode}
%
% \begin{macro}[EXP,pTF]{\tl_if_single_token:n}
%   There are four cases: empty token list, token list starting with
%   a normal token, with a brace group, or with a space token.
%   If the token list starts with a normal token, remove it
%   and check for emptyness. Otherwise, compare with a single
%   space, only case where we have a single token.
%    \begin{macrocode}
\prg_new_conditional:Npnn \tl_if_single_token:n #1 { p , T , F , TF }
  {
    \tl_if_head_is_N_type:nTF {#1}
      { \__str_if_eq_x_return:nn { \exp_not:o { \use_none:n #1 } } { } }
      { \__str_if_eq_x_return:nn { \exp_not:n {#1} } { ~ } }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\tl_reverse_tokens:n}
% \begin{macro}[EXP,aux]{\@@_reverse_group:nn}
%   The same as \cs{tl_reverse:n} but with recursion within brace groups.
%    \begin{macrocode}
\cs_new:Npn \tl_reverse_tokens:n #1
  {
    \etex_unexpanded:D \exp_after:wN
      {
        \tex_romannumeral:D
        \@@_act:NNNnn
          \@@_reverse_normal:nN
          \@@_reverse_group:nn
          \@@_reverse_space:n
          { }
          {#1}
      }
  }
\cs_new:Npn \@@_reverse_group:nn #1
  {
    \@@_act_group_recurse:Nnn
      \@@_act_reverse_output:n
      { \tl_reverse_tokens:n }
  }
%    \end{macrocode}
% \end{macro}
% \begin{macro}[EXP,aux]{\@@_act_group_recurse:Nnn}
%   In many applications of \cs{@@_act:NNNnn}, we need to recursively
%   apply some transformation within brace groups, then output. In this
%   code, |#1| is the output function, |#2| is the transformation,
%   which should expand in two steps, and |#3| is the group.
%    \begin{macrocode}
\cs_new:Npn \@@_act_group_recurse:Nnn #1#2#3
  {
    \exp_args:Nf #1
      { \exp_after:wN \exp_after:wN \exp_after:wN { #2 {#3} } }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\tl_count_tokens:n}
% \begin{macro}[EXP,aux]{\@@_act_count_normal:nN,
%     \@@_act_count_group:nn,\@@_act_count_space:n}
%   The token coung is computed through an \cs{int_eval:n} construction.
%   Each \texttt{1+} is output to the \emph{left}, into the integer
%   expression, and the sum is ended by the \cs{c_zero} inserted by
%   \cs{@@_act_end:wn}. Somewhat a hack.
%    \begin{macrocode}
\cs_new:Npn \tl_count_tokens:n #1
  {
    \int_eval:n
      {
        \@@_act:NNNnn
          \@@_act_count_normal:nN
          \@@_act_count_group:nn
          \@@_act_count_space:n
          { }
          {#1}
      }
  }
\cs_new:Npn \@@_act_count_normal:nN #1 #2 { 1 + }
\cs_new:Npn \@@_act_count_space:n #1 { 1 + }
\cs_new:Npn \@@_act_count_group:nn #1 #2
  { 2 + \tl_count_tokens:n {#2} + }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{variable}{\c_@@_act_uppercase_tl, \c_@@_act_lowercase_tl}
%   These constants contain the correspondance between lowercase
%   and uppercase letters, in the form |aAbBcC...| and |AaBbCc...|
%   respectively.
%    \begin{macrocode}
\tl_const:Nn \c_@@_act_uppercase_tl
  {
    aA bB cC dD eE fF gG hH iI jJ kK lL mM
    nN oO pP qQ rR sS tT uU vV wW xX yY zZ
  }
\tl_const:Nn \c_@@_act_lowercase_tl
  {
    Aa Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk Ll Mm
    Nn Oo Pp Qq Rr Ss Tt Uu Vv Ww Xx Yy Zz
  }
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}[EXP]{\tl_expandable_uppercase:n,\tl_expandable_lowercase:n}
% \begin{macro}[EXP,aux]{\@@_act_case_normal:nN,
%     \@@_act_case_group:nn,\@@_act_case_space:n}
%   The only difference between uppercasing and lowercasing is
%   the table of correspondance that is used. As for other
%   token list actions, we feed \cs{@@_act:NNNnn} three
%   functions, and this time, we use the \meta{parameters}
%   argument to carry which case-changing we are applying.
%   A space is simply output. A normal token is compared
%   to each letter in the alphabet using \cs{str_if_eq:nn}
%   tests, and converted if necessary to upper/lowercase,
%   before being output. For a group, we must perform the
%   conversion within the group (the \cs{exp_after:wN} trigger
%   \tn{romannumeral}, which expands fully to give the
%   converted group), then output.
%    \begin{macrocode}
\cs_new:Npn \tl_expandable_uppercase:n #1
  {
    \etex_unexpanded:D \exp_after:wN
      {
        \tex_romannumeral:D
          \@@_act_case_aux:nn { \c_@@_act_uppercase_tl } {#1}
      }
  }
\cs_new:Npn \tl_expandable_lowercase:n #1
  {
    \etex_unexpanded:D \exp_after:wN
      {
        \tex_romannumeral:D
          \@@_act_case_aux:nn { \c_@@_act_lowercase_tl } {#1}
      }
  }
\cs_new:Npn \@@_act_case_aux:nn
  {
    \@@_act:NNNnn
      \@@_act_case_normal:nN
      \@@_act_case_group:nn
      \@@_act_case_space:n
  }
\cs_new:Npn \@@_act_case_space:n #1 { \@@_act_output:n {~} }
\cs_new:Npn \@@_act_case_normal:nN #1 #2
  {
    \exp_args:Nf \@@_act_output:n
      {
        \exp_args:NNo \str_case:nnn #2 {#1}
          { \exp_stop_f: #2 }
      }
  }
\cs_new:Npn \@@_act_case_group:nn #1 #2
  {
    \exp_after:wN \@@_act_output:n \exp_after:wN
      { \exp_after:wN { \tex_romannumeral:D \@@_act_case_aux:nn {#1} {#2} } }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\tl_item:nn, \tl_item:Nn, \tl_item:cn}
% \begin{macro}[aux]{\@@_item:nn}
%   The idea here is to find the offset of the item from the left, then use
%   a loop to grab the correct item. If the resulting offset is too large,
%   then \cs{quark_if_recursion_tail_stop:n} terminates the loop, and returns
%   nothing at all.
%    \begin{macrocode}
\cs_new:Npn \tl_item:nn #1#2
  {
    \exp_args:Nf \@@_item:nn
      {
        \int_eval:n
          {
            \int_compare:nNnT {#2} < \c_zero
              { \tl_count:n {#1} + \c_one + }
            #2
          }
      }
    #1
    \q_recursion_tail
    \__prg_break_point:
  }
\cs_new:Npn \@@_item:nn #1#2
  {
    \__quark_if_recursion_tail_break:nN {#2} \__prg_break:
    \int_compare:nNnTF {#1} = \c_one
      { \__prg_break:n { \exp_not:n {#2} } }
      { \exp_args:Nf \@@_item:nn { \int_eval:n { #1 - 1 } } }
  }
\cs_new_nopar:Npn \tl_item:Nn { \exp_args:No \tl_item:nn }
\cs_generate_variant:Nn \tl_item:Nn { c }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Additions to \pkg{l3tokens}}
%
%    \begin{macrocode}
%<@@=char>
%    \end{macrocode}
%
% \begin{macro}{\char_set_active:Npn,\char_set_active:Npx}
% \begin{macro}{\char_gset_active:Npn,\char_gset_active:Npx}
% \begin{macro}{\char_set_active_eq:NN,\char_gset_active_eq:NN}
%    \begin{macrocode}
\group_begin:
  \char_set_catcode_active:N \^^@
  \cs_set:Npn \char_tmp:NN #1#2
    {
      \cs_new:Npn #1 ##1
        {
          \char_set_catcode_active:n { `##1 }
          \group_begin:
          \char_set_lccode:nn { `\^^@ } { `##1 }
          \tl_to_lowercase:n { \group_end: #2 ^^@ }
        }
    }
  \char_tmp:NN \char_set_active:Npn    \cs_set:Npn
  \char_tmp:NN \char_set_active:Npx    \cs_set:Npx
  \char_tmp:NN \char_gset_active:Npn   \cs_gset:Npn
  \char_tmp:NN \char_gset_active:Npx   \cs_gset:Npx
  \char_tmp:NN \char_set_active_eq:NN  \cs_set_eq:NN
  \char_tmp:NN \char_gset_active_eq:NN \cs_gset_eq:NN
\group_end:
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%    \begin{macrocode}
%<@@=peek>
%    \end{macrocode}
%
% \begin{macro}[TF]{\peek_N_type:}
% \begin{macro}{\@@_execute_branches_N_type:}
%   The next token is normal if it is neither a begin-group token,
%   nor an end-group token, nor a charcode-$32$ space token.
%   Note that implicit begin-group tokens, end-group tokens, and
%   spaces are also recognized as non-\texttt{N}-type.
%   Here, there is no \meta{search token}, so we feed a dummy
%   \cs{scan_stop:} to the \cs{peek_token_generic::NN} functions.
%    \begin{macrocode}
\cs_new_protected_nopar:Npn \@@_execute_branches_N_type:
  {
    \bool_if:nTF
      {
        \token_if_eq_catcode_p:NN \l_peek_token \c_group_begin_token ||
        \token_if_eq_catcode_p:NN \l_peek_token \c_group_end_token   ||
        \token_if_eq_meaning_p:NN \l_peek_token \c_space_token
      }
      { \@@_false:w }
      { \@@_true:w }
  }
\cs_new_protected_nopar:Npn \peek_N_type:TF
  { \@@_token_generic:NNTF \@@_execute_branches_N_type: \scan_stop: }
\cs_new_protected_nopar:Npn \peek_N_type:T
  { \@@_token_generic:NNT  \@@_execute_branches_N_type: \scan_stop: }
\cs_new_protected_nopar:Npn \peek_N_type:F
  { \@@_token_generic:NNF  \@@_execute_branches_N_type: \scan_stop: }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%    \begin{macrocode}
%</initex|package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
