diff options
83 files changed, 3968 insertions, 714 deletions
diff --git a/doc/context/documents/general/manuals/luametatex.pdf b/doc/context/documents/general/manuals/luametatex.pdf Binary files differindex 8bf43b633..a06bc7c1b 100644 --- a/doc/context/documents/general/manuals/luametatex.pdf +++ b/doc/context/documents/general/manuals/luametatex.pdf diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index 3f2bb0051..fa5dd6e8e 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -25221,7 +25221,7 @@ do -- create closure to overcome 200 locals limit package.loaded["libs-ini"] = package.loaded["libs-ini"] or true --- original size: 6287, stripped down to: 4006 +-- original size: 6459, stripped down to: 4006 if not modules then modules={} end modules ['libs-ini']={ version=1.001, @@ -25776,8 +25776,8 @@ end -- of closure -- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1023457 --- stripped bytes : 404622 +-- original bytes : 1023629 +-- stripped bytes : 404794 -- end library merge diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua index 3f2bb0051..fa5dd6e8e 100644 --- a/scripts/context/stubs/mswin/mtxrun.lua +++ b/scripts/context/stubs/mswin/mtxrun.lua @@ -25221,7 +25221,7 @@ do -- create closure to overcome 200 locals limit package.loaded["libs-ini"] = package.loaded["libs-ini"] or true --- original size: 6287, stripped down to: 4006 +-- original size: 6459, stripped down to: 4006 if not modules then modules={} end modules ['libs-ini']={ version=1.001, @@ -25776,8 +25776,8 @@ end -- of closure -- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1023457 --- stripped bytes : 404622 +-- original bytes : 1023629 +-- stripped bytes : 404794 -- end library merge diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun index 3f2bb0051..fa5dd6e8e 100644 --- a/scripts/context/stubs/unix/mtxrun +++ b/scripts/context/stubs/unix/mtxrun @@ -25221,7 +25221,7 @@ do -- create closure to overcome 200 locals limit package.loaded["libs-ini"] = package.loaded["libs-ini"] or true --- original size: 6287, stripped down to: 4006 +-- original size: 6459, stripped down to: 4006 if not modules then modules={} end modules ['libs-ini']={ version=1.001, @@ -25776,8 +25776,8 @@ end -- of closure -- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1023457 --- stripped bytes : 404622 +-- original bytes : 1023629 +-- stripped bytes : 404794 -- end library merge diff --git a/scripts/context/stubs/win64/mtxrun.lua b/scripts/context/stubs/win64/mtxrun.lua index 3f2bb0051..fa5dd6e8e 100644 --- a/scripts/context/stubs/win64/mtxrun.lua +++ b/scripts/context/stubs/win64/mtxrun.lua @@ -25221,7 +25221,7 @@ do -- create closure to overcome 200 locals limit package.loaded["libs-ini"] = package.loaded["libs-ini"] or true --- original size: 6287, stripped down to: 4006 +-- original size: 6459, stripped down to: 4006 if not modules then modules={} end modules ['libs-ini']={ version=1.001, @@ -25776,8 +25776,8 @@ end -- of closure -- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1023457 --- stripped bytes : 404622 +-- original bytes : 1023629 +-- stripped bytes : 404794 -- end library merge diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 64a98aa95..db88cd563 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{2020.11.26 15:38} +\newcontextversion{2020.11.27 20: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 25607f8b0..5961be478 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{2020.11.26 15:38} +\edef\contextversion{2020.11.27 20:07} %D For those who want to use this: diff --git a/tex/context/base/mkiv/catc-ini.lua b/tex/context/base/mkiv/catc-ini.lua index 9241f5a1b..4da00436b 100644 --- a/tex/context/base/mkiv/catc-ini.lua +++ b/tex/context/base/mkiv/catc-ini.lua @@ -31,15 +31,11 @@ end -- this only happens at runtime -for k, v in next, numbers do - tex[k] = v -- downward compatible +for name, number in next, numbers do + tex[name] = number -- downward compatible end -- nasty table.setmetatableindex(numbers,function(t,k) if type(k) == "number" then t[k] = k return k end end) table.setmetatableindex(names, function(t,k) if type(k) == "string" then t[k] = k return k end end) - -commands.registercatcodetable = catcodes.register ---------.definecatcodetable = characters.define -- not yet defined ---------.setcharactercodes = characters.setcodes -- not yet defined diff --git a/tex/context/base/mkiv/catc-ini.mkiv b/tex/context/base/mkiv/catc-ini.mkiv index a177b26ca..d0b2c3e16 100644 --- a/tex/context/base/mkiv/catc-ini.mkiv +++ b/tex/context/base/mkiv/catc-ini.mkiv @@ -177,7 +177,7 @@ \expandafter\xdef\csname\??catcodetablen\number\c_syst_catcodes_n\endcsname{\string#1}% logging \newconstant#1% #1\c_syst_catcodes_n - \ctxcommand{registercatcodetable("\expandafter\gobbleoneargument\string#1",\number#1)}} + \ctxlua{catcodes.register("\expandafter\gobbleoneargument\string#1",\number#1)}} \newtoks \everysetdefaultcatcodes diff --git a/tex/context/base/mkiv/char-ini.lua b/tex/context/base/mkiv/char-ini.lua index 1f8e72af7..ac31dbfc6 100644 --- a/tex/context/base/mkiv/char-ini.lua +++ b/tex/context/base/mkiv/char-ini.lua @@ -762,7 +762,7 @@ local is_spacing = allocate ( tohash { } ) local is_mark = allocate ( tohash { - "mn", "ms", + "mn", "ms", -- "mn", "mc", } ) local is_punctuation = allocate ( tohash { diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index 319b6dfa1..ae825d74e 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{2020.11.26 15:38} +\newcontextversion{2020.11.27 20: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 aa1a49022..69a4cc899 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -45,7 +45,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2020.11.26 15:38} +\edef\contextversion{2020.11.27 20:07} %D Kind of special: diff --git a/tex/context/base/mkiv/libs-ini.lua b/tex/context/base/mkiv/libs-ini.lua index 7f1645b44..5b8390df2 100644 --- a/tex/context/base/mkiv/libs-ini.lua +++ b/tex/context/base/mkiv/libs-ini.lua @@ -156,6 +156,9 @@ function libraries.optionalloaded(name,libnames) end end +-- For the moment the next blob is needed when we run \MTXRUN\ on top of \LUATEX\ and +-- \LUAJITTEX\ but at some point we will {\em always} assume \LUAMETATEX\ as runner. + if FFISUPPORTED and ffi and ffi.load then local ffiload = ffi.load diff --git a/tex/context/base/mkiv/node-ini.lua b/tex/context/base/mkiv/node-ini.lua index 3d49d01bd..701e3efa9 100644 --- a/tex/context/base/mkiv/node-ini.lua +++ b/tex/context/base/mkiv/node-ini.lua @@ -124,11 +124,10 @@ local noadoptions = allocate { right = 0x14 + 0x08, } -local dirvalues = CONTEXTLMTXMODE > 0 and mark(getvalues("dir")) - -if not dirvalues then - dirvalues = allocate { [0] = "lefttoright", [1] = "righttoleft" } -end +local dirvalues = allocate { + [0] = "lefttoright", + [1] = "righttoleft", +} local literalvalues = allocate { [0] = "origin", @@ -243,12 +242,9 @@ nodes.subtypes = allocate { -- [nodecodes.user] = usercodes, [nodecodes.vlist] = listcodes, [nodecodes.whatsit] = whatcodes, + [nodecodes.marginkern] = margincodes } -if CONTEXTLMTXMODE == 0 then - nodes.subtypes[nodecodes.marginkern] = margincodes -end - table.setmetatableindex(nodes.subtypes,function(t,k) local v = { } t[k] = v @@ -338,21 +334,3 @@ trackers.register("system.showcodes", nodes.showcodes) if node.fix_node_lists then node.fix_node_lists(false) end - --- We use the real node code numbers. - -if environment.initex and CONTEXTLMTXMODE > 0 then - - local texchardef = tex.chardef - - if texchardef then - for i=0,nodecodes.glyph do - texchardef(nodecodes[i] .. "nodecode",i) - end - for i=0,#gluecodes do - texchardef(gluecodes[i] .. "subtypecode",i) - end - -- tex.set("internalcodesmode",1) -- obsolete - end - -end diff --git a/tex/context/base/mkiv/spac-ali.lua b/tex/context/base/mkiv/spac-ali.lua index 7a09ba5aa..2e2650f3b 100644 --- a/tex/context/base/mkiv/spac-ali.lua +++ b/tex/context/base/mkiv/spac-ali.lua @@ -112,7 +112,7 @@ local function handler(head,leftpage,realpageno) -- traverse_list local head = setlink(new_stretch(3),list) -- prepend setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction)) if trace_realign then - report_realign("flushing right. align %a, page %a, realpage %a",align,pageno,realpageno) + report_realign("flushing right, align %a, page %a, realpage %a",align,pageno,realpageno) end elseif trace_realign then report_realign("invalid flushing, align %a, page %a, realpage %a",align,pageno,realpageno) diff --git a/tex/context/base/mkiv/spac-chr.lua b/tex/context/base/mkiv/spac-chr.lua index ac90926e1..fa6eb18a5 100644 --- a/tex/context/base/mkiv/spac-chr.lua +++ b/tex/context/base/mkiv/spac-chr.lua @@ -81,7 +81,7 @@ local fontquads = fonthashes.quads local setmetatableindex = table.setmetatableindex -local a_character = attributes.private("characters") +local a_character = attributes.private("characters") -- this will become a property (or maybe even a field) local a_alignstate = attributes.private("alignstate") local c_zero = byte('0') @@ -295,30 +295,6 @@ local methods = { characters.methods = methods --- function characters.handler(head) -- todo: use traverse_id --- local current = head --- while current do --- local char, id = isglyph(current) --- if char then --- local next = getnext(current) --- local method = methods[char] --- if method then --- if trace_characters then --- report_characters("replacing character %C, description %a",char,lower(chardata[char].description)) --- end --- local h = method(head,current) --- if h then --- head = remove_node(h,current,true) --- end --- end --- current = next --- else --- current = getnext(current) --- end --- end --- return head --- end - -- this also works ok in math as we run over glyphs and these stay glyphs ... not sure -- about scripts and such but that is not important anyway ... some day we can consider -- special definitions in math diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex 8e4f09585..5f7f0b520 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 3c6728c0d..d6aefd1d5 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/toks-scn.lua b/tex/context/base/mkiv/toks-scn.lua index ec5681cd7..98d2f66c0 100644 --- a/tex/context/base/mkiv/toks-scn.lua +++ b/tex/context/base/mkiv/toks-scn.lua @@ -294,11 +294,6 @@ local f_elseif = formatters[" elseif scankeywordcs('%s') then data['%s'] = sc ----- f_if_x = formatters[ " if not data['%s'] and scankeywordcs('%s') then data['%s'] = scan%s()"] ----- f_elseif_x = formatters[" elseif not data['%s'] and scankeywordcs('%s') then data['%s'] = scan%s()"] --- if CONTEXTLMTXMODE > 0 then --- f_if = formatters[" local key = scanletters() if key == '' then break elseif key == '%s' then data['%s'] = scan%s()"] --- f_elseif = formatters[" elseif key == '%s' then data['%s'] = scan%s()"] --- end - local f_local = formatters["local scan%s = scanners.%s"] local f_scan = formatters["scan%s()"] local f_shortcut = formatters["local %s = scanners.converters.%s"] @@ -309,11 +304,6 @@ local f_scan_c = formatters["%s(scan%s())"] -- see above --- if CONTEXTLMTXMODE > 0 then --- f_if_c = formatters[" local key = scanletters() if key == '' then break elseif key == '%s' then data['%s'] = %s(scan%s())"] --- f_elseif_c = formatters[" elseif k == '%s' then data['%s'] = %s(scan%s())"] --- end - local f_any = formatters[" else local key = scanword(true) if key then data[key] = scan%s() else break end end"] local f_any_c = formatters[" else local key = scanword(true) if key then data[key] = %s(scan%s()) else break end end"] local s_done = " else break end" diff --git a/tex/context/base/mkxl/anch-pos.mkxl b/tex/context/base/mkxl/anch-pos.mkxl index 53544fedc..6a2fbd5e1 100644 --- a/tex/context/base/mkxl/anch-pos.mkxl +++ b/tex/context/base/mkxl/anch-pos.mkxl @@ -396,18 +396,16 @@ {\the\t_anch_positions_tracers} \permanent\protected\def\enableparpositions % global - {\glet\registerparoptions\doregisterparoptions + {\enforced\aliased\glet\registerparoptions\doregisterparoptions \global\positioningtrue} \permanent\let\disableparpositions\relax -\let\registerparoptions\relax +\aliased\let\registerparoptions\relax -\protected\def\doregisterparoptions - {\iftrialtypesetting \else - \ifinpagebody \else \ifmmode \else \ifinformula \else - \anch_positions_register_par_options - \fi \fi \fi +\permanent\protected\def\doregisterparoptions + {\iftrialtypesetting \orelse\ifinpagebody \orelse\ifmmode \orelse\ifinformula \else + \anch_positions_register_par_options \fi} \def\anch_positions_register_par_options_normal diff --git a/tex/context/base/mkxl/blob-ini.mkxl b/tex/context/base/mkxl/blob-ini.mkxl index 3443836b7..1dcd55972 100644 --- a/tex/context/base/mkxl/blob-ini.mkxl +++ b/tex/context/base/mkxl/blob-ini.mkxl @@ -36,7 +36,7 @@ \aliased\let\heightanddepthofstring\totalofstring \aliased\let\htdpofstring \hdofstring -\let\hd\htdp % if yes then move this +% \let\hd\htdp % if yes then move this % This one takes anything that can be typeset diff --git a/tex/context/base/mkxl/catc-ini.lmt b/tex/context/base/mkxl/catc-ini.lmt new file mode 100644 index 000000000..ede8216a6 --- /dev/null +++ b/tex/context/base/mkxl/catc-ini.lmt @@ -0,0 +1,44 @@ +if not modules then modules = { } end modules ['catc-ini'] = { + version = 1.001, + comment = "companion to catc-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +catcodes = catcodes or { } +catcodes.numbers = catcodes.numbers or { } +catcodes.names = catcodes.names or { } + +storage.register("catcodes/numbers", catcodes.numbers, "catcodes.numbers") +storage.register("catcodes/names", catcodes.names, "catcodes.names") + +local numbers = catcodes.numbers +local names = catcodes.names + +-- We register the catcode tables in the \type {tex} namespace as we have been doing +-- right from the start (when there wasn't much in that namespace). Normally +-- registration of a table only happens when we're in so called ini mode. Also, the +-- number of tables is rather small. + +function catcodes.register(name,number) + numbers[name] = number + local cnn = names[number] + if cnn then + cnn[#cnn+1] = name + else + names[number] = { name } + end + tex[name] = number -- downward compatible +end + +-- At runtime we need to populate the \type {tex} namespace again. + +for name, number in next, numbers do + tex[name] = number -- downward compatible +end + +-- We catch wrong usage. + +table.setmetatableindex(numbers,function(t,k) if type(k) == "number" then t[k] = k return k end end) +table.setmetatableindex(names, function(t,k) if type(k) == "string" then t[k] = k return k end end) diff --git a/tex/context/base/mkxl/catc-ini.mkxl b/tex/context/base/mkxl/catc-ini.mkxl index 84d58b977..b7844fe89 100644 --- a/tex/context/base/mkxl/catc-ini.mkxl +++ b/tex/context/base/mkxl/catc-ini.mkxl @@ -11,8 +11,8 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D We've split the functionality of syst-cat.* over more files -%D now so that we can load more selectively. +%D We've split the functionality of syst-cat.* over more files now so that we can +%D load more selectively. \registerctxluafile{catc-ini}{} @@ -50,12 +50,6 @@ % rather special and used in writing to file: \let\par\outputnewlinechar -% \protected\def\initializenewlinechar % operating system dependent -% {\begingroup -% \newlinechar\newlineasciicode -% \xdef\outputnewlinechar{^^J}% -% \endgroup} - \permanent\protected\def\initializenewlinechar % operating system dependent {\begingroup \letcharcode\newlineasciicode\relax @@ -63,17 +57,8 @@ \xdef\outputnewlinechar{\Uchar\newlineasciicode}% \endgroup} -%D We predefine some prefixes ahead of syst-aux and mult-sys. - -% We reserve 8 slots for catcodes. -% -% \def\??catcodelet {1>>} % let : \let -% \def\??catcodedef {2>>} % def : \def -% \def\??catcodeued {3>>} % ued : \protected\def -% \def\??catcodeget {4>>} % \meaning -% -% \def\??catcodetablet{5>>} -% \def\??catcodetablen{6>>} +%D We predefine some prefixes ahead of syst-aux and mult-sys. We reserve 8 slots for +%D catcodes. \installsystemnamespace {catcodelet} % let : \let \installsystemnamespace {catcodedef} % def : \def @@ -91,9 +76,8 @@ \permanent\protected\def\newcatcodetable#1% we could move the cctdefcounter to lua {\global\advance\c_syst_catcodes_n\plusone \gdefcsname\??catcodetablen\number\c_syst_catcodes_n\endcsname{\string#1}% logging - %\setnewconstant#1\c_syst_catcodes_n \immutable\integerdef#1\c_syst_catcodes_n - \ctxcommand{registercatcodetable("\expandafter\gobbleoneargument\string#1",\number#1)}} + \ctxlua{catcodes.register("\expandafter\gobbleoneargument\string#1",\number#1)}} \newtoks \everysetdefaultcatcodes @@ -199,24 +183,8 @@ \permanent\def\reinstatecatcodecommand{\afterassignment\syst_catcodes_reinstate_normal\c_syst_catcodes_b} -% \def\syst_catcodes_reinstate_normal % can be used when a direct definition has been done -% {\begingroup % and the selector has been lost -% \uccode\c_syst_catcodes_hack\c_syst_catcodes_b -% \catcode\uccode\c_syst_catcodes_hack\activecatcode -% \uppercase{\xdef~{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}}% -% \endgroup} - -% \def\syst_catcodes_reinstate_unexpanded % can be used when a direct definition has been done -% {\begingroup % and the selector has been lost -% \uccode\c_syst_catcodes_hack\c_syst_catcodes_b -% \catcode\uccode\c_syst_catcodes_hack\activecatcode -% \uppercase{\protected\xdef~{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}}% -% \endgroup} - %D This can be used when a direct definition has been done and the selector has been -%D lost. - -% problem: \next needs to be unique (as it gets bound) +%D lost. A problem is that \type {\next} needs to be unique (as it gets bound) (still?). \def\syst_catcodes_reinstate_normal {\begingroup @@ -243,13 +211,14 @@ %D {restorecatcodes,pushcatcodetable,popcatcodetable} %D %D We're not finished dealing \CATCODES\ yet. In \CONTEXT\ we use only one auxiliary -%D file, which deals with tables of contents, registers, two pass tracking, references -%D etc. This file, as well as files concerning graphics, is processed when needed, -%D which can be in the mid of typesetting verbatim. However, when reading in data in -%D verbatim mode, we should temporary restore the normal \CATCODES, and that's exactly -%D what the next macros do. Saving the catcodes can be disabled by saying \type -%D {\localcatcodestrue}. In \MKIV\ instead we can push and pop catcode tables and as -%D we keep track of used tables users seldom need to deal with this themselves. +%D file, which deals with tables of contents, registers, two pass tracking, +%D references etc. This file, as well as files concerning graphics, is processed +%D when needed, which can be in the mid of typesetting verbatim. However, when +%D reading in data in verbatim mode, we should temporary restore the normal +%D \CATCODES, and that's exactly what the next macros do. Saving the catcodes can be +%D disabled by saying \type {\localcatcodestrue}. In \MKIV\ instead we can push and +%D pop catcode tables and as we keep track of used tables users seldom need to deal +%D with this themselves. \newcount\c_syst_catcodes_level @@ -277,11 +246,8 @@ \expandafter\catcodetable\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname \fi} -% \newtoks\everycatcodetable - \permanent\protected\def\setcatcodetable#1% {\catcodetable#1% -% \the\everycatcodetable \syst_catcodes_trace_set} %D Handy for debugging: @@ -324,6 +290,6 @@ \newcatcodetable \inicatcodes \initcatcodetable\inicatcodes -\let\currentcatcodetable\catcodetable +\mutable\let\currentcatcodetable\catcodetable \endinput diff --git a/tex/context/base/mkxl/colo-ini.mkxl b/tex/context/base/mkxl/colo-ini.mkxl index b71ac42d9..e6ec0d103 100644 --- a/tex/context/base/mkxl/colo-ini.mkxl +++ b/tex/context/base/mkxl/colo-ini.mkxl @@ -61,10 +61,10 @@ \let\m_colo_weight_gray\v!yes -\let\currentcolormodel \empty -\let\currentcolorname \empty -\let\currentcolorpalet \empty -\let\currentcolorprefix\empty % \currentcolorpalet: +\mutable\let\currentcolormodel \empty +\mutable\let\currentcolorname \empty +\mutable\let\currentcolorpalet \empty +\mutable\let\currentcolorprefix\empty % \currentcolorpalet: %D \macros %D {definecolor,defineglobalcolor,definenamedcolor,definespotcolor,definemultitonecolor, diff --git a/tex/context/base/mkxl/cont-new.mkxl b/tex/context/base/mkxl/cont-new.mkxl index 97b96b8cc..af62340bd 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{2020.11.26 15:38} +\newcontextversion{2020.11.27 20: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 c324d3917..d427c6c44 100644 --- a/tex/context/base/mkxl/context.mkxl +++ b/tex/context/base/mkxl/context.mkxl @@ -28,8 +28,8 @@ %D dependencies are more consistent. Beware, the version number has to match \type %D {YYYY.MM.DD HH:MM} format. -\edef\contextformat {\jobname} -\edef\contextversion{2020.11.26 15:38} +\immutable\edef\contextformat {\jobname} +\immutable\edef\contextversion{2020.11.27 20:07} %overloadmode 1 % check frozen / warning %overloadmode 2 % check frozen / error @@ -38,17 +38,17 @@ %D Kind of special: -\chardef\contextlmtxmode\directlua{tex.print(CONTEXTLMTXMODE or 0)}\relax +\immutable\chardef\contextlmtxmode\directlua{tex.print(CONTEXTLMTXMODE or 0)}\relax %D For those who want to use this: -\let\fmtname \contextformat -\let\fmtversion\contextversion +\aliased\let\fmtname \contextformat +\aliased\let\fmtversion\contextversion %D Loading: -\edef\mksuffix {mkiv} -\edef\contextmark{LMTX} +\immutable\edef\mksuffix {mkiv} +\immutable\edef\contextmark{LMTX} \ifdefined\normalinput \else \let\normalinput\input \fi diff --git a/tex/context/base/mkxl/file-mod.mklx b/tex/context/base/mkxl/file-mod.mklx index a95ac3483..2f9f13f1c 100644 --- a/tex/context/base/mkxl/file-mod.mklx +++ b/tex/context/base/mkxl/file-mod.mklx @@ -31,9 +31,9 @@ \installcorenamespace{module} -\let\currentmodule \s!unknown -\let\currentmodulecategory \empty -\let\currentmoduleparameters\empty +\mutable\let\currentmodule \s!unknown +\mutable\let\currentmodulecategory \empty +\mutable\let\currentmoduleparameters\empty \installmacrostack\currentmodule \installmacrostack\currentmodulecategory diff --git a/tex/context/base/mkxl/font-lib.mklx b/tex/context/base/mkxl/font-lib.mklx index 4a0c1627f..509e8ed86 100644 --- a/tex/context/base/mkxl/font-lib.mklx +++ b/tex/context/base/mkxl/font-lib.mklx @@ -41,7 +41,7 @@ \registerctxluafile{font-oto}{} \registerctxluafile{font-otj}{optimize} \registerctxluafile{font-oup}{} -\registerctxluafile{font-ota}{} +\registerctxluafile{font-ota}{autosuffix} \registerctxluafile{font-ots}{optimize} \registerctxluafile{font-otd}{optimize} \registerctxluafile{font-otc}{} diff --git a/tex/context/base/mkxl/font-mat.mklx b/tex/context/base/mkxl/font-mat.mklx index c81b7c5c7..b3008b6be 100644 --- a/tex/context/base/mkxl/font-mat.mklx +++ b/tex/context/base/mkxl/font-mat.mklx @@ -416,7 +416,7 @@ \newconditional\c_math_bold -\protected\def\mr % math regular +\permanent\protected\def\mr % math regular {\ifmmode \font_helpers_synchronize_math_family_mr \else @@ -425,7 +425,7 @@ \mathdefault \setfalse\c_math_bold} -\protected\def\mb % math bold +\permanent\protected\def\mb % math bold {\ifmmode \font_helpers_synchronize_math_family_mb \else @@ -463,13 +463,13 @@ \fi \to \everymathematics -\protected\def\nobigmath {\synchronizebigmathflag\zerocount} -\protected\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath} -\protected\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath} +\permanent\protected\def\nobigmath {\synchronizebigmathflag\zerocount} +\permanent\protected\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath} +\permanent\protected\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath} -\let\bigmathfontsize\empty +\mutable\let\bigmathfontsize\empty -\protected\def\synchronizebigmath +\permanent\protected\def\synchronizebigmath {\ifx\bigmathfontsize\fontsize % already in sync \else diff --git a/tex/context/base/mkxl/font-ota.lmt b/tex/context/base/mkxl/font-ota.lmt new file mode 100644 index 000000000..8f6c059ef --- /dev/null +++ b/tex/context/base/mkxl/font-ota.lmt @@ -0,0 +1,569 @@ +if not modules then modules = { } end modules ['font-ota'] = { + version = 1.001, + comment = "companion to font-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- context only + +local type = type +local setmetatableindex = table.setmetatableindex + +if not trackers then trackers = { register = function() end } end + +----- trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end) + +local fonts, nodes, node = fonts, nodes, node + +local allocate = utilities.storage.allocate + +local otf = fonts.handlers.otf + +local analyzers = fonts.analyzers +local initializers = allocate() +local methods = allocate() + +analyzers.initializers = initializers +analyzers.methods = methods + +local nuts = nodes.nuts +local tonut = nuts.tonut + +local getnext = nuts.getnext +local getprev = nuts.getprev +local getprev = nuts.getprev +local getprop = nuts.getprop +local setprop = nuts.setprop +local getsubtype = nuts.getsubtype +local getchar = nuts.getchar +local ischar = nuts.ischar + +local end_of_math = nuts.end_of_math + +local nodecodes = nodes.nodecodes +local disc_code = nodecodes.disc +local math_code = nodecodes.math + +local fontdata = fonts.hashes.identifiers +local descriptiondata = fonts.hashes.descriptions +local categories = characters and characters.categories or { } -- sorry, only in context +local chardata = characters and characters.data + +local otffeatures = fonts.constructors.features.otf +local registerotffeature = otffeatures.register + +--[[ldx-- +<p>Analyzers run per script and/or language and are needed in order to +process features right.</p> +--ldx]]-- + +local setstate = nuts.setstate +local getstate = nuts.getstate + +local classifiers = characters.classifiers + +-- never use these numbers directly + +local s_init = 1 local s_rphf = 7 +local s_medi = 2 local s_half = 8 +local s_fina = 3 local s_pref = 9 +local s_isol = 4 local s_blwf = 10 +local s_mark = 5 local s_pstf = 11 +local s_rest = 6 + +local states = allocate { + init = s_init, + medi = s_medi, + med2 = s_medi, + fina = s_fina, + fin2 = s_fina, + fin3 = s_fina, + isol = s_isol, + mark = s_mark, + rest = s_rest, + rphf = s_rphf, + half = s_half, + pref = s_pref, + blwf = s_blwf, + pstf = s_pstf, +} + +local features = allocate { + init = s_init, + medi = s_medi, + med2 = s_medi, + fina = s_fina, + fin2 = s_fina, + fin3 = s_fina, + isol = s_isol, + -- mark = s_mark, + -- rest = s_rest, + rphf = s_rphf, + half = s_half, + pref = s_pref, + blwf = s_blwf, + pstf = s_pstf, +} + +local mappers = allocate { + l = s_init, -- left + d = s_medi, -- double + c = s_medi, -- joiner + r = s_fina, -- right + u = s_isol, -- nonjoiner +} + +analyzers.states = states +analyzers.features = features +analyzers.useunicodemarks = false + +if not classifiers then + + -- why not just always use categories[k] = "mn" + + local f_arabic, l_arabic = characters.blockrange("arabic") + local f_syriac, l_syriac = characters.blockrange("syriac") + local f_mandiac, l_mandiac = characters.blockrange("mandiac") + local f_nko, l_nko = characters.blockrange("nko") + local f_ext_a, l_ext_a = characters.blockrange("arabicextendeda") + + classifiers = setmetatableindex(function(t,k) + if type(k) == "number" then + local c = chardata[k] + local v = false + if c then + local arabic = c.arabic + if arabic then + v = mappers[arabic] + if not v then + log.report("analyze","error in mapping arabic %C",k) + -- error + v = false + end + elseif (k >= f_arabic and k <= l_arabic) or + (k >= f_syriac and k <= l_syriac) or + (k >= f_mandiac and k <= l_mandiac) or + (k >= f_nko and k <= l_nko) or + (k >= f_ext_a and k <= l_ext_a) then + if categories[k] == "mn" then + v = s_mark + else + v = s_rest + end + end + end + t[k] = v + return v + end + end) + + characters.classifiers = classifiers + +end + +-- todo: analyzers per script/lang, cross font, so we need an font id hash -> script +-- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace + +local is_letter = characters.is_letter +local is_mark = characters.is_mark + +function analyzers.setstate(head,font) -- latin + local useunicodemarks = analyzers.useunicodemarks + local descriptions = descriptiondata[font] + local first = false + local last = false + local current = head + local done = false + -- only letters + while current do + local char, id = ischar(current,font) + if char then + if not getstate(current) then + -- local d = descriptions[char] + -- if d then + -- if d.class == "mark" or (useunicodemarks and categories[char] == "mn") then + if is_mark[char] then + setstate(current,s_mark) + elseif is_letter[char] then + if first then + setstate(current,s_medi) + else + setstate(current,s_init) + first = current + done = true + end + last = current + else + goto PICKUP + end + goto NEXT + -- end + end + ::PICKUP:: + if first then + setstate(last,first == last and s_isol or s_fina) + end + first = false + elseif char == false then + -- other font + if first then + setstate(last,first == last and s_isol or s_fina) + end + first = false + if id == math_code then + current = end_of_math(current) + end + elseif id == disc_code then + -- always in the middle .. it doesn't make much sense to assign a property + -- here ... we might at some point decide to flag the components when present + -- but even then it's kind of bogus + setstate(current,s_medi) + last = current + else -- finish + if first then + setstate(last,first == last and s_isol or s_fina) + end + first = false + if id == math_code then + current = end_of_math(current) + end + end + ::NEXT:: + current = getnext(current) + end + if first then + setstate(last,first == last and s_isol or s_fina) + end + return head, done +end + +-- in the future we will use language/script attributes instead of the +-- font related value, but then we also need dynamic features which is +-- somewhat slower; and .. we need a chain of them + +local function analyzeinitializer(tfmdata,value) -- attr + local script, language = otf.scriptandlanguage(tfmdata) -- attr + local action = initializers[script] + if not action then + -- skip + elseif type(action) == "function" then + return action(tfmdata,value) + else + local action = action[language] + if action then + return action(tfmdata,value) + end + end +end + +local function analyzeprocessor(head,font,attr) + local tfmdata = fontdata[font] + local script, language = otf.scriptandlanguage(tfmdata,attr) + local action = methods[script] + if not action then + -- skip + elseif type(action) == "function" then + return action(head,font,attr) + else + action = action[language] + if action then + return action(head,font,attr) + end + end + return head, false +end + +registerotffeature { + name = "analyze", + description = "analysis of character classes", + default = true, + initializers = { + node = analyzeinitializer, + }, + processors = { + position = 1, + node = analyzeprocessor, + } +} + +-- latin + +methods.latn = analyzers.setstate +-------.dflt = analyzers.setstate % can be an option or just the default + +local arab_warned = { } + +local function warning(current,what) + local char = getchar(current) + if not arab_warned[char] then + log.report("analyze","arab: character %C has no %a class",char,what) + arab_warned[char] = true + end +end + +-- we can also use this trick for devanagari + +function methods.arab(head,font,attr) + local first, last, c_first, c_last + local current = head + local done = false + current = tonut(current) + while current do + local char, id = ischar(current,font) + if char and not getstate(current) then + done = true + local classifier = classifiers[char] + if not classifier then + if last then + if c_last == s_medi or c_last == s_fina then + setstate(last,s_fina) + else + warning(last,"fina") + setstate(last,s_error) + end + first = nil + last = nil + elseif first then + if c_first == s_medi or c_first == s_fina then + setstate(first,s_isol) + else + warning(first,"isol") + setstate(first,s_error) + end + first = nil + end + elseif classifier == s_mark then + setstate(current,s_mark) + elseif classifier == s_isol then + if last then + if c_last == s_medi or c_last == s_fina then + setstate(last,s_fina) + else + warning(last,"fina") + setstate(last,s_error) + end + first = nil + last = nil + elseif first then + if c_first == s_medi or c_first == s_fina then + setstate(first,s_isol) + else + warning(first,"isol") + setstate(first,s_error) + end + first = nil + end + setstate(current,s_isol) + elseif classifier == s_medi then + if first then + last = current + c_last = classifier + setstate(current,s_medi) + else + setstate(current,s_init) + first = current + c_first = classifier + end + elseif classifier == s_fina then + if last then + if getstate(last) ~= s_init then + setstate(last,s_medi) + end + setstate(current,s_fina) + first, last = nil, nil + elseif first then + -- if getstate(first) ~= s_init then + -- -- needs checking + -- setstate(first,s_medi) + -- end + setstate(current,s_fina) + first = nil + else + setstate(current,s_isol) + end + else -- classifier == s_rest + setstate(current,s_rest) + if last then + if c_last == s_medi or c_last == s_fina then + setstate(last,s_fina) + else + warning(last,"fina") + setstate(last,s_error) + end + first = nil + last = nil + elseif first then + if c_first == s_medi or c_first == s_fina then + setstate(first,s_isol) + else + warning(first,"isol") + setstate(first,s_error) + end + first = nil + end + end + else + if last then + if c_last == s_medi or c_last == s_fina then + setstate(last,s_fina) + else + warning(last,"fina") + setstate(last,s_error) + end + first = nil + last = nil + elseif first then + if c_first == s_medi or c_first == s_fina then + setstate(first,s_isol) + else + warning(first,"isol") + setstate(first,s_error) + end + first = nil + end + if id == math_code then -- a bit duplicate as we test for glyphs twice + current = end_of_math(current) + end + end + current = getnext(current) + end + if last then + if c_last == s_medi or c_last == s_fina then + setstate(last,s_fina) + else + warning(last,"fina") + setstate(last,s_error) + end + elseif first then + if c_first == s_medi or c_first == s_fina then + setstate(first,s_isol) + else + warning(first,"isol") + setstate(first,s_error) + end + end + return head, done +end + +methods.syrc = methods.arab +methods.mand = methods.arab +methods.nko = methods.arab + +-- a quick first attemp .. more later + +do + + -- https://github.com/n8willis/opentype-shaping-documents/blob/master/opentype-shaping-mongolian.md#joining-properties + -- todo syrc + + local joining = setmetatableindex(function(t,k) + if type(k) == "number" then + local c = chardata[k] + local v = false + if c then + local mongolian = c.mongolian + -- + v = mongolian + end + t[k] = v + return v + end + end) + + function methods.mong(head,font,attr) + local first, last + local current = head + local done = false + local prevjoin = nil + local prestate = nil + current = tonut(current) + + local function wrapup() + if last then + if last ~= first then + local s = getstate(last) + if s == s_medi then + setstate(last,s_fina) + elseif s == s_init then + setstate(last,s_isol) + end + end + last = nil + first = nil + prevjoin = nil + prestate = nil + end + end + + while current do + local char, id = ischar(current,font) + if char and not getstate(current) then + local currjoin = joining[char] + done = true + if not last then + setstate(current,s_isol) + prevjoin = currjoin + first = current + last = current + prevstate = s_isol + elseif currjoin == "t" then -- transparent + -- keep state + last = current + elseif prevjoin == "d" or prevjoin == "jc" or prevjoin == "l" then + if currjoin == "d" or prevjoin == "jc" or prevjoin == "r" then + local s = getstate(last) + if s == s_isol then + setstate(last,s_init) + elseif s == s_fina then + setstate(last,s_medi) + end + setstate(current,s_fina) + prevstate = s_fina + elseif prevjoin == "nj" or prevjoin == "l" then + local s = getstate(last) + if s == s_medi then + setstate(last,s_fina) + elseif s == s_init then + setstate(last,s_isol) + end + setstate(current,s_isol) + prevstate = s_isol + end + prevjoin = currjoin + last = current + elseif prevjoin == "nj" or prevjoin == "r" then + if s == s_medi then + setstate(last,s_fina) + elseif s == s_init then + setstate(last,s_isol) + end + setstate(current,s_isol) + prevjoin = currjoin + prevstate = s_isol + last = current + elseif last then + wrapup() + end + else + if last then + wrapup() + end + if id == math_code then -- a bit duplicate as we test for glyphs twice + current = end_of_math(current) + end + end + current = getnext(current) + end + if last then + wrapup() + end + return head, done + end + +end + +directives.register("otf.analyze.useunicodemarks",function(v) + analyzers.useunicodemarks = v +end) diff --git a/tex/context/base/mkxl/lang-ini.mkxl b/tex/context/base/mkxl/lang-ini.mkxl index e55075d84..e115ce9f8 100644 --- a/tex/context/base/mkxl/lang-ini.mkxl +++ b/tex/context/base/mkxl/lang-ini.mkxl @@ -552,9 +552,9 @@ \permanent\protected\def\language {\doifelsenextoptionalcs\lang_basics_set_current\normallanguage} - \let\setlanguage\language % we make these synonyms + \aliased\let\setlanguage\language % we make these synonyms - \let\patterns\gobbleoneargument + \aliased\let\patterns\gobbleoneargument \popoverloadmode diff --git a/tex/context/base/mkxl/luat-ini.mkxl b/tex/context/base/mkxl/luat-ini.mkxl index 4f6556eda..472e8326e 100644 --- a/tex/context/base/mkxl/luat-ini.mkxl +++ b/tex/context/base/mkxl/luat-ini.mkxl @@ -273,23 +273,23 @@ % % \installctxfunction\foo{commands.foo} -\protected\def\installctxfunction#1#2% expandable +\permanent\protected\def\installctxfunction#1#2% expandable {\edef\m_syst_name{\csstring#1}% \global\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxfunction(\!!bs#2\!!es,true)}\relax} -\protected\def\installctxscanner#1#2% expandable +\permanent\protected\def\installctxscanner#1#2% expandable {\edef\m_syst_name{\csstring#1}% \global\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name",\!!bs#2\!!es,true)}\relax} -\protected\def\installprotectedctxfunction#1#2% protected +\permanent\protected\def\installprotectedctxfunction#1#2% protected {\edef\m_syst_name{\csstring#1}% \global\protected\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxfunction(\!!bs#2\!!es,true)}\relax} -\protected\def\installprotectedctxscanner#1#2% protected +\permanent\protected\def\installprotectedctxscanner#1#2% protected {\edef\m_syst_name{\csstring#1}% \global\protected\expandafter\normalluadef\csname\m_syst_name\endcsname\ctxcommand{ctxscanner("\m_syst_name",\!!bs#2\!!es,true)}\relax} -\protected\def\resetctxscanner#1% +\permanent\protected\def\resetctxscanner#1% {\edef\m_syst_name{\csstring#1}% \gletcsname\m_syst_name\endcsname\relax} diff --git a/tex/context/base/mkxl/math-ali.mkxl b/tex/context/base/mkxl/math-ali.mkxl index 70566d5b6..d7d7088c1 100644 --- a/tex/context/base/mkxl/math-ali.mkxl +++ b/tex/context/base/mkxl/math-ali.mkxl @@ -38,6 +38,7 @@ \newtoks\t_math_align_c \newskip\d_math_eqalign_distance +\newskip\d_math_eqalign_rulethickness \protected\def\math_eqalign_distance {\relax @@ -806,7 +807,9 @@ [\c!distance=\emwidth, \c!left=, \c!right=, - \c!align=\v!middle] + \c!align=\v!middle, + \c!rulecolor=, + \c!rulethickness=\linewidth] \appendtoks \frozen\instance\setuevalue{\e!start\currentmathmatrix}{\math_matrix_start[\currentmathmatrix]}% @@ -894,15 +897,55 @@ % \crcr % \noalign{\vskip-\struthtdp}} +\def\math_matrix_check_rule_step#1% + {\doifelsenumber{#1} + {\scratchdimen#1\d_math_eqalign_rulethickness} + {\edef\p_rulecolor{#1}}} + +\def\math_matrix_check_rule[#1]% + {\d_math_eqalign_rulethickness\mathmatrixparameter\c!rulethickness\relax + \scratchdimen\d_math_eqalign_rulethickness + \edef\p_rulecolor{\mathmatrixparameter\c!rulecolor}% + \iftok{#1}\emptytoks\else + \rawprocesscommalist[#1]\math_matrix_check_rule_step + \fi + \ifempty\p_rulecolor\else + \dousecolorparameter\p_rulecolor + \fi} + +\noaligned\permanent\tolerant\protected\def\math_matrix_HL[#1]#*% + {\noalign\bgroup + \math_matrix_check_rule[#1]% + \divide\scratchdimen\plustwo + \autorule\s!height\scratchdimen\s!depth\scratchdimen\relax + \egroup} + +\permanent\tolerant\protected\def\math_matrix_VL[#1]#*% + {\NC + \math_matrix_check_rule[#1]% + \divide\d_math_eqalign_distance\plustwo + \hskip-\d_math_eqalign_distance + \autorule\s!width\scratchdimen\relax + \hskip-\d_math_eqalign_distance + \NC} + +\newtoks\everymathmatrix + +\appendtoks + \enforced\let\NR\math_matrix_NR + \enforced\let\NC\math_matrix_NC + \enforced\let\MC\math_matrix_NC + \enforced\let\HL\math_matrix_HL + \enforced\let\VL\math_matrix_VL + \enforced\let\TB\math_common_TB +\to \everymathmatrix + \def\math_matrix_start_processing {\dontleavehmode \bgroup \tabskip\zeropoint \math_matrix_pickup - \enforced\let\NR\math_matrix_NR - \enforced\let\NC\math_matrix_NC - \enforced\let\MC\math_matrix_NC - \enforced\let\TB\math_common_TB + \the\everymathmatrix % \enforced\let\endmath\relax % @@ -940,6 +983,8 @@ \fi \fi \d_math_eqalign_distance\mathmatrixparameter\c!distance\relax + % \d_math_eqalign_rulethickness\mathmatrixparameter\c!rulethickness\relax + % \edef\p_rulecolor{\mathmatrixparameter\c!rulecolor} \edef\math_matrix_set_style{\mathmatrixparameter\c!style}} \def\math_matrix_set_defaults diff --git a/tex/context/base/mkxl/math-def.mkxl b/tex/context/base/mkxl/math-def.mkxl index 29ad9b465..040005293 100644 --- a/tex/context/base/mkxl/math-def.mkxl +++ b/tex/context/base/mkxl/math-def.mkxl @@ -80,7 +80,8 @@ \permanent\protected\def\setoperatorlimits#1#2% operator limits {\savenormalmeaning{#1}% - \expandafter\def\expandafter#1\expandafter{\csname normal\csstring#1\endcsname#2}} + %frozen\protected\expandafter\def\expandafter#1\expandafter{\csname normal\csstring#1\endcsname#2}} + \frozen\protected\edef#1{\expandafter\noexpand\csname normal\csstring#1\endcsname\noexpand#2}} \pushoverloadmode diff --git a/tex/context/base/mkxl/math-fen.mkxl b/tex/context/base/mkxl/math-fen.mkxl index f18d72c85..2e491f28b 100644 --- a/tex/context/base/mkxl/math-fen.mkxl +++ b/tex/context/base/mkxl/math-fen.mkxl @@ -390,7 +390,7 @@ \newconditional\c_math_fenced_done \newconditional\c_math_fenced_unknown \settrue\c_math_fenced_unknown -\protected\def\installmathfencepair#1#2#3#4% +\permanent\protected\def\installmathfencepair#1#2#3#4% {\letcsname\??mathleft \normalmeaning#1\endcsname#2% \letcsname\??mathright\normalmeaning#3\endcsname#4} diff --git a/tex/context/base/mkxl/math-ini.mkxl b/tex/context/base/mkxl/math-ini.mkxl index 7838d8fde..91946bcdb 100644 --- a/tex/context/base/mkxl/math-ini.mkxl +++ b/tex/context/base/mkxl/math-ini.mkxl @@ -409,18 +409,18 @@ % todo: only in mmode % these commands are semi-public but should not be used directly (lua names wil change) -\protected\def\math_set_attribute #1#2{\ifmmode\clf_setmathattribute{#1}{#2}\fi} -\protected\def\math_set_alphabet #1{\ifmmode\clf_setmathalphabet{#1}\fi} -\protected\def\math_set_font_style #1{\ifmmode\clf_setmathstyle{#1}\fi} -\protected\def\math_set_font_alternate#1{\ifmmode\clf_setmathalternate\defaultmathfamily{#1}\fi} +\permanent\protected\def\setmathattribute #1#2{\ifmmode\clf_setmathattribute{#1}{#2}\fi} +\permanent\protected\def\setmathalphabet #1{\ifmmode\clf_setmathalphabet{#1}\fi} +\permanent\protected\def\setmathfontstyle #1{\ifmmode\clf_setmathstyle{#1}\fi} +\permanent\protected\def\setmathfontalternate#1{\ifmmode\clf_setmathalternate\defaultmathfamily{#1}\fi} \installcorenamespace{mathstylealternative} % might become a setuphandler -\protected\def\math_set_font_style_alternate#1% +\permanent\protected\def\setmathfontstylealternate#1% {\ifcsname\??mathstylealternative\fontclass:#1\endcsname - \expandafter\math_set_font_alternate\lastnamedcs + \expandafter\setmathfontalternate\lastnamedcs \orelse\ifcsname\??mathstylealternative#1\endcsname - \expandafter\math_set_font_alternate\lastnamedcs + \expandafter\setmathfontalternate\lastnamedcs \fi} \permanent\tolerant\protected\def\setupmathrendering[#1]#*[#2]% the name might change @@ -457,10 +457,10 @@ \enforced\let\dotlessj\dotlessj \popoverloadmode -\permanent\protected\def\mathaltcalligraphic{\math_set_font_alternate{calligraphic}\cal} % set via goody file -\permanent\protected\def\mathaltitalic {\math_set_font_alternate{italic}} % set via goody file -\permanent\protected\def\mathslashedzero {\begingroup\math_set_font_alternate{zero}∅\endgroup} % set via goody file or automatic -\permanent\protected\def\mathdotless {\math_set_font_alternate{dotless}} % set via goody file or automatic +\permanent\protected\def\mathaltcalligraphic{\setmathfontalternate{calligraphic}\cal} % set via goody file +\permanent\protected\def\mathaltitalic {\setmathfontalternate{italic}} % set via goody file +\permanent\protected\def\mathslashedzero {\begingroup\setmathfontalternate{zero}∅\endgroup} % set via goody file or automatic +\permanent\protected\def\mathdotless {\setmathfontalternate{dotless}} % set via goody file or automatic \permanent\protected\def\mathdotlessi {\begingroup\mathdotless i\endgroup} \permanent\protected\def\mathdotlessj {\begingroup\mathdotless j\endgroup} @@ -477,35 +477,29 @@ \enforced\let\dotlessj\autodotlessj \to \everymathematics -\let\setmathattribute \math_set_attribute -\let\setmathalphabet \math_set_alphabet -\let\setmathfontstyle \math_set_font_style -\let\setmathfontalternate \math_set_font_alternate -\let\setmathfontalternative \math_set_font_alternate -\let\setmathfontstylealternate \math_set_font_style_alternate -\let\setmathfontstylealternative\math_set_font_style_alternate +\aliased\let\setmathfontalternative \setmathfontalternate +\aliased\let\setmathfontstylealternative\setmathfontstylealternate +\aliased\let\mathalternate \setmathfontalternate -\let\mathalternate \math_set_font_alternate +\permanent\protected\def\mathupright {\setmathattribute\s!regular\s!tf\setmathfontstylealternate\s!tf} +\permanent\protected\def\mathitalic {\setmathattribute\s!regular\s!it\setmathfontstylealternate\s!it} +\permanent\protected\def\mathscript {\setmathalphabet \s!script \setmathfontstylealternate\s!script} +\permanent\protected\def\mathfraktur {\setmathalphabet \s!fraktur \setmathfontstylealternate\s!fraktur} +\permanent\protected\def\mathblackboard{\setmathalphabet \s!blackboard \setmathfontstylealternate\s!blackboard} -\permanent\protected\def\mathupright {\math_set_attribute\s!regular\s!tf\math_set_font_style_alternate\s!tf} -\permanent\protected\def\mathitalic {\math_set_attribute\s!regular\s!it\math_set_font_style_alternate\s!it} -\permanent\protected\def\mathscript {\math_set_alphabet \s!script \math_set_font_style_alternate\s!script} -\permanent\protected\def\mathfraktur {\math_set_alphabet \s!fraktur \math_set_font_style_alternate\s!fraktur} -\permanent\protected\def\mathblackboard{\math_set_alphabet \s!blackboard \math_set_font_style_alternate\s!blackboard} +\permanent\protected\def\mathrm {\setmathattribute\s!rm\s!tf \setmathfontstylealternate\s!tf} +\permanent\protected\def\mathss {\setmathattribute\s!ss\s!tf \setmathfontstylealternate\s!tf} +\permanent\protected\def\mathtt {\setmathattribute\s!tt\s!tf \setmathfontstylealternate\s!tf} -\permanent\protected\def\mathrm {\math_set_attribute\s!rm\s!tf \math_set_font_style_alternate\s!tf} -\permanent\protected\def\mathss {\math_set_attribute\s!ss\s!tf \math_set_font_style_alternate\s!tf} -\permanent\protected\def\mathtt {\math_set_attribute\s!tt\s!tf \math_set_font_style_alternate\s!tf} +\permanent\protected\def\mathtf {\setmathfontstyle\s!tf \setmathfontstylealternate\s!tf} +\permanent\protected\def\mathsl {\setmathfontstyle\s!it \setmathfontstylealternate\s!it} % no sl +\permanent\protected\def\mathit {\setmathfontstyle\s!it \setmathfontstylealternate\s!it} -\permanent\protected\def\mathtf {\math_set_font_style\s!tf \math_set_font_style_alternate\s!tf} -\permanent\protected\def\mathsl {\math_set_font_style\s!it \math_set_font_style_alternate\s!it} % no sl -\permanent\protected\def\mathit {\math_set_font_style\s!it \math_set_font_style_alternate\s!it} +\permanent\protected\def\mathbf {\setmathfontstyle\s!bf \setmathfontstylealternate\s!bf} +\permanent\protected\def\mathbs {\setmathfontstyle\s!bi \setmathfontstylealternate\s!bi} % no sl +\permanent\protected\def\mathbi {\setmathfontstyle\s!bi \setmathfontstylealternate\s!bi} -\permanent\protected\def\mathbf {\math_set_font_style\s!bf \math_set_font_style_alternate\s!bf} -\permanent\protected\def\mathbs {\math_set_font_style\s!bi \math_set_font_style_alternate\s!bi} % no sl -\permanent\protected\def\mathbi {\math_set_font_style\s!bi \math_set_font_style_alternate\s!bi} - -\let\mathdefault\mathitalic +\aliased\let\mathdefault\mathitalic \appendtoks \edef\p_default{\mathematicsparameter\c!default}% diff --git a/tex/context/base/mkxl/math-pln.mkxl b/tex/context/base/mkxl/math-pln.mkxl index c5d814fbe..e386eb72d 100644 --- a/tex/context/base/mkxl/math-pln.mkxl +++ b/tex/context/base/mkxl/math-pln.mkxl @@ -23,7 +23,7 @@ % might change -\protected\def\hrulefill{\leaders\hrule\hfill} +\permanent\protected\def\hrulefill{\leaders\hrule\hfill} %protected\def\dotfill {\cleaders\hbox{\normalstartimath\mathsurround\zeropoint\mkern1.5mu.\mkern1.5mu\normalstopimath}\hfill} % will move diff --git a/tex/context/base/mkxl/meta-ini.mkxl b/tex/context/base/mkxl/meta-ini.mkxl index c715cbca5..4bf9134f9 100644 --- a/tex/context/base/mkxl/meta-ini.mkxl +++ b/tex/context/base/mkxl/meta-ini.mkxl @@ -403,12 +403,15 @@ \aliased\let\stopMPclip\relax +\mutable\def\width {0 } % left-over +\mutable\def\height{0 } % left-over + \protected\def\meta_grab_clip_path#1#2#3% {\begingroup \d_overlay_width #2\relax \d_overlay_height#3\relax - \edef\width {\the\d_overlay_width \space}% - \edef\height{\the\d_overlay_height\space}% + \edef\width {\the\d_overlay_width \space}% hm + \edef\height{\the\d_overlay_height\space}% hm \edef\currentMPclip{#1}% \ifcsname\??mpclip\currentMPclip\endcsname \meta_grab_clip_path_yes @@ -992,22 +995,10 @@ % \setupcolors[state=stop,conversion=never] % quite tricky ... type mismatch -% \startMPextensions -% color OverlayColor,OverlayLineColor; -% \stopMPextensions - \startMPinitializations CurrentLayout:="\currentlayout"; \stopMPinitializations -% \startMPinitializations -% OverlayWidth:=\overlaywidth; -% OverlayHeight:=\overlayheight; -% OverlayDepth:=\overlaydepth; -% OverlayLineWidth:=\overlaylinewidth; -% OverlayOffset:=\overlayoffset; -% \stopMPinitializations - %D A dirty trick, ** in colo-ini.lua (mpcolor). We cannot use a vardef, because %D that fails with spot colors. @@ -1016,53 +1007,11 @@ def OverlayColor =\ifempty\overlaycolor black \else\MPcolor{\overlaycolor} \fi enddef; \stopMPinitializations -% \newcount\c_overlay_colormodel -% \newcount\c_overlay_color -% \newcount\c_overlay_transparency -% \newcount\c_overlay_linecolor -% \newcount\c_overlay_linetransparency - -% \appendtoks -% \c_overlay_colormodel \c_attr_colormodel -% \c_overlay_color \colo_helpers_inherited_current_ca\overlaycolor -% \c_overlay_transparency \colo_helpers_inherited_current_ta\overlaycolor -% \c_overlay_linecolor \colo_helpers_inherited_current_ca\overlaylinecolor -% \c_overlay_linetransparency\colo_helpers_inherited_current_ta\overlaylinecolor -% \to \everyMPgraphic - -% \startMPinitializations -% BaseLineSkip:=\the\baselineskip; -% LineHeight:=\the\baselineskip; -% BodyFontSize:=\the\bodyfontsize; -% % -% TopSkip:=\the\topskip; -% StrutHeight:=\strutheight; -% StrutDepth:=\strutdepth; -% % -% CurrentWidth:=\the\hsize; -% CurrentHeight:=\the\vsize; -% HSize:=\the\hsize ; -% VSize:=\the\vsize ; -% % -% EmWidth:=\the\emwidth; -% ExHeight:=\the\exheight; -% \stopMPinitializations - \appendtoks \disablediscretionaries %\disablecompoundcharacters \to \everyMPgraphic -% \appendtoks % before color, inefficient, replace by low level copy -% \doregistercolor{currentcolor}\currentcolorname -% \to \everyMPgraphic - -% \color[green]{abc \startMPcode -% fill fullcircle scaled 3cm withoutcolor; -% fill fullcircle scaled 2cm withcolor \MPcolor{currentcolor} ; -% fill fullcircle scaled 1cm withcolor \MPcolor{red} ; -% \stopMPcode def} - \appendtoks \baselineskip1\baselineskip \lineheight 1\lineheight @@ -1099,14 +1048,6 @@ enddef ; \stopMPextensions -% \startMPextensions -% PageFraction := 1 ; -% \stopMPextensions - -% \startMPinitializations -% PageFraction := if \lastpage>1: (\realfolio-1)/(\lastpage-1) else: 1 fi ; -% \stopMPinitializations - \startMPdefinitions {metapost} if unknown context_bare : input mp-bare.mpiv ; fi ; \stopMPdefinitions diff --git a/tex/context/base/mkxl/mult-aux.mkxl b/tex/context/base/mkxl/mult-aux.mkxl index 9614f6cea..a8ab97fb1 100644 --- a/tex/context/base/mkxl/mult-aux.mkxl +++ b/tex/context/base/mkxl/mult-aux.mkxl @@ -352,11 +352,11 @@ \expandafter\noexpand\csname let#2parameter\endcsname \expandafter\noexpand\csname reset#2parameter\endcsname}} -\let\dousecurrentstyleparameter\relax -\let\dousecurrentcolorparameter\relax +\mutable\let\dousecurrentstyleparameter\relax +\mutable\let\dousecurrentcolorparameter\relax -\let\currentstyleparameter\empty -\let\currentcolorparameter\empty +\mutable\let\currentstyleparameter\empty +\mutable\let\currentcolorparameter\empty \protected\def\mult_interfaces_install_style_and_color_handler#1#2#3#4% {\frozen\protected\def#2##1##2% style color diff --git a/tex/context/base/mkxl/node-ini.lmt b/tex/context/base/mkxl/node-ini.lmt index 5cce9030d..0fba0a4d9 100644 --- a/tex/context/base/mkxl/node-ini.lmt +++ b/tex/context/base/mkxl/node-ini.lmt @@ -162,40 +162,6 @@ nodes.literalvalues = literalvalues nodes.nodecodes = nodecodes --- local subtypes = allocate { --- [nodecodes.glue] = gluecodes, --- [nodecodes.dir] = dircodes, --- [nodecodes.boundary] = boundarycodes, --- [nodecodes.noad] = noadcodes, --- [nodecodes.whatsit] = whatcodes, --- [nodecodes.glyph] = glyphcodes, --- [nodecodes.kern] = kerncodes, --- [nodecodes.penalty] = penaltycodes, --- [nodecodes.math] = mathcodes, --- [nodecodes.disc] = disccodes, --- [nodecodes.accent] = accentcodes, --- [nodecodes.radical] = radicalcodes, --- [nodecodes.fence] = fencecodes, --- [nodecodes.par] = parcodes, --- [nodecodes.rule] = rulecodes, - --- [nodecodes.vlist] = listcodes, --- [nodecodes.hlist] = listcodes, - --- -- [nodecodes.list] = listcodes, - --- -- [nodecodes.parameter] = parametercodes, --- -- [nodecodes.user] = usercodes, --- } - --- for k in next, table.sortedkeys(subtypes) do --- local v = nodecodes[k] --- print(k,v) --- if k and subtypes[k] then --- subtypes[v] = subtypes[k] --- end --- end - local subtypes = allocate { glue = gluecodes, dir = dircodes, @@ -276,5 +242,3 @@ end for i=0,#gluecodes do texsetintegervalue(gluecodes[i] .. "subtypecode",i,"immutable") end - --- tex.set("internalcodesmode",1) -- obsolete diff --git a/tex/context/base/mkxl/node-ref.lmt b/tex/context/base/mkxl/node-ref.lmt new file mode 100644 index 000000000..583f979b2 --- /dev/null +++ b/tex/context/base/mkxl/node-ref.lmt @@ -0,0 +1,811 @@ +if not modules then modules = { } end modules ['node-ref'] = { + version = 1.001, + optimize = true, + comment = "companion to node-ref.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- We supported pdf right from the start and in mkii this has resulted in +-- extensive control over the links. Nowadays pdftex provides a lot more +-- control over margins but as mkii supports multiple backends we stuck to +-- our own mechanisms. In mkiv again we implement our own handling. Eventually +-- we will even disable the pdf primitives. + +-- helper, will end up in luatex + +-- is grouplevel still used? + +local tonumber = tonumber +local concat = table.concat + +local attributes, nodes, node = attributes, nodes, node + +local allocate = utilities.storage.allocate, utilities.storage.mark +local mark = utilities.storage.allocate, utilities.storage.mark + +local nodeinjections = backends.nodeinjections +local codeinjections = backends.codeinjections + +local cleanupreferences = false +local cleanupdestinations = true + +local transparencies = attributes.transparencies +local colors = attributes.colors +local references = structures.references +local enableaction = nodes.tasks.enableaction + +local trace_references = false trackers.register("nodes.references", function(v) trace_references = v end) +local trace_destinations = false trackers.register("nodes.destinations", function(v) trace_destinations = v end) +local trace_areas = false trackers.register("nodes.areas", function(v) trace_areas = v end) +local show_references = false trackers.register("nodes.references.show", function(v) show_references = tonumber(v) or (v and 2.25 or false) end) +local show_destinations = false trackers.register("nodes.destinations.show", function(v) show_destinations = tonumber(v) or (v and 2.00 or false) end) + +local report_reference = logs.reporter("backend","references") +local report_destination = logs.reporter("backend","destinations") +local report_area = logs.reporter("backend","areas") + +local texsetcount = tex.setcount +----- texsetattribute = tex.setattribute + +local nuts = nodes.nuts +local nodepool = nuts.pool + +local tonode = nuts.tonode +local tonut = nuts.tonut + +local getfield = nuts.getfield +local setlink = nuts.setlink +local setnext = nuts.setnext +local setprev = nuts.setprev +local getnext = nuts.getnext +local getprev = nuts.getprev +local getid = nuts.getid +local getlist = nuts.getlist +local setlist = nuts.setlist +local getwidth = nuts.getwidth +local setwidth = nuts.setwidth +local getheight = nuts.getheight +local getattr = nuts.getattr +local setattr = nuts.setattr +local getsubtype = nuts.getsubtype +local getwhd = nuts.getwhd +local getdirection = nuts.getdirection +local setshift = nuts.setshift +local getboxglue = nuts.getboxglue + +local hpack_list = nuts.hpack +local vpack_list = nuts.vpack +local getdimensions = nuts.dimensions +local getrangedimensions = nuts.rangedimensions +local traverse = nuts.traverse +local find_node_tail = nuts.tail +local start_of_par = nuts.start_of_par + +local nodecodes = nodes.nodecodes +local gluecodes = nodes.gluecodes +local listcodes = nodes.listcodes + +local dirvalues = nodes.dirvalues +local lefttoright_code = dirvalues.lefttoright +local righttoleft_code = dirvalues.righttoleft + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local glue_code = nodecodes.glue +local glyph_code = nodecodes.glyph +local rule_code = nodecodes.rule +local dir_code = nodecodes.dir +local par_code = nodecodes.par + +local leftskip_code = gluecodes.leftskip +local rightskip_code = gluecodes.rightskip +local parfillleftskip_code = gluecodes.parfillleftskip +local parfillskip_code = gluecodes.parfillskip + +----- linelist_code = listcodes.line + +local new_rule = nodepool.rule +local new_kern = nodepool.kern +local new_hlist = nodepool.hlist + +local flush_node = nuts.flush + +local tosequence = nodes.tosequence + +local implement = interfaces.implement + +-- Normally a (destination) area is a box or a simple stretch if nodes but when it is +-- a paragraph we have a problem: we cannot calculate the height well. This happens +-- with footnotes or content broken across a page. + +-- skip is somewhat messy +-- when we have a line line we can look at the next line and make a shape +-- see dimensions: this is tricky with split off boxes like inserts +-- where we can end up with a first and last spanning lines so maybe +-- we need to do vlists differently +-- no need for dir here if we inject in the right spot as then we can +-- pick up the dir elsewhere (in lmtx) + +local inject_areas do + + local function hlist_dimensions(start,stop,parent) + local last = stop and getnext(stop) + if parent then + return getrangedimensions(parent,start,last) + else + return getdimensions(start,last) + end + end + + local function vlist_dimensions(start,stop) -- also needs the stretch and so + local temp + if stop then + temp = getnext(stop) + setnext(stop,nil) + end + local v = vpack_list(start) -- use helper but happens seldom anyway so ... + local w, h, d = getwhd(v) + setlist(v) -- not needed + flush_node(v) + if temp then + setnext(stop,temp) + end + return w, h, d + end + + -- not ok when vlist at mvl level + + local function dimensions(parent,start,stop) -- in principle we could move some to the caller + if start == stop then + local id = getid(start) + if id == hlist_code or id == vlist_code or id == rule_code or id == glyph_code then + local sw, sh, sd = getwhd(start) + local pw, ph, pd = getwhd(parent) + local ht = sh == 0 and ph or sh -- changed + local dp = sd == 0 and pd or sd -- changed + if trace_areas then + report_area("dimensions taken of %a (%p,%p,%p) with parent (%p,%p,%p) -> (%p,%p,%p)", + nodecodes[id],sw,sh,sd,pw,ph,pd,sw,ht,dp) + end + return sw, ht, dp + else + if trace_areas then + report_area("dimensions calculated of %a",nodecodes[id]) + end + return hlist_dimensions(start,stop) -- one node only so simple + end + elseif parent then + -- todo: if no prev and no next and parent + -- todo: we need a a list_dimensions for a vlist + if getid(parent) == vlist_code then + -- + -- we can as well calculate here because we only have kerns and glue + -- + local last = stop and getnext(stop) + local first = nil + local last = nil + local current = start + local noflines = 0 + while current do -- can be loop + local id = getid(current) + if id == hlist_code or id == vlist_code or id == rule_code then + if noflines == 0 then + first = current + noflines = 1 + else + noflines = noflines + 1 + end + last = current + end + if current == stop then + break + else + current = getnext(current) + end + end + if noflines > 1 then + if trace_areas then + report_area("dimensions taken of vlist") + end + local w, h, d = vlist_dimensions(first,last,parent) + local ht = getheight(first) + return w, ht, d + h - ht, first + elseif first then + if trace_areas then + report_area("dimensions taken of first line in vlist") + end + local w, h, d = getwhd(first) + return w, h, d, first + else + if trace_areas then + report_area("dimensions taken of vlist (probably wrong)") + end + return hlist_dimensions(start,stop,parent) + end + else + if trace_areas then + report_area("dimensions taken of range starting with %a using parent",nodecodes[id]) + end + return hlist_dimensions(start,stop,parent) + end + else + if trace_areas then + report_area("dimensions taken of range starting with %a",nodecodes[id]) + end + return hlist_dimensions(start,stop) + end + end + + -- Setting these once and not passign them each nested call is faster and this injector is + -- actually one of the more costly calls in a run (when we have lots of references to + -- check) and it's also a bti less code. + + local attribute, make, stack, done + + local function inject_range(head,first,last,reference,parent,pardir,txtdir) + local width, height, depth, line = dimensions(parent,first,last) + if txtdir == righttoleft_code then + width = - width + elseif txtdir == lefttoright_code then + -- go on + elseif pardir == righttoleft_code then + width = - width + end + local result, resolved = make(width,height,depth,reference) + if result and resolved then + if line then + -- special case, we only treat the first line in a vlist + local l = getlist(line) + if trace_areas then + report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","line", + reference,pardir or "?",txtdir or "?", + tosequence(l,nil,true),width,height,depth) + end + setlist(line,result) + setlink(result,l) + return head, last + elseif head == first then + if trace_areas then + report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","head", + reference,pardir or "?",txtdir or "?", + tosequence(first,last,true),width,height,depth) + end + setlink(result,first) + return result, last + else + if trace_areas then + report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","middle", + reference,pardir or "?",txtdir or "?", + tosequence(first,last,true),width,height,depth) + end + if first == last and getid(parent) == vlist_code and getid(first) == hlist_code then + if trace_areas then + -- think of a button without \dontleavehmode in the mvl + report_area("compensating for link in vlist") + end + setlink(result,getlist(first)) + setlist(first,result) + else + setlink(getprev(first),result,first) + end + return head, last + end + else + return head, last + end + end + + -- Somehow this one no longer got used. See node-ref.lua for the implementation. + -- + -- local function inject_list(id,current,reference,pardir,txtdir) + -- end + + local function inject(head,skip,parent,pardir,txtdir) + local first, last, firstdir, reference + local current = head + while current do + local id = getid(current) + if id == hlist_code or id == vlist_code then + local r = getattr(current,attribute) + -- test \goto{test}[page(2)] test \gotobox{test}[page(2)] + -- test \goto{\TeX}[page(2)] test \gotobox{\hbox {x} \hbox {x}}[page(2)] + if r then + if not reference then + reference, first, last, firstdir = r, current, current, txtdir + elseif r == reference then + -- same link + last = current + elseif (done[reference] or 0) == 0 then + if not skip or r > skip then -- maybe no > test + head, current = inject_range(head,first,last,reference,parent,pardir,firstdir) + reference, first, last, firstdir = nil, nil, nil, nil + end + else + reference, first, last, firstdir = r, current, current, txtdir + end + done[r] = (done[r] or 0) + 1 + end + local list = getlist(current) + if list then + local h + h, pardir, txtdir = inject(list,r or skip or 0,current,pardir,txtdir) + if h ~= current then + setlist(current,h) + end + end + if r then + done[r] = done[r] - 1 + end + goto NEXT + elseif id == dir_code then + local direction, pop = getdirection(current) + txtdir = not pop and direction -- we might need a stack + goto NEXT + elseif id == par_code then + if start_of_par(current) then + pardir = getdirection(current) + end + goto NEXT + elseif id == glue_code then + local subtype = getsubtype(current) + if subtype == leftskip_code or subtype == parfillleftskip_code then + goto NEXT + elseif subtype == rightskip_code or subtype == parfillskip_code then + if reference and (done[reference] or 0) == 0 then + head, current = inject_range(head,first,last,reference,parent,pardir,firstdir) + reference, first, last, firstdir = nil, nil, nil, nil + end + goto NEXT + end + end + do + local r = getattr(current,attribute) + if not r then + -- just go on, can be kerns + elseif not reference then + reference, first, last, firstdir = r, current, current, txtdir + elseif r == reference then + last = current + elseif (done[reference] or 0) == 0 then -- or (id == glue_code and getsubtype(current) == right_skip_code) then + if not skip or r > skip then -- maybe no > test + head, current = inject_range(head,first,last,reference,parent,pardir,firstdir) + reference, first, last, firstdir = nil, nil, nil, nil + end + else + reference, first, last, firstdir = r, current, current, txtdir + end + end + ::NEXT:: + current = getnext(current) + end + if reference and (done[reference] or 0) == 0 then + head = inject_range(head,first,last,reference,parent,pardir,firstdir) + end + return head, pardir, txtdir + end + + inject_areas = function(head,a,m,s,d) + attribute = a + make = m + stack = s + done = d + return (inject(head)) + end + +end + +-- tracing: todo: use predefined colors + +local colorize, justadd do + + local a_color = attributes.private('color') + local a_colormodel = attributes.private('colormodel') + local a_transparency = attributes.private('transparency') + local u_transparency = nil + local u_colors = { } + local force_gray = true + + local register_color = colors.register + + local function addstring(what,str,shift) --todo make a pluggable helper (in font-ctx) + if str then + local typesetters = nuts.typesetters + if typesetters then + local hashes = fonts.hashes + local infofont = fonts.infofont() + local emwidth = hashes.emwidths [infofont] + local exheight = hashes.exheights[infofont] + if what == "reference" then + str = str .. " " + shift = - (shift or 2.25) * exheight + else + str = str .. " " + shift = (shift or 2) * exheight + end + local text = typesetters.tohpack(str,infofont) + local rule = new_rule(emwidth/5,4*exheight,3*exheight) + setshift(text,shift) + return hpack_list(setlink(text,rule)) + end + end + end + + colorize = function(width,height,depth,n,reference,what,sr,offset) + if force_gray then + n = 0 + end + u_transparency = u_transparency or transparencies.register(nil,2,.65) + local ucolor = u_colors[n] + if not ucolor then + if n == 1 then + u_color = register_color(nil,'rgb',.75,0,0) + elseif n == 2 then + u_color = register_color(nil,'rgb',0,.75,0) + elseif n == 3 then + u_color = register_color(nil,'rgb',0,0,.75) + else + n = 0 + u_color = register_color(nil,'gray',.5) + end + u_colors[n] = u_color + end + if width == 0 then + -- probably a strut as placeholder + report_area("%s %s has no %s dimensions, width %p, height %p, depth %p",what,reference,"horizontal",width,height,depth) + width = 65536 + end + if height + depth <= 0 then + report_area("%s %s has no %s dimensions, width %p, height %p, depth %p",what,reference,"vertical",width,height,depth) + height = 65536/2 + depth = height + end + local rule = new_rule(width,height,depth) -- todo: use tracer rule + setattr(rule,a_colormodel,1) -- gray color model + setattr(rule,a_color,u_color) + setattr(rule,a_transparency,u_transparency) + if width < 0 then + local kern = new_kern(width) + setwidth(rule,-width) + setnext(kern,rule) + setprev(rule,kern) + return kern + elseif sr and sr ~= "" then + local text = addstring(what,sr,shift) + if text then + local kern = new_kern(-getwidth(text)) + setlink(kern,text,rule) + return kern + end + end + return rule + end + + justadd = function(what,sr,shift,current) -- needs testing + if sr and sr ~= "" then + local text = addstring(what,sr,shift) + if text then + local kern = new_kern(-getwidth(text)) + setlink(kern,text,current) + return new_hlist(kern) + end + end + end + +end + +local nofreferences = 0 + +do + + local stack = { } + local done = { } + local attribute = attributes.private('reference') + local topofstack = 0 + + nodes.references = { + attribute = attribute, + stack = stack, + done = done, + } + + -- todo: get rid of n (n is just a number, can be used for tracing, obsolete) + + local function setreference(h,d,r) -- h and d can be nil + topofstack = topofstack + 1 + -- the preroll permits us to determine samepage (but delayed also has some advantages) + -- so some part of the backend work is already done here + stack[topofstack] = { r, h or false, d or false, codeinjections.prerollreference(r) } + -- texsetattribute(attribute,topofstack) -- todo -> at tex end + texsetcount("lastreferenceattribute",topofstack) + end + + function references.get(n) -- not public so functionality can change + local sn = stack[n] + return sn and sn[1] + end + + local function makereference(width,height,depth,reference) -- height and depth are of parent + local sr = stack[reference] + if sr then + if trace_references then + report_reference("resolving attribute %a",reference) + end + local resolved = sr[1] + local ht = sr[2] + local dp = sr[3] + local set = sr[4] + local n = sr[5] + -- logs.report("temp","child: ht=%p dp=%p, parent: ht=%p dp=%p",ht,dp,height,depth) + if ht then + if height < ht then height = ht end + if depth < dp then depth = dp end + end + -- logs.report("temp","used: ht=%p dp=%p",height,depth) + local annot = nodeinjections.reference(width,height,depth,set,resolved.mesh) + if annot then + annot = tonut(annot) -- todo + nofreferences = nofreferences + 1 + local result, current, texts + if show_references then + local d = resolved + if d then + local r = d.reference + local p = d.prefix + if r then + if p then + texts = p .. "|" .. r + else + texts = r + end + else + -- t[#t+1] = d.internal or "?" + end + end + end + if trace_references then + local step = 65536 + result = new_hlist(colorize(width,height-step,depth-step,2,reference,"reference",texts,show_references)) -- step subtracted so that we can see seperate links + current = result + elseif texts then + texts = justadd("reference",texts,show_references,current) + if texts then + current = texts + end + end + if current then + setlink(current,annot) + else + result = annot + end + references.registerpage(n) + result = new_hlist(result) + if cleanupreferences then stack[reference] = nil end + return result, resolved + elseif trace_references then + report_reference("unable to resolve annotation %a",reference) + end + elseif trace_references then + report_reference("unable to resolve attribute %a",reference) + end + end + + function nodes.references.handler(head) + if head and topofstack > 0 then + return inject_areas(head,attribute,makereference,stack,done) + else + return head + end + end + + function references.inject(prefix,reference,specification) -- todo: use currentreference is possible + local set, bug = references.identify(prefix,reference) + if bug or #set == 0 then + -- unknown ref, just don't set it and issue an error + else + set.highlight = specification.highlight + set.newwindow = specification.newwindow + set.layer = specification.layer + setreference(specification.height,specification.depth,set) -- sets attribute / todo: for set[*].error + end + end + + -- function references.injectinternal(internal,specification) + -- references.inject("","internal("..internal..")",specification) + -- if bug or #set == 0 then + -- -- unknown ref, just don't set it and issue an error + -- else + -- -- nil prefix when "" + -- -- check + -- set.highlight = specification.highlight + -- set.newwindow = specification.newwindow + -- set.layer = specification.layer + -- setreference(specification.height,specification.depth,set) -- sets attribute / todo: for set[*].error + -- end + -- end + + function references.injectcurrentset(h,d) -- used inside doifelse + local currentset = references.currentset + if currentset then + setreference(h,d,currentset) -- sets attribute / todo: for set[*].error + end + end + +end + +local nofdestinations = 0 + +do + + local stack = { } + local done = { } + local attribute = attributes.private('destination') + local topofstack = 0 + + nodes.destinations = { + attribute = attribute, + stack = stack, + done = done, + } + + local function setdestination(n,h,d,name,view) -- n = grouplevel, name == table + topofstack = topofstack + 1 + stack[topofstack] = { n, h, d, name, view } + return topofstack + end + + local function makedestination(width,height,depth,reference) + local sr = stack[reference] + if sr then + if trace_destinations then + report_destination("resolving attribute %a",reference) + end + local resolved = sr[1] + local ht = sr[2] + local dp = sr[3] + local name = sr[4] + local view = sr[5] + if ht then + if height < ht then height = ht end + if depth < dp then depth = dp end + end + local result, current, texts + if show_destinations then + if name and #name > 0 then + local t = { } + for i=1,#name do + local s = name[i] + if type(s) == "number" then + local d = references.internals[s] + if d then + d = d.references + local r = d.reference + local p = d.usedprefix + if r then + if p then + t[#t+1] = p .. "|" .. r + else + t[#t+1] = r + end + else + -- t[#t+1] = d.internal or "?" + end + end + else + -- in fact we have a prefix:name here + end + end + if #t > 0 then + texts = concat(t," & ") + end + end + end + if trace_destinations then + local step = 0 + if width == 0 then + step = 4*65536 + width, height, depth = 5*step, 5*step, 0 + end + local rule = new_hlist(colorize(width,height,depth,3,reference,"destination",texts,show_destinations)) + if not result then + result, current = rule, rule + else + setlink(current,rule) + current = rule + end + width, height = width - step, height - step + elseif texts then + texts = justadd("destination",texts,show_destinations,current) + if texts then + current = texts + end + end + nofdestinations = nofdestinations + 1 + local annot = nodeinjections.destination(width,height,depth,name,view) + if annot then + annot = tonut(annot) -- obsolete soon + if result then + setlink(current,annot) + else + result = annot + end + current = find_node_tail(annot) + end + if result then + result = new_hlist(result) + end + if cleanupdestinations then stack[reference] = nil end + return result, resolved + elseif trace_destinations then + report_destination("unable to resolve attribute %a",reference) + end + end + + function nodes.destinations.handler(head) + if head and topofstack > 0 then + return inject_areas(head,attribute,makedestination,stack,done) + else + return head + end + end + + -- will move + + function references.mark(reference,h,d,view) + return setdestination(tex.currentgrouplevel,h,d,reference,view) + end + +end + +implement { + name = "injectreference", + actions = references.inject, + arguments = { + "string", + "string", + { + { "highlight", "boolean" }, + { "newwindow", "boolean" }, + { "layer" }, + { "height", "dimen" }, + { "depth", "dimen" }, + { "view" }, + } + } +} + +-- implement { +-- name = "injectinternalreference", +-- actions = references.injectinternal, +-- arguments = { +-- "integer", +-- { +-- { "highlight", "boolean" }, +-- { "newwindow", "boolean" }, +-- { "layer" }, +-- { "height", "dimen" }, +-- { "depth", "dimen" }, +-- { "view" }, +-- } +-- } +-- } + +implement { + name = "injectcurrentreference", + actions = references.injectcurrentset, +} + +implement { + name = "injectcurrentreferencehtdp", + actions = references.injectcurrentset, + arguments = { "dimen", "dimen" }, +} + +statistics.register("interactive elements", function() + if nofreferences > 0 or nofdestinations > 0 then + return string.format("%s references, %s destinations",nofreferences,nofdestinations) + else + return nil + end +end) diff --git a/tex/context/base/mkxl/node-rul.mkxl b/tex/context/base/mkxl/node-rul.mkxl index 569f0d284..97417c1d8 100644 --- a/tex/context/base/mkxl/node-rul.mkxl +++ b/tex/context/base/mkxl/node-rul.mkxl @@ -383,7 +383,7 @@ \fi \normalexpanded{\t_node_shifts_checklist{\the\t_node_shifts_checklist\node_shifts_redefine{\currentshift}}}% order ? \node_shifts_define - \setuevalue\currentshift{\node_shifts_direct{\currentshift}}% + \frozen\instance\setuevalue\currentshift{\node_shifts_direct{\currentshift}}% \to \everydefineshift \protected\def\node_shifts_define diff --git a/tex/context/base/mkxl/pack-rul.mkxl b/tex/context/base/mkxl/pack-rul.mkxl index 23de8d5cb..8ca6c69d5 100644 --- a/tex/context/base/mkxl/pack-rul.mkxl +++ b/tex/context/base/mkxl/pack-rul.mkxl @@ -453,7 +453,7 @@ \to \everyoverlay \permanent\tolerant\protected\def\defineoverlay[#1]#*[#2]% wil be overloaded - {\def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}% + {\def\pack_framed_define_overlay_indeed##1{\defcsname\??overlay##1\endcsname{\executedefinedoverlay{##1}{#2}}}% \processcommalist[#1]\pack_framed_define_overlay_indeed} \permanent\protected\def\executedefinedoverlay#1#2% we can share the definitions @@ -1595,9 +1595,9 @@ \dp\scratchbox\dp\b_framed_normal \setbox\b_framed_normal\box\scratchbox} -\def\installframedlocator#1#2#3% - {\setvalue{\??framedlocatorbefore#1}{#2}% - \setvalue{\??framedlocatorafter #1}{#3}} +\permanent\protected\def\installframedlocator#1#2#3% + {\defcsname\??framedlocatorbefore#1\endcsname{#2}% + \defcsname\??framedlocatorafter #1\endcsname{#3}} \def\pack_framed_locator_before#1{\begincsname\??framedlocatorbefore#1\endcsname} \def\pack_framed_locator_after #1{\begincsname\??framedlocatorafter #1\endcsname} diff --git a/tex/context/base/mkxl/page-brk.mkxl b/tex/context/base/mkxl/page-brk.mkxl index dace10eed..3e3a1c1d4 100644 --- a/tex/context/base/mkxl/page-brk.mkxl +++ b/tex/context/base/mkxl/page-brk.mkxl @@ -308,7 +308,7 @@ \def\page_breaks_columns_handle_direct#1% {\begincsname\??columnbreakmethod\currentoutputroutine:#1\endcsname} -\protected\def\installcolumnbreakmethod#1#2#3% #1=otr-id #2=tag #3=action +\permanent\protected\def\installcolumnbreakmethod#1#2#3% #1=otr-id #2=tag #3=action {\setvalue{\??columnbreakmethod#1:#2}{#3}} \aliased\let\installcolumnbreakhandler\installcolumnbreakmethod % will go diff --git a/tex/context/base/mkxl/page-mbk.mklx b/tex/context/base/mkxl/page-mbk.mklx index fcab1abf5..05b09c79e 100644 --- a/tex/context/base/mkxl/page-mbk.mklx +++ b/tex/context/base/mkxl/page-mbk.mklx @@ -171,7 +171,7 @@ \page_margin_blocks_set_l_box \page_margin_blocks_set_r_box} -\protected\def\page_margin_blocks_place_r_yes +\permanent\protected\def\page_margin_blocks_place_r_yes {\setbox\b_page_margin_blocks_prepared\hbox to \rightmarginwidth {\marginblockparameter\c!left \box\b_page_margin_blocks_prepared @@ -179,7 +179,7 @@ \vsmashbox\b_page_margin_blocks_prepared \box\b_page_margin_blocks_prepared} -\protected\def\page_margin_blocks_place_l_yes +\permanent\protected\def\page_margin_blocks_place_l_yes {\setbox\b_page_margin_blocks_prepared\hbox to \leftmarginwidth {\marginblockparameter\c!right \box\b_page_margin_blocks_prepared @@ -187,14 +187,14 @@ \vsmashbox\b_page_margin_blocks_prepared \box\b_page_margin_blocks_prepared} -\protected\def\page_margin_blocks_place_r_nop{\hskip\rightmarginwidth} -\protected\def\page_margin_blocks_place_l_nop{\hskip\leftmarginwidth} +\permanent\protected\def\page_margin_blocks_place_r_nop{\hskip\rightmarginwidth} +\permanent\protected\def\page_margin_blocks_place_l_nop{\hskip\leftmarginwidth} -\let\placerightmarginblock\page_margin_blocks_place_r_nop -\let\placeleftmarginblock \page_margin_blocks_place_l_nop +\aliased\let\placerightmarginblock\page_margin_blocks_place_r_nop +\aliased\let\placeleftmarginblock \page_margin_blocks_place_l_nop -\def\page_margin_blocks_set_r_box{\let\placerightmarginblock\page_margin_blocks_place_r_yes} -\def\page_margin_blocks_set_l_box{\let\placeleftmarginblock \page_margin_blocks_place_l_yes} +\def\page_margin_blocks_set_r_box{\enforced\aliased\let\placerightmarginblock\page_margin_blocks_place_r_yes} +\def\page_margin_blocks_set_l_box{\enforced\aliased\let\placeleftmarginblock \page_margin_blocks_place_l_yes} % margin floats (keyword 'margin' in option list) diff --git a/tex/context/base/mkxl/page-mix.mkxl b/tex/context/base/mkxl/page-mix.mkxl index c94a1f252..7fb4512e5 100644 --- a/tex/context/base/mkxl/page-mix.mkxl +++ b/tex/context/base/mkxl/page-mix.mkxl @@ -341,7 +341,7 @@ \installcorenamespace{mixedcolumnsseparator} -\protected\def\installmixedcolumnseparator#1#2% +\permanent\protected\def\installmixedcolumnseparator#1#2% {\setvalue{\??mixedcolumnsseparator#1}{#2}} \installmixedcolumnseparator\v!rule diff --git a/tex/context/base/mkxl/scrn-but.mklx b/tex/context/base/mkxl/scrn-but.mklx index 60073a6b7..3df4be248 100644 --- a/tex/context/base/mkxl/scrn-but.mklx +++ b/tex/context/base/mkxl/scrn-but.mklx @@ -327,6 +327,9 @@ \aliased\let\setupinteractionmenus\setupinteractionmenu +\mutable\let\currentinteractionmenudistance\empty +\mutable\let\currentinteractionmenustate \empty + \let\scrn_menu_action\relax \let\scrn_menu_define_original\defineinteractionmenu diff --git a/tex/context/base/mkxl/scrn-fld.mklx b/tex/context/base/mkxl/scrn-fld.mklx index fb249c01f..674be425a 100644 --- a/tex/context/base/mkxl/scrn-fld.mklx +++ b/tex/context/base/mkxl/scrn-fld.mklx @@ -110,6 +110,14 @@ \setupforms [\c!method=XML] % no need for everyjob initialization as this is the default +\mutable\let\currentfieldbackgroundcolor \empty +\mutable\let\currentfieldbackgroundcolorvalue\empty +\mutable\let\currentfieldbodycategory \empty +\mutable\let\currentfieldframecolor \empty +\mutable\let\currentfieldframecolorvalue \empty +\mutable\let\currentfieldlabel \empty +\mutable\let\currentfieldstackname \empty + \appendtoks \iflocation \clf_exportformdata{\formsparameter\c!export}% diff --git a/tex/context/base/mkxl/scrn-pag.mklx b/tex/context/base/mkxl/scrn-pag.mklx index a500b6695..80e16f63d 100644 --- a/tex/context/base/mkxl/scrn-pag.mklx +++ b/tex/context/base/mkxl/scrn-pag.mklx @@ -35,6 +35,10 @@ \newdimen\canvasbleedoffset \newdimen\canvasartoffset +\mutable\let\currentinteractionscreendelay \empty +\mutable\let\currentinteractionscreenheight\empty +\mutable\let\currentinteractionscreenwidth \empty + \newconditional\c_scrn_canvas_tight_page \def\scrn_canvas_calculate diff --git a/tex/context/base/mkxl/scrn-ref.mklx b/tex/context/base/mkxl/scrn-ref.mklx index 806f2f48a..63f76a092 100644 --- a/tex/context/base/mkxl/scrn-ref.mklx +++ b/tex/context/base/mkxl/scrn-ref.mklx @@ -51,6 +51,11 @@ \enabledirectives[destinations.offset=\the\dimexpr\interactionparameter\c!focusoffset\relax]% \to \everysetupinteraction +\mutable\let\currentinteractioncloseaction \empty +\mutable\let\currentinteractionclosepageaction\empty +\mutable\let\currentinteractionopenaction \empty +\mutable\let\currentinteractionopenpageaction \empty + %D We have to make sure of some settings: \def\scrn_reference_set_text_actions diff --git a/tex/context/base/mkxl/scrn-wid.mklx b/tex/context/base/mkxl/scrn-wid.mklx index 384a60a60..225bdc161 100644 --- a/tex/context/base/mkxl/scrn-wid.mklx +++ b/tex/context/base/mkxl/scrn-wid.mklx @@ -94,6 +94,12 @@ \c!depth=\v!fit, \c!location=\v!high] +\mutable\let\currentattachmentdepth \empty +\mutable\let\currentattachmentheight \empty +\mutable\let\currentattachmentregistered\empty +\mutable\let\currentattachmentsymbol \empty +\mutable\let\currentattachmentwidth \empty + \permanent\tolerant\protected\def\registerattachment[#tag]#spacer[#settings]% we save (globally) at the lua end {\ifarguments\else \begingroup @@ -397,6 +403,11 @@ \c!buffer=\v!comment, \c!location=\v!high] +\mutable\let\currentcommentdepth \empty +\mutable\let\currentcommentheight\empty +\mutable\let\currentcommentsymbol\empty +\mutable\let\currentcommentwidth \empty + \appendtoks \frozen\instance\setuevalue \currentcomment {\scrn_comment_argument[\currentcomment]}% \frozen\instance\setuevalue{\e!start\currentcomment}{\scrn_comment_start [\currentcomment]}% diff --git a/tex/context/base/mkxl/spac-ali.lmt b/tex/context/base/mkxl/spac-ali.lmt new file mode 100644 index 000000000..5c434fcdf --- /dev/null +++ b/tex/context/base/mkxl/spac-ali.lmt @@ -0,0 +1,134 @@ +if not modules then modules = { } end modules ['spac-ali'] = { + version = 1.001, + optimize = true, + comment = "companion to spac-ali.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local div = math.div +local format = string.format + +local tasks = nodes.tasks +local enableaction = tasks.enableaction + +local nuts = nodes.nuts + +local setlist = nuts.setlist +local setlink = nuts.setlink +local getdirection = nuts.getdirection +local takeattr = nuts.takeattr +local getwidth = nuts.getwidth +local findtail = nuts.tail + +local righttoleft_code = nodes.dirvalues.righttoleft +local linelist_code = nodes.listcodes.line + +local hpack_nodes = nuts.hpack +local nextlist = nuts.traversers.list + +local new_stretch = nuts.pool.stretch + +local a_realign = attributes.private("realign") + +local texsetattribute = tex.setattribute +local texgetcount = tex.getcount + +local isleftpage = layouts.status.isleftpage + +typesetters = typesetters or { } +local alignments = { } +typesetters.alignments = alignments + +local report_realign = logs.reporter("typesetters","margindata") +local trace_realign = trackers.register("typesetters.margindata", function(v) trace_margindata = v end) + +local nofrealigned = 0 + +-- leftskip rightskip parfillskip +-- raggedleft 0 + 0 - +-- raggedright 0 0 fil +-- raggedcenter 0 + 0 + - + +local function handler(head,leftpage,realpageno) -- traverse_list + for current, id, subtype, list in nextlist, head do + if subtype == linelist_code then + local a = takeattr(current,a_realign) + if a and a > 0 then + local pageno = div(a,10) + if pageno ~= realpageno then + local align = a % 10 + local action = 0 + if align == 1 then -- flushright + action = leftpage and 1 or 2 + elseif align == 2 then -- flushleft + action = leftpage and 2 or 1 + end + -- WS: watch this + local direction = getdirection(current) + -- or should this happen at the tex end: + if direction == righttoleft_code then + if action == 1 then + action = 2 + elseif action == 2 then + action = 1 + end + end + -- Currently we just prepend and append which kind of spoils the normalization unless + -- we extend our specs and also introduce left/right anchored stuff. + if action == 1 then + local head = list + setlink(findtail(list),new_stretch(3)) -- append + setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction)) + if trace_realign then + report_realign("flushing left, align %a, page %a, realpage %a",align,pageno,realpageno) + end + elseif action == 2 then + local head = setlink(new_stretch(3),list) -- prepend + setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction)) + if trace_realign then + report_realign("flushing right, align %a, page %a, realpage %a",align,pageno,realpageno) + end + elseif trace_realign then + report_realign("invalid flushing, align %a, page %a, realpage %a",align,pageno,realpageno) + end + nofrealigned = nofrealigned + 1 + end + end + end + handler(list,leftpage,realpageno) + end + return head +end + +function alignments.handler(head) + return handler(head,isleftpage(),texgetcount("realpageno")) +end + +local enabled = false + +function alignments.set(n) + if not enabled then + enableaction("shipouts","typesetters.alignments.handler") + enabled = true + if trace_realign then + report_realign("enabled") + end + end + texsetattribute(a_realign,texgetcount("realpageno") * 10 + n) +end + +interfaces.implement { + name = "setrealign", + actions = alignments.set, + arguments = "integer", +} + +statistics.register("realigning", function() + if nofrealigned > 0 then + return format("%s processed",nofrealigned) + else + return nil + end +end) diff --git a/tex/context/base/mkxl/spac-ali.mkxl b/tex/context/base/mkxl/spac-ali.mkxl index b19c9c8db..d72371659 100644 --- a/tex/context/base/mkxl/spac-ali.mkxl +++ b/tex/context/base/mkxl/spac-ali.mkxl @@ -19,7 +19,7 @@ %D variants. Starting at the last day of 2011 both methods are merged into one and %D caching has been added, which makes switching twice as fast. -\registerctxluafile{spac-ali}{optimize} +\registerctxluafile{spac-ali}{autosuffix,optimize} \definesystemattribute[realign] [public] % might be combined with the next one \definesystemattribute[alignstate][public] % will make a single attributes for several states @@ -29,7 +29,6 @@ \c_attr_alignstate\attributeunsetvalue \to \everyforgetall -\permanent\protected\def\resetrealignsignal{\c_attr_realign\attributeunsetvalue} \permanent\protected\def\signalinnerrealign{\clf_setrealign\plustwo} \permanent\protected\def\signalouterrealign{\clf_setrealign\plusone} @@ -147,8 +146,8 @@ \installcorenamespace{bidi} -\letvalue{\??bidi\v!left }\checkedlefttoright \letvalue{\??bidi l2r}\checkedlefttoright -\letvalue{\??bidi\v!right}\checkedrighttoleft \letvalue{\??bidi r2l}\checkedrighttoleft +\letcsname\??bidi\v!left \endcsname\checkedlefttoright \letcsname\??bidi l2r\endcsname\checkedlefttoright +\letcsname\??bidi\v!right\endcsname\checkedrighttoleft \letcsname\??bidi r2l\endcsname\checkedrighttoleft \permanent\protected\def\usebidiparameter#1% {\begincsname\??bidi#1\c!bidi\endcsname} @@ -197,7 +196,7 @@ \def\spac_align_set_raggedness_middle{\ifzeropt\hsize\plussix\bodyfontsize\else.5\hsize\fi} -\protected\def\setraggedness#1% tricky .. we keep the global tolerance otherwise ... to be reconsidered +\permanent\protected\def\setraggedness#1% tricky .. we keep the global tolerance otherwise ... to be reconsidered {\ifnum\tolerance<\c_spac_tolerance_minimum \tolerance\c_spac_tolerance_minimum % small values have unwanted side effects \else @@ -557,8 +556,7 @@ \rawprocesscommacommand[\m_spac_align_asked]\spac_align_collect \fi \normalexpanded{\t_spac_align_collected - {% \resetrealignsignal % can go as it is always set - \setfalse\raggedonelinerstate % bad + {\setfalse\raggedonelinerstate % bad \the\t_spac_align_collected \spac_align_flush_horizontal \spac_align_flush_vertical @@ -636,112 +634,91 @@ % Maybe we need something different in columns. -\protected\def\installalign#1#2% beware: commands must be unexpandable! +\permanent\protected\def\installalign#1#2% beware: commands must be unexpandable! {\ifcsname\??aligncommand#1\endcsname \else - \setvalue{\??aligncommand#1}{\toksapp\t_spac_align_collected{#2}}% + \defcsname\??aligncommand#1\endcsname{\toksapp\t_spac_align_collected{#2}}% \fi} -% beware, toks stuff and states are set at a differt time, so installalign is -% only for special options -% -% \setvalue{\??aligncommand whatever}% -% {\c_spac_align_state_horizontal\plushundred -% \toksapp\t_spac_align_collected{.....}} -% -% this one could deal with both -% -% \protected\def\installalignoption#1#2% -% {\ifcsname\??aligncommand#1\endcsname \else -% \setvalue{\??aligncommand#1}% -% {\spac_align_set_horizontal_none -% \c_spac_align_state_horizontal\plushundred % don't set -% \toksapp\t_spac_align_collected{#2}}% -% \fi} -% -% \installalignoption -% {whatever} -% {} - % The keywords: -\letvalue{\??aligncommand\empty }\empty -\setvalue{\??aligncommand\v!broad }{\c_spac_align_state_broad \plusone } -\setvalue{\??aligncommand\v!wide }{\c_spac_align_state_broad \plustwo } - -\setvalue{\??aligncommand\v!bottom }{\c_spac_align_state_page \plusone } -\setvalue{\??aligncommand\v!height }{\c_spac_align_state_page \plustwo } -\setvalue{\??aligncommand\v!line }{\c_spac_align_state_page \plusthree - % this will become another keyword (undocumented anyway) - \toksapp\t_spac_align_collected{\settrue\raggedonelinerstate}} - -\setvalue{\??aligncommand\v!high }{\c_spac_align_state_vertical \plusthree} -\setvalue{\??aligncommand\v!low }{\c_spac_align_state_vertical \plustwo } -\setvalue{\??aligncommand\v!lohi }{\c_spac_align_state_vertical \plusone } - -\setvalue{\??aligncommand\v!flushright }{\c_spac_align_state_horizontal\plusthree} -\setvalue{\??aligncommand\v!flushleft }{\c_spac_align_state_horizontal\plustwo } -\setvalue{\??aligncommand\v!middle }{\c_spac_align_state_horizontal\plusone } -\setvalue{\??aligncommand\v!no }{\c_spac_align_state_horizontal\plustwo } -\setvalue{\??aligncommand\v!yes }{\c_spac_align_state_horizontal\zerocount} -\setvalue{\??aligncommand\v!width }{\c_spac_align_state_horizontal\zerocount} -\setvalue{\??aligncommand\v!normal }{\c_spac_align_state_horizontal\zerocount} -\setvalue{\??aligncommand\v!reset }{\c_spac_align_state_page \zerocount - \c_spac_align_state_horizontal\zerocount} -\setvalue{\??aligncommand\v!inner }{\c_spac_align_state_horizontal\plusfour } -\setvalue{\??aligncommand\v!outer }{\c_spac_align_state_horizontal\plusfive } -\setvalue{\??aligncommand\v!flushinner }{\c_spac_align_state_horizontal\plusfour } -\setvalue{\??aligncommand\v!flushouter }{\c_spac_align_state_horizontal\plusfive } -\setvalue{\??aligncommand\v!right }{\c_spac_align_state_horizontal\plustwo } -\setvalue{\??aligncommand\v!left }{\c_spac_align_state_horizontal\plusthree} -\setvalue{\??aligncommand\v!center }{\c_spac_align_state_horizontal\plusone - \c_spac_align_state_broad \plustwo } -\setvalue{\??aligncommand\v!disable }{\c_spac_align_state_horizontal\plussix } -\setvalue{\??aligncommand\v!last }{\c_spac_align_state_horizontal\plusseven} -\setvalue{\??aligncommand\v!end }{\c_spac_align_state_horizontal\pluseight} -\setvalue{\??aligncommand\v!paragraph }{\c_spac_align_state_horizontal\plusnine} - -\setvalue{\??aligncommand\v!lefttoright }{\c_spac_align_state_direction \plusone } -\setvalue{\??aligncommand\v!righttoleft }{\c_spac_align_state_direction \plustwo } -\setvalue{\??aligncommand l2r}{\c_spac_align_state_direction \plusone } -\setvalue{\??aligncommand r2l}{\c_spac_align_state_direction \plustwo } - -\setvalue{\??aligncommand\v!table }{\c_spac_align_state_vertical \plusthree - \c_spac_align_state_broad \plusone - \c_spac_align_state_horizontal\plustwo } - -\setvalue{\??aligncommand\v!lesshyphenation}{\toksapp\t_spac_align_collected{\lesshyphens}} -\setvalue{\??aligncommand\v!morehyphenation}{\toksapp\t_spac_align_collected{\morehyphens}} - -\setvalue{\??aligncommand\v!hanging }{\toksapp\t_spac_align_collected{\font_protruding_enable }} -\setvalue{\??aligncommand\v!hangingboth }{\toksapp\t_spac_align_collected{\font_protruding_enable_b}} -\setvalue{\??aligncommand\v!nothanging }{\toksapp\t_spac_align_collected{\font_protruding_disable}} -\setvalue{\??aligncommand\v!hz }{\toksapp\t_spac_align_collected{\font_expansion_enable }} -\setvalue{\??aligncommand\v!fullhz }{\toksapp\t_spac_align_collected{\font_expansion_enable_k}} -\setvalue{\??aligncommand\v!nohz }{\toksapp\t_spac_align_collected{\font_expansion_disable }} -%setvalue{\??aligncommand\v!spacing }{\toksapp\t_spac_align_collected{\normalspacing\zerocount}} % not yet -%setvalue{\??aligncommand\v!nospacing }{\toksapp\t_spac_align_collected{\normalspacing\plusone}} % not yet -\setvalue{\??aligncommand\v!hyphenated }{\toksapp\t_spac_align_collected{\dohyphens}} -\setvalue{\??aligncommand\v!nothyphenated }{\toksapp\t_spac_align_collected{\nohyphens}} - -\setvalue{\??aligncommand\v!tolerant }{\toksapp\t_spac_align_collected{\spac_align_set_tolerant}} -\setvalue{\??aligncommand\v!verytolerant }{\toksapp\t_spac_align_collected{\spac_align_set_very_tolerant}} -\setvalue{\??aligncommand\v!stretch }{\toksapp\t_spac_align_collected{\spac_align_set_stretch}} -\setvalue{\??aligncommand\v!extremestretch }{\toksapp\t_spac_align_collected{\spac_align_set_extreme_stretch}} - -\setvalue{\??aligncommand \v!final}{\c_spac_align_state_par_fill\plusone} -\setvalue{\??aligncommand1*\v!final}{\c_spac_align_state_par_fill\plusone} -\setvalue{\??aligncommand2*\v!final}{\c_spac_align_state_par_fill\plustwo} % hardcoded multiplier -\setvalue{\??aligncommand3*\v!final}{\c_spac_align_state_par_fill\plusthree} -\setvalue{\??aligncommand4*\v!final}{\c_spac_align_state_par_fill\plusfour} +\letcsname\??aligncommand\empty \endcsname\empty +\defcsname\??aligncommand\v!broad \endcsname{\c_spac_align_state_broad \plusone } +\defcsname\??aligncommand\v!wide \endcsname{\c_spac_align_state_broad \plustwo } + +\defcsname\??aligncommand\v!bottom \endcsname{\c_spac_align_state_page \plusone } +\defcsname\??aligncommand\v!height \endcsname{\c_spac_align_state_page \plustwo } +\defcsname\??aligncommand\v!line \endcsname{\c_spac_align_state_page \plusthree + % this will become another keyword (undocumented anyway) + \toksapp\t_spac_align_collected{\settrue\raggedonelinerstate}} + +\defcsname\??aligncommand\v!high \endcsname{\c_spac_align_state_vertical \plusthree} +\defcsname\??aligncommand\v!low \endcsname{\c_spac_align_state_vertical \plustwo } +\defcsname\??aligncommand\v!lohi \endcsname{\c_spac_align_state_vertical \plusone } + +\defcsname\??aligncommand\v!flushright \endcsname{\c_spac_align_state_horizontal\plusthree} +\defcsname\??aligncommand\v!flushleft \endcsname{\c_spac_align_state_horizontal\plustwo } +\defcsname\??aligncommand\v!middle \endcsname{\c_spac_align_state_horizontal\plusone } +\defcsname\??aligncommand\v!no \endcsname{\c_spac_align_state_horizontal\plustwo } +\defcsname\??aligncommand\v!yes \endcsname{\c_spac_align_state_horizontal\zerocount} +\defcsname\??aligncommand\v!width \endcsname{\c_spac_align_state_horizontal\zerocount} +\defcsname\??aligncommand\v!normal \endcsname{\c_spac_align_state_horizontal\zerocount} +\defcsname\??aligncommand\v!reset \endcsname{\c_spac_align_state_page \zerocount + \c_spac_align_state_horizontal\zerocount} +\defcsname\??aligncommand\v!inner \endcsname{\c_spac_align_state_horizontal\plusfour } +\defcsname\??aligncommand\v!outer \endcsname{\c_spac_align_state_horizontal\plusfive } +\defcsname\??aligncommand\v!flushinner \endcsname{\c_spac_align_state_horizontal\plusfour } +\defcsname\??aligncommand\v!flushouter \endcsname{\c_spac_align_state_horizontal\plusfive } +\defcsname\??aligncommand\v!right \endcsname{\c_spac_align_state_horizontal\plustwo } +\defcsname\??aligncommand\v!left \endcsname{\c_spac_align_state_horizontal\plusthree} +\defcsname\??aligncommand\v!center \endcsname{\c_spac_align_state_horizontal\plusone + \c_spac_align_state_broad \plustwo } +\defcsname\??aligncommand\v!disable \endcsname{\c_spac_align_state_horizontal\plussix } +\defcsname\??aligncommand\v!last \endcsname{\c_spac_align_state_horizontal\plusseven} +\defcsname\??aligncommand\v!end \endcsname{\c_spac_align_state_horizontal\pluseight} +\defcsname\??aligncommand\v!paragraph \endcsname{\c_spac_align_state_horizontal\plusnine} + +\defcsname\??aligncommand\v!lefttoright \endcsname{\c_spac_align_state_direction \plusone } +\defcsname\??aligncommand\v!righttoleft \endcsname{\c_spac_align_state_direction \plustwo } +\defcsname\??aligncommand l2r\endcsname{\c_spac_align_state_direction \plusone } +\defcsname\??aligncommand r2l\endcsname{\c_spac_align_state_direction \plustwo } + +\defcsname\??aligncommand\v!table \endcsname{\c_spac_align_state_vertical \plusthree + \c_spac_align_state_broad \plusone + \c_spac_align_state_horizontal\plustwo } + +\defcsname\??aligncommand\v!lesshyphenation\endcsname{\toksapp\t_spac_align_collected{\lesshyphens}} +\defcsname\??aligncommand\v!morehyphenation\endcsname{\toksapp\t_spac_align_collected{\morehyphens}} + +\defcsname\??aligncommand\v!hanging \endcsname{\toksapp\t_spac_align_collected{\font_protruding_enable }} +\defcsname\??aligncommand\v!hangingboth \endcsname{\toksapp\t_spac_align_collected{\font_protruding_enable_b}} +\defcsname\??aligncommand\v!nothanging \endcsname{\toksapp\t_spac_align_collected{\font_protruding_disable}} +\defcsname\??aligncommand\v!hz \endcsname{\toksapp\t_spac_align_collected{\font_expansion_enable }} +\defcsname\??aligncommand\v!fullhz \endcsname{\toksapp\t_spac_align_collected{\font_expansion_enable_k}} +\defcsname\??aligncommand\v!nohz \endcsname{\toksapp\t_spac_align_collected{\font_expansion_disable }} +%defcsname\??aligncommand\v!spacing \endcsname{\toksapp\t_spac_align_collected{\normalspacing\zerocount}} % not yet +%defcsname\??aligncommand\v!nospacing \endcsname{\toksapp\t_spac_align_collected{\normalspacing\plusone}} % not yet +\defcsname\??aligncommand\v!hyphenated \endcsname{\toksapp\t_spac_align_collected{\dohyphens}} +\defcsname\??aligncommand\v!nothyphenated \endcsname{\toksapp\t_spac_align_collected{\nohyphens}} + +\defcsname\??aligncommand\v!tolerant \endcsname{\toksapp\t_spac_align_collected{\spac_align_set_tolerant}} +\defcsname\??aligncommand\v!verytolerant \endcsname{\toksapp\t_spac_align_collected{\spac_align_set_very_tolerant}} +\defcsname\??aligncommand\v!stretch \endcsname{\toksapp\t_spac_align_collected{\spac_align_set_stretch}} +\defcsname\??aligncommand\v!extremestretch \endcsname{\toksapp\t_spac_align_collected{\spac_align_set_extreme_stretch}} + +\defcsname\??aligncommand \v!final\endcsname{\c_spac_align_state_par_fill\plusone} +\defcsname\??aligncommand1*\v!final\endcsname{\c_spac_align_state_par_fill\plusone} +\defcsname\??aligncommand2*\v!final\endcsname{\c_spac_align_state_par_fill\plustwo} % hardcoded multiplier +\defcsname\??aligncommand3*\v!final\endcsname{\c_spac_align_state_par_fill\plusthree} +\defcsname\??aligncommand4*\v!final\endcsname{\c_spac_align_state_par_fill\plusfour} % a one shot (only usefull in e.g. framed, also needs tolerance and stretch) -\setvalue{\??aligncommand \v!more}{\toksapp\t_spac_align_collected{\looseness\plusone}} -\setvalue{\??aligncommand1*\v!more}{\toksapp\t_spac_align_collected{\looseness\plusone}} -\setvalue{\??aligncommand2*\v!more}{\toksapp\t_spac_align_collected{\looseness\plustwo}} +\defcsname\??aligncommand \v!more\endcsname{\toksapp\t_spac_align_collected{\looseness\plusone}} +\defcsname\??aligncommand1*\v!more\endcsname{\toksapp\t_spac_align_collected{\looseness\plusone}} +\defcsname\??aligncommand2*\v!more\endcsname{\toksapp\t_spac_align_collected{\looseness\plustwo}} -% \setvalue{\??aligncommand ... }{\toksapp\t_spac_align_collected{\nopenalties}} -% \setvalue{\??aligncommand ... }{\toksapp\t_spac_align_collected{\setdefaultpenalties}} +%defcsname\??aligncommand ...\endcsname{\toksapp\t_spac_align_collected{\nopenalties}} +%defcsname\??aligncommand ...\endcsname{\toksapp\t_spac_align_collected{\setdefaultpenalties}} \definehspace [\v!final] [\emspaceamount] @@ -762,8 +739,8 @@ \newtoks \t_spac_every_swap_align \appendtoks - \setvalue{\??aligncommand\v!right}{\c_spac_align_state_horizontal\plusthree}% - \setvalue{\??aligncommand\v!left }{\c_spac_align_state_horizontal\plustwo }% + \defcsname\??aligncommand\v!right\endcsname{\c_spac_align_state_horizontal\plusthree}% + \defcsname\??aligncommand\v!left \endcsname{\c_spac_align_state_horizontal\plustwo }% \to \t_spac_every_swap_align \permanent\protected\def\enablereversealignment @@ -809,11 +786,11 @@ \let\raggedbox\relax -\def\dosetraggedvbox#1% can be more keys .. how about caching here (but seldom used) +\permanent\protected\def\dosetraggedvbox#1% can be more keys .. how about caching here (but seldom used) {\enforced\let\raggedbox\vbox \processcommacommand[#1]\spac_align_set_ragged_vbox} -\def\dosetraggedhbox#1% can be more keys .. how about caching here (but seldom used) +\permanent\protected\def\dosetraggedhbox#1% can be more keys .. how about caching here (but seldom used) {\enforced\let\raggedbox\hbox \processcommacommand[#1]\spac_align_set_ragged_hbox} @@ -848,24 +825,24 @@ \permanent\protected\def\spac_align_horizontal_flushright{\doalignedline\v!left} \permanent\protected\def\spac_align_horizontal_center {\doalignedline\v!middle} -\setvalue{\??alignvertical \v!left }{\enforced\let\raggedbox\spac_align_vertical_left} -\setvalue{\??alignvertical \v!right }{\enforced\let\raggedbox\spac_align_vertical_right} -\setvalue{\??alignvertical \v!middle }{\enforced\let\raggedbox\spac_align_vertical_middle} -\setvalue{\??alignvertical \v!inner }{\enforced\let\raggedbox\spac_align_vertical_inner} -\setvalue{\??alignvertical \v!outer }{\enforced\let\raggedbox\spac_align_vertical_outer} -\setvalue{\??alignvertical \v!flushleft }{\enforced\let\raggedbox\spac_align_vertical_flushleft } -\setvalue{\??alignvertical \v!flushright}{\enforced\let\raggedbox\spac_align_vertical_flushright} -\setvalue{\??alignvertical \v!center }{\enforced\let\raggedbox\spac_align_vertical_center} -\setvalue{\??alignvertical \v!no }{\enforced\let\raggedbox\spac_align_vertical_no} - -\setvalue{\??alignhorizontal\v!left }{\enforced\let\raggedbox\spac_align_horizontal_left} -\setvalue{\??alignhorizontal\v!right }{\enforced\let\raggedbox\spac_align_horizontal_right} -\setvalue{\??alignhorizontal\v!middle }{\enforced\let\raggedbox\spac_align_horizontal_middle} -\setvalue{\??alignhorizontal\v!inner }{\enforced\let\raggedbox\spac_align_horizontal_inner} -\setvalue{\??alignhorizontal\v!outer }{\enforced\let\raggedbox\spac_align_horizontal_outer} -\setvalue{\??alignhorizontal\v!flushleft }{\enforced\let\raggedbox\spac_align_horizontal_flushleft} -\setvalue{\??alignhorizontal\v!flushright}{\enforced\let\raggedbox\spac_align_horizontal_flushright} -\setvalue{\??alignhorizontal\v!center }{\enforced\let\raggedbox\spac_align_horizontal_center} +\defcsname\??alignvertical \v!left \endcsname{\enforced\let\raggedbox\spac_align_vertical_left} +\defcsname\??alignvertical \v!right \endcsname{\enforced\let\raggedbox\spac_align_vertical_right} +\defcsname\??alignvertical \v!middle \endcsname{\enforced\let\raggedbox\spac_align_vertical_middle} +\defcsname\??alignvertical \v!inner \endcsname{\enforced\let\raggedbox\spac_align_vertical_inner} +\defcsname\??alignvertical \v!outer \endcsname{\enforced\let\raggedbox\spac_align_vertical_outer} +\defcsname\??alignvertical \v!flushleft \endcsname{\enforced\let\raggedbox\spac_align_vertical_flushleft } +\defcsname\??alignvertical \v!flushright\endcsname{\enforced\let\raggedbox\spac_align_vertical_flushright} +\defcsname\??alignvertical \v!center \endcsname{\enforced\let\raggedbox\spac_align_vertical_center} +\defcsname\??alignvertical \v!no \endcsname{\enforced\let\raggedbox\spac_align_vertical_no} + +\defcsname\??alignhorizontal\v!left \endcsname{\enforced\let\raggedbox\spac_align_horizontal_left} +\defcsname\??alignhorizontal\v!right \endcsname{\enforced\let\raggedbox\spac_align_horizontal_right} +\defcsname\??alignhorizontal\v!middle \endcsname{\enforced\let\raggedbox\spac_align_horizontal_middle} +\defcsname\??alignhorizontal\v!inner \endcsname{\enforced\let\raggedbox\spac_align_horizontal_inner} +\defcsname\??alignhorizontal\v!outer \endcsname{\enforced\let\raggedbox\spac_align_horizontal_outer} +\defcsname\??alignhorizontal\v!flushleft \endcsname{\enforced\let\raggedbox\spac_align_horizontal_flushleft} +\defcsname\??alignhorizontal\v!flushright\endcsname{\enforced\let\raggedbox\spac_align_horizontal_flushright} +\defcsname\??alignhorizontal\v!center \endcsname{\enforced\let\raggedbox\spac_align_horizontal_center} % The next one can be in use so we keep it around but oen should % be aware of possible interference. @@ -874,7 +851,7 @@ {\protected\def\updateraggedskips{\dosetraggedskips{#1}{#2}{#3}{#4}{#5}{#6}{#7}}% \updateraggedskips} -\permanent\def\dosetraggedskips#1#2#3#4#5#6#7% +\permanent\protected\def\dosetraggedskips#1#2#3#4#5#6#7% {\raggedstatus #1\relax \leftskip 1\leftskip \s!plus#2\relax \rightskip 1\rightskip\s!plus#3\relax @@ -951,7 +928,7 @@ {\everyleftofalignedline {\hskip\dimexpr#1+#4\relax}% \everyrightofalignedline{\hskip\dimexpr#2+#3\relax}}} -\permanent\def\doalignline#1#2% \\ == newline +\permanent\protected\def\doalignline#1#2% \\ == newline {\noindentation % was \noindent \dontleavehmode % added in marrakesch at TUG 2006\begingroup \begingroup @@ -968,21 +945,21 @@ % plain commands -\ifdefined\line \else \permanent\def\line {\hbox to\hsize} \fi -\ifdefined\leftline \else \permanent\def\leftline #1{\line{#1\hss}} \fi -\ifdefined\rightline \else \permanent\def\rightline #1{\line{\hss#1}} \fi -\ifdefined\centerline \else \permanent\def\centerline#1{\line{\hss#1\hss}} \fi +\ifdefined\line \else \permanent\protected\def\line {\hbox to\hsize} \fi +\ifdefined\leftline \else \permanent\protected\def\leftline #1{\line{#1\hss}} \fi +\ifdefined\rightline \else \permanent\protected\def\rightline #1{\line{\hss#1}} \fi +\ifdefined\centerline \else \permanent\protected\def\centerline#1{\line{\hss#1\hss}} \fi % direct commands \installcorenamespace{alignwrapper} -\setuvalue{\??alignwrapper\v!left }{\doalignline\relax \hss } -\setuvalue{\??alignwrapper\v!middle}{\doalignline\hss \hss } -\setuvalue{\??alignwrapper\v!right }{\doalignline\hss \relax} -\setuvalue{\??alignwrapper\v!max }{\doalignline\relax \relax} +\protected\defcsname\??alignwrapper\v!left \endcsname{\doalignline\relax \hss } +\protected\defcsname\??alignwrapper\v!middle\endcsname{\doalignline\hss \hss } +\protected\defcsname\??alignwrapper\v!right \endcsname{\doalignline\hss \relax} +\protected\defcsname\??alignwrapper\v!max \endcsname{\doalignline\relax \relax} -\def\spac_align_wrapper_middle {\doalignline\hss \hss} +\def\spac_align_wrapper_middle{\doalignline\hss\hss} \def\spac_align_wrapper_handle#1% {\ifcsname\??alignwrapper#1\endcsname\expandafter\lastnamedcs\else\expandafter\spac_align_wrapper_middle\fi} @@ -1014,15 +991,13 @@ \installcorenamespace{alignline} -\letvalue{\??alignline\v!left }\leftaligned -\letvalue{\??alignline\v!right }\rightaligned -\letvalue{\??alignline\v!middle }\midaligned -\letvalue{\??alignline\v!flushleft }\rightaligned % beware, makes no sense in locations / we will have a special locations handler -\letvalue{\??alignline\v!flushright}\leftaligned % beware, makes no sense in locations / we will have a special locations handler -\letvalue{\??alignline\v!center }\midaligned -\letvalue{\??alignline\v!max }\maxaligned - -% \permanent\protected\def\doalignedline#1{\resetrealignsignal\csname\??alignline#1\endcsname} +\letcsname\??alignline\v!left \endcsname\leftaligned +\letcsname\??alignline\v!right \endcsname\rightaligned +\letcsname\??alignline\v!middle \endcsname\midaligned +\letcsname\??alignline\v!flushleft \endcsname\rightaligned % beware, makes no sense in locations / we will have a special locations handler +\letcsname\??alignline\v!flushright\endcsname\leftaligned % beware, makes no sense in locations / we will have a special locations handler +\letcsname\??alignline\v!center \endcsname\midaligned +\letcsname\??alignline\v!max \endcsname\maxaligned %D Experimental (will be redone when floats are redone as it's real messy %D now). It can also be made faster (if needed). @@ -1048,21 +1023,21 @@ \permanent\protected\def\doxcheckline % used for floats so multipass anyway {\signalrightpage\doifelserightpage\donetrue\donefalse} -\setvalue{\??alignline\v!inner }{\doxalignline\doxcheckline++\zeropoint \relax\hss } -\setvalue{\??alignline\v!outer }{\doxalignline\doxcheckline++\zeropoint \hss \relax} -\setvalue{\??alignline\v!innermargin}{\doxalignline\doxcheckline-+\innermargintotal\relax\hss } -\setvalue{\??alignline\v!outermargin}{\doxalignline\doxcheckline+-\outermargintotal\hss \relax} -\setvalue{\??alignline\v!inneredge }{\doxalignline\doxcheckline-+\inneredgetotal \relax\hss } -\setvalue{\??alignline\v!outeredge }{\doxalignline\doxcheckline+-\outeredgetotal \hss \relax} -\setvalue{\??alignline\v!backspace }{\doxalignline\doxcheckline-+\backspace \relax\hss } -\setvalue{\??alignline\v!cutspace }{\doxalignline\doxcheckline+-\cutspace \hss \relax} +\defcsname\??alignline\v!inner \endcsname{\doxalignline\doxcheckline++\zeropoint \relax\hss } +\defcsname\??alignline\v!outer \endcsname{\doxalignline\doxcheckline++\zeropoint \hss \relax} +\defcsname\??alignline\v!innermargin\endcsname{\doxalignline\doxcheckline-+\innermargintotal\relax\hss } +\defcsname\??alignline\v!outermargin\endcsname{\doxalignline\doxcheckline+-\outermargintotal\hss \relax} +\defcsname\??alignline\v!inneredge \endcsname{\doxalignline\doxcheckline-+\inneredgetotal \relax\hss } +\defcsname\??alignline\v!outeredge \endcsname{\doxalignline\doxcheckline+-\outeredgetotal \hss \relax} +\defcsname\??alignline\v!backspace \endcsname{\doxalignline\doxcheckline-+\backspace \relax\hss } +\defcsname\??alignline\v!cutspace \endcsname{\doxalignline\doxcheckline+-\cutspace \hss \relax} -\setvalue{\??alignline\v!leftmargin }{\doxalignline\donefalse --\leftmargintotal \hss \relax} -\setvalue{\??alignline\v!rightmargin}{\doxalignline\donefalse ++\rightmargintotal\relax\hss } -\setvalue{\??alignline\v!leftedge }{\doxalignline\donefalse --\leftedgetotal \hss \relax} -\setvalue{\??alignline\v!rightedge }{\doxalignline\donefalse ++\rightedgetotal \relax\hss } +\defcsname\??alignline\v!leftmargin \endcsname{\doxalignline\donefalse --\leftmargintotal \hss \relax} +\defcsname\??alignline\v!rightmargin\endcsname{\doxalignline\donefalse ++\rightmargintotal\relax\hss } +\defcsname\??alignline\v!leftedge \endcsname{\doxalignline\donefalse --\leftedgetotal \hss \relax} +\defcsname\??alignline\v!rightedge \endcsname{\doxalignline\donefalse ++\rightedgetotal \relax\hss } -\permanent\protected\def\doalignedline#1{\csname\??alignline#1\endcsname} % no \resetrealignsignal here ? +\permanent\protected\def\doalignedline#1{\begincsname\??alignline#1\endcsname} \permanent\protected\def\alignedline#1#2% setting default {\ifcsname\??alignline#1\endcsname @@ -1143,21 +1118,21 @@ \protected\def\spac_align_simple_right #1{{\hss#1}} \protected\def\spac_align_simple_middle#1{{\hss#1\hss}} -\letvalue{\??alignsimple \v!right }\spac_align_simple_left -\letvalue{\??alignsimple \v!outer }\spac_align_simple_left % not managed! see linenumbers -\letvalue{\??alignsimple \v!flushleft }\spac_align_simple_left -\letvalue{\??alignsimple \v!left }\spac_align_simple_right -\letvalue{\??alignsimple \v!inner }\spac_align_simple_right % not managed! see linenumbers -\letvalue{\??alignsimple \v!flushright}\spac_align_simple_right -\letvalue{\??alignsimple \v!middle }\spac_align_simple_middle - -\letvalue{\??alignsimplereverse\v!right }\spac_align_simple_right -\letvalue{\??alignsimplereverse\v!outer }\spac_align_simple_right % not managed! see linenumbers -\letvalue{\??alignsimplereverse\v!flushleft }\spac_align_simple_right -\letvalue{\??alignsimplereverse\v!left }\spac_align_simple_left -\letvalue{\??alignsimplereverse\v!inner }\spac_align_simple_left % not managed! see linenumbers -\letvalue{\??alignsimplereverse\v!flushright}\spac_align_simple_left -\letvalue{\??alignsimplereverse\v!middle }\spac_align_simple_middle +\letcsname\??alignsimple \v!right \endcsname\spac_align_simple_left +\letcsname\??alignsimple \v!outer \endcsname\spac_align_simple_left % not managed! see linenumbers +\letcsname\??alignsimple \v!flushleft \endcsname\spac_align_simple_left +\letcsname\??alignsimple \v!left \endcsname\spac_align_simple_right +\letcsname\??alignsimple \v!inner \endcsname\spac_align_simple_right % not managed! see linenumbers +\letcsname\??alignsimple \v!flushright\endcsname\spac_align_simple_right +\letcsname\??alignsimple \v!middle \endcsname\spac_align_simple_middle + +\letcsname\??alignsimplereverse\v!right \endcsname\spac_align_simple_right +\letcsname\??alignsimplereverse\v!outer \endcsname\spac_align_simple_right % not managed! see linenumbers +\letcsname\??alignsimplereverse\v!flushleft \endcsname\spac_align_simple_right +\letcsname\??alignsimplereverse\v!left \endcsname\spac_align_simple_left +\letcsname\??alignsimplereverse\v!inner \endcsname\spac_align_simple_left % not managed! see linenumbers +\letcsname\??alignsimplereverse\v!flushright\endcsname\spac_align_simple_left +\letcsname\??alignsimplereverse\v!middle \endcsname\spac_align_simple_middle \permanent\protected\def\simplealignedbox#1#2% {\hbox \ifdim#1>\zeropoint to #1 @@ -1206,38 +1181,22 @@ \fi \fi} -% \installnamespace{alignsets} -% -% \setvalue{\??alignsets\v!right }#1#2{\let#1\relax\let#2\hss } -% \setvalue{\??alignsets\v!left }#1#2{\let#1\hss \let#2\relax} -% \setvalue{\??alignsets\v!flushright}#1#2{\let#1\hss \let#2\relax} -% \setvalue{\??alignsets\v!flushleft }#1#2{\let#1\relax\let#2\hss } -% \setvalue{\??alignsets\v!middle }#1#2{\let#1\hss \let#2\hss } -% \setvalue{\??alignsets\v!low }#1#2{\let#1\vss \let#2\relax} -% \setvalue{\??alignsets\v!high }#1#2{\let#1\relax\let#2\vss } -% \setvalue{\??alignsets\v!lohi }#1#2{\let#1\vss \let#2\vss } -% \setvalue{\??alignsets\s!unknown }#1#2{\let#1\relax\let#2\relax} -% -% \protected\def\spac_align_set_ss#1% -% {\csname\??alignsetss\ifcsname\??alignsetss#1\endcsname#1\else\s!unknown\fi\endcsname} - % Some obsolete (old) helpers: -\permanent\tolerant\protected\def\definehbox[#1][#2]% - {\ifarguments\else\setvalue{hbox#1}##1{\hbox to #2{\begstrut##1\endstrut\hss}}\fi} +\permanent\tolerant\protected\def\definehbox[#1]#*[#2]% + {\ifarguments\else\frozen\instance\protected\defcsname hbox#1\endcsname##1{\hbox to #2{\begstrut##1\endstrut\hss}}\fi} %D Some direction related helpers: \installcorenamespace {reverse} -\setvalue{\??reverse\v!normal }{\ifconditional\inlinelefttoright\else\s!reverse\fi} -\setvalue{\??reverse\v!reverse}{\ifconditional\inlinelefttoright \s!reverse\fi} +\defcsname\??reverse\v!normal \endcsname{\ifconditional\inlinelefttoright\else\s!reverse\fi} +\defcsname\??reverse\v!reverse\endcsname{\ifconditional\inlinelefttoright \s!reverse\fi} \permanent\def\usedirectionparameterreverse#1{\begincsname\??reverse#1\c!direction\endcsname} %D Now official: -\permanent\protected\def\spaceorpar - {\endgraf\ifhmode\space\fi} +\permanent\protected\def\spaceorpar{\endgraf\ifhmode\space\fi} \protect \endinput diff --git a/tex/context/base/mkxl/spac-chr.lmt b/tex/context/base/mkxl/spac-chr.lmt new file mode 100644 index 000000000..ac90926e1 --- /dev/null +++ b/tex/context/base/mkxl/spac-chr.lmt @@ -0,0 +1,348 @@ +if not modules then modules = { } end modules ['spac-chr'] = { + version = 1.001, + optimize = true, + comment = "companion to spac-chr.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local byte, lower = string.byte, string.lower + +-- beware: attribute copying is bugged ... there will be a proper luatex helper +-- for this + +-- to be redone: characters will become tagged spaces instead as then we keep track of +-- spaceskip etc + +-- todo: only setattr when export / use properties + +local next = next + +local trace_characters = false trackers.register("typesetters.characters", function(v) trace_characters = v end) +local trace_nbsp = false trackers.register("typesetters.nbsp", function(v) trace_nbsp = v end) + +local report_characters = logs.reporter("typesetting","characters") + +local nodes, node = nodes, node + +local nuts = nodes.nuts + +local getboth = nuts.getboth +local getnext = nuts.getnext +local getprev = nuts.getprev +local getattr = nuts.getattr +local setattr = nuts.setattr +local getlanguage = nuts.getlanguage +local setchar = nuts.setchar +local setattrlist = nuts.setattrlist +local getfont = nuts.getfont +local setsubtype = nuts.setsubtype +local isglyph = nuts.isglyph + +local setcolor = nodes.tracers.colors.set + +local insert_node_before = nuts.insert_before +local insert_node_after = nuts.insert_after +local remove_node = nuts.remove +----- traverse_id = nuts.traverse_id +----- traverse_char = nuts.traverse_char +local nextchar = nuts.traversers.char +local nextglyph = nuts.traversers.glyph + +local copy_node = nuts.copy + +local nodepool = nuts.pool +local new_penalty = nodepool.penalty +local new_glue = nodepool.glue +local new_kern = nodepool.kern +local new_rule = nodepool.rule + +local nodecodes = nodes.nodecodes +local gluecodes = nodes.gluecodes + +local glyph_code = nodecodes.glyph +local spaceskip_code = gluecodes.spaceskip + +local chardata = characters.data +local is_punctuation = characters.is_punctuation + +local typesetters = typesetters + +local unicodeblocks = characters.blocks + +local characters = typesetters.characters or { } -- can be predefined +typesetters.characters = characters + +local fonthashes = fonts.hashes +local fontparameters = fonthashes.parameters +local fontcharacters = fonthashes.characters +local fontquads = fonthashes.quads + +local setmetatableindex = table.setmetatableindex + +local a_character = attributes.private("characters") +local a_alignstate = attributes.private("alignstate") + +local c_zero = byte('0') +local c_period = byte('.') + +local function inject_quad_space(unicode,head,current,fraction) + if fraction ~= 0 then + fraction = fraction * fontquads[getfont(current)] + end + local glue = new_glue(fraction) + setattrlist(glue,current) + setattrlist(current) -- why reset all + setattr(glue,a_character,unicode) + return insert_node_after(head,current,glue) +end + +local function inject_char_space(unicode,head,current,parent) + local font = getfont(current) + local char = fontcharacters[font][parent] + local glue = new_glue(char and char.width or fontparameters[font].space) + setattrlist(glue,current) + setattrlist(current) -- why reset all + setattr(glue,a_character,unicode) + return insert_node_after(head,current,glue) +end + +local function inject_nobreak_space(unicode,head,current,space,spacestretch,spaceshrink) + local glue = new_glue(space,spacestretch,spaceshrink) + local penalty = new_penalty(10000) + setattrlist(glue,current) + setattrlist(current) -- why reset all + setattr(glue,a_character,unicode) -- bombs + head, current = insert_node_after(head,current,penalty) + if trace_nbsp then + local rule = new_rule(space) + local kern = new_kern(-space) + local penalty = new_penalty(10000) + setcolor(rule,"orange") + head, current = insert_node_after(head,current,rule) + head, current = insert_node_after(head,current,kern) + head, current = insert_node_after(head,current,penalty) + end + return insert_node_after(head,current,glue) +end + +local function nbsp(head,current) + local para = fontparameters[getfont(current)] + local attr = getattr(current,a_alignstate) or 0 + if attr >= 1 or attr <= 3 then -- flushright + head, current = inject_nobreak_space(0x00A0,head,current,para.space,0,0) + else + head, current = inject_nobreak_space(0x00A0,head,current,para.space,para.spacestretch,para.spaceshrink) + end + setsubtype(current,spaceskip_code) + return head, current +end + +-- assumes nuts or nodes, depending on callers .. so no tonuts here + +function characters.replacenbsp(head,original) + local head, current = nbsp(head,original) + return remove_node(head,original,true) +end + +function characters.replacenbspaces(head) + local wipe = false + for current, char, font in nextglyph, head do -- can be anytime so no traverse_char + if char == 0x00A0 then + if wipe then + head = remove_node(h,current,true) + wipe = false + end + local h = nbsp(head,current) + if h then + wipe = current + end + end + end + if wipe then + head = remove_node(head,current,true) + end + return head +end + +-- This initialization might move someplace else if we need more of it. The problem is that +-- this module depends on fonts so we have an order problem. + +local nbsphash = { } setmetatableindex(nbsphash,function(t,k) + -- this needs checking ! + for i=unicodeblocks.devanagari.first,unicodeblocks.devanagari.last do nbsphash[i] = true end + for i=unicodeblocks.kannada .first,unicodeblocks.kannada .last do nbsphash[i] = true end + setmetatableindex(nbsphash,nil) + return nbsphash[k] +end) + +local methods = { + + -- The next one uses an attribute assigned to the character but still we + -- don't have the 'local' value. + + -- maybe also 0x0008 : backspace + + [0x001F] = function(head,current) -- kind of special + local next = getnext(current) + if next then + local char, font = isglyph(next) + if char then + head, current = remove_node(head,current,true) + if not is_punctuation[char] then + local p = fontparameters[font] + head, current = insert_node_before(head,current,new_glue(p.space,p.space_stretch,p.space_shrink)) + end + end + end + end, + + [0x00A0] = function(head,current) -- nbsp + local prev, next = getboth(current) + if next then + local char = isglyph(current) + if not char then + -- move on + elseif char == 0x200C or char == 0x200D then -- nzwj zwj + next = getnext(next) + if next then + char = isglyph(next) + if char and nbsphash[char] then + return false + end + end + elseif nbsphash[char] then + return false + end + end + if prev then + local char = isglyph(prev) + if char and nbsphash[char] then + return false + end + end + return nbsp(head,current) + end, + + [0x00AD] = function(head,current) -- softhyphen + return insert_node_after(head,current,languages.explicithyphen(current)) + end, + + [0x2000] = function(head,current) -- enquad + return inject_quad_space(0x2000,head,current,1/2) + end, + + [0x2001] = function(head,current) -- emquad + return inject_quad_space(0x2001,head,current,1) + end, + + [0x2002] = function(head,current) -- enspace + return inject_quad_space(0x2002,head,current,1/2) + end, + + [0x2003] = function(head,current) -- emspace + return inject_quad_space(0x2003,head,current,1) + end, + + [0x2004] = function(head,current) -- threeperemspace + return inject_quad_space(0x2004,head,current,1/3) + end, + + [0x2005] = function(head,current) -- fourperemspace + return inject_quad_space(0x2005,head,current,1/4) + end, + + [0x2006] = function(head,current) -- sixperemspace + return inject_quad_space(0x2006,head,current,1/6) + end, + + [0x2007] = function(head,current) -- figurespace + return inject_char_space(0x2007,head,current,c_zero) + end, + + [0x2008] = function(head,current) -- punctuationspace + return inject_char_space(0x2008,head,current,c_period) + end, + + [0x2009] = function(head,current) -- breakablethinspace + return inject_quad_space(0x2009,head,current,1/8) -- same as next + end, + + [0x200A] = function(head,current) -- hairspace + return inject_quad_space(0x200A,head,current,1/8) -- same as previous (todo) + end, + + [0x200B] = function(head,current) -- zerowidthspace + return inject_quad_space(0x200B,head,current,0) + end, + + [0x202F] = function(head,current) -- narrownobreakspace + return inject_nobreak_space(0x202F,head,current,fontquads[getfont(current)]/8) + end, + + [0x205F] = function(head,current) -- math thinspace + return inject_nobreak_space(0x205F,head,current,4*fontquads[getfont(current)]/18) + end, + + -- The next one is also a bom so maybe only when we have glyphs around it + + -- [0xFEFF] = function(head,current) -- zerowidthnobreakspace + -- return head, current + -- end, + +} + +characters.methods = methods + +-- function characters.handler(head) -- todo: use traverse_id +-- local current = head +-- while current do +-- local char, id = isglyph(current) +-- if char then +-- local next = getnext(current) +-- local method = methods[char] +-- if method then +-- if trace_characters then +-- report_characters("replacing character %C, description %a",char,lower(chardata[char].description)) +-- end +-- local h = method(head,current) +-- if h then +-- head = remove_node(h,current,true) +-- end +-- end +-- current = next +-- else +-- current = getnext(current) +-- end +-- end +-- return head +-- end + +-- this also works ok in math as we run over glyphs and these stay glyphs ... not sure +-- about scripts and such but that is not important anyway ... some day we can consider +-- special definitions in math + +function characters.handler(head) + local wipe = false + for current, char in nextchar, head do + local method = methods[char] + if method then + if wipe then + head = remove_node(head,wipe,true) + wipe = false + end + if trace_characters then + report_characters("replacing character %C, description %a",char,lower(chardata[char].description)) + end + local h = method(head,current) + if h then + wipe = current + end + end + end + if wipe then + head = remove_node(head,wipe,true) + end + return head +end diff --git a/tex/context/base/mkxl/spac-chr.mkxl b/tex/context/base/mkxl/spac-chr.mkxl index 57700704f..82c8be0ec 100644 --- a/tex/context/base/mkxl/spac-chr.mkxl +++ b/tex/context/base/mkxl/spac-chr.mkxl @@ -15,7 +15,7 @@ \unprotect -\registerctxluafile{spac-chr}{optimize} +\registerctxluafile{spac-chr}{autosuffix,optimize} \definesystemattribute[characters][public] diff --git a/tex/context/base/mkxl/spac-hor.lmt b/tex/context/base/mkxl/spac-hor.lmt new file mode 100644 index 000000000..7db8d4d6f --- /dev/null +++ b/tex/context/base/mkxl/spac-hor.lmt @@ -0,0 +1,38 @@ +if not modules then modules = { } end modules ['spac-hor'] = { + version = 1.001, + comment = "companion to spac-hor.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local chardata = characters.data +local peekchar = tokens.scanners.peekchar +local ctx_space = context.space + +local can_have_space = table.tohash { + "lu", "ll", "lt", "lm", "lo", -- letters + -- "mn", "mc", "me", -- marks + "nd", "nl", "no", -- numbers + "ps", "pi", -- initial + -- "pe", "pf", -- final + -- "pc", "pd", "po", -- punctuation + "sm", "sc", "sk", "so", -- symbols + -- "zs", "zl", "zp", -- separators + -- "cc", "cf", "cs", "co", "cn", -- others +} + +interfaces.implement { + name = "autoinsertnextspace", + protected = true, + public = true, + actions = function() + local char = peekchar() + if char then + local d = chardata[char] + if d and can_have_space[d.category] then + ctx_space() + end + end + end, +} diff --git a/tex/context/base/mkxl/spac-hor.mkxl b/tex/context/base/mkxl/spac-hor.mkxl index b4704319f..687e7c370 100644 --- a/tex/context/base/mkxl/spac-hor.mkxl +++ b/tex/context/base/mkxl/spac-hor.mkxl @@ -15,9 +15,9 @@ \unprotect -\registerctxluafile{spac-hor}{} +\registerctxluafile{spac-hor}{autosuffix} -\let\parfillrightskip\parfillskip +\aliased\let\parfillrightskip\parfillskip \bitwiseflip \normalizelinemode \parindentskipcode \bitwiseflip \normalizelinemode \normalizelinecode @@ -126,7 +126,7 @@ \installcorenamespace{indentingmethod} \permanent\protected\def\installindentingmethod#1#2% - {\setvalue{\??indentingmethod#1}{#2}} + {\defcsname\??indentingmethod#1\endcsname{#2}} \installindentingmethod \v!no {\parindent\zeropoint} \installindentingmethod \v!not {\parindent\zeropoint} @@ -281,10 +281,10 @@ \begincsname\??indentnext\p_indentnext\endcsname \fi} -\letvalue{\??indentnext }\donothing -\letvalue{\??indentnext\v!yes }\spac_indentation_variant_yes -\letvalue{\??indentnext\v!no }\spac_indentation_variant_no -\letvalue{\??indentnext\v!auto}\spac_indentation_variant_auto +\letcsname\??indentnext \endcsname\donothing +\letcsname\??indentnext\v!yes \endcsname\spac_indentation_variant_yes +\letcsname\??indentnext\v!no \endcsname\spac_indentation_variant_no +\letcsname\??indentnext\v!auto\endcsname\spac_indentation_variant_auto %D An example of usage: %D @@ -383,16 +383,6 @@ \installspacingmethod \v!packed {\newfrenchspacing} % slighly more after punctuation \installspacingmethod \v!broad {\nonfrenchspacing} % more depending on what punctuation -%% \permanent\protected\def\setupspacing -%% {\doifelsenextoptionalcs\spac_spacecodes_setup_yes\spac_spacecodes_setup_nop} -%% -%% \def\spac_spacecodes_setup_yes[#1]% -%% {\begincsname\??spacecodemethod#1\endcsname -%% \updateraggedskips} -%% -%% \def\spac_spacecodes_setup_nop -%% {\updateraggedskips} - \permanent\tolerant\protected\def\setupspacing[#1]% {\ifarguments\or \begincsname\??spacecodemethod#1\endcsname @@ -481,7 +471,7 @@ \letcatcodecommand \ctxcatcodes \tildeasciicode \nonbreakablespace % overloaded later -% \def\space { } +% \def\space { } \permanent\protected\def\removelastspace{\ifhmode\unskip\fi} \permanent\protected\def\nospace {\removelastspace\ignorespaces} @@ -645,12 +635,12 @@ \c!default=\v!middle] \appendtoks - \frozen\instance\setuevalue{\e!start\currentnarrower}{\spac_narrower_start[\currentnarrower]}% - \frozen\instance\setuevalue{\e!stop \currentnarrower}{\spac_narrower_stop}% + \frozen\instance\protected\defcsname\e!start\currentnarrower\endcsname{\spac_narrower_start[\currentnarrower]}% + \frozen\instance\protected\defcsname\e!stop \currentnarrower\endcsname{\spac_narrower_stop}% \to \everydefinenarrower \permanent\protected\def\installnarrowermethod#1#2% - {\setvalue{\??narrowermethod#1}{#2}} + {\defcsname\??narrowermethod#1\endcsname{#2}} \protected\def\spac_narrower_method_analyze#1% {\ifcsname\??narrowermethod#1\endcsname @@ -793,21 +783,15 @@ \newskip\leftskipadaption \newskip\rightskipadaption -\setvalue{\??skipadaptionleft \v!yes }{\ifzeropt\d_spac_indentation_par\narrowerparameter\c!left\else\d_spac_indentation_par\fi} -\letvalue{\??skipadaptionleft \v!no }\zeropoint -\letvalue{\??skipadaptionleft \empty }\zeropoint -\setvalue{\??skipadaptionright\v!yes }{\narrowerparameter\c!right} -\letvalue{\??skipadaptionright\v!no }\zeropoint -\letvalue{\??skipadaptionright\empty }\zeropoint - -% \setvalue{\??skipadaptionleft \v!standard}{\ifzeropt\d_spac_indentation_par\narrowerparameter\c!left\else\d_spac_indentation_par\fi} -% \setvalue{\??skipadaptionright\v!standard}{\narrowerparameter\c!right} - -\letcsnamecsname\csname\??skipadaptionleft \v!standard\endcsname\csname\??skipadaptionleft \v!yes\endcsname -\letcsnamecsname\csname\??skipadaptionright\v!standard\endcsname\csname\??skipadaptionright\v!yes\endcsname +\defcsname\??skipadaptionleft \v!yes\endcsname{\ifzeropt\d_spac_indentation_par\narrowerparameter\c!left\else\d_spac_indentation_par\fi} +\letcsname\??skipadaptionleft \v!no \endcsname\zeropoint +\letcsname\??skipadaptionleft \empty\endcsname\zeropoint +\defcsname\??skipadaptionright\v!yes\endcsname{\narrowerparameter\c!right} +\letcsname\??skipadaptionright\v!no \endcsname\zeropoint +\letcsname\??skipadaptionright\empty\endcsname\zeropoint -% \protected\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\csname\??skipadaptionleft #1\endcsname\else#1\fi\relax} -% \protected\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\csname\??skipadaptionright#1\endcsname\else#1\fi\relax} +\letcsname\??skipadaptionleft \v!standard\expandafter\endcsname\csname\??skipadaptionleft \v!yes\endcsname +\letcsname\??skipadaptionright\v!standard\expandafter\endcsname\csname\??skipadaptionright\v!yes\endcsname \permanent\protected\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\lastnamedcs\else#1\fi\relax} \permanent\protected\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\lastnamedcs\else#1\fi\relax} @@ -840,7 +824,7 @@ \installcorenamespace{tolerancemethods} \permanent\protected\def\installtolerancemethod#1#2#3% - {\setvalue{\??tolerancemethods#1:#2}{#3}} + {\defcsname\??tolerancemethods#1:#2\endcsname{#3}} \installtolerancemethod \v!vertical \v!verystrict {\let\bottomtolerance\empty} \installtolerancemethod \v!vertical \v!strict {\def\bottomtolerance{.050}} @@ -913,17 +897,13 @@ %D {\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi} %D \stoptyping %D -%D But what is a \type{\strut}? Normally it's a rule of width -%D zero, but when made visual, it's a rule and a negative skip. -%D The mechanism for putting things in the margins described -%D here cannot handle this situation very well. One -%D characteristic of \type{\strut} is that the \type{\unhcopy} -%D results in entering horizontal mode, which in return leads -%D to some indentation. -%D -%D To serve our purpose a bit better, the macro \type{\strut} -%D can be redefined as: +%D But what is a \type {\strut}? Normally it's a rule of width zero, but when made +%D visual, it's a rule and a negative skip. The mechanism for putting things in the +%D margins described here cannot handle this situation very well. One characteristic +%D of \type {\strut} is that the \type {\unhcopy} results in entering horizontal +%D mode, which in return leads to some indentation. %D +%D To serve our purpose a bit better, the macro \type {\strut} can be redefined as: %D \starttyping %D \def\strut %D {\relax\ifmmode\else\hskip0pt\fi\copy\strutbox} @@ -940,9 +920,9 @@ %D \fi} %D \stoptyping %D -%D In \CONTEXT\ however we save some processing time by putting -%D an extra \type{\hbox} around the \type{\strutbox}. - +%D In \CONTEXT\ however we save some processing time by putting an extra \type +%D {\hbox} around the \type {\strutbox}. +%D %D \starttyping %D % \setuplayout[gridgrid=yes] \showgrid %D @@ -970,8 +950,8 @@ %D \stoptyping \permanent\protected\def\justonespace{\removeunwantedspaces\space} -%frozen\protected\def\justaperiod {\removeunwantedspaces.} -%frozen\protected\def\justacomma {\removeunwantedspaces,} +%permanent\protected\def\justaperiod {\removeunwantedspaces.} +%permanent\protected\def\justacomma {\removeunwantedspaces,} \installcorenamespace{hspace} @@ -981,9 +961,9 @@ \permanent\tolerant\protected\def\definehspace[#1]#*[#2]#*[#3]% #1 = optional namespace {\ifparameter#3\or - \setvalue{\??hspace#1:#2}{#3}% + \defcsname\??hspace#1:#2\endcsname{#3}% \else - \setvalue{\??hspace:#1}{#2}% + \defcsname\??hspace :#1\endcsname{#2}% \fi} \permanent\tolerant\protected\def\hspace[#1]#*[#2]% @@ -1081,7 +1061,7 @@ \installcorenamespace{spacemethods} \permanent\protected\def\installspacemethod#1#2% needs to set \obeyedspace - {\setvalue{\??spacemethods#1}{#2}} + {\defcsname\??spacemethods#1\endcsname{#2}} \permanent\def\activatespacehandler#1% {\csname\??spacemethods\ifcsname\??spacemethods#1\endcsname#1\else\v!off\fi\endcsname} @@ -1127,21 +1107,17 @@ %D %D \typebuffer \getbuffer -\permanent\protected\def\autoinsertnextspace - {\futurelet\nexttoken\spac_spaces_auto_insert_next} - -\permanent\def\spac_spaces_auto_insert_next - {\clf_autonextspace{\normalmeaning\nexttoken}} % todo, just consult nexttoken at the lua end +% \autoinsertnextspace % defined at the lua end %D Moved from bib module: \permanent\protected\def\outdented#1% {\hskip-\hangindent#1\relax} -%D Beware: due to char-def this becomes an active character but that -%D might change sometime when we will replace all these specials to -%D node insertions. We might even expand it to utf then as it then -%D can be used in string comparison (not that much needed anyway). +%D Beware: due to char-def this becomes an active character but that might change +%D sometime when we will replace all these specials to node insertions. We might +%D even expand it to utf then as it then can be used in string comparison (not that +%D much needed anyway). % \chardef\zwnj="200C % \chardef\zwj ="200D diff --git a/tex/context/base/mkxl/spac-prf.lmt b/tex/context/base/mkxl/spac-prf.lmt new file mode 100644 index 000000000..2223c7730 --- /dev/null +++ b/tex/context/base/mkxl/spac-prf.lmt @@ -0,0 +1,949 @@ + if not modules then modules = { } end modules ['spac-prf'] = { + version = 1.001, + comment = "companion to spac-prf.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is a playground, a byproduct of some experiments in a project where +-- we needed something like this where it works ok, but nevertheless it's +-- still experimental code. It is very likely to change (or extended). + +local unpack, rawget = unpack, rawget + +local formatters = string.formatters + +local nodecodes = nodes.nodecodes +local gluecodes = nodes.gluecodes +local listcodes = nodes.listcodes + +local glyph_code = nodecodes.glyph +local disc_code = nodecodes.disc +local kern_code = nodecodes.kern +local penalty_code = nodecodes.penalty +local glue_code = nodecodes.glue +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local unset_code = nodecodes.unset +local math_code = nodecodes.math +local rule_code = nodecodes.rule +local marginkern_code = nodecodes.marginkern + +local leaders_code = gluecodes.leaders +local lineskip_code = gluecodes.lineskip +local baselineskip_code = gluecodes.baselineskip + +local linelist_code = listcodes.line + +local texlists = tex.lists +local settexattribute = tex.setattribute + +local nuts = nodes.nuts +local tonut = nodes.tonut +local tonode = nuts.tonode + +local getreplace = nuts.getreplace +local getattr = nuts.getattr +local getid = nuts.getid +local getnext = nuts.getnext +local getprev = nuts.getprev +local getsubtype = nuts.getsubtype +local getlist = nuts.getlist +local gettexbox = nuts.getbox +local getwhd = nuts.getwhd +local getglue = nuts.getglue +local getkern = nuts.getkern +local getshift = nuts.getshift +local getwidth = nuts.getwidth +local getheight = nuts.getheight +local getdepth = nuts.getdepth +local getboxglue = nuts.getboxglue + +local setlink = nuts.setlink +local setlist = nuts.setlist +local setattr = nuts.setattr +local setwhd = nuts.setwhd +local setshift = nuts.setshift +local setwidth = nuts.setwidth +local setheight = nuts.setheight +local setdepth = nuts.setdepth + +local properties = nodes.properties.data +local setprop = nuts.setprop +local getprop = nuts.getprop +local theprop = nuts.theprop + +local floor = math.floor +local ceiling = math.ceil + +local new_rule = nuts.pool.rule +local new_glue = nuts.pool.glue +local new_kern = nuts.pool.kern +local hpack_nodes = nuts.hpack +local find_node_tail = nuts.tail +local setglue = nuts.setglue + +local a_visual = attributes.private("visual") +local a_snapmethod = attributes.private("snapmethod") +local a_profilemethod = attributes.private("profilemethod") +----- a_specialcontent = attributes.private("specialcontent") + +local variables = interfaces.variables +local v_none = variables.none +local v_fixed = variables.fixed +local v_strict = variables.strict + +local setcolor = nodes.tracers.colors.set +local settransparency = nodes.tracers.transparencies.set + +local enableaction = nodes.tasks.enableaction + +local profiling = { } +builders.profiling = profiling + +local report = logs.reporter("profiling") + +local show_profile = false trackers.register("profiling.show", function(v) show_profile = v end) +local trace_profile = false trackers.register("profiling.trace",function(v) trace_profile = v end) + +local function getprofile(line,step) + + -- only l2r + -- no hz yet + + local line = tonut(line) + local current = getlist(line) + + if not current then + return + end + + local glue_set, glue_order, glue_sign = getboxglue(line) + + local heights = { } + local depths = { } + local width = 0 + local position = 0 + local step = step or 65536 -- * 2 -- 2pt + local margin = step / 4 + local min = 0 + local max = ceiling(getwidth(line)/step) + 1 + local wd = 0 + local ht = 0 + local dp = 0 + + for i=min,max do + heights[i] = 0 + depths [i] = 0 + end + + -- remember p + + local function progress() + position = width + width = position + wd + p = floor((position - margin)/step + 0.5) + w = floor((width + margin)/step - 0.5) + if p < 0 then + p = 0 + end + if w < 0 then + w = 0 + end + if p > w then + w, p = p, w + end + if w > max then + for i=max+1,w+1 do + heights[i] = 0 + depths [i] = 0 + end + max = w + end + for i=p,w do + if ht > heights[i] then + heights[i] = ht + end + if dp > depths[i] then + depths[i] = dp + end + end + end + + local function process(current) -- called nested in disc replace + while current do + local id = getid(current) + if id == glyph_code then + wd, ht, dp = getwhd(current) + progress() + elseif id == kern_code then + wd = getkern(current) + ht = 0 + dp = 0 + progress() + elseif id == disc_code then + local replace = getreplace(current) + if replace then + process(replace) + end + elseif id == glue_code then + local width, stretch, shrink, stretch_order, shrink_order = getglue(current) + if glue_sign == 1 then + if stretch_order == glue_order then + wd = width + stretch * glue_set + else + wd = width + end + elseif glue_sign == 2 then + if shrink_order == glue_order then + wd = width - shrink * glue_set + else + wd = width + end + else + wd = width + end + if getsubtype(current) >= leaders_code then + local leader = getleader(current) + local w + w, ht, dp = getwhd(leader) -- can become getwhd(current) after 1.003 + else + ht = 0 + dp = 0 + end + progress() + elseif id == hlist_code then + -- we could do a nested check .. but then we need to push / pop glue + local shift = getshift(current) + local w, h, d = getwhd(current) + -- if getattr(current,a_specialcontent) then + if getprop(current,"specialcontent") then + -- like a margin note, maybe check for wd + wd = w + ht = 0 + dp = 0 + else + wd = w + ht = h - shift + dp = d + shift + end + progress() + elseif id == vlist_code or id == unset_code then + local shift = getshift(current) -- todo + wd, ht, dp = getwhd(current) + progress() + elseif id == rule_code then + wd, ht, dp = getwhd(current) + progress() + elseif id == math_code then + wd = getkern(current) + getwidth(current) -- surround + ht = 0 + dp = 0 + progress() + elseif id == marginkern_code then + -- not in lmtx + wd = getwidth(current) + ht = 0 + dp = 0 + progress() + else +-- print(nodecodes[id]) + end + current = getnext(current) + end + end + + process(current) + + return { + heights = heights, + depths = depths, + min = min, -- not needed + max = max, + step = step, + } + +end + +profiling.get = getprofile + +local function getpagelist() + local pagehead = texlists.page_head + if pagehead then + pagehead = tonut(texlists.page_head) + pagetail = find_node_tail(pagehead) + else + pagetail = nil + end + return pagehead, pagetail +end + +local function setprofile(n,step) + local p = rawget(properties,n) + if p then + local pp = p.profile + if not pp then + pp = getprofile(n,step) + p.profile = pp + end + return pp + else + local pp = getprofile(n,step) + properties[n] = { profile = pp } + return pp + end +end + +local function hasprofile(n) + local p = rawget(properties,n) + if p then + return p.profile + end +end + +local function addstring(height,depth) + local typesetters = nuts.typesetters + local hashes = fonts.hashes + local infofont = fonts.infofont() + local emwidth = hashes.emwidths [infofont] + local exheight = hashes.exheights[infofont] + local httext = height + local dptext = depth + local httext = typesetters.tohpack(height,infofont) + local dptext = typesetters.tohpack(depth,infofont) + setshift(httext,- 1.2 * exheight) + setshift(dptext, 0.6 * exheight) + local text = hpack_nodes(setlink( + new_kern(-getwidth(httext)-emwidth), + httext, + new_kern(-getwidth(dptext)), + dptext + )) + setwhd(text,0,0,0) + return text +end + +local function addprofile(node,profile,step) + + local line = tonut(node) + + if not profile then + profile = setprofile(line,step) + end + + if not profile then + report("some error") + return node + end + + if profile.shown then + return node + end + + local list = getlist(line) + profile.shown = true + + local heights = profile.heights + local depths = profile.depths + local step = profile.step + + local head = nil + local tail = nil + + local lastht = 0 + local lastdp = 0 + local lastwd = 0 + + local visual = "f:s:t" -- this can change ! + + local function progress() + if lastwd == 0 then + return + end + local what = nil + if lastht == 0 and lastdp == 0 then + what = new_kern(lastwd) + else + what = new_rule(lastwd,lastht,lastdp) + setcolor(what,visual) + settransparency(what,visual) + end + if tail then + setlink(tail,what) + else + head = what + end + tail = what + end + +-- inspect(profile) + + for i=profile.min,profile.max do + local ht = heights[i] + local dp = depths[i] + if ht ~= lastht or dp ~= lastdp and lastwd > 0 then + progress() + lastht = ht + lastdp = dp + lastwd = step + else + lastwd = lastwd + step + end + end + if lastwd > 0 then + progress() + end + + local rule = hpack_nodes(head) + + setwhd(rule,0,0,0) + + -- if texttoo then + -- + -- local text = addstring( + -- formatters["%0.4f"](getheight(rule)/65536), + -- formatters["%0.4f"](getdepth(rule) /65536) + -- ) + -- + -- setlink(text,rule) + -- + -- rule = text + -- + -- end + + setlink(rule,list) + setlist(line,rule) + +end + +profiling.add = addprofile + +local methods = { } + +local function getdelta(t_profile,b_profile) + local t_heights = t_profile.heights + local t_depths = t_profile.depths + local t_max = t_profile.max + local b_heights = b_profile.heights + local b_depths = b_profile.depths + local b_max = b_profile.max + + local max = t_max + local delta = 0 + + if t_max > b_max then + for i=b_max+1,t_max do + b_depths [i] = 0 + b_heights[i] = 0 + end + max = t_max + elseif b_max > t_max then + for i=t_max+1,b_max do + t_depths [i] = 0 + t_heights[i] = 0 + end + max = b_max + end + + for i=0,max do + local ht = b_heights[i] + local dp = t_depths[i] + local hd = ht + dp + if hd > delta then + delta = hd + end + end + + return delta +end + +-- local properties = theprop(bot) +-- local unprofiled = properties.unprofiled +-- if not unprofiled then -- experiment +-- properties.unprofiled = { +-- height = height, +-- strutht = strutht, +-- } +-- end + +-- lineskip | lineskiplimit + +local function inject(top,bot,amount) -- todo: look at penalties + local glue = new_glue(amount) + -- + setattr(glue,a_profilemethod,0) + setattr(glue,a_visual,getattr(top,a_visual)) + -- + setlink(top,glue,bot) +end + +methods[v_none] = function() + return false +end + +methods[v_strict] = function(top,bot,t_profile,b_profile,specification) + + local top = tonut(top) + local bot = tonut(bot) + + local strutht = specification.height or texdimen.strutht + local strutdp = specification.depth or texdimen.strutdp + local lineheight = strutht + strutdp + + local depth = getdepth(top) + local height = getheight(bot) + local total = depth + height + local distance = specification.distance or 0 + local delta = lineheight - total + + -- there is enough room between the lines so we don't need + -- to add extra distance + + if delta >= distance then + inject(top,bot,delta) + return true + end + + local delta = getdelta(t_profile,b_profile) + local skip = delta - total + distance + + -- we don't want to be too tight so we limit the skip and + -- make sure we have at least lineheight + + inject(top,bot,skip) + return true + +end + +-- todo: also set ht/dp of first / last (but what is that) + +methods[v_fixed] = function(top,bot,t_profile,b_profile,specification) + + local top = tonut(top) + local bot = tonut(bot) + + local strutht = specification.height or texdimen.strutht + local strutdp = specification.depth or texdimen.strutdp + local lineheight = strutht + strutdp + + local depth = getdepth(top) + local height = getheight(bot) + local total = depth + height + local distance = specification.distance or 0 + local delta = lineheight - total + + local snapmethod = getattr(top,a_snapmethod) + + if snapmethod then + + -- no distance (yet) + + if delta < lineheight then + setdepth(top,strutdp) + setheight(bot,strutht) + return true + end + + local delta = getdelta(t_profile,b_profile) + + local dp = strutdp + while depth > lineheight - strutdp do + depth = depth - lineheight + dp = dp + lineheight + end + setdepth(top,dp) + local ht = strutht + while height > lineheight - strutht do + height = height - lineheight + ht = ht + lineheight + end + setheight(bot,ht) + local lines = floor(delta/lineheight) + if lines > 0 then + inject(top,bot,-lines * lineheight) + end + + return true + + end + + if total < lineheight then + setdepth(top,strutdp) + setheight(bot,strutht) + return true + end + + if depth < strutdp then + setdepth(top,strutdp) + total = total - depth + strutdp + end + if height < strutht then + setheight(bot,strutht) + total = total - height + strutht + end + + local delta = getdelta(t_profile,b_profile) + + local target = total - delta + local factor = specification.factor or 1 + local step = lineheight / factor + local correction = 0 + local nofsteps = 0 + while correction < target - step - distance do -- a loop is more accurate, for now + correction = correction + step + nofsteps = nofsteps + 1 + end + + if trace_profile then + report("top line : %s %05i > %s",t_profile.shown and "+" or "-",top,nodes.toutf(getlist(top))) + report("bottom line : %s %05i > %s",b_profile.shown and "+" or "-",bot,nodes.toutf(getlist(bot))) + report(" depth : %p",depth) + report(" height : %p",height) + report(" total : %p",total) + report(" lineheight : %p",lineheight) + report(" delta : %p",delta) + report(" target : %p",target) + report(" factor : %i",factor) + report(" distance : %p",distance) + report(" step : %p",step) + report(" nofsteps : %i",nofsteps) + -- report(" max lines : %s",lines == 0 and "unset" or lines) + report(" correction : %p",correction) + end + + inject(top,bot,-correction) -- we could mess with the present glue (if present) + + return true -- remove interlineglue + +end + +function profiling.distance(top,bot,specification) + local step = specification.step + local method = specification.method + local ptop = getprofile(top,step) + local pbot = getprofile(bot,step) + local action = methods[method or v_strict] or methods[v_strict] + return action(top,bot,ptop,pbot,specification) +end + +local specifications = { } -- todo: save these ! + +function profiling.fixedprofile(current) + local a = getattr(current,a_profilemethod) + if a then + local s = specifications[a] + if s then + return s.method == v_fixed + end + end + return false +end + +local function profilelist(line,mvl) + + local current = line + + local top = nil + local bot = nil + + local t_profile = nil + local b_profile = nil + + local specification = nil + local lastattr = nil + local method = nil + local action = nil + + local distance = 0 + local lastglue = nil + + local pagehead = nil + local pagetail = nil + + if mvl then + + pagehead, pagetail = getpagelist() + + if pagetail then + local current = pagetail + while current do + local id = getid(current) + if id == hlist_code then + local subtype = getsubtype(current) + if subtype == linelist_code then + t_profile = hasprofile(current) + if t_profile then + top = current + end + end + break + elseif id == glue_code then + local wd = getwidth(current) + if not wd or wd == 0 then + -- go on + else + break + end + elseif id == penalty_code then + -- ok + else + break + end + current = getnext(current) + end + end + + end + + while current do + + local attr = getattr(current,a_profilemethod) + + if attr then + + if attr ~= lastattr then + specification = specifications[attr] + method = specification and specification.method + action = method and methods[method] or methods[v_strict] + lastattr = attr + end + + local id = getid(current) + + if id == hlist_code then -- check subtype + local subtype = getsubtype(current) + if subtype == linelist_code then + if top == current then + -- skip + bot = nil -- to be sure + elseif top then + bot = current + b_profile = setprofile(bot) + if show_profile then + addprofile(bot,b_profile) + end + if not t_profile.done then + if action then + local ok = action(top,bot,t_profile,b_profile,specification) + if ok and lastglue and distance ~= 0 then + setglue(lastglue) + end + end + t_profile.done = true + end + top = bot + bot = nil + t_profile = b_profile + b_profile = nil + distance = 0 + else + top = current + t_profile = setprofile(top) + bot = nil + if show_profile then + addprofile(top,t_profile) + end + end + else + top = nil + bot = nil + end + elseif id == glue_code then + if top then + local subtype = getsubtype(current) + -- if subtype == lineskip_code or subtype == baselineskip_code then + local wd = getwidth(current) + if wd > 0 then + distance = wd + lastglue = current + elseif wd < 0 then + top = nil + bot = nil + else + -- ok + end + -- else + -- top = nil + -- bot = nil + -- end + else + top = nil + bot = nil + end + elseif id == penalty_code then + -- okay + else + top = nil + bot = nil + end + else + top = nil + bot = nil + end + current = getnext(current) + end + if top then + t_profile = setprofile(top) + if show_profile then + addprofile(top,t_profile) + end + end +end + +profiling.list = profilelist + +local enabled = false + +function profiling.set(specification) + if not enabled then + enableaction("mvlbuilders", "builders.profiling.pagehandler") + -- too expensive so we expect that this happens explicitly, we keep for reference: + -- enableaction("vboxbuilders","builders.profiling.vboxhandler") + enabled = true + end + local n = #specifications + 1 + specifications[n] = specification + settexattribute(a_profilemethod,n) +end + +function profiling.profilebox(specification) + local boxnumber = specification.box + local current = getlist(gettexbox(boxnumber)) + local top = nil + local bot = nil + local t_profile = nil + local b_profile = nil + local method = specification and specification.method + local action = method and methods[method] or methods[v_strict] + local lastglue = nil + local distance = 0 + while current do + local id = getid(current) + if id == hlist_code then + local subtype = getsubtype(current) + if subtype == linelist_code then + if top then + bot = current + b_profile = setprofile(bot) + if show_profile then + addprofile(bot,b_profile) + end + if not t_profile.done then + if action then + local ok = action(top,bot,t_profile,b_profile,specification) + if ok and lastglue and distance ~= 0 then + setglue(lastglue) + end + end + t_profile.done = true + end + top = bot + t_profile = b_profile + b_profile = nil + distance = 0 + else + top = current + t_profile = setprofile(top) + if show_profile then + addprofile(top,t_profile) + end + bot = nil + end + else + top = nil + bot = nil + end + elseif id == glue_code then + local subtype = getsubtype(current) + if subtype == lineskip_code or subtype == baselineskip_code then + if top then + local wd = getwidth(current) + if wd > 0 then + distance = wd + lastglue = current + elseif wd < 0 then + top = nil + bot = nil + else + -- ok + end + else + top = nil + bot = nil + end + else + top = nil + bot = nil + end + elseif id == penalty_code then + -- okay + else + top = nil + bot = nil + end + current = getnext(current) + end + + if top then + t_profile = setprofile(top) -- not needed + if show_profile then + addprofile(top,t_profile) + end + end + +end + +-- local ignore = table.tohash { +-- "split_keep", +-- "split_off", +-- -- "vbox", +-- } +-- +-- function profiling.vboxhandler(head,where) +-- if head and not ignore[where] then +-- if getnext(head) then +-- profilelist(head) +-- end +-- end +-- return head +-- end + +function profiling.pagehandler(head) + if head then + profilelist(head,true) + end + return head +end + +interfaces.implement { + name = "setprofile", + actions = profiling.set, + arguments = { + { + { "name" }, + { "height", "dimen" }, + { "depth", "dimen" }, + { "distance", "dimen" }, + { "factor", "integer" }, + { "lines", "integer" }, + { "method" } + } + } +} + +interfaces.implement { + name = "profilebox", + actions = profiling.profilebox, + arguments = { + { + { "box", "integer" }, + { "height", "dimen" }, + { "depth", "dimen" }, + { "distance", "dimen" }, + { "factor", "integer" }, + { "lines", "integer" }, + { "method" } + } + } +} diff --git a/tex/context/base/mkxl/spac-prf.mklx b/tex/context/base/mkxl/spac-prf.mklx index 585437ac4..6b4a966f2 100644 --- a/tex/context/base/mkxl/spac-prf.mklx +++ b/tex/context/base/mkxl/spac-prf.mklx @@ -20,11 +20,11 @@ \unprotect -\registerctxluafile{spac-prf}{} +\registerctxluafile{spac-prf}{autosuffix} \definesystemattribute[profilemethod][public] -\installcorenamespace {profile} % beware, profiles are not like in mkii at all +\installcorenamespace {profile} \installcorenamespace {profiles} \installcommandhandler \??profile {profile} \??profile @@ -84,11 +84,11 @@ \ifparameter#settings\or \edef\currentprofile{#profile}% \setupcurrentprofile[#settings]% + \orelse\ifhastok={#profile}% + \let\currentprofile\v!none + \setupcurrentprofile[#profile]% \else - \doifassignmentelse{#profile} - {\let\currentprofile\v!none - \setupcurrentprofile[#profile]}% - {\edef\currentprofile{#profile}}% + \edef\currentprofile{#profile}% \fi \dowithnextbox {\profilegivenbox\currentprofile\nextbox diff --git a/tex/context/base/mkxl/spac-ver.mkxl b/tex/context/base/mkxl/spac-ver.mkxl index f2bb68093..fe74ee06e 100644 --- a/tex/context/base/mkxl/spac-ver.mkxl +++ b/tex/context/base/mkxl/spac-ver.mkxl @@ -648,33 +648,31 @@ \newdimen\openstrutheight \newdimen\openstrutdepth \newdimen\topskipgap -\newdimen\struttotal - -\def\strutheightfactor {.72} -\def\strutdepthfactor {.28} -\def\baselinefactor {2.8} +\newdimen\strutheight +\newdimen\strutdepth +\newdimen\struttotal +\newdimen\strutwidth \let\m_spac_vertical_baseline_stretch_factor \zerocount \let\m_spac_vertical_baseline_shrink_factor \zerocount -\def\minimumstrutheight {\zeropoint} -\def\minimumstrutdepth {\zeropoint} +\mutable\def\strutheightfactor {.72} +\mutable\def\strutdepthfactor {.28} +\mutable\def\baselinefactor {2.8} +\mutable\def\topskipfactor {1.0} +\mutable\def\maxdepthfactor {0.5} -\def\normallineheight {\baselinefactor\exheight} -\def\minimumlinedistance {\lineskip} +\mutable\def\minimumstrutheight {\zeropoint} +\mutable\def\minimumstrutdepth {\zeropoint} -\def\strutheight {\zeropoint} -\def\strutdepth {\zeropoint} -\def\strutwidth {\zeropoint} +\mutable\def\normallineheight {\baselinefactor\exheight} +\mutable\def\minimumlinedistance {\lineskip} -\let\spacingfactor \plusone +\mutable\let\spacingfactor \plusone -\def\topskipfactor {1.0} -\def\maxdepthfactor {0.5} - -\def\systemtopskipfactor {\topskipfactor} -\def\systemmaxdepthfactor {\maxdepthfactor} +\mutable\def\systemtopskipfactor {\topskipfactor} +\mutable\def\systemmaxdepthfactor{\maxdepthfactor} \ifdefined\globalbodyfontsize \else \newdimen\globalbodyfontsize @@ -768,7 +766,7 @@ {\ifgridsnapping \let\spacingfactor\plusone \else - \edef\spacingfactor{#1}% + \permanent\edef\spacingfactor{#1}% \fi \edef\systemtopskipfactor {\thewithoutunit\dimexpr#1\dimexpr\topskipfactor \points}% \edef\systemmaxdepthfactor{\thewithoutunit\dimexpr#1\dimexpr\maxdepthfactor\points}% @@ -927,8 +925,8 @@ \else \struttotal\dimexpr\strutht+\strutdp\relax \fi - \edef\strutheight{\the\strutht}% - \edef\strutdepth {\the\strutdp}% + \strutheight\strutht + \strutdepth \strutdp \ifdim\strutwidth=\zeropoint \spac_struts_set_hide \else @@ -1103,7 +1101,7 @@ \settestcrlf} \permanent\protected\def\setteststrut - {\def\strutwidth{.8pt}% + {\strutwidth.8\onepoint \setstrut} \permanent\protected\def\dontshowstruts @@ -1111,10 +1109,10 @@ \settestcrlf} \permanent\protected\def\unsetteststrut - {\let\strutwidth\zeropoint + {\strutwidth\zeropoint \setstrut} -\def\autostrutfactor{1.1} +\mutable\def\autostrutfactor{1.1} \permanent\protected\def\setautostrut {\begingroup @@ -1240,7 +1238,7 @@ \let\pseudoendstrut\removeunwantedspaces \permanent\protected\def\resetteststrut - {\def\strutwidth{\zeropoint}% no let + {\strutwidth\zeropoint \setstrut} \ifdefined\setfontparameters \else @@ -1260,7 +1258,7 @@ %D Handy: -\def\baselinedistance{\the\lineheight} +\permanent\def\baselinedistance{\the\lineheight} %D We need \type {\normaloffinterlineskip} because the new definition contains an %D assignment, and |<|don't ask me why|>| this assignment gives troubles in for @@ -1273,7 +1271,7 @@ \lineskip \zeropoint \lineskiplimit\maxdimen % We also need this here now; thanks to taco for figuring that out! - \def\minimumlinedistance{\zeropoint}} + \let\minimumlinedistance\zeropoint} \overloaded\permanent\protected\def\nointerlineskip {\prevdepth-\thousandpoint} @@ -1302,10 +1300,6 @@ {\aftergroup\page_otr_synchronize_page_indeed \global\enforced\let\page_otr_synchronize_page\relax} -% \protected\def\page_otr_synchronize_page_indeed -% {\clf_synchronizepage -% \glet\page_otr_synchronize_page\page_otr_synchronize_page_yes} -% % This has to become an otr method: \s!page_otr_command_synchonize_page \protected\def\page_otr_synchronize_page_indeed @@ -2445,6 +2439,6 @@ % test \par % test \par -\protected\def\ignoreparskip{\c_spac_vspacing_ignore_parskip\plusone} +\permanent\protected\def\ignoreparskip{\c_spac_vspacing_ignore_parskip\plusone} \protect \endinput diff --git a/tex/context/base/mkxl/strc-con.mklx b/tex/context/base/mkxl/strc-con.mklx index 54397ce3a..21213a330 100644 --- a/tex/context/base/mkxl/strc-con.mklx +++ b/tex/context/base/mkxl/strc-con.mklx @@ -103,9 +103,29 @@ \installcorenamespace{constructionlevel} % frozen after definition \installcorenamespace{constructionclass} % frozen after definition -\let\currentconstructionmain \empty -\let\currentconstructionlevel \empty -\let\currentconstructionhandler\empty +%aliased\let\currentconstructionhash \??construction + +\mutable\let\currentconstructionmain \empty +\mutable\let\currentconstructionlevel \empty +\mutable\let\currentconstructionhandler \empty + +\mutable\let\currentconstructionattribute \empty +\mutable\let\currentconstructionbookmark \empty +\mutable\let\currentconstructioncatcodes \empty +\mutable\let\currentconstructioncoding \empty +\mutable\let\currentconstructionexpansion \empty +\mutable\let\currentconstructionincrementnumber\empty +\mutable\let\currentconstructionlabel \empty +\mutable\let\currentconstructionlist \empty +\mutable\let\currentconstructionlistentry \empty +\mutable\let\currentconstructionlistnumber \empty +\mutable\let\currentconstructionmarking \empty +\mutable\let\currentconstructionnumber \empty +\mutable\let\currentconstructionreference \empty +\mutable\let\currentconstructionreferenceprefix\empty +\mutable\let\currentconstructionsynchronize \empty +\mutable\let\currentconstructiontitle \empty +\mutable\let\currentconstructionxmlsetup \empty \settrue\c_strc_constructions_define_commands % use with care, might become a proper key @@ -308,8 +328,6 @@ % we also need to make sure that no stretch creeps in (new per 2015-02-02, for Alan) \settrue\c_strc_constructions_distance_none} -\overloaded\let\currentconstructionhash\??construction - \protected\setvalue{\??constructionstarthandler\v!construction}% this will be redone (reorganized) .. too much boxing {\dostarttaggedchained\t!construction\currentconstruction\currentconstructionhash % \dotagsetconstruction diff --git a/tex/context/base/mkxl/strc-doc.mkxl b/tex/context/base/mkxl/strc-doc.mkxl index 046f0b086..50b71d9d2 100644 --- a/tex/context/base/mkxl/strc-doc.mkxl +++ b/tex/context/base/mkxl/strc-doc.mkxl @@ -19,6 +19,46 @@ %D This will move: +\mutable\let\currentstructureattribute \empty +\mutable\let\currentstructurebackreference \empty +\mutable\let\currentstructurebookmark \empty +\mutable\let\currentstructurecatcodes \empty +\mutable\let\currentstructurecoding \empty +\mutable\let\currentstructurecoupling \empty +\mutable\let\currentstructureexpansion \empty +\mutable\let\currentstructureincrementnumber \empty +\mutable\let\currentstructurelabel \empty +\mutable\let\currentstructurelevel \empty +\mutable\let\currentstructurelist \empty +\mutable\let\currentstructurelistattribute \empty +\mutable\let\currentstructuremarking \empty +\mutable\let\currentstructurename \empty +\mutable\let\currentstructureownnumber \empty +\mutable\let\currentstructureplaceholder \empty +\mutable\let\currentstructurereference \empty +\mutable\let\currentstructurereferenceattribute \empty +\mutable\let\currentstructurereferenceprefix \empty +\mutable\let\currentstructuresaveinlist \empty +\mutable\let\currentstructureshownumber \empty +\mutable\let\currentstructuretitle \empty +\mutable\let\currentstructurexmlsetup \empty + +\mutable\let\currentstructurecomponentattribute \empty +\mutable\let\currentstructurecomponentbookmark \empty +\mutable\let\currentstructurecomponentcatcodes \empty +\mutable\let\currentstructurecomponentcoding \empty +\mutable\let\currentstructurecomponentexpansion \empty +\mutable\let\currentstructurecomponentlabel \empty +\mutable\let\currentstructurecomponentlevel \empty +\mutable\let\currentstructurecomponentlist \empty +\mutable\let\currentstructurecomponentmarking \empty +\mutable\let\currentstructurecomponentname \empty +\mutable\let\currentstructurecomponentreference \empty +\mutable\let\currentstructurecomponentreferenceprefix\empty +\mutable\let\currentstructurecomponentsynchronize \empty +\mutable\let\currentstructurecomponenttitle \empty +\mutable\let\currentstructurecomponentxmlsetup \empty + \permanent\protected\def\setstructuresynchronization#1% todo: use ctxcontext {\clf_setinternalreference prefix {\currentstructurereferenceprefix}% diff --git a/tex/context/base/mkxl/strc-flt.mklx b/tex/context/base/mkxl/strc-flt.mklx index 500219f56..31622a336 100644 --- a/tex/context/base/mkxl/strc-flt.mklx +++ b/tex/context/base/mkxl/strc-flt.mklx @@ -187,6 +187,12 @@ \d_page_floats_compress_distance\floatparameter\c!compressdistance\relax \to \everysetupfloat +\mutable\let\currentfloatattribute \empty +\mutable\let\currentfloatcounter \empty +\mutable\let\currentfloatgroup \empty +\mutable\let\currentfloatnumber \empty +\mutable\let\currentfloatsynchronize\empty + %D We need to do it again here: \setupfloat @@ -1030,8 +1036,6 @@ % todo: optional user pars -\let\currentfloatattribute\empty % to be checked - \def\floatcaptionattribute {\iflocation \ifempty\currentfloatattribute @@ -1231,7 +1235,7 @@ \setvalue{\??floatmovement+2*\v!line}{\strc_floats_move_down_line{2}} \setvalue{\??floatmovement 2*\v!line}{\strc_floats_move_down_line{2}} -\protected\def\installfloatmovement#1#2{\setvalue{\??floatmovement#1}{#2}} +\permanent\protected\def\installfloatmovement#1#2{\setvalue{\??floatmovement#1}{#2}} \def\strc_floats_move_down#setting% {\begincsname\??floatmovement#setting\endcsname} diff --git a/tex/context/base/mkxl/strc-itm.mklx b/tex/context/base/mkxl/strc-itm.mklx index df6272310..e2f2244a5 100644 --- a/tex/context/base/mkxl/strc-itm.mklx +++ b/tex/context/base/mkxl/strc-itm.mklx @@ -228,15 +228,15 @@ \let \m_strc_itemgroups_indenting \empty \let \m_strc_itemgroups_destination \empty -\let \currentitemlevel \!!zerocount % public -\def \currentnofitems {\the\c_strc_itemgroups_max_items} -\def \currentitemnumber {\strc_counters_raw_sub\v_strc_itemgroups_counter\currentitemlevel} % public +\mutable\let \currentitemlevel \!!zerocount % public +\mutable\def \currentnofitems {\the\c_strc_itemgroups_max_items} +\mutable\def \currentitemnumber {\strc_counters_raw_sub\v_strc_itemgroups_counter\currentitemlevel} % public \newtoks \itemgroupcommands % maybe public -\def \currentitemgroupsymbol {n} % here we cannot use a _ in the name -\let \currentitemgroupconversionset \empty % here we cannot use a _ in the name -\let \currentitemgroupsegments \empty +\mutable\def \currentitemgroupsymbol {n} % here we cannot use a _ in the name +\mutable\let \currentitemgroupconversionset \empty % here we cannot use a _ in the name +\mutable\let \currentitemgroupsegments \empty \def\strc_itemgroups_register_status {\clf_registeritemgroup{\currentparentitemgroup}\c_strc_itemgroups_nesting\c_strc_itemgroups_n_of_items\dimexpr\itemgroupparameter\c!maxwidth\relax} diff --git a/tex/context/base/mkxl/strc-mat.mkxl b/tex/context/base/mkxl/strc-mat.mkxl index 8ebd79a73..991c3202e 100644 --- a/tex/context/base/mkxl/strc-mat.mkxl +++ b/tex/context/base/mkxl/strc-mat.mkxl @@ -315,15 +315,15 @@ \glet#1\relax \fi\fi} -\let\currentplaceformulaattribute\relax -\let\currentformulaattribute \relax -\let\currentsubformulaattribute \relax -\let\currentformulasattribute \relax +\mutable\let\currentplaceformulaattribute\relax +\mutable\let\currentformulaattribute \relax +\mutable\let\currentsubformulaattribute \relax +\mutable\let\currentformulasattribute \relax -\let\currentplaceformulanumber\relax -\let\currentformulanumber \relax -\let\currentsubformulanumber \relax -\let\currentformulasnumber \relax +\mutable\let\currentplaceformulanumber\relax +\mutable\let\currentformulanumber \relax +\mutable\let\currentsubformulanumber \relax +\mutable\let\currentformulasnumber \relax \mutable\let\currentformulasreference \empty \mutable\let\currentformulareference \empty @@ -349,10 +349,10 @@ \glet\currentnestedformulasuffix\empty \to \everyresetformulas -\let\currentplaceformulasynchronize\relax -\let\currentformulasynchronize \relax -\let\currentsubformulasynchronize \relax -\let\currentformulassynchronize \relax +\mutable\let\currentplaceformulasynchronize\relax +\mutable\let\currentformulasynchronize \relax +\mutable\let\currentsubformulasynchronize \relax +\mutable\let\currentformulassynchronize \relax \appendtoks \glet\currentplaceformulasynchronize \relax @@ -361,6 +361,11 @@ \glet\currentnestedformulasynchronize\relax \to \everyresetformulas +\mutable\let\currentsubformulasattribute \empty +\mutable\let\currentsubformulasnumber \empty +\mutable\let\currentsubformulasreference \empty +\mutable\let\currentsubformulassynchronize\empty + % currently we do the number, some day we will do the (sub) formula \def\strc_formulas_handle_current_references diff --git a/tex/context/base/mkxl/strc-ref.mklx b/tex/context/base/mkxl/strc-ref.mklx index 45f0ff713..10100fa03 100644 --- a/tex/context/base/mkxl/strc-ref.mklx +++ b/tex/context/base/mkxl/strc-ref.mklx @@ -29,7 +29,7 @@ \registerctxluafile{strc-rsc}{} \registerctxluafile{strc-ref}{} -\registerctxluafile{node-ref}{optimize} +\registerctxluafile{node-ref}{autosuffix,optimize} \unprotect @@ -58,12 +58,32 @@ %D page number in an unnumbered document). By setting the \type{interaction} %D variable, one can influences the way interactive references are set. -\let\referenceprefix\empty - \installcorenamespace{referencing} \installdirectcommandhandler \??referencing {referencing} % \??referencing +\mutable\let\referenceprefix \empty + +\mutable\let\currentreferenceattribute \empty +\mutable\let\currentreferencecoding \empty +\mutable\let\currentreferencecontent \empty +\mutable\let\currentreferencedata \empty +\mutable\let\currentreferenceexpansion \empty +\mutable\let\currentreferenceformatautocase\empty +\mutable\let\currentreferenceformatlabel \empty +\mutable\let\currentreferenceformatsetups \empty +\mutable\let\currentreferenceformattype \empty +\mutable\let\currentreferencekind \empty +\mutable\let\currentreferencelabels \empty +\mutable\let\currentreferencenumber \empty +\mutable\let\currentreferenceorder \empty +\mutable\let\currentreferencepage \empty +\mutable\let\currentreferencerealpage \empty +\mutable\let\currentreferencetext \empty +\mutable\let\currentreferencetitle \empty +\mutable\let\currentreferenceuserdata \empty + + \newif\ifreferencing \referencingtrue \appendtoks diff --git a/tex/context/base/mkxl/strc-reg.mkxl b/tex/context/base/mkxl/strc-reg.mkxl index f44819bc1..38ecae4a7 100644 --- a/tex/context/base/mkxl/strc-reg.mkxl +++ b/tex/context/base/mkxl/strc-reg.mkxl @@ -122,6 +122,30 @@ %D test \index{test+one} test \index{test+two} more \index{more} %D \stoptyping +\mutable\let\currentregistercharacter \empty +\mutable\let\currentregistercoding \empty +\mutable\let\currentregisterentries \empty +\mutable\let\currentregisterentriesa \empty +\mutable\let\currentregisterentriesb \empty +\mutable\let\currentregisterentriesc \empty +\mutable\let\currentregisterexpansion \empty +\mutable\let\currentregisterkeys \empty +\mutable\let\currentregisterkeysa \empty +\mutable\let\currentregisterkeysb \empty +\mutable\let\currentregisterkeysc \empty +\mutable\let\currentregisterlabel \empty +\mutable\let\currentregistermaxwidth \empty +\mutable\let\currentregistername \empty +\mutable\let\currentregisternumber \empty +\mutable\let\currentregisterownnumber \empty +\mutable\let\currentregisterpageindex \empty +\mutable\let\currentregisterpagesymbol \empty +\mutable\let\currentregistersectionindex\empty +\mutable\let\currentregisterseeindex \empty +\mutable\let\currentregisterseeword \empty +\mutable\let\currentregistersynchronize \empty +\mutable\let\currentregisterxmlsetup \empty + \newconditional\c_strc_registers_defining \setnewconstant\c_strc_registers_maxlevel \plusfive diff --git a/tex/context/base/mkxl/strc-sec.mkxl b/tex/context/base/mkxl/strc-sec.mkxl index 58f942b5f..9025b9930 100644 --- a/tex/context/base/mkxl/strc-sec.mkxl +++ b/tex/context/base/mkxl/strc-sec.mkxl @@ -99,6 +99,16 @@ \permanent\def\namedstructureheadlocation#1% expandable, maybe [#1] {\csname\??savedinternalreference\ifcsname\??savedinternalreference#1\endcsname#1\else\s!default\fi\endcsname} +\mutable\let\currentheadbackreference \empty +\mutable\let\currentheaddefault \empty +\mutable\let\currentheadincrement \empty +\mutable\let\currentheadinteraction \empty +\mutable\let\currentheadlabeltag \empty +\mutable\let\currentheadnumber \!!zerocount +\mutable\let\currentheadrenderingalternative\empty +\mutable\let\currentheadrenderingsetup \empty +\mutable\let\currentheadtext \empty + % The next directive only makes sense when we have sort of garanteed outcome (math is not so % nice for instance). % @@ -790,8 +800,8 @@ {\strc_sectioning_delayed_flush \normalexpanded{\setmarking[\currenthead]{li::\currentstructurelistnumber}}} -\let\deepstructurenumbercommand\relax -\let\deepstructuretitlecommand \relax +\mutable\let\deepstructurenumbercommand\relax +\mutable\let\deepstructuretitlecommand \relax \permanent\protected\def\fullheadnumber {\edef\currentheadlabeltag{\currentsectionblock\c!label}% @@ -814,11 +824,11 @@ \fi \dostoptagged} -\let\currenthead \empty -\let\currentheadcoupling\empty -\let\currentheadsection \empty -\let\currentheadlevel \!!zerocount -\let\currentheadcounter \!!zerocount +\mutable\let\currenthead \empty +\mutable\let\currentheadcoupling\empty +\mutable\let\currentheadsection \empty +\mutable\let\currentheadlevel \!!zerocount +\mutable\let\currentheadcounter \!!zerocount \let\strc_show_used\relax @@ -1182,7 +1192,7 @@ %permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\currenthead+\minusone\relax} \permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\previoushead\relax} -\let\previoushead\empty +\mutable\let\previoushead\empty \def\strc_sectioning_handle_page_nop {\edef\p_continue{\headparameter\c!continue}% @@ -1259,8 +1269,6 @@ \permanent\tolerant\protected\def\setupheadnumber[#1]#*[#2]% todo: reset if at other level {\setstructurenumber{\thenamedheadlevel{#1}}{\number#2}} -\def\currentheadnumber{0} % ==> \currentheadnumber - \permanent\protected\def\determineheadnumber[#1]% {\xdef\currentheadnumber{\getstructurenumber{\thenamedheadlevel{#1}}}} diff --git a/tex/context/base/mkxl/supp-box.mkxl b/tex/context/base/mkxl/supp-box.mkxl index 721667822..ac39b396a 100644 --- a/tex/context/base/mkxl/supp-box.mkxl +++ b/tex/context/base/mkxl/supp-box.mkxl @@ -814,7 +814,7 @@ \newevery \everyshapebox \relax -\def\shapesignal{.12345678pt} % or 12345sp +\permanent\dimensiondef\shapesignal.12345678pt % or 12345sp \permanent\protected\def\reshapebox#1% {\doreshapebox diff --git a/tex/context/base/mkxl/syst-aux.mkxl b/tex/context/base/mkxl/syst-aux.mkxl index 064416275..057aa5e98 100644 --- a/tex/context/base/mkxl/syst-aux.mkxl +++ b/tex/context/base/mkxl/syst-aux.mkxl @@ -2829,7 +2829,7 @@ %D %D A fully expandable message: -\let\immediatemessage\clf_immediatemessage % {} mandate / todo permanent at lua end +\aliased\let\immediatemessage\clf_immediatemessage % {} mandate / todo permanent at lua end %D \macros %D {rawgetparameters} @@ -5737,10 +5737,10 @@ \permanent\protected\def\settrialtypesetting {\the\everysettrialtypesetting } % obeys grouping so \permanent\protected\def\resettrialtypesetting{\the\everyresettrialtypesetting} % this one is seldom needed -\let\iftrialtypesetting\iffalse % so we have no \trialtypesettingtrue|false in mkiv ! +\aliased\let\iftrialtypesetting\iffalse % so we have no \trialtypesettingtrue|false in mkiv ! -\appendtoks \let\iftrialtypesetting\iftrue \to \everysettrialtypesetting -\appendtoks \let\iftrialtypesetting\iffalse \to \everyresettrialtypesetting +\appendtoks \enforced\aliased\let\iftrialtypesetting\iftrue \to \everysettrialtypesetting +\appendtoks \enforced\aliased\let\iftrialtypesetting\iffalse \to \everyresettrialtypesetting %D \macros %D {twodigitrounding} diff --git a/tex/context/base/mkxl/syst-ini.mkxl b/tex/context/base/mkxl/syst-ini.mkxl index 0f507d978..bdae879fa 100644 --- a/tex/context/base/mkxl/syst-ini.mkxl +++ b/tex/context/base/mkxl/syst-ini.mkxl @@ -626,7 +626,7 @@ \newif\ifscratchconditionone \newif\ifscratchconditiontwo -\let\htdp\boxtotal +\aliased\let\htdp\boxtotal %D A few shortcuts: @@ -723,12 +723,14 @@ \tracingstats\plusone -%D This is only used when we load \CONTEXT: +%D This is only used when we load \CONTEXT. Nesting is not supported here. \permanent\def\pushoverloadmode - {\edef\popoverloadmode{\overloadmode\the\overloadmode}% + {\enforced\permanent\protected\edef\popoverloadmode{\overloadmode\the\overloadmode\enforced\let\popoverloadmode\relax}% \overloadmode\zerocount} +\aliased\let\popoverloadmode\relax + \newtoks\everydump \pushoverloadmode diff --git a/tex/context/base/mkxl/tabl-ntb.mkxl b/tex/context/base/mkxl/tabl-ntb.mkxl index 67288c83e..aa29237b5 100644 --- a/tex/context/base/mkxl/tabl-ntb.mkxl +++ b/tex/context/base/mkxl/tabl-ntb.mkxl @@ -1679,7 +1679,7 @@ \newbox\TABLEsplitbox % public, don't change -\let\extratblsplitheight\zeropoint % additional space taken by before/afterTABLEsplitbox +\mutable\let\extratblsplitheight\zeropoint % additional space taken by before/afterTABLEsplitbox \def\tabl_ntb_split_box {\resettsplit @@ -1707,13 +1707,13 @@ % ! ! ! ! TODO: naast \postprocessTABLEsplitbox ook evt \postprocessTABLEbox voor niet split -\let\postprocessTABLEsplitbox\gobbleoneargument -\let\postprocessTABLEbox \gobbleoneargument +\mutable\let\postprocessTABLEsplitbox\gobbleoneargument % maybe just a parameter +\mutable\let\postprocessTABLEbox \gobbleoneargument % maybe just a parameter -\let\beforeTABLEsplitbox\relax -\let\afterTABLEsplitbox \relax -\let\beforeTABLEbox \relax -\let\afterTABLEbox \relax +\mutable\let\beforeTABLEsplitbox\relax % maybe just a parameter +\mutable\let\afterTABLEsplitbox \relax % maybe just a parameter +\mutable\let\beforeTABLEbox \relax % maybe just a parameter +\mutable\let\afterTABLEbox \relax % maybe just a parameter \def\tabl_ntb_check_widths_one{\tabl_ntb_check_widths_indeed\zerocount} % 0 = trial run \def\tabl_ntb_check_widths_two{\tabl_ntb_check_widths_indeed\plusone } % 1 = real run diff --git a/tex/context/base/mkxl/tabl-tbl.mkxl b/tex/context/base/mkxl/tabl-tbl.mkxl index 75c47df50..cacaef12c 100644 --- a/tex/context/base/mkxl/tabl-tbl.mkxl +++ b/tex/context/base/mkxl/tabl-tbl.mkxl @@ -232,9 +232,9 @@ \newtoks \everytabulate % public ? \protected\def\tolerantTABLEbreaktrue {\settrue \c_tabl_tabulate_tolerant_break} % used in styles ! -\protected\def\handletabulatepbreakfalse{\setfalse\c_tabl_tabulate_handlepbreak } % depricated +%protected\def\handletabulatepbreakfalse{\setfalse\c_tabl_tabulate_handlepbreak } % depricated -\def\noftabulaterows{\number\c_tabl_tabulate_noflines} % handy for testing if a table is empty +\permanent\def\noftabulaterows{\number\c_tabl_tabulate_noflines} % handy for testing if a table is empty \installcorenamespace{tabulatebox} \installcorenamespace{tabulatesetup} @@ -769,7 +769,7 @@ {\global\d_tabl_tabulate_vrulethickness#1\d_tabl_tabulate_vrulethickness_default} {\xdef\m_tabl_tabulate_vrule_color{#1}}} -\def\tabl_tabulate_set_entry#1#2% rulespec template +\permanent\protected\def\tabl_tabulate_set_entry#1#2% rulespec template {\c_tabl_tabulate_align\v_tabl_tabulate_align \c_tabl_tabulate_modus\zerocount \setfalse\c_tabl_tabulate_pwidth_set @@ -807,7 +807,7 @@ \tabl_tabulate_set_width_simple \fi} -\def\tabl_tabulate_set_last_entry#1% rulespec +\permanent\protected\def\tabl_tabulate_set_last_entry#1% rulespec {\glet\m_tabl_tabulate_color\empty \glet\m_tabl_tabulate_vrule_color\empty \edef\currenttabulationtrulespec{#1}% @@ -822,8 +822,8 @@ \tabl_tabulate_check_local_vrule_color\constantemptyargument\m_tabl_tabulate_vrule_color \tabl_tabulate_column_vrule_inject}} -\let\settabulateentry \tabl_tabulate_set_entry % used at the lua end -\let\settabulatelastentry\tabl_tabulate_set_last_entry % used at the lua end +\aliased\let\settabulateentry \tabl_tabulate_set_entry % used at the lua end +\aliased\let\settabulatelastentry\tabl_tabulate_set_last_entry % used at the lua end \def\tabl_tabulate_normalize_splitline {\ifcase\c_tabl_tabulate_splitlinemode diff --git a/tex/context/base/mkxl/tabl-tsp.mkxl b/tex/context/base/mkxl/tabl-tsp.mkxl index f09a5d9d8..561ed73cb 100644 --- a/tex/context/base/mkxl/tabl-tsp.mkxl +++ b/tex/context/base/mkxl/tabl-tsp.mkxl @@ -253,9 +253,9 @@ \resettsplit -\def\tsplitdirectwidth{\hsize} +\mutable\def\tsplitdirectwidth{\hsize} -\protected\def\handletsplit +\permanent\protected\def\handletsplit {\page_split_float_check_caption{\wd\b_split_content}% \global\setfalse\splitfloatfirstdone \testpagesync % new, sync, but still tricky diff --git a/tex/context/base/mkxl/toks-scn.mkxl b/tex/context/base/mkxl/toks-scn.mkxl index 12abf0cb8..e8da7063d 100644 --- a/tex/context/base/mkxl/toks-scn.mkxl +++ b/tex/context/base/mkxl/toks-scn.mkxl @@ -18,9 +18,6 @@ \registerctxluafile{toks-scn}{} \registerctxluafile{cldf-scn}{} \registerctxluafile{cldf-stp}{} - -\ifcase \contextlmtxmode \else - \registerctxluafile{cldf-lmt}{} -\fi +\registerctxluafile{cldf-lmt}{} \protect \endinput diff --git a/tex/context/base/mkxl/trac-vis.lmt b/tex/context/base/mkxl/trac-vis.lmt index 7ac5964da..96f3215f7 100644 --- a/tex/context/base/mkxl/trac-vis.lmt +++ b/tex/context/base/mkxl/trac-vis.lmt @@ -936,6 +936,8 @@ local ruledglue do -- local keepskip_code = gluecodes.keepskip or gluecodes.userskip local leftskip_code = gluecodes.leftskip local rightskip_code = gluecodes.rightskip + local lefthangskip_code = gluecodes.lefthangskip + local righthangskip_code = gluecodes.righthangskip local parfillleftskip_code = gluecodes.parfillleftskip or parfillskip_code local parfillrightskip_code = gluecodes.parfillrightskip or parfillskip_code local indentskip_code = gluecodes.indentskip @@ -956,8 +958,6 @@ local ruledglue do [gluecodes.topskip] = "TS", [gluecodes.splittopskip] = "ST", [gluecodes.tabskip] = "AS", - [gluecodes.lefthangskip] = "LH", - [gluecodes.righthangskip] = "RH", [gluecodes.thinmuskip] = "MS", [gluecodes.medmuskip] = "MM", [gluecodes.thickmuskip] = "ML", @@ -972,6 +972,8 @@ local ruledglue do -- false = "HS", [leftskip_code] = "LS", [rightskip_code] = "RS", + [lefthangskip_code] = "LH", + [righthangskip_code] = "RH", [spaceskip_code] = "SP", [xspaceskip_code] = "XS", [zerospaceskip_code] = "ZS", @@ -995,6 +997,8 @@ local ruledglue do info = sometext(amount,l_glue,c_space) elseif subtype == leftskip_code or subtype == rightskip_code then info = sometext(amount,l_glue,c_skip_a) + elseif subtype == lefthangskip_code or subtype == righthangskip_code then + info = sometext(amount,l_glue,c_skip_b) elseif subtype == parfillleftskip_code or subtype == parfillrightskip_code or subtype == indentskip_code or subtype == correctionskip_code then info = sometext(amount,l_glue,c_indent) elseif subtype == userskip_code then diff --git a/tex/context/base/mkxl/typo-cap.lmt b/tex/context/base/mkxl/typo-cap.lmt new file mode 100644 index 000000000..c5c91243e --- /dev/null +++ b/tex/context/base/mkxl/typo-cap.lmt @@ -0,0 +1,420 @@ +if not modules then modules = { } end modules ['typo-cap'] = { + version = 1.001, + optimize = true, + comment = "companion to typo-cap.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- see typo-cap.lua for a word traverser variant + +local next, type, tonumber = next, type, tonumber +local format, insert = string.format, table.insert +local div, getrandom = math.div, utilities.randomizer.get + +local trace_casing = false trackers.register("typesetters.casing", function(v) trace_casing = v end) + +local report_casing = logs.reporter("typesetting","casing") + +local nodes, node = nodes, node + +local nuts = nodes.nuts + +local getnext = nuts.getnext +local getid = nuts.getid +local takeattr = nuts.takeattr +local getfont = nuts.getfont +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 copy_node = nuts.copy +local end_of_math = nuts.end_of_math +local insert_after = nuts.insert_after +local find_attribute = nuts.find_attribute + +local nextglyph = nuts.traversers.glyph + +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 fontkern_code = kerncodes.fontkern + +local enableaction = nodes.tasks.enableaction + +local newkern = nuts.pool.kern + +local fonthashes = fonts.hashes +local fontdata = fonthashes.identifiers +local fontchar = fonthashes.characters + +local currentfont = font.current + +local variables = interfaces.variables +local v_reset = variables.reset + +local texsetattribute = tex.setattribute +local unsetvalue = attributes.unsetvalue + +typesetters = typesetters or { } +local typesetters = typesetters + +typesetters.cases = typesetters.cases or { } +local cases = typesetters.cases + +cases.actions = { } +local actions = cases.actions +local a_cases = attributes.private("case") + +local extract = bit32.extract +local run = 0 -- a trick to make neighbouring ranges work +local blocked = { } + +local function set(tag,font) + if run == 0x40 then -- 2^6 + run = 1 + else + run = run + 1 + end + local a = font * 0x10000 + tag * 0x100 + run + blocked[a] = false + return a +end + +local function get(a) + return + extract(a, 8, 8), -- tag + extract(a,16,12), -- font + extract(a, 0, 8) -- run +end + +-- a previous implementation used char(0) as placeholder for the larger font, so we needed +-- to remove it before it can do further harm ... that was too tricky as we use char 0 for +-- other cases too +-- +-- we could do the whole glyph run here (till no more attributes match) but then we end up +-- with more code .. maybe i will clean this up anyway as the lastfont hack is somewhat ugly +-- ... on the other hand, we need to deal with cases like: +-- +-- \WORD {far too \Word{many \WORD{more \word{pushed} in between} useless} words} + +local uccodes = characters.uccodes +local lccodes = characters.lccodes +local categories = characters.categories + +-- true false true == mixed + +local function replacer(start,codes) + local char, fnt = isglyph(start) + local dc = codes[char] + if dc then + local ifc = fontchar[fnt] + if type(dc) == "table" then + for i=1,#dc do + if not ifc[dc[i]] then + return start, false + end + end + for i=#dc,1,-1 do + local chr = dc[i] + if i == 1 then + setchar(start,chr) + else + local g = copy_node(start) + setchar(g,chr) + insert_after(start,start,g) + end + end + elseif ifc[dc] then + setchar(start,dc) + end + end + return start +end + +local registered, n = { }, 0 + +local function register(name,f) + if type(f) == "function" then + n = n + 1 + actions[n] = f + registered[name] = n + return n + else + local n = registered[f] + registered[name] = n + return n + end +end + +cases.register = register + +local function WORD(start,attr,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) + lastfont[n] = false + return replacer(first or start,lccodes) +end + +local function Words(start,attr,lastfont,n,count,where,first) -- looks quite complex + if where == "post" then + return + end + if count == 1 and where ~= "post" then + replacer(first or start,uccodes) + return start, true + else + return start, true + end +end + +local function Word(start,attr,lastfont,n,count,where,first) + blocked[attr] = true + return Words(start,attr,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) + return start, true +end + +local function mixed(start,attr,lastfont,n,count,where,first) + if where == "post" then + return + end + local used = first or start + local char = getchar(used) + local dc = uccodes[char] + if not dc then + -- quit + elseif dc == char then + local lfa = lastfont[n] + if lfa then + setfont(used,lfa) + end + else + replacer(used,uccodes) + end + return start, true +end + +local function Capital(start,attr,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 + setfont(used,lfa) + end + end + end + local s, c = replacer(first or start,uccodes) + if once then + lastfont[n] = false -- here + end + 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) +end + +local function none(start,attr,lastfont,n,count,where,first) + return start, true +end + +local function randomized(start,attr,lastfont,n,count,where,first) + local used = first or start + local char = getchar(used) + local font = getfont(used) + local tfm = fontchar[font] + lastfont[n] = false + local kind = categories[char] + if kind == "lu" then + while true do + local n = getrandom("capital lu",0x41,0x5A) + if tfm[n] then -- this also intercepts tables + setchar(used,n) + return start + end + end + elseif kind == "ll" then + while true do + local n = getrandom("capital ll",0x61,0x7A) + if tfm[n] then -- this also intercepts tables + setchar(used,n) + return start + end + end + end + return start +end + +register(variables.WORD, WORD) -- 1 +register(variables.word, word) -- 2 +register(variables.Word, Word) -- 3 +register(variables.Words, Words) -- 4 +register(variables.capital,capital) -- 5 +register(variables.Capital,Capital) -- 6 +register(variables.none, none) -- 7 (dummy) +register(variables.random, randomized) -- 8 +register(variables.mixed, mixed) -- 9 +register(variables.camel, camel) -- 10 + +register(variables.cap, variables.capital) -- clone +register(variables.Cap, variables.Capital) -- clone + +-- This can be more clever: when we unset we can actually use the same attr ref if +-- needed. Using properties to block further usage is not faster. + +function cases.handler(head) -- not real fast but also not used on much data + local start = head + local lastfont = { } + local lastattr = nil + local count = 0 + local previd = nil + local prev = nil + while start do -- while because start can jump ahead + local id = getid(start) + if id == glyph_code then + local attr = takeattr(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 "+") + end + elseif trace_casing then + report_casing("unknown case trigger %a",n) + end + end + elseif id == disc_code then + local attr = takeattr(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 + takeattr(g,a_cases) + local h, quit = action(start,attr,lastfont,n,cnt,"replace",g) + if quit then + break + end + end + end + if pre then + local cnt = count + for g in nextglyph, pre do + cnt = cnt + 1 + takeattr(g,a_cases) + local h, quit = action(start,attr,lastfont,n,cnt,"pre",g) + if quit then + break + end + end + end + if post then + local cnt = count + for g in nextglyph, post do + cnt = cnt + 1 + takeattr(g,a_cases) + local h, quit = action(start,attr,lastfont,n,cnt,"post",g) + if quit then + break + end + end + end + end + count = count + 1 + end + elseif id == math_code then + start = end_of_math(start) + count = 0 + elseif count > 0 then + if prev_id == kern_code and getsubtype(prev) == fontkern_code then + -- still inside a word ...normally kerns are added later + else + count = 0 + end + end + if start then + prev = start + previd = id + start = getnext(start) + end + end + return head +end + +local enabled = false + +function cases.set(n,id) + if n == v_reset then + n = unsetvalue + else + n = registered[n] or tonumber(n) + if n then + if not enabled then + enableaction("processors","typesetters.cases.handler") + if trace_casing then + report_casing("enabling case handler") + end + enabled = true + end + n = set(n,id or currentfont()) + else + n = unsetvalue + end + end + texsetattribute(a_cases,n) + -- return n -- bonus +end + +-- interface + +interfaces.implement { + name = "setcharactercasing", + -- public = true, + -- protected = true, + actions = cases.set, +-- arguments = { "string" } + arguments = { "argument" } +} diff --git a/tex/context/base/mkxl/typo-cap.mkxl b/tex/context/base/mkxl/typo-cap.mkxl index 5a6b73e5e..8c0cab502 100644 --- a/tex/context/base/mkxl/typo-cap.mkxl +++ b/tex/context/base/mkxl/typo-cap.mkxl @@ -18,7 +18,7 @@ %D Maybe we need a more clever system: either command or style mode etc. so %D that we can avoid the grouped mess in a simple style switch. -\registerctxluafile{typo-cap}{optimize} +\registerctxluafile{typo-cap}{autosuffix,optimize} % \definesystemattribute[case][public] % already predefined @@ -73,13 +73,13 @@ % test \word{test TEST \TeX} test % test \Word{test TEST \TeX} test -\permanent\protected\def\setcharactercasing[#1]{\clf_setcharactercasing{#1}\fontid\font} % can be public implementor +\permanent\protected\def\setcharactercasing[#1]{\clf_setcharactercasing{#1}} % can be public implementor -\protected\def\typo_capitale_WORD {\clf_setcharactercasing{\v!WORD }\fontid\font} -\protected\def\typo_capitale_word {\clf_setcharactercasing{\v!word }\fontid\font} -\protected\def\typo_capitale_Word {\clf_setcharactercasing{\v!Word }\fontid\font} -\protected\def\typo_capitale_Words{\clf_setcharactercasing{\v!Words}\fontid\font} -\protected\def\typo_capitale_camel{\clf_setcharactercasing{\v!camel}\fontid\font} +\protected\def\typo_capitale_WORD {\clf_setcharactercasing\v!WORD } +\protected\def\typo_capitale_word {\clf_setcharactercasing\v!word } +\protected\def\typo_capitale_Word {\clf_setcharactercasing\v!Word } +\protected\def\typo_capitale_Words{\clf_setcharactercasing\v!Words} +\protected\def\typo_capitale_camel{\clf_setcharactercasing\v!camel} \pushoverloadmode @@ -157,13 +157,13 @@ \def\typo_capitals_set_fake#1% {\edef\currentcapitals{#1}% - \clf_setcharactercasing{\currentcapitals}\fontid\font + \clf_setcharactercasing\currentcapitals \usecapitalsstyleparameter\c!style} \def\typo_capitals_set_real#1% {\edef\currentcapitals{#1}% \sc - \clf_setcharactercasing{\currentcapitals}\fontid\font} + \clf_setcharactercasing\currentcapitals} \permanent\protected\def\pseudosmallcapped{\triggergroupedcommandcs\font_style_pseudosmallcapped} \permanent\protected\def\pseudoSmallcapped{\triggergroupedcommandcs\font_style_pseudoSmallcapped} diff --git a/tex/context/base/mkxl/typo-del.mkxl b/tex/context/base/mkxl/typo-del.mkxl index ab25f72d8..13f525f69 100644 --- a/tex/context/base/mkxl/typo-del.mkxl +++ b/tex/context/base/mkxl/typo-del.mkxl @@ -145,8 +145,8 @@ \newsignal\d_typo_subsentence_signal \newcount \c_typo_subsentence_nesting -\let\beforesubsentence\donothing -\let\aftersubsentence \donothing +\mutable\let\beforesubsentence\donothing % maybe just a parameter +\mutable\let\aftersubsentence \donothing % maybe just a parameter % todo: make this language option % diff --git a/tex/context/base/mkxl/typo-mar.mkxl b/tex/context/base/mkxl/typo-mar.mkxl index 5d6f15f21..1fd904cc3 100644 --- a/tex/context/base/mkxl/typo-mar.mkxl +++ b/tex/context/base/mkxl/typo-mar.mkxl @@ -142,6 +142,11 @@ \newconditional\inhibitmargindata % This one is used at the Lua end! \newtoks \everymargindatacontent % Later on we will set this one. +\mutable\let\currentmargindatastrut \empty +\mutable\let\currentmargindatawidth \empty +\mutable\let\currentmarginfirstheight\empty +\mutable\let\currentmarginreference \empty + \appendtoks \settrue\inhibitmargindata \to \everyforgetall diff --git a/tex/context/modules/mkiv/m-scite.mkiv b/tex/context/modules/mkiv/m-scite.mkiv index 7116a5b32..659d5f58d 100644 --- a/tex/context/modules/mkiv/m-scite.mkiv +++ b/tex/context/modules/mkiv/m-scite.mkiv @@ -339,7 +339,7 @@ moduledata.scite = scite \unexpanded\def\buff_scite_slxb#1% {% we can have a side float \advance\hangindent\numexpr#1+2\relax\scitespaceskip - \begstrut\hskip#1\scitespaceskip + \begstrut\hskip#1\scitespaceskip\relax \ifcase\hangafter \hangafter\plusone\relax \fi} diff --git a/tex/context/modules/mkiv/s-system-macros.mkxl b/tex/context/modules/mkiv/s-system-macros.mkxl index 72fd3b7c2..6dcccd048 100644 --- a/tex/context/modules/mkiv/s-system-macros.mkxl +++ b/tex/context/modules/mkiv/s-system-macros.mkxl @@ -25,6 +25,8 @@ % \usemodule[article-basic] \setuplayout[tight] \setupbodyfont[7pt,tt] \usemodule[article-basic] \setuplayout[tight] \setupbodyfont[5pt,tt] +\setupbackgrounds[page][background=color,backgroundcolor=darkgray] \setupcolors[textcolor=white] + \setuppapersize [A4,landscape] [A4,landscape] diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index c60bc0ca6..2bb9d71cb 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 : 2020-11-26 15:38 +-- merge date : 2020-11-27 20:07 do -- begin closure to overcome local limits and interference |