From 01945ee778f661b15c72ca982b7f19293042057b Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 3 Jun 2021 20:50:26 +0000 Subject: lua-typo (3jun21) git-svn-id: svn://tug.org/texlive/trunk@59457 c570f23f-e606-0410-a88d-b1316a301751 --- .../texmf-dist/tex/lualatex/lua-typo/lua-typo.sty | 613 +++++++++++++++------ 1 file changed, 456 insertions(+), 157 deletions(-) (limited to 'Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.sty') 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 -- cgit v1.2.3