diff options
author | Karl Berry <karl@freefriends.org> | 2011-10-10 21:53:20 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2011-10-10 21:53:20 +0000 |
commit | 8fdc0d5c9ee743261c162302bdafbb83f9cfb542 (patch) | |
tree | 05e2062f23f57880ed2e0a26ad898e81b9d813be /Master/texmf-dist/source/latex/l3experimental/xgalley | |
parent | d2d088ff389655c2c3aad324760138895af2a9d3 (diff) |
l3experimental 2900 (10oct11)
git-svn-id: svn://tug.org/texlive/trunk@24258 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3experimental/xgalley')
3 files changed, 3783 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx b/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx new file mode 100644 index 00000000000..fa54ac37e59 --- /dev/null +++ b/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx @@ -0,0 +1,2140 @@ +% \iffalse +% +%% File: l3galley.dtx Copyright (C) 1999-2001, 2004-2009 Frank Mittelbach +%% (C) 2010,2011 The LaTeX3 Project +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This file is part of the "l3experimental bundle" (The Work in LPPL) +%% and all files in that bundle must be distributed together. +%% +%% The released version of this bundle is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the bundle can be found at +%% +%% http://www.latex-project.org/svnroot/experimental/trunk/ +%% +%% for those people who are interested. +%% +%%%%%%%%%%% +%% NOTE: %% +%%%%%%%%%%% +%% +%% Snapshots taken from the repository represent work in progress and may +%% not work or may contain conflicting material! We therefore ask +%% people _not_ to put them into distributions, archives, etc. without +%% prior consultation with the LaTeX Project Team. +%% +%% ----------------------------------------------------------------------- +%% +% +%<*driver|package> +\RequirePackage{l3names} +\GetIdInfo$Id: l3galley.dtx 2899 2011-10-09 21:22:06Z joseph $ + {L3 Experimental galley code} +%</driver|package> +%<*driver> +\documentclass[full]{l3doc} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{^^A +% The \textsf{l3galley} package\\ Galley code^^A +% \thanks{This file describes v\ExplFileVersion, +% last revised \ExplFileDate.}^^A +% } +% +% \author{^^A +% The \LaTeX3 Project\thanks +% {^^A +% E-mail: +% \href{mailto:latex-team@latex-project.org} +% {latex-team@latex-project.org}^^A +% }^^A +% } +% +% \date{Released \ExplFileDate} +% +% \maketitle +% +% \begin{documentation} +% +% \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 behaviour. +% +% 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}}). This +% layer is somewhat distinct from the galley as such, but is handled in +% the same place as there is, internally, interaction between the different +% layers. +% +% \section{Code interfaces} +% +% \subsection{Galley layers} +% +% \begin{variable}{\l_galley_width_dim} +% The total width of a galley, set either by the page geometry code +% for the main vertical galley or when creating an independent galley, +% such as a minipage. +% \end{variable} +% +% \begin{function}{\galley_level:} +% \begin{syntax} +% \cs{galley_level:} +% \end{syntax} +% Sets up a vertical box to contain a new galley level. The box should +% be \enquote{colour safe}, which is automatic for \LaTeX3 coffins but +% must be included manually (using \cs{color_group_begin:} and +% \cs{color_group_end:}) in \enquote{raw} vertical boxes. +% \end{function} +% +% \subsection{Measure} +% +% \begin{function} +% {\galley_margins_set_absolute:nn, \galley_margins_set_relative:nn} +% \begin{syntax} +% \cs{galley_margins_set_absolute:nn} \Arg{left margin} \Arg{right margin} +% \cs{galley_margins_set_relative:nn} \Arg{left margin} \Arg{right margin} +% \end{syntax} +% Sets the width of the measure to have the \meta{left margin} and +% \meta{right margin} specified by the arguments, both of which are +% \meta{dimension expressions}. The \texttt{relative} function will adjust +% the text width within any existing margins, whereas the \texttt{absolute} +% measure sets the margins based on the edges of the galley only. One or +% both of the \meta{margins} may be negative, to specify and outdent. +% \end{function} +% +% \subsection{Between paragraphs} +% +% \begin{variable}{\g_galley_restore_running_tl} +% When galley settings need to be reset at the end of a paragraph, the +% appropriate detail should be added to this token list. It is inserted +% immediately before the start of each paragraph, and can therefore be +% used to clear otherwise global settings. The token list itself is +% also cleared as part of this process. +% \end{variable} +% +% \begin{variable}{\g_galley_no_break_next_bool} +% Indicates that no page break should be allowed between the current +% paragraph and the next paragraph. +% \end{variable} +% +% \begin{function}{\g_galley_omit_next_indent_bool} +% Indicates that the indent should be omitted from the start of the next +% paragraph started. +% \end{function} +% +% \begin{variable}{\l_galley_interpar_penalty_int} +% The \meta{penalty} for a break between paragraphs. The \meta{penalty} +% should be in the range $-10\,000$ to $10\,000$, where $-10\,000$ forces a +% page break, $0$ has no effect at all and $10\,000$ forbids a page break. +% Note that setting \cs{g_galley_no_break_next_bool} to \texttt{true} +% will override any setting of \cs{l_galley_interpar_penalty_int}. +% \end{variable} +% +% \begin{variable}{\l_galley_interpar_vspace_skip} +% Stretchable space to be inserted between paragraphs, set at the design +% or template level. +% \end{variable} +% +% \begin{function}{\galley_set_user_penalty:n} +% \begin{syntax} +% \cs{galley_set_user_penalty:n} \Arg{penalty} +% \end{syntax} +% Sets the \meta{penalty} for a break between the current and next +% paragraph on a one-off basis. This function is intended for user-level +% adjustments to design, and takes precedent over both settings from +% \cs{galley_set_penalty:n} and from \cs{galley_no_break_next:}. +% \end{function} +% +% \begin{function}{\galley_set_user_vspace:n} +% \begin{syntax} +% \cs{galley_set_user_vspace:n} \Arg{space} +% \end{syntax} +% Sets the \meta{space} f to be inserted between the current and next +% paragraph on a one-off basis. This function is intended for user-level +% adjustments to design, and otherwise is analogous to +% \cs{galley_set_vspace:n}. +% \end{function} +% +% \subsection{Paragraph shape} +% +% \begin{function} +% { +% \galley_parshape_multi_par:nnnN, +% \galley_parshape_multi_par:nVVN, +% \galley_parshape_single_par:nnnN, +% \galley_parshape_single_par:nVVN +% } +% \begin{syntax} +% \cs{galley_parshape_multi_par:nnnN} \Arg{unaltered lines} \Arg{left indents} \Arg{right indents} \meta{resume flag} +% \cs{galley_parshape_single_par:nnnN} \Arg{unaltered lines} \Arg{left indents} \Arg{right indents} \meta{resume flag} +% \end{syntax} +% Sets the current paragraph shape to create an arbitrary paragraph shape. +% The paragraph shape is set such that there are \meta{unaltered lines} which +% have width and indent as set by the measure. The \enquote{altered} lines +% are then defined by the comma-separated lists of \meta{left indents} and +% \meta{right indents}. These are both indents from the edge of the measure, +% and may be negative, and should both contain the same number of items. +% If the \meta{resume flag} is \texttt{true}, after the last +% altered line the paragraph shape returns to that of the measure. On the +% other hand, if the flag is \texttt{false} then the shape of the last line +% is retained for the rest of the paragraph. +% For example, +% \begin{verbatim} +% \galley_parshape_set_multi_par:nnnN { 1 } +% { 2 pt , 4 pt , 6 pt } { 2 pt , 4 pt , 6 pt } \c_true_bool +% \end{verbatim} +% would create a paragraph shape in which the first line is the full +% width of the measure, the second line is indented by $2$\,pt on each side, +% the third line by by $4$\,pt and the fourth line and subsequent lines by +% $6$\,pt from the edge of the measure on each side. +% +% The \texttt{single_par} version applies only to a single paragraph, +% while the \texttt{multi_par} function sets the paragraph shape on an +% ongoing basis within the scope of the current \TeX{} group. +% \end{function} +% +% \begin{function} +% { +% \galley_parshape_fixed_lines:nnn, +% \galley_parshape_fixed_lines:nVV +% } +% \begin{syntax} +% \cs{galley_parshape_fixed_lines:nnn} \Arg{unaltered lines} \Arg{left indents} \Arg{right indents} +% \end{syntax} +% Sets the paragraph shape to create an arbitrary paragraph shape which will +% apply to an exact number of lines. +% The paragraph shape is set such that there are \meta{unaltered lines} which +% have width and indent as set by the measure. The \enquote{altered} lines +% are then defined by the comma-separated lists of \meta{left indents} and +% \meta{right indents}. These are both indents from the edge of the measure, +% and may be negative, and should both contain the same number of items. +% The altered lines will apply to one or more paragraphs, such that the +% entire indent specification is honoured before the standard measure +% resumes. +% \end{function} +% +% \subsection{Formatting inside the paragraph} +% +% The settings described here apply \enquote{inside} the paragraph, and so +% are active irrespective of any paragraph shape within the measure. +% +% \begin{variable}{\l_galley_line_left_skip, \l_galley_line_right_skip} +% Stretchable space added to the appropriate side each line in a paragraph. +% \end{variable} +% +% \begin{variable}{\l_galley_par_begin_skip, \l_galley_par_end_skip} +% Stretchable space added to the beginning of the first line and end of +% the last line of a paragraph, respectively. +% \end{variable} +% +% \begin{variable}{\l_galley_par_indent_dim} +% Fixed space added to the start of each paragraph except for those where +% \cs{l_galley_omit_next_indent_bool} is \texttt{true}. +% \end{variable} +% +% \begin{variable}{\l_galley_last_line_fit_int} +% Determines how the inter-word stretch is set for the last line of a +% paragraph when +% \begin{enumerate} +% \item The value of \cs{l_galley_par_end_skip} contains an infinite +% (\texttt{fil}) component; +% \item The values of \cs{l_galley_line_left_skip} and +% \cs{l_galley_line_right_skip} do \emph{not} contain an infinite +% (\texttt{fil}) component. +% \end{enumerate} +% Under these circumstances, \cs{l_galley_last_line_fit_int} is active, and +% applies as follows: +% \begin{itemize} +% \item Set to $0$, the last line of the paragraph is set with +% the inter-word spacing at natural width; +% \item Set to a $1000$ (or above), the inter-word spacing in the last line +% is stretched by the same factor as that applied to the penultimate +% line; +% \item Set to $n$ between these extremes, the inter-word spacing in the +% last line is stretched by $n/1000$ times the factor used for the +% penultimate line. +% \end{itemize} +% \end{variable} +% +% \begin{function}{\galley_set_interword_spacing:N} +% \begin{syntax} +% \cs{galley_set_interword_spacing:N} \meta{fixed spacing bool} +% \end{syntax} +% Sets the inter-word spacing used based on the values supplied by the +% current font. If the \meta{fixed spacing bool} flag is \texttt{true} then +% no stretch is permitted between words, otherwise the stretch specified by +% the font designer is used. +% \end{function} +% +% \subsection{Display material} +% +% Material which is set in \enquote{display-style} require additional settings +% to control the relationship with the surrounding material. +% +% \begin{function}{\galley_display_begin:, \galley_display_end:} +% \begin{syntax} +% \cs{galley_display_begin:} +% \ldots +% \cs{galley_display_end:} +% \end{syntax} +% Sets up a group to contain display-style material. Unlike an independent +% galley level, settings are inherited from the surroundings. However, +% the interaction of a display block with the paragraphs before and after it +% can be adjusted independent of the design of text. +% \end{function} +% +% \subsection{Line breaking} +% +% \begin{variable}{\l_galley_binop_penalty_int} +% Penalty charged if an inline math formula is broken at a +% binary operator. +% \end{variable} +% +% \begin{variable}{\l_galley_double_hyphen_demerits_int} +% Extra demerit charge of two (or more) lines in succession end +% in a hyphen. +% \end{variable} +% +% \begin{variable}{\l_galley_emergency_stretch_skip} +% 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. +% \end{variable} +% +% \begin{variable}{\l_galley_final_hyphen_demerits_int} +% Extra demerit charge if the second last line is hyphenated. +% \end{variable} +% +% \begin{variable}{\l_galley_linebreak_badness_int} +% Boundary that if exceeded will cause \TeX{} to report an +% underfull line. +% \end{variable} +% +% \begin{variable}{\l_galley_linebreak_fuzz_dim} +% Boundary below which overfull lines are not reported. +% \end{variable} +% +% \begin{variable}{\l_galley_linebreak_penalty_int} +% Extra penalty charged per line in the paragraph. By making +% this penalty higher \TeX{} will try harder to produce compact +% paragraphs. +% \end{variable} +% +% \begin{variable}{\l_galley_linebreak_pretolerance_int} +% Maximum tolerance allowed for individual lines to break the +% paragraph without attempting hyphenation. +% \end{variable} +% +% \begin{variable}{\l_galley_linebreak_tolerance_int} +% Maximum tolerance allowed for individual lines when breaking a +% paragraph while attempting hyphenation (if this limit can't be +% met \cs{l_galley_emergency_stretch_skip} comes into play). +% \end{variable} +% +% \begin{variable}{\l_galley_mismatch_demerits_int} +% Extra demerit charge if two visually incompatible lines follow +% each other. +% \end{variable} +% +% \begin{variable}{\l_galley_relation_penalty_int} +% Penalty charged if an inline math formula is broken at a +% relational symbol. +% \end{variable} +% +% \subsection{Paragraph breaking} +% +% \begin{variable}{\l_galley_parbreak_badness_int} +% Boundary that if exceeded will cause \TeX{} to report an +% underfull vertical box. +% \end{variable} +% +% \begin{variable}{\l_galley_parbreak_fuzz_dim} +% Boundary below which overfull vertical boxes are not reported. +% \end{variable} +% +% \begin{variable}{\l_galley_broken_penalty_int} +% Penalty for page breaking after a hyphenated line. +% \end{variable} +% +% \begin{variable}{\l_galley_pre_display_penalty_int} +% Penalty for breaking between immediately before display math material. +% \end{variable} +% +% \begin{variable}{\l_galley_post_display_penalty_int} +% Penalty for breaking between immediately after display math material. +% \end{variable} +% +% \begin{function} +% { +% \galley_set_club_penalties:n, +% \galley_set_club_penalties:V, +% \galley_set_club_penalties:v, +% \galley_set_display_club_penalties:n, +% \galley_set_display_club_penalties:V, +% \galley_set_display_club_penalties:v, +% \galley_set_display_widow_penalties:n, +% \galley_set_display_widow_penalties:V, +% \galley_set_display_widow_penalties:v, +% \galley_set_widow_penalties:n, +% \galley_set_widow_penalties:V, +% \galley_set_widow_penalties:v +% } +% \begin{syntax} +% \cs{galley_set_club_penalties:n} \Arg{penalty list} +% \end{syntax} +% Set the penalties for breaking lines at the beginning and end of +% (partial) paragraphs. In each case, the \meta{penalty list} is a +% comma-separated list of penalty values. The list applies as follows: +% \begin{itemize} +% \item[\texttt{club}] Penalties for breaking after the first, second, +% third, \emph{etc.}~line of the paragraph. +% \item[\texttt{display_club}] Penalties for breaking after the first, +% second, third, \emph{etc.}~line after a display math environment. +% \item[\texttt{display_club}] Penalties for breaking before the last, +% penultimate, antepenultimate, \emph{etc.}~line before a display +% math environment. +% \item[\texttt{widow}] Penalties for breaking before the last, +% penultimate, antepenultimate, \emph{etc.}~line of the paragraph. +% \end{itemize} +% In all cases, these penalties apply in addition to the general interline +% penalty or to any \enquote{special} line penalties. +% \end{function} +% +% \begin{function}{\galley_set_interline_penalty:n} +% \begin{syntax} +% \cs{galley_set_interline_penalty:n} \Arg{penalty} +% \end{syntax} +% Sets the standard interline penalty applied between lines of a paragraph. +% This value is added to any (display) club or widow penalty in force. +% \end{function} +% +% \begin{function} +% { +% \galley_set_interline_penalties:n, +% \galley_set_interline_penalties:V +% } +% \begin{syntax} +% \cs{galley_set_interline_penalties:n} \Arg{penalty list} +% \end{syntax} +% Sets \enquote{special} interline penalties to be used in place of +% the standard value, specified as a comma-separated \meta{penalty list}. +% The \meta{penalties} apply to the first, second, third, \emph{etc.}~line +% of the paragraph. +% \end{function} +% +% \begin{function} +% { +% \galley_save_club_penalties:N, +% \galley_save_display_club_penalties:N, +% \galley_save_display_widow_penalties:N, +% \galley_save_interline_penalties:N, +% \galley_save_widow_penalties:N +% } +% \begin{syntax} +% \cs{galley_save_club_penalties:N} \Arg{comma list} +% \end{syntax} +% These functions save the current value of the appropriate to the +% comma list specified, within the current \TeX{} group. +% \end{function} +% +% \begin{function}[EXP]{\galley_interline_penalty:} +% \begin{syntax} +% \cs{galley_interline_penalty:} +% \end{syntax} +% Expands to the current interline penalty as a \meta{integer denotation}. +% \end{function} +% +% \section{Hooks and insertion points} +% +% \begin{variable}{\g_galley_par_begin_hook_tl} +% Token list inserted at the beginning of every paragraph in horizontal mode. +% This is inserted after any paragraph indent but before any other horizontal +% mode material. +% \end{variable} +% +% \begin{variable}{\g_galley_par_end_hook_tl} +% Token list inserted at the end of every paragraph in horizontal mode. +% \end{variable} +% +% \begin{variable}{\g_galley_par_after_hook_tl} +% Token list inserted after each paragraph. This is used for resetting +% galley parameters, and is therefore cleared after use. +% \end{variable} +% +% \begin{variable}{\g_galley_whatsit_next_tl} +% Token list for whatsits to be inserted at the very beginning of the next +% paragraph started. +% \end{variable} +% +% \begin{variable}{\g_galley_whatsit_previous_hook_tl} +% Token list for whatsits to be inserted at the very end of the last +% paragraph started. +% \end{variable} +% +% \section{Internal variables} +% +% Some of the internal variables for the galley mechanism may be of +% interest to the programmer. These should all be treated as read-only +% values and accessed only through the defined interfaces described above. +% +% \begin{variable}{\l_galley_total_left_margin_dim} +% The total margin between the left side of the galley and the left side of +% the text block. This may be negative if the measure is set to overlap +% the text beyond the edge of the galley. +% \end{variable} +% +% \begin{variable}{\l_galley_total_right_margin_dim} +% The total margin between the right side of the galley and the right side +% of the text block. This may be negative if the measure is set to overlap +% the text beyond the edge of the galley. +% \end{variable} +% +% \begin{variable}{\l_galley_text_width_dim} +% The width of a line of text within the galley, taking account of +% any margins added. This may be larger than \cs{l_galley_width_dim} +% if the margins are negative. +% \end{variable} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3galley} Implementation} +% +% At the implementation level, there are a number of challenges which +% have to be overcome in order to make the galley easy to use at the +% designer and user levels. Inserting material into the main vertical +% list is in many ways an irreversible operation. Inserting items as +% they appear in the source is therefore not desirable. Instead, +% inserting vertical-mode material needs to be delayed until the start +% of the \enquote{next} paragraph. This is particularly notable for +% invisible items such as whatsits and specials, which will otherwise +% cause changes in spacing. Delaying insertion enables user-supplied +% settings to override design settings in a reliable fashion. This can +% be achieved as the design-level material can be ignored if a user +% value is supplied. There is a need to allow proper nesting of +% galleys, which means that all of the above needs to be set up so that +% it can be saved and restored. All of these manipulations require +% altering the meaning of the \cs{par} token, which is particularly +% awkward as \TeX{} inserts a token \emph{called} \cs{par} rather than +% one with a particular meaning. This makes moving \cs{par} to somewhere +% \enquote{safe} extremely challenging. +% +% Added to all of this complexity, there is a need to deal with +% \enquote{display-like} material. The most obvious example is the way +% lists are handled. These use \cs{par} tokens to achieve the correct +% appearance, but at the same time +% \begin{verbatim} +% Text +% \begin{itemize} +% \item An item +% \end{itemize} +% More text +% \end{verbatim} +% should form one visual paragraph while +% \begin{verbatim} +% Text +% \begin{itemize} +% \item An item +% \end{itemize} +% +% More text +% \end{verbatim} +% should be shown as two paragraphs. This requires an additional level +% of handling so that the \cs{par} token used to end the list in the +% first case does not start a new paragraph in a visual sense while the +% second does. +% +% Another factor to bear in mind is that \cs{tex_everypar:D} may be +% executed inside a group. For example, a paragraph starting +% \begin{verbatim} +% {Text} here +% \end{verbatim} +% will insert the tokens such that the current group level is $1$ +% higher for \enquote{Text} than for \enquote{here}. The result of this +% is that it's very important to watch how flags are set and reset. This +% can only be done reliably on a global level, which then has a knock-on +% effect on the rest of the implementation. +% +% At a \TeX{} level, settings can only apply to the current paragraph, +% but conceptually there is a need to allow for both single-paragraph +% and \enquote{running} settings. Whenever the code switches galley +% level both of these need to be correctly saved. +% +% \begin{macrocode} +%<*initex|package> +% \end{macrocode} +% +% \begin{macrocode} +%<*package> +\ProvidesExplPackage + {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} +\package_check_loaded_expl: +%</package> +% \end{macrocode} +% +% \subsection{Support items} +% +% Functions or settings which are needed by the galley but perhaps also +% elsewhere. +% +% \begin{macro}{\galley_leave_vmode:} +% The standard mode to leave vertical mode, starting a paragraph. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_leave_vmode: + { \tex_unhbox:D \c_empty_box } +% \end{macrocode} +% \end{macro} +% +% The default hyphenation character should be set and hyphenation should be +% enabled. +% \begin{macrocode} +%<*initex> +\tex_defaulthyphenchar:D 45 \scan_stop: +%</initex> +% \end{macrocode} +% +% \subsection{Galley settings} +% +% Settings for application by the galley respect the usual \TeX{} grouping and +% so are all local variables. +% +% \begin{variable} +% { +% \l_galley_parshape_left_indent_clist, +% \l_galley_parshape_right_indent_clist +% } +% \begin{variable} +% { +% \l_galley_parshape_multipar_bool, +% \l_galley_parshape_resume_std_bool, +% \l_galley_parshape_fixed_lines_bool +% } +% Setting up paragraph shape interacts with setting up the measure. The only +% way to keep things flexible is to have a rather \enquote{rich} set of data +% available. +% \begin{macrocode} +\clist_new:N \l_galley_parshape_left_indent_clist +\clist_new:N \l_galley_parshape_right_indent_clist +\bool_new:N \l_galley_parshape_multipar_bool +\bool_new:N \l_galley_parshape_resume_std_bool +\bool_new:N \l_galley_parshape_fixed_lines_bool +\int_new:N \l_galley_parshape_std_lines_int +% \end{macrocode} +% \end{variable} +% \end{variable} +% +% \begin{variable}{\l_galley_text_width_dim} +% The width of the current measure: the \enquote{running} setting can be +% inherited from \LaTeXe{}. +% \begin{macrocode} +%<*initex> +\dim_new:N \l_galley_text_width_dim +%</initex> +%<*package> +\cs_new_eq:NN \l_galley_text_width_dim \linewidth +%</package> +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% {\l_galley_total_left_margin_dim, \l_galley_total_right_margin_dim} +% Margins of the current text within the galley: these plus the galley +% width are one way to define the measure width. See also the text width, +% which is an alternative view (and should be in sync with this one!). +% \begin{macrocode} +%<*initex> +\dim_new:N \l_galley_total_left_margin_dim +%</initex> +%<*package> +\cs_new_eq:NN \l_galley_total_left_margin_dim \@totalleftmargin +%</package> +\dim_new:N \l_galley_total_right_margin_dim +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% {\l_galley_interpar_penalty_skip, \l_galley_interpar_vspace_skip} +% Items between paragraphs at the design level. +% \begin{macrocode} +\int_new:N \l_galley_interpar_penalty_int +\skip_new:N \l_galley_interpar_vspace_skip +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_galley_width_dim} +% The external size of a galley is the stored in the \TeX{} primitive +% \cs{tex_hsize:D}, which is renamed. This will only ever be reset by +% the code constructing a new galley, for example the start of a +% minipage. This value will be set for the main galley by the page +% layout system. +% \begin{macrocode} +\cs_new_eq:NN \l_galley_width_dim \tex_hsize:D +% \end{macrocode} +% \end{variable} +% +% \subsection{Galley data structures} +% +% In contrast to settings, the data structures used by the galley are all set +% globally. To allow different galley levels to exist, a local variant is +% defined for each one to save the value when starting a new level. +% +% \begin{variable}{\g_galley_begin_level_bool, \l_galley_begin_level_bool} +% Indicates that the galley is at the very beginning of the level, and that +% no material has yet been set. As a result, the global version is set +% \texttt{true} to begin with. +% \begin{macrocode} +\bool_new:N \g_galley_begin_level_bool +\bool_new:N \l_galley_begin_level_bool +\bool_gset_true:N \g_galley_begin_level_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\g_galley_omit_next_indent_bool, \l_galley_omit_next_indent_bool} +% A global flag is needed for suppressing indentation of the next +% paragraph. This does not need a \enquote{running} version since that +% should be handled using the \texttt{justification} object: the two +% concepts are related but not identical. The flag here is needed in +% cases such as the very first paragraph in a galley or immediately +% following a heading. +% \begin{macrocode} +\bool_new:N \g_galley_omit_next_indent_bool +\bool_new:N \l_galley_omit_next_indent_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\g_galley_parshape_set_bool, \l_galley_parshape_set_bool} +% This is not a setting for paragraph shape, but rather a tracker for the +% galley system. +% \begin{macrocode} +\bool_new:N \g_galley_parshape_set_bool +\bool_new:N \l_galley_parshape_set_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\g_galley_nobreak_next_bool, \l_galley_nobreak_next_bool} +% Dealing with the no-break flag is pretty much the same as the case +% for the indent: this applies on a single paragraph basis. +% \begin{macrocode} +\bool_new:N \g_galley_nobreak_next_bool +\bool_new:N \l_galley_nobreak_next_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% { +% \g_galley_par_begin_hook_tl, \l_galley_par_begin_hook_tl, +% \g_galley_par_end_hook_tl, \l_galley_par_end_hook_tl, +% } +% Hooks for user-level code: these are not used by the galley itself. +% \begin{macrocode} +\tl_new:N \g_galley_par_begin_hook_tl +\tl_new:N \l_galley_par_begin_hook_tl +\tl_new:N \g_galley_par_end_hook_tl +\tl_new:N \l_galley_par_end_hook_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% {\g_galley_par_after_hook_tl, \l_galley_par_after_hook_tl} +% This one is used by the galley: it happens \enquote{after} the current +% paragraph, and is used for reset purposes. +% \begin{macrocode} +\tl_new:N \g_galley_par_after_hook_tl +\tl_new:N \l_galley_par_after_hook_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% {\g_galley_previous_par_lines_int, \l_galley_previous_par_lines_int} +% The number of lines in the previous typeset paragraph. This is reset at +% the start of the paragraph and \emph{added to} when each \cs{tex_par:D} +% primitive is used: \LaTeX{} uses the primitive in places that do not end +% a (conceptual) paragraph. +% \begin{macrocode} +\int_new:N \g_galley_previous_par_lines_int +\int_new:N \l_galley_previous_par_lines_int +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\g_galley_restore_running_tl, \l_galley_restore_running_tl} +% When a parameter is altered from the \enquote{running} value to a +% different \enquote{current} one, there needs to be a method to restore +% the \enquote{running} value. This is done by adding the necessary +% assignment to a token list, which can be executed when needed. At the +% same time, this information is itself part of the galley parameter +% structure, and so there has to be a local save version. +% \begin{macrocode} +\tl_new:N \g_galley_restore_running_tl +\tl_new:N \l_galley_restore_running_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% { +% \g_galley_whatsit_next_tl, \l_galley_whatsit_next_tl, +% \g_galley_whatsit_previous_tl, \l_galley_whatsit_previous_tl +% } +% Whatsits only apply on a per-paragraph basis and so there is no need +% to differentiate between current and running values. However, there +% is a need to differentiate between whatsits that attach to the +% previous (completed) paragraph and those that attach to the next +% paragraph. +% \begin{macrocode} +\tl_new:N \g_galley_whatsit_next_tl +\tl_new:N \l_galley_whatsit_next_tl +\tl_new:N \g_galley_whatsit_previous_tl +\tl_new:N \l_galley_whatsit_previous_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% {\g_galley_interpar_penalty_user_tl, \l_galley_interpar_penalty_user_tl} +% The user may want to over-ride the penalty for a break between +% paragraphs, for example to prevent a break when the overall design +% allows one. This is handled using an additional penalty. +% \begin{macrocode} +\tl_new:N \g_galley_interpar_penalty_user_tl +\tl_new:N \l_galley_interpar_penalty_user_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% {\g_galley_interpar_vspace_user_tl, \l_galley_interpar_vspace_user_tl} +% Arbitrary vertical space can be inserted by the user on a one-off +% basis. This is used in place of any running space between paragraphs. +% \begin{macrocode} +\tl_new:N \g_galley_interpar_vspace_user_tl +\tl_new:N \l_galley_interpar_vspace_user_tl +% \end{macrocode} +% \end{variable} +% +% \subsection{Independent galley levels} +% +% As well as the main vertical list, independent galleys are required +% for items such as minipages and marginal notes. Each of these galleys +% requires an independent set of global data structures. This is +% achieved by storing the data structures in \emph{local} variables. The +% later are only used to save and restore the global value, and so \TeX{} +% grouping will manage the values correctly. This implies that each +% galley level must form a group: galley levels are tided to vertical +% boxes and so this is a reasonable requirements. +% +% \begin{macro}{\galley_initialise_variables:} +% At the start of a galley level, both the global and local variables +% will need to be reset to standard values. For example, the measure +% is set to the galley width and any paragraph shape is cleared. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_initialise_variables: + { + \bool_gset_true:N \g_galley_begin_level_bool + \tl_gclear:N \g_galley_interpar_penalty_user_tl + \tl_gclear:N \g_galley_interpar_vspace_user_tl + \bool_gset_true:N \g_galley_omit_next_indent_bool + \bool_gset_false:N \g_galley_nobreak_next_bool + \tl_gclear:N \g_galley_par_begin_hook_tl + \tl_gclear:N \g_galley_par_end_hook_tl + \tl_gclear:N \g_galley_par_after_hook_tl + \bool_gset_false:N \g_galley_parshape_set_bool + \int_gzero:N \g_galley_previous_par_lines_int + \tl_gclear:N \g_galley_restore_running_tl + \tl_gclear:N \g_galley_whatsits_previous_tl + \tl_gclear:N \g_galley_whatsits_next_tl + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\galley_initialise_settings:} +% This sets the local values of the various galley settings. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_initialise_settings: + { + \dim_set_eq:NN \l_galley_text_width_dim \l_galley_width_dim + \dim_zero:N \l_galley_left_margin_dim + \dim_zero:N \l_galley_right_margin_dim + \dim_zero:N \l_galley_total_left_margin_dim + \dim_zero:N \l_galley_total_right_margin_dim + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\galley_save_parameters:, \galley_restore_parameters:} +% Saving and restoring parameters is carried out by a series of copy +% functions. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_save_parameters: + { + \bool_set_eq:NN \l_galley_begin_level_bool + \g_galley_begin_level_bool + \tl_set_eq:NN \l_galley_interpar_penalty_user_tl + \g_galley_interpar_penalty_user_tl + \tl_set_eq:NN \l_galley_interpar_vspace_user_tl + \g_galley_interpar_vspace_user_tl + \bool_set_eq:NN \l_galley_omit_next_indent_bool + \g_galley_omit_next_indent_bool + \bool_set_eq:NN \l_galley_nobreak_next_bool + \g_galley_nobreak_next_bool + \tl_set_eq:NN \l_galley_par_begin_hook_tl + \g_galley_par_begin_hook_tl + \tl_set_eq:NN \l_galley_par_end_hook_tl + \g_galley_par_end_hook_tl + \tl_set_eq:NN \l_galley_par_after_hook_tl + \g_galley_par_after_hook_tl + \bool_set_eq:NN \l_galley_parshape_set_bool + \g_galley_parshape_set_bool + \int_set_eq:NN \l_galley_previous_par_lines_int + \g_galley_previous_par_lines_int + \tl_set_eq:NN \l_galley_restore_running_tl + \g_galley_restore_running_tl + \tl_set_eq:NN \l_galley_whatsits_previous_tl + \g_galley_whatsits_previous_tl + \tl_set_eq:NN \l_galley_whatsits_next_tl + \g_galley_whatsits_next_tl + } +\cs_new_protected_nopar:Npn \galley_restore_parameters: + { + \bool_gset_eq:NN \g_galley_begin_level_bool + \l_galley_begin_level_bool + \tl_gset_eq:NN \g_galley_interpar_penalty_user_tl + \l_galley_interpar_penalty_user_tl + \tl_gset_eq:NN \g_galley_interpar_vspace_user_tl + \l_galley_interpar_vspace_user_tl + \bool_gset_eq:NN \g_galley_omit_next_indent_bool + \l_galley_omit_next_indent_bool + \bool_gset_eq:NN \g_galley_nobreak_next_bool + \l_galley_nobreak_next_bool + \tl_gset_eq:NN \g_galley_par_begin_hook_tl + \l_galley_par_begin_hook_tl + \tl_gset_eq:NN \g_galley_par_end_hook_tl + \l_galley_par_end_hook_tl + \tl_gset_eq:NN \g_galley_par_after_hook_tl + \l_galley_par_after_hook_tl + \bool_gset_eq:NN \g_galley_parshape_set_bool + \l_galley_parshape_set_bool + \int_gset_eq:NN \g_galley_previous_par_lines_int + \l_galley_previous_par_lines_int + \tl_gset_eq:NN \g_galley_restore_running_tl + \l_galley_restore_running_tl + \tl_gset_eq:NN \g_galley_whatsits_previous_tl + \l_galley_whatsits_previous_tl + \tl_gset_eq:NN \g_galley_whatsits_next_tl + \l_galley_whatsits_next_tl + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\galley_level:} +% \begin{macro}[aux]{\galley_level_end:} +% Galley levels are created by saving all of the current global +% settings, starting a group then initialising both the local and global +% variables. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_level: + { + \galley_save_parameters: + \group_begin: + \galley_initialise_variables: + \galley_initialise_settings: + \group_insert_after:N \galley_level_end: + } +% \end{macrocode} +% At the end of the level, the global values are restored using the +% saved \emph{local} versions, hence the position of the close-of-group +% instruction. As this code can be inserted automatically, at the point +% of use only the start of a galley level needs to be marked up: the end +% must come in a fixed location. All of this relies on the the +% \enquote{colour safe} group used inside a box. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_level_end: + { + \par + \galley_restore_parameters: + \group_end: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{The \cs{par} token} +% +% \begin{macro}{\galley_std_par:} +% In vertical mode, the standard paragraph insert is just the primitive +% \cs{tex_par:D}. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_std_par: + { + \mode_if_vertical:TF + { \tex_par:D } +% \end{macrocode} +% In horizontal mode, the paragraph shape is set \enquote{just in time} +% before inserting \cs{tex_par:D}. The \cs{tex_par:D} is inside a +% group to preserve some dynamic settings (for example +% \cs{etex_interlinepenalties}). Once the +% paragraph has been typeset, the number of lines is \emph{added} to the +% running total. It's possible that the conceptual paragraph contains +% display-like material, and simply setting the number of lines equal to +% \cs{tex_prevgraf:D} would \enquote{loose} these. +% \begin{macrocode} + { + \g_galley_par_end_hook_tl + \galley_set_measure_and_parshape: + \group_begin: + \tex_par:D + \group_end: + \int_gadd:Nn \g_galley_previous_par_lines_int \tex_prevgraf:D + } + \g_galley_par_after_hook_tl + \tl_gclear:N \g_galley_par_after_hook_tl +% \end{macrocode} +% The non-breaking penalty is needed here as within the \cs{tex_everypar:D} +% hook there is an additional \cs{tex_par:D}. This leads to an extra +% \cs{tex_parskip:D}, which will leave an unwanted break-point here +% otherwise. +% \begin{macrocode} + \tex_penalty:D \c_ten_thousand + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\par} +% The meaning of the token \cs{par} itself starts off as a standard +% paragraph. +% \begin{macrocode} +\cs_set_protected_nopar:Npn \par { \galley_std_par: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@par} +% \LaTeXe{} requires a \enquote{long term} version of \cs{par}, which is +% stored as \cs{@par}. Things are done a bit differently by \LaTeX3 and +% so this will only be needed in package mode. +% \begin{macrocode} +%<*package> +\tl_set:Nn \@par { \galley_std_par: } +%</package> +% \end{macrocode} +% \end{macro} +% +% \subsection{Display levels} +% +% \begin{macro}{\galley_display_begin:, \galley_display_end:} +% \begin{macro}[aux]{\galley_display_penalty:N, \galley_display_vspace:N} +% \begin{macro}[aux]{\galley_display_par_setup:, \galley_display_par:} +% Display items within the galley are a bit like galley levels: they +% may have different paragraph settings to the main part of the galley. +% On the other hand, unlike independent galleys they should inherit the +% settings from the surrounding material. They may also start and end with +% special spacing values. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_display_begin: + { + \group_begin: + \galley_save_parameters: + \mode_if_vertical:TF + { + \galley_display_penalty:N \l_galley_display_begin_par_penalty_tl + \galley_display_vspace:N \l_galley_display_begin_par_vspace_tl + } + { + \galley_display_penalty:N \l_galley_display_begin_penalty_tl + \galley_display_vspace:N \l_galley_display_begin_vspace_tl + } + \par + } +% \end{macrocode} +% Two short-cuts for setting up any special penalty or vertical space. +% The idea is that the standard value is saved to the \enquote{restore} +% token list, before setting up the value to the special value needed +% in this one case. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_display_penalty:N #1 + { + \tl_if_empty:NF #1 + { + \tl_gput_right:Nx \g_galley_restore_running_tl + { + \int_gset:Nn \exp_not:N \g_galley_penalty_int + { \int_use:N \g_galley_penalty_int } + } + \int_gset:Nn \g_galley_penalty_int {#1} + } + } +\cs_new_protected_nopar:Npn \galley_display_vspace:N #1 + { + \tl_if_empty:NF #1 + { + \tl_gput_right:Nx \g_galley_restore_running_tl + { + \skip_gset:Nn \exp_not:N \g_galley_vspace_skip + { \skip_use:N \g_galley_vspace_skip } + } + \skip_gset:Nn \g_galley_vspace_int {#1} + } + } +% \end{macrocode} +% The \cs{par} token at the end of the display needs to go in at the same +% group level as the text, hence this function cannot be placed using +% \cs{group_insert_after:N}. Resetting the meaning of the \cs{par} token +% needs to be carried out after the group used for the environment. +% As \LaTeXe{} already adds one group, there are two \enquote{escapes} +% here: the format version needs only one escape. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_display_end: + { + \par + \galley_restore_parameters: + \group_end: +%<*package> + \group_insert_after:N \group_insert_after:N +%</package> + \group_insert_after:N \galley_display_par_setup: + } +% \end{macrocode} +% The method used here is to assume that the next piece of horizontal +% mode material will follow on from the displayed output without an +% intervening \cs{par} token (probably a blank line). The meaning of the +% \cs{par} token is then altered so that a check can be made to see if +% this assumption was correct. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_display_par_setup: + { + \bool_gset_false:N \g_galley_omit_next_indent_bool + \cs_set_eq:NN \par \galley_display_par: + } +% \end{macrocode} +% The \enquote{special} meaning of the paragraph token starts by putting +% things back to normal: there should never need to be more than one +% special paragraph marker in one group. If \TeX{} is in vertical mode, +% then there has been a paragraph token inserted, most likely by a +% blank line. Thus the next piece of material is a separate conceptual +% paragraph from the display. In that case, the assumption from above is +% undone and the indent is turned back on. On the other hand, for the +% case where \TeX{} is in horizontal mode then a \cs{tex_par:D} primitive +% is required in the same way as in \cs{galley_standard_par:}. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_display_par: + { + \cs_set_eq:NN \par \galley_std_par: + \mode_if_vertical:TF + { + \par + \bool_gset_false:N \g_galley_omit_next_indent_bool + \galley_display_penalty:N \l_galley_display_end_par_penalty_tl + \galley_display_vspace:N \l_galley_display_end_par_vspace_tl + } + { + \galley_set_measure_and_parshape: + \group_begin: + \tex_par:D + \group_end: + \int_gadd:Nn \g_galley_previous_par_lines_int \tex_prevgraf:D + \galley_display_penalty:N \l_galley_display_end_penalty_tl + \galley_display_vspace:N \l_galley_display_end_vspace_tl + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Insertions using \cs{tex_everypar:D}} +% +% The key to the entire galley mechanism is hooking into the +% \cs{tex_everypar:D} token register. This requires that the original +% is moved out of the way, with appropriate hooks left attached for +% further modification by other modules and by the user. This is all +% done such that there is no danger of accidentally deactivating the +% galley mechanism. +% +% \begin{macro}{\everypar} +% When used on top of \LaTeXe{} the original primitive name needs to be +% available without the risk of completely overwriting the new +% mechanism. This is implemented as a token register in case low-level +% \TeX{} is used. The \TeX{} primitive is set here as otherwise the +% \LaTeXe{} \cs{@nodocument} is never removed from the register. +% This precaution is not be needed for a stand-alone format. +% \begin{macrocode} +%<*initex> +\tex_everypar:D % TEMP + { + \bool_if:NTF \g_galley_begin_level_bool + { \galley_start_paragraph_first: } + { \galley_start_paragraph_std: } + } +%</initex> +%<*package> +\cs_undefine:N \everypar +\newtoks \everypar +\AtBeginDocument + { + \tex_everypar:D + { + \bool_if:NTF \g_galley_begin_level_bool + { \galley_start_paragraph_first: } + { \galley_start_paragraph_std: } + \tex_the:D \everypar + } + } +%</package> +% \end{macrocode} +% \end{macro} +% +% \subsection{The galley mechanism} +% +% \begin{variable}{\g_galley_last_box} +% A temporary box to hold the box inserted by \TeX{} when a paragraph +% is inserted with an indent. The galley actually inserts the space +% (\emph{i.e.}~\cs{tex_parindent:D} is globally zero), but there is +% still an empty box to test for. +% \begin{macrocode} +\box_new:N \g_galley_last_box +% \end{macrocode} +% \end{variable} +% +% The \enquote{start of paragraph} routines are fired by \cs{tex_everypar:D}. +% This can take place within a group in a construction such as +% \begin{verbatim} +% ... end of last par. +% +% {\Large Start} of par +% \end{verbatim} +% and so anything applied here must be done globally. +% +% \begin{macro}[int]{\galley_start_paragraph_std:} +% The routine at the start of a paragraph starts by removing any +% (empty) indent box from the vertical list. As there may be vertical +% mode items still to insert, a \cs{tex_par:D} primitive is used to +% get back into vertical mode before they are tidied up. To get back +% again to horizontal mode, \cs{tex_noindent:D} can be used. To avoid +% an infinite loop, \cs{tex_everypar:D} is locally cleared before doing +% that. Back in horizontal mode, the horizontal mode items can be +% tidied up before sorting out any items which have been set on a +% single-paragraph basis. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_start_paragraph_std: + { + \group_begin: + \box_gset_to_last:N \g_galley_last_box + \tex_par:D + \galley_insert_vertical_items: + \tex_everypar:D { } + \tex_noindent:D + \group_end: + \int_gzero:N \g_galley_previous_par_lines_int + \galley_insert_horizontal_items: + \galley_restore_running_parameters: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\galley_start_paragraph_first:} +% For the very first paragraph in a galley, the code needs to avoid +% adding any unnecessary vertical items at the top as it will interfere with +% vertical positioning in \cs{tex_vtop:D}. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_start_paragraph_first: + { + \bool_gset_false:N \g_galley_begin_level_bool + \mode_if_horizontal:TF + { + \group_begin: + \box_gset_to_last:N \g_galley_last_box + \tex_par:D + \galley_insert_vspace: + \tex_everypar:D { } + \tex_noindent:D + \group_end: + } + { \galley_insert_vspace: } + \galley_insert_horizontal_items: + \galley_restore_running_parameters: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\galley_insert_vertical_items, \galley_insert_vspace:} +% The aim here is to insert the vertical items such that they attach to +% the correct place. This function is used as part of the \cs{tex_everypar:D} +% mechanism, meaning that the immediately-preceding item on the vertical +% list is the \cs{tex_parskip:D}, always zero-length but an implicit +% penalty. So any whatsits \enquote{attached} to the previous paragraph +% should stay glued on. After the whatsits, a penalty for +% breaking will be inserted. This will be the user penalty if supplied, +% or the running penalty unless the no-break flag is set. Finally, +% the inter-paragraph space is applied. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_insert_vertical_items: + { + \g_galley_whatsit_previous_tl + \tl_gclear:N \g_galley_whatsit_previous_tl + \tl_if_empty:NTF \g_galley_interpar_penalty_user_tl + { + \bool_if:NTF \g_galley_nobreak_next_bool + { \tex_penalty:D \c_ten_thousand } + { \tex_penalty:D \l_galley_interpar_penalty_int } + } + { + \tex_penalty:D + \int_eval:w \g_galley_interpar_penalty_user_tl \int_eval_end: + \tl_gclear:N \g_galley_interpar_penalty_user_tl + } + \bool_gset_false:N \g_galley_nobreak_next_bool + \galley_insert_vspace: + } +% \end{macrocode} +% Inserting vertical space is set up as a separate function as it comes +% up in a few places. The idea here is that any user-set space will +% override the design value, and only one space is ever inserted. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_insert_vspace: + { + \tl_if_empty:NTF \g_galley_interpar_vspace_user_tl + { \skip_vertical:N \l_galley_interpar_vspace_skip } + { + \skip_vertical:n { \g_galley_interpar_vspace_user_tl } + \tl_gclear:N \g_galley_interpar_vspace_user_tl + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\galley_insert_horizontal_items:} +% Horizontal mode objects start with the whatsits for the next paragraph. An +% indent is then included if the removed box was not void. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_insert_horizontal_items: + { + \g_galley_whatsit_next_tl + \tl_gclear:N \g_galley_whatsit_next_tl + \bool_if:NT \g_galley_omit_next_indent_bool + { + \box_if_empty:NF \g_galley_last_box + { \hbox_to_wd:nn \l_galley_par_indent_dim { } } + } + \skip_horizontal:N \l_galley_par_begin_skip + \g_galley_par_begin_hook_tl + \bool_gset_true:N \g_galley_omit_next_indent_bool + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\galley_restore_running_parameters:} +% Restoring the ongoing parameters just means using the token list +% variable in which the appropriate assignments are stored. The +% list can then be cleared. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_restore_running_parameters: + { + \g_galley_restore_running_tl + \tl_gclear:N \g_galley_restore_running_tl + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Measure} +% +% \begin{macro} +% {\galley_margins_set_absolute:nn, \galley_margins_set_relative:nn} +% Setting the measure is just a question of adjusting margins, either +% in a relative or absolute sense. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_margins_set_absolute:nn #1#2 + { + \dim_set:Nn \l_galley_total_left_margin_dim {#1} + \dim_set:Nn \l_galley_total_right_margin_dim {#2} + \dim_set:Nn \l_galley_text_width_dim + { + \l_galley_width_dim + - \l_galley_total_left_margin_dim + - \l_galley_total_right_margin_dim + } + } +\cs_new_protected_nopar:Npn \galley_margins_set_relative:nn #1#2 + { + \dim_add:Nn \l_galley_total_left_margin_dim {#1} + \dim_add:Nn \l_galley_total_right_margin_dim {#2} + \dim_set:Nn \l_galley_text_width_dim + { + \l_galley_width_dim + - \l_galley_total_left_margin_dim + - \l_galley_total_right_margin_dim + } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Paragraph shape} +% +% \begin{macro} +% { +% \galley_parshape_fixed_lines:nnn, +% \galley_parshape_fixed_lines:nVV, +% \galley_parshape_multi_par:nnnN, +% \galley_parshape_multi_par:nVVN, +% \galley_parshape_single_par:nnnN, +% \galley_parshape_single_par:nVVN +% } +% Setting the paragraph shape is easy as most of the real work is done +% later. So this is just a case of saving the various pieces of data +% to the correct locations. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_parshape_fixed_lines:nnn #1#2#3 + { + \bool_gset_true:N \g_galley_parshape_set_bool + \bool_set_true:N \l_galley_parshape_fixed_lines_bool + \int_set:Nn \l_galley_parshape_std_lines_int {#1} + \clist_set:Nn \l_galley_parshape_left_indent_clist {#2} + \clist_set:Nn \l_galley_parshape_right_indent_clist {#3} + \bool_set_true:N \l_galley_parshape_resume_std_bool + } +\cs_new_protected_nopar:Npn \galley_parshape_multi_par:nnnN #1#2#3#4 + { + \bool_gset_true:N \g_galley_parshape_set_bool + \bool_set_true:N \l_galley_parshape_multipar_bool + \bool_set_false:N \l_galley_parshape_fixed_lines_bool + \int_set:Nn \l_galley_parshape_std_lines_int {#1} + \clist_set:Nn \l_galley_parshape_left_indent_clist {#2} + \clist_set:Nn \l_galley_parshape_right_indent_clist {#3} + \bool_set_eq:NN \l_galley_parshape_resume_std_bool #4 + } +\cs_new_protected_nopar:Npn \galley_parshape_single_par:nnnN #1#2#3#4 + { + \bool_gset_true:N \g_galley_parshape_set_bool + \bool_set_false:N \l_galley_parshape_multipar_bool + \bool_set_false:N \l_galley_parshape_fixed_lines_bool + \int_set:Nn \l_galley_parshape_std_lines_int {#1} + \clist_set:Nn \l_galley_parshape_left_indent_clist {#2} + \clist_set:Nn \l_galley_parshape_right_indent_clist {#3} + \bool_set_eq:NN \l_galley_parshape_resume_std_bool #4 + } +\cs_generate_variant:Nn \galley_parshape_fixed_lines:nnn { nVV } +\cs_generate_variant:Nn \galley_parshape_multi_par:nnnN { nVV } +\cs_generate_variant:Nn \galley_parshape_single_par:nnnN { nVV } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\galley_set_measure_and_parshape:} +% To set the paragraph shape for the current paragraph, there is a check to +% see if the measure alone should be used. If not, then the shape may be +% built by paragraph or based on the number of lines required. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_set_measure_and_parshape: + { + \bool_if:NTF \g_galley_parshape_set_bool + { + \bool_if:NTF \l_galley_parshape_fixed_lines_bool + { + \int_compare:nNnTF \g_galley_previous_par_lines_int > \c_zero + { \galley_generate_parshape_lines: } + { \galley_generate_parshape: } + } + { + \bool_gset_eq:NN \g_galley_parshape_set_bool + \l_galley_parshape_multipar_bool + \galley_generate_parshape: + } + } + { + \tex_global:D \tex_parshape:D + \c_one + \dim_use:N \l_galley_total_left_margin_dim + \c_space_tl + \dim_use:N \l_galley_text_width_dim + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\galley_generate_parshape:} +% \begin{macro}[aux]{\galley_set_parshape_map:nn, \galley_set_parshape_map:oo} +% \begin{macro}[aux]{\galley_set_parshape_map_aux:nw} +% For a shape to apply on a paragraph basis, the two user-supplied comma +% lists are taken and converted into left-side offsets and line lengths. +% This is all dependent on the current measure. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_generate_parshape: + { + \tex_global:D \tex_parshape:D + \int_eval:w + \l_galley_parshape_std_lines_int + + \int_min:nn + { \clist_length:N \l_galley_parshape_left_indent_clist } + { \clist_length:N \l_galley_parshape_right_indent_clist } + \bool_if:NT \l_galley_parshape_resume_std_bool { + 1 } + \int_eval_end: + \prg_replicate:nn \l_galley_parshape_std_lines_int + { + \dim_use:N \l_galley_total_left_margin_dim + \c_space_tl + \dim_use:N \l_galley_text_width_dim + \c_space_tl + } + \galley_set_parshape_map:oo + \l_galley_parshape_left_indent_clist + \l_galley_parshape_right_indent_clist + \bool_if:NT \l_galley_parshape_resume_std_bool + { + \c_space_tl + \dim_use:N \l_galley_total_left_margin_dim + \c_space_tl + \dim_use:N \l_galley_text_width_dim + } + } +\cs_new_nopar:Npn \galley_set_parshape_map:nn #1#2 + { \galley_set_parshape_map_aux:nw { } #1 , \q_mark #2 , \q_stop } +\cs_generate_variant:Nn \galley_set_parshape_map:nn { oo } +\cs_new_nopar:Npn \galley_set_parshape_map_aux:nw + #1#2 , #3 \q_mark #4 , #5 \q_stop + { + \bool_if:nTF { \tl_if_empty_p:n {#3} || \tl_if_empty_p:n {#4} } + { + #1 + \dim_eval:n { \l_galley_total_left_margin_dim + ( #2 ) } + \c_space_tl + \dim_eval:n { \l_galley_text_width_dim - ( ( #2 ) + ( #4 ) ) } + } + { + \galley_set_parshape_map_aux:nw + { + #1 + \dim_eval:n { \l_galley_total_left_margin_dim + ( #2 ) } + \c_space_tl + \dim_eval:n { \l_galley_text_width_dim - ( ( #2 ) + ( #4 ) ) } + \c_space_tl + } + #3 \q_mark #5 \q_stop + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[int]{\galley_generate_parshape_lines:} +% \begin{macro}[aux]{\galley_generate_parshape_lines_aux:n} +% The idea here is to construct a paragraph shape based on the remaining +% lines from the shape in the previous paragraph. If the previous paragraph +% was sufficiently long, then life is \enquote{back to normal} and the +% standard shape is set. If a special shape is needed, this is recovered +% from the paragraph shape using the \eTeX{} primitives. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_generate_parshape_lines: + { + \int_compare:nNnTF \tex_parshape:D > \g_galley_previous_par_lines_int + { + \tex_global:D \tex_parshape:D + \int_eval:w \tex_parshape:D - \g_galley_previous_par_lines_int + \int_eval_end: + \prg_stepwise_function:nnnN + { \g_galley_previous_par_lines_int + \c_one } + \c_one \tex_parshape:D \galley_generate_parshape_lines_aux:n + } + { + \bool_gset_false:N \g_galley_parshape_set_bool + \tex_global:D \tex_parshape:D + \c_one + \dim_use:N \l_galley_total_left_margin_dim + \c_space_tl + \dim_use:N \l_galley_text_width_dim + } + } +\cs_new_nopar:Npn \galley_generate_parshape_lines_aux:n #1 + { + \etex_parshapeindent:D #1 + ~ + \etex_parshapelength:D #1 + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Between paragraphs} +% +% \begin{macro}{\galley_set_user_penalty:n, \galley_set_user_vspace:n} +% User supplied penalties and spaces only apply for a single paragraph. +% In both cases, the input values need to be checked for the correct +% form but are stored as token lists. The \texttt{x}-type expansion +% deals with this nicely. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_set_user_penalty:n #1 + { \tl_gset:Nx \g_galley_interpar_penalty_user_tl { \int_eval:n {#1} } } +\cs_new_protected_nopar:Npn \galley_set_user_vspace:n #1 + { \tl_gset:Nx \g_galley_interpar_vspace_user_tl { \skip_eval:n {#1} } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\parskip} +% For the package, the \cs{parskip} primitive is moved out of the +% way as the code above is handling things. +% \begin{macrocode} +%<*package> +\dim_set:Nn \parskip \c_zero_dim +\cs_undefine:N \parskip +\skip_new:N \parskip +%</package> +% \end{macrocode} +% \end{macro} +% +% \subsection{Formatting inside the paragraph} +% +% Justification is more complex than is necessarily desirable as the various +% \TeX{} parameters here interact in ways which mean that clear separation +% between different areas is not so easy. +% +% \begin{variable} +% { +% \l_galley_line_left_skip, +% \l_galley_line_right_skip, +% \l_galley_par_begin_skip, +% \l_galley_par_end_skip, +% \l_galley_par_indent_dim +% } +% The variables for setting paragraph shape: essentially, these are +% the \TeX{} set. +% \begin{macrocode} +\cs_new_eq:NN \l_galley_line_left_skip \tex_leftskip:D +\cs_new_eq:NN \l_galley_line_right_skip \tex_rightskip:D +\dim_new:N \l_galley_par_begin_skip +\cs_new_eq:NN \l_galley_par_end_skip \tex_parfillskip:D +\cs_new_eq:NN \l_galley_par_indent_dim \tex_parindent:D +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_galley_last_line_fit_int} +% One from \eTeX{}. +% \begin{macrocode} +\cs_new_eq:NN \l_galley_last_line_fit_int \etex_lastlinefit:D +% \end{macrocode} +% \end{variable} +% +% \subsection{Inter-word spacing} +% +% Setting the spacing between words and between sentences is important +% for achieving the correct output from ragged and centred output. At +% the same time, as far as possible the aim is to retain the spacing +% specified by the font designer and not to use arbitrary values +% (\emph{cf.}~the approach in \emph{The \TeX{}book}, p.~101). +% +% \begin{macro}{\galley_set_interword_spacing:N} +% The approach taken to setting a fixed space is to use the information +% from the current font to set the spacing. This means that only +% \cs{tex_spacefactor:D} needs to be set, while \cs{tex_xspacefactor:D} +% is left alone. However, this is only necessary for fonts which have +% a stretch component to the inter-word spacing in the first place, +% \emph{i.e.}~monospaced fonts require no changes. The code therefore +% checks whether there is any stretch, and if there is uses the fixed +% component to set \cs{tex_spaceskip:D}. If there is a stretch component +% (non-zero \cs{tex_fontdimen:D} \texttt{3}), then the \cs{teX_spaceskip:D} +% is set to the fixed component from the font. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_set_interword_spacing:N #1 + { + \bool_if:NTF #1 + { % TODO Hook for font changes required! + \dim_compare:nNnTF { \tex_fontdimen:D \c_three \tex_font:D } + = \c_zero_dim + { \tex_spaceskip:D \c_zero_dim } + { \tex_spaceskip:D \tex_fontdimen:D \c_two \tex_font:D } + } + { \tex_spaceskip:D \c_zero_dim } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Hyphenation} +% +% \subsection{Line breaking} +% +% \begin{variable} +% { +% \l_galley_binop_penalty_int, +% \l_galley_double_hyphen_demerits_int, +% \l_galley_emergency_stretch_skip, +% \l_galley_final_hyphen_demerits_int, +% \l_galley_linebreak_badness_int, +% \l_galley_linebreak_fuzz_dim, +% \l_galley_linebreak_penalty_int, +% \l_galley_linebreak_pretolerance_int, +% \l_galley_linebreak_tolerance_int, +% \l_galley_mismatch_demerits_int, +% \l_galley_relation_penalty_int +% } +% All \TeX{} primitives renamed. +% \begin{macrocode} +\cs_new_eq:NN \l_galley_binop_penalty_int \tex_binoppenalty:D +\cs_new_eq:NN \l_galley_double_hyphen_demerits_int \tex_doublehyphendemerits:D +\cs_new_eq:NN \l_galley_emergency_stretch_skip \tex_emergencystretch:D +\cs_new_eq:NN \l_galley_final_hyphen_demerits_int \tex_finalhyphendemerits:D +\cs_new_eq:NN \l_galley_linebreak_badness_int \tex_hbadness:D +\cs_new_eq:NN \l_galley_linebreak_fuzz_dim \tex_hfuzz:D +\cs_new_eq:NN \l_galley_linebreak_penalty_int \tex_linepenalty:D +\cs_new_eq:NN \l_galley_linebreak_pretolerance_int \tex_pretolerance:D +\cs_new_eq:NN \l_galley_mismatch_demerits_int \tex_adjdemerits:D +\cs_new_eq:NN \l_galley_relation_penalty_int \tex_relpenalty:D +\cs_new_eq:NN \l_galley_linebreak_tolerance_int \tex_tolerance:D +% \end{macrocode} +% \end{variable} +% +% \subsection{Paragraph breaking} +% +% \begin{variable} +% { +% \l_galley_broken_penalty_int, +% \l_galley_interline_penalty_int, +% \l_galley_parbreak_badness_int, +% \l_galley_parbreak_fuzz_dim, +% \l_galley_post_display_penalty_int, +% \l_galley_pre_display_penalty_int +% +% } +% \TeX{} primitives renamed cover \emph{some} of this. +% \begin{macrocode} +\cs_new_eq:NN \l_galley_broken_penalty_int \tex_brokenpenalty:D +\cs_new_eq:NN \l_galley_interline_penalty_int \tex_interlinepenalty:D +\cs_new_eq:NN \l_galley_parbreak_badness_int \tex_vbadness:D +\cs_new_eq:NN \l_galley_parbreak_fuzz_dim \tex_vfuzz:D +\cs_new_eq:NN \l_galley_post_display_penalty_int \tex_postdisplaypenalty:D +\cs_new_eq:NN \l_galley_pre_display_penalty_int \tex_predisplaypenalty:D +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\l_galley_club_penalties_clist, \l_galley_line_penalties_clist} +% These are used to keep a track of information which cannot be +% extracted out of the primitives due to the overlapping nature of +% the meanings. +% \begin{macrocode} +\clist_new:N \l_galley_club_penalties_clist +\clist_new:N \l_galley_line_penalties_clist +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \galley_set_display_widow_penalties:n, +% \galley_set_display_widow_penalties:V, +% \galley_set_display_widow_penalties:v, +% \galley_set_widow_penalties:n, +% \galley_set_widow_penalties:V, +% \galley_set_widow_penalties:v +% } +% \begin{macro}[aux]{\galley_set_aux:n} +% By far the easiest penalties to deal with are those for widows. These +% work exactly as the names imply, with the display version only used +% immediately before display math, and the standard penalty used at the end +% of a paragraph. Thus there is only the need to convert the argument into +% the correct form, and add a $0$ penalty at the end to nullify the effect of +% repeating the last value. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_set_display_widow_penalties:n #1 + { + \etex_displaywidowpenalties:D + \int_eval:w \clist_length:n {#1} + \c_one \int_eval_end: + \clist_map_function:nN {#1} \galley_set_aux:n + \c_zero + } +\cs_generate_variant:Nn \galley_set_display_widow_penalties:n { V , v } +\cs_new_protected_nopar:Npn \galley_set_widow_penalties:n #1 + { + \etex_widowpenalties:D + \int_eval:w \clist_length:n {#1} + \c_one \int_eval_end: + \clist_map_function:nN {#1} \galley_set_aux:n + \c_zero + } +\cs_generate_variant:Nn \galley_set_widow_penalties:n { V , v } +\cs_new_nopar:Npn \galley_set_aux:n #1 { #1 ~ } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% { +% \galley_set_club_penalties:n, +% \galley_set_club_penalties:V, +% \galley_set_club_penalties:v, +% \galley_set_interline_penalties:n, +% \galley_set_interline_penalties:V, +% \galley_set_interline_penalties:v +% } +% Setting club or special line penalties is easy, as these are handled +% mainly by the interline set up function. The two concepts are essentially +% the same, but having two takes makes some special effects easier to +% carry out. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_set_club_penalties:n #1 + { + \clist_set:Nn \l_galley_club_penalties_clist {#1} + \galley_calc_interline_penalties: + } +\cs_generate_variant:Nn \galley_set_club_penalties:n { V , v } +\cs_new_protected_nopar:Npn \galley_set_interline_penalties:n #1 + { + \clist_set:Nn \l_galley_line_penalties_clist {#1} + \galley_calc_interline_penalties: + } +\cs_generate_variant:Nn \galley_set_interline_penalties:n { V , v } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \galley_set_display_club_penalties:n, +% \galley_set_display_club_penalties:V, +% \galley_set_display_club_penalties:v +% } +% Setting the display club penalties means first setting the primitive, +% then recalculating the interline array to allow for these new values. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_set_display_club_penalties:n #1 + { + \etex_clubpenalties:D + \int_eval:w \clist_length:n {#1} + \c_one \int_eval_end: + \clist_map_function:nN {#1} \galley_set_aux:n + \c_zero + \galley_calc_interline_penalties: + } +\cs_generate_variant:Nn \galley_set_display_club_penalties:n { V , v } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\galley_set_interline_penalty:n} +% \begin{macro}[aux]{\galley_set_interline_penalty_aux:nn} +% \begin{macro}[aux] +% { +% \galley_set_interline_penalty_aux_i:n, +% \galley_set_interline_penalty_aux_ii:n +% } +% Dealing with the general interline penalty is handled in one shot. +% The idea is that for lines with no special penalty, the old general +% penalty is removed and the new one is added. If there is currently +% no shape set, then after adding the general interline value the +% generic build system is invoked (in case the +% \cs{etex_interlinepenalties:D} has accidentally been cleared). +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_set_interline_penalty:n #1 + { + \int_compare:nNnTF { \etex_interlinepenalties:D \c_zero } = \c_zero + { + \etex_interlinepenalties:D \c_one \int_eval:w #1 \int_eval_end: + \galley_calc_interline_penalties: + } + { + \cs_set_nopar:Npn \galley_set_interline_penalty_aux_ii:n ##1 + { + \int_eval:w + \etex_interlinepenalties:D ##1 + - \etex_interlinepenalties:D \etex_interlinepenalties:D \c_zero + + #1 + \int_eval_end: + } + \exp_args:Nf \galley_set_interline_penalty_aux:nn + { \clist_length:N \l_galley_line_penalties_clist } {#1} + } + } +\cs_new_protected_nopar:Npn \galley_set_interline_penalty_aux:nn #1#2 + { + \etex_interlinepenalties:D + \etex_interlinepenalties:D \c_zero + \prg_stepwise_function:nnnN \c_one \c_one {#1} + \galley_set_interline_penalty_aux_i:n + \prg_stepwise_function:nnnN { #1 + \c_one } \c_one + { \etex_interlinepenalties:D \c_zero - \c_one } + \galley_set_interline_penalty_aux_ii:n + \int_eval:w #2 \int_eval_end: + } +\cs_new_nopar:Npn \galley_set_interline_penalty_aux_i:n #1 + { \etex_interlinepenalties:D \int_eval:w #1 \int_eval_end: } +\cs_new_nopar:Npn \galley_set_interline_penalty_aux_ii:n #1 { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[int]{\galley_calc_interline_penalties:} +% \begin{macro}[aux]{\galley_calc_interline_penalties_aux:nn} +% \begin{macro}[aux] +% { +% \galley_calc_interline_penalties_aux_i:n, +% \galley_calc_interline_penalties_aux_ii:n +% } +% The underlying interline penalty array has to deal with club penalties, +% display club penalties and any special line penalties, and include +% the general interline penalty. These requirements lead to a rather +% complex requirement on how many lines to deal with. This is needed twice, +% so an \texttt{f}-type expansion is used to make life a little less +% complex. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_calc_interline_penalties: + { + \exp_args:Nff \galley_calc_interline_penalties_aux:nn + { + \int_eval:n + { + \int_max:nn + { + \clist_length:N \l_galley_club_penalties_clist + + \c_one + } + { + \int_max:nn + { + \clist_length:N \l_galley_line_penalties_clist + + \c_one + } + { \etex_clubpenalties:D \c_zero } + } + } + } + { \clist_length:N \l_galley_line_penalties_clist } + } +% \end{macrocode} +% The idea is now to calculate the correct penalties. Two auxiliary functions +% are used: one for any \enquote{special penalty} lines and a second for +% normal lines. At the end of the process, the standard interline +% penalty is always included. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_calc_interline_penalties_aux:nn + #1#2 + { + \etex_interlinepenalties:D #1 ~ + \prg_stepwise_function:nnnN \c_one \c_one {#2} + \galley_calc_interline_penalties_aux_i:n + \prg_stepwise_function:nnnN { #2 + \c_one } \c_one { #1 - \c_one } + \galley_calc_interline_penalties_aux_ii:n + \etex_interlinepenalties:D \etex_interlinepenalties:D \c_zero + } +\cs_new_nopar:Npn \galley_calc_interline_penalties_aux_i:n + #1 + { + \int_eval:w + \clist_item:Nn \l_galley_line_penalties_clist { #1 - \c_one } + + 0 \clist_item:Nn \l_galley_club_penalties_clist + { #1 - \c_one } + - \etex_clubpenalties:D #1 ~ + \int_eval_end: + } +\cs_new_nopar:Npn \galley_calc_interline_penalties_aux_ii:n + #1 + { + \int_eval:w + \etex_interlinepenalties:D \etex_interlinepenalties:D \c_zero + + 0 \clist_item:Nn \l_galley_club_penalties_clist + { #1 - \c_one } + - \etex_clubpenalties:D #1 ~ + \int_eval_end: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% { +% \galley_save_club_penalties:N, +% \galley_save_interline_penalties:N, +% \galley_save_display_club_penalties:N, +% \galley_save_display_widow_penalties:N, +% \galley_save_widow_penalties:N +% } +% \begin{macro}[aux] +% { +% \galley_save_display_club_penalties_aux:n, +% \galley_save_display_widow_penalties_aux:n, +% \galley_save_widow_penalties_aux:n +% } +% \begin{macro}{\galley_interline_penalty:} +% Saving the array penalties varies in complexity depending on how they are +% stored internally. The first two are easy: these are simply copies. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_save_club_penalties:N #1 + { \clist_set_eq:NN #1 \l_galley_club_penalties_clist } +\cs_new_protected_nopar:Npn \galley_save_interline_penalties:N #1 + { \clist_set_eq:NN #1 \l_galley_line_penalties_clist } +% \end{macrocode} +% These all require appropriate mappings, using the fact that +% \cs{clist_set:Nx} will tidy up the excess comma. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_save_display_club_penalties:N #1 + { + \clist_set:Nx #1 + { + \prg_stepwise_function:nnnN \c_one \c_one + { \etex_clubpenalties:D \c_zero - \c_one } + \galley_save_display_club_penalties:_aux:n + } + } +\cs_new_nopar:Npn \galley_save_display_club_penalties:_aux:n #1 + { \int_use:N \etex_clubpenaltes:D \int_eval:w #1 \int_eval_end: , } +\cs_new_protected_nopar:Npn \galley_save_display_widow_penalties:N #1 + { + \clist_set:Nx #1 + { + \prg_stepwise_function:nnnN \c_one \c_one + { \etex_displaywidowpenalties:D \c_zero - \c_one } + \galley_save_display_widow_penalties:_aux:n + } + } +\cs_new_nopar:Npn \galley_save_display_widow_penalties:_aux:n #1 + { \int_use:N \etex_displaywidowpenalties:D \int_eval:w #1 \int_eval_end: , } +\cs_new_protected_nopar:Npn \galley_save_widow_penalties:N #1 + { + \clist_set:Nx #1 + { + \prg_stepwise_function:nnnN \c_one \c_one + { \etex_widowpenalties:D \c_zero - \c_one } + \galley_save_widow_penalties:_aux:n + } + } +\cs_new_nopar:Npn \galley_save_widow_penalties:_aux:n #1 + { \int_use:N \etex_widowpenalties:D \int_eval:w #1 \int_eval_end: , } +% \end{macrocode} +% This one is not an array, but is stored in a primitive, so there is +% a simple conversion. The general interline penalty is always the +% last value in the primitive array. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \galley_interline_penalty: + { \int_use:N \etex_interlinepenalties:D \etex_interlinepenalties:D \c_zero } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{\LaTeXe{} fixes} +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Purely for testing, some internal \LaTeXe{} functions are altered to work +% with the mechanism here. This material is not comprehensive: additions are +% made as-needed for test purposes. +% +% \begin{macro}{\@afterheading} +% Set some flags and hope for the best! +% \begin{macrocode} +\cs_set_protected_nopar:Npn \@afterheading + { + \bool_gset_true:N \g_galley_no_break_next_bool + \if@afterindent + \else + \bool_gset_true:N \galley_omit_next_indent_bool + \fi + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@hangfrom} +% The \cs{tex_handindent:D} primitive is no longer used, so the paragraph +% shape is set in a different way. As a result, the label is part of the +% same paragraph as the main body, hence the need to leave vertical mode. +% \begin{macrocode} +\cs_set_protected:Npn \@hangfrom #1 + { + \setbox \@tempboxa = \hbox { {#1} } + \galley_parshape_single_par:nnnN + \c_one + { \box_wd:N \@tempboxa } + \c_zero_dim + \c_false_bool + \bool_gset_true:N \g_galley_no_break_next_bool + \bool_gset_true:N \galley_omit_next_indent_bool + \box \@tempboxa + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@makefntext} +% Here, the paragraph indent is set up using the template system, and +% as in other places the code ensures that the label is set in horizontal +% mode. The flag used for omitting the indent is once again the galley +% one. +% \begin{macrocode} +\cs_set_protected:Npn \@makefntext #1 + { + \UseTemplate { justification } { std } { indent-width = 1 em } + \bool_gset_true:N \galley_omit_next_indent_bool + \galley_leave_vmode: + \hb@xt@ 1.8em { \hss \@makefnmark } #1 + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \begin{macrocode} +%</initex|package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex
\ No newline at end of file diff --git a/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx b/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx new file mode 100644 index 00000000000..0dc1c85b610 --- /dev/null +++ b/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx @@ -0,0 +1,1602 @@ +% \iffalse +% +%% File: xgalley.dtx Copyright (C) 1999-2001, 2004-2009 Frank Mittelbach +%% (C) 2010,2011 The LaTeX3 Project +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This file is part of the "l3experimental bundle" (The Work in LPPL) +%% and all files in that bundle must be distributed together. +%% +%% The released version of this bundle is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the bundle can be found at +%% +%% http://www.latex-project.org/svnroot/experimental/trunk/ +%% +%% for those people who are interested. +%% +%%%%%%%%%%% +%% NOTE: %% +%%%%%%%%%%% +%% +%% Snapshots taken from the repository represent work in progress and may +%% not work or may contain conflicting material! We therefore ask +%% people _not_ to put them into distributions, archives, etc. without +%% prior consultation with the LaTeX Project Team. +%% +%% ----------------------------------------------------------------------- +%% +% +%<*driver|package> +\RequirePackage{l3names} +\GetIdInfo$Id: xgalley.dtx 2895 2011-10-09 15:58:19Z joseph $ + {L3 Experimental galley} +%</driver|package> +%<*driver> +\documentclass[full]{l3doc} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{^^A +% The \textsf{xgalley} package\\ Galley^^A +% \thanks{This file describes v\ExplFileVersion, +% last revised \ExplFileDate.}^^A +% } +% +% \author{^^A +% The \LaTeX3 Project\thanks +% {^^A +% E-mail: +% \href{mailto:latex-team@latex-project.org} +% {latex-team@latex-project.org}^^A +% }^^A +% } +% +% \date{Released \ExplFileDate} +% +% \maketitle +% +% \begin{documentation} +% +% \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 behaviour. +% +% 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 A 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 +% } +% {0 pt} +% \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 +% } +% {0 pt} +% \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, \emph{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. +% } +% {0 pt} +% \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. +% } +% {0 pt} +% \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 A 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 +% } +% {0 pt} +% \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 +% } +% {0 pt} +% \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.} +% {0 pt plus 1 fil} +% \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 +% } +% {0 pt} +% \TemplateKey{right-skip}{skip} +% {^^A +% The skip between the right margin of the galley and the right edge of a +% paragraph.^^A +% } +% {0 pt} +% \TemplateKey{start-skip}{skip} +% {^^A +% The skip inserted in addition to |indent-width| at the start of a +% paragraph.^^A +% } +% {0 pt} +% \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}{15 pt} +% \InstanceSemantics +% Sets paragraphs fully-justified with the first line indented by +% |15 pt|. +% \end{InstanceDescription} +% +% \begin{InstanceDescription}{justification}{noindent}{std} +% \InstanceKey{end-skip}{15 pt plus 1 fil} +% \InstanceKey{indent-width}{0 pt} +% \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.} +% {0 pt plus 1 fil} +% \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 +% } +% {0 pt} +% \TemplateKey{right-skip}{skip} +% {^^A +% The skip between the right margin of the galley and the right edge of a +% paragraph.^^A +% } +% {0 pt} +% \TemplateKey{start-skip}{skip} +% {^^A +% The skip inserted in addition to |indent-width| at the start of a +% paragraph.^^A +% } +% {0 pt} +% \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}{justification}{centered}{std} +% \InstanceKey{end-skip}{0 pt} +% \InstanceKey{fixed-word-spacing}{true} +% \InstanceKey{indent-width}{0 pt} +% \InstanceKey{left-skip}{0 pt plus 1 em} +% \InstanceKey{right-skip}{0 pt plus 1 em} +% \InstanceSemantics +% Centres typeset material such that hyphenation will still occur and +% such that very short lines are discouraged. This is similar to the +% \LaTeXe{} \pkg{ragged2e} \env{Centering} environment. +% \end{InstanceDescription} +% +% \begin{InstanceDescription}{justification}{ragged-left}{std} +% \InstanceKey{end-skip}{0 pt} +% \InstanceKey{fixed-word-spacing}{true} +% \InstanceKey{indent-width}{0 pt} +% \InstanceKey{left-skip}{0 pt plus 2 em} +% \InstanceKey{right-skip}{0 pt} +% \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}{justification}{ragged-right}{std} +% \InstanceKey{end-skip}{0 pt} +% \InstanceKey{fixed-word-spacing}{true} +% \InstanceKey{indent-width}{0 pt} +% \InstanceKey{left-skip}{0 pt} +% \InstanceKey{right-skip}{0 pt plus 2 em} +% \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}{justification}{center}{std} +% \InstanceKey{end-skip}{0 pt} +% \InstanceKey{fixed-word-spacing}{true} +% \InstanceKey{indent-width}{0 pt} +% \InstanceKey{left-skip}{0 pt plus 1 fil} +% \InstanceKey{right-skip}{0 pt plus 1 fil} +% \InstanceSemantics +% Centres typeset material such that hyphenation is strongly discouraged +% and short lines are allowed. This template is suited to centring arbitrary +% material (such as boxes) rather than centring text. In the later case, the +% |centered| instance should be used. +% \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 +% } +% {10 000} +% \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 +% } +% {0 pt} +% \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.1 pt} +% \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 behaviour 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, \emph{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.1 pt} +% \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.} +% {10 000} +% \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}{paragraph-breaking}{nobreak}{std} +% \InstanceKey{interline-penalty}{10 000} +% \InstanceKey{post-display-penalty}{10 000} +% \InstanceSemantics +% Sets paragraphs such that they cannot be broken at all (as far as is +% possible in \TeX{}). +% \end{InstanceDescription} +% +% \begin{InstanceDescription}{paragraph-breaking}{nolone}{std} +% \InstanceKey{club-penalty}{10 000} +% \InstanceKey{display-widow-penalty}{10 000} +% \InstanceKey{widow-penalty}{10 000} +% \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}{paragraph-breaking}{single-nobreak}{single} +% \InstanceKey{interline-penalty}{10 000} +% \InstanceKey{post-display-penalty}{10 000} +% \InstanceSemantics +% Sets the next paragraph such that it cannot be broken at all (as far as is +% possible in \TeX{}). +% \end{InstanceDescription} +% +% \begin{InstanceDescription}{paragraph-breaking}{single-noclub}{single} +% \InstanceKey{club-penalty}{10 000} +% \InstanceKey{display-club-penalty}{10 000} +% \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}{paragraph-breaking}{single-nolone}{single} +% \InstanceKey{club-penalty}{10 000} +% \InstanceKey{display-club-penalty}{10 000} +% \InstanceKey{display-widow-penalty}{10 000} +% \InstanceKey{widow-penalty}{10 000} +% \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}{paragraph-breaking}{single-nowidow}{single} +% \InstanceKey{display-widow-penalty}{10 000} +% \InstanceKey{widow-penalty}{10 000} +% \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} +\ProvidesExplPackage + {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} +\RequirePackage{xparse,xtemplate,l3galley} +% \end{macrocode} +% +% \subsection{Variables} +% +% \begin{variable}{\l_galley_tmpa_clist, \l_galley_tmpb_clist} +% Scratch space. +% \begin{macrocode} +\clist_new:N \l_galley_tmpa_clist +\clist_new:N \l_galley_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 = 0 pt , + right-margin : length = 0 pt + } +\DeclareTemplateInterface { measure } { relative } { 0 } + { + left-margin : length = 0 pt , + right-margin : length = 0 pt + } +% \end{macrocode} +% +% \begin{variable}{\l_galley_left_margin_dim, \l_galley_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_galley_left_margin_dim \leftmargin +%</package> +%<*package> +\cs_new_eq:NN \l_galley_right_margin_dim \rightmargin +%</package> +\DeclareTemplateCode { measure } { absolute } { 0 } + { + left-margin = \l_galley_left_margin_dim , + right-margin = \l_galley_right_margin_dim + } + { + \AssignTemplateKeys + \galley_margins_set_absolute:nn \l_galley_left_margin_dim + \l_galley_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_galley_left_margin_dim , + right-margin = \l_galley_right_margin_dim + } + { + \AssignTemplateKeys + \galley_margins_set_relative:nn \l_galley_left_margin_dim + \l_galley_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 = 0 pt , + on-left-side : boolean = true , + lines : integer = 1 + } +\DeclareTemplateInterface { parshape } { initial } { 0 } + { + indent : length = 0 pt , + on-left-side : boolean = true , + lines : integer = 2 + } +% \end{macrocode} +% \begin{variable}{\l_galley_parshape_indent_dim} +% \begin{variable}{\l_galley_parshape_on_left_bool} +% \begin{variable}{\l_galley_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_galley_parshape_indent_dim , + on-left-side = \l_galley_parshape_on_left_bool , + lines = \l_galley_parshape_lines_int + } + { + \AssignTemplateKeys + \bool_if:NTF \l_galley_parshape_on_left_bool + { + \galley_parshape_single_par:nVVN + \l_galley_parshape_lines_int + \l_galley_parshape_indent_dim + \c_zero_dim + \c_false_bool + } + { + \galley_parshape_single_par:nVVN + \l_galley_parshape_lines_int + \c_zero_dim + \l_galley_parshape_indent_dim + \c_false_bool + } + } +\DeclareTemplateCode { parshape } { initial } { 0 } + { + indent = \l_galley_parshape_indent_dim , + on-left-side = \l_galley_parshape_on_left_bool , + lines = \l_galley_parshape_lines_int + } + { + \AssignTemplateKeys + \clist_clear:N \l_galley_tmpa_clist + \clist_clear:N \l_galley_tmpb_clist + \prg_replicate:nn { \l_galley_parshape_lines_int } + { + \clist_put_right:Nn \l_galley_tmpa_clist + { \l_galley_parshape_indent_dim } + \clist_put_right:Nn \l_galley_tmpb_clist + { \c_zero_dim } + } + \bool_if:NTF \l_galley_parshape_on_left_bool + { + \galley_parshape_single_par:nVVN + \c_zero + \l_galley_tmpa_clist + \l_galley_tmpb_clist + \c_true_bool + } + { + \galley_parshape_single_par:nVVN + \c_zero + \l_galley_tmpb_clist + \l_galley_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 } + } , + } + } + { + \AssignTemplateKeys + \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_galley_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_galley_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 = 0 pt plus 1 fil , + fixed-word-spacing : boolean = false , + indent-width : length , + left-skip : skip = 0 pt , + right-skip : skip = 0 pt , + start-skip : skip = 0 pt , + stretch-last-line : boolean = false + } +\DeclareTemplateInterface { justification } { single } { 0 } + { + end-skip : skip = 0 pt plus 1 fil , + fixed-word-spacing : boolean = false , + indent-width : length , + left-skip : skip = 0 pt , + right-skip : skip = 0 pt , + start-skip : skip = 0 pt , + 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 + } + { + \AssignTemplateKeys + \tl_clear:N \l_galley_justification_other_tl + \galley_set_interword_spacing:N \l_galley_fixed_spacing_bool + \bool_if:NTF \l_galley_par_stretch_last_bool + { \int_set_eq:NN \l_galley_last_line_fit_int \c_one_thousand } + { \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:Nx \l_galley_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_set_interword_space: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_start_skip + { \skip_use:N \l_galley_par_start_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_galley_justification_other_tl } + \AssignTemplateKeys + \galley_set_interword_spacing:N \l_galley_fixed_spacing_bool + \bool_if:NTF \l_galley_par_stretch_last_bool + { \int_set_eq:NN \l_galley_last_line_fit_int \c_one_thousand } + { \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 = 15 pt } +\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 = 15 pt plus 1 fil , + indent-width = 0 pt + } +% \end{macrocode} +% The other standard justification schemes are for text which is either +% centred or 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 } { centered } { std } + { + end-skip = 0 pt , + fixed-word-spacing = true , + indent-width = 0 pt , + left-skip = 0 pt plus 1 em , + right-skip = 0 pt plus 1 em + } +\DeclareInstance { justification } { ragged-left } { std } + { + end-skip = 0 pt , + fixed-word-spacing = true , + indent-width = 0 pt , + left-skip = 0 pt plus 2 em , + right-skip = 0 pt + } +\DeclareInstance { justification } { ragged-right } { std } + { + end-skip = 0 pt plus 1 fil , + fixed-word-spacing = true , + indent-width = 0 pt , + left-skip = 0 pt , + right-skip = 0 pt plus 2 em + } +% \end{macrocode} +% The \texttt{centering} instance is used to centre material without +% hyphenation: this is used for centring arbitrary material rather +% than text. +% \begin{macrocode} +\DeclareInstance { justification } { centering } { std } + { + end-skip = 0 pt , + fixed-word-spacing = true , + indent-width = 0 pt , + left-skip = 0 pt plus 1 fil , + right-skip = 0 pt plus 1 fil + } +% \end{macrocode} +% +% \begin{macro}{\galley_justification_first:, \galley_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 = \galley_justification_first: , + other-paragraphs = \galley_justification_other: + } + { + \AssignTemplateKeys + \galley_justification_first: + \tl_set:Nn \l_galley_justification_other_tl + { \galley_justification_other: } + \tl_gput_right:Nn \g_galley_restore_running_tl + { \l_galley_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 = 10 000 , + emergency-stretch : skip = 0 pt , + final-hyphen-demerits : integer = 5000 , + fuzz : length = 0.1 pt , + line-penalty : integer = 10 , + mismatch-demerits : integer = 10 000 , + pretolerance : integer = 100 , + relation-penalty : integer = 500 , + tolerance : integer = 200 + } +\DeclareTemplateCode{ line-breaking } { std } { 0 } + { + badness = \l_galley_linebreak_badness_int , + binop-penalty = \l_galley_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_galley_linebreak_penalty_int , + mismatch-demerits = \l_galley_mismatch_demerits_int , + pretolerance = \l_galley_linebreak_pretolerance_int , + relation-penalty = \l_galley_relation_penalty_int , + tolerance = \l_galley_linebreak_tolerance_int + } + { \AssignTemplateKeys } +% \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_galley_club_penalty_int , +% \l_galley_display_club_penalty_int , +% \l_galley_display_widow_penalty_int , +% \l_galley_interline_penalty_int , +% \l_galley_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.1 pt , + interline-penalty : integer = 0 , + post-display-penalty : integer = 0 , + pre-display-penalty : integer = 10 000 , + widow-penalty : integer = 150 + } +\DeclareTemplateCode { paragraph-breaking } { std } { 0 } + { + badness = \l_galley_parbreak_badness_int , + broken-penalty = \l_galley_broken_penalty_int , + club-penalty = \l_galley_club_penalty_int , + display-club-penalty = \l_galley_display_club_penalty_int , + display-widow-penalty = \l_galley_display_widow_penalty_int , + fuzz = \l_galley_parbreak_fuzz_dim , + interline-penalty = \l_galley_interline_penalty_int , + post-display-penalty = \l_galley_post_display_penalty_int , + pre-display-penalty = \l_galley_pre_display_penalty_int , + widow-penalty = \l_galley_widow_penalty_int + } + { + \AssignTemplateKeys + \galley_set_club_penalties:V \l_galley_club_penalty_int + \galley_set_display_club_penalties:V \l_galley_display_club_penalty_int + \galley_set_display_widow_penalties:V \l_galley_display_widow_penalty_int + \galley_set_interline_penalty:n \l_galley_interline_penalty_int + \galley_set_widow_penalties:V \l_galley_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_galley_parbreak_badness_tl , +% \l_galley_broken_penalty_tl , +% \l_galley_club_penalties_tl , +% \l_galley_display_club_penalties_tl , +% \l_galley_display_widow_penalties_tl , +% \l_galley_parbreak_fuzz_tl , +% \l_galley_interline_penalty_tl , +% \l_galley_post_display_penalty_tl , +% \l_galley_pre_display_penalty_tl , +% \l_galley_widow_penalties_tl , +% \c_galley_parbreak_multi_seq , +% \c_galley_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_galley_parbreak_badness_tl , + broken-penalty = \l_galley_broken_penalty_tl , + club-penalty = \l_galley_club_penalties_tl , + display-club-penalty = \l_galley_display_club_penalties_tl , + display-widow-penalty = \l_galley_display_widow_penalties_tl , + fuzz = \l_galley_parbreak_fuzz_tl , + interline-penalty = \l_galley_interline_penalty_tl , + post-display-penalty = \l_galley_post_display_penalty_tl , + pre-display-penalty = \l_galley_pre_display_penalty_tl , + widow-penalty = \l_galley_widow_penalties_tl + } + { + \AssignTemplateKeys +% \end{macrocode} +% The fuzz and interline penalties are handled explicitly as they have +% particular requirements. +% \begin{macrocode} + \tl_if_empty:NF \l_galley_interline_penalty_tl + { + \tl_gput_right:Nx \g_galley_par_after_hook_tl + { + \int_set:Nn \exp_not:N \l_galley_interline_penalty_int + { \galley_interline_penalty: } + } + \int_set:Nn \l_galley_interline_penalty_int + { \l_galley_interline_penalty_tl } + } + \tl_if_empty:NF \l_galley_parbreak_fuzz_tl + { + \tl_gput_right:Nx \g_galley_par_after_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_galley_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_galley_parbreak_single_seq + { + \tl_if_empty:cF { l_galley_ ##1 _tl } + { + \tl_gput_right:Nx \g_galley_par_after_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. +% \begin{macrocode} + \seq_map_inline:Nn \c_galley_parbreak_multi_seq + { + \tl_if_empty:cF { l_galley_ ##1 _tl } + { + \use:c { galley_save_ ##1 :N } \l_galley_tmpa_clist + \tl_gput_right:Nx \g_galley_par_after_hook_tl + { + \exp_not:c { galley_set_ ##1 :n } + { \exp_not:o \l_galley_tmpa_clist } + } + \use:c { galley_set_ ##1 :v } { l_galley_ ##1 _tl } + } + } + } +\seq_new:N \c_galley_parbreak_multi_seq +\seq_gput_right:Nn \c_galley_parbreak_multi_seq { club_penalties } +\seq_gput_right:Nn \c_galley_parbreak_multi_seq { display_club_penalties } +\seq_gput_right:Nn \c_galley_parbreak_multi_seq { display_widow_penalties } +\seq_gput_right:Nn \c_galley_parbreak_multi_seq { widow_penalties } +\seq_new:N \c_galley_parbreak_single_seq +\seq_gput_right:Nn \c_galley_parbreak_single_seq { parbreak_badness } +\seq_gput_right:Nn \c_galley_parbreak_single_seq { broken_penalty } +\seq_gput_right:Nn \c_galley_parbreak_single_seq { post_display_penalty } +\seq_gput_right:Nn \c_galley_parbreak_single_seq { 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 + } + { + \AssignTemplateKeys + \tl_if_empty:NF \l_galley_display_begin_par_vpenalty_tl + { + \tl_set:Nx \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:Nx \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:Nx \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:Nx \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 + } + { + \AssignTemplateKeys + \tl_if_empty:NF \l_galley_display_end_par_vpenalty_tl + { + \tl_set:Nx \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:Nx \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:Nx \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:Nx \l_galley_display_end_vspace_tl + { \skip_eval:n { \l_galley_display_end_vspace_tl } } + } + } +% \end{macrocode} +% +% \subsection{\LaTeXe{} functions} +% +% \begin{macro}{\nobreak} +% \begin{macro}{\noindent} +% \begin{macro}{\vspace} +% In package mode, some of \LaTeXe{}'s functions are re-implemented using +% the galley system. Not all of the optional arguments currently work! +% \begin{macrocode} +\RenewDocumentCommand \nobreak { } + { \bool_gset_true:N \g_galley_no_break_next_bool } +\RenewDocumentCommand \noindent { } + { \bool_gset_false:N \g_galley_omit_next_indent_bool } +\RenewDocumentCommand \vspace { s m } { \galley_set_vspace_user:n {#2} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.ins b/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.ins new file mode 100644 index 00000000000..cadc1d2a98f --- /dev/null +++ b/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.ins @@ -0,0 +1,41 @@ +\iffalse meta-comment + +File xgalley.ins Copyright (C) 2010,2011 The LaTeX3 Project + +It may be distributed and/or modified under the conditions of the +LaTeX Project Public License (LPPL), either version 1.3c of this +license or (at your option) any later version. The latest version +of this license is in the file + + http://www.latex-project.org/lppl.txt + +This file is part of the "l3experimental bundle" (The Work in LPPL) +and all files in that bundle must be distributed together. + +The released version of this bundle is available from CTAN. + +\fi + +\input docstrip.tex +\askforoverwritefalse + +\preamble + +EXPERIMENTAL CODE + +Do not distribute this file without also distributing the +source files specified above. + +Do not distribute a modified version of this file. + +\endpreamble +% stop docstrip adding \endinput +\postamble +\endpostamble + +\keepsilent + +\generate{\file{l3galley.sty}{\from{l3galley.dtx}{package}}} +\generate{\file{xgalley.sty} {\from{xgalley.dtx} {package}}} + +\endbatchfile |