summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/math-noa.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/math-noa.lua')
-rw-r--r--tex/context/base/mkiv/math-noa.lua1593
1 files changed, 927 insertions, 666 deletions
diff --git a/tex/context/base/mkiv/math-noa.lua b/tex/context/base/mkiv/math-noa.lua
index f9e8c9f70..4c1997a64 100644
--- a/tex/context/base/mkiv/math-noa.lua
+++ b/tex/context/base/mkiv/math-noa.lua
@@ -29,7 +29,7 @@ local formatters, gmatch = string.formatters, string.gmatch
local sortedhash = table.sortedhash
local insert, remove = table.insert, table.remove
local div = math.div
-local setbit, hasbit = number.setbit, number.hasbit
+local bor, band = bit32.bor, bit32.band
local fonts = fonts
local nodes = nodes
@@ -47,11 +47,14 @@ local registerdirective = directives.register
local logreporter = logs.reporter
local setmetatableindex = table.setmetatableindex
+local colortracers = nodes.tracers.colors
+
local trace_remapping = false registertracker("math.remapping", function(v) trace_remapping = v end)
local trace_processing = false registertracker("math.processing", function(v) trace_processing = v end)
local trace_analyzing = false registertracker("math.analyzing", function(v) trace_analyzing = v end)
local trace_normalizing = false registertracker("math.normalizing", function(v) trace_normalizing = v end)
local trace_collapsing = false registertracker("math.collapsing", function(v) trace_collapsing = v end)
+local trace_fixing = false registertracker("math.fixing", function(v) trace_foxing = v end)
local trace_patching = false registertracker("math.patching", function(v) trace_patching = v end)
local trace_goodies = false registertracker("math.goodies", function(v) trace_goodies = v end)
local trace_variants = false registertracker("math.variants", function(v) trace_variants = v end)
@@ -62,12 +65,13 @@ local trace_domains = false registertracker("math.domains", function
local trace_families = false registertracker("math.families", function(v) trace_families = v end)
local trace_fences = false registertracker("math.fences", function(v) trace_fences = v end)
-local check_coverage = true registerdirective("math.checkcoverage", function(v) check_coverage = v end)
+local check_coverage = true registerdirective("math.checkcoverage", function(v) check_coverage = v end)
local report_processing = logreporter("mathematics","processing")
local report_remapping = logreporter("mathematics","remapping")
local report_normalizing = logreporter("mathematics","normalizing")
local report_collapsing = logreporter("mathematics","collapsing")
+local report_fixing = logreporter("mathematics","fixing")
local report_patching = logreporter("mathematics","patching")
local report_goodies = logreporter("mathematics","goodies")
local report_variants = logreporter("mathematics","variants")
@@ -93,6 +97,7 @@ local setlist = nuts.setlist
local setnext = nuts.setnext
local setprev = nuts.setprev
local setchar = nuts.setchar
+local setfam = nuts.setfam
local setsubtype = nuts.setsubtype
local setattr = nuts.setattr
@@ -104,6 +109,7 @@ local getid = nuts.getid
local getsubtype = nuts.getsubtype
local getchar = nuts.getchar
local getfont = nuts.getfont
+local getfam = nuts.getfam
local getattr = nuts.getattr
local getlist = nuts.getlist
@@ -116,7 +122,6 @@ local setsub = nuts.setsub
local setsup = nuts.setsup
local flush_node = nuts.flush
-local new_node = nuts.new -- todo: pool: math_noad math_sub
local copy_node = nuts.copy
local slide_nodes = nuts.slide
local set_visual = nuts.setvisual
@@ -126,6 +131,10 @@ local mlist_to_hlist = nodes.mlist_to_hlist
local font_of_family = node.family_font
local new_kern = nodepool.kern
+local new_submlist = nodepool.submlist
+local new_noad = nodepool.noad
+local new_delimiter = nodepool.delimiter
+local new_fence = nodepool.fence
local fonthashes = fonts.hashes
local fontdata = fonthashes.identifiers
@@ -174,8 +183,8 @@ local math_noad = nodecodes.noad -- attr nucleus sub sup
local math_accent = nodecodes.accent -- attr nucleus sub sup accent
local math_radical = nodecodes.radical -- attr nucleus sub sup left degree
local math_fraction = nodecodes.fraction -- attr nucleus sub sup left right
-local math_box = nodecodes.subbox -- attr list
-local math_sub = nodecodes.submlist -- attr list
+local math_subbox = nodecodes.subbox -- attr list
+local math_submlist = nodecodes.submlist -- attr list
local math_char = nodecodes.mathchar -- attr fam char
local math_textchar = nodecodes.mathtextchar -- attr fam char
local math_delim = nodecodes.delim -- attr small_fam small_char large_fam large_char
@@ -219,7 +228,7 @@ local function process(start,what,n,parent)
elseif id == math_char then
local char = getchar(start)
local font = getfont(start)
- local fam = getfield(start,"fam")
+ local fam = getfam(start)
report_processing("%w%S, family %a, font %a, char %a, shape %c",n*2,nutstring(start),fam,font,char,char)
else
report_processing("%w%S",n*2,nutstring(start))
@@ -253,7 +262,7 @@ local function process(start,what,n,parent)
noad = getsub (start) if noad then process(noad,what,n,start) end -- list
elseif id == math_char or id == math_textchar or id == math_delim then
break
- elseif id == math_box or id == math_sub then
+ elseif id == math_subbox or id == math_submlist then
local noad = getlist(start) if noad then process(noad,what,n,start) end -- list (not getlist !)
elseif id == math_fraction then
local noad = getfield(start,"num") if noad then process(noad,what,n,start) end -- list
@@ -298,7 +307,7 @@ local function processnested(current,what,n)
noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list
noad = getsup (current) if noad then process(noad,what,n,current) end -- list
noad = getsub (current) if noad then process(noad,what,n,current) end -- list
- elseif id == math_box or id == math_sub then
+ elseif id == math_subbox or id == math_submlist then
noad = getlist(current) if noad then process(noad,what,n,current) end -- list (not getlist !)
elseif id == math_fraction then
noad = getfield(current,"num") if noad then process(noad,what,n,current) end -- list
@@ -334,7 +343,7 @@ local function processstep(current,process,n,id)
noad = getnucleus(current) if noad then process(noad,n,current) end -- list
noad = getsup (current) if noad then process(noad,n,current) end -- list
noad = getsub (current) if noad then process(noad,n,current) end -- list
- elseif id == math_box or id == math_sub then
+ elseif id == math_subbox or id == math_submlist then
noad = getlist(current) if noad then process(noad,n,current) end -- list (not getlist !)
elseif id == math_fraction then
noad = getfield(current,"num") if noad then process(noad,n,current) end -- list
@@ -447,7 +456,7 @@ do
}
families[math_char] = function(pointer)
- if getfield(pointer,"fam") == 0 then
+ if getfam(pointer) == 0 then
local a = getattr(pointer,a_mathfamily)
if a and a > 0 then
setattr(pointer,a_mathfamily,0)
@@ -459,13 +468,13 @@ do
if trace_families then
report_families("no bold replacement for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa])
end
- setfield(pointer,"fam",newa)
+ setfam(pointer,newa)
elseif not fontcharacters[font_of_family(newa)][bold] then
if trace_families then
report_families("no bold character for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa])
end
if newa > 3 then
- setfield(pointer,"fam",newa-3)
+ setfam(pointer,newa-3)
end
else
setattr(pointer,a_exportstatus,char)
@@ -473,7 +482,7 @@ do
if trace_families then
report_families("replacing %C by bold %C, family %s with remap %s becomes %s with remap %s",char,bold,a,familymap[a],newa,familymap[newa])
end
- setfield(pointer,"fam",newa)
+ setfam(pointer,newa)
end
else
local char = getchar(pointer)
@@ -485,7 +494,7 @@ do
if trace_families then
report_families("family of %C becomes %s with remap %s",char,a,familymap[a])
end
- setfield(pointer,"fam",a)
+ setfam(pointer,a)
end
end
end
@@ -522,6 +531,30 @@ do
end
end
+ -- will become:
+
+ -- families[math_delim] = function(pointer)
+ -- if getfam(pointer) == 0 then
+ -- local a = getattr(pointer,a_mathfamily)
+ -- if a and a > 0 then
+ -- setattr(pointer,a_mathfamily,0)
+ -- if a > 5 then
+ -- -- no bold delimiters in unicode
+ -- a = a - 3
+ -- end
+ -- local char = getchar(pointer)
+ -- local okay = fontcharacters[font_of_family(a)][char]
+ -- if okay then
+ -- setfam(pointer,a)
+ -- elseif a > 2 then
+ -- setfam(pointer,a-3)
+ -- end
+ -- else
+ -- setfam(pointer,0)
+ -- end
+ -- end
+ -- end
+
families[math_textchar] = families[math_char]
function handlers.families(head,style,penalties)
@@ -535,20 +568,20 @@ end
do
- local a_mathalphabet = privateattribute("mathalphabet")
- local a_mathgreek = privateattribute("mathgreek")
+ local a_mathalphabet = privateattribute("mathalphabet")
+ local a_mathgreek = privateattribute("mathgreek")
+
+ local relocate = { }
- processors.relocate = { }
+ local remapalphabets = mathematics.remapalphabets
+ local fallbackstyleattr = mathematics.fallbackstyleattr
+ local setnodecolor = colortracers.set
local function report_remap(tag,id,old,new,extra)
report_remapping("remapping %s in font (%s,%s) from %C to %C%s",
tag,id,fontdata[id].properties.fontname or "",old,new,extra)
end
- local remapalphabets = mathematics.remapalphabets
- local fallbackstyleattr = mathematics.fallbackstyleattr
- local setnodecolor = nodes.tracers.colors.set
-
local function checked(pointer)
local char = getchar(pointer)
local font = getfont(pointer)
@@ -570,7 +603,7 @@ do
end
end
- processors.relocate[math_char] = function(pointer)
+ relocate[math_char] = function(pointer)
local g = getattr(pointer,a_mathgreek) or 0
local a = getattr(pointer,a_mathalphabet) or 0
local char = getchar(pointer)
@@ -637,20 +670,20 @@ do
end
end
- processors.relocate[math_textchar] = function(pointer)
+ relocate[math_textchar] = function(pointer)
if trace_analyzing then
setnodecolor(pointer,"font:init")
end
end
- processors.relocate[math_delim] = function(pointer)
+ relocate[math_delim] = function(pointer)
if trace_analyzing then
setnodecolor(pointer,"font:fina")
end
end
function handlers.relocate(head,style,penalties)
- processnoads(head,processors.relocate,"relocate")
+ processnoads(head,relocate,"relocate")
return true
end
@@ -658,32 +691,36 @@ end
-- rendering (beware, not exported)
-processors.render = { }
-
-local rendersets = mathematics.renderings.numbers or { } -- store
+do
-processors.render[math_char] = function(pointer)
- local attr = getattr(pointer,a_mathrendering)
- if attr and attr > 0 then
- local char = getchar(pointer)
- local renderset = rendersets[attr]
- if renderset then
- local newchar = renderset[char]
- if newchar then
- local font = getfont(pointer)
- local characters = fontcharacters[font]
- if characters and characters[newchar] then
- setchar(pointer,newchar)
- setattr(pointer,a_exportstatus,char)
+ local render = { }
+
+ local rendersets = mathematics.renderings.numbers or { } -- store
+
+ render[math_char] = function(pointer)
+ local attr = getattr(pointer,a_mathrendering)
+ if attr and attr > 0 then
+ local char = getchar(pointer)
+ local renderset = rendersets[attr]
+ if renderset then
+ local newchar = renderset[char]
+ if newchar then
+ local font = getfont(pointer)
+ local characters = fontcharacters[font]
+ if characters and characters[newchar] then
+ setchar(pointer,newchar)
+ setattr(pointer,a_exportstatus,char)
+ end
end
end
end
end
-end
-function handlers.render(head,style,penalties)
- processnoads(head,processors.render,"render")
- return true
+ function handlers.render(head,style,penalties)
+ processnoads(head,render,"render")
+ return true
+ end
+
end
-- some resize options (this works ok because the content is
@@ -696,347 +733,405 @@ end
-- todo: just replace the character by an ord noad
-- and remove the right delimiter as well
-local a_mathsize = privateattribute("mathsize") -- this might move into other fence code
-local resize = { }
-processors.resize = resize
+do
+
+ local a_mathsize = privateattribute("mathsize") -- this might move into other fence code
+ local resize = { }
-resize[math_fence] = function(pointer)
- local subtype = getsubtype(pointer)
- if subtype == left_fence_code or subtype == right_fence_code then
- local a = getattr(pointer,a_mathsize)
- if a and a > 0 then
- local method, size = div(a,100), a % 100
- setattr(pointer,a_mathsize,0)
- local delimiter = getfield(pointer,"delim")
- local chr = getfield(delimiter,"small_char")
- if chr > 0 then
- local fam = getfield(delimiter,"small_fam")
- local id = font_of_family(fam)
- if id > 0 then
- setfield(delimiter,"small_char",mathematics.big(fontdata[id],chr,size,method))
+ resize[math_fence] = function(pointer)
+ local subtype = getsubtype(pointer)
+ if subtype == left_fence_code or subtype == right_fence_code then
+ local a = getattr(pointer,a_mathsize)
+ if a and a > 0 then
+ local method, size = div(a,100), a % 100
+ setattr(pointer,a_mathsize,0)
+ local delimiter = getfield(pointer,"delim")
+ local chr = getfield(delimiter,"small_char")
+ if chr > 0 then
+ local fam = getfield(delimiter,"small_fam")
+ local id = font_of_family(fam)
+ if id > 0 then
+ setfield(delimiter,"small_char",mathematics.big(fontdata[id],chr,size,method))
+ end
end
end
end
end
-end
-function handlers.resize(head,style,penalties)
- processnoads(head,resize,"resize")
- return true
+ -- will become:
+
+ -- resize[math_fence] = function(pointer)
+ -- local subtype = getsubtype(pointer)
+ -- if subtype == left_fence_code or subtype == right_fence_code then
+ -- local a = getattr(pointer,a_mathsize)
+ -- if a and a > 0 then
+ -- local method, size = div(a,100), a % 100
+ -- setattr(pointer,a_mathsize,0)
+ -- local delimiter = getfield(pointer,"delim")
+ -- local chr = getchar(delimiter)
+ -- if chr > 0 then
+ -- local fam = getfam(delimiter)
+ -- local id = font_of_family(fam)
+ -- if id > 0 then
+ -- setchar(delimiter,mathematics.big(fontdata[id],chr,size,method))
+ -- end
+ -- end
+ -- end
+ -- end
+ -- end
+
+ function handlers.resize(head,style,penalties)
+ processnoads(head,resize,"resize")
+ return true
+ end
+
end
-- still not perfect:
-local a_autofence = privateattribute("mathautofence")
-local autofences = { }
-processors.autofences = autofences
-local dummyfencechar = 0x2E
-
-local function makefence(what,char)
- local d = new_node(math_delim)
- local f = new_node(math_fence)
- if char then
- local sym = getnucleus(char)
- local chr = getchar(sym)
- local fam = getfield(sym,"fam")
- if chr == dummyfencechar then
- chr = 0
+do
+
+ local a_autofence = privateattribute("mathautofence")
+ local autofences = { }
+ local dummyfencechar = 0x2E
+
+ local function makefence(what,char)
+ local d = new_delimiter()
+ local f = new_fence()
+ if char then
+ local sym = getnucleus(char)
+ local chr = getchar(sym)
+ local fam = getfam(sym)
+ if chr == dummyfencechar then
+ chr = 0
+ end
+ setfield(d,"small_char",chr)
+ setfield(d,"small_fam",fam)
+ flush_node(sym)
end
- setfield(d,"small_char",chr)
- setfield(d,"small_fam", fam)
- flush_node(sym)
- end
- setsubtype(f,what)
- setfield(f,"delim",d)
- setfield(f,"class",-1) -- tex itself does this, so not fenceclasses[what]
- return f
-end
+ setsubtype(f,what)
+ setfield(f,"delim",d)
+ setfield(f,"class",-1) -- tex itself does this, so not fenceclasses[what]
+ return f
+ end
-local function makelist(noad,f_o,o_next,c_prev,f_c,middle)
- local list = new_node(math_sub)
- setlist(list,f_o)
- setsubtype(noad,noad_inner)
- setnucleus(noad,list)
- setlink(f_o,o_next)
- setlink(c_prev,f_c)
- if middle and next(middle) then
- local prev = f_o
- local current = o_next
- while current ~= f_c do
- local m = middle[current]
- if m then
- local next = getnext(current)
- local fence = makefence(middle_fence_code,current)
- setnucleus(current)
- flush_node(current)
- middle[current] = nil
- -- replace_node
- setlink(prev,fence,next)
- prev = fence
- current = next
- else
- prev = current
- current = getnext(current)
+ -- will become
+
+ -- local function makefence(what,char)
+ -- local d = new_delimiter()
+ -- local f = new_fence()
+ -- if char then
+ -- local sym = getnucleus(char)
+ -- local chr = getchar(sym)
+ -- local fam = getfam(sym)
+ -- if chr == dummyfencechar then
+ -- chr = 0
+ -- end
+ -- setchar(d,chr)
+ -- setfam(d,fam)
+ -- flush_node(sym)
+ -- end
+ -- setsubtype(f,what)
+ -- setfield(f,"delim",d)
+ -- setfield(f,"class",-1) -- tex itself does this, so not fenceclasses[what]
+ -- return f
+ -- end
+
+ local function makelist(noad,f_o,o_next,c_prev,f_c,middle)
+ local list = new_submlist()
+ setlist(list,f_o)
+ setsubtype(noad,noad_inner)
+ setnucleus(noad,list)
+ setlink(f_o,o_next)
+ setlink(c_prev,f_c)
+ if middle and next(middle) then
+ local prev = f_o
+ local current = o_next
+ while current ~= f_c do
+ local m = middle[current]
+ if m then
+ local next = getnext(current)
+ local fence = makefence(middle_fence_code,current)
+ setnucleus(current)
+ flush_node(current)
+ middle[current] = nil
+ -- replace_node
+ setlink(prev,fence,next)
+ prev = fence
+ current = next
+ else
+ prev = current
+ current = getnext(current)
+ end
end
end
end
-end
-local function convert_both(open,close,middle)
- local o_prev, o_next = getboth(open)
- local c_prev, c_next = getboth(close)
- if o_next == close then
- return close
- else
+ local function convert_both(open,close,middle)
+ local o_prev, o_next = getboth(open)
+ local c_prev, c_next = getboth(close)
+ if o_next == close then
+ return close
+ else
+ local f_o = makefence(left_fence_code,open)
+ local f_c = makefence(right_fence_code,close)
+ makelist(open,f_o,o_next,c_prev,f_c,middle)
+ setnucleus(close)
+ flush_node(close)
+ if c_next then
+ setprev(c_next,open)
+ end
+ setnext(open,c_next)
+ return open
+ end
+ end
+
+ local function convert_open(open,last,middle)
local f_o = makefence(left_fence_code,open)
- local f_c = makefence(right_fence_code,close)
- makelist(open,f_o,o_next,c_prev,f_c,middle)
- setnucleus(close)
- flush_node(close)
- if c_next then
- setprev(c_next,open)
+ local f_c = makefence(right_fence_code)
+ local o_prev, o_next = getboth(open)
+ local l_prev, l_next = getboth(last)
+ makelist(open,f_o,o_next,last,f_c,middle)
+ if l_next then
+ setprev(l_next,open)
end
- setnext(open,c_next)
+ setnext(open,l_next)
return open
end
-end
-
-local function convert_open(open,last,middle)
- local f_o = makefence(left_fence_code,open)
- local f_c = makefence(right_fence_code)
- local o_prev, o_next = getboth(open)
- local l_prev, l_next = getboth(last)
- makelist(open,f_o,o_next,last,f_c,middle)
- if l_next then
- setprev(l_next,open)
- end
- setnext(open,l_next)
- return open
-end
-local function convert_close(close,first,middle)
- local f_o = makefence(left_fence_code)
- local f_c = makefence(right_fence_code,close)
- local c_prev = getprev(close)
- makelist(close,f_o,first,c_prev,f_c,middle)
- return close
-end
+ local function convert_close(close,first,middle)
+ local f_o = makefence(left_fence_code)
+ local f_c = makefence(right_fence_code,close)
+ local c_prev = getprev(close)
+ makelist(close,f_o,first,c_prev,f_c,middle)
+ return close
+ end
-local stacks = setmetatableindex("table")
-
-local function processfences(pointer,n,parent)
- local current = pointer
- local last = pointer
- local start = pointer
- local done = false
- local initial = pointer
- local stack = nil
- local middle = nil -- todo: use properties
- while current do
- local id = getid(current)
- if id == math_noad then
- local a = getattr(current,a_autofence)
- if a and a > 0 then
- local stack = stacks[n]
- setattr(current,a_autofence,0)
- if a == 1 or (a == 4 and (not stack or #stack == 0)) then
- if trace_fences then
- report_fences("%2i: pushing open on stack",n)
- end
- insert(stack,current)
- elseif a == 2 or a == 4 then
- local open = remove(stack)
- if open then
+ local stacks = setmetatableindex("table")
+
+ local function processfences(pointer,n,parent)
+ local current = pointer
+ local last = pointer
+ local start = pointer
+ local done = false
+ local initial = pointer
+ local stack = nil
+ local middle = nil -- todo: use properties
+ while current do
+ local id = getid(current)
+ if id == math_noad then
+ local a = getattr(current,a_autofence)
+ if a and a > 0 then
+ local stack = stacks[n]
+ setattr(current,a_autofence,0)
+ if a == 1 or (a == 4 and (not stack or #stack == 0)) then
if trace_fences then
- report_fences("%2i: handling %s, stack depth %i",n,"both",#stack+1)
+ report_fences("%2i: pushing open on stack",n)
+ end
+ insert(stack,current)
+ elseif a == 2 or a == 4 then
+ local open = remove(stack)
+ if open then
+ if trace_fences then
+ report_fences("%2i: handling %s, stack depth %i",n,"both",#stack+1)
+ end
+ current = convert_both(open,current,middle)
+ elseif current == start then
+ -- skip
+ else
+ if trace_fences then
+ report_fences("%2i: handling %s, stack depth %i",n,"close",#stack+1)
+ end
+ current = convert_close(current,initial,middle)
+ if not parent then
+ initial = current
+ end
end
- current = convert_both(open,current,middle)
- elseif current == start then
- -- skip
- else
if trace_fences then
- report_fences("%2i: handling %s, stack depth %i",n,"close",#stack+1)
+ report_fences("%2i: popping close from stack",n)
end
- current = convert_close(current,initial,middle)
- if not parent then
- initial = current
+ elseif a == 3 then
+ if trace_fences then
+ report_fences("%2i: registering middle",n)
+ end
+ if middle then
+ middle[current] = last
+ else
+ middle = { [current] = last }
end
end
- if trace_fences then
- report_fences("%2i: popping close from stack",n)
- end
- elseif a == 3 then
- if trace_fences then
- report_fences("%2i: registering middle",n)
- end
- if middle then
- middle[current] = last
- else
- middle = { [current] = last }
- end
+ done = true
+ else
+ processstep(current,processfences,n+1,id)
end
- done = true
else
- processstep(current,processfences,n+1,id)
+ -- next at current level
+ processstep(current,processfences,n,id)
end
- else
- -- next at current level
- processstep(current,processfences,n,id)
+ last = current
+ current = getnext(current)
end
- last = current
- current = getnext(current)
- end
- if done then
- local stack = stacks[n]
- local s = #stack
- if s > 0 then
- if trace_fences then
- report_fences("%2i: handling %s stack levels",n,s)
- end
- for i=1,s do
- local open = remove(stack)
+ if done then
+ local stack = stacks[n]
+ local s = #stack
+ if s > 0 then
if trace_fences then
- report_fences("%2i: handling %s, stack depth %i",n,"open",#stack)
+ report_fences("%2i: handling %s stack levels",n,s)
+ end
+ for i=1,s do
+ local open = remove(stack)
+ if trace_fences then
+ report_fences("%2i: handling %s, stack depth %i",n,"open",#stack)
+ end
+ last = convert_open(open,last,middle)
end
- last = convert_open(open,last,middle)
end
end
end
-end
--- we can have a first changed node .. an option is to have a leading dummy node in math
--- lists like the par node as it can save a lot of mess
+ -- we can have a first changed node .. an option is to have a leading dummy node in math
+ -- lists like the par node as it can save a lot of mess
-local enabled = false
+ local enabled = false
-implement {
- name = "enableautofences",
- onlyonce = true,
- actions = function()
- enableaction("math","noads.handlers.autofences")
- enabled = true
- end
-}
+ implement {
+ name = "enableautofences",
+ onlyonce = true,
+ actions = function()
+ enableaction("math","noads.handlers.autofences")
+ enabled = true
+ end
+ }
-function handlers.autofences(head,style,penalties)
- if enabled then -- tex.modes.c_math_fences_auto
- -- inspect(nodes.totree(head))
- processfences(tonut(head),1)
- -- inspect(nodes.totree(head))
+ function handlers.autofences(head,style,penalties)
+ if enabled then -- tex.modes.c_math_fences_auto
+ -- inspect(nodes.totree(head))
+ processfences(tonut(head),1)
+ -- inspect(nodes.totree(head))
+ end
end
+
end
-- normalize scripts
-local unscript = { } noads.processors.unscript = unscript
-local superscripts = characters.superscripts
-local subscripts = characters.subscripts
-local fractions = characters.fractions
-local replaced = { }
-
-local function replace(pointer,what,n,parent)
- pointer = parent -- we're following the parent list (chars trigger this)
- local next = getnext(pointer)
- local start_super, stop_super, start_sub, stop_sub
- local mode = "unset"
- while next and getid(next) == math_noad do
- local nextnucleus = getnucleus(next)
- if nextnucleus and getid(nextnucleus) == math_char and not getsub(next) and not getsup(next) then
- local char = getchar(nextnucleus)
- local s = superscripts[char]
- if s then
- if not start_super then
- start_super = next
- mode = "super"
- elseif mode == "sub" then
- break
- end
- stop_super = next
- next = getnext(next)
- setchar(nextnucleus,s)
- replaced[char] = (replaced[char] or 0) + 1
- if trace_normalizing then
- report_normalizing("superscript %C becomes %C",char,s)
- end
- else
- local s = subscripts[char]
+do
+
+ local unscript = { } noads.processors.unscript = unscript
+ local superscripts = characters.superscripts
+ local subscripts = characters.subscripts
+ local fractions = characters.fractions
+ local replaced = { }
+
+ local function replace(pointer,what,n,parent)
+ pointer = parent -- we're following the parent list (chars trigger this)
+ local next = getnext(pointer)
+ local start_super, stop_super, start_sub, stop_sub
+ local mode = "unset"
+ while next and getid(next) == math_noad do
+ local nextnucleus = getnucleus(next)
+ if nextnucleus and getid(nextnucleus) == math_char and not getsub(next) and not getsup(next) then
+ local char = getchar(nextnucleus)
+ local s = superscripts[char]
if s then
- if not start_sub then
- start_sub = next
- mode = "sub"
- elseif mode == "super" then
+ if not start_super then
+ start_super = next
+ mode = "super"
+ elseif mode == "sub" then
break
end
- stop_sub = next
+ stop_super = next
next = getnext(next)
setchar(nextnucleus,s)
replaced[char] = (replaced[char] or 0) + 1
if trace_normalizing then
- report_normalizing("subscript %C becomes %C",char,s)
+ report_normalizing("superscript %C becomes %C",char,s)
end
else
- break
+ local s = subscripts[char]
+ if s then
+ if not start_sub then
+ start_sub = next
+ mode = "sub"
+ elseif mode == "super" then
+ break
+ end
+ stop_sub = next
+ next = getnext(next)
+ setchar(nextnucleus,s)
+ replaced[char] = (replaced[char] or 0) + 1
+ if trace_normalizing then
+ report_normalizing("subscript %C becomes %C",char,s)
+ end
+ else
+ break
+ end
end
+ else
+ break
end
- else
- break
- end
- end
- if start_super then
- if start_super == stop_super then
- setsup(pointer,getnucleus(start_super))
- else
- local list = new_node(math_sub) -- todo attr
- setlist(list,start_super)
- setsup(pointer,list)
- end
- if mode == "super" then
- setnext(pointer,getnext(stop_super))
end
- setnext(stop_super)
- end
- if start_sub then
- if start_sub == stop_sub then
- setsub(pointer,getnucleus(start_sub))
- else
- local list = new_node(math_sub) -- todo attr
- setlist(list,start_sub)
- setsub(pointer,list)
+ if start_super then
+ if start_super == stop_super then
+ setsup(pointer,getnucleus(start_super))
+ else
+ local list = new_submlist() -- todo attr
+ setlist(list,start_super)
+ setsup(pointer,list)
+ end
+ if mode == "super" then
+ setnext(pointer,getnext(stop_super))
+ end
+ setnext(stop_super)
end
- if mode == "sub" then
- setnext(pointer,getnext(stop_sub))
+ if start_sub then
+ if start_sub == stop_sub then
+ setsub(pointer,getnucleus(start_sub))
+ else
+ local list = new_submlist() -- todo attr
+ setlist(list,start_sub)
+ setsub(pointer,list)
+ end
+ if mode == "sub" then
+ setnext(pointer,getnext(stop_sub))
+ end
+ setnext(stop_sub)
end
- setnext(stop_sub)
+ -- we could return stop
end
- -- we could return stop
-end
-unscript[math_char] = replace -- not noads as we need to recurse
+ unscript[math_char] = replace -- not noads as we need to recurse
+
+ function handlers.unscript(head,style,penalties)
+ processnoads(head,unscript,"unscript")
+ -- processnoads(head,checkers,"checkers")
+ return true
+ end
-function handlers.unscript(head,style,penalties)
- processnoads(head,unscript,"unscript")
--- processnoads(head,checkers,"checkers")
- return true
end
-local function collected(list)
- if list and next(list) then
- local n, t = 0, { }
- for k, v in sortedhash(list) do
- n = n + v
- t[#t+1] = formatters["%C"](k)
+do
+
+ local function collected(list)
+ if list and next(list) then
+ local n, t = 0, { }
+ for k, v in sortedhash(list) do
+ n = n + 1
+ t[n] = formatters["%C"](k)
+ end
+ return formatters["% t (n=%s)"](t,n)
end
- return formatters["% t (n=%s)"](t,n)
end
-end
-statistics.register("math script replacements", function()
- return collected(replaced)
-end)
+ statistics.register("math script replacements", function()
+ return collected(replaced)
+ end)
-statistics.register("unknown math characters", function()
- return collected(unknowns)
-end)
+ statistics.register("unknown math characters", function()
+ return collected(unknowns)
+ end)
+
+end
-- math alternates: (in xits lgf: $ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$)
-- math alternates: (in lucidaot lgf: $ABC \mathalternate{italic} ABC$)
@@ -1050,7 +1145,7 @@ do
local last = 0
local known = setmetatableindex(function(t,k)
- local v = setbit(0,2^last)
+ local v = bor(0,2^last)
t[k] = v
last = last + 1
return v
@@ -1080,7 +1175,8 @@ do
alternates = alternates,
registered = registered,
presets = { },
-hashes = setmetatableindex("table")
+ resets = { },
+ hashes = setmetatableindex("table")
}
resources.mathalternates = mathalternates
end
@@ -1144,7 +1240,7 @@ hashes = setmetatableindex("table")
local fontdata = fonts.hashes.identifiers
local fontresources = fonts.hashes.resources
- local function getalternate(fam,tag)
+ local function getalternate(fam,tag,current)
local resources = fontresources[font_of_family(fam)]
local attribute = unsetvalue
if resources then
@@ -1152,25 +1248,37 @@ hashes = setmetatableindex("table")
if mathalternates then
local presets = mathalternates.presets
if presets then
+ local resets = mathalternates.resets
attribute = presets[tag]
if not attribute then
attribute = 0
local alternates = mathalternates.alternates
for s in gmatch(tag,"[^, ]+") do
- local a = alternates[s] -- or known[s]
- if a then
- attribute = attribute + a
+ if s == v_reset then
+ resets[tag] = true
+ current = unsetvalue
+ else
+ local a = alternates[s] -- or known[s]
+ if a then
+ attribute = bor(attribute,a)
+ end
end
end
if attribute == 0 then
attribute = unsetvalue
end
presets[tag] = attribute
+ elseif resets[tag] then
+ current = unsetvalue
end
end
end
end
- return attribute
+ if attribute > 0 and current and current > 0 then
+ return bor(current,attribute)
+ else
+ return attribute
+ end
end
local function presetalternate(fam,tag)
@@ -1185,10 +1293,7 @@ hashes = setmetatableindex("table")
local function setalternate(fam,tag)
local a = texgetattribute(a_mathalternate)
- local v = getalternate(fam,tag)
- if a and a > 0 then
- v = a + v
- end
+ local v = getalternate(fam,tag,a)
texsetattribute(a_mathalternate,v)
end
@@ -1212,7 +1317,7 @@ hashes = setmetatableindex("table")
local hashes = mathalternates.hashes
for i=1,#registered do
local r = registered[i]
- if hasbit(a,r) then
+ if band(a,r) ~= 0 then
local char = getchar(pointer)
local alt = hashes[i][char]
if alt == nil then
@@ -1259,66 +1364,59 @@ end
-- some juggling that we want to avoid but we need to do something here (in fact, we could
-- better fix the width of the character
-local a_mathitalics = privateattribute("mathitalics")
+do
+
+ local a_mathitalics = privateattribute("mathitalics")
-local italics = { }
-local default_factor = 1/20
+ local italics = { }
+ local default_factor = 1/20
-local setcolor = nodes.tracers.colors.set
-local resetcolor = nodes.tracers.colors.reset
-local italic_kern = new_kern
-local c_positive_d = "trace:dg"
-local c_negative_d = "trace:dr"
+ local setcolor = colortracers.set
+ local resetcolor = colortracers.reset
+ local italic_kern = new_kern
-local function insert_kern(current,kern)
- local sub = new_node(math_sub) -- todo: pool
- local noad = new_node(math_noad) -- todo: pool
- setlist(sub,kern)
- setnext(kern,noad)
- setnucleus(noad,current)
- return sub
-end
+ local c_positive_d = "trace:dg"
+ local c_negative_d = "trace:dr"
-registertracker("math.italics.visualize", function(v)
- if v then
- italic_kern = function(k)
- local n = new_kern(k)
- set_visual(n,"italic")
- return n
- end
- else
- italic_kern = new_kern
+ local function insert_kern(current,kern)
+ local sub = new_submlist()
+ local noad = new_noad()
+ setlist(sub,kern)
+ setnext(kern,noad)
+ setnucleus(noad,current)
+ return sub
end
-end)
-local function getcorrection(method,font,char) -- -- or character.italic -- (this one is for tex)
+ registertracker("math.italics.visualize", function(v)
+ if v then
+ italic_kern = function(k)
+ local n = new_kern(k)
+ set_visual(n,"italic")
+ return n
+ end
+ else
+ italic_kern = new_kern
+ end
+ end)
- local visual = chardata[char].visual
+ local function getcorrection(method,font,char) -- -- or character.italic -- (this one is for tex)
- if method == 1 then
- -- check on state
- local italics = fontitalics[font]
- if italics then
- local character = fontcharacters[font][char]
- if character then
- local correction = character.italic
- if correction and correction ~= 0 then
- return correction, visual
+ local visual = chardata[char].visual
+
+ if method == 1 then
+ -- check on state
+ local italics = fontitalics[font]
+ if italics then
+ local character = fontcharacters[font][char]
+ if character then
+ local correction = character.italic
+ if correction and correction ~= 0 then
+ return correction, visual
+ end
end
end
- end
- elseif method == 2 then
- -- no check
- local character = fontcharacters[font][char]
- if character then
- local correction = character.italic
- if correction and correction ~= 0 then
- return correction, visual
- end
- end
- elseif method == 3 then
- -- check on visual
- if visual == "it" or visual == "bi" then
+ elseif method == 2 then
+ -- no check
local character = fontcharacters[font][char]
if character then
local correction = character.italic
@@ -1326,109 +1424,121 @@ local function getcorrection(method,font,char) -- -- or character.italic -- (thi
return correction, visual
end
end
- end
- elseif method == 4 then
- -- combination of 1 and 3
- local italics = fontitalics[font]
- if italics and (visual == "it" or visual == "bi") then
- local character = fontcharacters[font][char]
- if character then
- local correction = character.italic
- if correction and correction ~= 0 then
- return correction, visual
+ elseif method == 3 then
+ -- check on visual
+ if visual == "it" or visual == "bi" then
+ local character = fontcharacters[font][char]
+ if character then
+ local correction = character.italic
+ if correction and correction ~= 0 then
+ return correction, visual
+ end
+ end
+ end
+ elseif method == 4 then
+ -- combination of 1 and 3
+ local italics = fontitalics[font]
+ if italics and (visual == "it" or visual == "bi") then
+ local character = fontcharacters[font][char]
+ if character then
+ local correction = character.italic
+ if correction and correction ~= 0 then
+ return correction, visual
+ end
end
end
end
- end
-end
+ end
-italics[math_char] = function(pointer,what,n,parent)
- local method = getattr(pointer,a_mathitalics)
- if method and method > 0 and method < 100 then
- local char = getchar(pointer)
- local font = getfont(pointer)
- local correction, visual = getcorrection(method,font,char)
- if correction and correction ~= 0 then
- local next_noad = getnext(parent)
- if not next_noad then
- if n == 1 then
- -- only at the outer level .. will become an option (always,endonly,none)
- if trace_italics then
- report_italics("method %a, flagging italic correction %p between %C and end math",method,correction,char)
- end
- if correction > 0 then
- correction = correction + 100
- else
- correction = correction - 100
+ italics[math_char] = function(pointer,what,n,parent)
+ local method = getattr(pointer,a_mathitalics)
+ if method and method > 0 and method < 100 then
+ local char = getchar(pointer)
+ local font = getfont(pointer)
+ local correction, visual = getcorrection(method,font,char)
+ if correction and correction ~= 0 then
+ local next_noad = getnext(parent)
+ if not next_noad then
+ if n == 1 then
+ -- only at the outer level .. will become an option (always,endonly,none)
+ if trace_italics then
+ report_italics("method %a, flagging italic correction %p between %C and end math",method,correction,char)
+ end
+ if correction > 0 then
+ correction = correction + 100
+ else
+ correction = correction - 100
+ end
+ setattr(pointer,a_mathitalics,correction)
+ setattr(parent,a_mathitalics,correction)
+ return -- so no reset later on
end
- setattr(pointer,a_mathitalics,correction)
- setattr(parent,a_mathitalics,correction)
end
end
end
+ setattr(pointer,a_mathitalics,unsetvalue)
end
-end
-
-function handlers.italics(head,style,penalties)
- processnoads(head,italics,"italics")
- return true
-end
-local enable
+ function handlers.italics(head,style,penalties)
+ processnoads(head,italics,"italics")
+ return true
+ end
-enable = function()
- enableaction("math", "noads.handlers.italics")
- if trace_italics then
- report_italics("enabling math italics")
+ local enable = function()
+ enableaction("math", "noads.handlers.italics")
+ if trace_italics then
+ report_italics("enabling math italics")
+ end
+ -- we enable math (unless already enabled elsewhere)
+ typesetters.italics.enablemath()
+ enable = false
end
- -- we enable math (unless already enabled elsewhere)
- typesetters.italics.enablemath()
- enable = false
-end
--- best do this only on math mode (less overhead)
+ -- best do this only on math mode (less overhead)
-function mathematics.setitalics(name)
- if enable then
- enable()
+ function mathematics.setitalics(name)
+ if enable then
+ enable()
+ end
+ texsetattribute(a_mathitalics,name and name ~= v_reset and tonumber(name) or unsetvalue) -- maybe also v_none
end
- texsetattribute(a_mathitalics,name and name ~= v_reset and tonumber(name) or unsetvalue) -- maybe also v_none
-end
-function mathematics.getitalics(name)
- if enable then
- enable()
+ function mathematics.getitalics(name)
+ if enable then
+ enable()
+ end
+ context(name and name ~= v_reset and tonumber(name) or unsetvalue)
end
- context(name and name ~= v_reset and tonumber(name) or unsetvalue)
-end
-function mathematics.resetitalics()
- texsetattribute(a_mathitalics,unsetvalue)
-end
+ function mathematics.resetitalics()
+ texsetattribute(a_mathitalics,unsetvalue)
+ end
-implement {
- name = "initializemathitalics",
- actions = enable,
- onlyonce = true,
-}
+ implement {
+ name = "initializemathitalics",
+ actions = enable,
+ onlyonce = true,
+ }
-implement {
- name = "setmathitalics",
- actions = mathematics.setitalics,
- arguments = "string",
-}
+ implement {
+ name = "setmathitalics",
+ actions = mathematics.setitalics,
+ arguments = "string",
+ }
-implement {
- name = "getmathitalics",
- actions = mathematics.getitalics,
- arguments = "string",
-}
+ implement {
+ name = "getmathitalics",
+ actions = mathematics.getitalics,
+ arguments = "string",
+ }
-implement {
- name = "resetmathitalics",
- actions = mathematics.resetitalics
-}
+ implement {
+ name = "resetmathitalics",
+ actions = mathematics.resetitalics
+ }
+
+end
do
@@ -1461,12 +1571,14 @@ do
local hash = setmetatableindex(function(t,font)
local g = fontdata[font].goodies
- local m = g and g[1].mathematics
+ local m = g and g[1] and g[1].mathematics
local k = m and m.kernpairs
t[font] = k
return k
end)
+ -- no correction after prime because that moved to a superscript
+
kernpairs[math_char] = function(pointer,what,n,parent)
if getattr(pointer,a_kernpairs) == 1 then
local font = getfont(pointer)
@@ -1506,243 +1618,372 @@ end
-- primes and such
-local collapse = { } processors.collapse = collapse
+do
+
+ -- is validpair stil needed?
+
+ local a_mathcollapsing = privateattribute("mathcollapsing")
+ local collapse = { }
+ local mathlists = characters.mathlists
+ local validpair = {
+ [noad_ord] = true,
+ [noad_rel] = true,
+ [noad_bin] = true, -- new
+ [noad_open] = true, -- new
+ [noad_close] = true, -- new
+ [noad_punct] = true, -- new
+ [noad_opdisplaylimits] = true,
+ [noad_oplimits] = true,
+ [noad_opnolimits] = true,
+ }
-local mathpairs = characters.mathpairs -- next will move to char-def
+ local reported = setmetatableindex("table")
+
+ collapse[math_char] = function(pointer,what,n,parent)
+
+ if parent and mathlists[getchar(pointer)] then
+ local found, last, lucleus, lsup, lsub, category
+ local tree = mathlists
+ local current = parent
+ while current and validpair[getsubtype(current)] do
+ local nucleus = getnucleus(current) -- == pointer
+ local sub = getsub(current)
+ local sup = getsup(current)
+ local char = getchar(nucleus)
+ if char then
+ local match = tree[char]
+ if match then
+ local method = getattr(current,a_mathcollapsing)
+ if method and method > 0 and method <= 3 then
+ local specials = match.specials
+ local mathlist = match.mathlist
+ local ligature
+ if method == 1 then
+ ligature = specials
+ elseif method == 2 then
+ ligature = specials or mathlist
+ else -- 3
+ ligature = mathlist or specials
+ end
+ if ligature then
+ category = mathlist and "mathlist" or "specials"
+ found = ligature
+ last = current
+ lucleus = nucleus
+ lsup = sup
+ lsub = sub
+ end
+ tree = match
+ if sub or sup then
+ break
+ else
+ current = getnext(current)
+ end
+ else
+ break
+ end
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ if found and last and lucleus then
+ local id = getfont(lucleus)
+ local characters = fontcharacters[id]
+ local replace = characters and characters[found]
+ if not replace then
+ if not reported[id][found] then
+ reported[id][found] = true
+ report_collapsing("%s ligature %C from %s","ignoring",found,category)
+ end
+ elseif trace_collapsing then
+ report_collapsing("%s ligature %C from %s","creating",found,category)
+ end
+ setchar(pointer,found)
+ local l = getnext(last)
+ local c = getnext(parent)
+ if lsub then
+ setsub(parent,lsub)
+ setsub(last)
+ end
+ if lsup then
+ setsup(parent,lsup)
+ setsup(last)
+ end
+ while c ~= l do
+ local n = getnext(c)
+ flush_node(c)
+ c = n
+ end
+ setlink(parent,l)
+ end
+ end
+ end
+
+ function noads.handlers.collapse(head,style,penalties)
+ processnoads(head,collapse,"collapse")
+ return true
+ end
-mathpairs[0x2032] = { [0x2032] = 0x2033, [0x2033] = 0x2034, [0x2034] = 0x2057 } -- (prime,prime) (prime,doubleprime) (prime,tripleprime)
-mathpairs[0x2033] = { [0x2032] = 0x2034, [0x2033] = 0x2057 } -- (doubleprime,prime) (doubleprime,doubleprime)
-mathpairs[0x2034] = { [0x2032] = 0x2057 } -- (tripleprime,prime)
+ local enable = function()
+ enableaction("math", "noads.handlers.collapse")
+ if trace_collapsing then
+ report_collapsing("enabling math collapsing")
+ end
+ enable = false
+ end
-mathpairs[0x2035] = { [0x2035] = 0x2036, [0x2036] = 0x2037 } -- (reversedprime,reversedprime) (reversedprime,doublereversedprime)
-mathpairs[0x2036] = { [0x2035] = 0x2037 } -- (doublereversedprime,reversedprime)
+ implement {
+ name = "initializemathcollapsing",
+ actions = enable,
+ onlyonce = true,
+ }
-mathpairs[0x222B] = { [0x222B] = 0x222C, [0x222C] = 0x222D }
-mathpairs[0x222C] = { [0x222B] = 0x222D }
+end
-mathpairs[0x007C] = { [0x007C] = 0x2016, [0x2016] = 0x2980 } -- bar+bar=double bar+double=triple
-mathpairs[0x2016] = { [0x007C] = 0x2980 } -- double+bar=triple
+do
+ -- inner under over vcenter
+
+ local fixscripts = { }
+ local movesub = {
+ -- primes
+ [0x2032] = 0xFE932,
+ [0x2033] = 0xFE933,
+ [0x2034] = 0xFE934,
+ [0x2057] = 0xFE957,
+ -- reverse primes
+ [0x2035] = 0xFE935,
+ [0x2036] = 0xFE936,
+ [0x2037] = 0xFE937,
+ }
-local movesub = {
- -- primes
- [0x2032] = 0xFE932,
- [0x2033] = 0xFE933,
- [0x2034] = 0xFE934,
- [0x2057] = 0xFE957,
- -- reverse primes
- [0x2035] = 0xFE935,
- [0x2036] = 0xFE936,
- [0x2037] = 0xFE937,
-}
+ mathematics.virtualize(movesub)
-local validpair = {
- [noad_rel] = true,
- [noad_ord] = true,
- [noad_bin] = true, -- new
- [noad_punct] = true, -- new
- [noad_opdisplaylimits] = true,
- [noad_oplimits] = true,
- [noad_opnolimits] = true,
-}
+ local options_supported = tokens.defined("Unosuperscript")
-local function movesubscript(parent,current_nucleus,current_char)
- local prev = getprev(parent)
- if prev and getid(prev) == math_noad then
- if not getsup(prev) and not getsub(prev) then
- -- {f} {'}_n => f_n^'
- setchar(current_nucleus,movesub[current_char or getchar(current_nucleus)])
- local nucleus = getnucleus(parent)
- local sub = getsub(parent)
- local sup = getsup(parent)
- setsup(prev,nucleus)
- setsub(prev,sub)
- local dummy = copy_node(nucleus)
- setchar(dummy,0)
- setnucleus(parent,dummy)
- setsub(parent)
- if trace_collapsing then
- report_collapsing("fixing subscript")
+ local function fixsupscript(parent,current,current_char,new_char)
+ if new_char ~= current_char and new_char ~= true then
+ setchar(current,new_char)
+ if trace_fixing then
+ report_fixing("fixing subscript, replacing superscript %U by %U",current_char,new_char)
end
- elseif not getsup(prev) then
- -- {f} {'}_n => f_n^'
- setchar(current_nucleus,movesub[current_char or getchar(current_nucleus)])
- local nucleus = getnucleus(parent)
- local sup = getsup(parent)
- setsup(prev,nucleus)
- local dummy = copy_node(nucleus)
- setchar(dummy,0)
- setnucleus(parent,dummy)
- if trace_collapsing then
- report_collapsing("fixing subscript")
+ else
+ if trace_fixing then
+ report_fixing("fixing subscript, superscript %U",current_char)
end
end
+ if options_supported then
+ setfield(parent,"options",0x08+0x22)
+ end
end
-end
-local function collapsepair(pointer,what,n,parent,nested) -- todo: switch to turn in on and off
- if parent then
- if validpair[getsubtype(parent)] then
- local current_nucleus = getnucleus(parent)
- if getid(current_nucleus) == math_char then
- local current_char = getchar(current_nucleus)
- if not getsub(parent) and not getsup(parent) then
- local mathpair = mathpairs[current_char]
- if mathpair then
- local next_noad = getnext(parent)
- if next_noad and getid(next_noad) == math_noad then
- if validpair[getsubtype(next_noad)] then
- local next_nucleus = getnucleus(next_noad)
- local next_char = getchar(next_nucleus)
- if getid(next_nucleus) == math_char then
- local newchar = mathpair[next_char]
- if newchar then
- local id = getfont(current_nucleus)
- local characters = fontcharacters[id]
- if characters and characters[newchar] then
- if trace_collapsing then
- report_collapsing("%U + %U => %U",current_char,next_char,newchar)
- end
- setchar(current_nucleus,newchar)
- local next_next_noad = getnext(next_noad)
- if next_next_noad then
- setlink(parent,next_next_noad)
- else
- setnext(parent)
- end
- setsup(parent,getsup(next_noad))
- setsub(parent,getsub(next_noad))
- setsup(next_noad)
- setsub(next_noad)
- flush_node(next_noad)
- collapsepair(pointer,what,n,parent,true)
- -- if not nested and movesub[current_char] then
- -- movesubscript(parent,current_nucleus,current_char)
- -- end
- end
- elseif not nested and movesub[current_char] then
- movesubscript(parent,current_nucleus,current_char)
- end
+ -- local function movesubscript(parent,current_nucleus,oldchar,newchar)
+ -- local prev = getprev(parent)
+ -- if prev and getid(prev) == math_noad then
+ -- local psup = getsup(prev)
+ -- local psub = getsub(prev)
+ -- if not psup and not psub then
+ -- fixsupscript(prev,current_nucleus,oldchar,newchar)
+ -- local nucleus = getnucleus(parent)
+ -- local sub = getsub(parent)
+ -- setsup(prev,nucleus)
+ -- setsub(prev,sub)
+ -- local dummy = copy_node(nucleus)
+ -- setchar(dummy,0)
+ -- setnucleus(parent,dummy)
+ -- setsub(parent)
+ -- elseif not psup then
+ -- fixsupscript(prev,current_nucleus,oldchar,newchar)
+ -- local nucleus = getnucleus(parent)
+ -- setsup(prev,nucleus)
+ -- local dummy = copy_node(nucleus)
+ -- setchar(dummy,0)
+ -- setnucleus(parent,dummy)
+ -- end
+ -- end
+ -- end
+
+ local function move_none_none(parent,prev,nuc,oldchar,newchar)
+ fixsupscript(prev,nuc,oldchar,newchar)
+ local sub = getsub(parent)
+ setsup(prev,nuc)
+ setsub(prev,sub)
+ local dummy = copy_node(nuc)
+ setchar(dummy,0)
+ setnucleus(parent,dummy)
+ setsub(parent)
+ end
+
+ local function move_none_psub(parent,prev,nuc,oldchar,newchar)
+ fixsupscript(prev,nuc,oldchar,newchar)
+ setsup(prev,nuc)
+ local dummy = copy_node(nuc)
+ setchar(dummy,0)
+ setnucleus(parent,dummy)
+ end
+
+ fixscripts[math_char] = function(pointer,what,n,parent,nested) -- todo: switch to turn in on and off
+ if parent then
+ local oldchar = getchar(pointer)
+ local newchar = movesub[oldchar]
+ if newchar then
+ local nuc = getnucleus(parent)
+ if pointer == nuc then
+ local sub = getsub(pointer)
+ local sup = getsup(pointer)
+ if sub then
+ if sup then
+ -- print("[char] sub sup")
+ else
+ -- print("[char] sub ---")
+ end
+ elseif sup then
+ -- print("[char] --- sup")
+ else
+ local prev = getprev(parent)
+ if prev and getid(prev) == math_noad then
+ local psub = getsub(prev)
+ local psup = getsup(prev)
+ if psub then
+ if psup then
+ -- print("sub sup [char] --- ---")
+ else
+ -- print("sub --- [char] --- ---")
+ move_none_psub(parent,prev,nuc,oldchar,newchar)
end
+ elseif psup then
+ -- print("--- sup [char] --- ---")
+ else
+ -- print("[char] --- ---")
+ move_none_none(parent,prev,nuc,oldchar,newchar)
end
- elseif not nested and movesub[current_char] then
- movesubscript(parent,current_nucleus,current_char)
+ else
+ -- print("no prev [char]")
end
- elseif not nested and movesub[current_char] then
- movesubscript(parent,current_nucleus,current_char)
end
- elseif not nested and movesub[current_char] then
- movesubscript(parent,current_nucleus,current_char)
+ else
+ -- print("[char]")
end
end
end
end
-end
-collapse[math_char] = collapsepair
+ function noads.handlers.fixscripts(head,style,penalties)
+ processnoads(head,fixscripts,"fixscripts")
+ return true
+ end
-function noads.handlers.collapse(head,style,penalties)
- processnoads(head,collapse,"collapse")
- return true
end
-- variants
-local variants = { }
-
-local validvariants = { -- fast check on valid
- [0x2229] = 0xFE00, [0x222A] = 0xFE00,
- [0x2268] = 0xFE00, [0x2269] = 0xFE00,
- [0x2272] = 0xFE00, [0x2273] = 0xFE00,
- [0x228A] = 0xFE00, [0x228B] = 0xFE00,
- [0x2293] = 0xFE00, [0x2294] = 0xFE00,
- [0x2295] = 0xFE00,
- [0x2297] = 0xFE00,
- [0x229C] = 0xFE00,
- [0x22DA] = 0xFE00, [0x22DB] = 0xFE00,
- [0x2A3C] = 0xFE00, [0x2A3D] = 0xFE00,
- [0x2A9D] = 0xFE00, [0x2A9E] = 0xFE00,
- [0x2AAC] = 0xFE00, [0x2AAD] = 0xFE00,
- [0x2ACB] = 0xFE00, [0x2ACC] = 0xFE00,
-}
+do
-variants[math_char] = function(pointer,what,n,parent) -- also set export value
- local char = getchar(pointer)
- local selector = validvariants[char]
- if selector then
- local next = getnext(parent)
- if next and getid(next) == math_noad then
- local nucleus = getnucleus(next)
- if nucleus and getid(nucleus) == math_char and getchar(nucleus) == selector then
- local variant
- local tfmdata = fontdata[getfont(pointer)]
- local mathvariants = tfmdata.resources.variants -- and variantdata
- if mathvariants then
- mathvariants = mathvariants[selector]
+ local variants = { }
+ local validvariants = { -- fast check on valid
+ [0x2229] = 0xFE00, [0x222A] = 0xFE00,
+ [0x2268] = 0xFE00, [0x2269] = 0xFE00,
+ [0x2272] = 0xFE00, [0x2273] = 0xFE00,
+ [0x228A] = 0xFE00, [0x228B] = 0xFE00,
+ [0x2293] = 0xFE00, [0x2294] = 0xFE00,
+ [0x2295] = 0xFE00,
+ [0x2297] = 0xFE00,
+ [0x229C] = 0xFE00,
+ [0x22DA] = 0xFE00, [0x22DB] = 0xFE00,
+ [0x2A3C] = 0xFE00, [0x2A3D] = 0xFE00,
+ [0x2A9D] = 0xFE00, [0x2A9E] = 0xFE00,
+ [0x2AAC] = 0xFE00, [0x2AAD] = 0xFE00,
+ [0x2ACB] = 0xFE00, [0x2ACC] = 0xFE00,
+ }
+
+ variants[math_char] = function(pointer,what,n,parent) -- also set export value
+ local char = getchar(pointer)
+ local selector = validvariants[char]
+ if selector then
+ local next = getnext(parent)
+ if next and getid(next) == math_noad then
+ local nucleus = getnucleus(next)
+ if nucleus and getid(nucleus) == math_char and getchar(nucleus) == selector then
+ local variant
+ local tfmdata = fontdata[getfont(pointer)]
+ local mathvariants = tfmdata.resources.variants -- and variantdata
if mathvariants then
- variant = mathvariants[char]
- end
- end
- if variant then
- setchar(pointer,variant)
- setattr(pointer,a_exportstatus,char) -- we don't export the variant as it's visual markup
- if trace_variants then
- report_variants("variant (%U,%U) replaced by %U",char,selector,variant)
+ mathvariants = mathvariants[selector]
+ if mathvariants then
+ variant = mathvariants[char]
+ end
end
- else
- if trace_variants then
- report_variants("no variant (%U,%U)",char,selector)
+ if variant then
+ setchar(pointer,variant)
+ setattr(pointer,a_exportstatus,char) -- we don't export the variant as it's visual markup
+ if trace_variants then
+ report_variants("variant (%U,%U) replaced by %U",char,selector,variant)
+ end
+ else
+ if trace_variants then
+ report_variants("no variant (%U,%U)",char,selector)
+ end
end
+ setprev(next,pointer)
+ setnext(parent,getnext(next))
+ flush_node(next)
end
- setprev(next,pointer)
- setnext(parent,getnext(next))
- flush_node(next)
end
end
end
-end
-function handlers.variants(head,style,penalties)
- processnoads(head,variants,"unicode variant")
- return true
+ function handlers.variants(head,style,penalties)
+ processnoads(head,variants,"unicode variant")
+ return true
+ end
+
end
-- for manuals
-local classes = { }
-
-local colors = {
- [noad_rel] = "trace:dr",
- [noad_ord] = "trace:db",
- [noad_bin] = "trace:dg",
- [noad_open] = "trace:dm",
- [noad_close] = "trace:dm",
- [noad_punct] = "trace:dc",
- -- [noad_opdisplaylimits] = "",
- -- [noad_oplimits] = "",
- -- [noad_opnolimits] = "",
- -- [noad_inner = "",
- -- [noad_under = "",
- -- [noad_over = "",
- -- [noad_vcenter = "",
-}
+do
-classes[math_char] = function(pointer,what,n,parent)
- local color = colors[getsubtype(parent)]
- if color then
- setcolor(pointer,color)
- else
- resetcolor(pointer)
+ local classes = { }
+ local colors = {
+ [noad_rel] = "trace:dr",
+ [noad_ord] = "trace:db",
+ [noad_bin] = "trace:dg",
+ [noad_open] = "trace:dm",
+ [noad_close] = "trace:dm",
+ [noad_punct] = "trace:dc",
+ -- [noad_opdisplaylimits] = "",
+ -- [noad_oplimits] = "",
+ -- [noad_opnolimits] = "",
+ -- [noad_inner = "",
+ -- [noad_under = "",
+ -- [noad_over = "",
+ -- [noad_vcenter = "",
+ }
+
+ local setcolor = colortracers.set
+ local resetcolor = colortracers.reset
+
+ classes[math_char] = function(pointer,what,n,parent)
+ local color = colors[getsubtype(parent)]
+ if color then
+ setcolor(pointer,color)
+ else
+ resetcolor(pointer)
+ end
end
-end
-function handlers.classes(head,style,penalties)
- processnoads(head,classes,"classes")
- return true
-end
+ function handlers.classes(head,style,penalties)
+ processnoads(head,classes,"classes")
+ return true
+ end
-registertracker("math.classes",function(v)
- setaction("math","noads.handlers.classes",v)
-end)
+ registertracker("math.classes",function(v)
+ setaction("math","noads.handlers.classes",v)
+ end)
+
+end
-- experimental
@@ -1760,9 +2001,7 @@ do
local categories = { }
local numbers = { }
local a_mathdomain = privateattribute("mathdomain")
-
mathematics.domains = categories
-
local permitted = {
ordinary = noad_ord,
binary = noad_bin,
@@ -1915,22 +2154,44 @@ end)
-- also for me
-local applyvisuals = nuts.applyvisuals
-local visual = false
+do
-function handlers.makeup(head)
- applyvisuals(tonut(head),visual)
-end
+ local applyvisuals = nuts.applyvisuals
+ local visual = false
-registertracker("math.makeup",function(v)
- visual = v
- setaction("math","noads.handlers.makeup",v)
-end)
+ function handlers.makeup(head)
+ applyvisuals(tonut(head),visual)
+ end
+
+ registertracker("math.makeup",function(v)
+ visual = v
+ setaction("math","noads.handlers.makeup",v)
+ end)
+
+end
-- the normal builder
-function builders.kernel.mlist_to_hlist(head,style,penalties)
- return mlist_to_hlist(head,style,penalties), true
+do
+
+ local force_penalties = false
+
+ -- registertracker("math.penalties",function(v)
+ -- force_penalties = v
+ -- end)
+
+ function builders.kernel.mlist_to_hlist(head,style,penalties)
+ return mlist_to_hlist(head,style,force_penalties or penalties), true
+ end
+
+ implement {
+ name = "setmathpenalties",
+ arguments = "integer",
+ actions = function(p)
+ force_penalties = p > 0
+ end,
+ }
+
end
-- function builders.kernel.mlist_to_hlist(head,style,penalties)