% \iffalse meta-comment % %% File: l3skip.dtx Copyright (C) 2004-2011 Frank Mittelbach, The LaTeX3 Project %% (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 LaTeX3 Project. %% %% ----------------------------------------------------------------------- % %<*driver|package> \RequirePackage{l3names} \GetIdInfo$Id: l3skip.dtx 3499 2012-03-05 16:08:55Z bruno $ {L3 Experimental dimensions and skips} % %<*driver> \documentclass[full]{l3doc} \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % \title{^^A % The \pkg{l3skip} package\\ Dimensions and skips^^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} % % \LaTeX3 provides two general length variables: \texttt{dim} and % \texttt{skip}. Lengths stored as \texttt{dim} variables have a fixed % length, whereas \texttt{skip} lengths have a rubber (stretch/shrink) % component. In addition, the \texttt{muskip} type is available for % use in math mode: this is a special form of \texttt{skip} where the % lengths involved are determined by the current math font (in % \texttt{mu)}. There are common features in the creation and setting of % length variables, but for clarity the functions are grouped by variable % type. % % \section{Creating and initialising \texttt{dim} variables} % % \begin{function}{\dim_new:N, \dim_new:c} % \begin{syntax} % \cs{dim_new:N} \meta{dimension} % \end{syntax} % Creates a new \meta{dimension} or raises an error if the name is % already taken. The declaration is global. The \meta{dimension} % will initially be equal to $0$\,pt. % \end{function} % % \begin{function}[added = 2012-03-05]{\dim_const:Nn, \dim_const:cn} % \begin{syntax} % \cs{dim_const:Nn} \meta{dimension} \Arg{dimension expression} % \end{syntax} % Creates a new constant \meta{dimension} or raises an error if the % name is already taken. The value of the \meta{dimension} will be set % globally to the \meta{dimension expression}. % \end{function} % % \begin{function}{\dim_zero:N, \dim_zero:c, \dim_gzero:N, \dim_gzero:c} % \begin{syntax} % \cs{dim_zero:N} \meta{dimension} % \end{syntax} % Sets \meta{dimension} to $0$\,pt. % \end{function} % % \begin{function}[added = 2012-01-07] % {\dim_zero_new:N, \dim_zero_new:c, \dim_gzero_new:N, \dim_gzero_new:c} % \begin{syntax} % \cs{dim_zero_new:N} \meta{dimension} % \end{syntax} % Ensures that the \meta{dimension} exists globally by applying % \cs{dim_new:N} if necessary, then applies \cs{dim_(g)zero:N} to leave % the \meta{dimension} set to zero. % \end{function} % % \begin{function}[EXP, pTF, added=2012-03-03]{\dim_if_exist:N, \dim_if_exist:c} % \begin{syntax} % \cs{dim_if_exist_p:N} \meta{dimension} % \cs{dim_if_exist:NTF} \meta{dimension} \Arg{true code} \Arg{false code} % \end{syntax} % Tests whether the \meta{dimension} is currently defined. This does % not check that the \meta{dimension} really is a dimension variable. % \end{function} % % \section{Setting \texttt{dim} variables} % % \begin{function}[updated = 2011-10-22] % {\dim_add:Nn, \dim_add:cn, \dim_gadd:Nn, \dim_gadd:cn} % \begin{syntax} % \cs{dim_add:Nn} \meta{dimension} \Arg{dimension expression} % \end{syntax} % Adds the result of the \meta{dimension expression} to the current % content of the \meta{dimension}. % \end{function} % % \begin{function}[updated = 2011-10-22] % {\dim_set:Nn, \dim_set:cn, \dim_gset:Nn, \dim_gset:cn} % \begin{syntax} % \cs{dim_set:Nn} \meta{dimension} \Arg{dimension expression} % \end{syntax} % Sets \meta{dimension} to the value of \meta{dimension expression}, which % must evaluate to a length with units. % \end{function} % % \begin{function} % { % \dim_set_eq:NN, \dim_set_eq:cN, \dim_set_eq:Nc, \dim_set_eq:cc, % \dim_gset_eq:NN, \dim_gset_eq:cN, \dim_gset_eq:Nc, \dim_gset_eq:cc % } % \begin{syntax} % \cs{dim_set_eq:NN} \meta{dimension1} \meta{dimension2} % \end{syntax} % Sets the content of \meta{dimension1} equal to that of % \meta{dimension2}. % \end{function} % % \begin{function}[updated = 2012-02-06] % {\dim_set_max:Nn, \dim_set_max:cn, \dim_gset_max:Nn, \dim_gset_max:cn} % \begin{syntax} % \cs{dim_set_max:Nn} \meta{dimension} \Arg{dimension expression} % \end{syntax} % Compares the current value of the \meta{dimension} with that of the % \meta{dimension expression}, and sets the \meta{dimension} to the % larger of these two value. % \end{function} % % \begin{function}[updated = 2012-02-06] % {\dim_set_min:Nn, \dim_set_min:cn, \dim_gset_min:Nn, \dim_gset_min:cn} % \begin{syntax} % \cs{dim_set_min:Nn} \meta{dimension} \Arg{dimension expression} % \end{syntax} % Compares the current value of the \meta{dimension} with that of the % \meta{dimension expression}, and sets the \meta{dimension} to the % smaller of these two value. % \end{function} % % \begin{function}[updated = 2011-10-22] % {\dim_sub:Nn, \dim_sub:cn, \dim_gsub:Nn, \dim_gsub:cn} % \begin{syntax} % \cs{dim_sub:Nn} \meta{dimension} \Arg{dimension expression} % \end{syntax} % Subtracts the result of the \meta{dimension expression} to the % current content of the \meta{dimension}. % \end{function} % % \section{Utilities for dimension calculations} % % \begin{function}[updated = 2011-10-22, EXP]{\dim_abs:n} % \begin{syntax} % \cs{dim_abs:n} \Arg{dimexpr} % \end{syntax} % Converts the \meta{dimexpr} to its absolute value, leaving the result % in the input stream as an \meta{dimension denotation}. % \end{function} % % \begin{function}[updated = 2011-10-22, EXP]{\dim_ratio:nn} % \begin{syntax} % \cs{dim_ratio:nn} \Arg{dimexpr_1} \Arg{dimexpr_2} % \end{syntax} % Parses the two \meta{dimension expressions} and converts the ratio of % the two to a form suitable for use inside a \meta{dimension expression}. % This ratio is then left in the input stream, allowing syntax such as % \begin{verbatim} % \dim_set:Nn \l_my_dim % { 10 pt * \dim_ratio:nn { 5 pt } { 10 pt } } % \end{verbatim} % The output of \cs{dim_ratio:nn} on full expansion is a ration expression % between two integers, with all distances converted to scaled points. % Thus % \begin{verbatim} % \tl_set:Nx \l_my_tl { \dim_ratio:nn { 5 pt } { 10 pt } } % \tl_show:N \l_my_tl % \end{verbatim} % will display |327680/655360| on the terminal. % \end{function} % % \section{Dimension expression conditionals} % % \begin{function}[EXP,pTF]{\dim_compare:nNn} % \begin{syntax} % \cs{dim_compare_p:nNn} \Arg{dimexpr_1} \meta{relation} \Arg{dimexpr_2} \\ % \cs{dim_compare:nNnTF} % ~~\Arg{dimexpr_1} \meta{relation} \Arg{dimexpr_2} % ~~\Arg{true code} \Arg{false code} % \end{syntax} % This function first evaluates each of the \meta{dimension expressions} % as described for \cs{dim_eval:n}. The two results are then % compared using the \meta{relation}: % \begin{center} % \begin{tabular}{ll} % Equal & |=| \\ % Greater than & |>| \\ % Less than & |<| \\ % \end{tabular} % \end{center} % \end{function} % % \begin{function}[EXP,pTF]{\dim_compare:n} % \begin{syntax} % \cs{dim_compare_p:n} \{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \\ % \cs{dim_compare:nTF} % ~~\{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} % ~~\Arg{true code} \Arg{false code} % \end{syntax} % This function first evaluates each of the \meta{dimension expressions} % as described for \cs{dim_eval:n}. The two results are then % compared using the \meta{relation}: % \begin{center} % \begin{tabular}{ll} % Equal & |=| or |==| \\ % Greater than or equal to & |>=| \\ % Greater than & |>| \\ % Less than or equal to & |<=| \\ % Less than & |<| \\ % Not equal & |!=| \\ % \end{tabular} % \end{center} % \end{function} % % \section{Dimension expression loops} % % \begin{function}[rEXP]{\dim_do_while:nNnn} % \begin{syntax} % \cs{dim_do_while:nNnn} \Arg{dimexpr_1} \meta{relation} \Arg{dimexpr_2} \Arg{code} % \end{syntax} % Evaluates the relationship between the two \meta{dimension expressions} % as described for \cs{dim_compare:nNnTF}, and then places the % \meta{code} in the input stream if the \meta{relation} is % \texttt{true}. After the \meta{code} has been processed by \TeX{} the % test will be repeated, and a loop will occur until the test is % \texttt{false}. % \end{function} % % \begin{function}[rEXP]{\dim_do_until:nNnn} % \begin{syntax} % \cs{dim_do_until:nNnn} \Arg{dimexpr_1} \meta{relation} \Arg{dimexpr_2} \Arg{code} % \end{syntax} % Evaluates the relationship between the two \meta{dimension expressions} % as described for \cs{dim_compare:nNnTF}, and then places the % \meta{code} in the input stream if the \meta{relation} is % \texttt{false}. After the \meta{code} has been processed by \TeX{} the % test will be repeated, and a loop will occur until the test is % \texttt{true}. % \end{function} % % \begin{function}[rEXP]{\dim_until_do:nNnn} % \begin{syntax} % \cs{dim_until_do:nNnn} \Arg{dimexpr_1} \meta{relation} \Arg{dimexpr_2} \Arg{code} % \end{syntax} % Places the \meta{code} in the input stream for \TeX{} to process, and % then evaluates the relationship between the two % \meta{dimension expressions} as described for \cs{dim_compare:nNnTF}. % If the test is \texttt{false} then the \meta{code} will be inserted % into the input stream again and a loop will occur until the % \meta{relation} is \texttt{true}. % \end{function} % % \begin{function}[rEXP]{\dim_while_do:nNnn} % \begin{syntax} % \cs{dim_while_do:nNnn} \Arg{dimexpr_1} \meta{relation} \Arg{dimexpr_2} \Arg{code} % \end{syntax} % Places the \meta{code} in the input stream for \TeX{} to process, and % then evaluates the relationship between the two % \meta{dimension expressions} as described for \cs{dim_compare:nNnTF}. % If the test is \texttt{true} then the \meta{code} will be inserted % into the input stream again and a loop will occur until the % \meta{relation} is \texttt{false}. % \end{function} % % \begin{function}[rEXP]{\dim_do_while:nn} % \begin{syntax} % \cs{dim_do_while:nn} \{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \Arg{code} % \end{syntax} % Evaluates the relationship between the two \meta{dimension expressions} % as described for \cs{dim_compare:nTF}, and then places the % \meta{code} in the input stream if the \meta{relation} is % \texttt{true}. After the \meta{code} has been processed by \TeX{} the % test will be repeated, and a loop will occur until the test is % \texttt{false}. % \end{function} % % \begin{function}[rEXP]{\dim_do_until:nn} % \begin{syntax} % \cs{dim_do_until:nn} \{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \Arg{code} % \end{syntax} % Evaluates the relationship between the two \meta{dimension expressions} % as described for \cs{dim_compare:nTF}, and then places the % \meta{code} in the input stream if the \meta{relation} is % \texttt{false}. After the \meta{code} has been processed by \TeX{} the % test will be repeated, and a loop will occur until the test is % \texttt{true}. % \end{function} % % \begin{function}[rEXP]{\dim_until_do:nn} % \begin{syntax} % \cs{dim_until_do:nn} \{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \Arg{code} % \end{syntax} % Places the \meta{code} in the input stream for \TeX{} to process, and % then evaluates the relationship between the two % \meta{dimension expressions} as described for \cs{dim_compare:nTF}. % If the test is \texttt{false} then the \meta{code} will be inserted % into the input stream again and a loop will occur until the % \meta{relation} is \texttt{true}. % \end{function} % % \begin{function}[rEXP]{\dim_while_do:nn} % \begin{syntax} % \cs{dim_while_do:nn} \{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \Arg{code} % \end{syntax} % Places the \meta{code} in the input stream for \TeX{} to process, and % then evaluates the relationship between the two % \meta{dimension expressions} as described for \cs{dim_compare:nTF}. % If the test is \texttt{true} then the \meta{code} will be inserted % into the input stream again and a loop will occur until the % \meta{relation} is \texttt{false}. % \end{function} % % \section{Using \texttt{dim} expressions and variables} % % \begin{function}[updated = 2011-10-22, EXP]{\dim_eval:n} % \begin{syntax} % \cs{dim_eval:n} \Arg{dimension expression} % \end{syntax} % Evaluates the \meta{dimension expression}, expanding any % dimensions and token list variables within the \meta{expression} % to their content (without requiring \cs{dim_use:N}/\cs{tl_use:N}) % and applying the standard mathematical rules. The result of the % calculation is left in the input stream as a % \meta{dimension denotation} after two expansions. This will be % expressed in points (\texttt{pt}), and will require suitable % termination if used in a \TeX{}-style assignment as it is \emph{not} % an \meta{internal dimension}. % \end{function} % % \begin{function}[EXP]{\dim_use:N, \dim_use:c} % \begin{syntax} % \cs{dim_use:N} \meta{dimension} % \end{syntax} % Recovers the content of a \meta{dimension} and places it directly % in the input stream. An error will be raised if the variable does % not exist or if it is invalid. Can be omitted in places where a % \meta{dimension} is required (such as in the argument of % \cs{dim_eval:n}). % \begin{texnote} % \cs{dim_use:N} is the \TeX{} primitive \tn{the}: this is one of % several \LaTeX3 names for this primitive. % \end{texnote} % \end{function} % % \section{Viewing \texttt{dim} variables} % % \begin{function}{\dim_show:N, \dim_show:c} % \begin{syntax} % \cs{dim_show:N} \meta{dimension} % \end{syntax} % Displays the value of the \meta{dimension} on the terminal. % \end{function} % % \begin{function}[added = 2011-11-22]{\dim_show:n} % \begin{syntax} % \cs{dim_show:n} \meta{dimension expression} % \end{syntax} % Displays the result of evaluating the \meta{dimension expression} % on the terminal. % \end{function} % % \section{Constant dimensions} % % \begin{variable}{\c_max_dim} % The maximum value that can be stored as a dimension or skip (these % are equivalent). % \end{variable} % % \begin{variable}{\c_zero_dim} % A zero length as a dimension or a skip (these are equivalent). % \end{variable} % % \section{Scratch dimensions} % % \begin{variable}{\l_tmpa_dim, \l_tmpb_dim, \l_tmpc_dim} % Scratch dimension for local assignment. These are never used by % the kernel code, and so are safe for use with any \LaTeX3-defined % function. However, they may be overwritten by other non-kernel % code and so should only be used for short-term storage. % \end{variable} % % \begin{variable}{\g_tmpa_dim, \g_tmpb_dim} % Scratch dimension for global assignment. These are never used by % the kernel code, and so are safe for use with any \LaTeX3-defined % function. However, they may be overwritten by other non-kernel % code and so should only be used for short-term storage. % \end{variable} % % \section{Creating and initialising \texttt{skip} variables} % % \begin{function}{\skip_new:N, \skip_new:c} % \begin{syntax} % \cs{skip_new:N} \meta{skip} % \end{syntax} % Creates a new \meta{skip} or raises an error if the name is % already taken. The declaration is global. The \meta{skip} % will initially be equal to $0$\,pt. % \end{function} % % \begin{function}[added = 2012-03-05]{\skip_const:Nn, \skip_const:cn} % \begin{syntax} % \cs{skip_const:Nn} \meta{skip} \Arg{skip expression} % \end{syntax} % Creates a new constant \meta{skip} or raises an error if the % name is already taken. The value of the \meta{skip} will be set % globally to the \meta{skip expression}. % \end{function} % % \begin{function}{\skip_zero:N, \skip_zero:c, \skip_gzero:N, \skip_gzero:c} % \begin{syntax} % \cs{skip_zero:N} \meta{skip} % \end{syntax} % Sets \meta{skip} to $0$\,pt. % \end{function} % % \begin{function}[added = 2012-01-07] % {\skip_zero_new:N, \skip_zero_new:c, \skip_gzero_new:N, \skip_gzero_new:c} % \begin{syntax} % \cs{skip_zero_new:N} \meta{skip} % \end{syntax} % Ensures that the \meta{skip} exists globally by applying % \cs{skip_new:N} if necessary, then applies \cs{skip_(g)zero:N} to leave % the \meta{skip} set to zero. % \end{function} % % \begin{function}[EXP, pTF, added=2012-03-03] % {\skip_if_exist:N, \skip_if_exist:c} % \begin{syntax} % \cs{skip_if_exist_p:N} \meta{skip} % \cs{skip_if_exist:NTF} \meta{skip} \Arg{true code} \Arg{false code} % \end{syntax} % Tests whether the \meta{skip} is currently defined. This does not % check that the \meta{skip} really is a skip variable. % \end{function} % % \section{Setting \texttt{skip} variables} % % \begin{function}[updated = 2011-10-22] % {\skip_add:Nn, \skip_add:cn, \skip_gadd:Nn, \skip_gadd:cn} % \begin{syntax} % \cs{skip_add:Nn} \meta{skip} \Arg{skip expression} % \end{syntax} % Adds the result of the \meta{skip expression} to the current % content of the \meta{skip}. % \end{function} % % \begin{function}[updated = 2011-10-22] % {\skip_set:Nn, \skip_set:cn, \skip_gset:Nn, \skip_gset:cn} % \begin{syntax} % \cs{skip_set:Nn} \meta{skip} \Arg{skip expression} % \end{syntax} % Sets \meta{skip} to the value of \meta{skip expression}, which % must evaluate to a length with units and may include a rubber % component (for example |1 cm plus 0.5 cm|. % \end{function} % % \begin{function} % { % \skip_set_eq:NN, \skip_set_eq:cN, \skip_set_eq:Nc, \skip_set_eq:cc, % \skip_gset_eq:NN, \skip_gset_eq:cN, \skip_gset_eq:Nc, \skip_gset_eq:cc % } % \begin{syntax} % \cs{skip_set_eq:NN} \meta{skip1} \meta{skip2} % \end{syntax} % Sets the content of \meta{skip1} equal to that of \meta{skip2}. % \end{function} % % \begin{function}[updated = 2011-10-22] % {\skip_sub:Nn, \skip_sub:cn, \skip_gsub:Nn, \skip_gsub:cn} % \begin{syntax} % \cs{skip_sub:Nn} \meta{skip} \Arg{skip expression} % \end{syntax} % Subtracts the result of the \meta{skip expression} to the % current content of the \meta{skip}. % \end{function} % % \section{Skip expression conditionals} % % \begin{function}[EXP,pTF]{\skip_if_eq:nn} % \begin{syntax} % \cs{skip_if_eq_p:nn} \Arg{skipexpr_1} \Arg{skipexpr_2} % \cs{dim_compare:nTF} % ~~\Arg{skip expr1} \Arg{skip expr2} % ~~\Arg{true code} \Arg{false code} % \end{syntax} % This function first evaluates each of the % \meta{skip expressions} as described for \cs{skip_eval:n}. % The two results are then compared for exact equality, % \emph{i.e.}~both the fixed and rubber components must be the same % for the test to be true. % \end{function} % % \begin{function}[EXP, pTF, updated = 2012-03-05]{\skip_if_infinite_glue:n} % \begin{syntax} % \cs{skip_if_infinite_glue_p:n} \Arg{skipexpr} % \cs{skip_if_infinite_glue:nTF} \Arg{skipexpr} \Arg{true code} \Arg{false code} % \end{syntax} % Evaluates the \meta{skip expression} as described for \cs{skip_eval:n}, % and then tests if this contains an infinite stretch or shrink % component (or both). % \end{function} % % \begin{function}[EXP, pTF, added = 2012-03-05]{\skip_if_finite:n} % \begin{syntax} % \cs{skip_if_finite_p:n} \Arg{skipexpr} % \cs{skip_if_finite:nTF} \Arg{skipexpr} \Arg{true code} \Arg{false code} % \end{syntax} % Evaluates the \meta{skip expression} as described for \cs{skip_eval:n}, % and then tests if all of its components are finite. % \end{function} % % \section{Using \texttt{skip} expressions and variables} % % \begin{function}[updated = 2011-10-22, EXP]{\skip_eval:n} % \begin{syntax} % \cs{skip_eval:n} \Arg{skip expression} % \end{syntax} % Evaluates the \meta{skip expression}, expanding any skips % and token list variables within the \meta{expression} % to their content (without requiring \cs{skip_use:N}/\cs{tl_use:N}) % and applying the standard mathematical rules. The result of the % calculation is left in the input stream as a \meta{glue denotation} % after two expansions. This will be expressed in points (\texttt{pt}), % and will require suitable termination if used in a \TeX{}-style % assignment as it is \emph{not} an \meta{internal glue}. % \end{function} % % \begin{function}[EXP]{\skip_use:N, \skip_use:c} % \begin{syntax} % \cs{skip_use:N} \meta{skip} % \end{syntax} % Recovers the content of a \meta{skip} and places it directly % in the input stream. An error will be raised if the variable does % not exist or if it is invalid. Can be omitted in places where a % \meta{dimension} is required (such as in the argument of % \cs{skip_eval:n}). % \begin{texnote} % \cs{skip_use:N} is the \TeX{} primitive \tn{the}: this is one of % several \LaTeX3 names for this primitive. % \end{texnote} % \end{function} % % \section{Viewing \texttt{skip} variables} % % \begin{function}{\skip_show:N, \skip_show:c} % \begin{syntax} % \cs{skip_show:N} \meta{skip} % \end{syntax} % Displays the value of the \meta{skip} on the terminal. % \end{function} % % \begin{function}[added = 2011-11-22]{\skip_show:n} % \begin{syntax} % \cs{skip_show:n} \meta{skip expression} % \end{syntax} % Displays the result of evaluating the \meta{skip expression} % on the terminal. % \end{function} % % \section{Constant skips} % % \begin{variable}{\c_max_skip} % The maximum value that can be stored as a dimension or skip (these % are equivalent). % \end{variable} % % \begin{variable}{\c_zero_skip} % A zero length as a dimension or a skip (these are equivalent). % \end{variable} % % \section{Scratch skips} % % \begin{variable}{\l_tmpa_skip, \l_tmpb_skip, \l_tmpc_skip} % Scratch skip for local assignment. These are never used by % the kernel code, and so are safe for use with any \LaTeX3-defined % function. However, they may be overwritten by other non-kernel % code and so should only be used for short-term storage. % \end{variable} % % \begin{variable}{\g_tmpa_skip, \g_tmpb_skip} % Scratch skip for global assignment. These are never used by % the kernel code, and so are safe for use with any \LaTeX3-defined % function. However, they may be overwritten by other non-kernel % code and so should only be used for short-term storage. % \end{variable} % % \section{Creating and initialising \texttt{muskip} variables} % % \begin{function}{\muskip_new:N, \muskip_new:c} % \begin{syntax} % \cs{muskip_new:N} \meta{muskip} % \end{syntax} % Creates a new \meta{muskip} or raises an error if the name is % already taken. The declaration is global. The \meta{muskip} % will initially be equal to $0$\,mu. % \end{function} % % \begin{function}[added = 2012-03-05]{\muskip_const:Nn, \muskip_const:cn} % \begin{syntax} % \cs{muskip_const:Nn} \meta{muskip} \Arg{muskip expression} % \end{syntax} % Creates a new constant \meta{muskip} or raises an error if the % name is already taken. The value of the \meta{muskip} will be set % globally to the \meta{muskip expression}. % \end{function} % % \begin{function} % {\muskip_zero:N, \muskip_zero:c, \muskip_gzero:N, \muskip_gzero:c} % \begin{syntax} % \cs{skip_zero:N} \meta{muskip} % \end{syntax} % Sets \meta{muskip} to $0$\,mu. % \end{function} % % \begin{function}[added = 2012-01-07] % { % \muskip_zero_new:N, \muskip_zero_new:c, % \muskip_gzero_new:N, \muskip_gzero_new:c % } % \begin{syntax} % \cs{muskip_zero_new:N} \meta{muskip} % \end{syntax} % Ensures that the \meta{muskip} exists globally by applying % \cs{muskip_new:N} if necessary, then applies \cs{muskip_(g)zero:N} % to leave the \meta{muskip} set to zero. % \end{function} % % \begin{function}[EXP, pTF, added=2012-03-03] % {\muskip_if_exist:N, \muskip_if_exist:c} % \begin{syntax} % \cs{muskip_if_exist_p:N} \meta{muskip} % \cs{muskip_if_exist:NTF} \meta{muskip} \Arg{true code} \Arg{false code} % \end{syntax} % Tests whether the \meta{muskip} is currently defined. This does not % check that the \meta{muskip} really is a muskip variable. % \end{function} % % \section{Setting \texttt{muskip} variables} % % \begin{function}[updated = 2011-10-22] % {\muskip_add:Nn, \muskip_add:cn, \muskip_gadd:Nn, \muskip_gadd:cn} % \begin{syntax} % \cs{muskip_add:Nn} \meta{muskip} \Arg{muskip expression} % \end{syntax} % Adds the result of the \meta{muskip expression} to the current % content of the \meta{muskip}. % \end{function} % % \begin{function}[updated = 2011-10-22] % {\muskip_set:Nn, \muskip_set:cn, \muskip_gset:Nn, \muskip_gset:cn} % \begin{syntax} % \cs{muskip_set:Nn} \meta{muskip} \Arg{muskip expression} % \end{syntax} % Sets \meta{muskip} to the value of \meta{muskip expression}, which % must evaluate to a math length with units and may include a rubber % component (for example |1 mu plus 0.5 mu|. % \end{function} % % \begin{function} % { % \muskip_set_eq:NN, \muskip_set_eq:cN, % \muskip_set_eq:Nc, \muskip_set_eq:cc, % \muskip_gset_eq:NN, \muskip_gset_eq:cN, % \muskip_gset_eq:Nc, \muskip_gset_eq:cc % } % \begin{syntax} % \cs{muskip_set_eq:NN} \meta{muskip1} \meta{muskip2} % \end{syntax} % Sets the content of \meta{muskip1} equal to that of % \meta{muskip2}. % \end{function} % % \begin{function}[updated = 2011-10-22] % {\muskip_sub:Nn, \muskip_sub:cn, \muskip_gsub:Nn, \muskip_gsub:cn} % \begin{syntax} % \cs{muskip_sub:Nn} \meta{muskip} \Arg{muskip expression} % \end{syntax} % Subtracts the result of the \meta{muskip expression} to the % current content of the \meta{skip}. % \end{function} % % \section{Using \texttt{muskip} expressions and variables} % % \begin{function}[updated = 2011-10-22, EXP]{\muskip_eval:n} % \begin{syntax} % \cs{muskip_eval:n} \Arg{muskip expression} % \end{syntax} % Evaluates the \meta{muskip expression}, expanding any skips % and token list variables within the \meta{expression} % to their content (without requiring \cs{muskip_use:N}/\cs{tl_use:N}) % and applying the standard mathematical rules. The result of the % calculation is left in the input stream as a \meta{muglue denotation} % after two expansions. This will be expressed in \texttt{mu}, % and will require suitable termination if used in a \TeX{}-style % assignment as it is \emph{not} an \meta{internal muglue}. % \end{function} % % \begin{function}[EXP]{\muskip_use:N, \muskip_use:c} % \begin{syntax} % \cs{muskip_use:N} \meta{muskip} % \end{syntax} % Recovers the content of a \meta{skip} and places it directly % in the input stream. An error will be raised if the variable does % not exist or if it is invalid. Can be omitted in places where a % \meta{dimension} is required (such as in the argument of % \cs{muskip_eval:n}). % \begin{texnote} % \cs{muskip_use:N} is the \TeX{} primitive \tn{the}: this is one of % several \LaTeX3 names for this primitive. % \end{texnote} % \end{function} % % \section{Inserting skips into the output} % % \begin{function}[updated = 2011-10-22] % {\skip_horizontal:N, \skip_horizontal:c, \skip_horizontal:n} % \begin{syntax} % \cs{skip_horizontal:N} \meta{skip} % \cs{skip_horizontal:n} \Arg{skipexpr} % \end{syntax} % Inserts a horizontal \meta{skip} into the current list. % \begin{texnote} % \cs{skip_horizontal:N} is the \TeX{} primitive \tn{hskip} renamed. % \end{texnote} % \end{function} % % \begin{function}[updated = 2011-10-22] % {\skip_vertical:N, \skip_vertical:c, \skip_vertical:n} % \begin{syntax} % \cs{skip_vertical:N} \meta{skip} % \cs{skip_vertical:n} \Arg{skipexpr} % \end{syntax} % Inserts a vertical \meta{skip} into the current list. % \begin{texnote} % \cs{skip_vertical:N} is the \TeX{} primitive \tn{vskip} renamed. % \end{texnote} % \end{function} % % \section{Viewing \texttt{muskip} variables} % % \begin{function}{\muskip_show:N, \muskip_show:c} % \begin{syntax} % \cs{muskip_show:N} \meta{muskip} % \end{syntax} % Displays the value of the \meta{muskip} on the terminal. % \end{function} % % \begin{function}[added = 2011-11-22]{\muskip_show:n} % \begin{syntax} % \cs{muskip_show:n} \meta{muskip expression} % \end{syntax} % Displays the result of evaluating the \meta{muskip expression} % on the terminal. % \end{function} % % \section{Internal functions} % % \begin{function}{\if_dim:w} % \begin{syntax} % \cs{if_dim:w} \meta{dimen1} \meta{relation} \meta{dimen1} % ~~\meta{true code} % \cs{else:} % ~~\meta{false} % \cs{fi:} % \end{syntax} % Compare two dimensions. The \meta{relation} is one of % |<|, |=| or |>| with category code $12$. % \begin{texnote} % This is the \TeX{} primitive \tn{ifdim}. % \end{texnote} % \end{function} % % \begin{function}[EXP]{\dim_eval:w, \dim_eval_end:} % \begin{syntax} % \cs{dim_eval:w} \meta{dimexpr} \cs{dim_eval_end:} % \end{syntax} % Evaluates \meta{dimension expression} as described for \cs{dim_eval:n}. % The evaluation stops when an unexpandable token which is not a valid % part of a dimension is read or when \cs{dim_eval_end:} is % reached. The latter is gobbled by the scanner mechanism: % \cs{dim_eval_end:} itself is unexpandable but used correctly % the entire construct is expandable. % \begin{texnote} % This is the \eTeX{} primitive \tn{dimexpr}. % \end{texnote} % \end{function} % % \section{Experimental skip functions} % % \begin{function}[updated = 2011-10-22]{\skip_split_finite_else_action:nnNN} % \begin{syntax} % \cs{skip_split_finite_else_action:nnNN} \Arg{skipexpr} \Arg{action} % ~~\meta{dimen1} \meta{dimen2} % \end{syntax} % Checks if the \meta{skipexpr} contains finite glue. If it does then it % assigns % \meta{dimen1} the stretch component and \meta{dimen2} the shrink % component. If % it contains infinite glue set \meta{dimen1} and \meta{dimen2} to $0$\,pt % and place |#2| into the input stream: this is usually an error or % warning message of some sort. % \end{function} % % \section{Internal functions} % % \begin{function}[added = 2011-11-11, EXP] % {\dim_strip_bp:n, \dim_strip_pt:n} % \begin{syntax} % \cs{dim_strip_bp:n} \Arg{dimension expression} % \cs{dim_strip_pt:n} \Arg{dimension expression} % \end{syntax} % Evaluates the \meta{dimension expression}, expanding any % dimensions and token list variables within the \meta{expression} % to their content (without requiring \cs{dim_use:N}/\cs{tl_use:N}) % and applying the standard mathematical rules. The magnitude of the % result, expressed in big points (\texttt{bp}) or points (\texttt{pt}), % will be left in the input stream with \emph{no units}. If the decimal % part of the magnitude is zero, this will be omitted. % % If the \Arg{dimension expression} contains additional units, these will % be ignored, so for example % \begin{verbatim} % \dim_strip_pt:n { 1 bp pt } % \end{verbatim} % will leave |1.00374| in the input stream (\emph{i.e.}~the magnitude of % one \enquote{big point} when converted to points). % \end{function} % % \end{documentation} % % \begin{implementation} % % \section{\pkg{l3skip} implementation} % % \begin{macrocode} %<*initex|package> % \end{macrocode} % % \begin{macrocode} %<*package> \ProvidesExplPackage {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} \package_check_loaded_expl: % % \end{macrocode} % % \subsection{Length primitives renamed} % % \begin{macro}{\if_dim:w} % \begin{macro}{\dim_eval:w} % \begin{macro}{\dim_eval_end:} % Primitives renamed. % \begin{macrocode} \cs_new_eq:NN \if_dim:w \tex_ifdim:D \cs_new_eq:NN \dim_eval:w \etex_dimexpr:D \cs_new_eq:NN \dim_eval_end: \tex_relax:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \subsection{Creating and initialising \texttt{dim} variables} % % \begin{macro}{\dim_new:N,\dim_new:c} % Allocating \meta{dim} registers \ldots % \begin{macrocode} %<*package> \cs_new_protected:Npn \dim_new:N #1 { \chk_if_free_cs:N #1 \newdimen #1 } % \cs_generate_variant:Nn \dim_new:N { c } % \end{macrocode} % \end{macro} % % \begin{macro}{\dim_const:Nn, \dim_const:cn} % Contrarily to integer constants, we cannot avoid using a register, % even for constants. % \begin{macrocode} \cs_new_protected:Npn \dim_const:Nn #1 { \dim_new:N #1 \dim_gset:Nn #1 } \cs_generate_variant:Nn \dim_const:Nn { c } % \end{macrocode} % \end{macro} % % \begin{macro}{\dim_zero:N, \dim_zero:c} % \begin{macro}{\dim_gzero:N, \dim_gzero:c} % Reset the register to zero. % \begin{macrocode} \cs_new_protected:Npn \dim_zero:N #1 { #1 \c_zero_dim } \cs_new_protected:Npn \dim_gzero:N { \tex_global:D \dim_zero:N } \cs_generate_variant:Nn \dim_zero:N { c } \cs_generate_variant:Nn \dim_gzero:N { c } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro} % {\dim_zero_new:N, \dim_zero_new:c, \dim_gzero_new:N, \dim_gzero_new:c} % Create a register if needed, otherwise clear it. % \begin{macrocode} \cs_new_protected:Npn \dim_zero_new:N #1 { \dim_if_exist:NTF #1 { \dim_zero:N #1 } { \dim_new:N #1 } } \cs_new_protected:Npn \dim_gzero_new:N #1 { \dim_if_exist:NTF #1 { \dim_gzero:N #1 } { \dim_new:N #1 } } \cs_generate_variant:Nn \dim_zero_new:N { c } \cs_generate_variant:Nn \dim_gzero_new:N { c } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF]{\dim_if_exist:N, \dim_if_exist:c} % Copies of the \texttt{cs} functions defined in \pkg{l3basics}. % \begin{macrocode} \cs_new_eq:NN \dim_if_exist:NTF \cs_if_exist:NTF \cs_new_eq:NN \dim_if_exist:NT \cs_if_exist:NT \cs_new_eq:NN \dim_if_exist:NF \cs_if_exist:NF \cs_new_eq:NN \dim_if_exist_p:N \cs_if_exist_p:N \cs_new_eq:NN \dim_if_exist:cTF \cs_if_exist:cTF \cs_new_eq:NN \dim_if_exist:cT \cs_if_exist:cT \cs_new_eq:NN \dim_if_exist:cF \cs_if_exist:cF \cs_new_eq:NN \dim_if_exist_p:c \cs_if_exist_p:c % \end{macrocode} % \end{macro} % % \subsection{Setting \texttt{dim} variables} % % \begin{macro}{\dim_set:Nn, \dim_set:cn} % \begin{macro}{\dim_gset:Nn, \dim_gset:cn} % Setting dimensions is easy enough. % \begin{macrocode} \cs_new_protected:Npn \dim_set:Nn #1#2 { #1 ~ \dim_eval:w #2 \dim_eval_end: } \cs_new_protected:Npn \dim_gset:Nn { \tex_global:D \dim_set:Nn } \cs_generate_variant:Nn \dim_set:Nn { c } \cs_generate_variant:Nn \dim_gset:Nn { c } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\dim_set_eq:NN,\dim_set_eq:cN, \dim_set_eq:Nc,\dim_set_eq:cc} % \begin{macro} % {\dim_gset_eq:NN,\dim_gset_eq:cN, \dim_gset_eq:Nc,\dim_gset_eq:cc} % All straightforward. % \begin{macrocode} \cs_new_protected:Npn \dim_set_eq:NN #1#2 { #1 = #2 } \cs_generate_variant:Nn \dim_set_eq:NN { c } \cs_generate_variant:Nn \dim_set_eq:NN { Nc , cc } \cs_new_protected:Npn \dim_gset_eq:NN #1#2 { \tex_global:D #1 = #2 } \cs_generate_variant:Nn \dim_gset_eq:NN { c } \cs_generate_variant:Nn \dim_gset_eq:NN { Nc , cc } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\dim_set_max:Nn, \dim_set_max:cn} % \begin{macro}{\dim_set_min:Nn, \dim_set_min:cn} % \begin{macro}{\dim_gset_max:Nn, \dim_gset_max:cn} % \begin{macro}{\dim_gset_min:Nn, \dim_gset_min:cn} % \begin{macro}[aux]{\dim_set_max_aux:NNNn} % Setting maximum and minimum values is simply a case of so build-in % comparison. This only applies to dimensions as skips are not ordered. % \begin{macrocode} \cs_new_protected_nopar:Npn \dim_set_max:Nn { \dim_set_max_aux:NNNn < \dim_set:Nn } \cs_new_protected_nopar:Npn \dim_gset_max:Nn { \dim_set_max_aux:NNNn < \dim_gset:Nn } \cs_new_protected_nopar:Npn \dim_set_min:Nn { \dim_set_max_aux:NNNn > \dim_set:Nn } \cs_new_protected_nopar:Npn \dim_gset_min:Nn { \dim_set_max_aux:NNNn > \dim_gset:Nn } \cs_new_protected:Npn \dim_set_max_aux:NNNn #1#2#3#4 { \dim_compare:nNnT {#3} #1 {#4} { #2 #3 {#4} } } \cs_generate_variant:Nn \dim_set_max:Nn { c } \cs_generate_variant:Nn \dim_gset_max:Nn { c } \cs_generate_variant:Nn \dim_set_min:Nn { c } \cs_generate_variant:Nn \dim_gset_min:Nn { c } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\dim_add:Nn, \dim_add:cn} % \begin{macro}{\dim_gadd:Nn, \dim_gadd:cn} % \begin{macro}{\dim_sub:Nn, \dim_sub:cn} % \begin{macro}{\dim_gsub:Nn, \dim_gsub:cn} % Using |by| here deals with the (incorrect) case |\dimen123|. % \begin{macrocode} \cs_new_protected:Npn \dim_add:Nn #1#2 { \tex_advance:D #1 by \dim_eval:w #2 \dim_eval_end: } \cs_new_protected:Npn \dim_gadd:Nn { \tex_global:D \dim_add:Nn } \cs_generate_variant:Nn \dim_add:Nn { c } \cs_generate_variant:Nn \dim_gadd:Nn { c } \cs_new_protected:Npn \dim_sub:Nn #1#2 { \tex_advance:D #1 by - \dim_eval:w #2 \dim_eval_end: } \cs_new_protected:Npn \dim_gsub:Nn { \tex_global:D \dim_sub:Nn } \cs_generate_variant:Nn \dim_sub:Nn { c } \cs_generate_variant:Nn \dim_gsub:Nn { c } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \subsection{Utilities for dimension calculations} % % \begin{macro}{\dim_abs:n} % Similar to the \cs{int_abs:n} function, but here an additional % \meta{dimexpr} is needed as \TeX{} won't simply tidy up an additional % |-| for us. % \begin{macrocode} \cs_new:Npn \dim_abs:n #1 { \dim_use:N \dim_eval:w \if_dim:w \dim_eval:w #1 < \c_zero_dim - \fi: \dim_eval:w #1 \dim_eval_end: \dim_eval_end: } % \end{macrocode} % \end{macro} % % \begin{macro}{\dim_ratio:nn} % \begin{macro}[aux]{\dim_ratio_aux:n} % With dimension expressions, something like |10 pt * ( 5 pt / 10 pt )| will % not work. Instead, the ratio part needs to be converted to an integer % expression. Using \cs{int_value:w} forces everything into |sp|, avoiding % any decimal parts. % \begin{macrocode} \cs_new:Npn \dim_ratio:nn #1#2 { \dim_ratio_aux:n {#1} / \dim_ratio_aux:n {#2} } \cs_new:Npn \dim_ratio_aux:n #1 { \int_value:w \dim_eval:w #1 \dim_eval_end: } % \end{macrocode} % \end{macro} % \end{macro} % % \subsection{Dimension expression conditionals} % % \begin{macro}{\dim_compare_p:nNn} % \begin{macro}[TF]{\dim_compare:nNn} % Simple comparison. % \begin{macrocode} \prg_new_conditional:Npnn \dim_compare:nNn #1#2#3 { p , T , F , TF } { \if_dim:w \dim_eval:w #1 #2 \dim_eval:w #3 \dim_eval_end: \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}[pTF, EXP]{\dim_compare:n} % \begin{macro}[aux, EXP]{\dim_compare_aux:w, \dim_compare_aux:NNw} % \begin{macro}[aux, EXP] % { % \dim_compare_=:NNw, % \dim_compare_<:NNw, % \dim_compare_>:NNw, % \dim_compare_==:NNw, % \dim_compare_!=:NNw, % \dim_compare_<=:NNw, % \dim_compare_>=:NNw % } % This code is adapted from the \cs{int_compare:nTF} function. First % evaluate the left-hand side. Then access the relation symbol by % grabbing until \texttt{pt} (with category other), and pursue % otherwise just as for \cs{int_compare:nTF}. % \begin{macrocode} \prg_new_conditional:Npnn \dim_compare:n #1 { p , T , F , TF } { \exp_after:wN \dim_compare_aux:w \dim_use:N \dim_eval:w #1 \kernel_compare_error: \dim_eval_end: \prg_return_true: \else: \prg_return_false: \fi: } \exp_args:Nno \use:nn { \cs_new:Npn \dim_compare_aux:w #1 } { \tl_to_str:n { pt } } #2 \kernel_compare_error: { \exp_after:wN \dim_compare_aux:NNw #2 ?? \q_mark #1 pt #2 } \cs_new:Npn \dim_compare_aux:NNw #1#2#3 \q_mark { \use:c { dim_compare_ #1 \if_meaning:w = #2 = \fi: :NNw } \kernel_compare_error:Nw #1 } \cs_new:cpn { dim_compare_=:NNw } #1#2#3 = { \if_dim:w #3 = \dim_eval:w } \cs_new:cpn { dim_compare_<:NNw } #1#2#3 < { \if_dim:w #3 < \dim_eval:w } \cs_new:cpn { dim_compare_>:NNw } #1#2#3 > { \if_dim:w #3 > \dim_eval:w } \cs_new:cpn { dim_compare_==:NNw } #1#2#3 == { \if_dim:w #3 = \dim_eval:w } \cs_new:cpn { dim_compare_!=:NNw } #1#2#3 != { \reverse_if:N \if_dim:w #3 = \dim_eval:w } \cs_new:cpn { dim_compare_<=:NNw } #1#2#3 <= { \reverse_if:N \if_dim:w #3 > \dim_eval:w } \cs_new:cpn { dim_compare_>=:NNw } #1#2#3 >= { \reverse_if:N \if_dim:w #3 < \dim_eval:w } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \subsection{Dimension expression loops} % % \begin{macro}{\dim_while_do:nn} % \begin{macro}{\dim_until_do:nn} % \begin{macro}{\dim_do_while:nn} % \begin{macro}{\dim_do_until:nn} % |while_do| and |do_while| functions for dimensions. Same as for the % |int| type only the names have changed. % \begin{macrocode} \cs_set:Npn \dim_while_do:nn #1#2 { \dim_compare:nT {#1} { #2 \dim_while_do:nn {#1} {#2} } } \cs_set:Npn \dim_until_do:nn #1#2 { \dim_compare:nF {#1} { #2 \dim_until_do:nn {#1} {#2} } } \cs_set:Npn \dim_do_while:nn #1#2 { #2 \dim_compare:nT {#1} { \dim_do_while:nn {#1} {#2} } } \cs_set:Npn \dim_do_until:nn #1#2 { #2 \dim_compare:nF {#1} { \dim_do_until:nn {#1} {#2} } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\dim_while_do:nNnn} % \begin{macro}{\dim_until_do:nNnn} % \begin{macro}{\dim_do_while:nNnn} % \begin{macro}{\dim_do_until:nNnn} % |while_do| and |do_while| functions for dimensions. Same as for the % |int| type only the names have changed. % \begin{macrocode} \cs_set:Npn \dim_while_do:nNnn #1#2#3#4 { \dim_compare:nNnT {#1} #2 {#3} { #4 \dim_while_do:nNnn {#1} #2 {#3} {#4} } } \cs_set:Npn \dim_until_do:nNnn #1#2#3#4 { \dim_compare:nNnF {#1} #2 {#3} { #4 \dim_until_do:nNnn {#1} #2 {#3} {#4} } } \cs_set:Npn \dim_do_while:nNnn #1#2#3#4 { #4 \dim_compare:nNnT {#1} #2 {#3} { \dim_do_while:nNnn {#1} #2 {#3} {#4} } } \cs_set:Npn \dim_do_until:nNnn #1#2#3#4 { #4 \dim_compare:nNnF {#1} #2 {#3} { \dim_do_until:nNnn {#1} #2 {#3} {#4} } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \subsection{Using \texttt{dim} expressions and variables} % % \begin{macro}{\dim_eval:n} % Evaluating a dimension expression expandably. % \begin{macrocode} \cs_new:Npn \dim_eval:n #1 { \dim_use:N \dim_eval:w #1 \dim_eval_end: } % \end{macrocode} % \end{macro} % % \begin{macro}[EXP]{\dim_strip_bp:n} % \begin{macrocode} \cs_new:Npn \dim_strip_bp:n #1 { \dim_strip_pt:n { 0.996 26 \dim_eval:w #1 \dim_eval_end: } } % \end{macrocode} % \end{macro} % % \begin{macro}[EXP]{\dim_strip_pt:n} % \begin{macro}[EXP, aux]{\dim_strip_pt:w} % A function which comes up often enough to deserve a place in the kernel. % The idea here is that the input is assumed to be in \texttt{pt}, but can % be given in other units, while the output is the value of the dimension % in \texttt{pt} but with no units given. This is used a lot by low-level % manipulations. % \begin{macrocode} \cs_new:Npn \dim_strip_pt:n #1 { \exp_after:wN \dim_strip_pt:w \dim_use:N \dim_eval:w #1 \dim_eval_end: \q_stop } \use:x { \cs_new:Npn \exp_not:N \dim_strip_pt:w ##1 . ##2 \tl_to_str:n { pt } ##3 \exp_not:N \q_stop { ##1 \exp_not:N \int_compare:nNnT {##2} > \c_zero { . ##2 } } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\dim_use:N, \dim_use:c} % Accessing a \meta{dim}. % \begin{macrocode} \cs_new_eq:NN \dim_use:N \tex_the:D \cs_generate_variant:Nn \dim_use:N { c } % \end{macrocode} % \end{macro} % % \subsection{Viewing \texttt{dim} variables} % % \begin{macro}{\dim_show:N, \dim_show:c} % Diagnostics. % \begin{macrocode} \cs_new_eq:NN \dim_show:N \kernel_register_show:N \cs_generate_variant:Nn \dim_show:N { c } % \end{macrocode} % \end{macro} % % \begin{macro}{\dim_show:n} % Diagnostics. % \begin{macrocode} \cs_new_protected:Npn \dim_show:n #1 { \tex_showthe:D \dim_eval:w #1 \dim_eval_end: } % \end{macrocode} % \end{macro} % % \subsection{Constant dimensions} % % \begin{variable}{\c_zero_dim} % \begin{variable}{\c_max_dim} % The source for these depends on whether we are in package mode. % \begin{macrocode} %<*initex> \dim_new:N \c_zero_dim \dim_new:N \c_max_dim \dim_set:Nn \c_max_dim { 16383.99999 pt } % %<*package> \cs_new_eq:NN \c_zero_dim \z@ \cs_new_eq:NN \c_max_dim \maxdimen % % \end{macrocode} % \end{variable} % \end{variable} % % \subsection{Scratch dimensions} % % \begin{variable}{\l_tmpa_dim, \l_tmpb_dim, \l_tmpc_dim} % \begin{variable}{\g_tmpa_dim, \g_tmpb_dim} % We provide three local and two global scratch registers, maybe we % need more or less. % \begin{macrocode} \dim_new:N \l_tmpa_dim \dim_new:N \l_tmpb_dim \dim_new:N \l_tmpc_dim \dim_new:N \g_tmpa_dim \dim_new:N \g_tmpb_dim % \end{macrocode} % \end{variable} % \end{variable} % % \subsection{Creating and initialising \texttt{skip} variables} % % \begin{macro}{\skip_new:N,\skip_new:c} % Allocation of a new internal registers. % \begin{macrocode} %<*package> \cs_new_protected:Npn \skip_new:N #1 { \chk_if_free_cs:N #1 \newskip #1 } % \cs_generate_variant:Nn \skip_new:N { c } % \end{macrocode} % \end{macro} % % \begin{macro}{\skip_const:Nn, \skip_const:cn} % Contrarily to integer constants, we cannot avoid using a register, % even for constants. % \begin{macrocode} \cs_new_protected:Npn \skip_const:Nn #1 { \skip_new:N #1 \skip_gset:Nn #1 } \cs_generate_variant:Nn \skip_const:Nn { c } % \end{macrocode} % \end{macro} % % \begin{macro}{\skip_zero:N, \skip_zero:c} % \begin{macro}{\skip_gzero:N, \skip_gzero:c} % Reset the register to zero. % \begin{macrocode} \cs_new_protected:Npn \skip_zero:N #1 { #1 \c_zero_skip } \cs_new_protected:Npn \skip_gzero:N { \tex_global:D \skip_zero:N } \cs_generate_variant:Nn \skip_zero:N { c } \cs_generate_variant:Nn \skip_gzero:N { c } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro} % {\skip_zero_new:N, \skip_zero_new:c, \skip_gzero_new:N, \skip_gzero_new:c} % Create a register if needed, otherwise clear it. % \begin{macrocode} \cs_new_protected:Npn \skip_zero_new:N #1 { \skip_if_exist:NTF #1 { \skip_zero:N #1 } { \skip_new:N #1 } } \cs_new_protected:Npn \skip_gzero_new:N #1 { \skip_if_exist:NTF #1 { \skip_gzero:N #1 } { \skip_new:N #1 } } \cs_generate_variant:Nn \skip_zero_new:N { c } \cs_generate_variant:Nn \skip_gzero_new:N { c } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF]{\skip_if_exist:N, \skip_if_exist:c} % Copies of the \texttt{cs} functions defined in \pkg{l3basics}. % \begin{macrocode} \cs_new_eq:NN \skip_if_exist:NTF \cs_if_exist:NTF \cs_new_eq:NN \skip_if_exist:NT \cs_if_exist:NT \cs_new_eq:NN \skip_if_exist:NF \cs_if_exist:NF \cs_new_eq:NN \skip_if_exist_p:N \cs_if_exist_p:N \cs_new_eq:NN \skip_if_exist:cTF \cs_if_exist:cTF \cs_new_eq:NN \skip_if_exist:cT \cs_if_exist:cT \cs_new_eq:NN \skip_if_exist:cF \cs_if_exist:cF \cs_new_eq:NN \skip_if_exist_p:c \cs_if_exist_p:c % \end{macrocode} % \end{macro} % % \subsection{Setting \texttt{skip} variables} % % \begin{macro}{\skip_set:Nn, \skip_set:cn} % \begin{macro}{\skip_gset:Nn, \skip_gset:cn} % Much the same as for dimensions. % \begin{macrocode} \cs_new_protected:Npn \skip_set:Nn #1#2 { #1 ~ \etex_glueexpr:D #2 \scan_stop: } \cs_new_protected:Npn \skip_gset:Nn { \tex_global:D \skip_set:Nn } \cs_generate_variant:Nn \skip_set:Nn { c } \cs_generate_variant:Nn \skip_gset:Nn { c } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro} % {\skip_set_eq:NN,\skip_set_eq:cN, \skip_set_eq:Nc,\skip_set_eq:cc} % \begin{macro} % {\skip_gset_eq:NN,\skip_gset_eq:cN, \skip_gset_eq:Nc,\skip_gset_eq:cc} % All straightforward. % \begin{macrocode} \cs_new_protected:Npn \skip_set_eq:NN #1#2 { #1 = #2 } \cs_generate_variant:Nn \skip_set_eq:NN { c } \cs_generate_variant:Nn \skip_set_eq:NN { Nc , cc } \cs_new_protected:Npn \skip_gset_eq:NN #1#2 { \tex_global:D #1 = #2 } \cs_generate_variant:Nn \skip_gset_eq:NN { c } \cs_generate_variant:Nn \skip_gset_eq:NN { Nc , cc } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\skip_add:Nn, \skip_add:cn} % \begin{macro}{\skip_gadd:Nn, \skip_gadd:cn} % \begin{macro}{\skip_sub:Nn, \skip_sub:cn} % \begin{macro}{\skip_gsub:Nn, \skip_gsub:cn} % Using |by| here deals with the (incorrect) case |\skip123|. % \begin{macrocode} \cs_new_protected:Npn \skip_add:Nn #1#2 { \tex_advance:D #1 by \etex_glueexpr:D #2 \scan_stop: } \cs_new_protected:Npn \skip_gadd:Nn { \tex_global:D \skip_add:Nn } \cs_generate_variant:Nn \skip_add:Nn { c } \cs_generate_variant:Nn \skip_gadd:Nn { c } \cs_new_protected:Npn \skip_sub:Nn #1#2 { \tex_advance:D #1 by - \etex_glueexpr:D #2 \scan_stop: } \cs_new_protected:Npn \skip_gsub:Nn { \tex_global:D \skip_sub:Nn } \cs_generate_variant:Nn \skip_sub:Nn { c } \cs_generate_variant:Nn \skip_gsub:Nn { c } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \subsection{Skip expression conditionals} % % \begin{macro}[pTF]{\skip_if_eq:nn} % Comparing skips means doing two expansions to make strings, and then % testing them. As a result, only equality is tested. % \begin{macrocode} \prg_new_conditional:Npnn \skip_if_eq:nn #1#2 { p , T , F , TF } { \if_int_compare:w \pdftex_strcmp:D { \skip_eval:n { #1 } } { \skip_eval:n { #2 } } = \c_zero \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % \end{macro} % % \begin{macro}[EXP,pTF]{\skip_if_finite:n} % \begin{macro}[EXP,aux]{\skip_if_finite_aux:wwNw} % With \eTeX{}, we have an easy access to the order of infinities of % the stretch and shrink components of a skip. However, to access % both, we either need to evaluate the expression twice, or evaluate % it, then call an auxiliary to extract both pieces of information % from the result. Since we are going to need an auxiliary anyways, % it is quicker to make it search for the string \texttt{fil} which % characterizes infinite glue. % \begin{macrocode} \cs_set_protected:Npn \cs_tmp:w #1 { \prg_new_conditional:Npnn \skip_if_finite:n ##1 { p , T , F , TF } { \exp_after:wN \skip_if_finite_aux:wwNw \skip_use:N \etex_glueexpr:D ##1 ; \prg_return_false: #1 ; \prg_return_true: \q_stop } \cs_new:Npn \skip_if_finite_aux:wwNw ##1 #1 ##2 ; ##3 ##4 \q_stop {##3} } \exp_args:No \cs_tmp:w { \tl_to_str:n { fil } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}[EXP, pTF]{\skip_if_infinite_glue:n} % Reverse of \cs{skip_if_finite:nTF}. % \begin{macrocode} \prg_new_conditional:Npnn \skip_if_infinite_glue:n #1 { p , T , F , TF } { \skip_if_finite:nTF {#1} \prg_return_false: \prg_return_true: } % \end{macrocode} % \end{macro} % % \subsection{Using \texttt{skip} expressions and variables} % % \begin{macro}{\skip_eval:n} % Evaluating a skip expression expandably. % \begin{macrocode} \cs_new:Npn \skip_eval:n #1 { \skip_use:N \etex_glueexpr:D #1 \scan_stop: } % \end{macrocode} % \end{macro} % % \begin{macro}{\skip_use:N, \skip_use:c} % Accessing a \meta{skip}. % \begin{macrocode} \cs_new_eq:NN \skip_use:N \tex_the:D \cs_generate_variant:Nn \skip_use:N { c } % \end{macrocode} % \end{macro} % % \subsection{Inserting skips into the output} % % \begin{macro}{\skip_horizontal:N, \skip_horizontal:c, \skip_horizontal:n} % \begin{macro}{\skip_vertical:N, \skip_vertical:c, \skip_vertical:n} % Inserting skips. % \begin{macrocode} \cs_new_eq:NN \skip_horizontal:N \tex_hskip:D \cs_new:Npn \skip_horizontal:n #1 { \skip_horizontal:N \etex_glueexpr:D #1 \scan_stop: } \cs_new_eq:NN \skip_vertical:N \tex_vskip:D \cs_new:Npn \skip_vertical:n #1 { \skip_vertical:N \etex_glueexpr:D #1 \scan_stop: } \cs_generate_variant:Nn \skip_horizontal:N { c } \cs_generate_variant:Nn \skip_vertical:N { c } % \end{macrocode} % \end{macro} % \end{macro} % % \subsection{Viewing \texttt{skip} variables} % % \begin{macro}{\skip_show:N, \skip_show:c} % Diagnostics. % \begin{macrocode} \cs_new_eq:NN \skip_show:N \kernel_register_show:N \cs_generate_variant:Nn \skip_show:N { c } % \end{macrocode} % \end{macro} % % \begin{macro}{\skip_show:n} % Diagnostics. % \begin{macrocode} \cs_new_protected:Npn \skip_show:n #1 { \tex_showthe:D \etex_glueexpr:D #1 \scan_stop: } % \end{macrocode} % \end{macro} % % \subsection{Constant skips} % % \begin{macro}{\c_zero_skip} % \begin{macro}{\c_max_skip} % Skips with no rubber component are just dimensions % \begin{macrocode} \cs_new_eq:NN \c_zero_skip \c_zero_dim \cs_new_eq:NN \c_max_skip \c_max_dim % \end{macrocode} % \end{macro} % \end{macro} % % \subsection{Scratch skips} % % \begin{variable}{\l_tmpa_skip, \l_tmpb_skip, \l_tmpc_skip} % \begin{variable}{\g_tmpa_skip, \g_tmpb_skip} % We provide three local and two global scratch registers, maybe we % need more or less. % \begin{macrocode} \skip_new:N \l_tmpa_skip \skip_new:N \l_tmpb_skip \skip_new:N \l_tmpc_skip \skip_new:N \g_tmpa_skip \skip_new:N \g_tmpb_skip % \end{macrocode} % \end{variable} % \end{variable} % % \subsection{Creating and initialising \texttt{muskip} variables} % % \begin{macro}{\muskip_new:N, \muskip_new:c} % And then we add muskips. % \begin{macrocode} %<*package> \cs_new_protected:Npn \muskip_new:N #1 { \chk_if_free_cs:N #1 \newmuskip #1 } % \cs_generate_variant:Nn \muskip_new:N { c } % \end{macrocode} % \end{macro} % % \begin{macro}{\muskip_const:Nn, \muskip_const:cn} % Contrarily to integer constants, we cannot avoid using a register, % even for constants. % \begin{macrocode} \cs_new_protected:Npn \muskip_const:Nn #1 { \muskip_new:N #1 \muskip_gset:Nn #1 } \cs_generate_variant:Nn \muskip_const:Nn { c } % \end{macrocode} % \end{macro} % % \begin{macro}{\muskip_zero:N, \muskip_zero:c} % \begin{macro}{\muskip_gzero:N, \muskip_gzero:c} % Reset the register to zero. % \begin{macrocode} \cs_new_protected:Npn \muskip_zero:N #1 { #1 \c_zero_muskip } \cs_new_protected:Npn \muskip_gzero:N { \tex_global:D \muskip_zero:N } \cs_generate_variant:Nn \muskip_zero:N { c } \cs_generate_variant:Nn \muskip_gzero:N { c } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro} % { % \muskip_zero_new:N, \muskip_zero_new:c, % \muskip_gzero_new:N, \muskip_gzero_new:c % } % Create a register if needed, otherwise clear it. % \begin{macrocode} \cs_new_protected:Npn \muskip_zero_new:N #1 { \muskip_if_exist:NTF #1 { \muskip_zero:N #1 } { \muskip_new:N #1 } } \cs_new_protected:Npn \muskip_gzero_new:N #1 { \muskip_if_exist:NTF #1 { \muskip_gzero:N #1 } { \muskip_new:N #1 } } \cs_generate_variant:Nn \muskip_zero_new:N { c } \cs_generate_variant:Nn \muskip_gzero_new:N { c } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF]{\muskip_if_exist:N, \muskip_if_exist:c} % Copies of the \texttt{cs} functions defined in \pkg{l3basics}. % \begin{macrocode} \cs_new_eq:NN \muskip_if_exist:NTF \cs_if_exist:NTF \cs_new_eq:NN \muskip_if_exist:NT \cs_if_exist:NT \cs_new_eq:NN \muskip_if_exist:NF \cs_if_exist:NF \cs_new_eq:NN \muskip_if_exist_p:N \cs_if_exist_p:N \cs_new_eq:NN \muskip_if_exist:cTF \cs_if_exist:cTF \cs_new_eq:NN \muskip_if_exist:cT \cs_if_exist:cT \cs_new_eq:NN \muskip_if_exist:cF \cs_if_exist:cF \cs_new_eq:NN \muskip_if_exist_p:c \cs_if_exist_p:c % \end{macrocode} % \end{macro} % % \subsection{Setting \texttt{muskip} variables} % % \begin{macro}{\muskip_set:Nn, \muskip_set:cn} % \begin{macro}{\muskip_gset:Nn, \muskip_gset:cn} % This should be pretty familiar. % \begin{macrocode} \cs_new_protected:Npn \muskip_set:Nn #1#2 { #1 ~ \etex_muexpr:D #2 \scan_stop: } \cs_new_protected:Npn \muskip_gset:Nn { \tex_global:D \muskip_set:Nn } \cs_generate_variant:Nn \muskip_set:Nn { c } \cs_generate_variant:Nn \muskip_gset:Nn { c } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro} % { % \muskip_set_eq:NN, \muskip_set_eq:cN, % \muskip_set_eq:Nc, \muskip_set_eq:cc % } % \begin{macro} % { % \muskip_gset_eq:NN,\muskip_gset_eq:cN, % \muskip_gset_eq:Nc,\muskip_gset_eq:cc % } % All straightforward. % \begin{macrocode} \cs_new_protected:Npn \muskip_set_eq:NN #1#2 { #1 = #2 } \cs_generate_variant:Nn \muskip_set_eq:NN { c } \cs_generate_variant:Nn \muskip_set_eq:NN { Nc , cc } \cs_new_protected:Npn \muskip_gset_eq:NN #1#2 { \tex_global:D #1 = #2 } \cs_generate_variant:Nn \muskip_gset_eq:NN { c } \cs_generate_variant:Nn \muskip_gset_eq:NN { Nc , cc } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\muskip_add:Nn, \muskip_add:cn} % \begin{macro}{\muskip_gadd:Nn, \muskip_gadd:cn} % \begin{macro}{\muskip_sub:Nn, \muskip_sub:cn} % \begin{macro}{\muskip_gsub:Nn, \muskip_gsub:cn} % Using |by| here deals with the (incorrect) case |\muskip123|. % \begin{macrocode} \cs_new_protected:Npn \muskip_add:Nn #1#2 { \tex_advance:D #1 by \etex_muexpr:D #2 \scan_stop: } \cs_new_protected:Npn \muskip_gadd:Nn { \tex_global:D \muskip_add:Nn } \cs_generate_variant:Nn \muskip_add:Nn { c } \cs_generate_variant:Nn \muskip_gadd:Nn { c } \cs_new_protected:Npn \muskip_sub:Nn #1#2 { \tex_advance:D #1 by - \etex_muexpr:D #2 \scan_stop: } \cs_new_protected:Npn \muskip_gsub:Nn { \tex_global:D \muskip_sub:Nn } \cs_generate_variant:Nn \muskip_sub:Nn { c } \cs_generate_variant:Nn \muskip_gsub:Nn { c } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \subsection{Using \texttt{muskip} expressions and variables} % % \begin{macro}{\muskip_eval:n} % Evaluating a muskip expression expandably. % \begin{macrocode} \cs_new:Npn \muskip_eval:n #1 { \muskip_use:N \etex_muexpr:D #1 \scan_stop: } % \end{macrocode} % \end{macro} % % \begin{macro}{\muskip_use:N, \muskip_use:c} % Accessing a \meta{muskip}. % \begin{macrocode} \cs_new_eq:NN \muskip_use:N \tex_the:D \cs_generate_variant:Nn \muskip_use:N { c } % \end{macrocode} % \end{macro} % % \subsection{Viewing \texttt{muskip} variables} % % \begin{macro}{\muskip_show:N, \muskip_show:c} % Diagnostics. % \begin{macrocode} \cs_new_eq:NN \muskip_show:N \kernel_register_show:N \cs_generate_variant:Nn \muskip_show:N { c } % \end{macrocode} % \end{macro} % % \begin{macro}{\muskip_show:n} % Diagnostics. % \begin{macrocode} \cs_new_protected:Npn \muskip_show:n #1 { \tex_showthe:D \etex_muexpr:D #1 \scan_stop: } % \end{macrocode} % \end{macro} % % \subsection{Experimental skip functions} % % \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} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \PrintIndex