diff options
author | Hans Hagen <pragma@wxs.nl> | 2021-12-24 19:46:30 +0100 |
---|---|---|
committer | Context Git Mirror Bot <phg@phi-gamma.net> | 2021-12-24 19:46:30 +0100 |
commit | 1cc6c316feae649d3c8b64ef0c980dfd792c2347 (patch) | |
tree | d2153ed2d05808a40963f095fb2d29c4f5e5c4c8 /tex | |
parent | 19750b667c23a9f276032837d6c517063376bd0c (diff) | |
download | context-1cc6c316feae649d3c8b64ef0c980dfd792c2347.tar.gz |
2021-12-24 19:09:00
Diffstat (limited to 'tex')
57 files changed, 2053 insertions, 1539 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index bbd1c93f6..648915909 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2021.12.14 19:16} +\newcontextversion{2021.12.24 19:07} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index 560c4107c..9d4bcc772 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2021.12.14 19:16} +\edef\contextversion{2021.12.24 19:07} %D For those who want to use this: diff --git a/tex/context/base/mkiv/anch-pgr.lua b/tex/context/base/mkiv/anch-pgr.lua index e822f12b4..8681239c9 100644 --- a/tex/context/base/mkiv/anch-pgr.lua +++ b/tex/context/base/mkiv/anch-pgr.lua @@ -81,7 +81,6 @@ local nodecodes = nodes.nodecodes local par_code = nodecodes.par local startofpar = nuts.startofpar - local insertbefore = nuts.insertbefore local insertafter = nuts.insertafter @@ -102,6 +101,7 @@ local enabled = false -- many pages but for an arbitrary background shape that is not so common. local function check(specification) + -- local a = specification.attribute local index = specification.index local depth = specification.depth @@ -208,21 +208,6 @@ local function registerbackground(name) end end --- local function collectbackgrounds(r,n) --- if enabled then --- local parent = getbox(n) --- local head = getlist(parent) --- realpage = r --- processranges(a_textbackground,flush,head) -- ,parent) --- end --- end --- --- interfaces.implement { --- name = "collectbackgrounds", --- actions = collectbackgrounds, --- arguments = { "integer", "integer" } --- } - nodes.handlers.textbackgrounds = function(head,where,parent) -- we have hlistdir and local dir -- todo enable action in register index = index + 1 @@ -785,9 +770,7 @@ local function calculatemultipar(tag) for i=bindex+1,eindex-1 do br = f_tag_two(btag,i) local r = collected[br] - if not r then - report_graphics("invalid middle for %a",br) - else + if r then local rp = r.p -- page local pp = list[rp] local mp = middlepart(b,e,p,rp,r,left,right) @@ -796,6 +779,8 @@ local function calculatemultipar(tag) else list[rp] = { mp } end + else + report_graphics("invalid middle for %a",br) end end local ep = e.p -- page diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index d61d0887e..98dbc868f 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.12.14 19:16} +\newcontextversion{2021.12.24 19:07} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 4675386c8..bc37c8aab 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -49,7 +49,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2021.12.14 19:16} +\edef\contextversion{2021.12.24 19:07} %D Kind of special: diff --git a/tex/context/base/mkiv/file-lib.lua b/tex/context/base/mkiv/file-lib.lua index 9b0679e25..50ac5e1db 100644 --- a/tex/context/base/mkiv/file-lib.lua +++ b/tex/context/base/mkiv/file-lib.lua @@ -18,10 +18,11 @@ local report_library = logs.reporter("files","library") ----- report_files = logs.reporter("files","readfile") local removesuffix = file.removesuffix +local collapsepath = file.collapsepath local getreadfilename = resolvers.getreadfilename -local loaded = { } +local libraries = table.setmetatableindex("table") local defaultpatterns = { "%s" } local function defaultaction(name,foundname) @@ -46,6 +47,7 @@ function resolvers.uselibrary(specification) -- todo: reporter local foundname = getreadfilename("any",".",somename) -- maybe some day also an option not to backtrack .. and ../.. (or block global) return foundname ~= "" and foundname end + local loaded = libraries[patterns] for i=1,#files do local filename = files[i] if not loaded[filename] then @@ -76,17 +78,25 @@ function resolvers.uselibrary(specification) -- todo: reporter end end end - if not loaded[foundname] then - if foundname then - action(name,foundname) + if type(foundname) == "string" then + if not loaded[foundname] then + if foundname then + foundname = collapsepath(foundname) + -- this way we can run a module (nil when making a format): + local inputname = environment.inputfilename + if not inputname or collapsepath(inputname) ~= foundname then + action(name,foundname) + end + -- afterwards: + if onlyonce then + loaded[foundname] = true -- todo: base this on return value + end + elseif failure then + failure(name) + end if onlyonce then - loaded[foundname] = true -- todo: base this on return value + loaded[filename] = true -- todo: base this on return value end - elseif failure then - failure(name) - end - if onlyonce then - loaded[filename] = true -- todo: base this on return value end end end diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua index 87c52de04..0249b906b 100644 --- a/tex/context/base/mkiv/mult-prm.lua +++ b/tex/context/base/mkiv/mult-prm.lua @@ -312,6 +312,7 @@ return { "efcode", "endlocalcontrol", "enforced", + "etoks", "etoksapp", "etokspre", "everybeforepar", @@ -552,6 +553,7 @@ return { "wordboundary", "wrapuppar", "xdefcsname", + "xtoks", "xtoksapp", "xtokspre", }, diff --git a/tex/context/base/mkiv/page-one.mkiv b/tex/context/base/mkiv/page-one.mkiv index dbed7429a..567a19884 100644 --- a/tex/context/base/mkiv/page-one.mkiv +++ b/tex/context/base/mkiv/page-one.mkiv @@ -372,13 +372,13 @@ \def\page_one_command_flush_bottom_insertions_indeed {\ifgridsnapping - % \floatparameter\c!bottombefore + % \rootfloatparameter\c!bottombefore \snaptogrid\hbox{\box\namedinsertionnumber\s!bottomfloat}% - % \floatparameter\c!bottomafter + % \rootfloatparameter\c!bottomafter \else - \floatparameter\c!bottombefore + \rootfloatparameter\c!bottombefore \unvbox\namedinsertionnumber\s!bottomfloat - \floatparameter\c!bottomafter + \rootfloatparameter\c!bottomafter \fi} \unexpanded\def\page_one_command_flush_floats diff --git a/tex/context/base/mkiv/publ-ini.lua b/tex/context/base/mkiv/publ-ini.lua index bc0a9106f..9d43f69f4 100644 --- a/tex/context/base/mkiv/publ-ini.lua +++ b/tex/context/base/mkiv/publ-ini.lua @@ -2408,6 +2408,10 @@ do s = k break end + -- weird + if type(s) == "table" then + return citevariants.default + end end if s then s = specifications[s] diff --git a/tex/context/base/mkiv/spac-ver.lua b/tex/context/base/mkiv/spac-ver.lua index 9e0bc2dd8..8baf25184 100644 --- a/tex/context/base/mkiv/spac-ver.lua +++ b/tex/context/base/mkiv/spac-ver.lua @@ -2005,10 +2005,7 @@ do function vspacing.vboxhandler(head,where) if head and not ignore[where] and getnext(head) then - if getnext(head) then -- what if a one liner and snapping? - head = collapser(head,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper - return head - end + head = collapser(head,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper end return head end diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex 708b6ffd2..64c9917b6 100644 --- a/tex/context/base/mkiv/status-files.pdf +++ b/tex/context/base/mkiv/status-files.pdf diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf Binary files differindex 10f855c72..38d788622 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkxl/anch-bck.mklx b/tex/context/base/mkxl/anch-bck.mklx index 5c9382a7b..818fade98 100644 --- a/tex/context/base/mkxl/anch-bck.mklx +++ b/tex/context/base/mkxl/anch-bck.mklx @@ -245,7 +245,7 @@ \carryoverpar\endgroup} \def\anch_backgrounds_text_start_txt - {\ifvmode \dontleavehmode \fi + {\ifvmode\dontleavehmode\fi \begingroup \c_anch_backgrounds_pos_state\plusone \usetextbackgroundstyleandcolor\c!style\c!color diff --git a/tex/context/base/mkxl/anch-pgr.lmt b/tex/context/base/mkxl/anch-pgr.lmt index 8a329fd13..5261a2afa 100644 --- a/tex/context/base/mkxl/anch-pgr.lmt +++ b/tex/context/base/mkxl/anch-pgr.lmt @@ -106,13 +106,12 @@ local jobpositions = job.positions local getpos = jobpositions.getpos local getfree = jobpositions.getfree -local data = { } local realpage = 1 -local recycle = 1000 -- only tables can overflow this local enabled = false --- Freeing the data is somewhat tricky as we can have backgrounds spanning --- many pages but for an arbitrary background shape that is not so common. +-- Freeing the data is somewhat tricky as we can have backgrounds spanning many +-- pages but for an arbitrary background shape that is not so common but we use +-- a different trick anyway in lmtx. local function check(specification) -- @@ -170,8 +169,11 @@ end local index = 0 +local registervalue = attributes.registervalue +local getvalue = attributes.getvalue + local function flush(head,f,l,a,parent,depth) - local d = data[a] + local d = getvalue(a_textbackground,a) if d then local ix = index local ht = getheight(parent) @@ -193,18 +195,11 @@ local function flush(head,f,l,a,parent,depth) end local function registerbackground(name) - local n = #data + 1 - if n > recycle then - -- we could also free all e: that are beyond a page but we don't always - -- know the page so a recycle is nicer and the s lists are kept anyway - -- so the amount of kept data is not that large - n = 1 - end local b = jobpositions.tobesaved["b:"..name] if b then local s = setmetatableindex("table") b.s = s - data[n] = { + local t = { bpos = b, name = name, n = n, @@ -212,7 +207,7 @@ local function registerbackground(name) count = 0, sindex = 0, } - texsetattribute(a_textbackground,n) + texsetattribute(a_textbackground,registervalue(a_textbackground,t)) if not enabled then enableaction("contributers", "nodes.handlers.textbackgrounds") enabled = true @@ -784,9 +779,7 @@ local function calculatemultipar(tag) for i=bindex+1,eindex-1 do br = f_tag_two(btag,i) local r = collected[br] - if not r then - report_graphics("invalid middle for %a",br) - else + if r then local rp = r.p -- page local pp = list[rp] local mp = middlepart(b,e,p,rp,r,left,right) @@ -795,6 +788,8 @@ local function calculatemultipar(tag) else list[rp] = { mp } end + else + report_graphics("invalid middle for %a",br) end end local ep = e.p -- page diff --git a/tex/context/base/mkxl/anch-pos.lmt b/tex/context/base/mkxl/anch-pos.lmt index 4900df683..5a9ffaa3d 100644 --- a/tex/context/base/mkxl/anch-pos.lmt +++ b/tex/context/base/mkxl/anch-pos.lmt @@ -102,7 +102,7 @@ local formatters = string.formatters local collected = allocate() local tobesaved = allocate() -local positionsused = false +local positionsused = nil local jobpositions = { collected = collected, @@ -145,7 +145,7 @@ local f_tag_two = formatters["%s:%s"] -- Because positions are set with a delay we cannot yet make the tree -- so that -- is a finalizer step. But, we already have a dual split. --- local treemode = false +local treemode = false local treemode = true local function checkshapes(s) @@ -231,12 +231,14 @@ if treemode then columndone = false local deltapacking = true -- so we can see the difference +-- local deltapacking = false -- so we can see the difference local function checkcommondata(v,common) if common then local i = v.i local t = common[i] if t then +v.i = nil local m = t.mt if not m then setmetatable(t,default) @@ -289,7 +291,8 @@ if treemode then local v = list[one] or false if v then if prefix == "p" then - if deltapacking and type(v) == "number" then + -- if deltapacking and type(v) == "number" then + if type(v) == "number" then for i=one,1,-1 do local l = list[i] if type(l) ~= "number" then @@ -312,7 +315,7 @@ if treemode then if not getmetatable(l) then checkcommondata(l,x_y_w_h_list) end - v = setmetatable({ p = p }, { __index = l }) + v = setmetatable({ p = v }, { __index = l }) list[one] = v break end @@ -433,17 +436,6 @@ if treemode then t[category] = tc return tc end) - -- - for k, v in next, collected do - if k ~= "shared" and next(v) then - positionsused = true - break - end - end - end - - function jobpositions.used() - return positionsused end local function finalizer() @@ -822,6 +814,19 @@ else end +function jobpositions.used() + if positionsused == nil then + positionsused = false + for k, v in next, collected do + if k ~= "shared" and next(v) then + positionsused = true + break + end + end + end + return positionsused +end + function jobpositions.getfree(page) return freedata[page] end @@ -1489,7 +1494,12 @@ function jobpositions.copy(target,source) end function jobpositions.replace(id,p,x,y,w,h,d) - collected[id] = { p = p, x = x, y = y, w = w, h = h, d = d } -- c g + local c = collected[id] + if c then + c.p = p ; c.x = x ; c.y = y ; c.w = w ; c.h = h ; c.d = d ; -- c g + else + collected[i] = { p = p, x = x, y = y, w = w, h = h, d = d } -- c g + end end local function getpage(id) @@ -1751,14 +1761,12 @@ implement { public = true, protected = true, actions = function(name,page,x,y,w,h,d) - collected[name] = { - p = page, - x = x, - y = y, - w = w, - h = h, - d = d, - } + local c = collected[name] + if c then + c.p = page ; c.x = x ; c.y = y ; c.w = w ; c.h = h ; c.d = d ; + else + collected[name] = { p = page, x = x, y = y, w = w, h = h, d = d } + end end } @@ -2249,7 +2257,7 @@ implement { public = true, protected = true, actions = function() - doifelse(positionsused) + doifelse(jobpositions.used()) end } diff --git a/tex/context/base/mkxl/anch-pos.mkxl b/tex/context/base/mkxl/anch-pos.mkxl index 70197e93e..fef8e54f6 100644 --- a/tex/context/base/mkxl/anch-pos.mkxl +++ b/tex/context/base/mkxl/anch-pos.mkxl @@ -419,7 +419,6 @@ \global\positioningtrue} \permanent\protected\lettonothing\disableparpositions - \permanent\protected\lettonothing\registerparoptions % hooks into everypar \permanent\protected\def\doregisterparoptions @@ -432,16 +431,22 @@ \def\anch_positions_register_par_options_traced {\anch_positions_register_par_options_normal - \smashedhbox to \zeropoint + \begingroup + \setbox\scratchbox\hpack {\hss \startcolor[blue]% - \llap{\infofont\number\c_anch_positions_paragraph}% + \hpack \s!yoffset -2\onepoint to \zeropoint + {\hss\infofont\number\c_anch_positions_paragraph\hskip2\onepoint}% \vrule \s!width 4\onepoint \s!height2\onepoint \s!depth 2\onepoint \stopcolor - \hss}} + \hss}% + \smashbox\scratchbox + \boxxoffset\scratchbox-2\onepoint + \box\scratchbox + \endgroup} \let\anch_positions_register_par_options\anch_positions_register_par_options_normal diff --git a/tex/context/base/mkxl/attr-ini.lmt b/tex/context/base/mkxl/attr-ini.lmt new file mode 100644 index 000000000..ca21365cb --- /dev/null +++ b/tex/context/base/mkxl/attr-ini.lmt @@ -0,0 +1,352 @@ +if not modules then modules = { } end modules ['attr-ini'] = { + version = 1.001, + comment = "companion to attr-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local next, type = next, type +local osexit = os.exit +local sortedhash = table.sortedhash + +--[[ldx-- +<p>We start with a registration system for atributes so that we can use the +symbolic names later on.</p> +--ldx]]-- + +local nodes = nodes +local context = context +local storage = storage +local commands = commands + +local implement = interfaces.implement + +attributes = attributes or { } +local attributes = attributes + +local sharedstorage = storage.shared + +local texsetattribute = tex.setattribute + +attributes.names = attributes.names or { } +attributes.numbers = attributes.numbers or { } +attributes.list = attributes.list or { } +attributes.values = attributes.values or { } +attributes.counts = attributes.counts or { } +attributes.handlers = attributes.handlers or { } +attributes.states = attributes.states or { } +attributes.unsetvalue = -0x7FFFFFFF + +local currentfont = font.current +local currentattributes = nodes and nodes. currentattributes or node.currentattributes +local getusedattributes = nodes and nodes.nuts and nodes.nuts.getusedattributes or node.direct.getusedattributes + +local names = attributes.names +local numbers = attributes.numbers +local list = attributes.list +local values = attributes.values +local counts = attributes.counts + +storage.register("attributes/names", names, "attributes.names") +storage.register("attributes/numbers", numbers, "attributes.numbers") +storage.register("attributes/list", list, "attributes.list") +storage.register("attributes/values", values, "attributes.values") +storage.register("attributes/counts", counts, "attributes.counts") + +local report_attribute = logs.reporter("attributes") +local report_value = logs.reporter("attributes","values") + +local trace_values = false + +trackers.register("attributes.values", function(v) trace_values = v end) + +-- function attributes.define(name,number) -- at the tex end +-- if not numbers[name] then +-- numbers[name] = number +-- names[number] = name +-- list[number] = { } +-- end +-- end + +--[[ldx-- +<p>We reserve this one as we really want it to be always set (faster).</p> +--ldx]]-- + +names[0], numbers["fontdynamic"] = "fontdynamic", 0 + +--[[ldx-- +<p>private attributes are used by the system and public ones are for users. We use dedicated +ranges of numbers for them. Of course a the <l n='context'/> end a private attribute can be +accessible too, so a private attribute can have a public appearance.</p> +--ldx]]-- + +sharedstorage.attributes_last_private = sharedstorage.attributes_last_private or 15 -- very private +sharedstorage.attributes_last_public = sharedstorage.attributes_last_public or 1024 -- less private + +function attributes.private(name) -- at the lua end (hidden from user) + local number = numbers[name] + if not number then + local last = sharedstorage.attributes_last_private + if last < 1023 then + last = last + 1 + sharedstorage.attributes_last_private = last + else + report_attribute("no more room for private attributes") + osexit() + end + number = last + numbers[name], names[number], list[number] = number, name, { } + end + return number +end + +function attributes.public(name) -- at the lua end (hidden from user) + local number = numbers[name] + if not number then + local last = sharedstorage.attributes_last_public + if last < 65535 then + last = last + 1 + sharedstorage.attributes_last_public = last + else + report_attribute("no more room for public attributes") + osexit() + end + number = last + numbers[name], names[number], list[number] = number, name, { } + end + return number +end + +attributes.system = attributes.private + +function attributes.define(name,category) + return (attributes[category or "public"] or attributes["public"])(name) +end + +-- tracers + +local function showlist(what,list) + if list then + local a = list.next + local i = 0 + while a do + local number = a.index + local value = a.value + i = i + 1 + report_attribute("%S %2i: attribute %3i, value %4i, name %a",what,i,number,value,names[number]) + a = a.next + end + end +end + +function attributes.showcurrent() + showlist("current",currentattributes()) +end + +function attributes.ofnode(n) + showlist(n,n.attr) +end + +-- rather special (can be optimized) + +local store = { } + +function attributes.save(name) + name = name or "" + local n = currentattributes() + n = n and n.next + local t = { } + while n do + t[n.index] = n.value + n = n.next + end + store[name] = { + attr = t, + font = currentfont(), + } +end + +function attributes.restore(name) + name = name or "" + local t = store[name] + if t then + local attr = t.attr + local font = t.font + if attr then + for k, v in next, attr do + texsetattribute(k,v) + end + end + if font then + -- tex.font = font + -- context.getvalue(fonts.hashes.csnames[font]) + currentfont(font) + end + end + -- store[name] = nil +end + +-- value manager + +local cleaners = { } + +-- function attributes.registervalue(index,value) +-- local list = values[index] +-- local last +-- if list then +-- last = counts[index] + 1 +-- list[last] = value +-- else +-- last = 1 +-- values[index] = { value } +-- end +-- counts[index] = last +-- return last +-- end + +function attributes.registervalue(index,value) + local list = values[index] + local last + if list then + local c = counts[index] + if c and c[2] > 0 then + -- this can be an option + for i=c[1],c[2] do + if list[i] == nil then + if trace_values then + report_value("reusing slot %i for attribute %i in range (%i,%i)",i,index,c[1],c[2]) + end + c[1] = i + list[i] = value + return i + end + end + else + c = { 0, 0 } + end + last = c[2] + 1 + list[last] = value + c[1] = last + c[2] = last + if trace_values then + report_value("expanding to slot %i for attribute %i",last,index) + end + else + last = 1 + values[index] = { value } + counts[index] = { last, last } + if trace_values then + report_value("starting at slot %i for attribute %i",last,index) + end + end + return last +end + +function attributes.getvalue(index,value) + local list = values[index] + return list and list[value] or nil +end + +function attributes.hasvalues(index) + local list = values[index] + return list and next(list) and true or false +end + +function attributes.setcleaner(index,cleaner) + cleaners[index] = cleaner +end + +function attributes.checkvalues() +-- if true then +-- report_value("no checking done") +-- return +-- end + if next(values) then + local active = getusedattributes() + if trace_values then + -- sorted + for index, list in sortedhash(values) do + local b = active[index] + if b then + local cleaner = cleaners[index] + for k in sortedhash(list) do + if b[k] then + report_value("keeping value %i for attribute %i",k,index) + else + report_value("wiping value %i for attribute %i",k,index) + if cleaner then + cleaner(list[k]) + end + list[k] = nil + end + end + if next(list) then + counts[index][1] = 0 + goto continue + end + end + report_value("no more values for attribute %i",index) + values[index] = nil + counts[index] = nil + ::continue:: + end + else + for index, list in next, values do + local b = active[index] + if b then + local cleaner = cleaners[index] + for k in next, list do + if not b[k] then + if cleaner then + cleaner(list[k]) + end + list[k] = nil + end + end + if next(list) then + counts[index][1] = 0 + goto continue + end + end + values[index] = nil + counts[index] = { 0, 0 } + ::continue:: + end + end + elseif trace_values then + report_value("no check needed") + end +end + +implement { + name = "cleanupattributes", + -- public = true, -- some day ... but then also \shipoutpage + protected = true, + actions = attributes.checkvalues, +} + +-- interface + +implement { + name = "defineattribute", + arguments = "2 strings", + actions = { attributes.define, context } +} + +implement { + name = "showattributes", + actions = attributes.showcurrent +} + +implement { + name = "savecurrentattributes", + arguments = "string", + actions = attributes.save +} + +implement { + name = "restorecurrentattributes", + arguments = "string", + actions = attributes.restore +} diff --git a/tex/context/base/mkxl/attr-ini.mkxl b/tex/context/base/mkxl/attr-ini.mkxl index 23a38eb12..e3538cf3d 100644 --- a/tex/context/base/mkxl/attr-ini.mkxl +++ b/tex/context/base/mkxl/attr-ini.mkxl @@ -15,7 +15,7 @@ \unprotect -\registerctxluafile{attr-ini}{} +\registerctxluafile{attr-ini}{autosuffix} \installcorenamespace{attributecount} % the counter representing the attribute (attrdef'd) \installcorenamespace{attributeid} % the internal number @@ -125,7 +125,6 @@ \definesystemattribute [layoutcomponent] [public] \definesystemattribute [internal] [public] \definesystemattribute [ruled] [public] -\definesystemattribute [ruledextra] [public] \definesystemattribute [shifted] [public] \definesystemattribute [checkedbreak] [public] \definesystemattribute [alternate] [public] diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl index 28c8d3bf6..b30d8996a 100644 --- a/tex/context/base/mkxl/cont-new.mkxl +++ b/tex/context/base/mkxl/cont-new.mkxl @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2021.12.14 19:16} +\newcontextversion{2021.12.24 19:07} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkxl/context.mkxl b/tex/context/base/mkxl/context.mkxl index 93c7f1d69..33bb1971a 100644 --- a/tex/context/base/mkxl/context.mkxl +++ b/tex/context/base/mkxl/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \immutable\edef\contextformat {\jobname} -\immutable\edef\contextversion{2021.12.14 19:16} +\immutable\edef\contextversion{2021.12.24 19:07} %overloadmode 1 % check frozen / warning %overloadmode 2 % check frozen / error @@ -219,7 +219,7 @@ \loadmkxlfile{colo-grp} % optional \loadmkxlfile{colo-ext} -\loadmkxlfile{node-bck} % overloads anch-pgr (experimental and undocumented) +% \loadmkxlfile{node-bck} % overloads anch-pgr (experimental and undocumented) \loadmkxlfile{pack-cut} @@ -502,6 +502,8 @@ \loadmkxlfile{phys-dim} \loadmkxlfile{node-rul} % beware, defined \underbar so after math +\loadmkxlfile{node-bck} % overloads anch-pgr (experimental and undocumented) + \loadmklxfile{font-sol} % font solutions \loadmklxfile{strc-not} diff --git a/tex/context/base/mkxl/file-job.lmt b/tex/context/base/mkxl/file-job.lmt index 84186a2d0..367ec4562 100644 --- a/tex/context/base/mkxl/file-job.lmt +++ b/tex/context/base/mkxl/file-job.lmt @@ -192,7 +192,7 @@ implement { -- moved from tex to lua: local texpatterns = { "%s.mklx", "%s.mkxl", "%s.mkvi", "%s.mkiv", "%s.tex" } -local luapatterns = { "%s" .. utilities.lua.suffixes.luc, "%s.lua", "%s.lmt" } +local luapatterns = { "%s" .. utilities.lua.suffixes.luc, "%s.lmt", "%s.lua" } local cldpatterns = { "%s.cld" } local xmlpatterns = { "%s.xml" } diff --git a/tex/context/base/mkxl/file-mod.mklx b/tex/context/base/mkxl/file-mod.mklx index ddcbcba3f..3a966894f 100644 --- a/tex/context/base/mkxl/file-mod.mklx +++ b/tex/context/base/mkxl/file-mod.mklx @@ -56,6 +56,7 @@ \edef\currentmoduleparameters{#name}% \else \edef\currentmodulecategory {#category}% + \edef\currentmodulecategory {#category}% \edef\currentmodule {#name}% \let \currentmoduleparameters\empty \fi diff --git a/tex/context/base/mkxl/luat-run.lmt b/tex/context/base/mkxl/luat-run.lmt index fa3336d4b..f6b2ea063 100644 --- a/tex/context/base/mkxl/luat-run.lmt +++ b/tex/context/base/mkxl/luat-run.lmt @@ -41,6 +41,8 @@ function luatex.registerstopactions (...) insert(stopactions, ...) end function luatex.registerdumpactions (...) insert(dumpactions, ...) end function luatex.registerpageactions (...) insert(pageactions, ...) end +local setexitcode = lua.setexitcode or status.setexitcode or function() end + local function start_run() if logs.start_run then logs.start_run() @@ -51,7 +53,7 @@ local function start_run() end end -local function stop_run() +local function stop_run(badrun) for i=1,#stopactions do stopactions[i]() end @@ -68,15 +70,14 @@ local function stop_run() end end if quit then - local setexitcode = lua.setexitcode or status.setexitcode - if setexitcode then - setexitcode(1) - if type(quit) == "table" then - logs.newline() - report_tex("quitting due to: %, t",quit) - logs.newline() - end + setexitcode(1) + if type(quit) == "table" then + logs.newline() + report_tex("quitting due to: %, t",quit) + logs.newline() end + elseif badrun and badrun > 0 then + setexitcode(1) end if logs.stop_run then logs.stop_run() @@ -147,6 +148,7 @@ end function luatex.abort() cleanup_run() + setexitcode(1) osexit(1) end @@ -289,6 +291,7 @@ callback.register("handle_overload", function(fatal,overload,csname,flags) logs.newline() if fatal then cleanup_run() + setexitcode(1) osexit(1) end end diff --git a/tex/context/base/mkxl/math-ali.lmt b/tex/context/base/mkxl/math-ali.lmt new file mode 100644 index 000000000..a84d5a4c4 --- /dev/null +++ b/tex/context/base/mkxl/math-ali.lmt @@ -0,0 +1,84 @@ +if not modules then modules = { } end modules ['math-ali'] = { + version = 1.001, + comment = "companion to math-ali.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local unpack = unpack +local gsub = string.gsub +local lpegmatch = lpeg.match +local settings_to_array = utilities.parsers.settings_to_array + +local rows = utilities.parsers.groupedsplitat(";") +local cols = utilities.parsers.groupedsplitat(",") + +local context = context + +local actions = { + transpose = function(m) + local t = { } + for j=1,#m[1] do + local r = { } + for i=1,#m do + r[i] = m[i][j] + end + t[j] = r + end + return t + end, + negate = function(m) + for i=1,#m do + local mi = m[i] + for j=1,#mi do + mi[j] = - mi[j] + end + end + return m + end, + scale = function(m,s) + s = tonumber(s) + if s then + for i=1,#m do + local mi = m[i] + for j=1,#mi do + mi[j] = s*mi[j] + end + end + end + return m + end, +} + +local useractions = { +} + +interfaces.implement { + name = "simplematrix", + arguments = "2 strings", + actions = function(method,data) + local m = lpegmatch(rows,(gsub(data,"%s+"," "))) + for i=1,#m do + m[i] = lpegmatch(cols,m[i]) + end + local methods = settings_to_array(method) + for i=1,#methods do + local detail = settings_to_array(methods[i]) + local method = detail[1] + local action = actions[method] or useractions[method] + if action then + m = action(m,unpack(detail,2)) or m + end + end + for i=1,#m do + context("\\NC %{ \\NC }t \\NR",m[i]) + end + end +} + +function mathematics.registersimplematrix(name,action) + if type(action) == "function" then + useractions[name] = action + end +end diff --git a/tex/context/base/mkxl/math-ali.mkxl b/tex/context/base/mkxl/math-ali.mkxl index cf941b586..30f5c0524 100644 --- a/tex/context/base/mkxl/math-ali.mkxl +++ b/tex/context/base/mkxl/math-ali.mkxl @@ -15,6 +15,8 @@ \unprotect +\registerctxluafile{math-ali}{autosuffix} + %D The code here has been moved from other files. Beware: the \MKII\ and \MKIV\ code %D is not gathered in files with the same name. In the meantime this code has been %D adapted to \MKIV\ but more is possible. The code is somewhat complicated by the @@ -368,6 +370,14 @@ % \begingroup not permitted ($$...assignments...\halign... ).. check in luametatex +% \definemathmatrix +% [pmatrix] +% [matrix:parentheses] +% % [align=1:right] +% [align=all:right] +% % [align=2:right] +% % [align={1:left,2:middle,3:right}] + \permanent\tolerant\protected\def\math_alignment_start[#1]#*[#2]% {\edef\currentmathalignment{#1}% \ifarguments\or\or @@ -399,8 +409,8 @@ \installcommandhandler \??mathalignment {mathalignment} \??mathalignment \appendtoks - \frozen\instance\setuevalue{\e!start\currentmathalignment}{\math_alignment_start[\currentmathalignment]}% - \frozen\instance\setvalue {\e!stop \currentmathalignment}{\math_alignment_stop}% can this be protected now? + \frozen\protected\instance\edefcsname\e!start\currentmathalignment\endcsname{\math_alignment_start[\currentmathalignment]}% + \noaligned\frozen\protected\instance \defcsname\e!stop \currentmathalignment\endcsname{\math_alignment_stop}% can this be protected now? \to \everydefinemathalignment % to be tested @@ -481,14 +491,28 @@ \dostoptagged % finish cell \dostarttagged\t!mtablecell\empty} +% \def\math_left_of_eqalign +% {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname +% \ifcase\lastnamedcs \or \relax \or \hfill \or \hfill \fi +% \fi} + +% \def\math_right_of_eqalign +% {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname +% \ifcase\lastnamedcs \or \hfill \or \relax \or \hfill \fi +% \fi} + \def\math_left_of_eqalign {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname \ifcase\lastnamedcs \or \relax \or \hfill \or \hfill \fi + \orelse\ifcsname\??mathalignmentvariant\number\zerocount\endcsname + \ifcase\lastnamedcs \or \relax \or \hfill \or \hfill \fi \fi} \def\math_right_of_eqalign {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname \ifcase\lastnamedcs \or \hfill \or \relax \or \hfill \fi + \orelse\ifcsname\??mathalignmentvariant\number\zerocount\endcsname + \ifcase\lastnamedcs \or \hfill \or \relax \or \hfill \fi \fi} \newconditional\c_math_alignment_local_number % not used but when true puts in front (todo) @@ -513,9 +537,29 @@ \fi \fi} -\def\math_eqalign_set_column#1% we could just add to the preamble (as with other alignments) - {\expandafter\chardef\csname\??mathalignmentvariant\number\c_math_eqalign_column\expandafter\expandafter\expandafter\endcsname - \ifcsname\??mathalignmentvariant#1\endcsname\lastnamedcs\else\zerocount\fi\relax} +% \def\math_eqalign_set_column#1% we could just add to the preamble (as with other alignments) +% {\expandafter\chardef\csname\??mathalignmentvariant\number\c_math_eqalign_column\expandafter\expandafter\expandafter\endcsname +% \ifcsname\??mathalignmentvariant#1\endcsname\lastnamedcs\else\zerocount\fi\relax} + +% \def\math_eqalign_set_column_indeed[#1:#2:#3]% we don't really check for all (so * will do too) ... yet +% {\expandafter\chardef\csname\??mathalignmentvariant\number +% \ifcstok{#2}\emptytoks\c_math_eqalign_column\orelse\ifchknum#1\or#1\else\zerocount\fi +% \endcsname +% \ifcsname\??mathalignmentvariant#2\endcsname\lastnamedcs\else\zerocount\fi\relax} + +\def\math_eqalign_set_column_indeed[#1:#2:#3]% we don't really check for all (so * will do too) ... yet + {\ifcstok{#2}\emptytoks + % current counter + \orelse\ifchknum#1\or + \c_math_eqalign_column#1\relax + \else + \c_math_eqalign_column\zerocount + \fi + \chardef\csname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname + \ifcsname\??mathalignmentvariant#2\endcsname\lastnamedcs\else\zerocount\fi\relax} + +\def\math_eqalign_set_column#1% + {\normalexpanded{\math_eqalign_set_column_indeed[#1::]}} \letcsname\??mathalignmentvariant\v!normal\endcsname\zerocount \letcsname\??mathalignmentvariant\v!left \endcsname\plusone @@ -1384,21 +1428,56 @@ %D The following code is derived from Aditya's simplematrix prototype but adapted to %D regular mathmatrices: -\def\math_matrix_simple_row#1% - {\rawprocesscommalist[#1]\math_matrix_simple_col - \toksapp\scratchtoks{\NR}} +% We keep this as reference: +% +% \def\math_matrix_simple_row#1% +% {\rawprocesscommalist[#1]\math_matrix_simple_col +% \toksapp\scratchtoks{\NR}} +% +% \def\math_matrix_simple_col#1% +% {\toksapp\scratchtoks{\NC#1}} +% +% \permanent\tolerant\protected\def\math_matrix_simple[#1]#*[#2]#:#3% +% {\begingroup +% \edef\currentmathmatrix{#1}% +% \setupcurrentmathmatrix[#2]% +% \scratchtoks\emptytoks +% \processlist[];\math_matrix_simple_row[#3]% +% \math_matrix_start[\currentmathmatrix]% +% \the\scratchtoks +% \math_matrix_stop +% \endgroup} -\def\math_matrix_simple_col#1% - {\toksapp\scratchtoks{\NC#1}} +%D With a little help from \LUA\ we now have this: +%D +%D \startbuffer +%D \definemathmatrix [Pmatrix] [matrix:parentheses] +%D [align={all:right}, +%D simplecommand=Pmatrix] +%D +%D \definemathmatrix [Tmatrix] [Pmatrix] +%D [action=transpose, +%D simplecommand=Tmatrix] +%D +%D \definemathmatrix [Nmatrix] [Pmatrix] +%D [action=negate, +%D simplecommand=Nmatrix] +%D +%D \startformula +%D \Pmatrix{ -1, 2, 3; 4,-5, 6; 7, 8,-9 } \neq +%D \Tmatrix{ -1, 2, 3; 4,-5, 6; 7, 8,-9 } \neq +%D \Nmatrix{ -1, 2, 3; 4,-5, 6; 7, 8,-9 } +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer \permanent\tolerant\protected\def\math_matrix_simple[#1]#*[#2]#:#3% {\begingroup \edef\currentmathmatrix{#1}% \setupcurrentmathmatrix[#2]% - \scratchtoks\emptytoks - \processlist[];\math_matrix_simple_row[#3]% \math_matrix_start[\currentmathmatrix]% - \the\scratchtoks + \clf_simplematrix{\mathmatrixparameter\c!action}{#3}% \math_matrix_stop \endgroup} @@ -1407,7 +1486,7 @@ \appendtoks \edef\p_simplecommand{\mathmatrixparameter\c!simplecommand}% \ifempty\p_simplecommand\else - \frozen\instance\setuevalue{\p_simplecommand}{\math_matrix_simple[\currentmathmatrix]}% + \frozen\protected\instance\edefcsname\p_simplecommand\endcsname{\math_matrix_simple[\currentmathmatrix]}% \fi \to \everydefinemathmatrix diff --git a/tex/context/base/mkxl/node-aux.lmt b/tex/context/base/mkxl/node-aux.lmt index 0c9bfc837..5915f5985 100644 --- a/tex/context/base/mkxl/node-aux.lmt +++ b/tex/context/base/mkxl/node-aux.lmt @@ -10,72 +10,72 @@ if not modules then modules = { } end modules ['node-aux'] = { local type, tostring = type, tostring -local nodes = nodes -local context = context - -local utfvalues = utf.values - -local nodecodes = nodes.nodecodes - -local glyph_code = nodecodes.glyph -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local attributelist_code = nodecodes.attributelist -- temporary -local par_code = nodecodes.par - -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode -local vianuts = nuts.vianuts - -local getbox = nuts.getbox -local getnext = nuts.getnext -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getlist = nuts.getlist -local getattr = nuts.getattr -local getboth = nuts.getboth -local getprev = nuts.getprev -local getwidth = nuts.getwidth -local setwidth = nuts.setwidth -local getboxglue = nuts.getboxglue -local setboxglue = nuts.setboxglue - -local setfield = nuts.setfield -local setattr = nuts.setattr -local setlink = nuts.setlink -local setlist = nuts.setlist -local setnext = nuts.setnext -local setprev = nuts.setprev -local setattrlist = nuts.setattrlist - -local traversers = nuts.traversers -local nextnode = traversers.node -local nextglyph = traversers.glyph - -local flushnode = nuts.flush -local flushlist = nuts.flushlist -local hpack_nodes = nuts.hpack -local vpack_nodes = nuts.vpack -local unsetattribute = nuts.unsetattribute -local firstglyph = nuts.firstglyph -local copy_node = nuts.copy -local find_tail = nuts.tail -local getbox = nuts.getbox -local count = nuts.count -local isglyph = nuts.isglyph - -local nodepool = nuts.pool -local new_glue = nodepool.glue -local new_glyph = nodepool.glyph - -local unsetvalue = attributes.unsetvalue - -local current_font = font.current - -local texsetbox = tex.setbox - -local report_error = logs.reporter("node-aux:error") +local nodes = nodes +local context = context + +local utfvalues = utf.values + +local nodecodes = nodes.nodecodes + +local glyph_code = nodecodes.glyph +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local attribute_code = nodecodes.attribute -- temporary +local par_code = nodecodes.par + +local nuts = nodes.nuts +local tonut = nuts.tonut +local tonode = nuts.tonode +local vianuts = nuts.vianuts + +local getbox = nuts.getbox +local getnext = nuts.getnext +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local getlist = nuts.getlist +local getattr = nuts.getattr +local getboth = nuts.getboth +local getprev = nuts.getprev +local getwidth = nuts.getwidth +local setwidth = nuts.setwidth +local getboxglue = nuts.getboxglue +local setboxglue = nuts.setboxglue + +local setfield = nuts.setfield +local setattr = nuts.setattr +local setlink = nuts.setlink +local setlist = nuts.setlist +local setnext = nuts.setnext +local setprev = nuts.setprev +local setattrlist = nuts.setattrlist + +local traversers = nuts.traversers +local nextnode = traversers.node +local nextglyph = traversers.glyph + +local flushnode = nuts.flush +local flushlist = nuts.flushlist +local hpack_nodes = nuts.hpack +local vpack_nodes = nuts.vpack +local unsetattribute = nuts.unsetattribute +local firstglyph = nuts.firstglyph +local copy_node = nuts.copy +local find_tail = nuts.tail +local getbox = nuts.getbox +local count = nuts.count +local isglyph = nuts.isglyph + +local nodepool = nuts.pool +local new_glue = nodepool.glue +local new_glyph = nodepool.glyph + +local unsetvalue = attributes.unsetvalue + +local current_font = font.current + +local texsetbox = tex.setbox + +local report_error = logs.reporter("node-aux:error") local function takebox(id) local box = getbox(id) @@ -281,12 +281,12 @@ local function link(list,currentfont,currentattr,head,tail) -- an oldie, might b elseif not head then head = n tail = find_tail(n) - elseif getid(n) == attributelist_code then + elseif getid(n) == attribute_code then -- weird case report_error("weird node type in list at index %s:",i) for i=1,#list do local l = list[i] - report_error("%3i: %s %S",i,getid(l) == attributelist_code and "!" or ">",l) + report_error("%3i: %s %S",i,getid(l) == attribute_code and "!" or ">",l) end os.exit() else diff --git a/tex/context/base/mkxl/node-bck.lmt b/tex/context/base/mkxl/node-bck.lmt index ba0e508b6..ff48ff8b5 100644 --- a/tex/context/base/mkxl/node-bck.lmt +++ b/tex/context/base/mkxl/node-bck.lmt @@ -83,7 +83,7 @@ trackers.register("backgrounds.alignments",function(v) trace_alignment = v end) local overshoot = math.floor(65781/5) -- could be an option per table (just also store it) -local function colored_a(current,list,template,id) +local function colored_a(current,list,template,id,data) local width, height, depth = getwhd(current) local total = height + depth if width > 0 and total > 0 then @@ -91,7 +91,7 @@ local function colored_a(current,list,template,id) -- local a = getattr(template,a_linefiller) if a then - local d = linefillers.data[a%1000] + local d = data[a] if d then rule = linefillers.filler(template,d,width,height,depth) end @@ -106,7 +106,7 @@ local function colored_a(current,list,template,id) end end -local function colored_b(current,list,template,id,indent) +local function colored_b(current,list,template,id,indent,data) local width, height, depth = getwhd(current) local total = height + depth if width > 0 and total > 0 then @@ -115,7 +115,7 @@ local function colored_b(current,list,template,id,indent) -- local a = getattr(template,a_linefiller) if a then - local d = linefillers.data[a%1000] + local d = data[a] if d then rule = linefillers.filler(template,d,width-indent,height,depth) end @@ -140,13 +140,13 @@ local currentrow = 0 local enabled = false local alignments = false -local function add_alignbackgrounds(head,list) +local function add_alignbackgrounds(head,list,data) for current, id, subtype, list in nextlist, list do if list and id == hlist_code and subtype == celllist_code then for template in nexthlist, list do local background = getattr(template,a_alignbackground) if background then - local list = colored_a(current,list,template) + local list = colored_a(current,list,template,data) if list then setlist(current,list) end @@ -158,25 +158,25 @@ local function add_alignbackgrounds(head,list) end local template = getprop(head,"alignmentchecked") if template then - list = colored_b(head,list,template[1],hlist_code,template[2]) + list = colored_b(head,list,template[1],hlist_code,template[2],data) flushnodelist(template) templates[currentrow] = false return list end end -local function add_backgrounds(head,id,list) +local function add_backgrounds(head,id,list,data) if list then for current, id, subtype, list in nextlist, list do if list then if alignments and subtype == alignmentlist_code then - local l = add_alignbackgrounds(current,list) + local l = add_alignbackgrounds(current,list,data) if l then list = l setlist(current,list) end end - local l = add_backgrounds(current,id,list) + local l = add_backgrounds(current,id,list,data) if l then list = l setlist(current,l) @@ -187,7 +187,7 @@ local function add_backgrounds(head,id,list) if id == hlist_code or id == vlist_code then local background = getattr(head,a_background) if background then - list = colored_a(head,list,head,id) + list = colored_a(head,list,head,id,data) -- not needed setattr(head,a_background,unsetvalue) -- or property -- todo return list @@ -196,21 +196,27 @@ local function add_backgrounds(head,id,list) end function nodes.handlers.backgrounds(head) - add_backgrounds(head,getid(head),getlist(head)) + local data = attributes.values[a_linefiller] + if data then + add_backgrounds(head,getid(head),getlist(head),data) + end return head end function nodes.handlers.backgroundspage(head,where) - if head and where == "alignment" then - for n in nexthlist, head do - local p = getprop(n,"alignmentchecked") - if not p and getsubtype(n) == alignmentlist_code then - currentrow = currentrow + 1 - local template = templates[currentrow] - if trace_alignment then - report_alignment("%03i %s %s",currentrow,"page",template and "+" or "-") + local data = attributes.values[a_linefiller] + if data then + if head and where == "alignment" then + for n in nexthlist, head do + local p = getprop(n,"alignmentchecked") + if not p and getsubtype(n) == alignmentlist_code then + currentrow = currentrow + 1 + local template = templates[currentrow] + if trace_alignment then + report_alignment("%03i %s %s",currentrow,"page",template and "+" or "-") + end + setprop(n,"alignmentchecked",template) end - setprop(n,"alignmentchecked",template) end end end @@ -218,18 +224,21 @@ function nodes.handlers.backgroundspage(head,where) end function nodes.handlers.backgroundsvbox(head,where) - if head and where == "vbox" then - local list = getlist(head) - if list then - for n in nexthlist, list do - local p = getprop(n,"alignmentchecked") - if not p and getsubtype(n) == alignmentlist_code then - currentrow = currentrow + 1 - local template = templates[currentrow] - if trace_alignment then - report_alignment("%03i %s %s",currentrow,"vbox",template and "+" or "-") + local data = attributes.values[a_linefiller] + if data then + if head and where == "vbox" then + local list = getlist(head) + if list then + for n in nexthlist, list do + local p = getprop(n,"alignmentchecked") + if not p and getsubtype(n) == alignmentlist_code then + currentrow = currentrow + 1 + local template = templates[currentrow] + if trace_alignment then + report_alignment("%03i %s %s",currentrow,"vbox",template and "+" or "-") + end + setprop(n,"alignmentchecked",template) end - setprop(n,"alignmentchecked",template) end end end @@ -237,15 +246,6 @@ function nodes.handlers.backgroundsvbox(head,where) return head end --- interfaces.implement { --- name = "enablebackgroundboxes", --- onlyonce = true, --- actions = enableaction, --- arguments = { "'shipouts'", "'nodes.handlers.backgrounds'" } --- } --- --- doing it in the shipout works as well but this is nicer - local function enable(alignmentstoo) if not enabled then enabled = true @@ -274,7 +274,7 @@ interfaces.implement { interfaces.implement { name = "setbackgroundrowdata", - arguments = { "integer", "integer", "dimension" }, + arguments = { "integer", "integer", "dimension" }, -- todo: "box" actions = function(row,box,indent) row = row -1 -- better here than in tex if box == 0 then diff --git a/tex/context/base/mkxl/node-bck.mkxl b/tex/context/base/mkxl/node-bck.mkxl index b456313df..3c2fa015c 100644 --- a/tex/context/base/mkxl/node-bck.mkxl +++ b/tex/context/base/mkxl/node-bck.mkxl @@ -26,6 +26,8 @@ % \backgroundvbox[red] {\input knuth } \par % \backgroundhbox[yellow]{\rotate[rotation=45]{hello world}} \par +% todo: use new register feature (but not used that much so ...) + \permanent\def\colorattr#1% {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname \node_backgrounds_thecolorattr{\currentcolorprefix#1}% diff --git a/tex/context/base/mkxl/node-ext.lmt b/tex/context/base/mkxl/node-ext.lmt index fa15b9d19..de2e8fa54 100644 --- a/tex/context/base/mkxl/node-ext.lmt +++ b/tex/context/base/mkxl/node-ext.lmt @@ -133,14 +133,10 @@ do end function backends.latelua(current,pos_h,pos_v) -- todo: pass pos_h and pos_v (more efficient in lmtx) - local p = nodeproperties[current] - if p then - data = p.data - else - data = getdata(current) - end - noflatelua = noflatelua + 1 + local prop = nodeproperties[current] + local data = prop and prop.data or getdata(current) local kind = type(data) + noflatelua = noflatelua + 1 if kind == "table" then data.action(data.specification or data) elseif kind == "function" then @@ -149,7 +145,7 @@ do if kind ~= "string" then data = serialize(data) end - if #data ~= "" then + if data and #data ~= "" then local code = loadstring(data) if code then code() diff --git a/tex/context/base/mkxl/node-ini.lmt b/tex/context/base/mkxl/node-ini.lmt index 06e36147c..1ec0932ab 100644 --- a/tex/context/base/mkxl/node-ini.lmt +++ b/tex/context/base/mkxl/node-ini.lmt @@ -47,27 +47,28 @@ do tex.magicconstants = table.setmetatableindex(t,c) end -local listcodes = mark(getsubtypes("list")) -local rulecodes = mark(getsubtypes("rule")) -local dircodes = mark(getsubtypes("dir")) -local markcodes = mark(getsubtypes("mark")) -local glyphcodes = mark(getsubtypes("glyph")) -local disccodes = mark(getsubtypes("disc")) -local gluecodes = mark(getsubtypes("glue")) -local boundarycodes = mark(getsubtypes("boundary")) -local penaltycodes = mark(getsubtypes("penalty")) -local kerncodes = mark(getsubtypes("kern")) -local mathcodes = mark(getsubtypes("math")) -local noadcodes = mark(getsubtypes("noad")) -local radicalcodes = mark(getsubtypes("radical")) -local accentcodes = mark(getsubtypes("accent")) -local fencecodes = mark(getsubtypes("fence")) ------ fractioncodes = mark(getsubtypes("fraction")) -local parcodes = mark(getsubtypes("par")) - -local fillvalues = mark(getvalues("fill")) -local dirvalues = mark(getvalues("dir")) -local mathvalues = mark(getvalues("math")) +local listcodes = mark(getsubtypes("list")) +local rulecodes = mark(getsubtypes("rule")) +local dircodes = mark(getsubtypes("dir")) +local markcodes = mark(getsubtypes("mark")) +local glyphcodes = mark(getsubtypes("glyph")) +local disccodes = mark(getsubtypes("disc")) +local gluecodes = mark(getsubtypes("glue")) +local boundarycodes = mark(getsubtypes("boundary")) +local penaltycodes = mark(getsubtypes("penalty")) +local kerncodes = mark(getsubtypes("kern")) +local mathcodes = mark(getsubtypes("math")) +local noadcodes = mark(getsubtypes("noad")) +local radicalcodes = mark(getsubtypes("radical")) +local accentcodes = mark(getsubtypes("accent")) +local fencecodes = mark(getsubtypes("fence")) +----- fractioncodes = mark(getsubtypes("fraction")) +local parcodes = mark(getsubtypes("par")) +local attributecodes = mark(getsubtypes("attribute")) + +local fillvalues = mark(getvalues("fill")) +local dirvalues = mark(getvalues("dir")) +local mathvalues = mark(getvalues("math")) local function simplified(t) local r = { } @@ -91,45 +92,47 @@ local noadoptions = allocate { local nodecodes = simplified(node.types()) -gluecodes = allocate(swapped(gluecodes,gluecodes)) -dircodes = allocate(swapped(dircodes,dircodes)) -markcodes = allocate(swapped(markcodes,markcodes)) -boundarycodes = allocate(swapped(boundarycodes,boundarycodes)) -noadcodes = allocate(swapped(noadcodes,noadcodes)) -radicalcodes = allocate(swapped(radicalcodes,radicalcodes)) -nodecodes = allocate(swapped(nodecodes,nodecodes)) -listcodes = allocate(swapped(listcodes,listcodes)) -glyphcodes = allocate(swapped(glyphcodes,glyphcodes)) -kerncodes = allocate(swapped(kerncodes,kerncodes)) -penaltycodes = allocate(swapped(penaltycodes,penaltycodes)) -mathcodes = allocate(swapped(mathcodes,mathcodes)) -disccodes = allocate(swapped(disccodes,disccodes)) -accentcodes = allocate(swapped(accentcodes,accentcodes)) -fencecodes = allocate(swapped(fencecodes,fencecodes)) -parcodes = allocate(swapped(parcodes,parcodes)) -rulecodes = allocate(swapped(rulecodes,rulecodes)) -noadoptions = allocate(swapped(noadoptions,noadoptions)) - -dirvalues = allocate(swapped(dirvalues,dirvalues)) -fillvalues = allocate(swapped(fillvalues,fillvalues)) -mathvalues = allocate(swapped(mathvalues,mathvalues)) - -nodes.gluecodes = gluecodes -nodes.dircodes = dircodes +gluecodes = allocate(swapped(gluecodes,gluecodes)) +dircodes = allocate(swapped(dircodes,dircodes)) +markcodes = allocate(swapped(markcodes,markcodes)) +boundarycodes = allocate(swapped(boundarycodes,boundarycodes)) +noadcodes = allocate(swapped(noadcodes,noadcodes)) +radicalcodes = allocate(swapped(radicalcodes,radicalcodes)) +nodecodes = allocate(swapped(nodecodes,nodecodes)) +listcodes = allocate(swapped(listcodes,listcodes)) +glyphcodes = allocate(swapped(glyphcodes,glyphcodes)) +kerncodes = allocate(swapped(kerncodes,kerncodes)) +penaltycodes = allocate(swapped(penaltycodes,penaltycodes)) +mathcodes = allocate(swapped(mathcodes,mathcodes)) +disccodes = allocate(swapped(disccodes,disccodes)) +accentcodes = allocate(swapped(accentcodes,accentcodes)) +fencecodes = allocate(swapped(fencecodes,fencecodes)) +parcodes = allocate(swapped(parcodes,parcodes)) +attributecodes = allocate(swapped(attributecodes,attributecodes)) +rulecodes = allocate(swapped(rulecodes,rulecodes)) +noadoptions = allocate(swapped(noadoptions,noadoptions)) + +dirvalues = allocate(swapped(dirvalues,dirvalues)) +fillvalues = allocate(swapped(fillvalues,fillvalues)) +mathvalues = allocate(swapped(mathvalues,mathvalues)) + +nodes.gluecodes = gluecodes +nodes.dircodes = dircodes nodes.markcodes = markcodes -nodes.boundarycodes = boundarycodes -nodes.noadcodes = noadcodes -nodes.listcodes = listcodes -nodes.glyphcodes = glyphcodes -nodes.kerncodes = kerncodes -nodes.penaltycodes = penaltycodes -nodes.mathcodes = mathcodes -nodes.disccodes = disccodes -nodes.accentcodes = accentcodes -nodes.radicalcodes = radicalcodes -nodes.fencecodes = fencecodes -nodes.parcodes = parcodes -nodes.rulecodes = rulecodes +nodes.boundarycodes = boundarycodes +nodes.noadcodes = noadcodes +nodes.listcodes = listcodes +nodes.glyphcodes = glyphcodes +nodes.kerncodes = kerncodes +nodes.penaltycodes = penaltycodes +nodes.mathcodes = mathcodes +nodes.disccodes = disccodes +nodes.accentcodes = accentcodes +nodes.radicalcodes = radicalcodes +nodes.fencecodes = fencecodes +nodes.parcodes = parcodes +nodes.attributecodes = attributecodes +nodes.rulecodes = rulecodes nodes.noadoptions = noadoptions nodes.fillvalues = fillvalues @@ -154,6 +157,7 @@ local subtypes = allocate { radical = radicalcodes, fence = fencecodes, par = parcodes, + attribute = attributecodes, rule = rulecodes, vlist = listcodes, diff --git a/tex/context/base/mkxl/node-ini.mkxl b/tex/context/base/mkxl/node-ini.mkxl index 101f55c05..ef5c85c5b 100644 --- a/tex/context/base/mkxl/node-ini.mkxl +++ b/tex/context/base/mkxl/node-ini.mkxl @@ -36,6 +36,7 @@ \registerctxluafile{node-acc}{autosuffix} % experimental %registerctxluafile{node-prp}{} % makes no sense (yet) \registerctxluafile{node-scn}{autosuffix} +\registerctxluafile{node-scn}{autosuffix} \registerctxluafile{node-par}{autosuffix} \registerctxluafile{node-bwc}{autosuffix} % for a while diff --git a/tex/context/base/mkxl/node-pro.lmt b/tex/context/base/mkxl/node-pro.lmt index f38e8280b..ab40dc0c1 100644 --- a/tex/context/base/mkxl/node-pro.lmt +++ b/tex/context/base/mkxl/node-pro.lmt @@ -102,9 +102,9 @@ do ----- texnest = tex.nest ----- getnest = tex.getnest - local getlist = nuts.getlist - local setlist = nuts.setlist - local getsubtype = nuts.getsubtype + local getlist = nodes.getlist -- still nodes ! + local setlist = nodes.setlist + local getsubtype = nodes.getsubtype local linelist_code = nodes.listcodes.line diff --git a/tex/context/base/mkxl/node-ref.lmt b/tex/context/base/mkxl/node-ref.lmt index 269b2e749..36715c067 100644 --- a/tex/context/base/mkxl/node-ref.lmt +++ b/tex/context/base/mkxl/node-ref.lmt @@ -528,6 +528,8 @@ local nofreferences = 0 do + -- here we can't use attributes.registervalue etc (afaiks) + local stack = { } local done = { } local attribute = attributes.private('reference') @@ -667,6 +669,8 @@ local nofdestinations = 0 do + -- here we can use attributes.registervalue etc + local stack = { } local done = { } local attribute = attributes.private('destination') diff --git a/tex/context/base/mkxl/node-rul.lmt b/tex/context/base/mkxl/node-rul.lmt index 0d1a9548e..3bf18ccf3 100644 --- a/tex/context/base/mkxl/node-rul.lmt +++ b/tex/context/base/mkxl/node-rul.lmt @@ -104,7 +104,6 @@ local implement = interfaces.implement local privateattributes = attributes.private local a_ruled = privateattributes('ruled') -local a_ruledextra = privateattributes('ruledextra') local a_runningtext = privateattributes('runningtext') local a_color = privateattributes('color') local a_transparency = privateattributes('transparency') @@ -112,6 +111,10 @@ local a_colormodel = privateattributes('colormodel') local a_linefiller = privateattributes("linefiller") local a_viewerlayer = privateattributes("viewerlayer") +local registervalue = attributes.registervalue +local getvalue = attributes.getvalue +local texsetattribute = tex.setattribute + local v_both = variables.both local v_left = variables.left local v_right = variables.right @@ -134,229 +137,234 @@ local processwords = nuts.processwords local setcoloring = nuts.colors.set -local rules = nodes.rules or { } -nodes.rules = rules -rules.data = rules.data or { } - -local nutrules = nuts.rules or { } -nuts.rules = nutrules -- not that many +do -storage.register("nodes/rules/data", rules.data, "nodes.rules.data") + local rules = nodes.rules or { } + nodes.rules = rules + -- rules.data = rules.data or { } -local data = rules.data + local nutrules = nuts.rules or { } + nuts.rules = nutrules -- not that many --- we implement user rules here as it takes less code this way + -- we implement user rules here as it takes less code this way -local function usernutrule(t,noattributes) - local r = new_userrule(t.width or 0,t.height or 0,t.depth or 0) - if noattributes == false or noattributes == nil then - -- avoid fuzzy ones - else - setattrlist(r,true) + local function usernutrule(t,noattributes) + local r = new_userrule(t.width or 0,t.height or 0,t.depth or 0) + if noattributes == false or noattributes == nil then + -- avoid fuzzy ones + else + setattrlist(r,true) + end + properties[r] = t + return r end - properties[r] = t - return r -end -nutrules.userrule = usernutrule + nutrules.userrule = usernutrule -local function userrule(t,noattributes) - return tonode(usernutrule(t,noattributes)) -end + local function userrule(t,noattributes) + return tonode(usernutrule(t,noattributes)) + end -rules.userrule = userrule -local ruleactions = { } + rules.userrule = userrule + local ruleactions = { } -rules .ruleactions = ruleactions -nutrules.ruleactions = ruleactions -- convenient + rules .ruleactions = ruleactions + nutrules.ruleactions = ruleactions -- convenient -local function mathaction(n,h,v,what) - local font = getruledata(n) - local actions = fontresources[font].mathruleactions - if actions then - local action = actions[what] - if action then - action(n,h,v,font) + local function mathaction(n,h,v,what) + local font = getruledata(n) + local actions = fontresources[font].mathruleactions + if actions then + local action = actions[what] + if action then + action(n,h,v,font) + end end end -end -local function mathradical(n,h,v) - mathaction(n,h,v,"radicalaction") -end + local function mathradical(n,h,v) + mathaction(n,h,v,"radicalaction") + end -local function mathrule(n,h,v) - mathaction(n,h,v,"hruleaction") -end + local function mathrule(n,h,v) + mathaction(n,h,v,"hruleaction") + end -local x + local x -local function useraction(n,h,v) - local p = properties[n] - if p then - local i = p.type or "draw" - local a = ruleactions[i] - if a then - a(p,h,v,i,n) + local function useraction(n,h,v) + local p = properties[n] + if p then + local i = p.type or "draw" + local a = ruleactions[i] + if a then + a(p,h,v,i,n) + end end end -end -local subtypeactions = { - [rulecodes.user] = useraction, - [rulecodes.over] = mathrule, - [rulecodes.under] = mathrule, - [rulecodes.fraction] = mathrule, - [rulecodes.radical] = mathradical, -} + local subtypeactions = { + [rulecodes.user] = useraction, + [rulecodes.over] = mathrule, + [rulecodes.under] = mathrule, + [rulecodes.fraction] = mathrule, + [rulecodes.radical] = mathradical, + } -function rules.process(n,h,v) - local n = tonut(n) -- already a nut - local s = getsubtype(n) - local a = subtypeactions[s] - if a then - a(n,h,v) + function rules.process(n,h,v) + local n = tonut(n) -- already a nut + local s = getsubtype(n) + local a = subtypeactions[s] + if a then + a(n,h,v) + end end -end --- + local trace_ruled = false trackers.register("nodes.rules", function(v) trace_ruled = v end) + local report_ruled = logs.reporter("nodes","rules") + local enabled = false -local trace_ruled = false trackers.register("nodes.rules", function(v) trace_ruled = v end) -local report_ruled = logs.reporter("nodes","rules") - -function rules.define(settings) - local nofdata = #data + 1 - data[nofdata] = settings - local text = settings.text - if text then - local b = nuts.takebox(text) - if b then - nodepool.register(b) - settings.text = getlist(b) - else - settings.text = nil + local texgetattribute = tex.getattribute + local unsetvalue = attributes.unsetvalue + + -- The setter is now the performance bottleneck but it is no longer + -- limited to a certain number of cases before we cycle resources. + + function rules.set(settings) + if not enabled then + enableaction("shipouts","nodes.rules.handler") + enabled = true + end + local text = settings.text + if text then + settings.text = tonut(text) + -- nodepool.register(text) -- todo: have a cleanup hook + end + -- todo: only when explicitly enabled + local attr = texgetattribute(a_ruled) + if attr ~= unsetvalue then + settings.nestingvalue = attr + settings.nestingdata = getvalue(a_ruled,attr) -- so still accessible when we wipe end + texsetattribute(a_ruled,registervalue(a_ruled,settings)) end - return nofdata -end -local extrarules = false -local extra = false + attributes.setcleaner(a_ruled,function(t) + local text = t.text + if text then + flushlist(text) + end + end) -function rules.enableextra() - extrarules = true -end + -- we could check the passed level on the real one ... (no need to pass level) -local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but acceptable for this purpose - local font = nil - local char, id = isglyph(f) - if char then - font = id - elseif id == hlist_code then - font = getattr(f,a_runningtext) - end - if not font then - -- saveguard ... we need to deal with rules and so (math) - return head - end - local r, m - if strip then - if trace_ruled then - local before = n_tosequence(f,l,true) - f, l = striprange(f,l) - local after = n_tosequence(f,l,true) - report_ruled("range stripper, before %a, after %a",before,after) - else - f, l = striprange(f,l) + local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but acceptable for this purpose + local level = d.stack or d.level or 1 + if level > d.max then + -- todo: trace message + return head end - end - if not f then - return head - end - local wd, ht, dp = getrangedimensions(parent,f,getnext(l)) - local method = d.method - local empty = d.empty == v_yes - local offset = d.offset - local dy = d.dy - local order = d.order - local max = d.max - local mp = d.mp - local rulethickness = d.rulethickness - local unit = d.unit - local ma = d.ma - local ca = d.ca - local ta = d.ta - local colorspace = ma > 0 and ma or getattr(f,a_colormodel) or 1 - local color = ca > 0 and ca or getattr(f,a_color) - local transparency = ta > 0 and ta or getattr(f,a_transparency) - local foreground = order == v_foreground - local layer = getattr(f,a_viewerlayer) - local e = dimenfactor(unit,font) -- what if no glyph node - local rt = tonumber(rulethickness) - if rt then - rulethickness = e * rulethickness / 2 - else - local n, u = splitdimen(rulethickness) - if n and u then -- we need to intercept ex and em and % and ... - rulethickness = n * dimenfactor(u,fontdata[font]) / 2 - else - rulethickness = 1/5 + local font = nil + local char, id = isglyph(f) + if char then + font = id + elseif id == hlist_code then + font = getattr(f,a_runningtext) end - end - -- - if level > max then - level = max - end - if method == 0 then -- center - offset = 2*offset - m = (offset+(level-1)*dy)*e/2 + rulethickness/2 - else - m = 0 - end - - local function inject(r,wd,ht,dp) - if layer then - setattr(r,a_viewerlayer,layer) + if not font then + -- saveguard ... we need to deal with rules and so (math) + return head + end + local r, m + if strip then + if trace_ruled then + local before = n_tosequence(f,l,true) + f, l = striprange(f,l) + local after = n_tosequence(f,l,true) + report_ruled("range stripper, before %a, after %a",before,after) + else + f, l = striprange(f,l) + end + end + if not f then + return head end - if empty then - head = insertnodebefore(head,f,r) - setlink(r,getnext(l)) - setprev(f) - setnext(l) - flushlist(f) + local wd, ht, dp = getrangedimensions(parent,f,getnext(l)) + local method = d.method + local empty = d.empty == v_yes + local offset = d.offset + local dy = d.dy + local order = d.order + local max = d.max + local mp = d.mp + local rulethickness = d.rulethickness + local unit = d.unit + local ma = d.ma + local ca = d.ca + local ta = d.ta + local colorspace = ma > 0 and ma or getattr(f,a_colormodel) or 1 + local color = ca > 0 and ca or getattr(f,a_color) + local transparency = ta > 0 and ta or getattr(f,a_transparency) + local foreground = order == v_foreground + local layer = getattr(f,a_viewerlayer) + local e = dimenfactor(unit,font) -- what if no glyph node + local rt = tonumber(rulethickness) + if rt then + rulethickness = e * rulethickness / 2 else - local k = new_kern(-wd) - if foreground then - insertnodeafter(head,l,k) - insertnodeafter(head,k,r) - l = r + local n, u = splitdimen(rulethickness) + if n and u then -- we need to intercept ex and em and % and ... + rulethickness = n * dimenfactor(u,fontdata[font]) / 2 else - head = insertnodebefore(head,f,r) - insertnodeafter(head,r,k) + rulethickness = 1/5 end end - if trace_ruled then - report_ruled("level %a, width %p, height %p, depth %p, nodes %a, text %a", - level,wd,ht,dp,n_tostring(f,l),n_tosequence(f,l,true)) + -- + if level > max then + level = max + end + if method == 0 then -- center + offset = 2*offset + m = (offset+(level-1)*dy)*e/2 + rulethickness/2 + else + m = 0 end - end - - local first = 1 - local last = level - if extra then - first = level - end + local function inject(r,wd,ht,dp) + if layer then + setattr(r,a_viewerlayer,layer) + end + if empty then + head = insertnodebefore(head,f,r) + setlink(r,getnext(l)) + setprev(f) + setnext(l) + flushlist(f) + else + local k = new_kern(-wd) + if foreground then + insertnodeafter(head,l,k) + insertnodeafter(head,k,r) + l = r + else + head = insertnodebefore(head,f,r) + insertnodeafter(head,r,k) + end + end + if trace_ruled then + report_ruled("level %a, width %p, height %p, depth %p, nodes %a, text %a", + level,wd,ht,dp,n_tostring(f,l),n_tosequence(f,l,true)) + end + end - if mp and mp ~= "" then - for i=first,last do + if mp and mp ~= "" then local r = usernutrule { width = wd, height = ht, depth = dp, type = "mp", factor = e, - offset = offset - (i-1)*dy, + offset = offset - (level-1)*dy, -- br ... different direction line = rulethickness, data = mp, ma = colorspace, @@ -364,364 +372,332 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a ta = transparency, } inject(r,wd,ht,dp) - end - else - local tx = d.text - if tx then - local l = copylist(tx) - if d["repeat"] == v_yes then - l = new_leader(wd,l) - setattrlist(l,tx) - end - l = hpack_nodes(l,wd,"exactly") - inject(l,wd,ht,dp) else - for i=first,last do - local hd = (offset+(i-1)*dy)*e - m + local tx = d.text + if tx then + local l = copylist(tx) + if d["repeat"] == v_yes then + l = new_leader(wd,l) + setattrlist(l,tx) + end + l = hpack_nodes(l,wd,"exactly") + inject(l,wd,ht,dp) + else + local hd = (offset+(level-1)*dy)*e - m local ht = hd + rulethickness local dp = -hd + rulethickness inject(setcoloring(new_rule(wd,ht,dp),colorspace,color,transparency),wd,ht,dp) end end + return head end - return head -end + rules.handler = function(head) + local data = attributes.values[a_ruled] + if data then + head = processwords(a_ruled,data,flush_ruled,head) -rules.handler = function(head) - extra = false - head = processwords(a_ruled,data,flush_ruled,head) - if extrarules then - extra = true - head = processwords(a_ruledextra,data,flush_ruled,head) + end + return head end - return head -end -function rules.enable() - enableaction("shipouts","nodes.rules.handler") -end - -local trace_shifted = false trackers.register("nodes.shifting", function(v) trace_shifted = v end) - -local report_shifted = logs.reporter("nodes","shifting") - -local a_shifted = attributes.private('shifted') + implement { + name = "setrule", + actions = rules.set, + arguments = { + { + { "continue" }, + { "unit" }, + { "order" }, + { "level", "integer" }, + { "stack", "integer" }, + { "method", "integer" }, + { "offset", "number" }, + { "rulethickness" }, + { "dy", "number" }, + { "max", "number" }, + { "ma", "integer" }, + { "ca", "integer" }, + { "ta", "integer" }, + { "mp" }, + { "empty" }, + { "text", "box" }, + { "repeat" }, + } + } + } -local shifts = nodes.shifts or { } -nodes.shifts = shifts -shifts.data = shifts.data or { } +end -storage.register("nodes/shifts/data", shifts.data, "nodes.shifts.data") +do -local data = shifts.data + local trace_shifted = false trackers.register("nodes.shifting", function(v) trace_shifted = v end) + local report_shifted = logs.reporter("nodes","shifting") + local a_shifted = attributes.private('shifted') + local enabled = false -function shifts.define(settings) - local nofdata = #data + 1 - data[nofdata] = settings - return nofdata -end + local shifts = nodes.shifts or { } + nodes.shifts = shifts -local function flush_shifted(head,first,last,data,level,parent,strip) -- not that fast but acceptable for this purpose - if true then - first, last = striprange(first,last) - end - local prev = getprev(first) - local next = getnext(last) - setprev(first) - setnext(last) - local width, height, depth = getrangedimensions(parent,first,next) - local list = hpack_nodes(first,width,"exactly") -- we can use a simple pack - if first == head then - head = list - end - if prev then - setlink(prev,list) + function shifts.set(settings) + if not enabled then + -- we could disable when no more found + enableaction("shipouts","nodes.shifts.handler") + enabled = true + end + texsetattribute(a_shifted,registervalue(a_shifted,settings)) end - if next then - setlink(list,next) + + local function flush_shifted(head,first,last,data,level,parent,strip) -- not that fast but acceptable for this purpose + if true then + first, last = striprange(first,last) + end + local prev = getprev(first) + local next = getnext(last) + setprev(first) + setnext(last) + local width, height, depth = getrangedimensions(parent,first,next) + local list = hpack_nodes(first,width,"exactly") -- we can use a simple pack + if first == head then + head = list + end + if prev then + setlink(prev,list) + end + if next then + setlink(list,next) + end + local raise = data.dy * dimenfactor(data.unit,fontdata[getfont(first)]) + setshift(list,raise) + setwhd(list,width,height,depth) + if trace_shifted then + report_shifted("width %p, nodes %a, text %a",width,n_tostring(first,last),n_tosequence(first,last,true)) + end + return head end - local raise = data.dy * dimenfactor(data.unit,fontdata[getfont(first)]) - setshift(list,raise) - setwhd(list,width,height,depth) - if trace_shifted then - report_shifted("width %p, nodes %a, text %a",width,n_tostring(first,last),n_tosequence(first,last,true)) + + shifts.handler = function(head) + local data = attributes.values[a_shifted] + if data then + head = processwords(a_shifted,data,flush_shifted,head) + end + return head end - return head -end -shifts.handler = function(head) - return processwords(a_shifted,data,flush_shifted,head) -end + implement { + name = "setshift", + actions = shifts.set, + arguments = { + { + { "continue" }, + { "unit" }, + { "method", "integer" }, + { "dy", "number" }, + } + } + } -function shifts.enable() - enableaction("shipouts","nodes.shifts.handler") end -- linefillers -local linefillers = nodes.linefillers or { } -nodes.linefillers = linefillers -linefillers.data = linefillers.data or { } +do -storage.register("nodes/linefillers/data", linefillers.data, "nodes.linefillers.data") + local linefillers = nodes.linefillers or { } + nodes.linefillers = linefillers + local enabled = false -local data = linefillers.data + local usernutrule = nuts.rules.userrule -function linefillers.define(settings) - local nofdata = #data + 1 - data[nofdata] = settings - return nofdata -end + function linefillers.set(settings) + if not enabled then + enableaction("finalizers","nodes.linefillers.handler") + enabled = true + end + texsetattribute(a_linefiller,registervalue(a_linefiller,settings)) + end -local function linefiller(current,data,width,location) - local height = data.height - local depth = data.depth - local mp = data.mp - local ma = data.ma - local ca = data.ca - local ta = data.ta - if mp and mp ~= "" then - return usernutrule { - width = width, - height = height, - depth = depth, - type = "mp", - line = data.rulethickness, - data = mp, - ma = ma, - ca = ca, - ta = ta, - option = location, - direction = getdirection(current), - } - else - return setcoloring(new_rule(width,height,depth),ma,ca,ta) + local function linefiller(current,data,width,location) + local height = data.height + local depth = data.depth + local mp = data.mp + local ma = data.ma + local ca = data.ca + local ta = data.ta + if mp and mp ~= "" then + return usernutrule { + width = width, + height = height, + depth = depth, + type = "mp", + line = data.rulethickness, + data = mp, + ma = ma, + ca = ca, + ta = ta, + option = location, + direction = getdirection(current), + } + else + return setcoloring(new_rule(width,height,depth),ma,ca,ta) + end end -end -function linefillers.filler(current,data,width,height,depth) - if width and width > 0 then - local height = height or data.height or 0 - local depth = depth or data.depth or 0 - if (height + depth) ~= 0 then - local mp = data.mp - local ma = data.ma - local ca = data.ca - local ta = data.ta - if mp and mp ~= "" then - return usernutrule { - width = width, - height = height, - depth = depth, - type = "mp", - line = data.rulethickness, - data = mp, - ma = ma, - ca = ca, - ta = ta, - option = location, - direction = getdirection(current), - } - else - return setcoloring(new_rule(width,height,depth),ma,ca,ta) + function linefillers.filler(current,data,width,height,depth) + if width and width > 0 then + local height = height or data.height or 0 + local depth = depth or data.depth or 0 + if (height + depth) ~= 0 then + local mp = data.mp + local ma = data.ma + local ca = data.ca + local ta = data.ta + if mp and mp ~= "" then + return usernutrule { + width = width, + height = height, + depth = depth, + type = "mp", + line = data.rulethickness, + data = mp, + ma = ma, + ca = ca, + ta = ta, + option = location, + direction = getdirection(current), + } + else + return setcoloring(new_rule(width,height,depth),ma,ca,ta) + end end end end -end -local function getskips(list) -- this could be a helper - local ls = nil - local rs = nil - local is = nil - local pl = nil - local pr = nil - local ok = false - for n, subtype in nextglue, list do - if subtype == rightskip_code then - rs = n - elseif subtype == parfillrightskip_code then - pr = n - elseif subtype == leftskip_code then - ls = n - elseif subtype == indentskip_code then - is = n - elseif subtype == parfillleftskip_code then - pl = n + local function getskips(list) -- this could be a helper + local ls = nil + local rs = nil + local is = nil + local pl = nil + local pr = nil + local ok = false + for n, subtype in nextglue, list do + if subtype == rightskip_code then + rs = n + elseif subtype == parfillrightskip_code then + pr = n + elseif subtype == leftskip_code then + ls = n + elseif subtype == indentskip_code then + is = n + elseif subtype == parfillleftskip_code then + pl = n + end end + return is, ls, pl, pr, rs end - return is, ls, pl, pr, rs -end -function linefillers.handler(head) - -- we have a normalized line .. - for current, id, subtype, list in nextlist, head do - if subtype == linelist_code and list then - local a = getattr(current,a_linefiller) - if a then - local class = a % 1000 - local data = data[class] - if data then - local location = data.location - local scope = data.scope - local distance = data.distance - local threshold = data.threshold - local leftlocal = false - local rightlocal = false - -- - if scope == v_right then - leftlocal = true - elseif scope == v_left then - rightlocal = true - elseif scope == v_local then - leftlocal = true - rightlocal = true - end - -- - local is, ls, pl, pr, rs = getskips(list) - if ls and rs then - if location == v_left or location == v_both then - local indentation = is and getwidth(is) or 0 - local leftfixed = ls and getwidth(ls) or 0 - local lefttotal = ls and effectiveglue(ls,current) or 0 - local width = lefttotal - (leftlocal and leftfixed or 0) + indentation - distance - if width > threshold then - if is then - setwidth(is,0) - end - setglue(ls,leftlocal and getwidth(ls) or nil) - if distance > 0 then - insertnodeafter(list,ls,new_kern(distance)) - end - insertnodeafter(list,ls,linefiller(current,data,width,"left")) + linefillers.handler = function(head) + local data = attributes.values[a_linefiller] + if data then + -- we have a normalized line .. + for current, id, subtype, list in nextlist, head do + if subtype == linelist_code and list then + local a = getattr(current,a_linefiller) + if a then + local data = data[a] + if data then + local location = data.location + local scope = data.scope + local distance = data.distance + local threshold = data.threshold + local leftlocal = false + local rightlocal = false + -- + if scope == v_right then + leftlocal = true + elseif scope == v_left then + rightlocal = true + elseif scope == v_local then + leftlocal = true + rightlocal = true end - end - -- - if location == v_right or location == v_both then - local rightfixed = rs and getwidth(rs) or 0 - local righttotal = rs and effectiveglue(rs,current) or 0 - local parfixed = pr and getwidth(pr) or 0 - local partotal = pr and effectiveglue(pr,current) or 0 - local width = righttotal - (rightlocal and rightfixed or 0) + partotal - distance - if width > threshold then - if pr then - setglue(pr) + -- + local is, ls, pl, pr, rs = getskips(list) + if ls and rs then + if location == v_left or location == v_both then + local indentation = is and getwidth(is) or 0 + local leftfixed = ls and getwidth(ls) or 0 + local lefttotal = ls and effectiveglue(ls,current) or 0 + local width = lefttotal - (leftlocal and leftfixed or 0) + indentation - distance + if width > threshold then + if is then + setwidth(is,0) + end + setglue(ls,leftlocal and getwidth(ls) or nil) + if distance > 0 then + insertnodeafter(list,ls,new_kern(distance)) + end + insertnodeafter(list,ls,linefiller(current,data,width,"left")) + end end - setglue(rs,rightlocal and getwidth(rs) or nil) - if distance > 0 then - insertnodebefore(list,rs,new_kern(distance)) + -- + if location == v_right or location == v_both then + local rightfixed = rs and getwidth(rs) or 0 + local righttotal = rs and effectiveglue(rs,current) or 0 + local parfixed = pr and getwidth(pr) or 0 + local partotal = pr and effectiveglue(pr,current) or 0 + local width = righttotal - (rightlocal and rightfixed or 0) + partotal - distance + if width > threshold then + if pr then + setglue(pr) + end + setglue(rs,rightlocal and getwidth(rs) or nil) + if distance > 0 then + insertnodebefore(list,rs,new_kern(distance)) + end + insertnodebefore(list,rs,linefiller(current,data,width,"right")) + end end - insertnodebefore(list,rs,linefiller(current,data,width,"right")) + else + -- error, not a properly normalized line end end - else - -- error, not a properly normalized line end end end end + return head end - return head -end - -local enable = false - -function linefillers.enable() - if not enable then - -- we could now nil it - enableaction("finalizers","nodes.linefillers.handler") - enable = true - end -end - --- interface - -implement { - name = "definerule", - actions = { rules.define, context }, - arguments = { - { - { "continue" }, - { "unit" }, - { "order" }, - { "method", "integer" }, - { "offset", "number" }, - { "rulethickness" }, - { "dy", "number" }, - { "max", "number" }, - { "ma", "integer" }, - { "ca", "integer" }, - { "ta", "integer" }, - { "mp" }, - { "empty" }, - { "text", "integer" }, - { "repeat" }, - } - } -} - -implement { - name = "enablerules", - onlyonce = true, - actions = rules.enable -} -implement { - name = "enableextrarules", - onlyonce = true, - actions = rules.enableextra -} - -implement { - name = "defineshift", - actions = { shifts.define, context }, - arguments = { - { - { "continue" }, - { "unit" }, - { "method", "integer" }, - { "dy", "number" }, - } - } -} - -implement { - name = "enableshifts", - onlyonce = true, - actions = shifts.enable -} - -implement { - name = "definelinefiller", - actions = { linefillers.define, context }, - arguments = { - { - { "method", "integer" }, - { "location", "string" }, - { "scope", "string" }, - { "mp", "string" }, - { "ma", "integer" }, - { "ca", "integer" }, - { "ta", "integer" }, - { "depth", "dimension" }, - { "height", "dimension" }, - { "distance", "dimension" }, - { "threshold", "dimension" }, - { "rulethickness", "dimension" }, + implement { + name = "setlinefiller", + actions = linefillers.set, + arguments = { + { + { "method", "integer" }, + { "location", "string" }, + { "scope", "string" }, + { "mp", "string" }, + { "ma", "integer" }, + { "ca", "integer" }, + { "ta", "integer" }, + { "depth", "dimension" }, + { "height", "dimension" }, + { "distance", "dimension" }, + { "threshold", "dimension" }, + { "rulethickness", "dimension" }, + } } } -} -implement { - name = "enablelinefillers", - onlyonce = true, - actions = linefillers.enable -} +end -- We add a bonus feature here (experiment): interfaces.implement { name = "autorule", + protected = true, + public = true, arguments = { { { "width", "dimension" }, diff --git a/tex/context/base/mkxl/node-rul.mkxl b/tex/context/base/mkxl/node-rul.mkxl index 5f9eef7cb..231a2f32b 100644 --- a/tex/context/base/mkxl/node-rul.mkxl +++ b/tex/context/base/mkxl/node-rul.mkxl @@ -74,76 +74,20 @@ \registerctxluafile{node-rul}{autosuffix,optimize} \installcorenamespace{bar} -% \installcorenamespace{barindex} -\installcorenamespace{barattribute} \installcorenamespace{barstack} \installcommandhandler \??bar {bar} \??bar -\newtoks\t_node_rules_checklist - -\mutable\let\c_node_rules_index\relax % temporary synonym (can be shared) -\mutable\let\p_node_rules_color\empty +\mutable\let\p_node_color \empty % of just \p_* +\mutable\let\p_node_text \empty +\mutable\let\p_node_offset\empty \aliased\let\setupbars\setupbar \appendtoks - \ifempty\currentbar - \the\t_node_rules_checklist - \else - \node_rules_define - \fi -\to \everysetupbar - -\appendtoks -% \ifcsname\??barindex\currentbar\endcsname -% \lastnamedcs\zerocount -% \else -% \expandafter\newcount\csname\??barindex\currentbar\endcsname -% \fi - % \normalexpanded{\t_node_rules_checklist{\node_rules_redefine{\currentbar}\the\t_node_rules_checklist}}% - \normalexpanded{\t_node_rules_checklist{\the\t_node_rules_checklist\relax\node_rules_redefine{\currentbar}}}% - % \etoksapp\t_node_rules_checklist{\node_rules_redefine{\currentbar}}% - \node_rules_define - \frozen\instance\setuevalue\currentbar{\node_rules_direct{\currentbar}}% + \frozen\protected\instance\edefcsname\currentbar\endcsname{\node_rules_direct{\currentbar}}% \to \everydefinebar -\newbox\b_node_rules - -% todo: delay mp graphic - -\protected\def\node_rules_define - {\edef\p_node_rules_color{\barparameter\c!color}% - \edef\p_node_text{\barparameter\c!text}% - \ifempty\p_node_text\else - \setbox\b_node_rules\hbox{\p_node_text}% - \fi - \expandafter\integerdef\csname\??barattribute\currentbar\endcsname - \clf_definerule - continue {\barparameter\c!continue}% - unit {\barparameter\c!unit}% - order {\barparameter\c!order}% - rulethickness {\barparameter\c!rulethickness}% - method \barparameter\c!method - max \barparameter\c!max\space % number - mp {\includeMPgraphic{\barparameter\c!mp}} - ma \c_attr_colormodel - ca \rawcolorattribute\p_node_rules_color - ta \rawtransparencyattribute\p_node_rules_color - offset \barparameter\c!offset\space % number - dy \barparameter\c!dy\space % number - empty {\barparameter\c!empty}% - \ifempty\p_node_text\else - % not that useful and efficient, more for testing something - text \b_node_rules - repeat {\barparameter\c!repeat}% - \fi - \relax - \relax} - -\protected\def\node_rules_redefine#1% - {\def\currentbar{#1}\node_rules_define} - \protected\def\node_rules_direct#1% {\groupedcommand {\node_rules_set{#1}\barparameter\c!left}% @@ -152,25 +96,6 @@ \permanent\protected\def\inlinebar[#1]% {\node_rules_direct{#1}} -% \protected\def\inlinecurrentbar -% {\node_rules_direct{\currentbar}} - -% store in properties - -% \permanent\protected\def\node_rules_set#1% maybe reverse the 1000 (also maybe use more attributes instead of settings) -% {\edef\currentbar{#1}% -% \usebarstyleandcolor\c!foregroundstyle\c!foregroundcolor -% % maybe: \usebarstyleandcolor\c!textgroundstyle\c!textcolor -% % todo: move this to lua .. we callout anyway -% \expandafter\let\expandafter\c_node_rules_index\csname\??barindex#1\endcsname -% \advance\c_node_rules_index\plusone -% \clf_enablerules % will be relaxed -% \c_attr_ruled\numexpr -% \plusthousand*\c_node_rules_index -% % optimizing this one needs testing -% +\csname\??barattribute#1\ifcsname\??bar#1:\number\c_node_rules_index\s!parent\endcsname:\number\c_node_rules_index\fi\endcsname -% \relax} - %D \overbar{Ãœber} \underbar{Unterstrich \underbar{steigt \overbar{auf} den \underbar{Unterberg}}}. %D %D \underbar {\underbar {\samplefile{tufte}}}\par @@ -181,49 +106,44 @@ %D \underbar {\underdots{\samplefile{tufte}}}\par %D \underdots{\underdots{\samplefile{tufte}}}\par -\newcount \c_node_rules_index -\integerdef \c_node_rules_used \zerocount -\mutable\let\m_node_rules_previous_bar\empty +\newcount\c_node_rules_nesting % todo: same as colors +\newcount\c_node_rules_level +\newcount\c_node_rules_up +\newcount\c_node_rules_down -\permanent\protected\def\node_rules_set#1% maybe reverse the 1000 (also maybe use more attributes instead of settings) - {\let\m_node_rules_previous_bar\currentbar - \edef\currentbar{#1}% +\permanent\protected\def\node_rules_set#1% + {\edef\currentbar{#1}% + \advance\c_node_rules_level\plusone \usebarstyleandcolor\c!foregroundstyle\c!foregroundcolor - % maybe: \usebarstyleandcolor\c!textgroundstyle\c!textcolor - % todo: move this to lua .. we callout anyway - % \expandafter\let\expandafter\c_node_rules_index\csname\??barindex#1\endcsname - \advance\c_node_rules_index\plusone - \clf_enablerules % will be relaxed - \edef\p_level{\barparameter\c!level}% - \ifx\p_level\v!yes - \integerdef\c_node_rules_used\c_node_rules_index - \c_attr_ruled - \orelse\ifx\p_level\v!auto - \integerdef\c_node_rules_used\c_node_rules_index - \ifempty\m_node_rules_previous_bar - \c_attr_ruled - \orelse\ifx\m_node_rules_previous_bar\currentbar - \c_attr_ruled - \else - \clf_enableextrarules % will be relaxed - \c_attr_ruledextra + \edef\p_node_color {\barparameter\c!color}% todo + \edef\p_node_text {\barparameter\c!text}% + \edef\p_node_offset{\barparameter\c!offset}% + % better is a dedicated key: up/down .. todo + \advance\ifdim\p_node_offset\onepoint<\zeropoint\c_node_rules_down\else\c_node_rules_up\fi\plusone + \clf_setrule + continue {\barparameter\c!continue}% + unit {\barparameter\c!unit}% + order {\barparameter\c!order}% + level \c_node_rules_level + stack \ifdim\p_node_offset\onepoint<\zeropoint\c_node_rules_down\else\c_node_rules_up\fi + rulethickness {\barparameter\c!rulethickness}% + method \barparameter\c!method + max \barparameter\c!max\space % number + mp {\includeMPgraphic{\barparameter\c!mp}} + ma \c_attr_colormodel + ca \rawcolorattribute\p_node_color + ta \rawtransparencyattribute\p_node_color + offset \p_node_offset\space % number + dy \barparameter\c!dy\space % number, also fraction + empty {\barparameter\c!empty}% + \ifempty\p_node_text\else + text \hbox{\p_node_text}% + repeat {\barparameter\c!repeat}% \fi - \orelse\ifchknum\p_level\or - \integerdef\c_node_rules_used\p_level - \c_attr_ruled - \else - \integerdef\c_node_rules_used\c_node_rules_index - \c_attr_ruled - \fi - \numexpr - \plusthousand*\c_node_rules_used - % optimizing this one needs testing - +\csname\??barattribute#1\ifcsname\??bar#1:\number\c_node_rules_index\s!parent\endcsname:\number\c_node_rules_used\fi\endcsname \relax} \permanent\protected\def\resetbar - {\c_attr_ruled \attributeunsetvalue - \c_attr_ruledextra\attributeunsetvalue} + {\c_attr_ruled\attributeunsetvalue} \permanent\protected\def\nobar {\groupedcommand @@ -248,13 +168,11 @@ % ungrouped % todo: use the lua based stacker -\newcount\c_node_rules_nesting % todo: same as colors - \permanent\protected\def\pushbar[#1]% {\global\advance\c_node_rules_nesting\plusone \edefcsname\??barstack\number\c_node_rules_nesting\endcsname - {\c_attr_ruled \the\c_attr_ruled - \c_attr_ruledextra\the\c_attr_ruledextra}% + {\c_node_rules_level\the\c_node_rules_level + \c_attr_ruled \the\c_attr_ruled}% \node_rules_set{#1}} \permanent\protected\def\popbar @@ -415,59 +333,25 @@ %D This will move: (a bit duplicated) \installcorenamespace{shift} -\installcorenamespace{shiftindex} -\installcorenamespace{shiftattribute} \installcommandhandler \??shift {shift} \??shift -\newtoks\t_node_shifts_checklist - -\mutable\let\c_node_shifts_index\relax % temporary synonym (can be shared) - \let\setupshifts\setupshift \appendtoks - \ifempty\currentshift - \the\t_node_shifts_checklist - \else - \node_shifts_define - \fi -\to \everysetupshift - -\appendtoks - \ifcsname\??shiftindex\currentshift\endcsname - \lastnamedcs\zerocount - \else - \expandafter\newcount\csname\??shiftindex\currentshift\endcsname - \fi - \normalexpanded{\t_node_shifts_checklist{\the\t_node_shifts_checklist\node_shifts_redefine{\currentshift}}}% order ? - \node_shifts_define - \frozen\instance\setuevalue\currentshift{\node_shifts_direct{\currentshift}}% + \frozen\protected\instance\edefcsname\currentshift\endcsname{\node_shifts_direct{\currentshift}}% \to \everydefineshift -\protected\def\node_shifts_define - {\edefcsname\??shiftattribute\currentshift\endcsname{\number - \clf_defineshift - continue {\shiftparameter\c!continue}% - unit {\shiftparameter\c!unit}% - method \shiftparameter\c!method - dy \shiftparameter\c!dy % number - \relax}} - -\protected\def\node_shifts_redefine#1% - {\def\currentshift{#1}\node_shifts_define} - \protected\def\node_shifts_set#1% todo: check parent ! todo: move attr etc to lua {\def\currentshift{#1}% - \expandafter\let\expandafter\c_node_shifts_index\csname\??shiftindex#1\endcsname - \advance\c_node_shifts_index\plusone - \clf_enableshifts % will be relaxed - \c_attr_shifted\numexpr - \plusthousand*\c_node_shifts_index - +\csname\??shiftattribute#1\ifcsname\??shift#1:\number\c_node_shifts_index\s!parent\endcsname:\number\c_node_shifts_index\fi\endcsname - \relax \useshiftstyleandcolor\c!style\c!color - \dosetupisolatedalign{\shiftparameter\c!align}} % weird feature that i probably needed once + \dosetupisolatedalign{\shiftparameter\c!align}% a weird feature that i probably needed once + \clf_setshift + continue {\shiftparameter\c!continue}% + unit {\shiftparameter\c!unit}% + method \shiftparameter\c!method + dy \shiftparameter\c!dy % number + \relax} \permanent\protected\def\startshift[#1]% {\begingroup @@ -497,8 +381,8 @@ % we want these always so ... -\expandafter\let\expandafter\shiftup \csname\v!shiftup \endcsname -\expandafter\let\expandafter\shiftdown \csname\v!shiftdown \endcsname +\expandafter\let\expandafter\shiftup \csname\v!shiftup \endcsname +\expandafter\let\expandafter\shiftdown\csname\v!shiftdown\endcsname % This is a weird helper.. these might go away: @@ -522,67 +406,29 @@ % Phillips on drums). The Amsterdam concert is equally energizing. \installcorenamespace{linefiller} -\installcorenamespace{linefillerindex} -\installcorenamespace{linefillerattribute} \installcommandhandler \??linefiller {linefiller} \??linefiller \definesystemattribute[linefiller][public] -\newtoks\t_node_linefiller_checklist - -\mutable\let\c_node_linefiller_index\relax % temporary synonym (can be shared) - \aliased\let\setuplinefillers\setuplinefiller -\appendtoks - \ifempty\currentlinefiller - \the\t_node_linefiller_checklist - \else - \node_linefiller_define - \fi -\to \everysetuplinefiller - -\appendtoks - \ifcsname\??linefillerindex\currentlinefiller\endcsname - \lastnamedcs\zerocount - \else - \expandafter\newcount\csname\??linefillerindex\currentlinefiller\endcsname - \fi - \etoksapp\t_node_linefiller_checklist{\t_node_linefiller_checklist\node_linefiller_redefine{\currentlinefiller}}% - \node_linefiller_define -\to \everydefinelinefiller - -\protected\def\node_linefiller_define - {\edef\p_node_rules_color{\linefillerparameter\c!color}% - \expandafter\integerdef\csname\??linefillerattribute\currentlinefiller\endcsname - \clf_definelinefiller +\protected\def\node_linefiller_set#1% todo: check parent ! todo: move attr etc to lua + {\def\currentlinefiller{#1}% + \edef\p_node_color{\linefillerparameter\c!color}% + \clf_setlinefiller %method \linefillerparameter\c!method location {\linefillerparameter\c!location}% scope {\linefillerparameter\c!scope}% mp {\includeMPgraphic{\linefillerparameter\c!mp}}% ma \c_attr_colormodel - ca \rawcolorattribute\p_node_rules_color - ta \rawtransparencyattribute\p_node_rules_color + ca \rawcolorattribute\p_node_color + ta \rawtransparencyattribute\p_node_color height \dimexpr\linefillerparameter\c!height\relax depth \dimexpr\linefillerparameter\c!depth\relax distance \dimexpr\linefillerparameter\c!distance\relax threshold \dimexpr\linefillerparameter\c!threshold\relax rulethickness \dimexpr\linefillerparameter\c!rulethickness\relax - \relax - \relax} - -\protected\def\node_linefiller_redefine#1% - {\def\currentlinefiller{#1}\node_linefiller_define} - -\protected\def\node_linefiller_set#1% todo: check parent ! todo: move attr etc to lua - {\def\currentlinefiller{#1}% - \expandafter\let\expandafter\c_node_linefiller_index\csname\??linefillerindex#1\endcsname - \advance\c_node_linefiller_index\plusone - \clf_enablelinefillers - \c_attr_linefiller\numexpr - \plusthousand*\c_node_linefiller_index - +\csname\??linefillerattribute#1\ifcsname\??linefiller#1:\number\c_node_linefiller_index\s!parent\endcsname:\number\c_node_linefiller_index\fi\endcsname \relax} \permanent\tolerant\protected\def\startlinefiller[#1]#*[#2]% @@ -653,7 +499,6 @@ \node_linefiller_set{#3}% already sets the attribute #1% attr \backgroundattribute \plusone - % attr \linefillerattribute \the\c_attr_linefiller {\box\nextbox}% \egroup}% #2} @@ -664,6 +509,6 @@ %D Bonus: -\permanent\protected\def\autorule{\clf_autorule} % todo: public implementor +% \autorule : defined at the lua end \protect \endinput diff --git a/tex/context/base/mkxl/node-scn.lmt b/tex/context/base/mkxl/node-scn.lmt index 947b9e25c..1530174c2 100644 --- a/tex/context/base/mkxl/node-scn.lmt +++ b/tex/context/base/mkxl/node-scn.lmt @@ -41,6 +41,8 @@ local userskip_code = gluecodes.userskip local spaceskip_code = gluecodes.spaceskip local xspaceskip_code = gluecodes.xspaceskip local leaders_code = gluecodes.leaders +local rightfillskip_code = gluecodes.rightparfillskip +local righthangskip_code = gluecodes.righthangskip local fontkern_code = kerncodes.fontkern @@ -111,13 +113,15 @@ nuts.striprange = striprange -- todo: switching inside math --- handlers +-- handlers (some are very specialized and demanding) -local function processwords(attribute,data,flush,head,parent,skip) -- we have hlistdir and local dir +local maxlevel = 1 + +local function processwords(nesting,attribute,data,flush,head,parent,skip) -- we have hlistdir and local dir local n = head if n then - local f, l, a, d, i, class - local continue, leaders, strip, level = false, false, false, true, -1 + local f, l, a, d, class + local continue, leaders, strip, level = false, false, true, -1 while n do local id = getid(n) if id == glyph_code @@ -127,6 +131,36 @@ local function processwords(attribute,data,flush,head,parent,skip) -- we have hl or id == boundary_code then local aa = getattr(n,attribute) + -- new approach + local dd, ll + if aa then + dd = data[aa] + ll = dd.level or 1 + if nesting == 1 and ll > maxlevel then + maxlevel = ll + end + if ll == nesting then + -- we're okay + else + while true do + local nestingvalue = dd.nestingvalue + if nestingvalue then + dd = dd.nestingdata + ll = dd.level + if ll == nesting then + aa = nestingvalue + break + end + else + -- no matching level found + aa = nil + dd = nil + break + end + end + end + end + -- old approach if aa and aa ~= skip then if aa == a then if not f then -- ? @@ -134,99 +168,121 @@ local function processwords(attribute,data,flush,head,parent,skip) -- we have hl end l = n else - -- possible extensions: when in same class then keep spanning - local newlevel, newclass = floor(aa/1000), aa%1000 -- will be configurable - -- strip = not continue or level == 1 -- 0 if f then - if class == newclass then -- and newlevel > level then - head = flush(head,f,l,d,level,parent,false), true + if class == aa then -- and newlevel > level then + head = flush(head,f,l,d,level,parent,false) else - head = flush(head,f,l,d,level,parent,strip), true + head = flush(head,f,l,d,level,parent,strip) end end f, l, a = n, n, aa - level, class = newlevel, newclass - d = data[class] + d = dd + class = aa if d then - local c = d.continue - leaders = c == v_all - continue = leaders or c == v_yes + continue = d.continue + level = d.level or 1 + leaders = continue == v_all + continue = leaders or continue == v_yes else continue = true + level = 1 + leaders = false end end else if f then - head = flush(head,f,l,d,level,parent,strip), true + head = flush(head,f,l,d,level,parent,strip) end f, l, a = nil, nil, nil end if id == hlist_code then local list = getlist(n) if list then - setlist(n,processwords(attribute,data,flush,list,n,aa)) + setlist(n,processwords(nesting,attribute,data,flush,list,n,aa)) end end --- elseif id == disc_code or id == boundary_code then --- if f then --- l = n --- end - elseif id == kern_code and getsubtype(n) == fontkern_code then - if f then - l = n + goto next + -- elseif id == disc_code or id == boundary_code then + -- if f then + -- l = n + -- end + -- goto next + elseif id == kern_code then + if getsubtype(n) == fontkern_code then + if f then + l = n + end + goto next + else + goto rest end elseif id == math_code then -- otherwise not consistent: a $b$ c vs a $b+c$ d etc -- we need a special (optional) go over math variant if f then - head = flush(head,f,l,d,level,parent,strip), true + head = flush(head,f,l,d,level,parent,strip) f, l, a = nil, nil, nil end + goto next elseif id == hlist_code or id == vlist_code then if f then - head = flush(head,f,l,d,level,parent,strip), true + head = flush(head,f,l,d,level,parent,strip) f, l, a = nil, nil, nil end local list = getlist(n) if list then - setlist(n,processwords(attribute,data,flush,list,n,skip)) + setlist(n,processwords(nesting,attribute,data,flush,list,n,skip)) end + goto next elseif id == dir_code then -- only changes in dir, we assume proper boundaries if f then l = n end - elseif f then + goto next + end + ::rest:: + if f then if continue then if id == penalty_code then l = n + goto next -- elseif id == kern_code then -- l = n + -- goto next elseif id == glue_code then -- catch \underbar{a} \underbar{a} (subtype test is needed) local subtype = getsubtype(n) if getattr(n,attribute) and (subtype == userskip_code or subtype == spaceskip_code or subtype == xspaceskip_code or (leaders and subtype >= leaders_code)) then l = n else - head = flush(head,f,l,d,level,parent,strip), true + head = flush(head,f,l,d,level,parent,strip) f, l, a = nil, nil, nil end end else - head = flush(head,f,l,d,level,parent,strip), true + head = flush(head,f,l,d,level,parent,strip) f, l, a = nil, nil, nil end end + ::next:: n = getnext(n) end if f then - head = flush(head,f,l,d,level,parent,strip), true + head = flush(head,f,l,d,level,parent,strip) end end return head end nuts.processwords = function(attribute,data,flush,head,parent) -- we have hlistdir and local dir - return processwords(attribute,data,flush,head,parent) + -- print("processing words at level "..1)io.flush() + maxlevel = 1 + head = processwords(1,attribute,data,flush,head,parent) + for i=2,maxlevel do + -- print("processing words at level "..i)io.flush() + head = processwords(i,attribute,data,flush,head,parent) + end + return head end -- works on lines ! @@ -240,7 +296,7 @@ local function processranges(attribute,flush,head,parent,depth,skip) local id = getid(n) if id == glyph_code or id == rule_code then local aa = getattr(n,attribute) --- if aa and (not skip or aa ~= skip) then + -- if aa and (not skip or aa ~= skip) then if aa then if aa == a then if not f then @@ -249,13 +305,13 @@ local function processranges(attribute,flush,head,parent,depth,skip) l = n else if f then - head = flush(head,f,l,a,parent,depth), true + head = flush(head,f,l,a,parent,depth) end f, l, a = n, n, aa end else if f then - head = flush(head,f,l,a,parent,depth), true + head = flush(head,f,l,a,parent,depth) end f, l, a = nil, nil, nil end @@ -265,16 +321,21 @@ local function processranges(attribute,flush,head,parent,depth,skip) else -- weird end - elseif id == kern_code and getsubtype(n) == fontkern_code then - if f then - l = n + elseif id == kern_code then + if getsubtype(n) == fontkern_code then + if f then + l = n + end end -- elseif id == penalty_code then elseif id == glue_code then -- todo: leaders +-- if getsubtype(n) == rightfillskip_code or getsubtype(n) == righthangskip_code then +-- break +-- end elseif id == hlist_code or id == vlist_code then local aa = getattr(n,attribute) --- if aa and (not skip or aa ~= skip) then + -- if aa and (not skip or aa ~= skip) then if aa then if aa == a then if not f then @@ -301,7 +362,7 @@ local function processranges(attribute,flush,head,parent,depth,skip) n = getnext(n) end if f then - head = flush(head,f,l,a,parent,depth), true + head = flush(head,f,l,a,parent,depth) end end return head diff --git a/tex/context/base/mkxl/node-ser.lmt b/tex/context/base/mkxl/node-ser.lmt index 333784803..089009260 100644 --- a/tex/context/base/mkxl/node-ser.lmt +++ b/tex/context/base/mkxl/node-ser.lmt @@ -39,12 +39,11 @@ local canbezero = { } local canbelist = { - attribute = "<attribute>", - node = "<node>", - token = "<token>", - attribute_list = "<attributes>", - node_list = "<nodes>", - token_list = "<tokens>", + attribute = "<attribute>", + node = "<node>", + token = "<token>", + node_list = "<nodes>", + token_list = "<tokens>", } local canbeignored = { @@ -68,10 +67,12 @@ nodes.fieldtypes = fieldtypes local function astable(n) n = tonode(n) if n then - local fields = fieldtypes[n.id] + local id = n.id + local fields = fieldtypes[id] if fields then - local result = { } - for field, fieldtype in sortedhash(fields) do + local subtype = n.subtype + local result = { } + for field, fieldtype in sortedhash(fields) do -- no need to sort local value = n[field] if value then if canbeignored[field] then @@ -86,16 +87,12 @@ local function astable(n) end end end - local id = n.id - if id then - id = nodecodes[id] - result.id = id - local subtype = n.subtype - if subtype then - local subtypes = subtypes[id] - if subtypes then - result.subtype = subtypes[subtype] - end + id = nodecodes[id] + result.id = id + if subtype then + local subtypes = subtypes[id] + if subtypes then + result.subtype = subtypes[subtype] end end return result @@ -119,7 +116,7 @@ local function to_table(n,flat,verbose,noattributes,done) for field, fieldtype in sortedhash(fields) do local value = n[field] if value then - if fieldtype == "attributelist" or fieldtype == "attribute" or fieldtype == "attribute_list" then + if fieldtype == "attribute" then if noattributes then result[value] = canbeignored[value] else diff --git a/tex/context/base/mkxl/node-tra.lmt b/tex/context/base/mkxl/node-tra.lmt index 214c8a27c..1ef1bb8ad 100644 --- a/tex/context/base/mkxl/node-tra.lmt +++ b/tex/context/base/mkxl/node-tra.lmt @@ -481,6 +481,8 @@ end number.todimen = numbertodimen nodes .todimen = nodetodimen +-- todo: dk + function number.topoints (n,fmt) return numbertodimen(n,"pt",fmt) end function number.toinches (n,fmt) return numbertodimen(n,"in",fmt) end function number.tocentimeters (n,fmt) return numbertodimen(n,"cm",fmt) end diff --git a/tex/context/base/mkxl/node-tsk.lmt b/tex/context/base/mkxl/node-tsk.lmt index ca18c9c3b..c1cdf91a4 100644 --- a/tex/context/base/mkxl/node-tsk.lmt +++ b/tex/context/base/mkxl/node-tsk.lmt @@ -679,17 +679,32 @@ return function(head) end ]], +-- process = [[ +-- local tonut = nodes.tonut +-- local tonode = nodes.nuts.tonode +-- +-- %localize% +-- +-- return function(head,groupcode) +-- local nuthead = tonut(head) +-- +-- return function(nuthead,groupcode) +-- +-- %actions% +-- return tonode(nuthead) +-- end +-- ]], + process = [[ local tonut = nodes.tonut local tonode = nodes.nuts.tonode %localize% -return function(head,groupcode) - local nuthead = tonut(head) +return function(nuthead,groupcode) %actions% - return tonode(nuthead) + return nuthead end ]], diff --git a/tex/context/base/mkxl/pack-box.mkxl b/tex/context/base/mkxl/pack-box.mkxl index 77b0bbc69..43934f7f7 100644 --- a/tex/context/base/mkxl/pack-box.mkxl +++ b/tex/context/base/mkxl/pack-box.mkxl @@ -465,7 +465,7 @@ \permanent\tolerant\protected\def\ornamenttext[#1]#*[#2]% takes another argument {\bgroup - \doifelseassignment{#1} + \doifelseassignment{#1}% {\letdummyparameter\c!alternative\v!a \getdummyparameters[#1]% \doifelse{\directdummyparameter\c!alternative}\v!a diff --git a/tex/context/base/mkxl/page-imp.mkxl b/tex/context/base/mkxl/page-imp.mkxl index 8271d7aad..4ef318985 100644 --- a/tex/context/base/mkxl/page-imp.mkxl +++ b/tex/context/base/mkxl/page-imp.mkxl @@ -189,7 +189,8 @@ \fi \clf_shipoutpage#1\relax \global\setbox#1\emptybox - \global\deadcycles\zerocount} + \global\deadcycles\zerocount + \clf_cleanupattributes} \def\page_shipouts_normal#1% {\global\advance\shippedoutpages\plusone diff --git a/tex/context/base/mkxl/page-one.mkxl b/tex/context/base/mkxl/page-one.mkxl index e8f873422..61f9172ea 100644 --- a/tex/context/base/mkxl/page-one.mkxl +++ b/tex/context/base/mkxl/page-one.mkxl @@ -363,7 +363,7 @@ \noffloatinserts\zerocount \let\totaltopinserted\!!zeropoint \page_one_command_set_top_insertions_indeed - \ifnum\rootfloatparameter\c!nbottom=\zerocount + \ifnum\rootfloatparameter\c!nbottom=\zerocount % \ifnum\c_page_floats_n_of_bottom=\zerocount \ifnum\rootfloatparameter\c!nlines>\zerocount \ifdim\totaltopinserted>\zeropoint\relax \ifdim\dimexpr\rootfloatparameter\c!nlines\lineheight+\totaltopinserted\relax>\textheight @@ -440,7 +440,6 @@ \page_one_command_set_bottom_insertions_indeed} \protected\def\page_one_command_flush_top_insertions -% {\ifvoid\namedinsertionnumber\s!topfloat\else {\ifzeropt\page_inserts_get_height\namedinsertionnumber\s!topfloat\else \page_one_command_flush_top_insertions_indeed % less tracing \fi @@ -463,7 +462,6 @@ \fi} \protected\def\page_one_command_flush_bottom_insertions -% {\ifvoid\namedinsertionnumber\s!bottomfloat\else {\ifzeropt\page_inserts_get_height\namedinsertionnumber\s!bottomfloat\else \page_one_command_flush_bottom_insertions_indeed \fi @@ -472,13 +470,13 @@ \def\page_one_command_flush_bottom_insertions_indeed {\ifgridsnapping - % \floatparameter\c!bottombefore + % \rootfloatparameter\c!bottombefore \snaptogrid\hbox{\page_inserts_get_boxed\namedinsertionnumber\s!bottomfloat}% - % \floatparameter\c!bottomafter + % \rootfloatparameter\c!bottomafter \else - \floatparameter\c!bottombefore + \rootfloatparameter\c!bottombefore \page_inserts_get_unboxed\namedinsertionnumber\s!bottomfloat - \floatparameter\c!bottomafter + \rootfloatparameter\c!bottomafter \fi} \protected\def\page_one_command_flush_floats diff --git a/tex/context/base/mkxl/page-sid.mkxl b/tex/context/base/mkxl/page-sid.mkxl index 052b3ee11..fb1022c2a 100644 --- a/tex/context/base/mkxl/page-sid.mkxl +++ b/tex/context/base/mkxl/page-sid.mkxl @@ -429,16 +429,28 @@ % \fi % \page_otr_command_set_vsize} % new +% test case: +% +% \starttext +% \strut\vskip180mm \input ward +% \subject{Test} +% \placefigure[right,none]{none}{\blackrule[width=4cm,height=3cm]} test +% \stoptext + \protected\def\page_sides_force_depth {\iftracesidefloats \enabletrackers[otr.forcestrutdepth]% \c_page_force_strut_depth_trace_mode\plusone \fi % flush what we have and check \forcestrutdepth - % trigger pagebuilder - % \penalty\zerocount - \pageboundary - % catch up + % trigger pagebuilder, \pageboundary gives nicer tracing + \iffalse + \penalty\zerocount % works too + \else + %\tracingpages\plusone \tracingonline\plustwo + \pageboundary % becomes a penalty (after triggering the callback) (experimental!) + %\tracingpages\zerocount + \fi \page_otr_command_set_vsize} % new, no longer really needed \def\page_sides_flush_floats diff --git a/tex/context/base/mkxl/spac-ali.mkxl b/tex/context/base/mkxl/spac-ali.mkxl index 6e16614aa..085ed143a 100644 --- a/tex/context/base/mkxl/spac-ali.mkxl +++ b/tex/context/base/mkxl/spac-ali.mkxl @@ -570,28 +570,58 @@ \c_spac_align_state_direction \zerocount % what is default ? \c_spac_align_state_page \zerocount \c_spac_align_state_par_fill \zerocount - \ifcsname\??aligncommand\m_spac_align_asked\endcsname + \ifcsname\??aligncommand\m_spac_align_named\endcsname \lastnamedcs \else \rawprocesscommacommand[\m_spac_align_asked]\spac_align_collect \fi - \normalexpanded{\t_spac_align_collected - {\setfalse\raggedonelinerstate % bad - \the\t_spac_align_collected - \spac_align_flush_horizontal - \spac_align_flush_vertical - \spac_align_flush_direction - \spac_align_flush_page - \spac_align_flush_parfill - }}% kept, nice for tracing + % % kept, nice for tracing + % + % \normalexpanded{\t_spac_align_collected + % {\setfalse\raggedonelinerstate % bad + % \the\t_spac_align_collected + % \spac_align_flush_horizontal + % \spac_align_flush_vertical + % \spac_align_flush_direction + % \spac_align_flush_page + % \spac_align_flush_parfill + % }}% + % + % \etoksapp\t_spac_align_collected + % {\spac_align_flush_horizontal + % \spac_align_flush_vertical + % \spac_align_flush_direction + % \spac_align_flush_page + % \spac_align_flush_parfill}% + % \etokspre\t_spac_align_collected + % {\setfalse\raggedonelinerstate}% bad + % + \etoks\t_spac_align_collected + {\setfalse\raggedonelinerstate % bad + \the\t_spac_align_collected + \spac_align_flush_horizontal + \spac_align_flush_vertical + \spac_align_flush_direction + \spac_align_flush_page + \spac_align_flush_parfill}% + % \enforced\permanent\protected\edef\raggedcommand {\the\t_spac_align_collected }% \enforced\permanent\protected\edef\updateraggedskips{\spac_align_flush_horizontal}% - \enforced\aliased\gletcsname\??alignmentnormalcache\m_spac_align_asked\endcsname\raggedcommand - \enforced\aliased\gletcsname\??alignmentraggedcache\m_spac_align_asked\endcsname\updateraggedskips} + \enforced\aliased\gletcsname\??alignmentnormalcache\m_spac_align_named\endcsname\raggedcommand + \enforced\aliased\gletcsname\??alignmentraggedcache\m_spac_align_named\endcsname\updateraggedskips} + +\mutable\def\m_spac_align_named{\m_spac_align_asked} \def\spac_align_collect#1% {\csname\??aligncommand#1\endcsname} +\permanent\protected\tolerant\def\definealign[#1]#*[#2]% + {\pushmacro\m_spac_align_named + \edef\m_spac_align_named{#1}% + \edef\m_spac_align_asked{#2}% + \spac_align_add_to_cache + \popmacro\m_spac_align_named} + % The local (key driven) setter: \permanent\protected\def\spac_align_prepare#1% deferred @@ -655,7 +685,7 @@ % Maybe we need something different in columns. \permanent\protected\def\installalign#1#2% beware: commands must be unexpandable! - {\ifcsname\??aligncommand#1\endcsname \else + {\ifcsname\??aligncommand#1\endcsname \else % : so maybe we should use \etoksapp \defcsname\??aligncommand#1\endcsname{\toksapp\t_spac_align_collected{#2}}% \fi} diff --git a/tex/context/base/mkxl/spac-ver.lmt b/tex/context/base/mkxl/spac-ver.lmt index 3faa15c77..955d65f4f 100644 --- a/tex/context/base/mkxl/spac-ver.lmt +++ b/tex/context/base/mkxl/spac-ver.lmt @@ -98,7 +98,6 @@ local v_blines = variables.blines local trace_vbox_vspacing = false trackers.register("vspacing.vbox", function(v) trace_vbox_vspacing = v end) local trace_page_vspacing = false trackers.register("vspacing.page", function(v) trace_page_vspacing = v end) -local trace_page_builder = false trackers.register("builders.page", function(v) trace_page_builder = v end) local trace_collect_vspacing = false trackers.register("vspacing.collect", function(v) trace_collect_vspacing = v end) local trace_vspacing = false trackers.register("vspacing.spacing", function(v) trace_vspacing = v end) local trace_vsnapping = false trackers.register("vspacing.snapping", function(v) trace_vsnapping = v end) @@ -128,6 +127,8 @@ local getlist = nuts.getlist local setlist = nuts.setlist local getattr = nuts.getattr local setattr = nuts.setattr +local setattrs = nuts.setattrs +local getattrs = nuts.getattrs local getsubtype = nuts.getsubtype local getbox = nuts.getbox local getwhd = nuts.getwhd @@ -185,6 +186,7 @@ local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local rule_code = nodecodes.rule local par_code = nodecodes.par +local boundary_code = nodecodes.boundary local userskip_code = gluecodes.userskip local lineskip_code = gluecodes.lineskip @@ -735,28 +737,57 @@ storage.register("builders/vspacing/data/skip", vspacingdata.skip, "builders.vsp local setspecification, getspecification --- attributes : more overhead : feels faster than properties --- properties : more natural : feels slower than attributes --- data : more native : is little faster than attributes +-- 1 statepool : 2 : more overhead : a bit slower than properties +-- 2 attributes : 1 : more overhead : feels faster than properties +-- 3 properties : 3 : more natural : feels slower than attributes +-- 4 data : 1 : more native : is little faster than attributes (limited penalty) -if true then --- if false then +-- testfile: t:/bugs/bottomfloats-001.tex - -- quite okay but more memory due to attributes (not many) +local method = 1 -- better tracing +-- local method = 2 +-- local method = 3 +-- local method = 4 + +if method == 1 then + + local registervalue = attributes.registervalue + local getvalue = attributes.getvalue + local values = attributes.values + + setspecification = function(n,category,penalty,order) + local detail = { category, penalty, order or 1 } + local value = registervalue(a_skipcategory,detail) + setattr(n,a_skipcategory,value) + end + + getspecification = function(n) + local value = getattr(n,a_skipcategory) + if value then + local detail = getvalue(a_skipcategory,value) + -- local detail = attributes.values[a_skipcategory][value] + -- local detail = values[a_skipcategory][value] + if detail then + return detail[1], detail[2], detail[3] + end + end + return false, false, 1 + end + +elseif method == 2 then - local setattrs = nuts.setattrs - local getattrs = nuts.getattrs + -- quite okay but more memory due to attributes (not many) setspecification = function(n,category,penalty,order) - setattrs(n,false,a_skipcategory,category,a_skippenalty,penalty,a_skiporder,order or 1) + setattrs(n,false,a_skipcategory,category or nil,a_skippenalty,penalty or nil,a_skiporder,order or 1) end getspecification = function(n) - return getattrs(n,a_skipcategory,a_skippenalty,a_skiporder) + local c, p, o = getattrs(n,a_skipcategory,a_skippenalty,a_skiporder) + return c or false, p or false, o or 1 end --- elseif true then -elseif false then +elseif method == 3 then -- more natural as we stay in lua @@ -776,7 +807,7 @@ elseif false then end end -else +elseif method == 4 then -- quite efficient but needs testing because we limit values @@ -1460,7 +1491,11 @@ do return remove_node(head,current,true) end + -- where -> scope + -- what -> where (original context) + local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also pass tail + if trace then reset_tracing(head) end @@ -1483,10 +1518,11 @@ do local pagetail -- -- todo: keep_together: between headers + -- todo: make this nicer in the engine -- local function getpagelist() if not pagehead then - pagehead = texlists.pagehead + pagehead = texlists.pagehead -- pagehead, pagetail = tex.getlist("pagehead") if pagehead then pagehead = tonut(pagehead) pagetail = find_node_tail(pagehead) -- no texlists.page_tail yet-- no texlists.page_tail yet @@ -1494,6 +1530,12 @@ do end end -- + -- local function getpagelist() + -- if not pagehead then + -- pagehead, pagetail = texgetlist("pagehead") + -- end + -- end + -- local function compensate(n) local g = 0 while n and getid(n) == glue_code do @@ -1971,7 +2013,7 @@ do local next = getnext(current) -- if next and getattr(next,a_skipcategory) == notopskip then if next and getspecification(next) == notopskip then - nuts.setglue(current) -- zero + setglue(current) -- zero end if snap then local s = getattr(current,a_snapmethod) @@ -2084,7 +2126,7 @@ do glue_data = nil elseif tail then setlink(tail,glue_data) -setnext(glue_data) + setnext(glue_data) else head = glue_data end @@ -2115,6 +2157,8 @@ setnext(glue_data) -- ugly code: we get partial lists (check if this stack is still okay) ... and we run -- into temp nodes (sigh) + -- this really need a rework + local forceflush = false function vspacing.pagehandler(newhead,where) @@ -2122,7 +2166,7 @@ setnext(glue_data) local newtail = find_node_tail(newhead) -- best pass that tail, known anyway local flush = false stackhack = true -- todo: only when grid snapping once enabled - -- todo: fast check if head = tail + for n, id, subtype in nextnode, newhead do -- we could just look for glue nodes if id ~= glue_code then flush = true @@ -2198,18 +2242,15 @@ setnext(glue_data) forceflush = true end - local ignore = table.tohash { - "split_keep", - "split_off", - -- "vbox", + local ignored = table.tohash { + "splitkeep", + "splitoff", +-- "insert", } function vspacing.vboxhandler(head,where) - if head and not ignore[where] and getnext(head) then - if getnext(head) then -- what if a one liner and snapping? - head = collapser(head,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper - return head - end + if head and not ignored[where] and getnext(head) then + head = collapser(head,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper end return head end diff --git a/tex/context/base/mkxl/supp-box.lmt b/tex/context/base/mkxl/supp-box.lmt index 8a290b5ae..93b97b48e 100644 --- a/tex/context/base/mkxl/supp-box.lmt +++ b/tex/context/base/mkxl/supp-box.lmt @@ -169,213 +169,221 @@ implement { end } -local function applytochars(current,doaction,noaction,nested) - while current do - local id = getid(current) - if nested and (id == hlist_code or id == vlist_code) then - context.beginhbox() - applytochars(getlist(current),doaction,noaction,nested) - context.endhbox() - elseif id ~= glyph_code then - noaction(tonode(copy_node(current))) - else - doaction(tonode(copy_node(current))) +do + + local function applytochars(current,doaction,noaction,nested) + while current do + local id = getid(current) + if nested and (id == hlist_code or id == vlist_code) then + context.beginhbox() + applytochars(getlist(current),doaction,noaction,nested) + context.endhbox() + elseif id ~= glyph_code then + noaction(tonode(copy_node(current))) + else + doaction(tonode(copy_node(current))) + end + current = getnext(current) end - current = getnext(current) end -end -local function applytowords(current,doaction,noaction,nested) - local start - while current do - local id = getid(current) - if id == glue_code then - if start then - doaction(tonode(copylist(start,current))) - start = nil + local function applytowords(current,doaction,noaction,nested) + local start + while current do + local id = getid(current) + if id == glue_code then + if start then + doaction(tonode(copylist(start,current))) + start = nil + end + noaction(tonode(copy_node(current))) + elseif nested and (id == hlist_code or id == vlist_code) then + context.beginhbox() + applytowords(getlist(current),doaction,noaction,nested) + context.egroup() + elseif not start then + start = current end - noaction(tonode(copy_node(current))) - elseif nested and (id == hlist_code or id == vlist_code) then - context.beginhbox() - applytowords(getlist(current),doaction,noaction,nested) - context.egroup() - elseif not start then - start = current + current = getnext(current) + end + if start then + doaction(tonode(copylist(start))) end - current = getnext(current) - end - if start then - doaction(tonode(copylist(start))) end -end -local methods = { - char = applytochars, - characters = applytochars, - word = applytowords, - words = applytowords, -} + local methods = { + char = applytochars, + characters = applytochars, + word = applytowords, + words = applytowords, + } -implement { - name = "applytobox", - arguments = { - { - { "box", "integer" }, - { "command" }, - { "method" }, - { "nested", "boolean" }, - } - }, - actions = function(specification) - local list = checkedlist(specification.box) - local action = methods[specification.method or "char"] - if list and action then - action(list,context[specification.command or "ruledhbox"],context,specification.nested) - end - end -} + implement { + name = "applytobox", + arguments = { + { + { "box", "integer" }, + { "command" }, + { "method" }, + { "nested", "boolean" }, + } + }, + actions = function(specification) + local list = checkedlist(specification.box) + local action = methods[specification.method or "char"] + if list and action then + action(list,context[specification.command or "ruledhbox"],context,specification.nested) + end + end + } -local split_char = lpeg.Ct(lpeg.C(1)^0) -local split_word = lpeg.tsplitat(lpeg.patterns.space) -local split_line = lpeg.tsplitat(lpeg.patterns.eol) - -local function processsplit(specification) - local str = specification.data or "" - local command = specification.command or "ruledhbox" - local method = specification.method or "word" - local spaced = specification.spaced - if command then - command = context[command] - end - if method == "char" or method == "character" then - if spaced then - spaced = context.space + local split_char = lpeg.Ct(lpeg.C(1)^0) + local split_word = lpeg.tsplitat(lpeg.patterns.space) + local split_line = lpeg.tsplitat(lpeg.patterns.eol) + + local function processsplit(specification) + local str = specification.data or "" + local command = specification.command or "ruledhbox" + local method = specification.method or "word" + local spaced = specification.spaced + if command then + command = context[command] end - local words = lpegmatch(split_char,str) - for i=1,#words do - local word = words[i] - if word == " " then - if spaced then - spaced() + if method == "char" or method == "character" then + if spaced then + spaced = context.space + end + local words = lpegmatch(split_char,str) + for i=1,#words do + local word = words[i] + if word == " " then + if spaced then + spaced() + end + elseif command then + command(word) + else + context(word) end - elseif command then - command(word) - else - context(word) end - end - elseif method == "word" then - if spaced then - spaced = context.space - end - local words = lpegmatch(split_word,str) - for i=1,#words do - local word = words[i] - if spaced and i > 1 then - spaced() + elseif method == "word" then + if spaced then + spaced = context.space end - if command then - command(word) - else - context(word) + local words = lpegmatch(split_word,str) + for i=1,#words do + local word = words[i] + if spaced and i > 1 then + spaced() + end + if command then + command(word) + else + context(word) + end end - end - elseif method == "line" then - if spaced then - spaced = context.par - end - local words = lpegmatch(split_line,str) - for i=1,#words do - local word = words[i] - if spaced and i > 1 then - spaced() + elseif method == "line" then + if spaced then + spaced = context.par end - if command then - command(word) - else - context(word) + local words = lpegmatch(split_line,str) + for i=1,#words do + local word = words[i] + if spaced and i > 1 then + spaced() + end + if command then + command(word) + else + context(word) + end end + else + context(str) end - else - context(str) end -end -implement { - name = "processsplit", - actions = processsplit, - arguments = { - { - { "data" }, - { "command" }, - { "method" }, - { "spaced", "boolean" }, + implement { + name = "processsplit", + actions = processsplit, + arguments = { + { + { "data" }, + { "command" }, + { "method" }, + { "spaced", "boolean" }, + } } } -} -local a_vboxtohboxseparator = attributes.private("vboxtohboxseparator") +end -implement { - name = "vboxlisttohbox", - arguments = { "integer", "integer", "dimen" }, - actions = function(original,target,inbetween) - local current = getlist(getbox(original)) - local head = nil - local tail = nil - while current do - local id = getid(current) - local next = getnext(current) - if id == hlist_code then - local list = getlist(current) - if head then - if inbetween > 0 then - local n = new_glue(0,0,inbetween) - setlink(tail,n) - tail = n - end - setlink(tail,list) - else - head = list - end - tail = find_tail(list) - -- remove last separator - if getid(tail) == hlist_code and getattribute(tail,a_vboxtohboxseparator) == 1 then - local temp = tail - local prev = getprev(tail) - if next then - local list = getlist(tail) - setlink(prev,list) - setlist(tail) - tail = find_tail(list) +do + + local a_vboxtohboxseparator = attributes.private("vboxtohboxseparator") + + implement { + name = "vboxlisttohbox", + arguments = { "integer", "integer", "dimen" }, + actions = function(original,target,inbetween) + local current = getlist(getbox(original)) + local head = nil + local tail = nil + while current do + local id = getid(current) + local next = getnext(current) + if id == hlist_code then + local list = getlist(current) + if head then + if inbetween > 0 then + local n = new_glue(0,0,inbetween) + setlink(tail,n) + tail = n + end + setlink(tail,list) else - tail = prev + head = list + end + tail = find_tail(list) + -- remove last separator + if getid(tail) == hlist_code and getattribute(tail,a_vboxtohboxseparator) == 1 then + local temp = tail + local prev = getprev(tail) + if next then + local list = getlist(tail) + setlink(prev,list) + setlist(tail) + tail = find_tail(list) + else + tail = prev + end + flushnode(temp) end - flushnode(temp) + -- done + setnext(tail) + setlist(current) end - -- done - setnext(tail) - setlist(current) + current = next end - current = next + local result = new_hlist() + setlist(result,head) + setbox(target,result) + -- setbox(target,new_hlist(head)) end - local result = new_hlist() - setlist(result,head) - setbox(target,result) - -- setbox(target,new_hlist(head)) - end -} + } -implement { - name = "hboxtovbox", - arguments = "integer", - actions = function(n) - local b = getbox(n) - local factor = texget("baselineskip",false) / texget("hsize") - setdepth(b,0) - setheight(b,getwidth(b) * factor) - end -} + implement { + name = "hboxtovbox", + arguments = "integer", + actions = function(n) + local b = getbox(n) + local factor = texget("baselineskip",false) / texget("hsize") + setdepth(b,0) + setheight(b,getwidth(b) * factor) + end + } + +end implement { name = "boxtostring", @@ -386,39 +394,14 @@ implement { end } -local function getnaturaldimensions(n) - local w = 0 - local h = 0 - local d = 0 - local l = getlist(getbox(n)) - if l then - w, h, d = getdimensions(l) - end - texsetdimen("lastnaturalboxwd",w) - texsetdimen("lastnaturalboxht",h) - texsetdimen("lastnaturalboxdp",d) - return w, h, d -end +do -implement { - name = "getnaturaldimensions", - arguments = "integer", - actions = getnaturaldimensions -} + -- we can now move this to the tex end -implement { - name = "naturalwd", - arguments = "integer", - actions = function(n) - getnaturaldimensions(n) - context.lastnaturalboxwd(false) - end -} + local values = tokens.values + local dimension_value = values.dimension -implement { - name = "getnaturalwd", - arguments = "integer", - actions = function(n) + local function getnaturaldimensions(n) local w = 0 local h = 0 local d = 0 @@ -426,25 +409,64 @@ implement { if l then w, h, d = getdimensions(l) end - context("\\dimexpr%i\\scaledpoint\\relax",w) + texsetdimen("lastnaturalboxwd",w) + texsetdimen("lastnaturalboxht",h) + texsetdimen("lastnaturalboxdp",d) + return w, h, d end -} -local function setboxtonaturalwd(n) - local old = takebox(n) - local new = hpack(getlist(old)) - setlist(old,nil) - flushnode(old) - setbox(n,new) -end + local function setboxtonaturalwd(n) + local old = takebox(n) + local new = hpack(getlist(old)) + setlist(old,nil) + flushnode(old) + setbox(n,new) + end -implement { - name = "setnaturalwd", - arguments = "integer", - actions = setboxtonaturalwd -} + implement { + name = "getnaturaldimensions", + arguments = "integer", + public = true, + protected = true, + untraced = true, + actions = getnaturaldimensions + } + + implement { + name = "naturalwd", + arguments = "integer", + usage = "value", + public = true, + protected = true, + actions = function(n) + return dimension_value, (getnaturaldimensions(n)) + end + } -nodes.setboxtonaturalwd = setboxtonaturalwd + implement { + name = "getnaturalwd", + arguments = "integer", + usage = "value", + public = true, + protected = true, + actions = function(n) + local l = getlist(getbox(n)) + return dimension_value, l and getdimensions(l) or 0 + end + } + + implement { + name = "setnaturalwd", + arguments = "integer", + public = true, + protected = true, + untraced = true, + actions = setboxtonaturalwd + } + + nodes.setboxtonaturalwd = setboxtonaturalwd + +end local doifelse = commands.doifelse @@ -1433,7 +1455,7 @@ end do - function setsplitlisthtdp(n,ht,dp) + local function setsplitlisthtdp(n,ht,dp) local box = getbox(n) if box then local head = getlist(box) diff --git a/tex/context/base/mkxl/supp-box.mkxl b/tex/context/base/mkxl/supp-box.mkxl index 2ad067002..8e5b38365 100644 --- a/tex/context/base/mkxl/supp-box.mkxl +++ b/tex/context/base/mkxl/supp-box.mkxl @@ -2728,11 +2728,11 @@ %D We can define these public in lua: -\aliased\let\getnaturaldimensions\clf_getnaturaldimensions % sets three dimensions -\aliased\let\naturalwd \clf_naturalwd % calculates and returns wd +% \aliased\let\getnaturaldimensions\clf_getnaturaldimensions % sets three dimensions +% \aliased\let\naturalwd \clf_naturalwd % calculates and returns wd -\aliased\let\getnaturalwd\clf_getnaturalwd % no intermediate -\aliased\let\setnaturalwd\clf_setnaturalwd % no intermediate +% \aliased\let\getnaturalwd\clf_getnaturalwd % no intermediate +% \aliased\let\setnaturalwd\clf_setnaturalwd % no intermediate \permanent\protected\def\doifelserighttoleftinbox{\clf_doifelserighttoleftinbox} diff --git a/tex/context/base/mkxl/tabl-tbl.mkxl b/tex/context/base/mkxl/tabl-tbl.mkxl index e329da268..959ef4617 100644 --- a/tex/context/base/mkxl/tabl-tbl.mkxl +++ b/tex/context/base/mkxl/tabl-tbl.mkxl @@ -183,15 +183,21 @@ \newconditional \c_tabl_tabulate_nopbreak \newconditional \c_tabl_tabulate_firstflushed \newconditional \c_tabl_tabulate_equal -\newconditional \c_tabl_tabulate_split \settrue\c_tabl_tabulate_split +\newconditional \c_tabl_tabulate_split \newconditional \c_tabl_tabulate_automode -\newconditional \c_tabl_tabulate_handlepbreak \settrue\c_tabl_tabulate_handlepbreak -\newconditional \c_tabl_tabulate_autorulespacing \settrue\c_tabl_tabulate_autorulespacing +\newconditional \c_tabl_tabulate_handlepbreak +\newconditional \c_tabl_tabulate_autorulespacing \newconditional \c_tabl_tabulate_someamble \newconditional \c_tabl_tabulate_tolerant_break \newconditional \c_tabl_tabulate_splitoff_whitespace \newconditional \c_tabl_tabulate_pwidth_set \newconditional \c_tabl_tabulate_reshape +\newconditional \c_tabl_tabulate_no_blank_in_paragraphs % can become always on + +\settrue\c_tabl_tabulate_split +\settrue\c_tabl_tabulate_handlepbreak +\settrue\c_tabl_tabulate_autorulespacing +\settrue\c_tabl_tabulate_no_blank_in_paragraphs \newdimen \d_tabl_tabulate_width_p \newdimen \d_tabl_tabulate_width_w @@ -1993,7 +1999,11 @@ \fi} \protected\def\tabl_tabulate_eskip_second - {\par\egroup + {\par + \ifconditional\c_tabl_tabulate_no_blank_in_paragraphs + \removelastskip + \fi + \egroup \tabl_tabulate_pheight_set \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes \tabl_tabulate_splitoff_box} @@ -2003,6 +2013,9 @@ % first line \global\setbox\b_tabl_tabulate_current\c_tabl_tabulate_column\vbox \bgroup + \ifconditional\c_tabl_tabulate_no_blank_in_paragraphs + \inhibitblank + \fi \glet\tabl_tabulate_hook\tabl_tabulate_hook_nop \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi % \begstrut % interferes with pre-\pars diff --git a/tex/context/base/mkxl/trac-deb.lmt b/tex/context/base/mkxl/trac-deb.lmt index 9cf122d32..195a7cb8e 100644 --- a/tex/context/base/mkxl/trac-deb.lmt +++ b/tex/context/base/mkxl/trac-deb.lmt @@ -163,6 +163,7 @@ local function processerror(offset,errortype) if job and type(job.disablesave) == "function" then job.disablesave() end + lua.setexitcode(1) end directives.register("system.quitonerror",function(v) diff --git a/tex/context/base/mkxl/typo-bld.lmt b/tex/context/base/mkxl/typo-bld.lmt index 9c83adede..ae644d297 100644 --- a/tex/context/base/mkxl/typo-bld.lmt +++ b/tex/context/base/mkxl/typo-bld.lmt @@ -34,11 +34,12 @@ constructors.attribute = a_parbuilder local unsetvalue = attributes.unsetvalue local texsetattribute = tex.setattribute local texnest = tex.nest -local texlists = tex.lists - local texget = tex.get local texset = tex.set +local getspeciallist = nodes.nuts.getspeciallist +local setspeciallist = nodes.nuts.setspeciallist + local texgetdimen = tex.getdimen local nodes = nodes @@ -216,46 +217,32 @@ end local pageactions = nodes.tasks.actions("mvlbuilders") ----- lineactions = nodes.tasks.actions("linebuilders") -local function report(groupcode,head) - report_page_builder("trigger: %s",groupcode) +local function report(pagecontext,head) + report_page_builder("trigger: %s at level %i",pagecontext,texnest.ptr) report_page_builder(" vsize : %p",texget("vsize")) report_page_builder(" pagegoal : %p",texget("pagegoal")) report_page_builder(" pagetotal: %p",texget("pagetotal")) report_page_builder(" list : %s",head and nodeidstostring(head) or "<empty>") end --- check why box is called before after_linebreak .. maybe make categories and --- call 'm less - --- this will be split into contribute_filter for these 4 so at some point --- the check can go away +-- Watch out: contributehead can be any head (kind of) not per se the page one +-- but that needs to be intercepted when needed by groupcode and level. At some +-- point this one might be split by group. --- Todo: contrib_head can be any head (kind of) not per se the page one so maybe I will --- intercept that in the engine with contributehead or so. - -function builders.buildpage_filter(groupcode) - local head = texlists.contributehead +function builders.buildpage_filter(pagecontext) + local head, tail = getspeciallist("contributehead") if head then - local done = false - -- called quite often ... maybe time to remove timing - starttiming(builders) if trace_page_builder then - report(groupcode,head) + report(pagecontext,head) end - head, done = pageactions(head,groupcode) + starttiming(builders) + head = pageactions(head,pagecontext) -- todo: tail stoptiming(builders) - -- -- doesn't work here (not passed on?) - -- texset("pagegoal,texget("vsize") - texgetdimen("d_page_floats_inserted_top") - texgetdimen("d_page_floats_inserted_bottom") - texlists.contributehead = head or nil -- needs checking - -- tex.setlist("contributehead",head,head and nodes.tail(head)) - return done and head or true -- no return value needed + setspeciallist("contributehead", head) else - -- happens quite often if trace_page_builder then - report(groupcode) + report(pagecontext) end --- return nil, false -- no return value needed - return nil end end diff --git a/tex/context/base/mkxl/typo-brk.lmt b/tex/context/base/mkxl/typo-brk.lmt index f9c255608..3a7b69db9 100644 --- a/tex/context/base/mkxl/typo-brk.lmt +++ b/tex/context/base/mkxl/typo-brk.lmt @@ -397,9 +397,6 @@ function breakpoints.handler(head) -- end end end - if done then --- unsetattributes(a_breakpoints, head) - end end return head end diff --git a/tex/context/base/mkxl/typo-cap.lmt b/tex/context/base/mkxl/typo-cap.lmt index 02a2c1aaf..4a55c410f 100644 --- a/tex/context/base/mkxl/typo-cap.lmt +++ b/tex/context/base/mkxl/typo-cap.lmt @@ -19,96 +19,83 @@ local report_casing = logs.reporter("typesetting","casing") local nodes, node = nodes, node -local nuts = nodes.nuts +local nuts = nodes.nuts -local getnext = nuts.getnext -local getid = nuts.getid -local getattr = nuts.getattr -local getcharspec = nuts.getcharspec -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar -local isglyph = nuts.isglyph -local getdisc = nuts.getdisc +local getnext = nuts.getnext +local getid = nuts.getid +local getattr = nuts.getattr +local getcharspec = nuts.getcharspec +local getsubtype = nuts.getsubtype +local getchar = nuts.getchar +local isglyph = nuts.isglyph +local getdisc = nuts.getdisc -local setchar = nuts.setchar -local setfont = nuts.setfont -local setscales = nuts.setscales +local setchar = nuts.setchar +local setfont = nuts.setfont +local setscales = nuts.setscales -local copy_node = nuts.copy -local endofmath = nuts.endofmath -local insertafter = nuts.insertafter -local findattribute = nuts.findattribute -local unsetattributes = nuts.unsetattributes +local copy_node = nuts.copy +local endofmath = nuts.endofmath +local insertafter = nuts.insertafter +local findattribute = nuts.findattribute +local unsetattributes = nuts.unsetattributes -local nextglyph = nuts.traversers.glyph +local nextglyph = nuts.traversers.glyph -local nodecodes = nodes.nodecodes -local kerncodes = nodes.kerncodes +local nodecodes = nodes.nodecodes +local kerncodes = nodes.kerncodes -local glyph_code = nodecodes.glyph -local kern_code = nodecodes.kern -local disc_code = nodecodes.disc -local math_code = nodecodes.math +local glyph_code = nodecodes.glyph +local kern_code = nodecodes.kern +local disc_code = nodecodes.disc +local math_code = nodecodes.math -local fontkern_code = kerncodes.fontkern +local fontkern_code = kerncodes.fontkern -local enableaction = nodes.tasks.enableaction +local enableaction = nodes.tasks.enableaction -local newkern = nuts.pool.kern +local newkern = nuts.pool.kern -local fonthashes = fonts.hashes -local fontdata = fonthashes.identifiers -local fontchar = fonthashes.characters +local fonthashes = fonts.hashes +local fontdata = fonthashes.identifiers +local fontchar = fonthashes.characters -local currentfont = font.current +local currentfont = font.current -local variables = interfaces.variables -local v_reset = variables.reset +local variables = interfaces.variables +local v_reset = variables.reset -local texsetattribute = tex.setattribute -local unsetvalue = attributes.unsetvalue -local texgetcount = tex.getcount +local texsetattribute = tex.setattribute +----- unsetvalue = attributes.unsetvalue +----- texgetcount = tex.getcount +local texgetscales = tex.getglyphscales -typesetters = typesetters or { } -local typesetters = typesetters +typesetters = typesetters or { } +local typesetters = typesetters -typesetters.cases = typesetters.cases or { } -local cases = typesetters.cases +typesetters.cases = typesetters.cases or { } +local cases = typesetters.cases -cases.actions = { } -local actions = cases.actions -local a_cases = attributes.private("case") +cases.actions = { } +local actions = cases.actions +local a_cases = attributes.private("case") -local run = 0 -- a trick to make neighbouring ranges work -local blocked = { } +local run = 0 -- a trick to make neighbouring ranges work -local fontstate = { } -- this will become something generic +local registervalue = attributes.registervalue +local getvalue = attributes.getvalue +local texsetattribute = tex.setattribute local function set(tag,font) - if run < 0x7F then - run = run + 1 - else - run = 1 - end - local a = (font << 16) - + (tag << 8) - + (run << 0) - blocked[a] = false - -- it makes sense to fetch them all at once ut it doesn't happen often: tex.getglyphscales() scale xscale yscale data [script] [state] - fontstate[a] = { - texgetcount("glyphscale"), - texgetcount("glyphxscale"), - texgetcount("glyphyscale"), - texgetcount("glyphdatafield") + run = run + 1 + local settings = { + font = font, + tag = tag, + run = run, -- still needed ? + -- blocked = false + scales = { texgetscales() }, } - return a -end - -local function get(a) - return - (a >> 8) & 0x00FF, -- tag - (a >> 16) & 0xFFFF, -- font - (a >> 0) & 0x00FF -- run + texsetattribute(a_cases,registervalue(a_cases,settings)) end -- a previous implementation used char(0) as placeholder for the larger font, so we needed @@ -172,17 +159,17 @@ end cases.register = register -local function WORD(start,attr,lastfont,n,count,where,first) +local function WORD(start,data,lastfont,n,count,where,first) lastfont[n] = false return replacer(first or start,uccodes) end -local function word(start,attr,lastfont,n,count,where,first) +local function word(start,data,lastfont,n,count,where,first) lastfont[n] = false return replacer(first or start,lccodes) end -local function Words(start,attr,lastfont,n,count,where,first) -- looks quite complex +local function Words(start,data,lastfont,n,count,where,first) -- looks quite complex if where == "post" then return end @@ -194,18 +181,18 @@ local function Words(start,attr,lastfont,n,count,where,first) -- looks quite com end end -local function Word(start,attr,lastfont,n,count,where,first) - blocked[attr] = true - return Words(start,attr,lastfont,n,count,where,first) +local function Word(start,data,lastfont,n,count,where,first) + data.blocked = true + return Words(start,data,lastfont,n,count,where,first) end -local function camel(start,attr,lastfont,n,count,where,first) - word(start,attr,lastfont,n,count,where,first) - Words(start,attr,lastfont,n,count,where,first) +local function camel(start,data,lastfont,n,count,where,first) + word(start,data,lastfont,n,count,where,first) + Words(start,data,lastfont,n,count,where,first) return start, true end -local function mixed(start,attr,lastfont,n,count,where,first) +local function mixed(start,data,lastfont,n,count,where,first) if where == "post" then return end @@ -217,10 +204,10 @@ local function mixed(start,attr,lastfont,n,count,where,first) elseif dc == char then local lfa = lastfont[n] if lfa then - local s = fontstate[attr] + local s = data.scales setfont(used,lfa) if s then - setscales(used, s[1], s[2], s[3]) + setscales(used,s[1],s[2],s[3]) end end else @@ -229,17 +216,17 @@ local function mixed(start,attr,lastfont,n,count,where,first) return start, true end -local function Capital(start,attr,lastfont,n,count,where,first,once) -- 3 +local function Capital(start,data,lastfont,n,count,where,first,once) -- 3 local used = first or start if count == 1 and where ~= "post" then local lfa = lastfont[n] if lfa then local dc = uccodes[getchar(used)] if dc then - local s = fontstate[attr] + local s = data.scales setfont(used,lfa) if s then - setscales(used, s[1], s[2], s[3]) + setscales(used,s[1],s[2],s[3]) end end end @@ -251,15 +238,15 @@ local function Capital(start,attr,lastfont,n,count,where,first,once) -- 3 return start, c end -local function capital(start,attr,lastfont,n,where,count,first,count) -- 4 - return Capital(start,attr,lastfont,n,where,count,first,true) +local function capital(start,data,lastfont,n,where,count,first,count) -- 4 + return Capital(start,data,lastfont,n,where,count,first,true) end -local function none(start,attr,lastfont,n,count,where,first) +local function none(start,data,lastfont,n,count,where,first) return start, true end -local function randomized(start,attr,lastfont,n,count,where,first) +local function randomized(start,data,lastfont,n,count,where,first) local used = first or start local char, font = getcharfont(used) @@ -301,89 +288,92 @@ register(variables.cap, variables.capital) -- clone register(variables.Cap, variables.Capital) -- clone function cases.handler(head) - local _, start = findattribute(head, a_cases) + local _, start = findattribute(head,a_cases) if start then local lastfont = { } local lastattr = nil local count = 0 - local done = false while start do -- while because start can jump ahead local id = getid(start) if id == glyph_code then local attr = getattr(start,a_cases) - if attr and attr > 0 and not blocked[attr] then - if attr ~= lastattr then - lastattr = attr - count = 1 - else - count = count + 1 - end - local n, id, m = get(attr) --- if lastfont[n] == nil then - lastfont[n] = id --- end - local action = actions[n] -- map back to low number - if action then - local quit - start, quit = action(start,attr,lastfont,n,count) - if trace_casing then - report_casing("case trigger %a, instance %a, fontid %a, result %a",n,m,id,quit and "-" or "+") + if attr and attr > 0 then + local data = getvalue(a_cases,attr) + if data and not data.blocked then + if attr ~= lastattr then + lastattr = attr + count = 1 + else + count = count + 1 + end + local tag = data.tag + local font = data.font + local run = data.run + local action = actions[tag] -- map back to low number + lastfont[tag] = font + if action then + local quit + start, quit = action(start,data,lastfont,tag,count) + if trace_casing then + report_casing("case trigger %a, instance %a, fontid %a, result %a", + tag,run,font,quit and "-" or "+") + end + elseif trace_casing then + report_casing("unknown case trigger %a",tag) end - elseif trace_casing then - report_casing("unknown case trigger %a",n) end - done = true end elseif id == disc_code then local attr = getattr(start,a_cases) - if attr and attr > 0 and not blocked[attr] then - if attr ~= lastattr then - lastattr = attr - count = 0 - end - local n, id, m = get(attr) --- if lastfont[n] == nil then - lastfont[n] = id --- end - local action = actions[n] -- map back to low number - if action then - local pre, post, replace = getdisc(start) - if replace then - local cnt = count - for g in nextglyph, replace do - cnt = cnt + 1 - getattr(g,a_cases) - local h, quit = action(start,attr,lastfont,n,cnt,"replace",g) - if quit then - break + if attr and attr > 0 then + local data = getvalue(a_cases,attr) + if data and not data.blocked then + if attr ~= lastattr then + lastattr = attr + count = 0 + end + local tag = data.tag + local font = data.font + local action = actions[tag] -- map back to low number + lastfont[tag] = font + if action then + local pre, post, replace = getdisc(start) + if replace then + local cnt = count + for g in nextglyph, replace do + cnt = cnt + 1 + getattr(g,a_cases) + local h, quit = action(start,data,lastfont,tag,cnt,"replace",g) + if quit then + break + end end end - end - if pre then - local cnt = count - for g in nextglyph, pre do - cnt = cnt + 1 - getattr(g,a_cases) - local h, quit = action(start,attr,lastfont,n,cnt,"pre",g) - if quit then - break + if pre then + local cnt = count + for g in nextglyph, pre do + cnt = cnt + 1 + getattr(g,a_cases) + local h, quit = action(start,data,lastfont,tag,cnt,"pre",g) + if quit then + break + end end end - end - if post then - local cnt = count - for g in nextglyph, post do - cnt = cnt + 1 - getattr(g,a_cases) - local h, quit = action(start,attr,lastfont,n,cnt,"post",g) - if quit then - break + if post then + local cnt = count + for g in nextglyph, post do + cnt = cnt + 1 + getattr(g,a_cases) + local h, quit = action(start,data,lastfont,tag,cnt,"post",g) + if quit then + break + end end end end + count = count + 1 end - count = count + 1 - done = true end else if id == math_code then @@ -395,9 +385,6 @@ function cases.handler(head) start = getnext(start) end end - if done then - -- unsetattributes(a_cases,head) - end end return head end @@ -405,9 +392,7 @@ end local enabled = false function cases.set(n,id) - if n == v_reset then - n = unsetvalue - else + if n ~= v_reset then n = registered[n] or tonumber(n) if n then if not enabled then @@ -417,13 +402,11 @@ function cases.set(n,id) end enabled = true end - n = set(n,id or currentfont()) - else - n = unsetvalue + set(n,id or currentfont()) + return end end - texsetattribute(a_cases,n) - -- return n -- bonus + texsetattribute(a_cases) -- ,unsetvalue) end -- interface diff --git a/tex/context/base/mkxl/typo-rub.lmt b/tex/context/base/mkxl/typo-rub.lmt index eff522e02..f5bba7f7f 100644 --- a/tex/context/base/mkxl/typo-rub.lmt +++ b/tex/context/base/mkxl/typo-rub.lmt @@ -170,13 +170,14 @@ do local function setruby(n,m) nofrubies = nofrubies + 1 local r = takebox(n) - rubylist[nofrubies] = setmetatableindex({ + local t = { text = r, width = getwidth(r), basewidth = 0, start = false, stop = false, - }, shared) + } + rubylist[nofrubies] = setmetatableindex(t, shared) texsetattribute(a_ruby,nofrubies) end diff --git a/tex/context/base/mkxl/typo-rub.mkxl b/tex/context/base/mkxl/typo-rub.mkxl index b4b0cbc5e..bf48d8fa1 100644 --- a/tex/context/base/mkxl/typo-rub.mkxl +++ b/tex/context/base/mkxl/typo-rub.mkxl @@ -60,7 +60,7 @@ comment {#2} \relax} -\setvalue{\??rubyanalyze\v!top}#1#2% +\defcsname\??rubyanalyze\v!top\endcsname#1#2% {\clf_ruby align {\rubyparameter\c!align}% stretch {\rubyparameter\c!stretch}% @@ -70,7 +70,7 @@ comment {#2} \relax} -\setvalue{\??rubyplacement\v!top}#1#2% +\defcsname\??rubyplacement\v!top\endcsname#1#2% {\setbox\scratchbox\hbox\bgroup \userubystyleandcolor\c!style\c!color #2% @@ -79,7 +79,7 @@ \relax #1} -\setvalue{\??rubyplacement\v!right}#1#2% +\defcsname\??rubyplacement\v!right\endcsname#1#2% {#1% \edef\p_distance{\rubyparameter\c!distance}% \ifempty\p_distance\orelse\ifx\p_distance\v!none\else\hskip\p_distance\fi @@ -88,7 +88,7 @@ \rubyparameter\c!left#2\rubyparameter\c!right \endgroup} -\setvalue{\??rubyplacement\v!left}#1#2% +\defcsname\??rubyplacement\v!left\endcsname#1#2% {\begingroup \userubystyleandcolor\c!style\c!color \rubyparameter\c!left#2\rubyparameter\c!right diff --git a/tex/context/modules/mkiv/m-matrix.mkiv b/tex/context/modules/mkiv/m-matrix.mkiv index 4a0bd712d..a5747ac81 100644 --- a/tex/context/modules/mkiv/m-matrix.mkiv +++ b/tex/context/modules/mkiv/m-matrix.mkiv @@ -729,6 +729,7 @@ $\qquad\qquad$ \stopsubject \startsubject[title={Transpose a matrix}] + \startbuffer \startluacode moduledata.matrix.typeset(document.DemoMatrixA) @@ -752,6 +753,7 @@ $\qquad\qquad$ \getbuffer[demo] +\startbuffer \startluacode context("$<1,2,3> \\cdot <3,1,2, 4> \\ =\\ $ ") context(moduledata.matrix.inner({ 1, 2, 3 }, { 3, 1, 2, 4 })) @@ -882,7 +884,6 @@ context(moduledata.matrix.inner({ 1, 2, 3 }, { 3, 1, 2, 4 })) context("$\\Rightarrow$") moduledata.matrix.typeset(moduledata.matrix.rowechelon(m,1)) \stopluacode - \stopbuffer \getbuffer[demo] @@ -989,6 +990,4 @@ context(moduledata.matrix.inner({ 1, 2, 3 }, { 3, 1, 2, 4 })) \getbuffer[demo] -\stopsubject - \stoptext diff --git a/tex/context/modules/mkiv/m-punk.mkiv b/tex/context/modules/mkiv/m-punk.mkiv index 9eb7411ba..8aecfb01f 100644 --- a/tex/context/modules/mkiv/m-punk.mkiv +++ b/tex/context/modules/mkiv/m-punk.mkiv @@ -19,7 +19,7 @@ \ifcase\contextlmtxmode\else \writestatus{punk}{use metapost library punk instead} - \endinput + \expandafter\endinput \fi \startluacode diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index f3e33db69..f0cd85039 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 2021-12-14 19:16 +-- merge date : 2021-12-24 19:07 do -- begin closure to overcome local limits and interference |