From 01945ee778f661b15c72ca982b7f19293042057b Mon Sep 17 00:00:00 2001
From: Karl Berry <karl@freefriends.org>
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

