% \iffalse
%
%% File: xgalley.dtx
%
% Copyright (C) 1999-2001,2004-2009 Frank Mittelbach
%           (C) 2010-2012,2014,2016-2025 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
% license or (at your option) any later version.  The latest version
% of this license is in the file
%
%    https://www.latex-project.org/lppl.txt
%
% This file is part of the "l3experimental bundle" (The Work in LPPL)
% and all files in that bundle must be distributed together.
%
% -----------------------------------------------------------------------
%
% The development version of the bundle can be found at
%
%    https://github.com/latex3/latex3
%
% for those people who are interested.
%
%<*driver>
\documentclass[full]{l3doc}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{^^A
%   The \pkg{xgalley} package\\ Galley^^A
% }
%
% \author{^^A
%  The \LaTeX{} Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Released 2025-06-30}
%
% \maketitle
%
% \begin{documentation}
%
% \section{Introduction}
%
% In \LaTeX3 terminology a galley is a rectangular area which receives
% text and other material filling it from top. The vertically extend of
% a galley is normally not restricted: instead certain chunks are taken
% off the top of an already partially filled galley to form columns or
% similar areas on a page. This process is typically asynchronous but
% there are ways to control or change its behavior.
%
% Examples for galleys are \enquote{the main galley}, where the
% continuous document data gets formatted into  and from which columns
% and pages are constructed, and \enquote{vertical box galleys}, such
% as the body of a minipage environment. The latter galleys are
% typically not split after formatting, though there can be exceptions.
%
% \section{Formatting layers}
%
% The present module is mainly concerned with the formatting of text
% in galleys. The mechanism by which this is achieved uses four
% (somewhat) distinct layers, some of which can be addressed using the
% templates provided here.
%
% \subsection{Layer one: external dimensions}
%
% The bottom layer of the system is the external dimensions of the
% galley. Normally only the horizontal dimension is fixed externally,
% while the vertical (filling) dimension is unspecified. The external
% dimensions are fixed when starting a new galley, and are therefore
% not modifiable within the galley.
%
% There are no templates for setting this layer directly, although the
% external values are influenced by other parts of the system (for
% example when creating minipage environments).
%
% \subsection{Layer two: internal dimensions}
%
% The second layer is the internal dimensions of the galley: the
% \emph{measure} used for paragraph text and the position of the
% paragraph relative to the edges of the galley.
%
% This layer is normally accessed by higher-level templates
% \emph{via} the object type \texttt{measure}. Changes made using
% level two templates will often extend for large parts of a document
% (up to and including the entire document).
%
% \subsection{Layer three: paragraph shape}
%
% The third layer defines the paragraph shape within the measure as
% provided by the second layer. In the absence of any specification
% for that layer the paragraph shape used will be that of a
% rectangular area of the width of the current measure.
%
% There are some restrictions imposed on the shape of a paragraph by the
% underlying \TeX{} mechanisms. For example, cut out sections in
% paragraphs can be specified from the top of the paragraph but not from
% the bottom.
%
% \subsection{Layer four: formatting inside the paragraph}
%
% The forth layer deals with the paragraph formatting aspects such as
% hyphenation and justification within the paragraph (this is sometimes
% referred to as \enquote{\texttt{h\&j}} or \enquote{\texttt{hj}}).
%
% \section{Templates}
%
% \subsection{Layer two: internal dimensions}
%
% \begin{TemplateInterfaceDescription}{measure}
%   \TemplateArgument{}{} ^^A Some hack
%   \TemplateSemantics
%   Sets the width available to typeset material within the galley.
%   The \meta{left margin} and \meta{right margin} values are used in the
%   adjustment to over-ride any given in the template. Depending upon
%   the template in use, the margins may be absolute (relative only to the
%   edges of the galley) or relative (taking account of |measure| adjustments
%   already made). The template applies to the galley from the point of
%   us forward, unless over-ridden by another use of the |measure|
%   object type.
% \end{TemplateInterfaceDescription}
%
% \begin{TemplateDescription}{measure}{absolute}
%   \TemplateKey{left-margin}{length}
%     {^^A
%       The distance from the left edge of the galley to the left edge of
%       the area for typeset material. A negative value will cause the
%       typeset material to extend beyond the edge of the galley.^^A
%     }
%     {0pt}
%   \TemplateKey{right-margin}{length}
%     {^^A
%       The distance from the right edge of the galley to the right edge of
%       the area for typeset material. A negative value will cause the
%       typeset material to extend beyond the edge of the galley.^^A
%     }
%     {0pt}
%   \TemplateSemantics
%   This template sets up the typesetting area such that typeset material
%   runs from |left-margin| away from the left edge of the galley to
%   |right-margin| away from the right edge of the galley. Both of these
%   distances are absolute, i.e., no account is taken of previous
%   |measure| settings. Either on or both values may be negative, in which
%   case the typeset material will protrude outside of the edges of the
%   galley.
% \end{TemplateDescription}
%
% \begin{TemplateDescription}{measure}{relative}
%   \TemplateKey{left-margin}{length}
%     {^^A
%       The distance from the previous left margin of the typeset material
%       within the galley to the new position of the left margin. A negative
%       value will cause the new margin to be \enquote{outside} of the
%       previous one, and \emph{may} cause the typeset material to
%       protrude outside of the edge of the galley.
%     }
%     {0pt}
%   \TemplateKey{right-margin}{length}
%     {^^A
%       The distance from the previous right margin of the typeset material
%       within the galley to the new position of the right margin. A negative
%       value will cause the new margin to be \enquote{outside} of the
%       previous one, and \emph{may} cause the typeset material to
%       protrude outside of the edge of the galley.
%     }
%     {0pt}
%   \TemplateSemantics
%   This template sets up the typesetting area such that it has margins
%   |left-margin| and |right-margin| within those previously set. For a
%   galley within no previous margins, this will result in margins relative
%   to the edges of the galley. Within a galley in which the |measure| has
%   already been set, using the |relative| template will indent the typeset
%   material relative to the existing margins.
%   Either on or both values may be negative, in which
%   case the typeset material may protrude outside of the edges of the
%   galley.
% \end{TemplateDescription}
%
% \subsection{Layer three: paragraph shape}
%
% \begin{TemplateInterfaceDescription}{parshape}
%   \TemplateArgument{}{}^^A Some hack
%   \TemplateSemantics
%   Template of this type define any shaping of the paragraph within the
%   current measure of the galley. Thus they are used to generate
%   \enquote{special} paragraph shapes, for example placing a cutout
%   in one side of the paragraph. Typically, \texttt{parshape} templates
%   will apply in a limited sense (to a single paragraph or a defined number of
%   lines). However, \texttt{parshape} templates may also apply in an
%   \enquote{ongoing} manner.
%
%   Note that \texttt{parshape} templates do not alter any first-line
%   indent for paragraphs (or any other \enquote{in paragraph} setting).
%   Instead, they define a shape inside which the paragraph material will be
%   placed.
% \end{TemplateInterfaceDescription}
%
% \begin{TemplateDescription}{parshape}{hang}
%   \TemplateKey{indent}{length}
%     {^^A
%       The hanging indent from either the left- or right-hand margin
%       (as determined by \texttt{on-left-side}).^^A
%     }
%     {0pt}
%   \TemplateKey{on-left-side}{boolean}
%     {^^A
%       If \texttt{true}, causes the hanging indent to be on the left-hand
%       side of the paragraph.^^A
%     }
%     {true}
%   \TemplateKey{lines}{integer}
%     {The number of lines of full width before hanging begins.}
%     {1}
%  \TemplateSemantics
%  Sets the paragraph shape such that the after a number of full-width
%  lines, specified by |lines|, the paragraph is indented by the
%  |indent| from a margin. If |on-left-side| is |true| this indent will be
%  from the left-hand margin, otherwise it will be from the right. In either
%  case, the indent is relative to the edge of the current |measure| and
%  may be negative (in which case an outdent will result).
%  This template type applies only to a single paragraph.
% \end{TemplateDescription}
%
% \begin{TemplateDescription}{parshape}{initial}
%   \TemplateKey{indent}{length}
%     {^^A
%       The indent for the initial lines from either the left- or right-hand
%       margin (as determined by \texttt{on-left-side}).^^A
%     }
%     {0pt}
%   \TemplateKey{on-left-side}{boolean}
%     {^^A
%       If \texttt{true}, causes the indent to be on the left-hand
%       side of the paragraph.^^A
%     }
%     {true}
%   \TemplateKey{lines}{integer}
%     {The number of lines of indented lines before full-width line begins.}
%     {2}
%   \TemplateSemantics
%   Sets the paragraph shape such that the first |lines| lines
%   are indented by the |indent| given, before lines of full width begin.
%   If |on-left-side| is |true| this indent will be
%   from the left-hand margin, otherwise it will be from the right. In either
%   case, the indent is relative to the edge of the current |measure| and
%   may be negative (in which case an outdent will result).
%   This template type applies only to a single paragraph.
% \end{TemplateDescription}
%
% \begin{TemplateDescription}{parshape}{std}
%   \TemplateKey{}{}{}{} ^^A hack
%   \TemplateSemantics
%   Sets a rectangular paragraph shape which occupies the full width
%   specified by the |measure|. It is therefore intended as a
%   \enquote{do nothing} template for use where a paragraph shape is required
%   but where no special formatting is needed. This template type applies only
%   to a single paragraph.
% \end{TemplateDescription}
%
% \subsection{Layer four: formatting inside the paragraph}
%
% \begin{TemplateInterfaceDescription}{hyphenation}
%   \TemplateArgument{}{} ^^A Hack
%   \TemplateSemantics
%   Controls whether hyphenation is attempted within the current
%   galley. This object type may also alter the degree to which hyphenation
%   is encouraged by manipulating the underlying \TeX{} parameters. This
%   object type applies to the galley from the point of use forward.
% \end{TemplateInterfaceDescription}
%
% \begin{TemplateDescription}{hyphenation}{std}
%   \TemplateKey{enable}{boolean}
%     {Switches all hyphenation on or off.}
%     {true}
%   \TemplateKey{enable-upper-case}
%     {boolean}
%     {^^A
%       Switches hyphenation on or off for words beginning with upper case
%       letters.^^A
%     }
%     {true}
%   \TemplateKey{penalty}{choice}
%     {^^A
%       Sets the degree to which \TeX{} is discouraged from undertaking
%       hyphenation, from the choices |low|, |medium| and |high|.^^A
%     }
%     {low}
%   \TemplateSemantics
%   Determines both whether hyphenation is allowed at all, and if so to
%   what degree it is discouraged. Setting |penalty| to |high| does not
%   prevent hyphenation: this is only done if |enable| is set |false|.
% \end{TemplateDescription}
%
% \begin{TemplateInterfaceDescription}{justification}
%   \TemplateArgument{}{} ^^A Hack
%   \TemplateSemantics
%   Controls the nature of justification undertaken within the galley.
%   The template applies from the point of use forward.
% \end{TemplateInterfaceDescription}
%
% \begin{TemplateDescription}{justification}{std}
%   \TemplateKey{end-skip}{skip}
%     {The skip inserted to fill the last line of a paragraph.}
%     {0pt plus 1fil}
%   \TemplateKey{fixed-word-spacing}{boolean}
%     {^^A
%       Determines whether inter-word spacing has a stretch component (for
%       non-monospaced fonts.^^A
%     }
%     {false}
%   \TemplateKey{indent-width}{length}
%     {^^A
%       The length of the indent inserted at the start of the first line of a
%       new paragraph.^^A
%     }
%     {}
%   \TemplateKey{left-skip}{skip}
%     {^^A
%       The skip between the left margin of the galley and the left edge of a
%       paragraph.^^A
%     }
%     {0pt}
%   \TemplateKey{right-skip}{skip}
%     {^^A
%       The skip between the right margin of the galley and the right edge of a
%       paragraph.^^A
%     }
%     {0pt}
%   \TemplateKey{start-skip}{skip}
%     {^^A
%       The skip inserted in addition to |indent-width| at the start of a
%       paragraph.^^A
%     }
%     {0pt}
%   \TemplateSemantics
%   The |std| template for justification provides rubber lengths
%   at the start and end of the paragraph and at each side of the paragraph.
%   It also allows for both flexible and fixed inter-word spacing. The
%   interaction between the settings is demonstrated in the selection of
%   standard instances provided.
% \end{TemplateDescription}
%
% \begin{InstanceDescription}{justification}{justified}{std}
%   \InstanceKey{indent-width}{15pt}
%   \InstanceSemantics
%   Sets paragraphs fully-justified with the first line indented by
%   |15pt|.
% \end{InstanceDescription}
%
% \begin{InstanceDescription}{justification}{noindent}{std}
%   \InstanceKey{end-skip}{15pt plus 1fil}
%   \InstanceKey{indent-width}{0pt}
%   \InstanceSemantics
%   Sets paragraphs fully-justified with no indent for the first line. To
%   ensure that paragraphs have some visual distinction, the |end-skip| is
%   set to insert some space in all cases.
% \end{InstanceDescription}
%
% \begin{TemplateDescription}{justification}{single}
%   \TemplateKey{end-skip}{skip}
%     {The skip inserted to fill the last line of a paragraph.}
%     {0pt plus 1fil}
%   \TemplateKey{fixed-word-spacing}{boolean}
%     {^^A
%       Determines whether inter-word spacing has a stretch component (for
%       non-monospaced fonts.^^A
%     }
%     {false}
%   \TemplateKey{indent-width}{length}
%     {^^A
%       The length of the indent inserted at the start of the first line of a
%       new paragraph.^^A
%     }
%     {}
%   \TemplateKey{left-skip}{skip}
%     {^^A
%       The skip between the left margin of the galley and the left edge of a
%       paragraph.^^A
%     }
%     {0pt}
%   \TemplateKey{right-skip}{skip}
%     {^^A
%       The skip between the right margin of the galley and the right edge of a
%       paragraph.^^A
%     }
%     {0pt}
%   \TemplateKey{start-skip}{skip}
%     {^^A
%       The skip inserted in addition to |indent-width| at the start of a
%       paragraph.^^A
%     }
%     {0pt}
%   \TemplateKey{stretch-last-line}{boolean}
%     {
%       Determines whether inter-word spacing in the last line is stretched.
%       If \texttt{true}, the spacing in the last line is stretched in the
%       by the same factor as that in the penultimate line.^^A
%     }
%     {false}
%   \TemplateSemantics
%   The |single| template for justification provides rubber lengths
%   at the start and end of the paragraph and at each side of the paragraph.
%   It also allows for both flexible and fixed inter-word spacing. The
%   interaction between the settings is demonstrated in the selection of
%   standard instances provided. The template applies only to a single
%   paragraph.
% \end{TemplateDescription}
%
% \begin{InstanceDescription}[fixed-word-spacing-xxx]{justification}{ragged-left}{std}
%   \InstanceKey{end-skip}{0pt}
%   \InstanceKey{fixed-word-spacing}{true}
%   \InstanceKey{indent-width}{0pt}
%   \InstanceKey{left-skip}{0pt plus 2em}
%   \InstanceKey{right-skip}{0pt}
%   \InstanceSemantics
%   Typesets material with a ragged left margin such that hyphenation will
%   still occur and such that very short lines are discouraged. This is
%   similar to the \LaTeXe{} \pkg{ragged2e} \env{RaggedLeft} environment.
% \end{InstanceDescription}
%
% \begin{InstanceDescription}[fixed-word-spacing-xxx]{justification}{ragged-right}{std}
%   \InstanceKey{end-skip}{0pt}
%   \InstanceKey{fixed-word-spacing}{true}
%   \InstanceKey{indent-width}{0pt}
%   \InstanceKey{left-skip}{0pt}
%   \InstanceKey{right-skip}{0pt plus 2em}
%   \InstanceSemantics
%   Typesets material with a ragged right margin such that hyphenation will
%   still occur and such that very short lines are discouraged. This is
%   similar to the \LaTeXe{} \pkg{ragged2e} \env{RaggedLeft} environment.
% \end{InstanceDescription}
%
% \begin{InstanceDescription}[fixed-word-spacing-xxx]{justification}{center}{std}
%   \InstanceKey{end-skip}{0pt}
%   \InstanceKey{fixed-word-spacing}{true}
%   \InstanceKey{indent-width}{0pt}
%   \InstanceKey{left-skip}{0pt plus 1fil}
%   \InstanceKey{right-skip}{0pt plus 1fil}
%   \InstanceSemantics
%   Centers typeset material such that hyphenation is discouraged and short
%   lines are allowed.
% \end{InstanceDescription}
%
% \begin{TemplateDescription}{justification}{compound}
%   \TemplateKey{first-paragraph}{instance}
%     {Justification for the first paragraph.}
%     {}
%   \TemplateKey{other-paragraphs}{instance}
%     {Justification for the remaining paragraphs.}
%     {}
%   \TemplateSemantics
%   Here, both keys should themselves be instances of the |justification|
%   template. The |compound| template is used to set up a single
%   \enquote{non-standard} paragraph followed by \enquote{standard} ones.
%   For example, it can be used to ensure that one |noindent| paragraph is
%   then followed by |std| justification.
% \end{TemplateDescription}
%
% \begin{TemplateInterfaceDescription}{line-breaking}
%   \TemplateArgument{}{} ^^A Hack
%   \TemplateSemantics
%   Controls the line breaking attempted by \TeX{} when typesetting
%   material for the galley. This does not include whether words are
%   hyphenated, which is handled separately.
% \end{TemplateInterfaceDescription}
%
% \begin{TemplateDescription}{line-breaking}{std}
%   \TemplateKey{badness}{integer}
%      {^^A
%        Boundary that if exceeded will cause \TeX{} to report an
%        underfull line.^^A
%      }
%      {1000}
%   \TemplateKey{binop-penalty}{integer}
%      {^^A
%        Penalty charged if an inline math formula is broken at a
%        binary operator.^^A
%      }
%      {700}
%   \TemplateKey{double-hyphen-demerits}{integer}
%      {^^A
%        Extra demerit charge of two (or more) lines in succession end
%        in a hyphen.^^A
%      }
%      {10000}
%   \TemplateKey{emergency-stretch}{skip}
%      {^^A
%        Additional stretch assumed for each line if no better line breaking
%        can be found without it. This stretch is not actually added to lines,
%        so its use may result in underfull box warnings.^^A
%      }
%      {0pt}
%   \TemplateKey{final-hyphen-demerits}{integer}
%      {Extra demerit charge if the second last line is hyphenated.}
%      {5000}
%   \TemplateKey{fuzz}{length}
%      {Boundary below overfull lines are not reported.}
%      {0.1pt}
%   \TemplateKey{mismatch-demerits}{integer}
%      {^^A
%        Extra demerit charge if two visually incompatible lines follow
%        each other.^^A
%      }
%      {10000}
%   \TemplateKey{line-penalty}{integer}
%      {^^A
%        Extra penalty charged per line in the paragraph. By making
%        this penalty higher \TeX{} will try harder to produce compact
%        paragraphs.^^A
%      }
%      {10}
%   \TemplateKey{pretolerance}{integer}
%      {^^A
%        Maximum tolerance allowed for individual lines to break the
%        paragraph without attempting hyphenation.^^A
%      }
%      {100}
%   \TemplateKey{relation-penalty}{integer}
%      {^^A
%        Penalty charged if an inline math formula is broken at a
%        relational symbol.^^A
%      }
%      {500}
%   \TemplateKey{tolerance}{integer}
%      {^^A
%        Maximum tolerance allowed for individual lines when breaking a
%        paragraph while attempting hyphenation (if this limit can't be
%        met \texttt{emergency-stretch} comes into play).^^A
%      }
%      {200}
%   \TemplateSemantics
%   This is an interface to the underlying \TeX{} system for determining
%   line breaking.
% \end{TemplateDescription}
%
% \subsection{Between paragraphs}
%
% \begin{TemplateInterfaceDescription}{paragraph-breaking}
%   \TemplateArgument{}{} ^^A Hack
%   \TemplateSemantics
%   This object type determines how \TeX{} determines the behavior when
%   the paragraph-breaking algorithm is calculating whether to break up a
%   paragraph.  Thus for example an instance of this object type may prevent
%   breaks within a paragraph, forbid widows or orphans, etc.
% \end{TemplateInterfaceDescription}
%
% \begin{TemplateDescription}{paragraph-breaking}{std}
%   \TemplateKey{badness}{integer}
%      {^^A
%        Boundary that if exceeded will cause \TeX{} to report an
%        underfull vertical box.^^A
%      }
%      {1000}
%   \TemplateKey{broken-penalty}{integer}
%      {Penalty for page breaking after a hyphenated line.}
%      {100}
%   \TemplateKey{club-penalty}{integer}
%      {Penalty for generating a club line when page breaking.}
%      {150}
%   \TemplateKey{display-club-penalty}{integer}
%      {^^A
%        Penalty for breaking between to leave a club line after display
%        math.^^A
%      }
%      {150}
%   \TemplateKey{display-widow-penalty}{integer}
%      {^^A
%        Penalty for breaking between to leave a widow line before display
%        math.^^A
%      }
%      {150}
%   \TemplateKey{fuzz}{length}
%      {Boundary below which overfull vertical boxes are not reported.}
%      {0.1pt}
%   \TemplateKey{interline-penalty}{integer}
%      {Penalty for breaking between lines in a paragraph.}
%      {0}
%   \TemplateKey{pre-display-penalty}{integer}
%      {Penalty for breaking between immediately before display math material.}
%      {10000}
%   \TemplateKey{post-display-penalty}{integer}
%      {Penalty for breaking between immediately after display math material.}
%      {0}
%   \TemplateKey{widow-penalty}{integer}
%      {Penalty for generating a widow line when page breaking.}
%      {150}
%   \TemplateSemantics
%   This template provides an interface to the underlying \TeX{} mechanism for
%   controlling page breaking. The template applies on an ongoing basis to all
%   paragraphs after the template is used.
% \end{TemplateDescription}
%
% \begin{InstanceDescription}{paragraph-breaking}{std}{std}
%   \InstanceSemantics
%   Sets paragraphs such that they can break with widows and orphans
%   discouraged but not prevented. Breaks are possible after display math
%   material but no immediately before it.
% \end{InstanceDescription}
%
% \begin{InstanceDescription}[post-display-penalty-xxxx]{paragraph-breaking}{nobreak}{std}
%   \InstanceKey{interline-penalty}{10000}
%   \InstanceKey{post-display-penalty}{10000}
%   \InstanceSemantics
%   Sets paragraphs such that they cannot be broken at all (as far as is
%   possible in \TeX{}).
% \end{InstanceDescription}
%
% \begin{InstanceDescription}[post-display-penalty-xxxx]{paragraph-breaking}{nolone}{std}
%   \InstanceKey{club-penalty}{10000}
%   \InstanceKey{display-widow-penalty}{10000}
%   \InstanceKey{widow-penalty}{10000}
%   \InstanceSemantics
%   Sets paragraphs such that they cannot be broken to leave a club or
%   widow line (as far as is possible in \TeX{}).
% \end{InstanceDescription}
%
% \begin{TemplateDescription}{paragraph-breaking}{single}
%   \TemplateKey{badness}{integer}
%      {^^A
%        Boundary that if exceeded will cause \TeX{} to report an
%        underfull vertical box.^^A
%      }
%      {\meta{none}}
%   \TemplateKey{broken-penalty}{integer}
%      {Penalty for page breaking after a hyphenated line.}
%      {\meta{none}}
%   \TemplateKey{club-penalty}{integer}
%      {Penalty for generating a club line when page breaking.}
%      {\meta{none}}
%   \TemplateKey{display-club-penalty}{integer}
%      {^^A
%        Penalty for breaking between to leave a club line after display
%        math.^^A
%      }
%      {\meta{none}}
%   \TemplateKey{display-widow-penalty}{integer}
%      {^^A
%        Penalty for breaking between to leave a widow line before display
%        math.^^A
%      }
%      {\meta{none}}
%   \TemplateKey{fuzz}{length}
%      {Boundary below which overfull vertical boxes are not reported.}
%      {\meta{none}}
%   \TemplateKey{interline-penalty}{integer}
%      {Penalty for breaking between lines in a paragraph.}
%      {\meta{none}}
%   \TemplateKey{pre-display-penalty}{integer}
%      {Penalty for breaking between immediately before display math material.}
%      {\meta{none}}
%   \TemplateKey{post-display-penalty}{integer}
%      {Penalty for breaking between immediately after display math material.}
%      {\meta{none}}
%   \TemplateKey{widow-penalty}{integer}
%      {Penalty for generating a widow line when page breaking.}
%      {\meta{none}}
%   \TemplateSemantics
%   This template provides an interface to the underlying \TeX{} mechanism for
%   controlling page breaking. The template applies only to the next paragraph,
%   and can thus be used to achieve effects such as non-breaking paragraphs.
% \end{TemplateDescription}
%
% \begin{InstanceDescription}{paragraph-breaking}{single-std}{single}
%   \InstanceSemantics
%   Sets the next paragraph such that it can break with widows and orphans
%   discouraged but not prevented. Breaks are possible after display math
%   material but no immediately before it.
% \end{InstanceDescription}
%
% \begin{InstanceDescription}[post-display-penalty-xxx]{paragraph-breaking}{single-nobreak}{single}
%   \InstanceKey{interline-penalty}{10000}
%   \InstanceKey{post-display-penalty}{10000}
%   \InstanceSemantics
%   Sets the next paragraph such that it cannot be broken at all (as far as is
%   possible in \TeX{}).
% \end{InstanceDescription}
%
% \begin{InstanceDescription}[display-club-penalty-xxx]{paragraph-breaking}{single-noclub}{single}
%   \InstanceKey{club-penalty}{10000}
%   \InstanceKey{display-club-penalty}{10000}
%   \InstanceSemantics
%   Sets the next paragraph such that it cannot be broken to leave a club
%   line (as far as is possible in \TeX{}).
% \end{InstanceDescription}
%
% \begin{InstanceDescription}[display-widow-penalty-xxx]{paragraph-breaking}{single-nolone}{single}
%   \InstanceKey{club-penalty}{10000}
%   \InstanceKey{display-club-penalty}{10000}
%   \InstanceKey{display-widow-penalty}{10000}
%   \InstanceKey{widow-penalty}{10000}
%   \InstanceSemantics
%   Sets the next paragraph such that it cannot be broken to leave a club or
%   widow line (as far as is possible in \TeX{}).
% \end{InstanceDescription}
%
% \begin{InstanceDescription}[display-widow-penalty-xxx]{paragraph-breaking}{single-nowidow}{single}
%   \InstanceKey{display-widow-penalty}{10000}
%   \InstanceKey{widow-penalty}{10000}
%   \InstanceSemantics
%   Sets the next paragraph such that it cannot be broken to leave a
%   widow line (as far as is possible in \TeX{}).
% \end{InstanceDescription}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{xgalley} implementation}
%
% This module provided a template-level interface for the \LaTeX3 galley. As
% such, the code here is intended for design-level changes which apply to
% large blocks. The variables provided are therefore used only for supporting
% the templates, while any documented interfaces are in \pkg{l3galley}.
%
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%
%    \begin{macrocode}
%<@@=galley>
%    \end{macrocode}
%
%    \begin{macrocode}
\ProvidesExplPackage{xgalley}{2025-06-30}{}
  {L3 Experimental galley}
\RequirePackage{xtemplate,l3galley}
%    \end{macrocode}
%
% \subsection{Variables}
%
% \begin{variable}{\l_@@_tmpa_clist, \l_@@_tmpb_clist}
%   Scratch space.
%    \begin{macrocode}
\clist_new:N \l_@@_tmpa_clist
\clist_new:N \l_@@_tmpb_clist
%    \end{macrocode}
% \end{variable}
%
% \subsection{Layer two: internal dimensions}
%
% There is a single object type for level two, the \texttt{measure} for
% the text in the galley. There are no arguments, as the measure is a design
% concept.
%    \begin{macrocode}
\DeclareObjectType { measure } { 0 }
%    \end{macrocode}
%
% There are two templates for galley measures: absolute and relative.
% Both use the same interface.
%    \begin{macrocode}
\DeclareTemplateInterface { measure } { absolute } { 0 }
  {
    left-margin  : length = 0pt ,
    right-margin : length = 0pt
  }
\DeclareTemplateInterface { measure } { relative } { 0 }
  {
    left-margin  : length = 0pt ,
    right-margin : length = 0pt
  }
%    \end{macrocode}
%
% \begin{variable}{\l_@@_left_margin_dim, \l_@@_right_margin_dim}
%   In the \texttt{absolute} template, the two margin values are relative
%   to the edges of the galley. This means that any existing offset or
%   line-length adjustment are ignored.
%    \begin{macrocode}
%<*package>
\cs_new_eq:NN \l_@@_left_margin_dim \leftmargin
%</package>
%<*package>
\cs_new_eq:NN \l_@@_right_margin_dim \rightmargin
%</package>
\DeclareTemplateCode { measure } { absolute } { 0 }
  {
    left-margin  = \l_@@_left_margin_dim  ,
    right-margin = \l_@@_right_margin_dim
  }
  {
    \galley_margins_set_absolute:nn \l_@@_left_margin_dim
      \l_@@_right_margin_dim
  }
%    \end{macrocode}
% On the other hand, the \texttt{relative} template works relative to
% the current indentation at both sides.
%    \begin{macrocode}
\DeclareTemplateCode { measure } { relative } { 0 }
  {
    left-margin  = \l_@@_left_margin_dim  ,
    right-margin = \l_@@_right_margin_dim
  }
  {
    \galley_margins_set_relative:nn \l_@@_left_margin_dim
      \l_@@_right_margin_dim
  }
%    \end{macrocode}
% \end{variable}
%
% \subsection{Layer three: paragraph shape}
%
% The object type \texttt{parshape} is a somewhat extended interface
% to the \TeX{} \cs{tex_parshape:D} primitive. As with the \texttt{measure},
% the \texttt{parshape} template has no arguments as it is essentially a
% design-oriented concept.
%    \begin{macrocode}
\DeclareObjectType { parshape } { 0 }
%    \end{macrocode}
%
% There are two standard templates for paragraph shapes which do
% something, both with the same interface. The \texttt{hang} template
% provides one or more standard lines followed by a hanging paragraph,
% while the \texttt{initial} template cuts out a space at the start of
% the paragraph.
%    \begin{macrocode}
\DeclareTemplateInterface { parshape } { hang } { 0 }
  {
    indent       : length  = 0pt  ,
    on-left-side : boolean = true ,
    lines        : integer = 1
  }
\DeclareTemplateInterface { parshape } { initial } { 0 }
  {
    indent       : length  = 0pt  ,
    on-left-side : boolean = true ,
    lines        : integer = 2
  }
%    \end{macrocode}
% \begin{variable}{\l_@@_parshape_indent_dim}
% \begin{variable}{\l_@@_parshape_on_left_bool}
% \begin{variable}{\l_@@_parshape_lines_int}
%   Both of the templates are implemented as special cases of the more
%   general function defined earlier.
%    \begin{macrocode}
\DeclareTemplateCode { parshape } { hang } { 0 }
  {
    indent       = \l_@@_parshape_indent_dim   ,
    on-left-side = \l_@@_parshape_on_left_bool ,
    lines        = \l_@@_parshape_lines_int
  }
  {
    \bool_if:NTF \l_@@_parshape_on_left_bool
      {
        \galley_parshape_set_single:nVVN
          \l_@@_parshape_lines_int
          \l_@@_parshape_indent_dim
          \c_zero_dim
          \c_false_bool
      }
      {
        \galley_parshape_set_single:nVVN
          \l_@@_parshape_lines_int
          \c_zero_dim
          \l_@@_parshape_indent_dim
          \c_false_bool
      }
  }
\DeclareTemplateCode { parshape } { initial } { 0 }
  {
    indent       = \l_@@_parshape_indent_dim   ,
    on-left-side = \l_@@_parshape_on_left_bool ,
    lines        = \l_@@_parshape_lines_int
  }
  {
    \clist_clear:N \l_@@_tmpa_clist
    \clist_clear:N \l_@@_tmpb_clist
    \prg_replicate:nn { \l_@@_parshape_lines_int }
      {
        \clist_put_right:Nn \l_@@_tmpa_clist
          { \l_@@_parshape_indent_dim }
        \clist_put_right:Nn \l_@@_tmpb_clist
          { \c_zero_dim }
      }
    \bool_if:NTF \l_@@_parshape_on_left_bool
      {
        \galley_parshape_set_single:nVVN
          { 0 }
          \l_@@_tmpa_clist
          \l_@@_tmpb_clist
          \c_true_bool
      }
      {
        \galley_parshape_set_single:nVVN
          { 0 }
          \l_@@_tmpb_clist
          \l_@@_tmpa_clist
          \c_true_bool
      }
  }
%    \end{macrocode}
% \end{variable}
% \end{variable}
% \end{variable}
%
% There is also a \enquote{do nothing} paragraph shape for cases where
% a template is needed but no action is desirable.
%    \begin{macrocode}
\DeclareTemplateInterface { parshape } { std } { 0 } { }
\DeclareTemplateCode { parshape } { std } { 0 } { } { }
%    \end{macrocode}
%
% \subsection{Layer four: formatting inside the paragraph}
%
% The first type of object within a paragraph is the hyphenation. This
% object needs no arguments.
%    \begin{macrocode}
\DeclareObjectType { hyphenation } { 0 }
%    \end{macrocode}
%
% There is only hyphenation template as standard. This provides a
% semi-flexible interface to the underlying \TeX{} methods. (The detail
% is therefore hidden within the implementation phase.)
%    \begin{macrocode}
\DeclareTemplateInterface { hyphenation } { std } { 0 }
  {
    enable            : boolean                        = true ,
    enable-upper-case : boolean                        = true ,
    penalty           : choice { low , medium , high } = low
  }
%    \end{macrocode}
% The implementation for hyphenation mainly sets low-level values.
% The minimum number of characters after a hyphen is set directly,
% whereas the number before is not. This is so that
% \cs{tex_lefthyphenmin:D} can also be used to completely prevent
% hyphenation.
%    \begin{macrocode}
\DeclareTemplateCode { hyphenation } { std } { 0 }
  {
    enable            = \l_galley_hyphen_enable_bool    ,
    enable-upper-case = \l_galley_hyphen_uppercase_bool ,
    penalty           =
      {
        low    =
          {
            \int_set:Nn \tex_hyphenpenalty:D   { 51 }
            \int_set:Nn \tex_exhyphenpenalty:D { 51 }
          } ,
        medium =
          {
            \int_set:Nn \tex_hyphenpenalty:D   { 151 }
            \int_set:Nn \tex_exhyphenpenalty:D { 151 }
          } ,
        high   =
          {
            \int_set:Nn \tex_hyphenpenalty:D   { 301 }
            \int_set:Nn \tex_exhyphenpenalty:D { 301 }
          } ,
      }
  }
  {
    \int_set:Nn \tex_lefthyphenmin:D
      {
        \bool_if:NTF \l_galley_hyphen_enable_bool
          { \l_galley_hyphen_left_int  }
          { 63 }
      }
    \int_set:Nn \tex_uchyph:D
      {
        \bool_if:NTF \l_galley_hyphen_uppercase_bool
          { 1 }
          { 0 }
      }
  }
%    \end{macrocode}
% At this stage, the default hyphenation character should be set and
% hyphenation should be enabled.
%    \begin{macrocode}
\UseTemplate { hyphenation } { std } { }
\tex_defaulthyphenchar:D 45 \scan_stop:
%    \end{macrocode}
%
% \begin{variable}{\l_@@_justification_other_tl}
%   Used for the reset system for justification: using this token list means
%   that there is no need to remove anything from
%   \cs{g_galley_restore_running_tl}.
%    \begin{macrocode}
\tl_new:N \l_@@_justification_other_tl
%    \end{macrocode}
% \end{variable}
%
% The second level four object is the justification, which again
% takes no arguments.
%    \begin{macrocode}
\DeclareObjectType { justification } { 0 }
%    \end{macrocode}
% There are two templates here with the same interface: the standard one
% to apply from this point onward, and one which applies only to a single
% paragraph.
%    \begin{macrocode}
\DeclareTemplateInterface { justification } { std } { 0 }
  {
    end-skip           : skip    = 0pt plus 1fil ,
    fixed-word-spacing : boolean = false         ,
    indent-width       : length                  ,
    left-skip          : skip    = 0pt           ,
    right-skip         : skip    = 0pt           ,
    start-skip         : skip    = 0pt           ,
    stretch-last-line  : boolean = false
  }
\DeclareTemplateInterface { justification } { single } { 0 }
  {
    end-skip           : skip    = 0pt plus 1fil ,
    fixed-word-spacing : boolean = false         ,
    indent-width       : length                  ,
    left-skip          : skip    = 0pt           ,
    right-skip         : skip    = 0pt           ,
    start-skip         : skip    = 0pt           ,
    stretch-last-line  : boolean = false
  }
%    \end{macrocode}
% \begin{variable}{\l_galley_fixed_spacing_bool}
%   The implementation here is pretty simple as almost everything that
%   goes on is a simple case of saving the settings, which are then
%   applied either by \TeX{} itself or the rest of the galley system.
%    \begin{macrocode}
\DeclareTemplateCode { justification } { std } { 0 }
  {
    end-skip           = \l_galley_par_end_skip          ,
    fixed-word-spacing = \l_galley_fixed_spacing_bool    ,
    indent-width       = \l_galley_par_indent_dim        ,
    left-skip          = \l_galley_line_left_skip        ,
    right-skip         = \l_galley_line_right_skip       ,
    start-skip         = \l_galley_par_begin_skip        ,
    stretch-last-line  = \l_galley_par_stretch_last_bool
  }
  {
    \tl_clear:N \l_@@_justification_other_tl
    \galley_interword_spacing_set:N \l_galley_fixed_spacing_bool
    \bool_if:NTF \l_galley_par_stretch_last_bool
      { \int_set:Nn \l_galley_last_line_fit_int { 1000 } }
      { \int_zero:N \l_galley_last_line_fit_int }
    \skip_set:Nn \@rightskip { \l_galley_line_right_skip }
  }
%    \end{macrocode}
% \end{variable}
% To deal with a single paragraph, the approach used is to save the current
% settings to the paragraph-reset code, then to assign the template in the
% same way as for the |std| template.
%    \begin{macrocode}
\DeclareTemplateCode { justification } { single } { 0 }
  {
    end-skip           = \l_galley_par_end_skip         ,
    fixed-word-spacing = \l_galley_fixed_spacing_bool   ,
    indent-width       = \l_galley_par_indent_dim       ,
    left-skip          = \l_galley_line_left_skip       ,
    right-skip         = \l_galley_line_right_skip      ,
    start-skip         = \l_galley_par_begin_skip       ,
    stretch-last-line  = \l_galley_par_stretch_last_bool
  }
  {
    \tl_put_left:Ne \l_@@_justification_other_tl
      {
        \skip_set:Nn \exp_not:N \l_galley_par_end_skip
          { \skip_use:N \l_galley_par_end_skip }
        \bool_if:NTF \l_galley_fixed_spacing_bool
          { \bool_set_true:N  \exp_not:N \l_galley_fixed_spacing_bool }
          { \bool_set_false:N \exp_not:N \l_galley_fixed_spacing_bool }
        \galley_interword_spacing_set:N
          \exp_not:N \l_galley_fixed_spacing_bool
        \dim_set:Nn \exp_not:N \l_galley_par_indent_dim
          { \dim_use:N \l_galley_par_indent_dim  }
        \skip_set:Nn \l_galley_line_left_skip
          { \skip_use:N \l_galley_line_left_skip }
        \skip_set:Nn \exp_not:N \l_galley_line_right_skip
          { \skip_use:N \l_galley_line_right_skip }
        \skip_set:Nn \exp_not:N \l_galley_par_begin_skip
          { \skip_use:N \l_galley_par_begin_skip }
        \int_set:Nn \exp_not:N \l_galley_last_line_fit_int
          { \int_use:N \l_galley_last_line_fit_int }
        \skip_set:Nn \exp_not:N \@rightskip
          { \skip_use:N \l_galley_line_right_skip }
      }
    \tl_gput_right:Nn \g_galley_restore_running_tl
      { \l_@@_justification_other_tl }
    \AssignTemplateKeys
    \galley_interword_spacing_set:N \l_galley_fixed_spacing_bool
    \bool_if:NTF \l_galley_par_stretch_last_bool
      { \int_set:Nn \l_galley_last_line_fit_int { 1000 } }
      { \int_zero:N \l_galley_last_line_fit_int }
    \skip_set:Nn \@rightskip { \l_galley_line_right_skip }
  }
%    \end{macrocode}
% The standard instance for justification is very simple to set up as
% the default values for the template are set up for exactly this case.
% The advantage of this scheme is that at a design level altering the
% indent used for justified paragraphs is very easy to do. As this is
% the standard template for all \LaTeX3 documents, it is applied here.
%    \begin{macrocode}
\DeclareInstance { justification } { justified } { std }
  { indent-width = 15pt }
\UseInstance { justification } { justified }
%    \end{macrocode}
% The instance for no indentation at all but with justified text is
% intended for layouts which leave white space between paragraphs. With
% no indentation, some space has to be included at the end of each
% paragraph. This is set up to mirror the indent that has been removed.
%    \begin{macrocode}
\DeclareInstance { justification } { noindent } { std }
  {
    end-skip     = 15pt plus 1fil ,
    indent-width = 0pt
  }
%    \end{macrocode}
% The other standard justification schemes are for text which ragged.
% The settings here are taken from the \LaTeXe{}
% \pkg{ragged2e} package, as they maintain a reasonable appearance by
% ensuring that \TeX{} will not be too tolerant of very short lines.
% To keep the design clear here, no default values are relied on even
% though this would make the instance declarations shorter.
%    \begin{macrocode}
\DeclareInstance { justification } { ragged-left } { std }
  {
    end-skip           = 0pt           ,
    fixed-word-spacing = true          ,
    indent-width       = 0pt           ,
    left-skip          = 0pt plus 2em  ,
    right-skip         = 0pt
  }
\DeclareInstance { justification } { ragged-right } { std }
  {
    end-skip           = 0pt plus 1fil ,
    fixed-word-spacing = true          ,
    indent-width       = 0pt           ,
    left-skip          = 0pt           ,
    right-skip         = 0pt plus 2em
  }
%    \end{macrocode}
% The \texttt{center} instance is used to center material with minimal
% hyphenation.
%    \begin{macrocode}
\DeclareInstance { justification } { center } { std }
  {
    end-skip           = 0pt           ,
    fixed-word-spacing = true          ,
    indent-width       = 0pt           ,
    left-skip          = 0pt plus 1fil ,
    right-skip         = 0pt plus 1fil
  }
%    \end{macrocode}
%
% \begin{macro}{\@@_justification_first:, \@@_justification_other:}
%   A second form of justification template is the case where the first
%   paragraph is different from all of the others. This is set up by
%   getting the justification to reset itself after the first paragraph.
%   The code built into the \texttt{std} version will ensure that any
%   subsequent template use will over-ride the setting here correctly.
%    \begin{macrocode}
\DeclareTemplateInterface { justification } { compound } { 0 }
  {
    first-paragraph  : instance { justification } ,
    other-paragraphs : instance { justification }
  }
\DeclareTemplateCode { justification } { compound } { 0 }
  {
    first-paragraph  = \@@_justification_first: ,
    other-paragraphs = \@@_justification_other:
  }
  {
    \@@_justification_first:
    \tl_set:Nn \l_@@_justification_other_tl
      { \@@_justification_other: }
    \tl_gput_right:Nn \g_galley_restore_running_tl
      { \l_@@_justification_other_tl }
  }
%    \end{macrocode}
% \end{macro}
%
% How \TeX{} breaks text into lines is influences by a number of
% parameters, most of which are not actually likely to change. These
% work with the \texttt{hyphenation} but are independent of whether
% any hyphenation is actually active. The math values here could be
% set up as a separate template, but in practice this seems likely to
% be overkill.
%    \begin{macrocode}
\DeclareObjectType { line-breaking } { 0 }
%    \end{macrocode}
% The only template provided for line breaking is a simple interface to
% \TeX{}'s parameters. There is not really much that can be added to this:
% after all, the way that penalties work is more or less arbitrary but
% works well! The default values given here are intended to be sensible
% for a lot of cases.
%    \begin{macrocode}
\DeclareTemplateInterface { line-breaking } { std } { 0 }
  {
    badness                : integer = 1000  ,
    binop-penalty          : integer = 700   ,
    double-hyphen-demerits : integer = 10000 ,
    emergency-stretch      : skip    = 0pt   ,
    final-hyphen-demerits  : integer = 5000  ,
    fuzz                   : length  = 0.1pt ,
    line-penalty           : integer = 10    ,
    mismatch-demerits      : integer = 10000 ,
    pretolerance           : integer = 100   ,
    relation-penalty       : integer = 500   ,
    tolerance              : integer = 200
  }
\DeclareTemplateCode{ line-breaking } { std } { 0 }
  {
    badness                = \l_galley_linebreak_badness_int      ,
    binop-penalty          = \l_@@_binop_penalty_int          ,
    double-hyphen-demerits = \l_galley_double_hyphen_demerits_int ,
    emergency-stretch      = \l_galley_emergency_stretch_skip     ,
    final-hyphen-demerits  = \l_galley_final_hyphen_demerits_int  ,
    fuzz                   = \l_galley_linebreak_fuzz_dim         ,
    line-penalty           = \l_@@_linebreak_penalty_int      ,
    mismatch-demerits      = \l_galley_mismatch_demerits_int      ,
    pretolerance           = \l_galley_linebreak_pretolerance_int ,
    relation-penalty       = \l_@@_relation_penalty_int       ,
    tolerance              = \l_galley_linebreak_tolerance_int
  }
  { }
%    \end{macrocode}
% The default values are set such that they are suitable for good
% quality typesetting. So the standard template changes nothing at
% all from the template. This instance should also be applied now,
% as it will then apply to the entire document unless changed
% deliberately.
%    \begin{macrocode}
\DeclareInstance { line-breaking } { std } { std } { }
\UseInstance { line-breaking } { std }
%    \end{macrocode}
%
% \subsection{Between paragraphs}
%
% \begin{variable}
%   {
%     \l_@@_club_penalty_int          ,
%     \l_@@_display_club_penalty_int  ,
%     \l_@@_display_widow_penalty_int ,
%     \l_@@_interline_penalty_int     ,
%     \l_@@_widow_penalty_int
%   }
%   The second object here sets up how \TeX{} acts to break paragraphs at
%   page boundaries. As with the \texttt{line-breaking} object, there is not
%   much to do except provide an interface to the \TeX{} internals. The
%   \texttt{std} template does \emph{not} make the \eTeX{} array nature of
%   various penalties available.
%    \begin{macrocode}
\DeclareObjectType { paragraph-breaking } { 0 }
\DeclareTemplateInterface { paragraph-breaking } { std } { 0 }
  {
    badness               : integer = 1000  ,
    broken-penalty        : integer = 100   ,
    club-penalty          : integer = 150   ,
    display-club-penalty  : integer = 150   ,
    display-widow-penalty : integer = 150   ,
    fuzz                  : length  = 0.1pt ,
    interline-penalty     : integer = 0     ,
    post-display-penalty  : integer = 0     ,
    pre-display-penalty   : integer = 10000 ,
    widow-penalty         : integer = 150
  }
\DeclareTemplateCode { paragraph-breaking } { std } { 0 }
  {
    badness               = \l_galley_parbreak_badness_int      ,
    broken-penalty        = \l_@@_broken_penalty_int        ,
    club-penalty          = \l_@@_club_penalty_int          ,
    display-club-penalty  = \l_@@_display_club_penalty_int  ,
    display-widow-penalty = \l_@@_display_widow_penalty_int ,
    fuzz                  = \l_galley_parbreak_fuzz_dim         ,
    interline-penalty     = \l_@@_interline_penalty_int     ,
    post-display-penalty  = \l_@@_post_display_penalty_int  ,
    pre-display-penalty   = \l_@@_pre_display_penalty_int   ,
    widow-penalty         = \l_@@_widow_penalty_int
  }
  {
    \galley_club_penalties_set:V          \l_@@_club_penalty_int
    \galley_display_club_penalties_set:V  \l_@@_display_club_penalty_int
    \galley_display_widow_penalties_set:V \l_@@_display_widow_penalty_int
    \galley_interline_penalty_set:n       \l_@@_interline_penalty_int
    \galley_widow_penalties_set:V         \l_@@_widow_penalty_int
  }
%    \end{macrocode}
% \end{variable}
% The standard instance of the \texttt{paragraph-breaking} object simply
% applies the defaults: this is used.
%    \begin{macrocode}
\DeclareInstance { paragraph-breaking } { std } { std } { }
\UseInstance { paragraph-breaking } { std }
%    \end{macrocode}
% Two additional instances are provided: one to prevent any breaks
% at all, and a second to prevent any widow or club lines.
%    \begin{macrocode}
\DeclareInstance { paragraph-breaking } { nobreak } { std }
  {
    interline-penalty    = 10 000 ,
    post-display-penalty = 10 000
  }
\DeclareInstance { paragraph-breaking } { nolone } { std }
  {
    club-penalty          = 10 000 ,
    display-club-penalty  = 10 000 ,
    display-widow-penalty = 10 000 ,
    widow-penalty         = 10 000
  }
%    \end{macrocode}
% \begin{variable}
%   {
%     \l_@@_parbreak_badness_tl        ,
%     \l_@@_broken_penalty_tl          ,
%     \l_@@_club_penalties_tl          ,
%     \l_@@_display_club_penalties_tl  ,
%     \l_@@_display_widow_penalties_tl ,
%     \l_@@_parbreak_fuzz_tl           ,
%     \l_@@_interline_penalty_tl       ,
%     \l_@@_post_display_penalty_tl    ,
%     \l_@@_pre_display_penalty_tl     ,
%     \l_@@_widow_penalties_tl         ,
%     \c_@@_parbreak_multi_seq         ,
%     \c_@@_parbreak_single_seq
%   }
%   There is also a version of this code which applies only to one
%   paragraph. This is done by storing the input in token list variables
%   with no default: only explicit settings will be picked up.
%    \begin{macrocode}
\DeclareTemplateInterface { paragraph-breaking } { single } { 0 }
  {
    badness               : tokenlist ,
    broken-penalty        : tokenlist ,
    club-penalty          : tokenlist ,
    display-club-penalty  : tokenlist ,
    display-widow-penalty : tokenlist ,
    fuzz                  : tokenlist ,
    interline-penalty     : tokenlist ,
    post-display-penalty  : tokenlist ,
    pre-display-penalty   : tokenlist ,
    widow-penalty         : tokenlist
  }
\DeclareTemplateCode { paragraph-breaking } { single } { 0 }
  {
    badness               = \l_@@_parbreak_badness_tl        ,
    broken-penalty        = \l_@@_broken_penalty_tl          ,
    club-penalty          = \l_@@_club_penalties_tl          ,
    display-club-penalty  = \l_@@_display_club_penalties_tl  ,
    display-widow-penalty = \l_@@_display_widow_penalties_tl ,
    fuzz                  = \l_@@_parbreak_fuzz_tl           ,
    interline-penalty     = \l_@@_interline_penalty_tl       ,
    post-display-penalty  = \l_@@_post_display_penalty_tl    ,
    pre-display-penalty   = \l_@@_pre_display_penalty_tl     ,
    widow-penalty         = \l_@@_widow_penalties_tl
  }
  {
%    \end{macrocode}
%   The fuzz and interline penalties are handled explicitly as they have
%   particular requirements.
%    \begin{macrocode}
    \tl_if_empty:NF \l_@@_interline_penalty_tl
      {
        \tl_gput_right:Ne \g_galley_par_reset_hook_tl
          {
            \int_set:Nn \exp_not:N \l_@@_interline_penalty_int
              { \galley_interline_penalty: }
          }
        \int_set:Nn \l_@@_interline_penalty_int
          { \l_@@_interline_penalty_tl }
      }
    \tl_if_empty:NF \l_@@_parbreak_fuzz_tl
      {
        \tl_gput_right:Ne \g_galley_par_reset_hook_tl
          {
            \dim_set:Nn \exp_not:N \l_galley_parbreak_fuzz_dim
              { \dim_use:N \l_galley_parbreak_fuzz_dim }
          }
        \dim_set:Nn \l_galley_parbreak_fuzz_dim { \l_@@_parbreak_fuzz_tl }
      }
%    \end{macrocode}
%  For the single integer penalties, a simple check is needed to save the
%  value.
%    \begin{macrocode}
    \seq_map_inline:Nn \c_@@_parbreak_single_seq
      {
        \tl_if_empty:cF { l_galley_ ##1 _tl }
          {
            \tl_gput_right:Ne \g_galley_par_reset_hook_tl
              {
                \int_set:Nn \exp_not:c { l_galley_ ##1 _int }
                  { \int_use:c { l_galley_ ##1 _int } }
              }
            \int_set:cn { l_galley_ ##1 _int }
              { \tl_use:c { l_galley_ ##1 _tl } }
          }
      }
%    \end{macrocode}
%   A bit more complex for the array penalties. Although the interface here
%   does not expose the arrays, it is necessary to correctly save them.
%   We suspend debugging to allow an assignment to a constant.
%    \begin{macrocode}
    \seq_map_inline:Nn \c_@@_parbreak_multi_seq
      {
        \tl_if_empty:cF { l_galley_ ##1 _tl }
          {
            \use:c { galley_save_ ##1 :N } \l_@@_tmpa_clist
            \tl_gput_right:Ne \g_galley_par_reset_hook_tl
              {
                \exp_not:c { galley_set_ ##1 :n }
                  { \exp_not:o \l_@@_tmpa_clist }
              }
            \use:c { galley_set_ ##1 :v } { l_galley_ ##1 _tl }
          }
      }
  }
\seq_const_from_clist:Nn \c_@@_parbreak_multi_seq
  {
    club_penalties ,
    display_club_penalties ,
    display_widow_penalties ,
    widow_penalties ,
  }
\seq_const_from_clist:Nn \c_@@_parbreak_single_seq
  {
    parbreak_badness ,
    broken_penalty ,
    post_display_penalty ,
    pre_display_penalty ,
  }
%    \end{macrocode}
% \end{variable}
%    \begin{macrocode}
\DeclareInstance { paragraph-breaking } { single-std } { single } { }
\DeclareInstance { paragraph-breaking } { single-nobreak } { single }
  {
    interline-penalty    = 10 000 ,
    post-display-penalty = 10 000
  }
\DeclareInstance { paragraph-breaking } { single-noclub } { single }
  {
    club-penalty         = 10 000 ,
    display-club-penalty = 10 000
  }
\DeclareInstance { paragraph-breaking } { single-nolone } { single }
  {
    club-penalty          = 10 000 ,
    display-club-penalty  = 10 000 ,
    display-widow-penalty = 10 000 ,
    widow-penalty         = 10 000
  }
\DeclareInstance { paragraph-breaking } { single-nowidow } { single }
  {
    display-widow-penalty = 10 000 ,
    widow-penalty         = 10 000
  }
%    \end{macrocode}
%
% \subsection{Templates for display material}
%
% To allow special handling of display-like material, templates are
% needed at the beginning and end of the block which set up any special
% space or breaks. These need to be optional, and so are stored as token
% lists: rather than \enquote{magic} values, empty lists indicate that
% standard settings are to be used. To ensure that the error checking
% needed takes place early, each token list is re-set with the
% appropriate evaluation.
%    \begin{macrocode}
\DeclareObjectType { display-begin } { 0 }
\DeclareObjectType { display-end }   { 0 }
\DeclareTemplateInterface { display-begin } { std } { 0 }
  {
    par-penalty : tokenlist ,
    par-space   : tokenlist ,
    penalty     : tokenlist ,
    space       : tokenlist
  }
\DeclareTemplateInterface { display-end } { std } { 0 }
  {
    par-penalty : tokenlist ,
    par-space   : tokenlist ,
    penalty     : tokenlist ,
    space       : tokenlist
  }
\DeclareTemplateCode { display-begin } { std } { 0 }
  {
    par-penalty = \l_galley_display_begin_par_vpenalty_tl ,
    par-space   = \l_galley_display_begin_par_vspace_tl   ,
    penalty     = \l_galley_display_begin_vpenalty_tl     ,
    space       = \l_galley_display_begin_vspace_tl
  }
  {
    \tl_if_empty:NF \l_galley_display_begin_par_vpenalty_tl
      {
        \tl_set:Ne \l_galley_display_begin_par_vpenalty_tl
          { \int_eval:n { \l_galley_display_begin_par_vpenalty_tl } }
      }
    \tl_if_empty:NF \l_galley_display_begin_par_vspace_tl
      {
        \tl_set:Ne \l_galley_display_begin_par_vspace_tl
          { \skip_eval:n { \l_galley_display_begin_par_vspace_tl } }
      }
    \tl_if_empty:NF \l_galley_display_begin_vpenalty_tl
      {
        \tl_set:Ne \l_galley_display_begin_vpenalty_tl
          { \int_eval:n { \l_galley_display_begin_vpenalty_tl } }
      }
    \tl_if_empty:NF \l_galley_display_begin_vspace_tl
      {
        \tl_set:Ne \l_galley_display_begin_vspace_tl
          { \skip_eval:n { \l_galley_display_begin_vspace_tl } }
      }
  }
\DeclareTemplateCode { display-end } { std } { 0 }
  {
    par-penalty = \l_galley_display_end_par_vpenalty_tl ,
    par-space   = \l_galley_display_end_par_vspace_tl   ,
    penalty     = \l_galley_display_end_vpenalty_tl     ,
    space       = \l_galley_display_end_vspace_tl
  }
  {
    \tl_if_empty:NF \l_galley_display_end_par_vpenalty_tl
      {
        \tl_set:Ne \l_galley_display_end_par_vpenalty_tl
          { \int_eval:n { \l_galley_display_end_par_vpenalty_tl } }
      }
    \tl_if_empty:NF \l_galley_display_end_par_vspace_tl
      {
        \tl_set:Ne \l_galley_display_end_par_vspace_tl
          { \skip_eval:n { \l_galley_display_end_par_vspace_tl } }
      }
    \tl_if_empty:NF \l_galley_display_end_vpenalty_tl
      {
        \tl_set:Ne \l_galley_display_end_vpenalty_tl
          { \int_eval:n { \l_galley_display_end_vpenalty_tl } }
      }
    \tl_if_empty:NF \l_galley_display_end_vspace_tl
      {
        \tl_set:Ne \l_galley_display_end_vspace_tl
          { \skip_eval:n { \l_galley_display_end_vspace_tl } }
      }
  }
%    \end{macrocode}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
