% \iffalse %% File: l3skip.dtx Copyright (C) 2005-2010 Frank Mittelbach, 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 ``expl3 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{l3names} % %\fi \GetIdInfo$Id: l3skip.dtx 2047 2010-09-23 09:27:30Z will $ {L3 Experimental skip registers} %\iffalse %<*driver> %\fi \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse \documentclass[full]{l3doc} \begin{document} \DocInput{l3skip.dtx} \end{document} % % \fi % % % \title{The \textsf{l3skip} package\thanks{This file % has version number \fileversion, last % revised \filedate.}\\ % Dimension and skip registers} % \author{\Team} % \date{\filedate} % \maketitle % % \begin{documentation} % % \LaTeX3 knows about two types of length registers for internal use: % rubber lengths ("skip"s) and rigid lengths ("dim"s). % % \section{Skip registers} % % % % \subsection{Functions} % % \begin{function}{ \skip_new:N | % \skip_new:c } % \begin{syntax} % "\skip_new:N" % \end{syntax} % Defines to be a new variable of type "skip". % \begin{texnote} % "\skip_new:N" is the equivalent to plain \TeX{}'s \tn{newskip}. % \end{texnote} % \end{function} % % \begin{function}{% % \skip_zero:N | % \skip_zero:c | % \skip_gzero:N | % \skip_gzero:c | % } % \begin{syntax} % "\skip_zero:N" % \end{syntax} % Locally or globally reset to zero. % For global variables the global versions % should be used. % \end{function} % % % \begin{function}{% % \skip_set:Nn | % \skip_set:cn | % \skip_gset:Nn | % \skip_gset:cn | % } % \begin{syntax} % "\skip_set:Nn" \Arg{skip value} % \end{syntax} % These functions will set the register to the value. % \end{function} % % % \begin{function}{% % \skip_add:Nn | % \skip_add:cn | % \skip_gadd:Nn | % \skip_gadd:cn | % } % \begin{syntax} % "\skip_add:Nn" \Arg{length} % \end{syntax} % These functions will add to the register the value . If % the second argument is a register too, the surrounding braces % can be left out. % \end{function} % % \begin{function}{% % \skip_sub:Nn | % \skip_gsub:Nn | % } % \begin{syntax} % "\skip_gsub:Nn" \Arg{length} % \end{syntax} % These functions will subtract from the register the value % . If the second argument is a register too, the % surrounding braces can be left out. % \end{function} % % \begin{function}{% % \skip_use:N | % \skip_use:c | % } % \begin{syntax} % "\skip_use:N" % \end{syntax} % This function returns the length value kept in in a way % suitable for further processing. % \begin{texnote} % The function "\skip_use:N" could be implemented directly as the \TeX{} % primitive "\tex_the:D" which is also responsible to produce the values for % other internal quantities. We have chosen to use individual functions % for counters, dimensions etc.\ to allow checks and to make the code % more self-explanatory. % \end{texnote} % \end{function} % % \begin{function}{ \skip_show:N | % \skip_show:c } % \begin{syntax} % "\skip_show:N" % \end{syntax} % This function pauses the compilation and displays the length value kept % in in the console output and log file. % \begin{texnote} % The function "\skip_show:N" could be implemented directly as the \TeX{} % primitive "\tex_showthe:D" which is also responsible to produce the values for % other internal quantities. We have chosen to use individual functions % for counters, dimensions etc.\ to allow checks and to make the code % more self-explanatory. % \end{texnote} % \end{function} % % \begin{function}{% % \skip_horizontal:N | % \skip_horizontal:c | % \skip_horizontal:n | % \skip_vertical:N | % \skip_vertical:c | % \skip_vertical:n | % } % \begin{syntax} % "\skip_horizontal:N" \\ % "\skip_horizontal:n" \Arg{length} % \end{syntax} % The "hor" functions insert or with the \TeX\ % primitive \tn{hskip}. The "vertical" variants do the same with % \tn{vskip}. The "n" versions evaluate with "\skip_eval:n". % \end{function} % % % \begin{function}{ \skip_if_infinite_glue_p:n | % \skip_if_infinite_glue:n / (TF) } % \begin{syntax} % "\skip_if_infinite_glue:nTF" \Arg{skip} \Arg{true} \Arg{false} % \end{syntax} % Checks if contains infinite stretch or shrink components % and executes either or . Also works on input like % "3pt plus .5in". % \end{function} % % % % \begin{function}{% % \skip_split_finite_else_action:nnNN | % } % \begin{syntax} % "\skip_split_finite_else_action:nnNN" \Arg{skip} \Arg{action} % % \end{syntax} % Checks if contains finite glue. If it does then it assigns % the stretch component and the shrink component. If % it contains infinite glue set and to zero and execute % "#2" which is usually an error or warning message of some sort. % \end{function} % % % % \begin{function}{% % \skip_eval:n / (EXP) | % } % \begin{syntax} % "\skip_eval:n" \Arg{skip expr} % \end{syntax} % Evaluates the value of so that % "\skip_eval:n {5pt plus 3fil + 3pt minus 1fil}" puts % "8.0pt plus 3.0fil minus 1.0fil" back into the input stream. % Expandable. % \begin{texnote} % This is the \eTeX{} primitive \tn{glueexpr} turned into a function % taking an argument. % \end{texnote} % \end{function} % % % \subsection{Formatting a skip register value} % % % \subsection{Variable and constants} % % \begin{variable}{% % \c_max_skip | % } % Constant that denotes the maximum value which can be stored in a % register. % \end{variable} % % \begin{variable}{% % \c_zero_skip | % } % Constants denoting a zero skip. % \end{variable} % % \begin{variable}{% % \l_tmpa_skip | % \l_tmpb_skip | % \l_tmpc_skip | % \g_tmpa_skip | % \g_tmpb_skip | % } % Scratch register for immediate use. % \end{variable} % % % % % % \section{Dim registers} % % % \subsection{Functions} % % % % % \begin{function}{ \dim_new:N | % \dim_new:c } % \begin{syntax} % "\dim_new:N" % \end{syntax} % Defines to be a new variable of type "dim". % \begin{texnote} % "\dim_new:N" is the equivalent to plain \TeX{}'s \tn{newdimen}. % \end{texnote} % \end{function} % % \begin{function}{% % \dim_zero:N | % \dim_zero:c | % \dim_gzero:N | % \dim_gzero:c | % } % \begin{syntax} % "\dim_zero:N" % \end{syntax} % Locally or globally reset to zero. % For global variables the global versions % should be used. % \end{function} % % % \begin{function}{% % \dim_set:Nn | % \dim_set:Nc | % \dim_set:cn | % \dim_gset:Nn | % \dim_gset:Nc | % \dim_gset:cn | % \dim_gset:cc | % } % \begin{syntax} % "\dim_set:Nn" \Arg{dim value} % \end{syntax} % These functions will set the register to the value. % \end{function} % % % \begin{function}{% % \dim_add:Nn | % \dim_add:Nc | % \dim_add:cn | % \dim_gadd:Nn | % \dim_gadd:cn | % } % \begin{syntax} % "\dim_add:Nn" \Arg{length} % \end{syntax} % These functions will add to the register the value . If % the second argument is a register too, the surrounding braces % can be left out. % \end{function} % % \begin{function}{% % \dim_sub:Nn | % \dim_sub:Nc | % \dim_sub:cn | % \dim_gsub:Nn | % \dim_gsub:cn | % } % \begin{syntax} % "\dim_gsub:Nn" \Arg{length} % \end{syntax} % These functions will subtract from the register the value % . If the second argument is a register too, the % surrounding braces can be left out. % \end{function} % % \begin{function}{% % \dim_use:N | % \dim_use:c | % } % \begin{syntax} % "\dim_use:N" % \end{syntax} % This function returns the length value kept in in a way % suitable for further processing. % \begin{texnote} % The function "\dim_use:N" could be implemented directly as the \TeX{} % primitive "\tex_the:D" which is also responsible to produce the values for % other internal quantities. We have chosen to use individual functions % for counters, dimensions etc.\ to allow checks and to make the code % more self-explanatory. % \end{texnote} % \end{function} % % \begin{function}{ \dim_show:N | % \dim_show:c } % \begin{syntax} % "\dim_show:N" % \end{syntax} % This function pauses the compilation and displays the length value kept % in in the console output and log file. % \begin{texnote} % The function "\dim_show:N" could be implemented directly as the \TeX{} % primitive "\tex_showthe:D" which is also responsible to produce the values for % other internal quantities. We have chosen to use individual functions % for counters, dimensions etc.\ to allow checks and to make the code % more self-explanatory. % \end{texnote} % \end{function} % % % \begin{function}{% % \dim_eval:n | % } % \begin{syntax} % "\dim_eval:n" \Arg{dim expr} % \end{syntax} % Evaluates the value of a dimension expression so that % "\dim_eval:n {5pt+3pt}" puts "8pt" back into the input stream. % Expandable. % \begin{texnote} % This is the \eTeX{} primitive \tn{dimexpr} turned into a function % taking an argument. % \end{texnote} % \end{function} % % \begin{function}{% % \if_dim:w | % } % \begin{syntax} % "\if_dim:w" "\else:" "\fi:" % \end{syntax} % Compare two dimensions. It is recommended to use "\dim_eval:n" to % correctly evaluate and terminate these numbers. is one of % "<", "=" or ">" with catcode 12. % \begin{texnote} % This is the \TeX{} primitive \tn{ifdim}. % \end{texnote} % \end{function} % %\begin{function}{ % \dim_compare_p:n / (EXP) | % \dim_compare:n / (TF) (EXP) %} % \begin{syntax} % "\dim_compare_p:n" \Arg{ } % "\dim_compare:nTF" \Arg{ } % ~~~~ % \end{syntax} % Evaluates and and then carries out a % comparison of the resulting lengths using C-like operators: % \begin{center} % \begin{tabular}{ll@{\hspace{2cm}}ll} % Less than & "<" & Less than or equal & "<=" \\ % Greater than & ">" & Greater than or equal & ">=" \\ % Equal & "==" or "=" & Not equal & "!=" % \end{tabular} % \end{center} % Based on the result of the comparison either the % or is executed. Both dimension expressions are evaluated % fully in the process. Note the syntax, which allows natural input in % the style of % \begin{quote} % |\dim_compare_p:n {2.54cm != \l_tmpb_int}| % \end{quote} % A single equals sign is available as comparator (in addition to those % familiar to C users) as standard \TeX\ practice is to compare % values using \texttt{=}. % \end{function} % % \begin{function}{ \dim_compare:nNn / (TF)(EXP) | \dim_compare_p:nNn / (EXP)} % \begin{syntax} % "\dim_compare:nNnTF" \Arg{dim~expr} \Arg{dim~expr} % \Arg{true} \Arg{false} % \end{syntax} % These functions test two dimension expressions against each other. They % are both evaluated by "\dim_eval:n". Note that if both expressions % are normal dimension variables as in % \begin{verbatim} % \dim_compare:nNnTF \l_temp_dim < \c_zero_skip {negative}{non-negative} % \end{verbatim} % you can safely omit the braces. % % These functions are faster than the \texttt{n} % variants described above but do not support an extended set % of relational operators. % \begin{texnote} % This is the \TeX{} primitive \tn{ifdim} turned into a function. % \end{texnote} % \end{function} % % % \begin{function}{% % \dim_while_do:nNnn | % \dim_until_do:nNnn | % \dim_do_while:nNnn | % \dim_do_until:nNnn | % } % \begin{syntax} % "\dim_while_do:nNnn" % \end{syntax} % "\dim_while_do:nNnn" tests the dimension expressions and if true performs % repeatedly while the test remains true. "\dim_do_while:nNnn" is similar % but executes the body first and then performs the check, thus % ensuring that the body is executed at least once. The `until' versions % are similar but continue the loop as long as the test is false. % \end{function} % % % % \subsection{Variable and constants} % % \begin{variable}{% % \c_max_dim | % } % Constant that denotes the maximum value which can be stored in a % register. % \end{variable} % % \begin{variable}{% % \c_zero_dim | % } % Set of constants denoting useful values. % \end{variable} % % \begin{variable}{% % \l_tmpa_dim | % \l_tmpb_dim | % \l_tmpc_dim | % \l_tmpd_dim | % \g_tmpa_dim | % \g_tmpb_dim | % } % Scratch register for immediate use. % \end{variable} % % \section{Muskips} % % \begin{function}{ \muskip_new:N } % \begin{syntax} % "\muskip_new:N" % \end{syntax} % \begin{texnote} % Defines to be a new variable of type "muskip". % "\muskip_new:N" is the equivalent to plain \TeX{}'s \tn{newmuskip}. % \end{texnote} % \end{function} % % \begin{function}{% % \muskip_set:Nn | % \muskip_gset:Nn | % } % \begin{syntax} % "\muskip_set:Nn" \Arg{muskip value} % \end{syntax} % These functions will set the register to the % value. % \end{function} % % % \begin{function}{% % \muskip_add:Nn | % \muskip_gadd:Nn | % } % \begin{syntax} % "\muskip_add:Nn" \Arg{length} % \end{syntax} % These functions will add to the register the value % . If the second argument is a register too, the % surrounding braces can be left out. % \end{function} % % \begin{function}{% % \muskip_sub:Nn | % \muskip_gsub:Nn | % } % \begin{syntax} % "\muskip_gsub:Nn" \Arg{length} % \end{syntax} % These functions will subtract from the register the value % . If the second argument is a register too, the % surrounding braces can be left out. % \end{function} % % \begin{function}{ \muskip_use:N } % \begin{syntax} % "\muskip_use:N" % \end{syntax} % This function returns the length value kept in in a way % suitable for further processing. % \begin{texnote} % See note for "\dim_use:N". % \end{texnote} % \end{function} % % \begin{function}{ \muskip_show:N } % \begin{syntax} % "\muskip_show:N" % \end{syntax} % This function pauses the compilation and displays the length value kept % in in the console output and log file. % \end{function} % % \end{documentation} % % \begin{implementation} % % \section{\pkg{l3skip} implementation} % % % We start by ensuring that the required packages are loaded. % \begin{macrocode} %<*package> \ProvidesExplPackage {\filename}{\filedate}{\fileversion}{\filedescription} \package_check_loaded_expl: % %<*initex|package> % \end{macrocode} % % \subsection{Skip registers} % % \begin{macro}{\skip_new:N,\skip_new:c} % Allocation of a new internal registers. % \begin{macrocode} %<*initex> \alloc_new:nnnN {skip} \c_zero \c_max_register_int \tex_skipdef:D % %<*package> \cs_new_protected_nopar: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_set:Nn} % \begin{macro}{\skip_set:cn} % \begin{macro}{\skip_gset:Nn} % \begin{macro}{\skip_gset:cn} % Setting skips is again something that I would like to make % uniform at the moment to get a better overview. % \begin{macrocode} \cs_new_protected_nopar:Npn \skip_set:Nn #1#2 { #1\skip_eval:n{#2} %<*check> \chk_local_or_pref_global:N #1 % } \cs_new_protected_nopar:Npn \skip_gset:Nn { %<*check> \pref_global_chk: % %<-check> \pref_global:D \skip_set:Nn } \cs_generate_variant:Nn \skip_set:Nn {cn} \cs_generate_variant:Nn \skip_gset:Nn {cn} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\skip_zero:N} % \begin{macro}{\skip_gzero:N} % \begin{macro}{\skip_zero:c} % \begin{macro}{\skip_gzero:c} % Reset the register to zero. % \begin{macrocode} \cs_new_protected_nopar:Npn \skip_zero:N #1{ #1\c_zero_skip \scan_stop: %<*check> \chk_local_or_pref_global:N #1 % } \cs_new_protected_nopar:Npn \skip_gzero:N { % \end{macrocode} % We make sure that a local variable is not updated globally by % changing the internal test (i.e.\ |\chk_local_or_pref_global:N|) before % making the assignment. This is done by |\pref_global_chk:| which also % issues the necessary |\pref_global:D|. This is not very efficient, but % this code will be only included for debugging purposes. Using % |\pref_global:D| in front of the local function is better in the % production versions. % \begin{macrocode} %<*check> \pref_global_chk: % %<-check> \pref_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} % \end{macro} % \end{macro} % % % \begin{macro}{\skip_add:Nn} % \begin{macro}{\skip_add:cn} % \begin{macro}{\skip_gadd:Nn} % \begin{macro}{\skip_gadd:cn} % \begin{macro}{\skip_sub:Nn} % \begin{macro}{\skip_gsub:Nn} % Adding and subtracting to and from s % \begin{macrocode} \cs_new_protected_nopar:Npn \skip_add:Nn #1#2 { % \end{macrocode} % We need to say |by| in case the first argment is a register % accessed by its number, e.g., |\skip23|. % \begin{macrocode} \tex_advance:D#1 by \skip_eval:n{#2} %<*check> \chk_local_or_pref_global:N #1 % } \cs_generate_variant:Nn \skip_add:Nn {cn} % \end{macrocode} % % \begin{macrocode} \cs_new_protected_nopar:Npn \skip_sub:Nn #1#2{ \tex_advance:D#1-\skip_eval:n{#2} %<*check> \chk_local_or_pref_global:N #1 % } % \end{macrocode} % % \begin{macrocode} \cs_new_protected_nopar:Npn \skip_gadd:Nn { %<*check> \pref_global_chk: % %<-check> \pref_global:D \skip_add:Nn } \cs_generate_variant:Nn \skip_gadd:Nn {cn} % \end{macrocode} % % \begin{macrocode} \cs_new_nopar:Npn \skip_gsub:Nn { %<*check> \pref_global_chk: % %<-check> \pref_global:D \skip_sub:Nn } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\skip_horizontal:N} % \begin{macro}{\skip_horizontal:c} % \begin{macro}{\skip_horizontal:n} % \begin{macro}{\skip_vertical:N} % \begin{macro}{\skip_vertical:c} % \begin{macro}{\skip_vertical:n} % Inserting skips. % \begin{macrocode} \cs_new_eq:NN \skip_horizontal:N \tex_hskip:D \cs_generate_variant:Nn \skip_horizontal:N {c} % \end{macrocode} % % \begin{macrocode} \cs_new_nopar:Npn \skip_horizontal:n #1 { \skip_horizontal:N \skip_eval:n{#1} } \cs_new_eq:NN \skip_vertical:N \tex_vskip:D \cs_generate_variant:Nn \skip_vertical:N {c} \cs_new_nopar:Npn \skip_vertical:n #1 { \skip_vertical:N \skip_eval:n{#1} } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\skip_use:N} % \begin{macro}{\skip_use:c} % Here is how skip registers are accessed: % \begin{macrocode} \cs_new_eq:NN \skip_use:N \tex_the:D \cs_generate_variant:Nn \skip_use:N {c} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\skip_show:N} % \begin{macro}{\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} % \end{macro} % % \begin{macro}{\skip_eval:n} % Evaluating a calc expression. % \begin{macrocode} \cs_new_protected_nopar:Npn \skip_eval:n #1 { \etex_glueexpr:D #1 \scan_stop: } % \end{macrocode} % \end{macro} % % \begin{macro}{\l_tmpa_skip} % \begin{macro}{\l_tmpb_skip} % \begin{macro}{\l_tmpc_skip} % \begin{macro}{\g_tmpa_skip} % \begin{macro}{\g_tmpb_skip} % We provide three local and two global scratch registers, maybe we % need more or less. % \begin{macrocode} %%\chk_if_free_cs:N \l_tmpa_skip %%\tex_skipdef:D\l_tmpa_skip 255 %currently taken up by \skip@ \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{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\c_zero_skip} % \begin{macro}{\c_max_skip} % \begin{macrocode} %<*!package> \skip_new:N \c_zero_skip \skip_set:Nn \c_zero_skip {0pt} \skip_new:N \c_max_skip \skip_set:Nn \c_max_skip {16383.99999pt} % %<*!initex> \cs_set_eq:NN \c_zero_skip \z@ \cs_set_eq:NN \c_max_skip \maxdimen % % \end{macrocode} % \end{macro} % \end{macro} % % % % \begin{macro}{\skip_if_infinite_glue_p:n} % \begin{macro}[TF]{\skip_if_infinite_glue:n} % With \eTeX{} we all of a sudden get access to a lot information we % should otherwise consider ourselves lucky to get. One is % the stretch and shrink components of a skip register and the order % or those components. "\skip_if_infinite_glue:nTF" tests it directly by % looking at the stretch and shrink order. If either of the predicate % functions return \m{true} "\bool_if:nTF" will return \m{true} % and the logic test will take the true branch. % \begin{macrocode} \prg_new_conditional:Nnn \skip_if_infinite_glue:n {p,TF,T,F} { \bool_if:nTF { \intexpr_compare_p:nNn {\etex_gluestretchorder:D #1 } > \c_zero || \intexpr_compare_p:nNn {\etex_glueshrinkorder:D #1 } > \c_zero } {\prg_return_true:} {\prg_return_false:} } % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\skip_split_finite_else_action:nnNN} % This macro is useful when performing error checking in certain % circumstances. If the \m{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 global. % \begin{macrocode} \cs_new_nopar:Npn \skip_split_finite_else_action:nnNN #1#2#3#4{ \skip_if_infinite_glue:nTF {#1} { #3 = \c_zero_skip #4 = \c_zero_skip #2 } { #3 = \etex_gluestretch:D #1 \scan_stop: #4 = \etex_glueshrink:D #1 \scan_stop: } } % \end{macrocode} % \end{macro} % % % % \subsection{Dimen registers} % % \begin{macro}{\dim_new:N,\dim_new:c} % Allocating \meta{dim} registers... % \begin{macrocode} %<*initex> \alloc_new:nnnN {dim} \c_zero \c_max_register_int \tex_dimendef:D % %<*package> \cs_new_protected_nopar: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_set:Nn} % \begin{macro}{\dim_set:cn} % \begin{macro}{\dim_set:Nc} % \begin{macro}{\dim_gset:Nn} % \begin{macro}{\dim_gset:cn} % \begin{macro}{\dim_gset:Nc} % \begin{macro}{\dim_gset:cc} % We add |\dim_eval:n| in order to allow simple arithmetic % and a space just for those using |\dimen1| or alike. See OR! % \begin{macrocode} \cs_new_protected_nopar:Npn \dim_set:Nn #1#2 { #1~ \dim_eval:n{#2} } \cs_generate_variant:Nn \dim_set:Nn {cn,Nc} % \end{macrocode} % % \begin{macrocode} \cs_new_protected_nopar:Npn \dim_gset:Nn { \pref_global:D \dim_set:Nn } \cs_generate_variant:Nn \dim_gset:Nn {cn,Nc,cc} % \end{macrocode} % \end{macro}\end{macro}\end{macro}\end{macro} % \end{macro}\end{macro}\end{macro} % % \begin{macro}{\dim_zero:N} % \begin{macro}{\dim_gzero:N} % \begin{macro}{\dim_zero:c} % \begin{macro}{\dim_gzero:c} % Resetting. % \begin{macrocode} \cs_new_protected_nopar:Npn \dim_zero:N #1 { #1\c_zero_skip } \cs_generate_variant:Nn \dim_zero:N {c} % \end{macrocode} % % \begin{macrocode} \cs_new_protected_nopar:Npn \dim_gzero:N { \pref_global:D \dim_zero:N } \cs_generate_variant:Nn \dim_gzero:N {c} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\dim_add:Nn} % \begin{macro}{\dim_add:cn} % \begin{macro}{\dim_add:Nc} % \begin{macro}{\dim_gadd:Nn} % \begin{macro}{\dim_gadd:cn} % Addition. % \begin{macrocode} \cs_new_protected_nopar:Npn \dim_add:Nn #1#2{ % \end{macrocode} % We need to say |by| in case the first argment is a register % accessed by its number, e.g., |\dimen23|. % \begin{macrocode} \tex_advance:D#1 by \dim_eval:n{#2}\scan_stop: } \cs_generate_variant:Nn \dim_add:Nn {cn,Nc} % \end{macrocode} % % \begin{macrocode} \cs_new_protected_nopar:Npn \dim_gadd:Nn { \pref_global:D \dim_add:Nn } \cs_generate_variant:Nn \dim_gadd:Nn {cn} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\dim_sub:Nn} % \begin{macro}{\dim_sub:cn} % \begin{macro}{\dim_sub:Nc} % \begin{macro}{\dim_gsub:Nn} % \begin{macro}{\dim_gsub:cn} % Subtracting. % \begin{macrocode} \cs_new_protected_nopar:Npn \dim_sub:Nn #1#2 { \tex_advance:D#1-#2\scan_stop: } \cs_generate_variant:Nn \dim_sub:Nn {cn,Nc} % \end{macrocode} % % \begin{macrocode} \cs_new_protected_nopar:Npn \dim_gsub:Nn { \pref_global:D \dim_sub:Nn } \cs_generate_variant:Nn \dim_gsub:Nn {cn} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\dim_use:N} % \begin{macro}{\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} % \end{macro} % % \begin{macro}{\dim_show:N} % \begin{macro}{\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} % \end{macro} % % \begin{macro}{\l_tmpa_dim} % \begin{macro}{\l_tmpb_dim} % \begin{macro}{\l_tmpc_dim} % \begin{macro}{\l_tmpd_dim} % \begin{macro}{\g_tmpa_dim} % \begin{macro}{\g_tmpb_dim} % Some scratch registers. % \begin{macrocode} \dim_new:N \l_tmpa_dim \dim_new:N \l_tmpb_dim \dim_new:N \l_tmpc_dim \dim_new:N \l_tmpd_dim \dim_new:N \g_tmpa_dim \dim_new:N \g_tmpb_dim % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\c_zero_dim} % \begin{macro}{\c_max_dim} % Just aliases. % \begin{macrocode} \cs_new_eq:NN \c_zero_dim \c_zero_skip \cs_new_eq:NN \c_max_dim \c_max_skip % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\dim_eval:n} % Evaluating a calc expression. % \begin{macrocode} \cs_new_protected_nopar:Npn \dim_eval:n #1 { \etex_dimexpr:D #1 \scan_stop: } % \end{macrocode} % \end{macro} % % \begin{macro}{\if_dim:w} % The comparison primitive. % \begin{macrocode} \cs_new_eq:NN \if_dim:w \tex_ifdim:D % \end{macrocode} % \end{macro} % % % \begin{macro}{\dim_compare_p:nNn} % \begin{macro}[TF]{\dim_compare:nNn} % \begin{macrocode} \prg_new_conditional:Nnn \dim_compare:nNn {p,TF,T,F} { \if_dim:w \dim_eval:n {#1} #2 \dim_eval:n {#3} \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\dim_compare_p:n} % \begin{macro}[TF]{\dim_compare:n} % [This code plus comments lifted directly from the |\intexpr_compare:nTF| function.] % Some things we need for the code below. % TODO: normalise names and things. % \begin{macrocode} \cs_set_eq:NN \dim_value:w \tex_number:D \cs_set_eq:NN \dim_eval:w \etex_dimexpr:D \cs_set_eq:NN \if_dim_compare:w \if_dim:w \cs_set_eq:NN \dim_eval_end: \scan_stop: % \end{macrocode} % Comparison tests using a simple syntax where only one set of braces % is required and additional operators such as "!=" and ">=" are % supported. First some notes on the idea behind this. We wish to % support writing code like % \begin{verbatim} % \dim_compare_p:n { 5 + \l_tmpa_dim != 4 - \l_tmpb_dim } % \end{verbatim} % In other words, we want to somehow add the missing "\dim_eval:w" % where required. We can start evaluating from the left using % "\dim:w", and we know that since the relation symbols "<", ">", % "=" and "!" are not allowed in such expressions, they will terminate % the expression. Therefore, we first let \TeX\ evaluate this left % hand side of the (in)equality. % \begin{macrocode} \prg_new_conditional:Npnn \dim_compare:n #1 {p,TF,T,F} { \exp_after:wN \dim_compare_auxi:w \dim_value:w \dim_eval:w #1 \q_stop } % \end{macrocode} % Then the next step is to figure out which relation we should use, so % we have to somehow get rid of the first evaluation so that we can % see what stopped it. "\tex_romannumeral:D" is handy here since its % expansion given a non-positive number is \m{null}. We therefore % simply check if the first token of the left hand side evaluation is % a minus. If not, we insert it and issue "\tex_romannumeral:D", % thereby ridding us of the left hand side evaluation. We do however % save it for later. % \begin{macrocode} \cs_new:Npn \dim_compare_auxi:w #1#2 \q_stop { \exp_after:wN \dim_compare_auxii:w \tex_romannumeral:D \if:w #1- \else: -\fi: #1#2 \q_mark #1#2 \q_stop } % \end{macrocode} % This leaves the first relation symbol in front and assuming the % right hand side has been input, at least one other token as well. We % support the following forms: |=|, |<|, |>| and the extended |!=|, % |==|, |<=| and |>=|. All the extended forms have an extra |=| so we % check if that is present as well. Then use specific function to % perform the test. % \begin{macrocode} \cs_new:Npn \dim_compare_auxii:w #1#2#3\q_mark{ \use:c{ dim_compare_ #1 \if_meaning:w =#2 = \fi: :w} } % \end{macrocode} % The actual comparisons are then simple function calls, using the % relation as delimiter for a delimited argument. % Equality is easy: % \begin{macrocode} \cs_new:cpn {dim_compare_=:w} #1 = #2 \q_stop { \if_dim_compare:w #1 sp = \dim_eval:w #2 \dim_eval_end: \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % So is the one using |==| -- we just have to use |==| in the % parameter text. % \begin{macrocode} \cs_new:cpn {dim_compare_==:w} #1 == #2 \q_stop { \if_dim_compare:w #1 sp = \dim_eval:w #2 \dim_eval_end: \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % Not equal is just about reversing the truth value. % \begin{macrocode} \cs_new:cpn {dim_compare_!=:w} #1 != #2 \q_stop { \if_dim_compare:w #1 sp = \dim_eval:w #2 \dim_eval_end: \prg_return_false: \else: \prg_return_true: \fi: } % \end{macrocode} % Less than and greater than are also straight forward. % \begin{macrocode} \cs_new:cpn {dim_compare_<:w} #1 < #2 \q_stop { \if_dim_compare:w #1 sp < \dim_eval:w #2 \dim_eval_end: \prg_return_true: \else: \prg_return_false: \fi: } \cs_new:cpn {dim_compare_>:w} #1 > #2 \q_stop { \if_dim_compare:w #1 sp > \dim_eval:w #2 \dim_eval_end: \prg_return_true: \else: \prg_return_false: \fi: } % \end{macrocode} % The less than or equal operation is just the opposite of the greater % than operation. Vice versa for less than or equal. % \begin{macrocode} \cs_new:cpn {dim_compare_<=:w} #1 <= #2 \q_stop { \if_dim_compare:w #1 sp > \dim_eval:w #2 \dim_eval_end: \prg_return_false: \else: \prg_return_true: \fi: } \cs_new:cpn {dim_compare_>=:w} #1 >= #2 \q_stop { \if_dim_compare:w #1 sp < \dim_eval:w #2 \dim_eval_end: \prg_return_false: \else: \prg_return_true: \fi: } % \end{macrocode} % \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_new_nopar: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_new_nopar: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_new_nopar: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_new_nopar: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{Muskips} % % \begin{macro}{\muskip_new:N} % And then we add muskips. % \begin{macrocode} %<*initex> \alloc_new:nnnN {muskip} \c_zero \c_max_register_int \tex_muskipdef:D % %<*package> \cs_new_protected_nopar:Npn \muskip_new:N #1 { \chk_if_free_cs:N #1 \newmuskip #1 } % % \end{macrocode} % \end{macro} % % \begin{macro}{\muskip_set:Nn} % \begin{macro}{\muskip_gset:Nn} % \begin{macro}{\muskip_add:Nn} % \begin{macro}{\muskip_gadd:Nn} % \begin{macro}{\muskip_sub:Nn} % \begin{macro}{\muskip_gsub:Nn} % Simple functions for muskips. % \begin{macrocode} \cs_new_protected_nopar:Npn \muskip_set:Nn#1#2{#1\etex_muexpr:D#2\scan_stop:} \cs_new_protected_nopar:Npn \muskip_gset:Nn{\pref_global:D\muskip_set:Nn} \cs_new_protected_nopar:Npn \muskip_add:Nn#1#2{\tex_advance:D#1\etex_muexpr:D#2\scan_stop:} \cs_new_protected_nopar:Npn \muskip_gadd:Nn{\pref_global:D\muskip_add:Nn} \cs_new_protected_nopar:Npn \muskip_sub:Nn#1#2{\tex_advance:D#1-\etex_muexpr:D#2\scan_stop:} \cs_new_protected_nopar:Npn \muskip_gsub:Nn{\pref_global:D\muskip_sub:Nn} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\muskip_use:N} % Accessing a \meta{muskip}. % \begin{macrocode} \cs_new_eq:NN \muskip_use:N \tex_the:D % \end{macrocode} % \end{macro} % % % \begin{macro}{\muskip_show:N} % \begin{macrocode} \cs_new_eq:NN \muskip_show:N \kernel_register_show:N % \end{macrocode} % \end{macro} % % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % \PrintIndex % % \endinput