summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/lualatex/lua-typo
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-06-03 20:50:26 +0000
committerKarl Berry <karl@freefriends.org>2021-06-03 20:50:26 +0000
commit01945ee778f661b15c72ca982b7f19293042057b (patch)
tree25d71cf808044d76c4ebddf96e87ee2007e848ad /Master/texmf-dist/tex/lualatex/lua-typo
parent7cff8b44d3f87cd67e7037e61050c11eec8360b7 (diff)
lua-typo (3jun21)
git-svn-id: svn://tug.org/texlive/trunk@59457 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/lualatex/lua-typo')
-rw-r--r--Master/texmf-dist/tex/lualatex/lua-typo/lua-typo-2021-04-18.sty843
-rw-r--r--Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.cfg10
-rw-r--r--Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.sty613
3 files changed, 1305 insertions, 161 deletions
diff --git a/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo-2021-04-18.sty b/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo-2021-04-18.sty
new file mode 100644
index 00000000000..1580bcb1470
--- /dev/null
+++ b/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo-2021-04-18.sty
@@ -0,0 +1,843 @@
+%%
+%% This is file `lua-typo.sty' v0.40,
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% lua-typo.dtx (with options: `sty')
+%%
+%% IMPORTANT NOTICE:
+%% For the copyright see the source file `lua-typo.dtx'.
+%%
+\NeedsTeXFormat{LaTeX2e}[2020/01/01]
+\ProvidesPackage{lua-typo}
+ [2021/04/18 v.0.40 Daniel Flipo]
+\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
+
+\begin{luacode}
+luatypo = { }
+\end{luacode}
+\SetupKeyvalOptions{
+ family=luatypo,
+ prefix=LT@,
+}
+\DeclareBoolOption[false]{ShowOptions}
+\DeclareBoolOption[false]{None}
+\DeclareBoolOption[false]{All}
+\DeclareBoolOption[false]{BackParindent}
+\DeclareBoolOption[false]{ShortLines}
+\DeclareBoolOption[false]{ShortPages}
+\DeclareBoolOption[false]{OverfullLines}
+\DeclareBoolOption[false]{UnderfullLines}
+\DeclareBoolOption[false]{Widows}
+\DeclareBoolOption[false]{Orphans}
+\DeclareBoolOption[false]{EOPHyphens}
+\DeclareBoolOption[false]{RepeatedHyphens}
+\DeclareBoolOption[false]{ParLastHyphen}
+\DeclareBoolOption[false]{EOLShortWords}
+\DeclareBoolOption[false]{FirstWordMatch}
+\DeclareBoolOption[false]{LastWordMatch}
+\AddToKeyvalOption{luatypo}{All}{%
+ \LT@ShortLinestrue \LT@ShortPagestrue
+ \LT@OverfullLinestrue \LT@UnderfullLinestrue
+ \LT@Widowstrue \LT@Orphanstrue
+ \LT@EOPHyphenstrue \LT@RepeatedHyphenstrue
+ \LT@ParLastHyphentrue \LT@EOLShortWordstrue
+ \LT@FirstWordMatchtrue \LT@LastWordMatchtrue
+ \LT@BackParindenttrue
+}
+\ProcessKeyvalOptions{luatypo}
+\AtEndOfPackage{%
+ \ifLT@None
+ \directlua{ luatypo.None = true }%
+ \else
+ \directlua{ luatypo.None = false }%
+ \fi
+ \ifLT@BackParindent
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.BackParindent = true }%
+ \else
+ \directlua{ luatypo.BackParindent = false }%
+ \fi
+ \ifLT@ShortLines
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.ShortLines = true }%
+ \else
+ \directlua{ luatypo.ShortLines = false }%
+ \fi
+ \ifLT@ShortPages
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.ShortPages = true }%
+ \else
+ \directlua{ luatypo.ShortPages = false }%
+ \fi
+ \ifLT@OverfullLines
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.OverfullLines = true }%
+ \else
+ \directlua{ luatypo.OverfullLines = false }%
+ \fi
+ \ifLT@UnderfullLines
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.UnderfullLines = true }%
+ \else
+ \directlua{ luatypo.UnderfullLines = false }%
+ \fi
+ \ifLT@Widows
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.Widows = true }%
+ \else
+ \directlua{ luatypo.Widows = false }%
+ \fi
+ \ifLT@Orphans
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.Orphans = true }%
+ \else
+ \directlua{ luatypo.Orphans = false }%
+ \fi
+ \ifLT@EOPHyphens
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.EOPHyphens = true }%
+ \else
+ \directlua{ luatypo.EOPHyphens = false }%
+ \fi
+ \ifLT@RepeatedHyphens
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.RepeatedHyphens = true }%
+ \else
+ \directlua{ luatypo.RepeatedHyphens = false }%
+ \fi
+ \ifLT@ParLastHyphen
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.ParLastHyphen = true }%
+ \else
+ \directlua{ luatypo.ParLastHyphen = false }%
+ \fi
+ \ifLT@EOLShortWords
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.EOLShortWords = true }%
+ \else
+ \directlua{ luatypo.EOLShortWords = false }%
+ \fi
+ \ifLT@FirstWordMatch
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.FirstWordMatch = true }%
+ \else
+ \directlua{ luatypo.FirstWordMatch = false }%
+ \fi
+ \ifLT@LastWordMatch
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.LastWordMatch = true }%
+ \else
+ \directlua{ luatypo.LastWordMatch = false }%
+ \fi
+}
+\ifLT@ShowOptions
+ \GenericWarning{* }{%
+ *** List of possible options for lua-typo ***\MessageBreak
+ [Default values between brackets]%
+ \MessageBreak
+ ShowOptions [false]\MessageBreak
+ None [false]\MessageBreak
+ BackParindent [false]\MessageBreak
+ ShortLines [false]\MessageBreak
+ ShortPages [false]\MessageBreak
+ OverfullLines [false]\MessageBreak
+ UnderfullLines [false]\MessageBreak
+ Widows [false]\MessageBreak
+ Orphans [false]\MessageBreak
+ EOPHyphens [false]\MessageBreak
+ RepeatedHyphens [false]\MessageBreak
+ ParLastHyphen [false]\MessageBreak
+ EOLShortWords [false]\MessageBreak
+ FirstWordMatch [false]\MessageBreak
+ LastWordMatch [false]\MessageBreak
+ \MessageBreak
+ *********************************************%
+ \MessageBreak Lua-typo [ShowOptions]
+ }%
+\fi
+\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{%
+\ifnum\luatypo@options = 0 \LT@Nonetrue \fi
+\ifLT@None
+ \directlua{
+ texio.write_nl(' ')
+ texio.write_nl('***********************************')
+ texio.write_nl('*** lua-typo loaded with NO option:')
+ texio.write_nl('*** NO CHECK PERFORMED! ***')
+ texio.write_nl('***********************************')
+ texio.write_nl(' ')
+ }%
+\else
+ \directlua{
+ texio.write_nl(' ')
+ texio.write_nl('*************************************')
+ 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(luatypo.pagelist)
+ end
+ texio.write_nl('***********************************')
+ texio.write_nl(' ')
+ }%
+\fi}
+\newcommand*{\luatypoOneChar}[2]{%
+ \def\luatypo@LANG{#1}\luatypo@single={#2}%
+ \ifcsname l@\luatypo@LANG\endcsname
+ \luatypo@LANGno=\the\csname l@\luatypo@LANG\endcsname \relax
+ \directlua{
+ local langno = \the\luatypo@LANGno
+ local string = \the\luatypo@single
+ luatypo.single[langno] = " "
+ for p, c in utf8.codes(string) do
+ local s = string.char(c)
+ luatypo.single[langno] = luatypo.single[langno] .. s
+ end
+ }%
+ \else
+ \PackageWarning{luatypo}{Unknown language "\luatypo@LANG",
+ \MessageBreak \protect\luatypoOneChar\space command ignored}%
+ \fi}
+\newcommand*{\luatypoTwoChars}[2]{%
+ \def\luatypo@LANG{#1}\luatypo@double={#2}%
+ \ifcsname l@\luatypo@LANG\endcsname
+ \luatypo@LANGno=\the\csname l@\luatypo@LANG\endcsname \relax
+ \directlua{
+ local langno = \the\luatypo@LANGno
+ local string = \the\luatypo@double
+ luatypo.double[langno] = " "
+ for p, c in utf8.codes(string) do
+ local s = string.char(c)
+ luatypo.double[langno] = luatypo.double[langno] .. s
+ end
+ }%
+ \else
+ \PackageWarning{luatypo}{Unknown language "\luatypo@LANG",
+ \MessageBreak \protect\luatypoTwoChars\space command ignored}%
+ \fi}
+\newcommand*{\luatypoSetColor}[2]{%
+ \begingroup
+ \color{#2}%
+ \directlua{luatypo.colortbl[#1]=\the\LuaCol@Attribute}%
+ \endgroup
+}
+\begin{luacode}
+luatypo.single = { }
+luatypo.double = { }
+luatypo.colortbl = { }
+luatypo.pagelist = ""
+
+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 split_lig = { }
+split_lig[0xFB00] = "ff"
+split_lig[0xFB01] = "fi"
+split_lig[0xFB02] = "fl"
+split_lig[0xFB03] = "ffi"
+split_lig[0xFB04] = "ffl"
+split_lig[0xFB05] = "st"
+split_lig[0xFB06] = "st"
+
+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 LPAR = node.id("local_par")
+local MKERN = node.id("margin_kern")
+local PENALTY = node.id("penalty")
+local USRSKIP = 0
+local PARSKIP = 3
+local LFTSKIP = 8
+local RGTSKIP = 9
+local TOPSKIP = 10
+local PARFILL = 15
+local LINE = 1
+local BOX = 2
+local EQN = 6
+local USER = 0
+local HYPH = 0x2D
+local LIGA = 0x102
+local parline = 0
+
+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
+
+local color_node = function (node, color)
+ local attr = oberdiek.luacolor.getattribute()
+ if node and node.id == DISC then
+ local pre = node.pre
+ local post = node.post
+ local repl = node.replace
+ if pre then
+ set_attribute(pre,attr,color)
+ end
+ if post then
+ set_attribute(post,attr,color)
+ end
+ if repl then
+ set_attribute(repl,attr,color)
+ end
+ elseif node then
+ set_attribute(node,attr,color)
+ end
+end
+local color_hlist = function (head, color)
+ local first = head.head
+ for n in traverse(first) do
+ color_node(n, color)
+ end
+end
+local color_line = function (head, color)
+ local first = head.head
+ for n in traverse(first) do
+ if n and n.id == HLIST then
+ color_hlist(n, color)
+ else
+ color_node(n, color)
+ end
+ end
+end
+local signature = function (node, string, swap)
+ local n = node
+ local str = string
+ if n and n.id == GLYPH then
+ local b, id = is_glyph(n)
+ if b and not char_to_discard[b] then
+ if b == 0x2019 then b = 0x27 end
+ if b < 0x100 then
+ str = str .. string.char(b)
+ elseif split_lig[b] then
+ local c = split_lig[b]
+ if swap then
+ c = string.reverse(c)
+ end
+ str = str .. c
+ elseif n.subtype == LIGA and b > 0xE000 then
+ local c = string.sub(b,-2)
+ if swap then
+ c = string.reverse(c)
+ end
+ str = str .. c
+ end
+ end
+ elseif n and n.id == DISC then
+ local pre = n.pre
+ local post = n.post
+ local c1 = ""
+ local c2 = ""
+ if pre and pre.char and pre.char ~= HYPH and pre.char < 0x100 then
+ c1 = string.char(pre.char)
+ end
+ if post and post.char then
+ if post.char < 0x100 then
+ c2 = string.char(post.char)
+ elseif split_lig[post.char] then
+ c2 = split_lig[post.char]
+ if swap then
+ c2 = string.reverse(c2)
+ end
+ end
+ end
+ if swap then
+ str = str .. c2 .. c1
+ else
+ str = str .. c1 .. c2
+ end
+ end
+ local len = string.len(str)
+ if string.find(str, "_") then
+ len = len - 1
+ end
+ return len, str
+end
+local check_last_word = function (old, node, flag)
+ local COLOR = luatypo.colortbl[11]
+ local match = false
+ local new = ""
+ local maxlen = 0
+ if flag and node then
+ local swap = true
+ local lastn = node
+ while lastn and lastn.id ~= GLYPH and lastn.id ~= DISC do
+ lastn = lastn.prev
+ end
+ local n = lastn
+ while n and n.id ~= GLUE do
+ maxlen, new = signature (n, new, swap)
+ n = n.prev
+ end
+ if n and n.id == GLUE then
+ new = new .. "_"
+ repeat
+ n = n.prev
+ maxlen, new = signature (n, new, swap)
+ until not n or n.id == GLUE
+ end
+ new = string.reverse(new)
+ local MinFull = luatypo.MinFull
+ local MinPart = luatypo.MinPart
+ MinFull = math.min(MinPart,MinFull)
+ local k = MinPart
+ local oldlast = string.gsub (old, '.*_', '')
+ local newlast = string.gsub (new, '.*_', '')
+ local i = string.find(new, "_")
+ if i and i > maxlen - MinPart + 1 then
+ k = MinPart + 1
+ end
+ local oldsub = string.sub(old,-k)
+ local newsub = string.sub(new,-k)
+ local l = string.len(new)
+ if oldsub == newsub and l >= k then
+ match = true
+ elseif oldlast == newlast and string.len(newlast) >= MinFull then
+ match = true
+ oldsub = oldlast
+ newsub = newlast
+ k = string.len(newlast)
+ end
+ if match then
+ local osub = oldsub
+ local nsub = newsub
+ while osub == nsub and k <= maxlen do
+ k = k +1
+ osub = string.sub(old,-k)
+ nsub = string.sub(new,-k)
+ if osub == nsub then
+ newsub = nsub
+ end
+ end
+ pageflag = true
+ newsub = string.gsub(newsub, '^_', '')
+ oldsub = string.reverse(newsub)
+ local newsub = ""
+ local n = lastn
+ repeat
+ if n and n.id ~= GLUE then
+ color_node(n, COLOR)
+ l, newsub = signature(n, newsub, swap)
+ elseif n then
+ newsub = newsub .. "_"
+ end
+ n = n.prev
+ until not n or newsub == oldsub or l >= k
+ end
+ end
+ return new
+end
+local check_first_word = function (old, node, flag)
+ local COLOR = luatypo.colortbl[10]
+ local match = false
+ local swap = false
+ local new = ""
+ local maxlen = 0
+ local start = node
+ local n = start
+ while n and n.id ~= GLYPH and n.id ~= DISC do
+ n = n.next
+ end
+ while n and n.id ~= GLUE do
+ maxlen, new = signature (n, new, swap)
+ n = n.next
+ end
+ if n and n.id == GLUE then
+ new = new .. "_"
+ repeat
+ n = n.next
+ maxlen, new = signature (n, new, swap)
+ until not n or n.id == GLUE
+ end
+ if flag then
+ local MinFull = luatypo.MinFull
+ local MinPart = luatypo.MinPart
+ MinFull = math.min(MinPart,MinFull)
+ local k = MinPart
+ local oldsub = ""
+ local newsub = ""
+ local oldfirst = string.gsub (old, '_.*', '')
+ local newfirst = string.gsub (new, '_.*', '')
+ local i = string.find(new, "_")
+ if i and i <= MinPart then
+ k = MinPart + 1
+ end
+ local oldsub = string.sub(old,1,k)
+ local newsub = string.sub(new,1,k)
+ local l = string.len(newsub)
+ if oldsub == newsub and l >= k then
+ match = true
+ elseif oldfirst == newfirst and string.len(newfirst) >= MinFull then
+ match = true
+ oldsub = oldfirst
+ newsub = newfirst
+ k = string.len(newfirst)
+ end
+ if match then
+ local osub = oldsub
+ local nsub = newsub
+ while osub == nsub and k <= maxlen do
+ k = k + 1
+ osub = string.sub(old,1,k)
+ nsub = string.sub(new,1,k)
+ if osub == nsub then
+ newsub = nsub
+ end
+ end
+ pageflag = true
+ newsub = string.gsub(newsub, '_$', '') --$
+ oldsub = newsub
+ local newsub = ""
+ local k = string.len(oldsub)
+ local n = start
+ repeat
+ if n and n.id ~= GLUE then
+ color_node(n, COLOR)
+ l, newsub = signature(n, newsub, swap)
+ elseif n then
+ newsub = newsub .. "_"
+ end
+ n = n.next
+ until not n or newsub == oldsub or l >= k
+ end
+ end
+ return new
+end
+local check_regexpr = function (glyph)
+ local COLOR = luatypo.colortbl[3]
+ local lang = glyph.lang
+ local match = false
+ local lchar, id = is_glyph(glyph)
+ local previous = glyph.prev
+ if lang and luatypo.single[lang] then
+ if lchar and lchar < 0x100 and previous and previous.id == GLUE then
+ match = string.find(luatypo.single[lang], string.char(lchar))
+ if match then
+ pageflag = true
+ color_node(glyph,COLOR)
+ end
+ end
+ end
+ if lang and luatypo.double[lang] then
+ if lchar and previous and previous.id == GLYPH then
+ local pchar, id = is_glyph(previous)
+ local pprev = previous.prev
+ if pchar and pchar < 0x100 and pprev and pprev.id == GLUE then
+ local pattern = string.char(pchar) .. string.char(lchar)
+ match = string.find(luatypo.double[lang], pattern)
+ if match then
+ pageflag = true
+ color_node(previous,COLOR)
+ color_node(glyph,COLOR)
+ end
+ end
+ elseif lchar and previous and previous.id == KERN then
+ local pprev = previous.prev
+ if pprev and pprev.id == GLYPH then
+ local pchar, id = is_glyph(pprev)
+ local ppprev = pprev.prev
+ if pchar and pchar < 0x100 and
+ ppprev and ppprev.id == GLUE then
+ local pattern = string.char(pchar) .. string.char(lchar)
+ match = string.find(luatypo.double[lang], pattern)
+ if match then
+ pageflag = true
+ color_node(pprev,COLOR)
+ color_node(glyph,COLOR)
+ end
+ end
+ end
+ end
+ end
+end
+local show_pre_disc = function (disc, color)
+ local n = disc
+ while n and n.id ~= GLUE do
+ color_node(n, color)
+ n = n.prev
+ end
+ return n
+end
+luatypo.check_page = function (head)
+ local PAGEmin = luatypo.PAGEmin
+ local HYPHmax = luatypo.HYPHmax
+ local LLminWD = luatypo.LLminWD
+ local BackPI = luatypo.BackPI
+ local BackFuzz = luatypo.BackFuzz
+ local BackParindent = luatypo.BackParindent
+ local ShortLines = luatypo.ShortLines
+ local ShortPages = luatypo.ShortPages
+ local OverfullLines = luatypo.OverfullLines
+ local UnderfullLines = luatypo.UnderfullLines
+ local Widows = luatypo.Widows
+ local Orphans = luatypo.Orphans
+ local EOPHyphens = luatypo.EOPHyphens
+ local RepeatedHyphens = luatypo.RepeatedHyphens
+ local FirstWordMatch = luatypo.FirstWordMatch
+ local ParLastHyphen = luatypo.ParLastHyphen
+ local EOLShortWords = luatypo.EOLShortWords
+ local LastWordMatch = luatypo.LastWordMatch
+ local pageno = tex.getcount("c@page")
+ local Stretch = math.max(luatypo.Stretch/100,1)
+ local blskip = tex.getglue("baselineskip")
+ local textht = tex.getdimen("textheight")
+ local vpos_min = (PAGEmin+1) * blskip
+ local vpos = 0
+
+ local pageflag = false
+ local orphanflag = false
+ local widowflag = false
+ local lwhyphflag = false
+ local pageshort = false
+ local firstwd = ""
+ local lastwd = ""
+ local hyphcount = 0
+ local pageline = 0
+
+ while head do
+ local nextnode = head.next
+ local prevnode = head.prev
+ local pprevnode = nil
+ if prevnode then
+ pprevnode = prevnode.prev
+ end
+ if head.id == HLIST and head.subtype == LINE then
+ vpos = vpos + head.height + head.depth
+ local first = head.head
+ while first.id == MKERN or
+ (first.id == GLUE and first.subtype == LFTSKIP) do
+ first = first.next
+ end
+ local ListItem = false
+ pageline = pageline + 1
+ if head.glue_set == 1 and head.glue_sign == 2 and
+ head.glue_order == 0 and OverfullLines then
+ pageflag = true
+ local COLOR = luatypo.colortbl[7]
+ color_line (head, COLOR)
+ elseif head.glue_set >= Stretch and head.glue_sign == 1 and
+ head.glue_order == 0 and UnderfullLines then
+ local COLOR = luatypo.colortbl[8]
+ pageflag = true
+ color_line (head, COLOR)
+ end
+ if first.id == LPAR then
+ hyphcount = 0
+ parline = 1
+ if not nextnode then
+ orphanflag = true
+ end
+ local nn = first.next
+ if nn and nn.id == HLIST and nn.subtype == BOX then
+ ListItem = true
+ end
+ else
+ parline = parline + 1
+ end
+ if FirstWordMatch then
+ local flag = not ListItem
+ firstwd = check_first_word(firstwd, first, flag)
+ end
+ local ln = slide(first)
+ local pn = ln.prev
+ if pn and pn.id == GLUE and pn.subtype == PARFILL then
+ hyphcount = 0
+ orphanflag = false
+ if pageline == 1 and parline > 1 then
+ widowflag = true
+ end
+ local PFskip = effective_glue(pn,head)
+ if ShortLines then
+ local llwd = tex.hsize - PFskip
+ if llwd < LLminWD then
+ pageflag = true
+ local COLOR = luatypo.colortbl[6]
+ local attr = oberdiek.luacolor.getattribute()
+ color_line (head, COLOR)
+ end
+ end
+ if BackParindent and PFskip < BackPI and PFskip > BackFuzz then
+ pageflag = true
+ local COLOR = luatypo.colortbl[12]
+ local attr = oberdiek.luacolor.getattribute()
+ color_line (head, COLOR)
+ end
+ if LastWordMatch then
+ local flag = textline
+ if PFskip > BackPI then
+ flag = false
+ end
+ lastwd = check_last_word(lastwd, pn, flag)
+ end
+ elseif pn and pn.id == DISC then
+ hyphcount = hyphcount + 1
+ if LastWordMatch then
+ lastwd = check_last_word(lastwd, ln, true)
+ end
+ if hyphcount > HYPHmax and RepeatedHyphens then
+ local COLOR = luatypo.colortbl[2]
+ local pg = show_pre_disc (pn,COLOR)
+ pageflag = true
+ end
+ if not nextnode and EOPHyphens then
+ lwhyphflag = true
+ end
+ if nextnode and ParLastHyphen then
+ local nnnode = nextnode.next
+ local nnnnode = nil
+ if nnnode and nnnode.next then
+ nnnnode = nnnode.next
+ if nnnnode and nnnnode.id == HLIST and
+ nnnnode.subtype == 1 and nnnnode.glue_order == 2 then
+ local COLOR = luatypo.colortbl[0]
+ local pg = show_pre_disc (pn,COLOR)
+ pageflag = true
+ end
+ end
+ end
+ else
+ hyphcount = 0
+ if LastWordMatch and pn then
+ lastwd = check_last_word(lastwd, pn, true)
+ end
+ if EOLShortWords then
+ while pn and pn.id ~= GLYPH and pn.id ~= HLIST do
+ pn = pn.prev
+ end
+ if pn and pn.id == GLYPH then
+ check_regexpr(pn,line)
+ end
+ end
+ end
+ if widowflag and Widows then
+ pageflag = true
+ widowflag = false
+ local COLOR = luatypo.colortbl[4]
+ color_line (head, COLOR)
+ end
+ if orphanflag and Orphans then
+ pageflag = true
+ local COLOR = luatypo.colortbl[5]
+ color_line (head, COLOR)
+ end
+ if lwhyphflag and EOPHyphens then
+ pageflag = true
+ local COLOR = luatypo.colortbl[1]
+ local pg = show_pre_disc (pn,COLOR)
+ end
+ elseif head.id == GLUE and head.subtype == USRSKIP then
+ vpos = vpos + head.width
+ if not nextnode and ShortPages and
+ pageline > 1 and pageline < PAGEmin then
+ pageshort = true
+ end
+ if pageshort and vpos < vpos_min then
+ pageflag = true
+ local COLOR = luatypo.colortbl[9]
+ local n = head
+ repeat
+ n = n.prev
+ until n.id == HLIST and (n.subtype == LINE or n.subtype == EQN)
+ if n then
+ color_line(n, COLOR)
+ end
+ end
+ elseif head.id == GLUE then
+ vpos = vpos + head.width
+ end
+ head = nextnode
+ end
+ 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
+ end
+ return true
+end
+return luatypo.check_page
+\end{luacode}
+\AtEndOfPackage{%
+ \directlua{
+ if not luatypo.None then
+ luatexbase.add_to_callback
+ ("pre_output_filter",luatypo.check_page,"check_page")
+ end
+ }
+}
+
+\InputIfFileExists{lua-typo.cfg}%
+ {\PackageInfo{lua-typo.sty}{'lua-typo.cfg' file loaded}}%
+ {\PackageInfo{lua-typo.sty}{'lua-typo.cfg' file not found.
+ \MessageBreak Providing default values.}%
+ \definecolor{mygrey}{gray}{0.6}%
+ \definecolor{myred}{rgb}{1,0.55,0}
+ \luatypoSetColor0{red}% Paragraph last full line hyphenated
+ \luatypoSetColor1{red}% Page last word hyphenated
+ \luatypoSetColor2{red}% Hyphens ending two many consecutive lines
+ \luatypoSetColor3{red}% Short word at end of line
+ \luatypoSetColor4{cyan}% Widow
+ \luatypoSetColor5{cyan}% Orphan
+ \luatypoSetColor6{cyan}% Paragraph ending on a short line
+ \luatypoSetColor7{blue}% Overfull lines
+ \luatypoSetColor8{blue}% Underfull lines
+ \luatypoSetColor9{red}% Nearly empty page
+ \luatypoSetColor{10}{myred}% First word matches
+ \luatypoSetColor{11}{myred}% Last word matches
+ \luatypoSetColor{12}{mygrey}% Paragraph ending on a nearly full line
+ \luatypoBackPI=1em\relax
+ \luatypoBackFuzz=2pt\relax
+ \luatypoLLminWD=2\parindent\relax
+ \luatypoStretchMax=200\relax
+ \luatypoHyphMax=2\relax
+ \luatypoPageMin=5\relax
+ \luatypoMinFull=4\relax
+ \luatypoMinPART=4\relax
+ }%
+%%
+%%
+%% End of file `lua-typo.sty'.
diff --git a/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.cfg b/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.cfg
index a395e4fe2a5..5ad15f92242 100644
--- a/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.cfg
+++ b/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.cfg
@@ -6,7 +6,9 @@
\luatypoBackFuzz=2pt\relax
%% Minimum length of paragraphs’ last lines
-\luatypoLLminWD=2\parindent\relax
+\ifdim\parindent=0pt \luatypoLLminWD=20pt\relax
+\else \luatypoLLminWD=2\parindent\relax
+\fi
%% Maximum number of consecutive hyphenated lines
\luatypoHyphMax=2\relax
@@ -26,7 +28,7 @@
\definecolor{myred}{rgb}{1,0.55,0}
\luatypoSetColor0{red} % Paragraph last full line hyphenated
\luatypoSetColor1{red} % Page last word hyphenated
-\luatypoSetColor2{red} % Hyphens ending two many consecutive lines
+\luatypoSetColor2{red} % Hyphens on to many consecutive lines
\luatypoSetColor3{red} % Short word at end of line
\luatypoSetColor4{cyan} % Widow
\luatypoSetColor5{cyan} % Orphan
@@ -37,10 +39,10 @@
\luatypoSetColor{10}{myred} % First word matches
\luatypoSetColor{11}{myred} % Last word matches
\luatypoSetColor{12}{mygrey}% Paragraph ending on a nearly full line
+\luatypoSetColor{13}{cyan} % Footnote split
-%% Language specific settings (example for French only currently):
+%% Language specific settings (example for French):
%% short words (two letters max) to be avoided at end of lines.
-%% French:
%%\luatypoOneChar{french}{'À à Ô'}
%%\luatypoTwoChars{french}{'Je Tu Il On'}
%%
diff --git a/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.sty b/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.sty
index ed88c065c35..5110fb0e605 100644
--- a/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.sty
+++ b/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.sty
@@ -6,9 +6,21 @@
%%
%% lua-typo.dtx (with options: `sty')
%%
-\NeedsTeXFormat{LaTeX2e}[2020/01/01]
+%% IMPORTANT NOTICE:
+%% For the copyright see the source file `lua-typo.dtx’.
+%%
\ProvidesPackage{lua-typo}
- [2021/03/14 v.0.32 Daniel Flipo]
+ [2021/05/13 v.0.50 Daniel Flipo]
+\ifdefined\DeclareRelease
+ \DeclareRelease{v0.4}{2021-01-01}{lua-typo-2021-04-18.sty}
+ \DeclareCurrentRelease{}{2021-05-13}
+\else
+ \PackageWarning{lua-typo}{Your LaTeX kernel is too old to provide
+ access\MessageBreak to former versions of the lettrine package.%
+ \MessageBreak Anyway, lua-typo requires a LaTeX kernel dated%
+ \MessageBreak 2020-01-01 or newer; reported}
+\fi
+\NeedsTeXFormat{LaTeX2e}[2021/06/01]
\ifdefined\directlua
\RequirePackage{luatexbase,luacode,luacolor}
\RequirePackage{kvoptions,atveryend}
@@ -51,6 +63,7 @@ luatypo = { }
\DeclareBoolOption[false]{EOLShortWords}
\DeclareBoolOption[false]{FirstWordMatch}
\DeclareBoolOption[false]{LastWordMatch}
+\DeclareBoolOption[false]{FootnoteSplit}
\AddToKeyvalOption{luatypo}{All}{%
\LT@ShortLinestrue \LT@ShortPagestrue
\LT@OverfullLinestrue \LT@UnderfullLinestrue
@@ -58,7 +71,7 @@ luatypo = { }
\LT@EOPHyphenstrue \LT@RepeatedHyphenstrue
\LT@ParLastHyphentrue \LT@EOLShortWordstrue
\LT@FirstWordMatchtrue \LT@LastWordMatchtrue
- \LT@BackParindenttrue
+ \LT@BackParindenttrue \LT@FootnoteSplittrue
}
\ProcessKeyvalOptions{luatypo}
\AtEndOfPackage{%
@@ -145,6 +158,12 @@ luatypo = { }
\else
\directlua{ luatypo.LastWordMatch = false }%
\fi
+ \ifLT@FootnoteSplit
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.FootnoteSplit = true }%
+ \else
+ \directlua{ luatypo.FootnoteSplit = false }%
+ \fi
}
\ifLT@ShowOptions
\GenericWarning{* }{%
@@ -166,6 +185,7 @@ luatypo = { }
EOLShortWords [false]\MessageBreak
FirstWordMatch [false]\MessageBreak
LastWordMatch [false]\MessageBreak
+ FootnoteSplit [false]\MessageBreak
\MessageBreak
*********************************************%
\MessageBreak Lua-typo [ShowOptions]
@@ -207,6 +227,10 @@ luatypo = { }
end
texio.write_nl('***********************************')
texio.write_nl(' ')
+ local fileout= tex.jobname .. ".typo"
+ local out=io.open(fileout,"w+")
+ out:write(luatypo.buffer)
+ io.close(out)
}%
\fi}
\newcommand*{\luatypoOneChar}[2]{%
@@ -254,13 +278,8 @@ 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
+luatypo.buffer = "List of typographic flaws found for "
+ .. tex.jobname .. ".tex:\string\n\string\n"
local char_to_discard = { }
char_to_discard[string.byte(",")] = true
@@ -284,10 +303,13 @@ local DISC = node.id("disc")
local GLYPH = node.id("glyph")
local GLUE = node.id("glue")
local KERN = node.id("kern")
+local RULE = node.id("rule")
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 WHATSIT = node.id("whatsit")
local USRSKIP = 0
local PARSKIP = 3
local LFTSKIP = 8
@@ -296,10 +318,16 @@ local TOPSKIP = 10
local PARFILL = 15
local LINE = 1
local BOX = 2
+local INDENT = 3
+local ALIGN = 4
+local EQN = 6
local USER = 0
local HYPH = 0x2D
local LIGA = 0x102
+local parline = 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
@@ -328,22 +356,64 @@ local color_node = function (node, color)
set_attribute(node,attr,color)
end
end
-local color_hbox = function (head, color)
- local first = head.head
- for n in traverse(first) do
- color_node(n, color)
- end
-end
local color_line = function (head, color)
local first = head.head
for n in traverse(first) do
- if n and n.id == HLIST and n.subtype == BOX then
- color_hbox(n, color)
+ if n.id == HLIST or n.id == VLIST then
+ local ff = n.head
+ for nn in traverse(ff) do
+ if nn.id == HLIST or nn.id == VLIST then
+ local f3 = nn.head
+ for n3 in traverse(f3) do
+ if n3.id == HLIST or n3.id == VLIST then
+ local f4 = n3.head
+ for n4 in traverse(f4) do
+ if n4.id == HLIST or n4.id == VLIST then
+ local f5 = n4.head
+ for n5 in traverse(f5) do
+ if n5.id == HLIST or n5.id == VLIST then
+ local f6 = n5.head
+ for n6 in traverse(f6) do
+ color_node(n6, color)
+ end
+ else
+ color_node(n5, color)
+ end
+ end
+ else
+ color_node(n4, color)
+ end
+ end
+ else
+ color_node(n3, color)
+ end
+ end
+ else
+ color_node(nn, color)
+ end
+ end
else
color_node(n, color)
end
end
end
+log_flaw= function (msg, line, colno, footnote)
+ local pageno = tex.getcount("c@page")
+ local prt ="p. " .. pageno
+ if colno then
+ prt = prt .. ", col." .. colno
+ end
+ if line then
+ local l = string.format("%2d, ", line)
+ if footnote then
+ prt = prt .. ", (ftn.) line " .. l
+ else
+ prt = prt .. ", line " .. l
+ end
+ end
+ prt = prt .. msg
+ luatypo.buffer = luatypo.buffer .. prt .. "\string\n"
+end
local signature = function (node, string, swap)
local n = node
local str = string
@@ -397,23 +467,44 @@ local signature = function (node, string, swap)
end
return len, str
end
-local check_last_word = function (old, node, color, flag)
+local check_last_word = function (old, node, line, flag)
+ local COLOR = luatypo.colortbl[11]
local match = false
local new = ""
local maxlen = 0
if flag and node then
local swap = true
+ local box, go
local lastn = node
- while lastn and lastn.id ~= GLYPH and lastn.id ~= DISC do
+ while lastn and lastn.id ~= GLYPH and lastn.id ~= DISC and
+ lastn.id ~= HLIST do
lastn = lastn.prev
end
local n = lastn
+ if n and n.id == HLIST then
+ box = n
+ prev = n.prev
+ lastn = slide(n.head)
+ n = lastn
+ end
while n and n.id ~= GLUE do
maxlen, new = signature (n, new, swap)
n = n.prev
end
if n and n.id == GLUE then
new = new .. "_"
+ go = true
+ elseif box and not n then
+ local p = box.prev
+ if p.id == GLUE then
+ new = new .. "_"
+ n = p
+ else
+ n = box
+ end
+ go = true
+ end
+ if go then
repeat
n = n.prev
maxlen, new = signature (n, new, swap)
@@ -452,39 +543,66 @@ local check_last_word = function (old, node, color, flag)
newsub = nsub
end
end
+ pageflag = true
newsub = string.gsub(newsub, '^_', '')
+ local msg = "E.O.L. MATCH=" .. newsub
+ log_flaw(msg, line, colno, footnote)
oldsub = string.reverse(newsub)
local newsub = ""
local n = lastn
repeat
if n and n.id ~= GLUE then
- color_node(n, color)
+ color_node(n, COLOR)
l, newsub = signature(n, newsub, swap)
- elseif n then
+ elseif n and n.id == GLUE then
newsub = newsub .. "_"
+ elseif not n and box then
+ n = box
+ else
+ break
end
n = n.prev
- until not n or newsub == oldsub or l >= k
+ until newsub == oldsub or l >= k
end
end
- return new, match
+ return new
end
-local check_first_word = function (old, node, color, flag)
+local check_first_word = function (old, node, line, flag)
+ local COLOR = luatypo.colortbl[10]
local match = false
local swap = false
local new = ""
local maxlen = 0
- local start = node
- local n = start
- while n and n.id ~= GLYPH and n.id ~= DISC do
+ local n = node
+ local box, go
+ while n and n.id ~= GLYPH and n.id ~= DISC and
+ (n.id ~= HLIST or n.subtype == INDENT) do
n = n.next
end
+ local start = n
+ if n and n.id == HLIST then
+ box = n
+ start = n.head
+ n = n.head
+ end
while n and n.id ~= GLUE do
maxlen, new = signature (n, new, swap)
n = n.next
end
if n and n.id == GLUE then
new = new .. "_"
+ go = true
+ elseif box and not n then
+ local bn = box.next
+ if bn.id == GLUE then
+ new = new .. "_"
+ n = bn
+ else
+ n = box
+ end
+ go = true
+ end
+ if go then
repeat
n = n.next
maxlen, new = signature (n, new, swap)
@@ -525,25 +643,33 @@ local check_first_word = function (old, node, color, flag)
newsub = nsub
end
end
+ pageflag = true
newsub = string.gsub(newsub, '_$', '') --$
+ local msg = "B.O.L. MATCH=" .. newsub
+ log_flaw(msg, line, colno, footnote)
oldsub = newsub
local newsub = ""
local k = string.len(oldsub)
local n = start
repeat
if n and n.id ~= GLUE then
- color_node(n, color)
+ color_node(n, COLOR)
l, newsub = signature(n, newsub, swap)
- elseif n then
+ elseif n and n.id == GLUE then
newsub = newsub .. "_"
+ elseif not n and box then
+ n = box
+ else
+ break
end
n = n.next
- until not n or newsub == oldsub or l >= k
+ until newsub == oldsub or l >= k
end
end
- return new, match
+ return new
end
-local check_regexpr = function (glyph)
+local check_regexpr = function (glyph, line)
+ local pageno = tex.getcount("c@page")
local COLOR = luatypo.colortbl[3]
local lang = glyph.lang
local match = false
@@ -553,6 +679,9 @@ local check_regexpr = function (glyph)
if lchar and lchar < 0x100 and previous and previous.id == GLUE then
match = string.find(luatypo.single[lang], string.char(lchar))
if match then
+ pageflag = true
+ local msg = "RGX MATCH=" .. string.char(lchar)
+ log_flaw(msg, line, colno, footnote)
color_node(glyph,COLOR)
end
end
@@ -565,6 +694,9 @@ local check_regexpr = function (glyph)
local pattern = string.char(pchar) .. string.char(lchar)
match = string.find(luatypo.double[lang], pattern)
if match then
+ pageflag = true
+ local msg = "RGX MATCH=" .. pattern
+ log_flaw(msg, line, colno, footnote)
color_node(previous,COLOR)
color_node(glyph,COLOR)
end
@@ -574,10 +706,14 @@ local check_regexpr = function (glyph)
if pprev and pprev.id == GLYPH then
local pchar, id = is_glyph(pprev)
local ppprev = pprev.prev
- if pchar and pchar < 0x100 and ppprev and ppprev.id == GLUE then
+ if pchar and pchar < 0x100 and
+ ppprev and ppprev.id == GLUE then
local pattern = string.char(pchar) .. string.char(lchar)
match = string.find(luatypo.double[lang], pattern)
if match then
+ pageflag = true
+ local msg = "RGX MATCH=" .. pattern
+ log_flaw(msg, line, colno, footnote)
color_node(pprev,COLOR)
color_node(glyph,COLOR)
end
@@ -585,7 +721,6 @@ local check_regexpr = function (glyph)
end
end
end
- return match
end
local show_pre_disc = function (disc, color)
local n = disc
@@ -594,112 +729,189 @@ local show_pre_disc = function (disc, color)
n = n.prev
end
return n
+ end
+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
+ for n in traverse_id(VLIST,first) do
+ if n.subtype == 0 and n.height == textht then
+ body = n
+ break
+ else
+ first = n.list
+ for n in traverse_id(VLIST,first) do
+ if n.subtype == 0 and n.height == textht then
+ 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
-luatypo.check_page = function (head)
+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
+ n = n.next
+ if n and n.id == RULE and n.subtype == 0 then
+ htr = htr + n.height
+ n = n.next
+ if n and n.id == KERN and n.subtype == 1 then
+ htr = htr + n.kern
+ if htr == 0 then
+ flag = true
+ end
+ end
+ end
+ end
+ return flag
+end
+check_vtop = function (head, colno)
local PAGEmin = luatypo.PAGEmin
local HYPHmax = luatypo.HYPHmax
local LLminWD = luatypo.LLminWD
local BackPI = luatypo.BackPI
local BackFuzz = luatypo.BackFuzz
- local BackParindent = luatypo.BackParindent
- local ShortLines = luatypo.ShortLines
- local ShortPages = luatypo.ShortPages
- local OverfullLines = luatypo.OverfullLines
- local UnderfullLines = luatypo.UnderfullLines
- local Widows = luatypo.Widows
- local Orphans = luatypo.Orphans
- local EOPHyphens = luatypo.EOPHyphens
+ local BackParindent = luatypo.BackParindent
+ local ShortLines = luatypo.ShortLines
+ local ShortPages = luatypo.ShortPages
+ local OverfullLines = luatypo.OverfullLines
+ local UnderfullLines = luatypo.UnderfullLines
+ local Widows = luatypo.Widows
+ local Orphans = luatypo.Orphans
+ local EOPHyphens = luatypo.EOPHyphens
local RepeatedHyphens = luatypo.RepeatedHyphens
- local FirstWordMatch = luatypo.FirstWordMatch
- local ParLastHyphen = luatypo.ParLastHyphen
- local EOLShortWords = luatypo.EOLShortWords
- local LastWordMatch = luatypo.LastWordMatch
- local Stretch = math.max(luatypo.Stretch/100,1)
-
+ local FirstWordMatch = luatypo.FirstWordMatch
+ local ParLastHyphen = luatypo.ParLastHyphen
+ local EOLShortWords = luatypo.EOLShortWords
+ local LastWordMatch = luatypo.LastWordMatch
+ 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 first_bot = true
+ local footnote = false
+ local ftnsplit = false
local orphanflag = false
local widowflag = false
local lwhyphflag = false
- local match1 = false
- local match2 = false
+ local pageshort = false
local firstwd = ""
local lastwd = ""
+ local hyphcount = 0
+ local pageline = 0
+ local ftnline = 0
+ local line = 0
while head do
local nextnode = head.next
- local prevnode = head.prev
- local pprevnode = nil
- if prevnode then
- pprevnode = prevnode.prev
- end
- if head.id == GLUE and head.subtype == TOPSKIP then
- pageno = tex.getcount("c@page")
- hyphcount = 0
- if pageno > prevno then
- pageflag = false
- pagelines = 0
- match1 = false
+ 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 = ""
- prevno = pageno
- end
- elseif head.id == HLIST and head.subtype == LINE then
- local first = head.head
- if first.id == MKERN or
- (first.id == GLUE and first.subtype == LFTSKIP) then
- first = first.next
+ else
+ vpos = vpos + head.kern
end
- pagelines = pagelines + 1
- local ListItem = false
- local textline = false
- if first.id == GLYPH then
- textline = true
+ elseif head.id == HLIST and head.subtype == LINE and
+ (head.height > 0 or head.depth > 0) then
+ if footnote then
+ ftnline = ftnline + 1
+ line = ftnline
else
- local n = first
- repeat
- n = n.next
- if n and n.id == GLYPH then
- textline = true
- break
- end
- until not n or (n.id == GLUE and n.subtype == RGTSKIP)
+ pageline = pageline + 1
+ line = pageline
end
- if head.glue_set == 1 and head.glue_sign == 2 and
- head.glue_order == 0 and OverfullLines then
+ local first = head.head
+ local hmax = head.width + tex.hfuzz
+ local w,h,d = dimensions(1,2,0, first)
+ if w > hmax and OverfullLines then
pageflag = true
+ local wpt = string.format("%.2fpt", (w-head.width)/65536)
+ local msg = "OVERFULL line " .. wpt
+ log_flaw(msg, line, colno, footnote)
local COLOR = luatypo.colortbl[7]
color_line (head, COLOR)
- elseif head.glue_set >= Stretch and head.glue_sign == 1 and
- head.glue_order == 0 and UnderfullLines then
- local COLOR = luatypo.colortbl[8]
+ elseif head.glue_set > Stretch and head.glue_sign == 1 and
+ head.glue_order == 0 and UnderfullLines then
pageflag = true
+ local s = string.format("%.0f%s", 100*head.glue_set, "%")
+ local msg = "UNDERFULL line stretch=" .. s
+ log_flaw(msg, line, colno, footnote)
+ local COLOR = luatypo.colortbl[8]
color_line (head, COLOR)
end
+ 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
+ if not n then
+ if footnote then
+ page_bottom = true
+ else
+ page_bottom = true
+ body_bottom = true
+ end
+ elseif footnoterule_ahead(n, false) then
+ body_bottom = true
+ end
+ if footnote and page_bottom then
+ ftnsplit = true
+ end
+ while first.id == MKERN or
+ (first.id == GLUE and first.subtype == LFTSKIP) do
+ first = first.next
+ end
+ local ListItem = false
if first.id == LPAR then
hyphcount = 0
- parlines = 1
- if not nextnode then
+ if not footnote then
+ parline = 1
+ end
+ if body_bottom then
orphanflag = true
end
local nn = first.next
- if nn and nn.id == HLIST and nn.subtype == BOX then
- ListItem = true
+ if nn and nn.id == HLIST and nn.subtype == BOX then
+ ListItem = true
end
- else
- parlines = parlines + 1
+ elseif not footnote then
+ parline = parline + 1
end
if FirstWordMatch then
local flag = not ListItem
- local COLOR = luatypo.colortbl[10]
- firstwd, match1 = check_first_word(firstwd, first, COLOR, flag)
- if match1 then
- pageflag = true
- end
+ firstwd = check_first_word(firstwd, first, line, flag)
end
local ln = slide(first)
local pn = ln.prev
if pn and pn.id == GLUE and pn.subtype == PARFILL then
hyphcount = 0
+ ftnsplit = false
orphanflag = false
- if pagelines == 1 and parlines > 1 then
+ if pageline == 1 and parline > 1 then
widowflag = true
end
local PFskip = effective_glue(pn,head)
@@ -707,120 +919,205 @@ luatypo.check_page = function (head)
local llwd = tex.hsize - PFskip
if llwd < LLminWD then
pageflag = true
- local COLOR = luatypo.colortbl[6]
+ local msg = "SHORT LINE: " ..
+ string.format("%.0fpt", llwd/65536)
+ log_flaw(msg, line, colno, footnote)
+ local COLOR = luatypo.colortbl[6]
local attr = oberdiek.luacolor.getattribute()
color_line (head, COLOR)
end
end
if BackParindent and PFskip < BackPI and PFskip > BackFuzz then
pageflag = true
- local COLOR = luatypo.colortbl[12]
+ local msg = "LINE NEARLY FULL: missing " ..
+ string.format("%.1fpt", PFskip/65536)
+ log_flaw(msg, line, colno, footnote)
+ local COLOR = luatypo.colortbl[12]
local attr = oberdiek.luacolor.getattribute()
color_line (head, COLOR)
end
if LastWordMatch then
- local COLOR = luatypo.colortbl[11]
local flag = textline
if PFskip > BackPI then
flag = false
end
- lastwd, match1 = check_last_word(lastwd, pn, COLOR, flag)
- if match1 then
- pageflag = true
- end
+ lastwd = check_last_word(lastwd, pn, line, flag)
end
elseif pn and pn.id == DISC then
hyphcount = hyphcount + 1
if LastWordMatch then
- local COLOR = luatypo.colortbl[11]
- lastwd, match1 = check_last_word(lastwd, ln, COLOR, true)
- if match1 then
- pageflag = true
- end
+ lastwd = check_last_word(lastwd, ln, line, true)
end
if hyphcount > HYPHmax and RepeatedHyphens then
local COLOR = luatypo.colortbl[2]
local pg = show_pre_disc (pn,COLOR)
pageflag = true
+ local msg = "REPEATED HYPHENS: more than " .. HYPHmax
+ log_flaw(msg, line, colno, footnote)
end
- if not nextnode and EOPHyphens then
+ if (page_bottom or body_bottom) and EOPHyphens then
lwhyphflag = true
end
if nextnode and ParLastHyphen then
- local nnnode = nextnode.next
- local nnnnode = nil
- if nnnode and nnnode.next then
- nnnnode = nnnode.next
- if nnnnode and nnnnode.id == HLIST and
- nnnnode.subtype == 1 and nnnnode.glue_order == 2 then
+ local nn = nextnode.next
+ local nnn = nil
+ if nn and nn.next then
+ nnn = nn.next
+ if nnn.id == HLIST and nnn.subtype == LINE and
+ nnn.glue_order == 2 then
+ pageflag = true
+ local msg = "HYPHEN on next to last line"
+ log_flaw(msg, line, colno, footnote)
local COLOR = luatypo.colortbl[0]
local pg = show_pre_disc (pn,COLOR)
- pageflag = true
end
end
end
- elseif pn and pn.id == GLYPH then
+ else
hyphcount = 0
- if LastWordMatch then
- local COLOR = luatypo.colortbl[11]
- lastwd, match1 = check_last_word(lastwd, pn, COLOR, true)
+ if LastWordMatch and pn then
+ lastwd = check_last_word(lastwd, pn, line, true)
end
if EOLShortWords then
- match2 = check_regexpr(pn)
- end
- if match1 or match2 then
- pageflag = true
- end
- elseif pn and pn.id == MKERN then
- hyphcount = 0
- local ppn = pn.prev
- if ppn and ppn.id == GLYPH then
- if LastWordMatch then
- local COLOR = luatypo.colortbl[11]
- lastwd, match1 = check_last_word(lastwd, pn, COLOR, true)
- end
- if EOLShortWords then
- match2 = check_regexpr(ppn)
+ while pn and pn.id ~= GLYPH and pn.id ~= HLIST do
+ pn = pn.prev
end
- if match1 or match2 then
- pageflag = true
+ if pn and pn.id == GLYPH then
+ check_regexpr(pn,line)
end
end
- else
- hyphcount = 0
end
if widowflag and Widows then
pageflag = true
widowflag = false
+ local msg = "WIDOW"
+ log_flaw(msg, line, colno, footnote)
local COLOR = luatypo.colortbl[4]
color_line (head, COLOR)
end
if orphanflag and Orphans then
pageflag = true
+ local msg = "ORPHAN"
+ log_flaw(msg, line, colno, footnote)
local COLOR = luatypo.colortbl[5]
color_line (head, COLOR)
end
+ if ftnsplit and FootnoteSplit then
+ pageflag = true
+ local msg = "FOOTNOTE SPLIT"
+ log_flaw(msg, line, colno, footnote)
+ local COLOR = luatypo.colortbl[13]
+ color_line (head, COLOR)
+ end
if lwhyphflag and EOPHyphens then
pageflag = true
+ local msg = "LAST WORD SPLIT"
+ log_flaw(msg, line, colno, footnote)
local COLOR = luatypo.colortbl[1]
local pg = show_pre_disc (pn,COLOR)
end
- elseif not nextnode and head.id == GLUE and
- head.subtype == USRSKIP then
- if pagelines > 1 and pagelines < PAGEmin and ShortPages then
- pageflag = true
- local COLOR = luatypo.colortbl[9]
- local n = head
- while n and (n.id ~= HLIST or n.subtype ~= LINE) do
- n = n.prev
+ elseif head.id == HLIST and
+ (head.subtype == EQN or head.subtype == ALIGN) and
+ (head.height > 0 or head.depth > 0) then
+ vpos = vpos + head.height + head.depth
+ if footnote then
+ ftnline = ftnline + 1
+ line = ftnline
+ else
+ pageline = pageline + 1
+ line = pageline
+ end
+ local fl = true
+ local wd = 0
+ local hmax = 0
+ if head.subtype == EQN then
+ local f = head.list
+ wd = rangedimensions(head,f)
+ hmax = head.width + tex.hfuzz
+ else
+ wd = head.width
+ hmax = tex.getdimen("linewidth") + tex.hfuzz
+ end
+ if wd > hmax and OverfullLines then
+ if head.subtype == ALIGN then
+ local first = head.list
+ for n in traverse_id(HLIST, first) do
+ local last = slide(n.list)
+ if last.id == GLUE and last.subtype == USER then
+ wd = wd - effective_glue(last,n)
+ if wd <= hmax then fl = false end
+ end
+ end
end
- if n then
- color_line(n, COLOR)
+ if fl then
+ pageflag = true
+ local w = wd - hmax + tex.hfuzz
+ local wpt = string.format("%.2fpt", w/65536)
+ local msg = "OVERFULL equation " .. wpt
+ log_flaw(msg, line, colno, footnote)
+ local COLOR = luatypo.colortbl[7]
+ color_line (head, COLOR)
+ end
+ end
+ 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
+ elseif head.id == VLIST then
+ vpos = vpos + head.height + head.depth
+ elseif body_bottom and head.id == GLUE and head.subtype == 0 then
+ if first_bot then
+ if pageline > 1 and pageline < PAGEmin and ShortPages then
+ pageshort = true
end
+ if pageshort and vpos < vpos_min then
+ pageflag = true
+ local msg = "SHORT PAGE: only " .. pageline .. " lines"
+ log_flaw(msg, line, colno, footnote)
+ local COLOR = luatypo.colortbl[9]
+ local n = head
+ repeat
+ n = n.prev
+ until n.id == HLIST
+ color_line (n, COLOR)
+ end
+ first_bot = false
end
+ elseif head.id == GLUE then
+ vpos = vpos + effective_glue(head,body)
end
head = nextnode
end
+ return pageflag
+end
+luatypo.check_page = function (head)
+ local pageno = tex.getcount("c@page")
+ local pageflag = false
+ local n2, n3, col, colno
+ local body = get_pagebody(head)
+ local first = body.list
+ if first.id == HLIST and first.subtype == 2 then
+ n2 = first.list
+ colno = 0
+ for n in traverse_id(HLIST, n2) do
+ if n.id == HLIST and n.subtype == 2 then
+ n3 = n.list
+ col = n3.list
+ colno = colno + 1
+ pageflag = check_vtop(col,colno)
+ end
+ end
+ elseif body.id == VLIST and body.subtype == 0 then
+ col = body.list
+ pageflag = check_vtop(col,colno)
+ end
if pageflag then
local pl = luatypo.pagelist
local p = tonumber(string.match(pl, "%s(%d+),%s$"))
@@ -836,7 +1133,7 @@ return luatypo.check_page
\directlua{
if not luatypo.None then
luatexbase.add_to_callback
- ("pre_output_filter",luatypo.check_page,"check_page")
+ ("pre_shipout_filter",luatypo.check_page,"check_page",1)
end
}
}
@@ -849,7 +1146,7 @@ return luatypo.check_page
\definecolor{myred}{rgb}{1,0.55,0}
\luatypoSetColor0{red}% Paragraph last full line hyphenated
\luatypoSetColor1{red}% Page last word hyphenated
- \luatypoSetColor2{red}% Hyphens ending two many consecutive lines
+ \luatypoSetColor2{red}% Hyphens on to many consecutive lines
\luatypoSetColor3{red}% Short word at end of line
\luatypoSetColor4{cyan}% Widow
\luatypoSetColor5{cyan}% Orphan
@@ -860,9 +1157,11 @@ return luatypo.check_page
\luatypoSetColor{10}{myred}% First word matches
\luatypoSetColor{11}{myred}% Last word matches
\luatypoSetColor{12}{mygrey}% Paragraph ending on a nearly full line
+ \luatypoSetColor{13}{cyan}% Footnote split
\luatypoBackPI=1em\relax
\luatypoBackFuzz=2pt\relax
- \luatypoLLminWD=2\parindent\relax
+ \ifdim\parindent=0pt \luatypoLLminWD=20pt\relax
+ \else\luatypoLLminWD=2\parindent\relax\fi
\luatypoStretchMax=200\relax
\luatypoHyphMax=2\relax
\luatypoPageMin=5\relax