summaryrefslogtreecommitdiff
path: root/macros/luatex/latex/lua-typo
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2023-02-05 03:01:59 +0000
committerNorbert Preining <norbert@preining.info>2023-02-05 03:01:59 +0000
commit478726121e4185461616cf790eb4da8604ae2e2c (patch)
tree0e819f3cfcccd7db36b231580b5c6f7faee507f7 /macros/luatex/latex/lua-typo
parentdc612812fbda1ab7fc28a6c80576bb1e8aae6ff2 (diff)
CTAN sync 202302050301
Diffstat (limited to 'macros/luatex/latex/lua-typo')
-rw-r--r--macros/luatex/latex/lua-typo/README.md20
-rw-r--r--macros/luatex/latex/lua-typo/doc/lua-typo-demo.pdfbin16794 -> 16859 bytes
-rw-r--r--macros/luatex/latex/lua-typo/doc/lua-typo-fr.pdfbin64171 -> 80360 bytes
-rw-r--r--macros/luatex/latex/lua-typo/doc/lua-typo.pdfbin138442 -> 169623 bytes
-rw-r--r--macros/luatex/latex/lua-typo/source/lua-typo.dtx998
5 files changed, 707 insertions, 311 deletions
diff --git a/macros/luatex/latex/lua-typo/README.md b/macros/luatex/latex/lua-typo/README.md
index 64373e6913..a9c6c7a2aa 100644
--- a/macros/luatex/latex/lua-typo/README.md
+++ b/macros/luatex/latex/lua-typo/README.md
@@ -28,15 +28,15 @@ Installation
------------
This bundle is meant to be included in most TeX distributions,
-but if you need to install it by yourself
+but if you really need to install it by yourself
1. run "luatex lua-typo.dtx" to strip the comments and create
lua-typo.sty, lua-typo.cfg, lua-typo.ltx and lua-typo-fr.ltx;
2. run "lualatex lua-typo.ltx" to get the full documentation
(lua-typo.pdf) in English;
-2. run "lualatex lua-typo-fr.ltx" to get the French documentation
- (lua-typo-fr.pdf, code not included).
+3. run "lualatex lua-typo-fr.ltx" to get the French documentation
+ (lua-typo-fr.pdf, without documented code).
-Recommended loactions for installation:
+Recommended locations for installation:
- TDS:tex/lualatex/lua-typo/lua-typo.sty
- TDS:tex/lualatex/lua-typo/lua-typo.cfg
- TDS:doc/lualatex/lua-typo/lua-typo.pdf
@@ -45,6 +45,9 @@ Recommended loactions for installation:
- TDS:doc/lualatex/lua-typo/README.md
- TDS:source/lualatex/lua-typo/lua-typo.dtx
+On Debian based systems, the "TDS:" prefix can be replaced by "$HOME/texmf/"
+for a single user installation.
+
Changes
-------
@@ -69,6 +72,13 @@ Changes
- coloration of faulty lines improved;
- all flaws found are now recorded into file "`\jobname`.typo".
+* v.0.51 (not released): bug fix
+ - in some cases orphans were not detected.
+
+* v.0.60: new implementation, Feb. 2023
+ - this version should do a better job on two columns documents;
+ - debugging stuff added.
+
--
-Copyright 2020--2021 Daniel Flipo
+Copyright 2020--2023 Daniel Flipo
E-mail: daniel (dot) flipo (at) free (dot) fr
diff --git a/macros/luatex/latex/lua-typo/doc/lua-typo-demo.pdf b/macros/luatex/latex/lua-typo/doc/lua-typo-demo.pdf
index 89951bdf86..9b4721716e 100644
--- a/macros/luatex/latex/lua-typo/doc/lua-typo-demo.pdf
+++ b/macros/luatex/latex/lua-typo/doc/lua-typo-demo.pdf
Binary files differ
diff --git a/macros/luatex/latex/lua-typo/doc/lua-typo-fr.pdf b/macros/luatex/latex/lua-typo/doc/lua-typo-fr.pdf
index 315c8306e1..0b96add63d 100644
--- a/macros/luatex/latex/lua-typo/doc/lua-typo-fr.pdf
+++ b/macros/luatex/latex/lua-typo/doc/lua-typo-fr.pdf
Binary files differ
diff --git a/macros/luatex/latex/lua-typo/doc/lua-typo.pdf b/macros/luatex/latex/lua-typo/doc/lua-typo.pdf
index 5b2b2dcbdf..4f50db5529 100644
--- a/macros/luatex/latex/lua-typo/doc/lua-typo.pdf
+++ b/macros/luatex/latex/lua-typo/doc/lua-typo.pdf
Binary files differ
diff --git a/macros/luatex/latex/lua-typo/source/lua-typo.dtx b/macros/luatex/latex/lua-typo/source/lua-typo.dtx
index ebcd727a67..29e087ccb1 100644
--- a/macros/luatex/latex/lua-typo/source/lua-typo.dtx
+++ b/macros/luatex/latex/lua-typo/source/lua-typo.dtx
@@ -1,9 +1,5 @@
-% \CheckSum{373}
-%
% \iffalse meta-comment
%
-% Copyright © 2020-2021 Daniel Flipo.
-%
% This program can be distributed and/or modified under the terms
% of the LaTeX Project Public License either version 1.3c of this
% license or (at your option) any later version.
@@ -16,7 +12,7 @@
%
% Lua-Typo package for LaTeX version 2e
%
-% Copyright © 2020-2021 by Daniel Flipo
+% Copyright © 2020-2023 by Daniel Flipo
%
% Please report errors to: daniel (dot) flipo (at) free (dot) fr
%
@@ -36,12 +32,18 @@
\let\MetaPrefix\DoubleperCent
\askforoverwritefalse
\generate{%
- \file{lua-typo.sty}{\from{lua-typo.dtx}{sty}}% {sty,dbg}
- \nopreamble
- \file{lua-typo.cfg}{\from{lua-typo.dtx}{cfg}}%
- \file{lua-typo-fr.ltx}{\from{lua-typo.dtx}{driver,docfr}}%
- \file{lua-typo.ltx}{\from{lua-typo.dtx}{driver,doc}}%
-}
+ \file{lua-typo.sty}{\from{lua-typo.dtx}{sty}}%
+ \nopreamble
+ \file{lua-typo.cfg}{\from{lua-typo.dtx}{cfg}}%
+ \file{lua-typo-fr.ltx}{\from{lua-typo.dtx}{driver,docfr}}%
+ \file{lua-typo.ltx}{\from{lua-typo.dtx}{driver,doc}}%
+ }
+\iffalse
+ \generate{%
+ \file{lua-typo.sty}{\from{lua-typo.dtx}{sty,dbg}}%
+ \file{scan-page.sty}{\from{lua-typo.dtx}{scan}}%
+ }
+\fi
\endbatchfile
%</batch>
%<*gobble>
@@ -51,24 +53,24 @@
%</gobble>
%<*driver>
\RequirePackage{pdfmanagement-testphase}
-%<-docfr>\DeclareDocumentMetadata{pdfstandard=A-2b, lang=en-GB}
-%<-doc>\DeclareDocumentMetadata{pdfstandard=A-2b, lang=fr-FR}
+%<+doc>\DeclareDocumentMetadata{pdfstandard=A-2b, lang=en-GB}
+%<+docfr>\DeclareDocumentMetadata{pdfstandard=A-2b, lang=fr-FR}
\documentclass[a4paper]{ltxdoc}
\usepackage[dvipsnames]{xcolor}
\usepackage{fontspec}
\setmainfont{erewhon}
\setsansfont{Cabin}[Scale=MatchLowercase]
\setmonofont{VeraMono.ttf}[
+ Scale = MatchLowercase,
ItalicFont = VeraMoIt.ttf,
BoldFont = VeraMoBd.ttf,
BoldItalicFont = VeraMoBI.ttf,
- Scale = MatchLowercase,
HyphenChar=None, Color=Sepia,
]
\usepackage[expansion=true, protrusion=true]{microtype}
-%<-docfr>\usepackage[british]{babel}
-%<-doc>\usepackage[french]{babel}
-%<-doc>\frenchsetup{og=«, fg=»}
+%<+doc>\usepackage[british]{babel}
+%<+docfr>\usepackage[french]{babel}
+%<+docfr>\frenchsetup{og=«, fg=»}
\usepackage[ShortPages, OverfullLines, UnderfullLines,
Widows, Orphans, EOPHyphens, RepeatedHyphens
]{lua-typo}
@@ -79,24 +81,27 @@
\usepackage[numbered]{hypdoc}
\hypersetup{colorlinks,urlcolor=blue,unicode}
%
-%<-doc>\OnlyDescription
-%<-doc>\let\FrenchDoc\begingroup\let\endFrenchDoc\endgroup
-%
-%<-docfr>\let\FrenchDoc\comment\let\endFrenchDoc\endcomment
-%<-docfr>\RecordChanges
-%<-docfr>\AtEndDocument{%
-%<-docfr> \clearpage
-%<-docfr> \section{Change History}%
-%<-docfr> \GlossaryPrologue{}%
-%<-docfr> Changes are listed in reverse order (latest first)
-%<-docfr> from version~0.30.
-%<-docfr> \PrintChanges
-%<-docfr>}
-%
+%<+docfr>\OnlyDescription
+%<+docfr>\let\FrenchDoc\begingroup\let\endFrenchDoc\endgroup
+%<+doc|docfr>\let\Debugging\comment\let\endDebugging\endcomment
+%<*doc>
+\let\FrenchDoc\comment\let\endFrenchDoc\endcomment
+\RecordChanges
+\AtEndDocument{%
+ \clearpage
+ \section{Change History}%
+ \GlossaryPrologue{}%
+ Changes are listed in reverse order (latest first)
+ from version~0.30.
+ \PrintChanges
+}
+%</doc>
+\newcommand*\texdir[1]{\textsc{#1}}
\newcommand*\file[1]{\texttt{#1}}
\newcommand*\pkg[1]{\texttt{#1}}
\newcommand*\opt[1]{\texttt{#1}}
\renewcommand\meta[1]{\texttt{\textsl{\color{Sepia}<#1>}}}
+\newcommand*\node[1]{\textsc{#1}}
%
\setlength{\parindent}{0pt}
\setlength{\parskip}{.3\baselineskip plus 0.3pt minus 0.3pt}
@@ -155,6 +160,16 @@
% d’une coupure malvenue ne va pas provoquer des désordres plus
% graves encore.
%
+% Un outil potentiellement utile est la commande TeX |\spaceskip|
+% qui, utilisée dans un groupe, permet de modifier localement
+% l’espace inter-mots. Un léger accroissement de celui-ci dans un
+% paragraphe peut rendre acceptable la dernière ligne de celui-ci
+% alors qu’elle était trop courte ou, si elle était presque pleine,
+% lui ajouter une ligne, supprimant ainsi une orpheline éventuelle.
+% De même une légère réduction de l’espace inter-mots peut supprimer
+% la dernière ligne (courte) d’un paragraphe et éviter une veuve en
+% début de la page suivante.
+%
% Je conseille de n’appliquer \pkg{lua-typo} que sur des textes
% « presque au point », d’améliorer ce qui peut l’être puis de
% \emph{supprimer} l’appel à \pkg{lua-typo} afin de ne pas risquer
@@ -163,7 +178,7 @@
% \pkg{lua-typo}, il suffit d’ajouter dans le préambule la ligne\\
% |\usepackage[All]{lua-typo}|
%
-% La version courante (0.50) nécessite un noyau LaTeX très récent,
+% La version courante (0.60) nécessite un noyau LaTeX récent,
% 2021/06/01 ou ultérieur. Ceux qui ne disposent que d’un noyau plus
% ancient reçoivent un message d’avertissement et un message d’erreur
% «\texttt{Unable to register callback}» ; une version «rollback »
@@ -173,6 +188,7 @@
% Les fichiers \file{demo.tex} et \file{demo.pdf} fournissent un
% exemple du traitement opéré par \pkg{lua-typo}.
%
+% \pagebreak[4]
% Un grand merci à Jacques André et Thomas Savary pour avoir accepté
% de tester les pré-versions et pour leurs retours riches et toujours
% pertinents ; leurs suggestions et leurs encouragements ont
@@ -286,10 +302,10 @@
%
% Le fichier \file{lua-typo.cfg} fourni avec la distribution reprend
% exactement les réglages internes, il se trouve normalement dans le
-% répertoire \textsc{texmfdist} des distributions TeXLive, MikTeX, etc.
+% répertoire \texdir{texmfdist} des distributions TeXLive, MikTeX, etc.
% L’utilisateur a la possibilité de recopier ce fichier soit dans son
% répertoire de travail pour un document particulier, soit dans son
-% répertoire \textsc{texmfhome} ou \textsc{texmflocal} et de le
+% répertoire \texdir{texmfhome} ou \texdir{texmflocal} et de le
% personnaliser comme il l’entend.
%
% Voici la liste complète des paramètres personnalisables avec leur
@@ -379,8 +395,8 @@
% \luatypoSetColor4{cyan} % Veuve
% \luatypoSetColor5{cyan} % Orpheline
% \luatypoSetColor6{cyan} % Dernière ligne d’alinéa trop courte
-% \luatypoSetColor7{mygrey} % Ligne trop pleine
-% \luatypoSetColor8{mygrey} % Ligne creuse
+% \luatypoSetColor7{blue} % Ligne trop pleine
+% \luatypoSetColor8{blue} % Ligne creuse
% \luatypoSetColor9{red} % Page presque vide (qq. lignes)
% \luatypoSetColor{10}{myred} % Répétitions en début de ligne
% \luatypoSetColor{11}{myred} % Répétitions en fin de ligne
@@ -424,17 +440,26 @@
% issues (underflow/overfull lines) when fixing one of the flaws
% mentionned above, human correction providing much better results.
% For completeness, overfull and underfull lines are also coloured
-% (in grey by default) and mentionned in the summary provided at the
+% (in blue by default) and mentionned in the summary provided at the
% end of the \file{.log} file.
%
+% The TeX commands |\spaceskip| and |\xspaceskip| which alter the
+% inter-word spacing (locally when used in a group) should be
+% considered: slightly enlarging the inter-word space may be
+% sufficient to make a paragraph’s last line acceptable when it was
+% originally too short or add a line to a paragraph when its last
+% line was nearly full, thus possibly removing an orphan.
+% Conversely, slightly reducing it may remove a paragraph’s last line
+% (when it was short) and get rid of a widow on top of next page.
+%
% I suggest to add a call |\usepackage[All]{lua-typo}| to the
% preamble of a document which is ``nearly finished’’
% \emph{and to remove it} once all possible corrections have been
% made: if some flaws remain, getting them printed in colour in
% the final document would be a shame!
%
-% This version (0.50) requires the latest LaTeX kernel (dated
-% 2021/06/01). Users running an older kernel will get a warning
+% Starting with version 0.50 a recent LaTeX kernel (dated 2021/06/01)
+% is reiquired. Users running an older kernel will get a warning
% and an error message ``\texttt{Unable to register callback}’’;
% for them, a ``rollback’’ version of \pkg{lua-typo} is provided,
% it can be loaded this way: |\usepackage[All]{lua-typo}[=v0.4]|.
@@ -461,7 +486,6 @@
% or to enable just a few checks, then do it this way:\\
% |\usepackage[|\meta{OptX}|, |\meta{OptY}|, |\meta{OptZ}|]{lua-typo}|
%
-% \pagebreak
% Here is the full list of possible checks (name and purpose):\\[12pt]
% \begin{tabular}{>{\ttfamily}ll}
% \multicolumn{1}{l}{Name} & Glitch to highlight\\ \hline
@@ -537,16 +561,16 @@
%
% A default configuration file \file{lua-typo.cfg} is provided
% with all parameters set to their defaults; it is located under
-% the \textsc{texmfdist} directory. It is up to the users to copy
-% this file into their working directory (or \textsc{texmfhome} or
-% \textsc{texmflocal}) and tune the defaults according to their own
+% the \texdir{texmfdist} directory. It is up to the users to copy
+% this file into their working directory (or \texdir{texmfhome} or
+% \texdir{texmflocal}) and tune the defaults according to their own
% taste.
%
% It is also possible to provide defaults directly in the
% document’s preamble (this overwrites the corresponding settings
% done in the configuration file found on TeX’s search path: current
-% directory, then \textsc{texmfhome}, \textsc{texmflocal} and
-% finally \textsc{texmfdist}.
+% directory, then \texdir{texmfhome}, \texdir{texmflocal} and
+% finally \texdir{texmfdist}.
%
% Here are the parameters names (all prefixed by |luatypo| in order
% to avoid conflicts with other packages) and their default values:
@@ -626,8 +650,8 @@
% \luatypoSetColor4{cyan} % Widow
% \luatypoSetColor5{cyan} % Orphan
% \luatypoSetColor6{cyan} % Paragraph ending on a short line
-% \luatypoSetColor7{mygrey} % Overfull lines
-% \luatypoSetColor8{mygrey} % Underfull lines
+% \luatypoSetColor7{blue} % Overfull lines
+% \luatypoSetColor8{blue} % Underfull lines
% \luatypoSetColor9{red} % Nearly empty page (a few lines)
% \luatypoSetColor{10}{myred} % First word matches
% \luatypoSetColor{11}{myred} % Last word matches
@@ -645,18 +669,18 @@
% \section{\TeX{}nical details}
%
% \iffalse
-%<*sty>
+%<*sty|scan>
%% IMPORTANT NOTICE:
%% For the copyright see the source file `lua-typo.dtx’.
%%
-\ProvidesPackage{lua-typo}
-%</sty>
-%<*dtx>
-\ProvidesFile{lua-typo.dtx}
-%</dtx>
-%<*dtx|sty>
- [2021/05/13 v.0.50 Daniel Flipo]
-%</dtx|sty>
+\NeedsTeXFormat{LaTeX2e}[2021/06/01]
+%</sty|scan>
+%<+sty>\ProvidesPackage{lua-typo}
+%<+scan>\ProvidesPackage{scan-page}
+%<+dtx>\ProvidesFile{lua-typo.dtx}
+%<*dtx|sty|scan>
+ [2023-02-04 v.0.60 Daniel Flipo]
+%</dtx|sty|scan>
%<*sty>
% \fi
%
@@ -671,10 +695,10 @@
% \begin{macrocode}
\ifdefined\DeclareRelease
\DeclareRelease{v0.4}{2021-01-01}{lua-typo-2021-04-18.sty}
- \DeclareCurrentRelease{}{2021-05-13}
+ \DeclareCurrentRelease{}{2023-02-04}
\else
\PackageWarning{lua-typo}{Your LaTeX kernel is too old to provide
- access\MessageBreak to former versions of the lettrine package.%
+ access\MessageBreak to former versions of the lua-typo package.%
\MessageBreak Anyway, lua-typo requires a LaTeX kernel dated%
\MessageBreak 2020-01-01 or newer; reported}
\fi
@@ -927,11 +951,11 @@ luatypo = { }
\directlua{
texio.write_nl(' ')
texio.write_nl('*************************************')
- if luatypo.pagelist == "" then
+ if luatypo.pagelist == " " then
texio.write_nl('*** lua-typo: No Typo Flaws found.')
else
texio.write_nl('*** lua-typo: WARNING *************')
- texio.write_nl('The following pages need attention: ')
+ texio.write_nl('The following pages need attention:')
texio.write(luatypo.pagelist)
end
texio.write_nl('***********************************')
@@ -965,8 +989,8 @@ luatypo = { }
local s = string.char(c)
luatypo.single[langno] = luatypo.single[langno] .. s
end
-%<dbg> texio.write_nl("SINGLE=" .. luatypo.single[langno])
-%<dbg> texio.write_nl(' ')
+%<dbg> texio.write_nl("SINGLE=" .. luatypo.single[langno])
+%<dbg> texio.write_nl(' ')
}%
\else
\PackageWarning{luatypo}{Unknown language "\luatypo@LANG",
@@ -984,8 +1008,8 @@ luatypo = { }
local s = string.char(c)
luatypo.double[langno] = luatypo.double[langno] .. s
end
-%<dbg> texio.write_nl("DOUBLE=" .. luatypo.double[langno])
-%<dbg> texio.write_nl(' ')
+%<dbg> texio.write_nl("DOUBLE=" .. luatypo.double[langno])
+%<dbg> texio.write_nl(' ')
}%
\else
\PackageWarning{luatypo}{Unknown language "\luatypo@LANG",
@@ -1020,7 +1044,7 @@ luatypo = { }
luatypo.single = { }
luatypo.double = { }
luatypo.colortbl = { }
-luatypo.pagelist = ""
+luatypo.pagelist = " "
luatypo.buffer = "List of typographic flaws found for "
.. tex.jobname .. ".tex:\string\n\string\n"
@@ -1112,7 +1136,7 @@ local color_node = function (node, color)
local repl = node.replace
if pre then
set_attribute(pre,attr,color)
-%<dbg> texio.write_nl('PRE=' .. tostring(pre.char))
+%<dbg> texio.write_nl('PRE=' .. tostring(pre.char))
end
if post then
set_attribute(post,attr,color)
@@ -1193,7 +1217,7 @@ end
%
% This function appends a line to a buffer which will be written
% to file `\cs{jobname.typo}’; it takes four arguments:
-% a string, two numbers (which can be \texttt{nil}) and a flag.
+% a string, two numbers (which can be \node{nil}) and a flag.
%
% \changes{v0.50}{2021/05/13}{Summary of flaws written to file
% `\cs{jobname.typo}’.}
@@ -1374,8 +1398,8 @@ local check_last_word = function (old, node, line, flag)
until not n or n.id == GLUE
end
new = string.reverse(new)
-%<dbg> texio.write_nl('EOLsigold=' .. old)
-%<dbg> texio.write(' EOLsig=' .. new)
+%<dbg> texio.write_nl('EOLsigold=' .. old)
+%<dbg> texio.write(' EOLsig=' .. new)
local MinFull = luatypo.MinFull
local MinPart = luatypo.MinPart
MinFull = math.min(MinPart,MinFull)
@@ -1390,10 +1414,10 @@ local check_last_word = function (old, node, line, flag)
local newsub = string.sub(new,-k)
local l = string.len(new)
if oldsub == newsub and l >= k then
-%<dbg> texio.write_nl('EOLnewsub=' .. newsub)
+%<dbg> texio.write_nl('EOLnewsub=' .. newsub)
match = true
elseif oldlast == newlast and string.len(newlast) >= MinFull then
-%<dbg> texio.write_nl('EOLnewlast=' .. newlast)
+%<dbg> texio.write_nl('EOLnewlast=' .. newlast)
match = true
oldsub = oldlast
newsub = newlast
@@ -1415,7 +1439,7 @@ local check_last_word = function (old, node, line, flag)
end
pageflag = true
newsub = string.gsub(newsub, '^_', '')
-%<dbg> texio.write_nl('EOLfullmatch=' .. newsub)
+%<dbg> texio.write_nl('EOLfullmatch=' .. newsub)
local msg = "E.O.L. MATCH=" .. newsub
log_flaw(msg, line, colno, footnote)
% \end{macrocode}
@@ -1512,10 +1536,10 @@ local check_first_word = function (old, node, line, flag)
local newsub = string.sub(new,1,k)
local l = string.len(newsub)
if oldsub == newsub and l >= k then
-%<dbg> texio.write_nl('BOLnewsub=' .. newsub)
+%<dbg> texio.write_nl('BOLnewsub=' .. newsub)
match = true
elseif oldfirst == newfirst and string.len(newfirst) >= MinFull then
-%<dbg> texio.write_nl('BOLnewfirst=' .. newfirst)
+%<dbg> texio.write_nl('BOLnewfirst=' .. newfirst)
match = true
oldsub = oldfirst
newsub = newfirst
@@ -1537,7 +1561,7 @@ local check_first_word = function (old, node, line, flag)
end
pageflag = true
newsub = string.gsub(newsub, '_$', '') --$
-%<dbg> texio.write_nl('BOLfullmatch=' .. newsub)
+%<dbg> texio.write_nl('BOLfullmatch=' .. newsub)
local msg = "B.O.L. MATCH=" .. newsub
log_flaw(msg, line, colno, footnote)
% \end{macrocode}
@@ -1569,7 +1593,7 @@ end
% This auxillary function looks for a short word (one or two chars)
% at end of lines, compares it to a given list and colours it if
% matches. The first argument must be a node of type |GLYPH|,
-% usually the last line’s node, the second one is the line number.\\
+% usually the last line’s node, the second one is the line number.\par
% TODO: where does ``out of range’’ starts? U+0100? U+0180?
%
% \begin{macrocode}
@@ -1646,7 +1670,7 @@ end
%
% This auxillary function prints the first part of an hyphenated word
% up to the discretionary, with a supplied colour.
-% It requires two arguments: a |DISC| node and a (named) colour.
+% It requires two arguments: a \node{disc} node and a (named) colour.
%
% \begin{macrocode}
local show_pre_disc = function (disc, color)
@@ -1659,7 +1683,58 @@ local show_pre_disc = function (disc, color)
end
% \end{macrocode}
%
-% This auxillary function scans the `vlists’ in search of the page body.
+% \begin{macro}{footnoterule-ahead}
+% This auxillary function scans the current \node{vlist} in search
+% of a |\footnoterule|; it returns |true| if found, false otherwise.
+% The \node{rule} node above footnotes is normaly surrounded by
+% two (vertical) \node{kern} nodes, the total height is either
+% 0 (standard and koma classes) or equals the rule’s height
+% (memoir class).
+%
+% \changes{v0.50}{2021/05/02}{New function `footnoterule\_ahead’.}
+%
+% \begin{macrocode}
+local footnoterule_ahead = function (head)
+ local n = head
+ local flag = false
+ local totalht, ruleht, ht1, ht2, ht3
+ if n and n.id == KERN and n.subtype == 1 then
+ totalht = n.kern
+ n = n.next
+%<dbg> ht1 = string.format("%.2fpt", totalht/65536)
+% \end{macrocode}
+% \changes{v0.51}{2023/01/17}{In some cases glue nodes might preceed
+% the footnote rule; next line added}
+% \begin{macrocode}
+ while n and n.id == GLUE do n = n.next end
+ if n and n.id == RULE and n.subtype == 0 then
+ ruleht = n.height
+%<dbg> ht2 = string.format("%.2fpt", ruleht/65536)
+ totalht = totalht + ruleht
+ n = n.next
+ if n and n.id == KERN and n.subtype == 1 then
+%<dbg> ht3 = string.format("%.2fpt", n.kern/65536)
+ totalht = totalht + n.kern
+ if totalht == 0 or totalht == ruleht then
+ flag = true
+ else
+%<dbg> texio.write_nl(' ')
+%<dbg> texio.write_nl('Not a footnoterule:')
+%<dbg> texio.write(' KERN height=' .. ht1)
+%<dbg> texio.write(' RULE height=' .. ht2)
+%<dbg> texio.write(' KERN height=' .. ht3)
+ end
+ end
+ end
+ end
+ return flag
+end
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{get-pagebody}
+% This auxillary function scans the \node{vlist}s on the current
+% page in search of the page body.
% It returns the corresponding node or nil in case of failure.
%
% \changes{v0.50}{2021/05/02}{New function `get\_pagebody’ required for
@@ -1673,21 +1748,29 @@ local get_pagebody = function (head)
repeat
fn = fn.next
until fn.id == VLIST and fn.height > 0
-%<dbg> texio.write_nl(' ht=' .. fn.height/65536 .. 'pt')
-%<dbg> texio.write(' dp=' .. fn.depth/65536 .. 'pt')
+%<dbg> texio.write_nl(' ')
+%<dbg> local ht = string.format("%.1fpt", fn.height/65536)
+%<dbg> local dp = string.format("%.1fpt", fn.depth/65536)
+%<dbg> texio.write_nl('get_pagebody: TOP VLIST')
+%<dbg> texio.write(' ht=' .. ht .. ' dp=' .. dp)
first = fn.list
for n in traverse_id(VLIST,first) do
if n.subtype == 0 and n.height == textht then
-%<dbg> texio.write_nl(' BODY: ' .. n.height/65536 .. 'pt')
+%<dbg> local ht = string.format("%.1fpt", n.height/65536)
+%<dbg> texio.write_nl('BODY found: ht=' .. ht)
+%<dbg> texio.write_nl(' ')
body = n
break
else
-%<dbg> texio.write_nl(' ht=' .. n.height/65536 .. 'pt')
-%<dbg> texio.write_nl(' dp=' .. n.depth/65536 .. 'pt')
+%<dbg> texio.write_nl('Skip short VLIST:')
+%<dbg> local ht = string.format("%.1fpt", n.height/65536)
+%<dbg> local dp = string.format("%.1fpt", n.depth/65536)
+%<dbg> texio.write(' ht=' .. ht .. ' dp=' .. dp)
first = n.list
for n in traverse_id(VLIST,first) do
if n.subtype == 0 and n.height == textht then
-%<dbg> texio.write_nl(' BODY: ' .. n.height/65536 .. 'pt')
+%<dbg> local ht = string.format("%.1fpt", n.height/65536)
+%<dbg> texio.write_nl(' BODY: ht=' .. ht)
body = n
break
end
@@ -1700,61 +1783,26 @@ local get_pagebody = function (head)
return body
end
% \end{macrocode}
+% \end{macro}
%
-% This auxillary function scans the current `vlist’ in search
-% of a |\footnoterule| (kern, rule, kern, totalheight=0).
-% It returns |true| if found, false othewise.
+% \begin{macro}{check-vtop}
+% This function is called repeatedly by |check_page| (see below);
+% it scans the boxes found in the page body (f.i. columns)
+% in search of typographical flaws and logs them if it finds any.
%
-% \changes{v0.50}{2021/05/02}{New function `footnoterule\_ahead’.}
+% \changes{v0.40}{2021/04/18}{Title pages, pages with figures and/or
+% tables may not be empty pages: check `vpos’ last line’s position.}
%
-% \begin{macrocode}
-local footnoterule_ahead = function (head, debug)
- local n = head
- local flag = false
- if n and n.id == KERN and n.subtype == 1 then
- local htr = n.kern
- local ht1, ht2, ht3
-%<dbg> if debug then
-%<dbg> ht1 = string.format("%.2fpt", n.kern/65536)
-%<dbg> end
- n = n.next
- if n and n.id == RULE and n.subtype == 0 then
- htr = htr + n.height
-%<dbg> if debug then
-%<dbg> ht2 = string.format("%.2fpt", n.height/65536)
-%<dbg> end
- n = n.next
- if n and n.id == KERN and n.subtype == 1 then
- htr = htr + n.kern
-%<dbg> if debug then
-%<dbg> ht3 = string.format("%.2fpt", n.kern/65536)
-%<dbg> texio.write_nl(' ')
-%<dbg> texio.write_nl('KERN height: ' .. ht1)
-%<dbg> texio.write(' RULE height: ' .. ht2)
-%<dbg> texio.write(' KERN height: ' .. ht3)
-%<dbg> texio.write_nl('TOTAL height: ' .. htr .. 'sp')
-%<dbg> end
- if htr == 0 then
- flag = true
-%<dbg> if debug then
-%<dbg> texio.write(' => footnoterule found!')
-%<dbg> end
- end
- end
- end
- end
- return flag
-end
-% \end{macrocode}
+% \changes{v0.60}{2023/01/28}{Loop redesigned.}
%
-% This function scans the page body (or each column) in search of
-% typographical flaws.
+% \changes{v0.60}{2023/01/29}{Typographical flaws are recorded here
+% (formerly in check\_page).}
%
-% \changes{v0.40}{2021/04/18}{Title pages, pages with figures and/or
-% tables may not be empty pages: check `vpos’ last line’s position.}
+% \changes{v0.60}{2023/01/29}{Break `check\_vtop’ loop
+% if a two columns box starts.}
%
% \begin{macrocode}
-check_vtop = function (head, colno)
+check_vtop = function (head, colno, vpos)
local PAGEmin = luatypo.PAGEmin
local HYPHmax = luatypo.HYPHmax
local LLminWD = luatypo.LLminWD
@@ -1776,13 +1824,9 @@ check_vtop = function (head, colno)
local FootnoteSplit = luatypo.FootnoteSplit
local Stretch = math.max(luatypo.Stretch/100,1)
local blskip = tex.getglue("baselineskip")
- local pageno = tex.getcount("c@page")
local vpos_min = PAGEmin * blskip
vpos_min = vpos_min * 1.5
- local vpos = 0
- local pageflag = false
- local body_bottom = false
- local page_bottom = false
+ local linewd = tex.getdimen("textwidth")
local first_bot = true
local footnote = false
local ftnsplit = false
@@ -1796,37 +1840,31 @@ check_vtop = function (head, colno)
local pageline = 0
local ftnline = 0
local line = 0
+ local body_bottom = false
+ local page_bottom = false
+ local pageflag = false
+ local plist = luatypo.pagelist
+ local lastp = tonumber(string.match(plist, "%s(%d+),%s$"))
+ local pageno = tex.getcount("c@page")
% \end{macrocode}
% The main loop scans the content of the |\vtop| holding the page
% (or column) body, footnotes included.
-% The vertical position of the current node is stored in the |vpos|
-% dimension (integer in `sp’ units).
% \begin{macrocode}
while head do
local nextnode = head.next
% \end{macrocode}
-% If a |\footnoterule| is found, set the |footnote| flag and reset
-% some counters and flags for the coming footnotes.
+% Let's scan the top nodes of this vbox: expected are \node{hlist}
+% (text lines or vboxes), \node{rule}, \node{kern}, \node{glue}…
% \begin{macrocode}
- if not footnote and head.id == KERN and head.subtype == 1 then
- if footnoterule_ahead(head, true) then
- footnote = true
- ftnline = 0
- body_bottom = false
- orphanflag = false
- lwhyphflag = false
- hyphcount = 0
- firstwd = ""
- lastwd = ""
- else
- vpos = vpos + head.kern
- end
- elseif head.id == HLIST and head.subtype == LINE and
+ if head.id == HLIST and head.subtype == LINE and
(head.height > 0 or head.depth > 0) then
% \end{macrocode}
-% This is a text line, increment counters |pageline| or
-% |ftnline| and |line| (for |log_flaw|).
+% This is a text line, store the line width, increment counters
+% |pageline| or |ftnline| and |line| (for |log_flaw|).
+% Let’s update |vpos| (vertical position in `sp' units) too.
% \begin{macrocode}
+ vpos = vpos + head.height + head.depth
+ linewd = head.width
if footnote then
ftnline = ftnline + 1
line = ftnline
@@ -1835,12 +1873,30 @@ check_vtop = function (head, colno)
line = pageline
end
% \end{macrocode}
-% Is it overfull or underfull?
+% Is this line the last one on the page or before footnotes?\par
+% This has to be known early (orphanflag, lwhyphflag, ftnsplit).
+% \begin{macrocode}
+ local n = nextnode
+ while n and (n.id == GLUE or n.id == PENALTY or
+ n.id == WHATSIT ) do
+ n = n.next
+ end
+ if not n then
+ page_bottom = true
+ body_bottom = true
+ elseif footnoterule_ahead(n) then
+ body_bottom = true
+%<dbg> texio.write_nl('=> FOOTNOTE RULE ahead')
+%<dbg> texio.write_nl('check_vtop: last line before footnotes')
+%<dbg> texio.write_nl(' ')
+ end
+% \end{macrocode}
+% Is the current line overfull or underfull?
% \changes{v0.50}{2021/05/13}{Detection of overfull boxes fixed: the
% former code didn’t work for typewriter fonts.}
% \begin{macrocode}
local first = head.head
- local hmax = head.width + tex.hfuzz
+ local hmax = linewd + tex.hfuzz
local w,h,d = dimensions(1,2,0, first)
if w > hmax and OverfullLines then
pageflag = true
@@ -1859,34 +1915,6 @@ check_vtop = function (head, colno)
color_line (head, COLOR)
end
% \end{macrocode}
-% Let’s update |vpos| and check if the current line is the last one
-% of the page body; this requires to look ahead \emph{now} for the
-% next nodes in the `vlist’ as this information is needed to decide
-% about orphans, last page’s word hyphenated, etc.
-% \begin{macrocode}
- vpos = vpos + head.height + head.depth
- local n = head.next
- while n and
- (n.id == GLUE or n.id == PENALTY or n.id == WHATSIT) do
- n = n.next
- end
-% \end{macrocode}
-% Is this line the last one on the current page? …
-% \begin{macrocode}
- if not n then
- if footnote then
- page_bottom = true
- else
- page_bottom = true
- body_bottom = true
- end
-% \end{macrocode}
-% or the last one before |\footnoterule|?
-% \begin{macrocode}
- elseif footnoterule_ahead(n, false) then
- body_bottom = true
- end
-% \end{macrocode}
% Set flag |ftnsplit| to |true| on every page’s last line.
% This flag will be reset to false if the current line ends a
% paragraph.
@@ -1922,14 +1950,14 @@ check_vtop = function (head, colno)
hyphcount = 0
if not footnote then
parline = 1
- end
- if body_bottom then
+ if body_bottom then
% \end{macrocode}
% We are at the page bottom (footnotes excluded), this ligne is
% an orphan (unless it is the unique line of the paragraph, this
% will be checked later when scanning the end of line).
% \begin{macrocode}
- orphanflag = true
+ orphanflag = true
+ end
end
% \end{macrocode}
% List items begin with |LPAR| followed by an hbox.
@@ -1964,7 +1992,7 @@ check_vtop = function (head, colno)
orphanflag = false
% \end{macrocode}
% but it is a widow if it is the page’s first line and it does’nt
-% start a new paragraph.\\ Orphans and widows will be colored later.
+% start a new paragraph.\par Orphans and widows will be colored later.
% \begin{macrocode}
if pageline == 1 and parline > 1 then
widowflag = true
@@ -1974,11 +2002,11 @@ check_vtop = function (head, colno)
% \begin{macrocode}
local PFskip = effective_glue(pn,head)
if ShortLines then
- local llwd = tex.hsize - PFskip
-%<dbg> local PFskip_pt = string.format("%.1fpt", PFskip/65536)
-%<dbg> local llwd_pt = string.format("%.1fpt", llwd/65536)
-%<dbg> texio.write_nl('PFskip= ' .. PFskip_pt)
-%<dbg> texio.write(' llwd= ' .. llwd_pt)
+ local llwd = linewd - PFskip
+%<dbg> local PFskip_pt = string.format("%.1fpt", PFskip/65536)
+%<dbg> local llwd_pt = string.format("%.1fpt", llwd/65536)
+%<dbg> texio.write_nl('PFskip= ' .. PFskip_pt)
+%<dbg> texio.write(' llwd= ' .. llwd_pt)
% \end{macrocode}
% |llwd| is the line’s length. Is it too short?
% \begin{macrocode}
@@ -2042,7 +2070,8 @@ check_vtop = function (head, colno)
% \end{macrocode}
% Does the next line end the current paragraph? If so, |nextnode| is
% a `linebreak penalty’, the next one is a `baseline skip’ and the
-% node after a `hlist of subtype line’ with |glue_order=2|.
+% node after a \node{hlist} of subtype \node{line} with
+% |glue_order=2|.
% \begin{macrocode}
local nn = nextnode.next
local nnn = nil
@@ -2059,9 +2088,9 @@ check_vtop = function (head, colno)
end
end
% \end{macrocode}
-% CASE 3: the current line ends with anything else (|MKERN|,
-% |GLYPH|, |HLIST|, etc.), reset |hyphcount|, perform checks
-% for `LastWordMatch’ and for `EOLShortWords’.
+% CASE 3: the current line ends with anything else (\node{mkern},
+% \node{glyph}, \node{hlist}, etc.), reset |hyphcount|, perform
+% checks for `LastWordMatch’ and for `EOLShortWords’.
% \begin{macrocode}
else
hyphcount = 0
@@ -2089,7 +2118,7 @@ check_vtop = function (head, colno)
color_line (head, COLOR)
end
% \end{macrocode}
-% Colour the whole line if is is a orphan or footenote continuing
+% Colour the whole line if is is a orphan or footnote continuing
% on the next page.
% \begin{macrocode}
if orphanflag and Orphans then
@@ -2116,16 +2145,19 @@ check_vtop = function (head, colno)
local COLOR = luatypo.colortbl[1]
local pg = show_pre_disc (pn,COLOR)
end
+% \end{macrocode}
+% End of scanning for the main type of node (text lines).
+% \begin{macrocode}
elseif head.id == HLIST and
(head.subtype == EQN or head.subtype == ALIGN) and
(head.height > 0 or head.depth > 0) then
% \end{macrocode}
+% This line is a displayed or aligned equation.
+% Let’s update |vpos| and the line number.
%
% \changes{v0.50}{2021/05/05}{Consider displayed and aligned equations
% too for overfull boxes.}
%
-% This line is a displayed or aligned equation.
-% Let’s update |vpos| and the line number.
% \begin{macrocode}
vpos = vpos + head.height + head.depth
if footnote then
@@ -2139,7 +2171,8 @@ check_vtop = function (head, colno)
% Let’s check for an ``Overfull box''. For a displayed equation
% it is straightforward. A set of aligned equations all have the
% same (maximal) width; in order to avoid highlighting the whole
-% set, we have to look for glues at the end of embedded `hlists’.
+% set, we have to look for glues at the end of embedded
+% \node{hlist}s.
% \begin{macrocode}
local fl = true
local wd = 0
@@ -2173,49 +2206,53 @@ check_vtop = function (head, colno)
color_line (head, COLOR)
end
end
+ elseif head and head.id == RULE and head.subtype == 0 then
% \end{macrocode}
-% We also need to set flag |body_bottom| and to increment the
-% |pageline| counter to track empty pages.
+% This is a \node{rule}, possibly a footnote rule.
% \begin{macrocode}
- local n = head.next
- while n and (n.id == GLUE or n.id == PENALTY or
- n.id == WHATSIT or n.id == VLIST) do
- n = n.next
- end
- if not n then
- page_bottom = true
- body_bottom = true
- elseif footnoterule_ahead(n, false) then
- body_bottom = true
- end
+ vpos = vpos + head.height + head.depth
+ if body_bottom then
% \end{macrocode}
-% This is a |\vbox|, let’s update |vpos|.
+% If a |\footnoterule| has been detected on the previous run,
+% set the |footnote| flag and reset some counters and flags
+% for the coming footnote lines.
% \begin{macrocode}
- elseif head.id == VLIST then
- vpos = vpos + head.height + head.depth
+%<dbg> texio.write_nl('check_vtop: footnotes start')
+%<dbg> texio.write_nl(' ')
+ footnote = true
+ ftnline = 0
+ body_bottom = false
+ ftnrule_ahead = false
+ orphanflag = false
+ lwhyphflag = false
+ hyphcount = 0
+ firstwd = ""
+ lastwd = ""
+ end
% \end{macrocode}
-% Track empty pages: check the number of lines at end of page,
+% Track short pages: check the number of lines at end of page,
% in case this number is low, \emph{and} |vpos| is less than
-% |vpos_min|, fetch the last line and colour it.\\
+% |vpos_min|, fetch the last line and colour it.\par
% NOTE1: |effective_glue| requires a `parent’ node, as pointed out by
% Marcel Krüger on S.E., this implies using |pre_shipout_filter|
-% instead of |pre_output_filter|.\\
+% instead of |pre_output_filter|.\par
% NOTE2: Widows are already detected, skip them here; there are
-% usually two consecutive nodes of type 12-0 at end of pages…
+% usually two consecutive nodes of type \node{glue}-0 at end of
+% pages…
% \begin{macrocode}
elseif body_bottom and head.id == GLUE and head.subtype == 0 then
if first_bot then
-%<dbg> local vpos_pt = string.format("%.1fpt", vpos/65536)
-%<dbg> local vmin_pt = string.format("%.1fpt", vpos_min/65536)
-%<dbg> texio.write_nl('pageline=' .. pageline)
-%<dbg> texio.write_nl('vpos=' .. vpos_pt)
-%<dbg> texio.write(' vpos_min=' .. vmin_pt)
-%<dbg> if page_bottom then
-%<dbg> local tht = tex.getdimen("textheight")
-%<dbg> local tht_pt = string.format("%.1fpt", tht/65536)
-%<dbg> texio.write(' textheight=' .. tht_pt)
-%<dbg> end
-%<dbg> texio.write_nl(' ')
+%<dbg> local vpos_pt = string.format("%.1fpt", vpos/65536)
+%<dbg> local vmin_pt = string.format("%.1fpt", vpos_min/65536)
+%<dbg> texio.write_nl('pageline=' .. pageline)
+%<dbg> texio.write_nl('vpos=' .. vpos_pt)
+%<dbg> texio.write(' vpos_min=' .. vmin_pt)
+%<dbg> if page_bottom then
+%<dbg> local tht = tex.getdimen("textheight")
+%<dbg> local tht_pt = string.format("%.1fpt", tht/65536)
+%<dbg> texio.write(' textheight=' .. tht_pt)
+%<dbg> end
+%<dbg> texio.write_nl(' ')
if pageline > 1 and pageline < PAGEmin and ShortPages then
pageshort = true
end
@@ -2232,85 +2269,176 @@ check_vtop = function (head, colno)
end
first_bot = false
end
+ elseif head.id == GLUE then
% \end{macrocode}
% Increment |vpos| on other vertical glues.
% \begin{macrocode}
- elseif head.id == GLUE then
vpos = vpos + effective_glue(head,body)
+ elseif head.id == KERN and head.subtype == 1 then
+% \end{macrocode}
+% This is a vertical kern, let’s update |vpos|.
+% \begin{macrocode}
+ vpos = vpos + head.kern
+ elseif head.id == VLIST then
+% \end{macrocode}
+% This is a vertical a |\vbox|, let’s update |vpos|.
+% \begin{macrocode}
+ vpos = vpos + head.height + head.depth
+% \end{macrocode}
+% Leave |check_vtop| if a two columns box starts.
+% \begin{macrocode}
+ elseif head.id == HLIST and head.subtype == BOX then
+ local hf = head.list
+ if hf and hf.id == VLIST and hf.subtype == 0 then
+%<dbg> texio.write_nl('check_vtop: BREAK => multicol')
+%<dbg> texio.write_nl(' ')
+ break
+ end
end
head = nextnode
end
- return pageflag
+%<dbg> if nextnode then
+%<dbg> texio.write('Exit check_vtop, next=')
+%<dbg> texio.write(tostring(node.type(nextnode.id)))
+%<dbg> texio.write('-'.. nextnode.subtype)
+%<dbg> else
+%<dbg> texio.write_nl('Exit check_vtop, next=nil')
+%<dbg> end
+%<dbg> texio.write_nl('')
+% \end{macrocode}
+% Record flaws:
+% \begin{macrocode}
+ if pageflag then
+ if not lastp or pageno > lastp then
+ luatypo.pagelist = luatypo.pagelist .. tostring(pageno) .. ", "
+ end
+ end
+ return head
+% \end{macrocode}
+% head is nil unless |check_vtop| exited on a two column start.
+% \begin{macrocode}
end
% \end{macrocode}
+% \end{macro}
%
+% \begin{macro}{check-page}
% This is the main function which will be added to the
% |pre_shipout_filter| callback unless option |None| is selected.
-% It executes |get_pagebody|, then scans the page body for possible
-% columns (multi column page).
+% It executes |get_pagebody| which returns a node of type
+% \node{vlist}-0, then scans this \node{vlist}: expected are
+% \node{vlist}-0 (full width block) or \node{hlist}-2 (multi
+% column block).
+% The vertical position of the current node is stored in the |vpos|
+% dimension (integer in `sp’ units, 1\,pt~=~65536\,sp). It is used to
+% detect short pages.
+%
+% \changes{v0.60}{2023/01/29}{Loop redesigned to properly handle
+% two colums.}
%
% \begin{macrocode}
luatypo.check_page = function (head)
- local pageno = tex.getcount("c@page")
- local pageflag = false
+ local textwd = tex.getdimen("textwidth")
+ local vpos = 0
local n2, n3, col, colno
local body = get_pagebody(head)
+ local footnote = false
+ local top = body
local first = body.list
-%<dbg> texio.write_nl('body.id=' .. tostring(node.type(body.id)))
-%<dbg> texio.write('-' .. body.subtype)
-%<dbg> texio.write_nl(' ')
-%<dbg> texio.write_nl('first.id=' .. tostring(node.type(first.id)))
-%<dbg> texio.write('-' .. first.subtype)
-%<dbg> texio.write_nl(' ')
- if first.id == HLIST and first.subtype == 2 then
+ if (first and first.id == HLIST and first.subtype == BOX) or
+ (first and first.id == VLIST and first.subtype == 0) then
% \end{macrocode}
-% Two or more columns, each one is boxed in an hlist.
-% Run |check_vtop| on every column.
+% Some classes (\cls{memoir}, \cls{tugboat} …) use one more level
+% of bowing, let’s step down one level.
% \begin{macrocode}
- n2 = first.list
- colno = 0
- for n in traverse_id(HLIST, n2) do
-%<dbg> texio.write_nl('n.id=' .. tostring(node.type(n.id)))
-%<dbg> texio.write('-' .. n.subtype)
-%<dbg> texio.write(' ht=' .. n.height)
-%<dbg> texio.write_nl(' ')
- if n.id == HLIST and n.subtype == 2 then
- n3 = n.list
-%<dbg> texio.write_nl('n3.id=' .. tostring(node.type(n3.id)))
-%<dbg> texio.write('-' .. n3.subtype)
-%<dbg> texio.write(' ht=' .. n3.height)
-%<dbg> texio.write_nl(' ')
- col = n3.list
- colno = colno + 1
- pageflag = check_vtop(col,colno)
- end
- end
- elseif body.id == VLIST and body.subtype == 0 then
+%<dbg> local boxwd = string.format("%.1fpt", first.width/65536)
+%<dbg> texio.write_nl('One step down: boxwd=' .. boxwd)
+%<dbg> texio.write_nl(' ')
+ top = body.list
+ first = top.list
+ end
+ while top do
+ first = top.list
+%<dbg> texio.write_nl('Page loop: top=' .. tostring(node.type(top.id)))
+%<dbg> texio.write('-' .. top.subtype)
+%<dbg> texio.write_nl(' ')
+ if top and top.id == VLIST and top.subtype == 0 and
+ top.width > textwd/2 then
% \end{macrocode}
% Single column, run |check_vtop| on the top vlist.
% \begin{macrocode}
- col = body.list
- pageflag = check_vtop(col,colno)
- end
+%<dbg> local boxht = string.format("%.1fpt", top.height/65536)
+%<dbg> local boxwd = string.format("%.1fpt", top.width/65536)
+%<dbg> texio.write_nl('**VLIST: ')
+%<dbg> texio.write(tostring(node.type(top.id)))
+%<dbg> texio.write('-' .. top.subtype)
+%<dbg> texio.write(' wd=' .. boxwd .. ' ht=' .. boxht)
+%<dbg> texio.write_nl(' ')
+ local next = check_vtop(first,colno,vpos)
+ if next then
+ top = next
+ elseif top then
+ top = top.next
+ end
+ elseif (top and top.id == HLIST and top.subtype == BOX) and
+ (first and first.id == VLIST and first.subtype == 0) and
+ (first.height > 0 and first.width > 0) then
% \end{macrocode}
-% Add this page number to the summary if any flaw has been found on it.
-% Skip duplicates.
-%
-% \changes{v0.32}{2021/03/14}{Remove duplicates in the summary of pages.}
-%
+% Two or more columns, each one is boxed in a vlist.\par
+% Run |check_vtop| on every column.
% \begin{macrocode}
- if pageflag then
- local pl = luatypo.pagelist
- local p = tonumber(string.match(pl, "%s(%d+),%s$"))
- if not p or pageno > p then
- luatypo.pagelist = luatypo.pagelist .. tostring(pageno) .. ", "
- end
+%<dbg> texio.write_nl('**MULTICOL type1:')
+%<dbg> texio.write_nl(' ')
+ colno = 0
+ for n in traverse_id(VLIST, first) do
+ colno = colno + 1
+ col = n.list
+%<dbg> texio.write_nl('Start of col.' .. colno)
+%<dbg> texio.write_nl(' ')
+ check_vtop(col,colno,vpos)
+%<dbg> texio.write_nl('End of col.' .. colno)
+%<dbg> texio.write_nl(' ')
+ end
+ colno = nil
+ top = top.next
+%<dbg> texio.write_nl('MULTICOL type1 END: next=')
+%<dbg> texio.write(tostring(node.type(top.id)))
+%<dbg> texio.write('-' .. top.subtype)
+%<dbg> texio.write_nl(' ')
+ elseif (top and top.id == HLIST and top.subtype == BOX) and
+ (first and first.id == HLIST and first.subtype == BOX) and
+ (first.height > 0 and first.width > 0) then
+% \end{macrocode}
+% Two or more columns, each one is boxed in an hlist which
+% holds a vlist.\par
+% Run |check_vtop| on every column.
+% \begin{macrocode}
+%<dbg> texio.write_nl('**MULTICOL type2:')
+%<dbg> texio.write_nl(' ')
+ colno = 0
+ for n in traverse_id(HLIST, first) do
+ colno = colno + 1
+ local nn = n.list
+ if nn and nn.list then
+ col = nn.list
+%<dbg> texio.write_nl('Start of col.' .. colno)
+%<dbg> texio.write_nl(' ')
+ check_vtop(col,colno,vpos)
+%<dbg> texio.write_nl('End of col.' .. colno)
+%<dbg> texio.write_nl(' ')
+ end
+ end
+ colno = nil
+ top = top.next
+ else
+ top = top.next
+ end
end
return true
end
return luatypo.check_page
\end{luacode}
% \end{macrocode}
+% \end{macro}
%
% Add the |luatypo.check_page| function to the |pre_shipout_filter|
% callback (with priority 1 for color attributes to be effective),
@@ -2318,7 +2446,7 @@ return luatypo.check_page
% boolean’s value is forwarded to Lua `AtEndOfPackage’…
%
% \changes{v0.50}{2021/05/02}{Callback `pre\_output\_filter’ replaced
-% by `pre\_shipout\_filter’, in the later the material is not boxed
+% by `pre\_shipout\_filter’, in the former the material is not boxed
% yet and footnotes are not visible.}
%
% \begin{macrocode}
@@ -2328,11 +2456,11 @@ return luatypo.check_page
luatexbase.add_to_callback
("pre_shipout_filter",luatypo.check_page,"check_page",1)
end
- }
+ }%
}
% \end{macrocode}
%
-% Load a local config file if present in LaTeX’s search path.\\
+% Load a local config file if present in LaTeX’s search path.\par
% Otherwise, set reasonnable defaults.
% \enlargethispage*{\baselineskip}
% \begin{macrocode}
@@ -2429,32 +2557,290 @@ return luatypo.check_page
%%\luatypoTwoChars{french}{'Je Tu Il On'}
% \end{macrocode}
%
-%\iffalse
+% \iffalse
%</cfg>
% \fi
%
+% \changes{v0.60}{2023/02/02}{Debugging stuff added.}
+%
+% \section{Debugging lua-typo}
+%
+% Personal stuff useful \emph{only} for maintaining the
+% \pkg{lua-typo} package has been added at the end of
+% \file{lua-typo.dtx} in version~0.60.
+% It is not extracted unless a) both `|\iffalse|’ and `|\fi|’ on
+% lines 41 and 46 at the beginning of \file{lua-typo.dtx} are
+% commented out and b) all files are generated again by a
+% |luatex lua-typo.dtx| command; then a (very) verbose version of
+% \file{lua-typo.sty} is generated together with
+% a \file{scan-page.sty} file which can be used instead of
+% \file{lua-typo.sty} to show the structured list of nodes
+% found in a document.
+%
% \iffalse
-%<*dtx>
+%<*scan>
% \fi
-%%
-%% \CharacterTable
-%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
-%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
-%% Digits \0\1\2\3\4\5\6\7\8\9
-%% Exclamation \! Double quote \" Hash (number) \#
-%% Dollar \$ Percent \% Ampersand \&
-%% Acute accent \' Left paren \( Right paren \)
-%% Asterisk \* Plus \+ Comma \,
-%% Minus \- Point \. Solidus \/
-%% Colon \: Semicolon \; Less than \<
-%% Equals \= Greater than \> Question mark \?
-%% Commercial at \@ Left bracket \[ Backslash \\
-%% Right bracket \] Circumflex \^ Underscore \_
-%% Grave accent \` Left brace \{ Vertical bar \|
-%% Right brace \} Tilde \~}
-%%
+%
+% \begin{Debugging}
+% \begin{macrocode}
+\ifdefined\directlua
+ \RequirePackage{luatexbase,luacode,luacolor}
+ \RequirePackage{kvoptions,atveryend}
+\else
+ \PackageError{This package is meant for LuaTeX only! Aborting}
+ {No more information available, sorry!}
+\fi
+
+\newdimen\luatypoLLminWD
+\newdimen\luatypoBackPI
+\newdimen\luatypoBackFuzz
+\newcount\luatypoStretchMax
+\newcount\luatypoHyphMax
+\newcount\luatypoPageMin
+\newcount\luatypoMinFull
+\newcount\luatypoMinPart
+\newcount\luatypo@LANGno
+\newcount\luatypo@options
+\newtoks\luatypo@single
+\newtoks\luatypo@double
+
+\AtBeginDocument{%
+ \directlua{
+ luatypo.HYPHmax = tex.count.luatypoHyphMax
+ luatypo.PAGEmin = tex.count.luatypoPageMin
+ luatypo.Stretch = tex.count.luatypoStretchMax
+ luatypo.MinFull = tex.count.luatypoMinFull
+ luatypo.MinPart = tex.count.luatypoMinPart
+ luatypo.LLminWD = tex.dimen.luatypoLLminWD
+ luatypo.BackPI = tex.dimen.luatypoBackPI
+ luatypo.BackFuzz = tex.dimen.luatypoBackFuzz
+ }%
+}
+
+\AtVeryEndDocument{%
+ \directlua{
+ texio.write_nl(' ')
+ texio.write_nl('***************************')
+ texio.write_nl('*** PAGE SCANNING ONLY: ***')
+ texio.write_nl('*** NO CHECK PERFORMED! ***')
+ texio.write_nl('***************************')
+ texio.write_nl(' ')
+ }%
+}
+
+\newcommand*{\luatypoOneChar}[2]{}
+\newcommand*{\luatypoTwoChars}[2]{}
+\newcommand*{\luatypoSetColor}[2]{}
+
+\begin{luacode}
+luatypo = { }
+luatypo.single = { }
+luatypo.double = { }
+luatypo.colortbl = { }
+luatypo.pagelist = " "
+
+local hyphcount = 0
+local parlines = 0
+local pagelines = 0
+local pageno = 0
+local prevno = 0
+local pageflag = false
+
+local char_to_discard = { }
+char_to_discard[string.byte(",")] = true
+char_to_discard[string.byte(".")] = true
+char_to_discard[string.byte("!")] = true
+char_to_discard[string.byte("?")] = true
+char_to_discard[string.byte(":")] = true
+char_to_discard[string.byte(";")] = true
+char_to_discard[string.byte("-")] = true
+
+local DISC = node.id("disc")
+local GLYPH = node.id("glyph")
+local GLUE = node.id("glue")
+local KERN = node.id("kern")
+local HLIST = node.id("hlist")
+local VLIST = node.id("vlist")
+local LPAR = node.id("local_par")
+local MKERN = node.id("margin_kern")
+local PENALTY = node.id("penalty")
+local USRSKIP = 0
+local PARSKIP = 3
+local LEFTSKIP = 8
+local TOPSKIP = 10
+local PARFILL = 15
+local LINE = 1
+local BOX = 2
+local USER = 0
+
+local dimensions = node.dimensions
+local rangedimensions = node.rangedimensions
+local effective_glue = node.effective_glue
+local set_attribute = node.set_attribute
+local slide = node.slide
+local traverse = node.traverse
+local traverse_id = node.traverse_id
+local has_field = node.has_field
+local uses_font = node.uses_font
+local is_glyph = node.is_glyph
+
+% \end{macrocode}
+% Some helpers functions.
+% \begin{macrocode}
+local get_pagebody = function (head)
+ local textht = tex.getdimen("textheight")
+ local fn = head.list
+ local body = nil
+ repeat
+ fn = fn.next
+ until fn.id == VLIST and fn.height > 0
+ first = fn.list
+ local ht = string.format("%.1fpt", fn.height/65536)
+ local dp = string.format("%.1fpt", fn.depth/65536)
+ texio.write_nl('SKIP vlist: ht=' .. ht .. ' dp=' .. dp)
+ for n in traverse_id(VLIST,first) do
+ if n.subtype == 0 and n.height == textht then
+ local ht = string.format("%.1fpt", n.height/65536)
+ texio.write_nl(' BODY: ' .. ht)
+ texio.write_nl(' ')
+ body = n
+ break
+ else
+ local ht = string.format("%.1fpt", n.height/65536)
+ local dp = string.format("%.1fpt", n.depth/65536)
+ texio.write_nl(' SKIP vlist: ht=' .. ht .. ' dp=' .. dp)
+ first = n.list
+ for n in traverse_id(VLIST,first) do
+ if n.subtype == 0 and n.height == textht then
+ ht = string.format("%.1fpt", n.height/65536)
+ texio.write_nl(' BODY: ' .. ht)
+ texio.write_nl(' ')
+ body = n
+ break
+ end
+ end
+ end
+ end
+ if not body then
+ texio.write_nl('***lua-typo ERROR: PAGE BODY *NOT* FOUND!***')
+ end
+ return body
+end
+
+local print_subtype = function (node,parent)
+ local n = node
+ if n.id == GLYPH and n.subtype == 256 and n.char < 0x100 then
+ texio.write(string.char(n.char))
+ else
+ if n.subtype then
+ texio.write(n.subtype)
+ else
+ texio.write(' ')
+ end
+ end
+ if n.id == GLUE then
+ real_pt = string.format("%.1fpt", effective_glue(n,parent)/65536)
+ texio.write(' realwd=' .. real_pt)
+ elseif n.id == DISC then
+ texio.write(' pre=' .. tostring(n.pre))
+ texio.write(' post=' .. tostring(n.post))
+ texio.write(' repl=' .. tostring(n.replace))
+ elseif n.subtype and n.subtype < 256 and n.height and n.depth then
+ ht_pt = string.format("%.1fpt", n.height/65536)
+ dp_pt = string.format("%.1fpt", n.depth/65536)
+ texio.write(' ht=' .. ht_pt .. ' dp=' .. dp_pt)
+ if n.width then
+ wd_pt = string.format("%.1fpt", n.width/65536)
+ texio.write(' wd=' .. wd_pt)
+ end
+ end
+end
+
+% \end{macrocode}
+% Main function. It prints a structured list of nodes found on the
+% page body (header and footer excluded, footnotes included).
+% \begin{macrocode}
+local scanvlist = function (head)
+ local textht = tex.getdimen("textheight")
+ local textwd = tex.getdimen("textwidth")
+ local pageno = tex.getcount("c@page")
+ texio.write_nl('PAGE ' .. pageno)
+ texio.write(' textheight='.. string.format("%.1fpt", textht/65536))
+ texio.write(' textwidth=' .. string.format("%.1fpt", textwd/65536))
+ local linecount = 0
+ local body, parent, ht_pt, dp_pt, real_pt
+ body = get_pagebody(head)
+ if body then
+ parent = body
+ head = body.head
+ end
+ while (head) do
+ texio.write_nl(tostring(node.type(head.id)))
+ texio.write('-')
+ print_subtype(head,body)
+ if head.kern then
+ ht_pt = string.format("%.1fpt", head.kern/65536)
+ texio.write(' KERN ht/wd=' .. ht_pt)
+ end
+ local next = head.next
+ local first = head.head
+ for n in traverse(first) do
+ parent = head
+ texio.write_nl(' ' .. tostring(node.type(n.id)))
+ texio.write('-')
+ print_subtype(n,head)
+ if n.id == VLIST or n.id == HLIST then
+ local ff = n.head
+ for nn in traverse(ff) do
+ parent = n
+ texio.write_nl(' ' .. tostring(node.type(nn.id)))
+ texio.write('-')
+ print_subtype(nn,n)
+ if nn.id == VLIST or nn.id == HLIST then
+ local f3 = nn.head
+ for n3 in traverse(f3) do
+ parent = nn
+ texio.write_nl(' ' .. tostring(node.type(n3.id)))
+ texio.write('-')
+ print_subtype(n3,nn)
+ if n3.id == VLIST or n3.id == HLIST then
+ local f4 = n3.head
+ for n4 in traverse(f4) do
+ parent = n3
+ texio.write_nl(' ' .. tostring(node.type(n4.id)))
+ texio.write('-')
+ print_subtype(n4,n3)
+ if n4.id == VLIST or n4.id == HLIST then
+ local f5 = n4.head
+ for n5 in traverse(f5) do
+ parent = n4
+ texio.write_nl(' ' .. tostring(node.type(n4.id)))
+ texio.write('-')
+ print_subtype(n5,n4)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ head = next
+ end
+ return true
+end
+
+% \end{macrocode}
+% Add the main function to callback "pre\_shipout\_filter".
+% \begin{macrocode}
+luatexbase.add_to_callback("pre_shipout_filter",scanvlist,"check_vlists")
+% \end{macrocode}
+\end{luacode}
+% \end{Debugging}
+%
% \iffalse
-%</dtx>
+%</scan>
% \fi
%
% \Finale