summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/multicolrule/multicolrule.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/multicolrule/multicolrule.dtx')
-rw-r--r--macros/latex/contrib/multicolrule/multicolrule.dtx489
1 files changed, 328 insertions, 161 deletions
diff --git a/macros/latex/contrib/multicolrule/multicolrule.dtx b/macros/latex/contrib/multicolrule/multicolrule.dtx
index 85de910089..ac6d017a18 100644
--- a/macros/latex/contrib/multicolrule/multicolrule.dtx
+++ b/macros/latex/contrib/multicolrule/multicolrule.dtx
@@ -147,12 +147,13 @@ and the derived files multicolrule.ins,
% \cs_new_nopar:Npn,\cs_set:Npn,
% \c_one_int,\c_zero_dim,\c_zero_int,
% \dim_compare_p:nNn,\dim_new:N,\dim_set:Nn,
-% \dim_compare:nNnTF,\dim_eval:n,\dimen,
-% \end,\ExplSyntaxOff,\ExplSyntaxOn,\fill,\hbox:n,\hspace,\ht,
-% \int_compare_nNnTF,\int_compare_p:nNn,
+% \dim_compare:nNnTF,\dim_eval:n,\dim_max:nn,\dimen,
+% \end,\ExplSyntaxOff,\ExplSyntaxOn,\exp_stop_f:,
+% \fill,\fp_to_dim:n,\hbox:n,\hspace,\ht,
+% \int_compare:nNnTF,\int_compare:nNnT,\int_compare_p:nNn,
% \int_gdecr:N,\int_gincr:N,\int_gset:Nn,\int_gzero:N,
% \int_new:N,\int_set:Nn,\kern,\keys_define:nn,
-% \keys_set:nn,\keys_set_finter:nnn,
+% \keys_set:nn,\keys_set_filter:nnV,
% \msg_error:nnn,\msg_info:nnn,\msg_new:nnn,\msg_new:nnnn,\msg_warning:nn,
% \NewDocumentCommand,\node,\prg_replicate:nn,\ProcessKeysOptions,
% \prop_get:NnNTF,\prop_gput:Nnn,\prop_item:Nn,\prop_new:N,
@@ -179,6 +180,7 @@ and the derived files multicolrule.ins,
% \changes{v1.1}{2018/12/21}{Allow extended rules}
% \changes{v1.2}{2019/1/1}{Define rule patterns}
% \changes{v1.2}{2019/1/1}{Allow per-column rule changes}
+% \changes{v1.2a}{2019/2/12}{Improve documentation}
%
%\begin{abstract}
% The \mcrule{} package lets you customize the appearance of the vertical rule
@@ -210,7 +212,7 @@ and the derived files multicolrule.ins,
% Of course it's a legitimate question why anyone should \emph{want} to change
% this rule, or indeed use one at all, as good typography tends to avoid using
% large vertical lines.\footnote{See, for example, the remarks in the
-% documentation for the \pkg{booktabs} package} In my own case, I needed to
+% documentation for the \pkg{booktabs} package.} In my own case, I needed to
% modify the rule because of the requirements of a particular style I was
% imitating, and having done the hard work of creating the necessary
% infrastructure for one line style, it was simple to extend the solution to a
@@ -225,9 +227,16 @@ and the derived files multicolrule.ins,
% \begin{multicols}{2}
% \SetMCRule{custom-line={\path (TOP) to [ornament=85] (BOT);},extend-top=-24pt,
% extend-bot=-8pt}
-% \subsection*{New for Version 1.2}
+% \subsection*{New for Version 1.3}
% Version\stydsc{custom-line=\\\{\textbackslash path (TOP) to [ornament=85]
-% (BOT);\}, extend-top=-24pt, extend-bot=-8pt} 1.2 adds the ability to define
+% (BOT);\}, extend-top=-24pt, extend-bot=-8pt} 1.3 adds a strut rule. This
+% places an invisible rule (a strut) that obeys the other options for the rule.
+% Using a strut allows you to achieve effects such as selectively disabling one
+% separator within a pattern or using the extend and reserve options to control
+% the spacing to the text outside the \env{multicols} environment.
+%
+% \subsection*{New for Version 1.2}
+% Version 1.2 adds the ability to define
% patterns, which are aliases for a series of \cs{SetMCRule} settings. With
% patterns, you can change individual separators on the same page. For example,
% in three-column text, the left separator can differ from the right.
@@ -272,7 +281,7 @@ and the derived files multicolrule.ins,
% whether this is the case. If you would like support for one of these, please
% send me an email or file a feature request on github and I'll see what I can
% do.
-%
+%
% The line styles that work by repeating elements in a tiled pattern may have
% significant gaps at the end of columns, particularly for larger patterns.
% You can mitigate this problem slightly by tweaking the spaces above and
@@ -284,11 +293,10 @@ and the derived files multicolrule.ins,
% Extending rules beyond their natural column lengths can seriously mess up
% the output, including, in certain edge cases, causing \pkg{multicol} to
% overprint columns or even put them in the margins. The fact that the extended
-% rule occupies space on the page instead of extending up into the margin was a
-% deliberate design decision and is necessary to support the
-% \kvdesc{extend-fill} and \kvdesc{extend-reserve} options work correctly. A
-% future version may support drawing the rules to a background layer so that
-% the text is not shifted.
+% rule affects the vertical layout was a deliberate design decision and is
+% necessary to support the \kvdesc{extend-fill} and \kvdesc{extend-reserve}
+% options. A future version may support drawing the rules to a background layer
+% so that the text is not shifted.
% \end{multicols}
%
% \begin{multicols}{2}[\subsection{License}]
@@ -350,7 +358,11 @@ and the derived files multicolrule.ins,
% \end{multicols}
%
% \section{The User Interface}
-% |\SetMCRule| \marg{key-value list}
+% \begin{function}{\SetMCRule}
+% \begin{syntax}
+% \cs{SetMCRule} \meta{key-value list}
+% \end{syntax}
+% \end{function}
%
% \begin{multicols}{2}
% \SetMCRule{width=2pt,line-style=circles}
@@ -393,6 +405,8 @@ and the derived files multicolrule.ins,
% (see sec. \ref{sec:custom})\\
% \kvdesc{double} & Draw two copies of the rule (see sec.
% \ref{sec:repeats})\\
+% \kvdesc{expand} & Change the extend distance by the same amount at the top
+% and bottom of the column (see sec. \ref{sec:extend})\\
% \kvdesc{extend-bot} & Set an extra amount to extend the rule at the bottom of
% the column (see sec. \ref{sec:extend})\\
% \kvdesc{extend-fill} & Extend rule to the bottom of the text area
@@ -415,6 +429,8 @@ and the derived files multicolrule.ins,
% sec. \ref{sec:repeats})\\
% \kvdesc{repeat-distance} & Set the horizontal space between
% adjacent copies of repeated rules (see sec. \ref{sec:repeats})\\
+% \kvdesc{shift} & Shift the extend distance downward; this affects both the
+% top and bottom of the column (see sec. \ref{sec:extend})\\
% \kvdesc{triple} & Draw three copies of the rule (see sec.
% \ref{sec:repeats})\\
% \kvdesc{width} & Set the width of the rule (see sec.
@@ -497,6 +513,7 @@ and the derived files multicolrule.ins,
% \kvdesc{solid} & A solid line, like \kvdesc{default}, but supports extending
% rules\\
% \kvdesc{solid-circles} & A series of filled circles (\emph{tikz only})\\
+% \kvdesc{strut} & An invisible (0pt) strut is drawn in place of a solid rule.\\
% \bottomrule
% \end{longtable}
%
@@ -525,6 +542,12 @@ and the derived files multicolrule.ins,
% The \kvdesc{dotted} styles differ from \kvdesc{dots} in that the former are
% squares with side lengths equal to \cs{columnseprule}. This mirrors the
% behavior of the equivalently named dotted patterns in \pkg{tikz}.
+%
+% The \kvdesc{strut} style draws a 0pt rule. Like every other line style,
+% however, the value of \cs{columnseprule} must be greater than 0pt for it
+% to be drawn. An invisible rule can be useful if you want to disable a rule
+% in the middle of a cycle of patterns or in conjunction with the extend
+% various extend options. See section \ref{sec:extend}.
% \end{multicols}
%
% \subsubsection{Custom Patterns}\label{sec:custom}
@@ -589,9 +612,16 @@ and the derived files multicolrule.ins,
% This function will use the color set in
% \cs{columnseprulecolor} if you don't set it explicitly within the tikz
% command, but you must provide everything else necessary to draw the line
-% correctly, including the line width. Note that this function should be
-% considered experimental. It works for single-line commands such as the one
-% shown in the example, but I haven't tested it with anything more elaborate.
+% correctly, including the line width. Note that nothing limits you to drawing
+% a picture that fits within the space between the columns. If the rule is
+% wider than the available space, it will be centered between the columns and
+% overlap the text. Normally, of course, that will be undesirable, but you can
+% use it to your advantage in certain cases. The file \file{mcrule-example.pdf}
+% contains examples showing the effect of a rule that is too wide, as well as
+% a custom rule which includes horizontal rules at the top and bottom of the
+% column.\footnote{This latter rule was developed as an answer to
+% \href{https://tex.stackexchange.com/questions/473828/horizontal-rules-before-and-after-multicols}
+% {StackExchange question 473828}.}
% \end{multicols}
%
% \begin{multicols}{2}[\subsection{Colors}\label{sec:color}]
@@ -627,8 +657,9 @@ and the derived files multicolrule.ins,
% \SetMCRule{width=thick,line-style=dash-dot-dot}
% You\stydsc{line-style= dash-dot-dot,\\ width=thick} can set the width of the
% rule with the \kvdesc{width} key. Legal values are any explicit dimension or
-% dimension expression, as well as with names that parallel those used by
-% \pkg{tikz}, except that spaces in the key names are replaced with hyphens.
+% dimension expression, as well as one of the names listed in table
+% \ref{table:linewidths}. These names parallel those used by \pkg{tikz}, except
+% that spaces in the key names are replaced with hyphens.
%
% The current width of the rule is kept in \cs{columnseprule}, just as in
% vanilla \LaTeX, and if it is set separately, the custom rule's width will
@@ -681,33 +712,49 @@ and the derived files multicolrule.ins,
% \end{multicols}
%
%\begin{multicols}{2}[\subsection{Extended Rules}\label{sec:extend}]
-% \SetMCRule{line-style=dashed,extend-top=-16pt,extend-bot=-16pt}
-%
-% You\stydsc{line-style=dashed, extend-top=-16pt, extend-bot=-16pt} can specify
-% an additional amount by which the top or bottom of the rule projects beyond
-% the column's natural length with the keys \kvdesc{extend-top} and
-% \kvdesc{extend-bot}, each of which can be set to a dimension expression.
-% Extending the top of the rule with a positive dimension will push the columns
-% down from any preceding material. A positive value for \kvdesc{extend-bot}
-% does the same in the other direction when a column ends in the middle of a
-% page, but the rule will extend into the the bottom margin if the column goes
-% to the end of the page, and so you probably only want to use this in very
-% limited situations where you need a special effect for one column or a small
-% \env{multicol} environment. Overprinting and other bizarre effects can
-% result from extending the rule in the wrong place. Negative values for both
-% keys may be more generally useful, as they have the effect of shrinking the
-% rule. This behavior is illustrated with the rule for this section.
-%
-% The \kvdesc{extend-fill} key is a boolean option that, when set to true, will
-% extend the rule to occupy any space between the bottom of the columns and the
-% end of the text area. Providing the key with no value is equivalent to
-% |extend-fill=true|. This option has no effect unless the \pkg{multicol}
-% package is loaded.
-%
-% If you want text below the \env{multicols} environment when using
-% \kvdesc{extend-fill}, you can reserve space for it with
-% \kvdesc{extend-reserve}, which takes a dimension expression specifying the
-% vertical space to leave available after the rule. If the value is greater
+% \SetMCRule{line-style=dashed,expand=-16pt}
+%
+% You\stydsc{line-style=dashed, expand=-16pt} can specify an additional amount
+% by which the top or bottom of the rule projects beyond the column's natural
+% length with the keys \kvdesc{extend-top} and \kvdesc{extend-bot}, each of
+% which can be set to a dimension expression. Extending the top of the rule
+% with a positive dimension will push the columns down from any preceding
+% material. A positive value for \kvdesc{extend-bot} does the same in the other
+% direction when a column ends in the middle of a page, but the rule will
+% extend into the the bottom margin if the column goes to the end of the page.
+%
+% Note that positive values for extending the rules should be used with
+% caution and only in situations where you need a special effect for one column
+% or a small \env{multicol} environment. (See section \ref{sec:patterns} for a
+% way to limit the change to one or a few columns.) Overprinting and other
+% bizarre effects can result from extending the rule in the wrong place.
+% Negative values for both keys may be more generally useful, as they have the
+% effect of shrinking the rule. This behavior is illustrated with the rule for
+% this section.
+%
+% The \kvdesc{expand} and \kvdesc{shift} keys provide shorthands for two
+% common situations. You can use \kvdesc{expand} to set the same value for
+% \kvdesc{extend-top} and \kvdesc{extend-bot} For example, |expand=-16pt| is
+% equivalent to |extend-bot=-16pt, extend-top=-16pt|. The \kvdesc{shift} key
+% moves the rule downward for positive values and upward for negative ones
+% without changing the overall length of the rule. More precisely, |shift=x|
+% translates to |extend-bot=x, extend-top=-x|. For example, |shift=16pt| is
+% equivalent to |extend-bot=16pt, extend-top=-16pt|.
+%\end{multicols}
+%
+%\begin{multicols}{2}
+% \SetMCRule{line-style=solid,extend-fill}
+% The\stydsc{line-style=solid, extend-fill} \kvdesc{extend-fill} key is a
+% boolean option that, when set to true, will extend the rule to occupy any
+% space between the bottom of the columns and the end of the text area.
+% Providing the key with no value is equivalent to |extend-fill=true|. This
+% option is only relevant for the \env{multicols} environment. It will have
+% no effect with either \env{multicols*} or the plain \LaTeX{} two-column mode.
+%
+% If you want text below and on the same page as the \env{multicols}
+% environment when using \kvdesc{extend-fill}, you can reserve space for it
+% with \kvdesc{extend-reserve}, which takes a dimension expression specifying
+% the vertical space to leave available after the rule. If the value is greater
% than zero, the height of the extended line will be reduced by the reserved
% amount plus the value of \cs{multicolsep}. In other words, you only have to
% specify the actual space you need for the text itself, not the space that
@@ -717,54 +764,64 @@ and the derived files multicolrule.ins,
% probably will find this material spilling onto the next page anyway.
%\end{multicols}
%
-%\subsection{Rule Patterns}
+%\subsection{Rule Patterns}\label{sec:patterns}
+% \begin{function}{\DeclareMCRulePattern}
% \begin{syntax}
- % |\DeclareMCRulePattern| \marg{name} \marg{key-value list}
- % \end{syntax}
+% \cs{DeclareMCRulePattern} \marg{name} \marg{key-value list}
+% \end{syntax}
+% \end{function}
%\DeclareMCRulePattern{left-hand}{custom-tile={\HandLeft}{8pt}{8pt}}
%\DeclareMCRulePattern{right-hand}{custom-tile={\HandRight}{8pt}{8pt}}
%\begin{multicols}{3}
% \noindent \DescribeMacro{\DeclareMCRulePattern}
% \SetMCRule{patterns={right-hand,left-hand}}
% A\stydsc{patterns=\{right-hand, left-hand\}\\ See the code sample below for
-% the definitions of the patterns} ``pattern'' refers to a bundle of settings used by \mcrule. You can declare
-% a pattern for a line style with the command \cs{DeclareMCRulePattern}. The
-% \meta{name} should consist of letters and hyphens only. The
-% \meta{key-value list} can contain all keys that are valid for \cs{SetMCRule}
-% with the exception of \kvdesc{patterns}. If you put something like
-% |patterns=foo| in the definition of a pattern, you won't get an error, but it
-% will be ignored.
+% the definitions of the patterns} \emph{pattern} refers to a bundle of
+% settings used by \mcrule. Although you can use patterns as a shortcut to save
+% you a little typing, their main purpose is to let you to alter individual
+% rules within a multicol environment. For example, if you have three-column
+% text, you can make the left rule different from the right one. In two-column
+% text, you can have different rules for alternating pages.
+%
+% You declare a pattern for a line style with the command
+% \cs{DeclareMCRulePattern}. The \meta{name} should consist of letters and
+% hyphens only. The \meta{key-value list} can contain all keys that are valid
+% for \cs{SetMCRule} with the exception of \kvdesc{patterns}, which is filtered
+% out. In other words, if you put something like |patterns=foo| in the
+% pattern definition, it will be ignored.
%
% Once you have declared a pattern, you can use it as a value for the
% \kvdesc{patterns} argument of \cs{SetMCRule}. This key can accept either a
% single pattern or a comma-separated list of patterns. If you use a
% comma-separated list, make sure you enclose it in braces.
%
-% When a pattern is in effect, its settings are applied on top of whatever
-% the prior settings are. If you set the key to an empty list, any patterns
-% currently in effect will be canceled, and \mcrule{} will revert to the
-% previous settings.
+% When a pattern is in effect, its settings are applied on top of the prior
+% settings. If you set the key to an empty list, any patterns currently in
+% effect will be canceled, and \mcrule{} will revert to the previous settings.
%
% If the \kvdesc{patterns} key contains more than one pattern, \mcrule{} will
% cycle through the list of patterns, using one pattern each time a rule is
-% drawn between columns. (Note, the patterns do not cycle within a single
-% column separator if you use the \kvdesc{repeat} key.) This cycle is global,
-% so if the number columns is not a multiple of the number of patterns and you
-% start a new \env{multicols} environment with the same patterns in effect, the
-% cycle will pick up where it left off. Every time you set new patternss,
-% however, the cycle begins anew.
-%
+% drawn between columns. Note that the patterns do not cycle within a single
+% column separator if you use the \kvdesc{repeat} key. This cycle is global,
+% so if the number column separators is not a multiple of the number of
+% patterns and you start a new \env{multicols} environment with the same
+% patterns in effect, the cycle will pick up where it left off. Every time you
+% set new patterns, however, the cycle begins anew with the first pattern in
+% the list.
%\end{multicols}
%
-% The columns above were defined with the following:
-%\begin{verbatim}
+% \noindent The columns above were defined with the following commands:
+%
+% \medskip
+%
+% \begin{BVerbatim}
% \DeclareMCRulePattern{left-hand}{custom-tile={\HandLeft}{8pt}{8pt}}
% \DeclareMCRulePattern{right-hand}{custom-tile={\HandRight}{8pt}{8pt}}
% \begin{multicols}{3}
% \SetMCRule{patterns={right-hand,left-hand}}
% ...
% \end{multicols}
-%\end{verbatim}
+% \end{BVerbatim}
%
%\DeclareMCRulePattern{shrink-me}{line-style=solid,extend-top=-3\baselineskip}
%\begin{multicols}{3}
@@ -789,7 +846,7 @@ and the derived files multicolrule.ins,
% For example, suppose you have four-column text and want to alter the third
% column separator on the first page of the environment only.\footnote{Remember
% that you have one less column separator than you have columns.} You could
-% accomplish this task with the code above.
+% accomplish this task with the code below.
%
% Using predefined patterns adds processing overhead, since they must be
% applied each time the rule is drawn. Therefore it is more efficient to avoid
@@ -798,20 +855,24 @@ and the derived files multicolrule.ins,
% unlikely to notice too much delay.
%
% Note that any settings you provide in the same command where you apply a
-% \kvdesc{patterns} key do not alter definition of the pattern. If you do this,
-% you are altering the settings in effect before the pattern is applied.
+% \kvdesc{patterns} key do not alter definition of the pattern, even if they
+% come after the \kvdesc{patterns} key. Such settings will take effect before
+% the pattern is applied and will reappear after the pattern ends, if it does.
%
%\end{multicols}
-
-% Shrinking the final two column separators in four-column text:
-%\begin{verbatim}
+%
+% \noindent Shrinking the final two column separators in four-column text:
+%
+% \medskip
+%
+%\begin{BVerbatim}
% \DeclareMCRulePattern{shrink-me}{line-style=solid,
% extend-top=-3\baselineskip}
% \begin{multicols}{4}
% \SetMCRule{patterns=shrink-me,pattern-after=1,pattern-for=2}
% ...
% \end{multicols}
-%\end{verbatim}
+%\end{BVerbatim}
%
%\end{documentation}
%
@@ -830,7 +891,7 @@ and the derived files multicolrule.ins,
%\subsection{Preliminaries}
%
% \begin{macrocode}
-\ProvidesExplPackage {multicolrule} {2019/01/01} {1.2}
+\ProvidesExplPackage {multicolrule} {2019/10/01} {1.3}
{Decorative vertical rules between columns}
% \end{macrocode}
%
@@ -932,23 +993,50 @@ and the derived files multicolrule.ins,
\ProcessKeysOptions{mcrule-opts}
% \end{macrocode}
%
-% \subsection{Patching Output Routines}
+% \subsection{Patching Output Routines}\label{sec:patching}
+% Now that we know what mode we're going to run in, we patch the output
+% routine(s) to substitute our custom rule for the vanilla one. Since
+% \pkg{multicol} doesn't fully support twocolumn mode, we patch one or the
+% other, but not both.
%
-%\begin{function}{\@@_column_height:,\@@_column_depth:}
+% First we set some stubs for functions we'll need to redirect depending on
+% the mode we're operating in.
%
-% Get the height and depth of the box appropriate to the supported mode.
+%\begin{macro}{\@@_column_height:}
+% Returns the fixed height of the columns. The actual code to calculate the
+% height is set when we set the appropriate mode.
%
% \begin{macrocode}
\cs_new:Npn \@@_column_height: {}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@@_column_depth:}
+% Returns the maximum depth of the columns. The actual code to calculate the
+% depth is set when we set the appropriate mode.
+%
+% \begin{macrocode}
\cs_new:Npn \@@_column_depth: {}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
-%\begin{function}{\@@_patch_mcol_output:N}
-% Now that we know what mode we're going to run in, we patch the output
-% routine(s) to substitute our custom rule for the vanilla one. Since
-% \pkg{multicol} doesn't fully support twocolumn mode, we patch one or the
-% other, but not both. As of version 1.2, we make \cs{columnseprulecolor}
+%\begin{macro}{\@@_column_overflow:}
+% Returns the amount by which text overflows the bottom of the columns. This
+% situation occurs in \pkg{multicol} when \cs{maxbalancingoverflow} is greater
+% than 0 (by default it's 12pt) and there would otherwise be a widow at the end
+% of the environment, so we don't check for it in two-column mode.
+% \changes{v1.2a}{2019/2/12}{New internal function}
+%
+% \begin{macrocode}
+\cs_new:Npn \@@_column_overflow: {0pt}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@@_patch_mcol_output:N}
+% We create a helper macro to simplify patching the appropriate part of the
+% relevant \pkg{multicol} routines. The search and replace texts are identical
+% across several routines, so only the name of the function to be patched
+% needs to be passed as a parameter. We make \cs{columnseprulecolor}
% part of \cs{mcruledivider} so that we can set the color as part of a
% style pattern.
% \changes{v1.2}{2019/1/1}{Move \cs{columnseprulecolor} inside
@@ -962,9 +1050,9 @@ and the derived files multicolrule.ins,
{\msg_info:nnn {multicolrule} {patch-failure} {#1}}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
-%\begin{function}{\@@_patch_twocol_output:N}
+%\begin{macro}{\@@_patch_twocol_output:N}
% The same idea as above, only for the vanilla twocolumn mode.
% \changes{v1.2}{2019/1/1}{Move \cs{columnseprulecolor} inside
% \cs{mcruledivider}}
@@ -977,7 +1065,9 @@ and the derived files multicolrule.ins,
{\msg_info:nnn {multicolrule} {patch-failure} {#1}}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
+%
+% Now the actual patching begins.
%
% \begin{macrocode}
\bool_if:NTF \g_@@_twocolumn_bool
@@ -985,15 +1075,23 @@ and the derived files multicolrule.ins,
\@ifpackageloaded{multicol}
{\msg_warning:nn {multicolrule} {multicol-loaded}}{}
% \end{macrocode}
-% Provide the column-color macro from \pkg{multicol}.
+%
+% Default \LaTeX{} lacks \cs{columnseprulecolor}, so if we're in two-column
+% mode, we provide it here.
+%
% \begin{macrocode}
\cs_gset:Npn \columnseprulecolor {\normalcolor}
+% \end{macrocode}
+%
+% In vanilla twocolumn mode, the column height and depth can be taken directly
+% from \cmd{\@outputbox}.
+%
+% \begin{macrocode}
\cs_gset:Npn \@@_column_height: {\box_ht:N \@outputbox}
\cs_gset:Npn \@@_column_depth: {\box_dp:N \@outputbox}
- \@@_patch_twocol_output:N \@outputdblcol
% \end{macrocode}
%
-% Now patch the relevant code in |\@outputdblcol|, replacing the hard-coded
+% Now patch the relevant code in \cmd{\@outputdblcol}, replacing the hard-coded
% rule with a macro that we can overwrite.
%
% \begin{macrocode}
@@ -1004,6 +1102,7 @@ and the derived files multicolrule.ins,
% after \pkg{xcolor}, \pkg{tikz}, \emph{and} \pkg{multicol}, so it must always
% be loaded after us. We use \cs{AfterPackage} from \pkg{scrlfile} to insert
% the patch if \pkg{bidi} is loaded later on.
+%
% \begin{macrocode}
\AfterPackage!{bidi}
{
@@ -1022,14 +1121,48 @@ and the derived files multicolrule.ins,
\@@_patch_mcol_output:N \RL@column@boxes
% \end{macrocode}
%
-% Although taking the height of \cmd{\mult@rightbox} is a reliable way
-% to get the column height, the same isn't true for the depth, so we
-% use |\dimen\tw@|, which \pkg{multicol} uses to hold the maximum
-% depth of all the columns, instead.
+% In LTR mode, we are invoked after a column has been typeset, which destroys
+% their boxes in the process. So the only boxes we can be sure still exist are
+% \cmd{\mult@rightbox}, which will be set to the same column height as all the
+% others, and \cmd{\mult@nat@firstbox}, which contains the first column at its
+% natural height.
%
% \begin{macrocode}
- \cs_gset:Npn \@@_column_height: {\box_ht:N \mult@rightbox}
- \cs_gset:Npn \@@_column_depth: {\dimen\tw@}
+ \cs_gset:Npn \@@_column_height:
+ {
+ \box_ht:N \mult@rightbox
+ }
+% \end{macrocode}
+%
+% Since the depth can differ from column to column, we use |\dimen\tw@|,
+% which \pkg{multicol} uses to hold the maximum depth of all the columns
+% already typeset, but as it won't have reached the final one yet, we check
+% that too. This could lead to an inconsistent height in the event that
+% there are 3 or more columns and a middle column has a significantly larger
+% depth than either the previous columns or the last column, but for now it
+% does not seem worth accounting for a condition that is likely to be very
+% rare in actual user documents.
+% \changes{v1.2a}{2019/2/12}{Check depth of final column}
+%
+% \begin{macrocode}
+ \cs_gset:Npn \@@_column_depth:
+ {
+ \dim_max:nn {\dimen\tw@}{\box_dp:N \mult@rightbox}
+ }
+% \end{macrocode}
+%
+% To avoid widows, \pkg{multicol} allows some overflow, by default up to 12pt,
+% and so it's possible that some text will overflow beyond the fixed bottom of
+% the column. In this case, our rule won't descend far enough. To correct, we
+% measure the column overflow as the difference between the natural height of
+% the first box and the height of the last column, and add that amount if it's
+% greater than 0pt.
+%
+% \begin{macrocode}
+\cs_gset:Npn \@@_column_overflow:
+{
+ \dim_max:nn {\box_ht:N \mult@nat@firstbox - \box_ht:N \mult@rightbox}{0pt}
+}
% \end{macrocode}
%
% We need to reissue \cs{LRmulticolcolumns} to update the actual code in
@@ -1045,9 +1178,8 @@ and the derived files multicolrule.ins,
% columns in right-to-left order, and the effect is to leave the original
% \pkg{multicol} definitions loaded but unused. As a result, after these
% changes, the \pkg{multicol} commands \cs{LRmulticolcolumns} and
-% \cs{RLmulticolcolumns} have no visible effect. But as \pkg{bidi} also
-% reworks the footnotes extensively, it's easier just to patch the equivalent
-% output routines rather than rewrite it properly.
+% \cs{RLmulticolcolumns} have no visible effect. First we replace
+% \pkg{bidi}'s copies of the column boxes routines with our patched version.
%
% \begin{macrocode}
\AfterPackage!{bidi}
@@ -1065,28 +1197,24 @@ and the derived files multicolrule.ins,
}
}
% \end{macrocode}
-%
%
% \subsection{Creating the Rules}
-% Utility functions for different rule types
-%
-%\begin{macro}{\mcruledivider}
+% Now we declare utility functions for different rule types.
%
-% This is the function directly called by the patched output routines. It
-% has a \LaTeX2 name so the user can redefine it if necessary. Its main
-% function is to call the internal function \cs{mcrule_divider:}, which contains
+%\begin{function}{\mcruledivider}
+% This is the function directly called by the patched output routines. Its main
+% purpose is to call the internal function \cs{mcrule_divider:}, which contains
% the actual rule-typesetting instructions, the number of times specified in
-% \cs{l_@@_repeat_int}. \pkg{multicol} puts the rule in a group
-% in order to keep the color contained, which means that any local changes
-% here will be lost at the end of the rule. For this reason, we must set the
-% pattern, if any, here in order to support having different line styles
-% between different columns.
+% \cs{l_@@_repeat_int}. \pkg{multicol} puts the rule in a group in order to keep
+% the color contained, which means that any local changes here will be lost at
+% the end of the rule. For this reason, we must set the pattern, if any, here in
+% order to support having different line styles between different columns.
%
-% \changes{v1.2}{2019/1/1}{Add pattern support}
% \begin{macrocode}
\cs_new_protected:Npn \mcruledivider
{
% \end{macrocode}
+% \changes{v1.2}{2019/1/1}{Add pattern support}
% If the |pattern-after| counter is set, wait that many iterations of the rule
% before we apply the patterns.
% \begin{macrocode}
@@ -1096,9 +1224,11 @@ and the derived files multicolrule.ins,
}
{
% \end{macrocode}
+%
% Don't change if the pattern is empty or the |pattern-for| counter has
% expired. The way the logic works here, negative values of |pattern-for|
% result in an indefinite number of repeats.
+%
% \begin{macrocode}
\bool_lazy_and:nnT
{\int_compare_p:nNn {\seq_count:N \l_@@_pattern_list_seq} > {\c_zero_int}}
@@ -1110,7 +1240,8 @@ and the derived files multicolrule.ins,
{
\int_gset:Nn \g_@@_pattern_count_int {\c_one_int}
}
- \tl_set:Nx \l_tmpa_tl {\seq_item:Nn \l_@@_pattern_list_seq {\g_@@_pattern_count_int} }
+ \tl_set:Nx \l_tmpa_tl {\seq_item:Nn \l_@@_pattern_list_seq
+ {\g_@@_pattern_count_int} }
\tl_if_blank:VF \l_tmpa_tl
{
\@@_set_pattern:V \l_tmpa_tl
@@ -1122,13 +1253,17 @@ and the derived files multicolrule.ins,
}
}
% \end{macrocode}
+%
% Now that the pattern has been changed we can set the color.
+%
% \begin{macrocode}
\columnseprulecolor
% \end{macrocode}
+%
% We only call \cs{mcrule_divider:} if \cs{columnseprule} $>0$, so that all
% line styles can be turned off by setting it to 0, just as is the case with
% the vanilla rules.
+%
% \begin{macrocode}
\bool_lazy_and:nnT
{\dim_compare_p:nNn {\columnseprule} > {\c_zero_dim}}
@@ -1143,24 +1278,27 @@ and the derived files multicolrule.ins,
}
}
% \end{macrocode}
-%\end{macro}
+%\end{function}
%
-%\begin{function}{\@@_column_total_height:,\@@_column_total_depth:}
+%\begin{macro}{\@@_column_total_height:,\@@_column_total_depth:}
% Get column height and depth with any explicit alterations.
+% \changes{v1.2a}{2019/2/12}{Account for overflow text}
+%
% \begin{macrocode}
\cs_new:Npn \@@_column_total_height:
{
\dim_eval:n {\@@_column_height: + \@@_column_depth: +
- \@@_extend_column_top: + \@@_extend_column_bottom:}
+ \@@_extend_column_top: + \@@_column_overflow: + \@@_extend_column_bottom:}
}
\cs_new:Npn \@@_column_total_depth:
{
- \dim_eval:n {\@@_column_depth: + \@@_extend_column_bottom:}
+ \dim_eval:n {\@@_column_depth: + \@@_column_overflow: +
+ \@@_extend_column_bottom:}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
-%\begin{function}{\@@_extend_column_top:}
+%\begin{macro}{\@@_extend_column_top:}
% Currently, the extend amount for the top is just the
% |\l_@@_extend_top_dim| distance. In the future we may allow more complex
% criteria, such as by odd or even page, or on a particular page. Although
@@ -1172,9 +1310,9 @@ and the derived files multicolrule.ins,
\l_@@_extend_top_dim
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
-%\begin{function}{\@@_extend_column_bottom:}
+%\begin{macro}{\@@_extend_column_bottom:}
% The |extend-fill| option, which is only applicable with \pkg{multicol},
% extends the rule from the bottom of the column to the end of the text area,
% minus whatever reserved space the user specifies. If there's less space
@@ -1194,9 +1332,9 @@ and the derived files multicolrule.ins,
{\l_@@_extend_bot_dim}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
-%\begin{function}{\@@_extend_reserve:}
+%\begin{macro}{\@@_extend_reserve:}
% The reserved space is the amount of user-provided space we want, but we also
% have to account for the space added with \cs{multicolsep}.
% \begin{macrocode}
@@ -1207,7 +1345,7 @@ and the derived files multicolrule.ins,
{\c_zero_dim}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
%\begin{function}{\mcrule_divider:}
% This is the routine that contains the instructions to draw one copy
@@ -1219,14 +1357,15 @@ and the derived files multicolrule.ins,
% \end{macrocode}
%\end{function}
%
-%\begin{function}{\@@_pattern:nnn}
+%\begin{macro}{\@@_pattern:nnn}
% \begin{syntax}
-% |\__mcrule_pattern:nnn| \Arg{pattern} \Arg{space above} \Arg{space below}
+% \cs{@@_mcrule_pattern:nnn} \Arg{pattern} \Arg{space above} \Arg{space below}
% \end{syntax}
% Typesets a single copy of a pattern, vertically centered, in a vertical
% box that is the height of the current column. The pattern must be
-% something that can go in a horizontal box. The spaces above and below
-% must be fixed dimensions.
+% something that can go in a horizontal box. The \meta{space above} and
+% \meta{space below} arguments must be dimension expressions.
+% \changes{v1.2a}{2018/1/2}{Allow evaluated dimensions for kerns}
% \begin{macrocode}
\cs_new_nopar:Npn \@@_pattern:nnn #1#2#3
{
@@ -1235,22 +1374,25 @@ and the derived files multicolrule.ins,
\vbox_to_ht:nn {\@@_column_total_height:}
{
\tex_vfill:D
- \tex_kern:D #2 \hbox:n{#1} \tex_kern:D #3
+ \tex_kern:D \dim_eval:n {#2} \exp_stop_f:
+ \hbox:n{#1}
+ \tex_kern:D \dim_eval:n {#3} \exp_stop_f:
\tex_vfill:D
}
}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
-%\begin{function}{\@@_tile_pattern:nnn}
+%\begin{macro}{\@@_tile_pattern:nnn}
% \begin{syntax}
-% |\__mcrule_tile_pattern:nnn| \Arg{pattern} \Arg{space above} \Arg{space below}
+% \cs{mcrule_tile_pattern:nnn} \Arg{pattern} \Arg{space above} \Arg{space below}
% \end{syntax}
% Typesets multiple copies of pattern, tiled so as to occupy a vertical box
% that is the height of the current column. The pattern must be something
-% that can go in a horizontal box. The spaces above and below must be fixed
-% dimensions.
+% that can go in a horizontal box. The \meta{space above} and
+% \meta{space below} arguments must be dimension expressions.
+% \changes{v1.2a}{2018/1/2}{Allow evaluated dimensions for kerns}
% \begin{macrocode}
\cs_new_nopar:Npn \@@_tile_pattern:nnn #1#2#3
{
@@ -1260,24 +1402,27 @@ and the derived files multicolrule.ins,
{
\tex_cleaders:D \vbox:n
{
- \tex_kern:D #2 \hbox:n{#1} \tex_kern:D #3
+ \tex_kern:D \dim_eval:n {#2} \exp_stop_f:
+ \hbox:n{#1}
+ \tex_kern:D \dim_eval:n {#3} \exp_stop_f:
}
\tex_vfill:D
}
}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
-%\begin{function}{\@@_line_pattern:nnnn}
+%\begin{macro}{\@@_line_pattern:nnnn}
% \begin{syntax}
-% |\__mcrule_line_pattern:nnnn| \Arg{tikz-name} \Arg{height} \Arg{space above}
+% \cs{@@_mcrule_line_pattern:nnnn} \Arg{tikz-name} \Arg{height} \Arg{space above}
% \Arg{space below}
% \end{syntax}
% This function can draw a line pattern using either a \pkg{tikz} name or
% directly (as a tiled pattern). The latter case is currently limited to line
% patterns that can be described in terms of a solid line of length
% \meta{height} separated by spaces above and/or below the line.
+%
% \begin{macrocode}
\cs_new:Npn \@@_line_pattern:nnnn #1#2#3#4
{
@@ -1290,9 +1435,9 @@ and the derived files multicolrule.ins,
}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
-%\begin{function}{\@@_solid_line:}
+%\begin{macro}{\@@_solid_line:}
% Unlike the default solid line, which is created with a simple \tn{vrule},
% this version allows us to extend the line beyond the natural space of the
% column.
@@ -1302,7 +1447,18 @@ and the derived files multicolrule.ins,
\rule[-\@@_column_total_depth:]{\columnseprule}{\@@_column_total_height:}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
+%
+%\begin{macro}{\@@_strut:}
+% Uses a zero-width rule, regardless of the actual value of \cs{columnseprule}.
+% \changes{v1.3}{2019/10/1}{New function}
+% \begin{macrocode}
+\cs_new:Npn \@@_strut:
+{
+ \rule[-\@@_column_total_depth:]{0pt}{\@@_column_total_height:}
+}
+% \end{macrocode}
+%\end{macro}
%
% \subsubsection{Tikz-only Routines}
%
@@ -1318,7 +1474,7 @@ and the derived files multicolrule.ins,
\ExplSyntaxOn
% \end{macrocode}
%
-%\begin{function}{\@@_tikz_picture:n}
+%\begin{macro}{\@@_tikz_picture:n}
% \begin{syntax}
% |\__mcrule_tikz_picture:n| \Arg{draw function}
% \end{syntax}
@@ -1337,11 +1493,11 @@ and the derived files multicolrule.ins,
\end{tikzpicture}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
-%\begin{function}{\@@_pattern_line:n}
+%\begin{macro}{\@@_pattern_line:n}
% \begin{syntax}
-% |\__mcrule_pattern_line:n| \Arg{tikz pattern}
+% \cs{@@_mcrule_pattern_line:n} \Arg{tikz pattern}
% \end{syntax}
% For the \pkg{tikz} versions of the predefined lines, we just draw
% a line the length of the column box. \meta{tikz pattern} should
@@ -1355,9 +1511,9 @@ and the derived files multicolrule.ins,
\end{tikzpicture}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
-%\begin{function}{\@@_circle:}
+%\begin{macro}{\@@_circle:}
% Draw a hollow circle with a diameter equal to |\columnseprule|. This will be
% used as a tile pattern.
%
@@ -1369,9 +1525,9 @@ and the derived files multicolrule.ins,
\end{tikzpicture}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
-%\begin{function}{\@@_solid_circle:}
+%\begin{macro}{\@@_solid_circle:}
% Draw a filled circle with a diameter equal to |\columnseprule|. This will be
% used as a tile pattern.
%
@@ -1384,7 +1540,7 @@ and the derived files multicolrule.ins,
}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
% In case \pkg{tikz} functions are not active, we provide stubs
% that issue error messages.
@@ -1403,7 +1559,7 @@ and the derived files multicolrule.ins,
% \end{macrocode}
%
% \subsection{Color}
-%\begin{function}{\@@_set_rule_color:}
+%\begin{macro}{\@@_set_rule_color:}
% Reset color definition in \cs{columnseprulecolor} by name or
% by model and color specification.
%
@@ -1424,11 +1580,11 @@ and the derived files multicolrule.ins,
}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
% \subsection{Patterns}
%
-%\begin{function}{\@@_set_pattern_list:n}
+%\begin{macro}{\@@_set_pattern_list:n}
% Sets a comma-separated list of patterns as a sequence for later use. The
% global counter that indicates where we are in the list is also reset here, so
% setting a list of patterns always means that the next rule will use the first
@@ -1442,9 +1598,9 @@ and the derived files multicolrule.ins,
\int_gset:Nn \g_@@_pattern_for_int {-1}
}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
-%\begin{function}{\@@_set_pattern:n}
+%\begin{macro}{\@@_set_pattern:n}
%
% Set the keys an individual pattern. To avoid potential recursion and loops,
% we filter out the key `pattern' when it appears in a pattern definition.
@@ -1462,7 +1618,7 @@ and the derived files multicolrule.ins,
}
\cs_generate_variant:Nn \@@_set_pattern:n {V}
% \end{macrocode}
-%\end{function}
+%\end{macro}
%
% \subsection{Key-Values}
% Set up all the key definitions. For the line styles, this involves
@@ -1471,6 +1627,7 @@ and the derived files multicolrule.ins,
% extend-reserve keys}
% \changes{v1.2}{2019/1/1}{Added patterns, pattern-after, and pattern-for
% keys}
+% \changes{v1.2a}{2019/2/12}{Added expand and shift shortcuts}
%
% \begin{macrocode}
\keys_define:nn {mcrule}
@@ -1480,11 +1637,21 @@ and the derived files multicolrule.ins,
extend-fill .bool_set:N = \l_@@_extend_fill_bool,
extend-fill .default:n = true,
extend-reserve .dim_set:N = \l_@@_extend_reserve_dim,
+ expand .code:n = {
+ \dim_set:Nn \l_@@_extend_bot_dim {#1}
+ \dim_set:Nn \l_@@_extend_top_dim {#1}
+ },
+ shift .code:n = {
+ \dim_set:Nn \l_@@_extend_bot_dim {#1}
+ \dim_set:Nn \l_@@_extend_top_dim {\fp_to_dim:n {-1 * \l_@@_extend_bot_dim}}
+ },
line-style .choice:,
line-style / default .code:n = \cs_set:Npn \mcrule_divider:
{\vrule\@width\columnseprule},
line-style / solid .code:n = \cs_set:Npn \mcrule_divider:
{\@@_solid_line:},
+ line-style / strut .code:n = \cs_set:Npn \mcrule_divider:
+ {\@@_strut:},
line-style / dots .code:n = \cs_set:Npn \mcrule_divider:
{\@@_tile_pattern:nnn {.}{1pt}{1pt}},
line-style / dense-dots .code:n = \cs_set:Npn \mcrule_divider:
@@ -1591,10 +1758,10 @@ and the derived files multicolrule.ins,
%\end{macro}
%
%\begin{macro}{\DeclareMCRulePattern}
-% Declare a new style pattern.
% \begin{syntax}
-% |\DeclareMCRule| \marg{name} \marg{key-value list}
+% \cs{DeclareMCRule} \Arg{name} \meta{key-value list}
% \end{syntax}
+% Declare a new style pattern.
% If a pattern of that name exists, it will be overwritten silently.
% \begin{macrocode}
\NewDocumentCommand{\DeclareMCRulePattern}{m m}