diff options
Diffstat (limited to 'tex/context/base/mkiv')
271 files changed, 45308 insertions, 7886 deletions
diff --git a/tex/context/base/mkiv/anch-pgr.lua b/tex/context/base/mkiv/anch-pgr.lua index be9e28c08..239b33010 100644 --- a/tex/context/base/mkiv/anch-pgr.lua +++ b/tex/context/base/mkiv/anch-pgr.lua @@ -76,7 +76,7 @@ local getheight = nuts.getheight local getdepth = nuts.getdepth local nodecodes = nodes.nodecodes -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local start_of_par = nuts.start_of_par local insert_before = nuts.insert_before @@ -165,7 +165,7 @@ local function flush(head,f,l,a,parent,depth) ln = new_hlist(setlink(new_rule(65536,65536*4,0),new_kern(-65536),ln)) rn = new_hlist(setlink(new_rule(65536,0,65536*4),new_kern(-65536),rn)) end - if getid(f) == localpar_code and start_of_par(f) then -- we need to clean this mess + if getid(f) == par_code and start_of_par(f) then -- we need to clean this mess insert_after(head,f,ln) else head, f = insert_before(head,f,ln) diff --git a/tex/context/base/mkiv/anch-pos.lua b/tex/context/base/mkiv/anch-pos.lua index 554f3fdc0..b2ad5b8b5 100644 --- a/tex/context/base/mkiv/anch-pos.lua +++ b/tex/context/base/mkiv/anch-pos.lua @@ -50,6 +50,7 @@ local ctx_latelua = context.latelua local tex = tex local texgetcount = tex.getcount +local texgetinteger = tex.getintegervalue or tex.getcount local texsetcount = tex.setcount local texget = tex.get local texsp = tex.sp @@ -282,7 +283,7 @@ local function setall(name,p,x,y,w,h,d,extra) e = extra ~= "" and extra or nil, r = region, c = column, - r2l = texgetcount("inlinelefttoright") == 1 and true or nil, + r2l = texgetinteger("inlinelefttoright") == 1 and true or nil, } end @@ -626,7 +627,7 @@ implement { x = true, y = true, n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetcount("inlinelefttoright") == 1 or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, } tobesaved[name] = spec ctx_latelua { action = enhance, specification = spec } @@ -647,7 +648,7 @@ implement { h = h ~= 0 and h or nil, d = d ~= 0 and d or nil, n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetcount("inlinelefttoright") == 1 or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, } tobesaved[name] = spec ctx_latelua { action = enhance, specification = spec } @@ -670,7 +671,7 @@ implement { h = h ~= 0 and h or nil, d = d ~= 0 and d or nil, n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetcount("inlinelefttoright") == 1 or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, } tobesaved[name] = spec ctx_latelua { action = enhance, specification = spec } @@ -692,7 +693,7 @@ implement { d = d ~= 0 and d or nil, n = nofparagraphs > 0 and nofparagraphs or nil, e = scanstring(), - r2l = texgetcount("inlinelefttoright") == 1 or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, } tobesaved[name] = spec ctx_latelua { action = enhance, specification = spec } @@ -714,7 +715,7 @@ implement { h = h ~= 0 and h or nil, d = d ~= 0 and d or nil, n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetcount("inlinelefttoright") == 1 or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, } tobesaved[name] = spec ctx_latelua { action = enhance, specification = spec } @@ -737,7 +738,7 @@ implement { h = h ~= 0 and h or nil, d = d ~= 0 and d or nil, n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetcount("inlinelefttoright") == 1 or nil, + r2l = texgetinteger("inlinelefttoright") == 1 or nil, } tobesaved[name] = spec ctx_latelua { action = enhance, specification = spec } diff --git a/tex/context/base/mkiv/attr-col.lua b/tex/context/base/mkiv/attr-col.lua index 88358aeb7..9c542a942 100644 --- a/tex/context/base/mkiv/attr-col.lua +++ b/tex/context/base/mkiv/attr-col.lua @@ -445,7 +445,6 @@ function colors.setmodel(name,weightgray) else -- stil the same end - return default end diff --git a/tex/context/base/mkiv/attr-eff.mkxl b/tex/context/base/mkiv/attr-eff.mkxl new file mode 100644 index 000000000..04a0c55ce --- /dev/null +++ b/tex/context/base/mkiv/attr-eff.mkxl @@ -0,0 +1,60 @@ +%D \module +%D [ file=attr-eff, +%D version=2007.06.06, +%D title=\CONTEXT\ Attribute Macros, +%D subtitle=Effects, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Attribute Macros / Effects} + +\registerctxluafile{attr-eff}{} + +\unprotect + +\installcorenamespace{effect} + +\installcommandhandler \??effect {effect} \??effect + +\setupeffect + [\c!method=\v!none, + \c!stretch=\zerocount, + \c!rulethickness=\zeropoint, + \c!alternative=\v!normal] + +\appendtoks + \edef\p_method{\effectparameter\c!method}% + \ifx\p_method\v!command + \setuxvalue{\e!start\currenteffect}{\starteffect[#1]}% + \setuxvalue{\e!stop \currenteffect}{\stopeffect}% + \fi +\to \everydefineeffect + +\permanent\protected\def\starteffect[#1]% + {\clf_seteffect + alternative {\namedeffectparameter{#1}\c!alternative} + stretch \numexpr\namedeffectparameter{#1}\c!stretch\relax + rulethickness \dimexpr\namedeffectparameter{#1}\c!rulethickness\relax + \relax} + +\permanent\protected\def\stopeffect % can be special + {\clf_reseteffect} % v!normal 0 0 + +\permanent\protected\def\effect[#1]% + {\groupedcommand{\starteffect[#1]}{\stopeffect}} + +% yes or no grouped + +\defineeffect [\v!inner] [\c!alternative=\v!inner,\c!rulethickness=.25pt] +\defineeffect [\v!outer] [\c!alternative=\v!outer,\c!rulethickness=.25pt] +\defineeffect [\v!both] [\c!alternative=\v!both, \c!rulethickness=.25pt] +\defineeffect [\v!normal] [\c!alternative=\v!normal] +\defineeffect [\v!hidden] [\c!alternative=\v!hidden] +\defineeffect [\v!stretch] [\c!alternative=\v!stretch,\c!stretch=1] + +\protect \endinput diff --git a/tex/context/base/mkiv/attr-ini.mkxl b/tex/context/base/mkiv/attr-ini.mkxl new file mode 100644 index 000000000..d36ad1d0e --- /dev/null +++ b/tex/context/base/mkiv/attr-ini.mkxl @@ -0,0 +1,143 @@ +%D \module +%D [ file=attr-ini, +%D version=2007.06.06, +%D title=\CONTEXT\ Attribute Macros, +%D subtitle=Initialization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Attribute Macros / Initialization} + +%D Although it's still somewhat experimental, here we introduce code +%D related to attributes. Housekeeping will move completely to \LUA\ +%D and \type {\newattribute} will go away. + +\unprotect + +\registerctxluafile{attr-ini}{} + +\installcorenamespace{attributecount} % the counter representing the attribute (attrdef'd) +\installcorenamespace{attributeid} % the internal number +\installcorenamespace{attributestack} % the attribute specific stack +\installcorenamespace{attributepickup} + +\permanent\protected\def\pushattribute#1% + {\global\advance\csname\??attributestack\string#1\endcsname\plusone + \expandafter\xdef\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname{\number\attribute#1}} + +\permanent\protected\def\popattribute#1% + {\attribute#1\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname\relax + \global\advance\csname\??attributestack\string#1\endcsname\minusone} + +\permanent\protected\def\installattributestack#1% + {\ifcsname\??attributestack\string#1\endcsname \else + \expandafter\newcount\csname\??attributestack\string#1\endcsname + \fi} + +\newtoks \t_attr_list_global +\newtoks \t_attr_list_local +\newtoks \t_attr_list_pickup +\newtoks \t_attr_list_nomath + +\ifdefined \s!global \else \immutable\def\s!global {global} \fi % for metatex % or hard check later +\ifdefined \s!public \else \immutable\def\s!public {public} \fi % for metatex % or hard check later +\ifdefined \s!private \else \immutable\def\s!private {private} \fi % for metatex % or hard check later +\ifdefined \s!attribute \else \immutable\def\s!attribute{attribute} \fi % for metatex % or hard check later +\ifdefined \s!pickup \else \immutable\def\s!pickup {pickup} \fi % for metatex % or hard check later +\ifdefined \s!forget \else \immutable\def\s!forget {forget} \fi % for metatex % or hard check later + +\immutable\def\??attributeprefix{c_attr_} + +\permanent\protected\def\defineattribute {\attr_basics_define_indeed[\s!public ]} +\permanent\protected\def\definesystemattribute{\attr_basics_define_indeed[\s!private]} + +\tolerant\def\attr_basics_define_indeed[#1]#*[#2]#*[#3]% + {\ifcsname\??attributeprefix#2\endcsname\else + \scratchcounter\clf_defineattribute{#2}{#1}\relax + %\writestatus\m!system{defining #1 attribute #2 with number \number\scratchcounter}% + \global\expandafter\attributedef\csname\??attributeprefix#2\endcsname\scratchcounter % \foo = 123 + \global\expandafter\integerdef \csname\??attributeid #2\endcsname\scratchcounter % \attribute\foo = 123 + % some attributes are always global + \doifelseinset\s!global{#3}% + {\xtoksapp\t_attr_list_global{\csname\??attributeprefix#2\endcsname\attributeunsetvalue}}% \c_attr_foo + {\xtoksapp\t_attr_list_local {\csname\??attributeprefix#2\endcsname\attributeunsetvalue}}% + \doifinset\s!nomath{#3}% + {\xtoksapp\t_attr_list_nomath{\csname\??attributeprefix#2\endcsname\attributeunsetvalue}}% + \doifinset\s!public{#3}% + {\aliased\expandafter\glet\csname#2\s!attribute\expandafter\endcsname\csname\??attributeid#2\endcsname}% \attribute\fooattribute + \doifinset\s!pickup{#3}% + {\global\expandafter\integerdef\csname\??attributepickup#2\endcsname\attributeunsetvalue + \xtoksapp\t_attr_list_pickup{\csname\??attributeprefix#2\endcsname\csname\??attributepickup#2\endcsname}% + \ifcsname#2\s!attribute\endcsname + \expandafter\xdef\csname\s!pickup#2\s!attribute\endcsname{\expandafter\integerdef\csname\??attributepickup#2\endcsname\csname\??attributeprefix#2\endcsname}% + \expandafter\xdef\csname\s!forget#2\s!attribute\endcsname{\expandafter\integerdef\csname\??attributepickup#2\endcsname\attributeunsetvalue}% + \fi}% + \fi} + +\permanent\protected\def\pickupattributes + {\the\t_attr_list_pickup\relax} + +\permanent\protected\def\newattribute#1% + {\attr_basics_define_indeed\s!public[\csstring#1][]% + \expandafter\glet\expandafter#1\csname\??attributeid\csstring#1\endcsname} + +% expandable so we can \edef them for speed + +\permanent\def\dosetattribute#1#2{\csname\??attributeprefix#1\endcsname#2\relax} +\permanent\def\doresetattribute#1{\csname\??attributeprefix#1\endcsname\attributeunsetvalue} +\permanent\def\dogetattribute #1{\number\csname\??attributeprefix#1\endcsname} +\permanent\def\dogetattributeid#1{\number\csname\??attributeid #1\endcsname} + +\aliased\let\dompattribute\gobbletwoarguments + +\permanent\protected\def\resetglobalattributes{\the\t_attr_list_global\glyphdatafield\zerocount\glyphscriptfield\zerocount} +\permanent\protected\def\resetlocalattributes {\the\t_attr_list_local \glyphdatafield\zerocount\glyphscriptfield\zerocount} + +\aliased\let\resetallattributes\resetlocalattributes + +%D Rather special. + +\permanent\protected\def\savecurrentattributes #1{\clf_savecurrentattributes {#1}} +\permanent\protected\def\restorecurrentattributes#1{\clf_restorecurrentattributes{#1}} + +%D For the moment we put this here. The order of definition matters a bit because +%D performance is better when we put frequently accessed attributes at the front. +%D So, we might move more here. + +%definesystemattribute [state] % nomath +\definesystemattribute [color] [public] % global +\definesystemattribute [colormodel] [public,global] +%definesystemattribute [skip] +%definesystemattribute [penalty] +\definesystemattribute [transparency] [public] +\definesystemattribute [reference] [public] +\definesystemattribute [destination] [public] +\definesystemattribute [case] [public] +\definesystemattribute [visual] [public,global] +\definesystemattribute [viewerlayer] [public] +\definesystemattribute [background] [public] +\definesystemattribute [alignbackground] [public] +\definesystemattribute [colorintent] [public] +\definesystemattribute [negative] [public] +\definesystemattribute [effect] [public] +\definesystemattribute [layoutcomponent] [public] +\definesystemattribute [internal] [public] +\definesystemattribute [ruled] [public] +\definesystemattribute [shifted] [public] +\definesystemattribute [checkedbreak] [public] +\definesystemattribute [vboxtohboxseparator] [public] + +\permanent\protected\let\showattributes\clf_showattributes % maybe at lua end + +%D Todo: + +% \appendtoks +% \clf_cleanupattributes +% \to \everyafterpagebreak + +\protect \endinput diff --git a/tex/context/base/mkiv/back-exp.lua b/tex/context/base/mkiv/back-exp.lua index f247e4e27..314d66eeb 100644 --- a/tex/context/base/mkiv/back-exp.lua +++ b/tex/context/base/mkiv/back-exp.lua @@ -2984,7 +2984,7 @@ local collectresults do -- too many locals otherwise local kern_code = nodecodes.kern local disc_code = nodecodes.disc local whatsit_code = nodecodes.whatsit - local localpar_code = nodecodes.localpar + local par_code = nodecodes.par local userskip_code = gluecodes.userskip local rightskip_code = gluecodes.rightskip @@ -3059,7 +3059,7 @@ local collectresults do -- too many locals otherwise local function collectresults(head,list,pat,pap) -- is last used (we also have currentattribute) local p - local localparagraph + local paragraph local maybewrong local pid for n, id, subtype in nextnode, head do @@ -3077,7 +3077,7 @@ local collectresults do -- too many locals otherwise if last ~= at then local tl = taglist[at] local ap = getattr(n,a_taggedpar) or pap - if localparagraph and (not ap or ap < localparagraph) then + if paragraph and (not ap or ap < paragraph) then maybewrong = addtomaybe(maybewrong,c,1) end pushcontent() @@ -3113,7 +3113,7 @@ local collectresults do -- too many locals otherwise currentattribute = last currentparagraph = ap end - if localparagraph and (not ap or ap < localparagraph) then + if paragraph and (not ap or ap < paragraph) then maybewrong = addtomaybe(maybewrong,c,2) end if trace_export then @@ -3390,8 +3390,8 @@ end last = nil currentparagraph = nil end - elseif not localparagraph and id == localpar_code and start_of_par(n) then - localparagraph = getattr(n,a_taggedpar) + elseif not paragraph and id == par_code and start_of_par(n) then + paragraph = getattr(n,a_taggedpar) elseif id == disc_code then -- very unlikely because we stripped them local pre, post, replace = getdisc(n) diff --git a/tex/context/base/mkiv/back-exp.mkiv b/tex/context/base/mkiv/back-exp.mkiv index 05e404697..23ffdbda0 100644 --- a/tex/context/base/mkiv/back-exp.mkiv +++ b/tex/context/base/mkiv/back-exp.mkiv @@ -235,10 +235,10 @@ \to \everyenableelements \appendtoks - \let\specialfixedspace \explicitfixedspace - \let\specialobeyedspace \explicitobeyedspace - \let\specialstretchedspace\explicitstretchedspace - \let\specialcontrolspace \explicitcontrolspace + \enforced\let\specialfixedspace \explicitfixedspace + \enforced\let\specialobeyedspace \explicitobeyedspace + \enforced\let\specialstretchedspace\explicitstretchedspace + \enforced\let\specialcontrolspace \explicitcontrolspace \to \everyenableelements \appendtoks diff --git a/tex/context/base/mkiv/back-ini.mkxl b/tex/context/base/mkiv/back-ini.mkxl index 4e2fa351e..00bfeb188 100644 --- a/tex/context/base/mkiv/back-ini.mkxl +++ b/tex/context/base/mkiv/back-ini.mkxl @@ -75,7 +75,6 @@ %D \stoptext %D \stoptyping -\unexpanded\def\setupoutput[#1]% - {\clf_enabledriver{#1}} +\permanent\protected\def\setupoutput[#1]{\clf_enabledriver{#1}} \protect \endinput diff --git a/tex/context/base/mkiv/back-lua.mkxl b/tex/context/base/mkiv/back-lua.mkxl index 6c5aaf82c..0fb1bcc88 100644 --- a/tex/context/base/mkiv/back-lua.mkxl +++ b/tex/context/base/mkiv/back-lua.mkxl @@ -11,8 +11,6 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\ifcase\contextlmtxmode \else - \registerctxluafile{back-lua}{autosuffix,optimize} -\fi +\registerctxluafile{back-lua}{autosuffix,optimize} \endinput diff --git a/tex/context/base/mkiv/back-mps.mkxl b/tex/context/base/mkiv/back-mps.mkxl index 318b73848..d4d428d42 100644 --- a/tex/context/base/mkiv/back-mps.mkxl +++ b/tex/context/base/mkiv/back-mps.mkxl @@ -11,8 +11,6 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\ifcase\contextlmtxmode \else - \registerctxluafile{back-mps}{autosuffix,optimize} -\fi +\registerctxluafile{back-mps}{autosuffix,optimize} \endinput diff --git a/tex/context/base/mkiv/back-out.lmt b/tex/context/base/mkiv/back-out.lmt index acf004634..1f33da557 100644 --- a/tex/context/base/mkiv/back-out.lmt +++ b/tex/context/base/mkiv/back-out.lmt @@ -43,7 +43,7 @@ local pageliteral_code = literalvalues.page local directliteral_code = literalvalues.direct local rawliteral_code = literalvalues.raw -local immediate_code = tex.prefixcodes.immediate +local immediate_code = tex.flagcodes.immediate local nodeproperties = nodes.properties.data diff --git a/tex/context/base/mkiv/back-out.mkxl b/tex/context/base/mkiv/back-out.mkxl index 248622c54..9e499a843 100644 --- a/tex/context/base/mkiv/back-out.mkxl +++ b/tex/context/base/mkiv/back-out.mkxl @@ -13,11 +13,10 @@ \registerctxluafile{back-out}{autosuffix} -\let\normalimmediate\immediate -\let\normalopenout \openout -\let\normalwrite \write -\let\normalcloseout \closeout -\let\normallatelua \latelua -\let\normalspecial \special +\let\normalopenout \openout +\let\normalwrite \write +\let\normalcloseout\closeout +\let\normallatelua \latelua +\let\normalspecial \special \endinput diff --git a/tex/context/base/mkiv/back-pdf.mkxl b/tex/context/base/mkiv/back-pdf.mkxl index b2312bccd..c28352c92 100644 --- a/tex/context/base/mkiv/back-pdf.mkxl +++ b/tex/context/base/mkiv/back-pdf.mkxl @@ -56,33 +56,33 @@ %D \type {\pdfextension} and \type {\pdffeedback} primitives but it will probably %D have bad side effects. -\unexpanded\def\pdfextension{\clf_pdfextension} - \def\pdffeedback {\clf_pdffeedback} - \def\pdfvariable {\clf_pdfvariable} +\permanent\protected\def\pdfextension{\clf_pdfextension} +\permanent \def\pdffeedback {\clf_pdffeedback} +\permanent \def\pdfvariable {\clf_pdfvariable} %D For the moment we keep this for tikz but hopefully it will at some point use %D the proper ones. Consider them obsolete: -\unexpanded\def\pdfliteral {\clf_pdfliteral} -\unexpanded\def\pdfobj {\clf_pdfobj}% -\unexpanded\def\pdflastobj {\numexpr\clf_pdflastobj\relax} -\unexpanded\def\pdfrefobj {\clf_pdfrefobj} +\permanent\protected\def\pdfliteral {\clf_pdfliteral} +\permanent\protected\def\pdfobj {\clf_pdfobj}% +\permanent\protected\def\pdflastobj {\numexpr\clf_pdflastobj\relax} +\permanent\protected\def\pdfrefobj {\clf_pdfrefobj} -\unexpanded\def\pdfrestore {\pdfextension restore} -\unexpanded\def\pdfsave {\pdfextension save} -\unexpanded\def\pdfsetmatrix{\pdfextension setmatrix} +\permanent\protected\def\pdfrestore {\pdfextension restore} +\permanent\protected\def\pdfsave {\pdfextension save} +\permanent\protected\def\pdfsetmatrix{\pdfextension setmatrix} - \let\pdfxform \saveboxresource - \let\pdflastxform \lastsavedboxresourceindex - \let\pdfrefxform \useboxresource +\permanent\let\pdfxform \saveboxresource +\permanent\let\pdflastxform\lastsavedboxresourceindex +\permanent\let\pdfrefxform \useboxresource %D Here are quick and dirty compression flippers, mostly used when testing something %D as one can best stick to the defaults that also adapt to specific standards. -\unexpanded\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount} -\unexpanded\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree} -\unexpanded\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine } -\unexpanded\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree} +\permanent\protected\def\nopdfcompression {\clf_setpdfcompression\zerocount\zerocount} +\permanent\protected\def\onlypdfobjectcompression{\clf_setpdfcompression\zerocount\plusthree} +\permanent\protected\def\maximumpdfcompression {\clf_setpdfcompression\plusnine \plusnine } +\permanent\protected\def\normalpdfcompression {\clf_setpdfcompression\plusthree\plusthree} %D PDF/X (maybe combine the two lua calls) @@ -112,26 +112,26 @@ %D These are the only official methods to add stuff to the resources. If more is %D needed for third party low level code, it can be added. -\unexpanded\def\pdfbackendsetcatalog #1#2{\clf_lpdf_addtocatalog{#1}{#2}} -\unexpanded\def\pdfbackendsetinfo #1#2{\clf_lpdf_addtoinfo{#1}{#2}} -\unexpanded\def\pdfbackendsetname #1#2{\clf_lpdf_addtonames{#1}{#2}} +\permanent\protected\def\pdfbackendsetcatalog #1#2{\clf_lpdf_addtocatalog{#1}{#2}} +\permanent\protected\def\pdfbackendsetinfo #1#2{\clf_lpdf_addtoinfo{#1}{#2}} +\permanent\protected\def\pdfbackendsetname #1#2{\clf_lpdf_addtonames{#1}{#2}} -\unexpanded\def\pdfbackendsetpageattribute #1#2{\clf_lpdf_addtopageattributes{#1}{#2}} -\unexpanded\def\pdfbackendsetpagesattribute#1#2{\clf_lpdf_addtopagesattributes{#1}{#2}} -\unexpanded\def\pdfbackendsetpageresource #1#2{\clf_lpdf_addtopageresources{#1}{#2}} +\permanent\protected\def\pdfbackendsetpageattribute #1#2{\clf_lpdf_addtopageattributes{#1}{#2}} +\permanent\protected\def\pdfbackendsetpagesattribute#1#2{\clf_lpdf_addtopagesattributes{#1}{#2}} +\permanent\protected\def\pdfbackendsetpageresource #1#2{\clf_lpdf_addtopageresources{#1}{#2}} -\unexpanded\def\pdfbackendsetextgstate #1#2{\clf_lpdf_adddocumentextgstate{#1}{#2}} -\unexpanded\def\pdfbackendsetcolorspace #1#2{\clf_lpdf_adddocumentcolorspace{#1}{#2}} -\unexpanded\def\pdfbackendsetpattern #1#2{\clf_lpdf_adddocumentpattern{#1}{#2}} -\unexpanded\def\pdfbackendsetshade #1#2{\clf_lpdf_adddocumentshade{#1}{#2}} +\permanent\protected\def\pdfbackendsetextgstate #1#2{\clf_lpdf_adddocumentextgstate{#1}{#2}} +\permanent\protected\def\pdfbackendsetcolorspace #1#2{\clf_lpdf_adddocumentcolorspace{#1}{#2}} +\permanent\protected\def\pdfbackendsetpattern #1#2{\clf_lpdf_adddocumentpattern{#1}{#2}} +\permanent\protected\def\pdfbackendsetshade #1#2{\clf_lpdf_adddocumentshade{#1}{#2}} - \def\pdfbackendcurrentresources {\clf_lpdf_collectedresources} - \def\pdfcolor #1{\clf_lpdf_color\numexpr\thecolorattribute{#1}\relax} +\permanent \def\pdfbackendcurrentresources {\clf_lpdf_collectedresources} +\permanent \def\pdfcolor #1{\clf_lpdf_color\numexpr\thecolorattribute{#1}\relax} %D This is a temporary hack mthat will be removed, improved or somehow can become %D default. -\def\TransparencyHack{\setupcolors[\c!pagecolormodel=\v!auto]} +\permanent\def\TransparencyHack{\setupcolors[\c!pagecolormodel=\v!auto]} %D Just in case one needs this \unknown: %D @@ -139,7 +139,7 @@ %D text \pdfbackendactualtext{Meier}{Müller} text %D \stoptyping -\unexpanded\def\pdfbackendactualtext#1#2% not interfaced +\permanent\protected\def\pdfbackendactualtext#1#2% not interfaced {\clf_startactualtext{#2}% #1% \clf_stopactualtext} @@ -149,9 +149,9 @@ %D Bah, this is also needed for tikz: \ifdefined\pdfsavepos\else - \let\pdfsavepos \savepos - \let\pdflastxpos\lastxpos - \let\pdflastypos\lastypos + \permanent\let\pdfsavepos \savepos + \permanent\let\pdflastxpos\lastxpos + \permanent\let\pdflastypos\lastypos \fi \protect \endinput diff --git a/tex/context/base/mkiv/bibl-tra.mkiv b/tex/context/base/mkiv/bibl-tra.mkiv index 5389400f3..eebd92d68 100644 --- a/tex/context/base/mkiv/bibl-tra.mkiv +++ b/tex/context/base/mkiv/bibl-tra.mkiv @@ -815,9 +815,6 @@ \doifelse{\publicationlistparameter\c!maybeyear}{\v!off}{\def\maybeyear##1{}}{\def\maybeyear##1{##1}}% \forgetall} -\unexpanded\def\outdented#1% move to supp-box ? - {\hskip-\hangindent#1\relax} - %D The full list of publications \unexpanded\def\completepublications diff --git a/tex/context/base/mkiv/blob-ini.mkxl b/tex/context/base/mkiv/blob-ini.mkxl index 126319b12..3443836b7 100644 --- a/tex/context/base/mkiv/blob-ini.mkxl +++ b/tex/context/base/mkiv/blob-ini.mkxl @@ -28,19 +28,19 @@ % \depthofstring % defined in lua % \heightanddepthofstring % defined in lua -\def\wdofstring#1{\dimexpr\widthofstring {#1}\relax} % assured an dimen -\def\htofstring#1{\dimexpr\heightofstring{#1}\relax} % assured an dimen -\def\dpofstring#1{\dimexpr\depthofstring {#1}\relax} % assured an dimen -\def\hdofstring#1{\dimexpr\totalofstring {#1}\relax} % assured an dimen +\permanent\def\wdofstring#1{\dimexpr\widthofstring {#1}\relax} % assured an dimen +\permanent\def\htofstring#1{\dimexpr\heightofstring{#1}\relax} % assured an dimen +\permanent\def\dpofstring#1{\dimexpr\depthofstring {#1}\relax} % assured an dimen +\permanent\def\hdofstring#1{\dimexpr\totalofstring {#1}\relax} % assured an dimen -\let\heightanddepthofstring\totalofstring -\let\htdpofstring \hdofstring +\aliased\let\heightanddepthofstring\totalofstring +\aliased\let\htdpofstring \hdofstring \let\hd\htdp % if yes then move this % This one takes anything that can be typeset -\unexpanded\def\setwidthof#1\to#2{\edef#2{\widthofstring{#1}}} +\permanent\protected\def\setwidthof#1\to#2{\edef#2{\widthofstring{#1}}} \protect \endinput diff --git a/tex/context/base/mkiv/buff-par.mkvi b/tex/context/base/mkiv/buff-par.mkvi index 0ee66dd01..a2d32c6be 100644 --- a/tex/context/base/mkiv/buff-par.mkvi +++ b/tex/context/base/mkiv/buff-par.mkvi @@ -65,8 +65,8 @@ \let\buff_parallel_define_saved\defineparallel \let\buff_parallel_setup_saved \setupparallel -\unexpanded\def\defineparallel{\dodoubleargument\buff_parallel_define} -\unexpanded\def\setupparallel {\dotripleargument\buff_parallel_setup} +\unexpanded\overloaded\def\defineparallel{\dodoubleargument\buff_parallel_define} +\unexpanded\overloaded\def\setupparallel {\dotripleargument\buff_parallel_setup} \def\buff_parallel_define[#name][#instances]% {\buff_parallel_define_saved[#name][\c!list={#instances}]% list is internal diff --git a/tex/context/base/mkiv/buff-ver.mkiv b/tex/context/base/mkiv/buff-ver.mkiv index 067ae7c39..c9a5c4525 100644 --- a/tex/context/base/mkiv/buff-ver.mkiv +++ b/tex/context/base/mkiv/buff-ver.mkiv @@ -287,10 +287,10 @@ \def\buff_verbatim_type_nop {\buff_verbatim_left_of_type - \futurelet\next\buff_verbatim_type_one} + \futurelet\nexttoken\buff_verbatim_type_one} \def\buff_verbatim_type_one - {\ifx\next\bgroup + {\ifx\nexttoken\bgroup \expandafter\buff_verbatim_type_a \else \expandafter\buff_verbatim_type_two @@ -299,10 +299,10 @@ \def\buff_verbatim_type_two {\catcode`<=\othercatcode % old precaution \catcode`>=\othercatcode % old precaution - \futurelet\next\buff_verbatim_type_three} + \futurelet\nexttoken\buff_verbatim_type_three} \def\buff_verbatim_type_three - {\if\next<% + {\if\nexttoken<% \expandafter\buff_verbatim_type_b \else \expandafter\buff_verbatim_type_c diff --git a/tex/context/base/mkiv/buff-ver.mkxl b/tex/context/base/mkiv/buff-ver.mkxl index 4dc82288a..9f8a20695 100644 --- a/tex/context/base/mkiv/buff-ver.mkxl +++ b/tex/context/base/mkiv/buff-ver.mkxl @@ -42,7 +42,7 @@ \resetbreakpoints \to \everyinitializeverbatim -\unexpanded\def\setverbatimspaceskip % to be checked: must happen after font switch +\permanent\protected\def\setverbatimspaceskip % to be checked: must happen after font switch {\spaceskip\fontcharwd\font`x\relax \xspaceskip\spaceskip} @@ -51,10 +51,10 @@ \setvalue{\??typinglines\v!yes }{\buff_verbatim_obey_breakpoints} \setvalue{\??typinglines\v!hyphenated}{\buff_verbatim_obey_hyphens} -\setvalue{\??typingspace\v!on }{\let\obeyedspace\specialcontrolspace} -\setvalue{\??typingspace\v!stretch }{\let\obeyedspace\specialstretchedspace} +\setvalue{\??typingspace\v!on }{\enforced\let\obeyedspace\specialcontrolspace} +\setvalue{\??typingspace\v!stretch }{\enforced\let\obeyedspace\specialstretchedspace} \setvalue{\??typingspace\v!normal }{} -\setvalue{\??typingspace\v!fixed }{\let\obeyedspace\specialfixedspace} +\setvalue{\??typingspace\v!fixed }{\enforced\let\obeyedspace\specialfixedspace} \setvalue{\??typingblank\v!standard }{\s_spac_whitespace_parskip} \setvalue{\??typingblank\v!small }{\smallskipamount} @@ -64,18 +64,18 @@ \setvalue{\??typingblank\v!line }{\baselineskip} \setvalue{\??typingblank\v!none }{\zeropoint} -\unexpanded\def\buff_verbatim_obey_hyphens +\protected\def\buff_verbatim_obey_hyphens {} -\unexpanded\def\buff_verbatim_obey_breakpoints +\protected\def\buff_verbatim_obey_breakpoints {\language\minusone % tricky as this affects the pagebuilder \veryraggedright} -\unexpanded\def\buff_verbatim_ignore_hyphens +\protected\def\buff_verbatim_ignore_hyphens {\language\minusone} % tricky as this affects the pagebuilder \def\buff_verbatim_initialize_type_one - {\let\obeylines\ignorelines + {\enforced\let\obeylines\ignorelines \edef\p_buff_option{\typeparameter\c!option}% \ifx\p_buff_option\v!none \usetypestyleandcolor\c!style\c!color @@ -88,15 +88,15 @@ \def\buff_verbatim_initialize_type_two {\spaceskip.5\emwidth\relax - \let\obeyedspace\specialobeyedspace - \let\controlspace\specialcontrolspace + \enforced\let\obeyedspace\specialobeyedspace + \enforced\let\controlspace\specialcontrolspace \edef\p_buff_lines{\typeparameter\c!lines}% \begincsname\??typinglines\p_buff_lines\endcsname \edef\p_buff_space{\typeparameter\c!space}% \begincsname\??typingspace\p_buff_space\endcsname \relax\the\everyinitializeverbatim\relax} -\unexpanded\def\doinitializeverbatim % for use elsewhere .. temp hack (see lxml-ini) +\protected\def\doinitializeverbatim % for use elsewhere .. temp hack (see lxml-ini) {\buff_verbatim_initialize_type_one \buff_verbatim_initialize_type_two} @@ -130,8 +130,8 @@ \def\buff_verbatim_initialize_typing_two {\spaceskip.5\emwidth\relax - \let\obeyedspace\specialobeyedspace - \let\controlspace\specialcontrolspace + \enforced\let\obeyedspace\specialobeyedspace + \enforced\let\controlspace\specialcontrolspace \edef\p_buff_lines{\typingparameter\c!lines}% \begincsname\??typinglines\p_buff_lines\endcsname \edef\p_buff_space{\typingparameter\c!space}% @@ -192,7 +192,7 @@ \def\buff_verbatim_initialize_visualizer#1% {\ifproductionrun\clf_loadvisualizer{#1}\fi} -\unexpanded\def\doifelsevisualizer#1% +\protected\def\doifelsevisualizer#1% {\clf_doifelsevisualizer{#1}} \let\doifvisualizerelse\doifelsevisualizer @@ -264,29 +264,26 @@ {\egroup \typeparameter\c!right} -\unexpanded\def\type{\buff_verbatim_type\empty} -\unexpanded\def\typ {\buff_verbatim_typ \empty} +\permanent\protected\def\type{\buff_verbatim_type\empty} +\permanent\protected\def\typ {\buff_verbatim_typ \empty} -\unexpanded\def\buff_verbatim_type#1% +\protected\def\buff_verbatim_type#1% {\dontleavehmode \bgroup \edef\currenttype{#1}% - \doifelsenextoptionalcs\buff_verbatim_type_yes\buff_verbatim_type_nop} - -\def\buff_verbatim_type_yes[#1]% - {\setupcurrenttype[#1]% - \buff_verbatim_type_nop} + \buff_verbatim_type_indeed} \def\buff_verbatim_typ#1% {\dontleavehmode \bgroup \edef\currenttype{#1}% \lettypeparameter\c!lines\v!hyphenated - \let\specialobeyedspace\specialstretchedspace - \doifelsenextoptionalcs\buff_verbatim_type_yes\buff_verbatim_type_nop} + \enforced\let\specialobeyedspace\specialstretchedspace + \buff_verbatim_type_indeed} -\def\buff_verbatim_type_nop - {\buff_verbatim_left_of_type +\tolerant\def\buff_verbatim_type_indeed[#1]% + {\ifarguments\or\setupcurrenttype[#1]\fi + \buff_verbatim_left_of_type \futureexpand\bgroup\buff_verbatim_type_a\buff_verbatim_type_one} \def\buff_verbatim_type_one @@ -369,33 +366,33 @@ %D right, but a decent hyphenation support of \type{\tt} text will be implemented %D soon. -\unexpanded\def\specialfixedspace {\kern\interwordspace\relax} -\unexpanded\def\specialobeyedspace {\hskip\interwordspace\relax} % better than spaceskip -\unexpanded\def\specialstretchedspace {\hskip.5\interwordspace\s!plus.125\interwordspace\relax} % \interwordstretch can be zero -\unexpanded\def\specialcontrolspace {\normalcontrolspace\allowbreak} % uses fallback +\permanent\protected\def\specialfixedspace {\kern\interwordspace\relax} +\permanent\protected\def\specialobeyedspace {\hskip\interwordspace\relax} % better than spaceskip +\permanent\protected\def\specialstretchedspace {\hskip.5\interwordspace\s!plus.125\interwordspace\relax} % \interwordstretch can be zero +\permanent\protected\def\specialcontrolspace {\normalcontrolspace\allowbreak} % uses fallback -\unexpanded\def\explicitfixedspace {\asciispacechar} -\unexpanded\def\explicitobeyedspace {\asciispacechar\allowbreak} -\unexpanded\def\explicitstretchedspace{\asciispacechar\hskip\zeropoint\s!plus.125\interwordspace\relax}% -\unexpanded\def\explicitcontrolspace {\optionalcontrolspace\allowbreak} % uses asciispace +\permanent\protected\def\explicitfixedspace {\asciispacechar} +\permanent\protected\def\explicitobeyedspace {\asciispacechar\allowbreak} +\permanent\protected\def\explicitstretchedspace{\asciispacechar\hskip\zeropoint\s!plus.125\interwordspace\relax}% +\permanent\protected\def\explicitcontrolspace {\optionalcontrolspace\allowbreak} % uses asciispace \appendtoks - \unexpanded\def\obeyedspace{\hskip\zeropoint\asciispacechar\hskip\zeropoint}% + \protected\def\obeyedspace{\hskip\zeropoint\asciispacechar\hskip\zeropoint}% \to \everyenableelements -\unexpanded\def\obeyhyphens - {\let\obeyedspace \specialobeyedspace % maybe \specialstretchedspace - \let\controlspace\specialcontrolspace +\permanent\protected\def\obeyhyphens + {\enforced\let\obeyedspace \specialobeyedspace % maybe \specialstretchedspace + \enforced\let\controlspace\specialcontrolspace \spaceskip.25\emwidth\relax} % hm a bit of stretch ! -\unexpanded\def\obeybreakpoints +\permanent\protected\def\obeybreakpoints {\ignorehyphens \veryraggedright} -\unexpanded\def\ignorehyphens +\permanent\protected\def\ignorehyphens {\language\minusone % extra bonus, the \null should do the job too - \let\obeyedspace \specialobeyedspace - \let\controlspace\specialcontrolspace + \enforced\let\obeyedspace \specialobeyedspace + \enforced\let\controlspace\specialcontrolspace \spaceskip.5\emwidth\relax} %D \macros @@ -427,21 +424,21 @@ \aftergroup\egroup \let\nexttoken} -\unexpanded\def\tex{\buff_verbatim_special_type\texescape \relax} -\unexpanded\def\arg{\buff_verbatim_special_type\leftargument \rightargument} -\unexpanded\def\mat{\buff_verbatim_special_type\inlinemathmarker \inlinemathmarker} -\unexpanded\def\dis{\buff_verbatim_special_type\displaymathmarker\displaymathmarker} +\protected\def\tex{\buff_verbatim_special_type\texescape \relax} +\protected\def\arg{\buff_verbatim_special_type\leftargument \rightargument} +\protected\def\mat{\buff_verbatim_special_type\inlinemathmarker \inlinemathmarker} +\protected\def\dis{\buff_verbatim_special_type\displaymathmarker\displaymathmarker} \let\normaltexttex\tex \let\normaltextarg\arg \let\normaltextmat\mat \let\normaltextdis\dis -\unexpanded\def\astype +\permanent\protected\def\astype {\dontleavehmode \bgroup\usetypestyleandcolor\c!style\c!color\let\nexttoken} -\unexpanded\def\asciistr#1% used in some old styles +\permanent\protected\def\asciistr#1% used in some old styles {\dontleavehmode\begingroup \dostarttagged\t!verbatim\empty \usetypestyleandcolor\c!style\c!color\detokenize{#1}% @@ -454,20 +451,12 @@ \let\beginofverbatimlines\relax % hooks \let\endofverbatimlines \relax % hooks -\unexpanded\def\buff_verbatim_typing_start#1% tricky non standard lookahead +\protected\def\buff_verbatim_typing_start#1% tricky non standard lookahead {\begingroup \edef\currenttyping{#1}% \obeylines \futureexpandis[\buff_verbatim_typing_start_yes\buff_verbatim_typing_start_nop} -\unexpanded\def\buff_verbatim_setup_keep_together - {\edef\p_keeptogether{\typingparameter\c!keeptogether}% - \ifx\p_keeptogether\v!yes - \settrue \c_buff_optimize_linebreaks - \else - \setfalse\c_buff_optimize_linebreaks - \fi} - \def\buff_verbatim_typing_start_nop {\typingparameter\c!before \startpacked[\v!blank]% @@ -489,7 +478,17 @@ \buff_verbatim_setup_keep_together \normalexpanded{\buff_verbatim_type_block{\e!start\currenttyping}{\e!stop\currenttyping}}} -\unexpanded\def\buff_verbatim_type_block#1#2% +% \startnamedtyping[#1] + +\protected\def\buff_verbatim_setup_keep_together + {\edef\p_keeptogether{\typingparameter\c!keeptogether}% + \ifx\p_keeptogether\v!yes + \settrue \c_buff_optimize_linebreaks + \else + \setfalse\c_buff_optimize_linebreaks + \fi} + +\protected\def\buff_verbatim_type_block#1#2% {\edef\p_strip{\typingparameter\c!strip}% \normalexpanded{\buff_pickup {_typing_}% @@ -499,7 +498,7 @@ {\buff_verbatim_type_block_verbatim_indeed{#1}{#2}}% \ifx\p_strip\v!no\zerocount\else\plusone\fi}} -\unexpanded\def\buff_verbatim_type_block_verbatim_indeed#1#2% +\protected\def\buff_verbatim_type_block_verbatim_indeed#1#2% {\buff_verbatim_initialize_typing_two \dostarttaggedchained\t!verbatimblock\currenttyping\??typing \beginofverbatimlines @@ -518,7 +517,7 @@ \dostoptagged \begincsname#2\endcsname} -\unexpanded\def\buff_verbatim_typing_stop#1% hm, currenttyping +\protected\def\buff_verbatim_typing_stop#1% hm, currenttyping {\stoppacked \typingparameter\c!after \useindentnextparameter\typingparameter @@ -578,27 +577,49 @@ % [category] [settings] {name} % for historic reasons, all filenames are {} -\unexpanded\def\typefile - {\dodoubleempty\buff_verbatim_type_file} - \appendtoks \setuevalue{\e!type\currenttyping\v!file}{\typefile[\currenttyping]}% \to \everydefinetyping -\def\buff_verbatim_type_file[#1][#2]#3% +%% \protected\def\typefile +%% {\dodoubleempty\buff_verbatim_type_file} +%% +%% \def\buff_verbatim_type_file[#1][#2]#3% +%% {\begingroup +%% \ifsecondargument +%% \setuptyping[#1][#2]% +%% \buff_verbatim_type_file_checked{#1}{#3}% +%% \orelse\iffirstargument +%% \ifcondition\validassignment{#1}% +%% \setuptyping[\v!file][#1]% +%% \buff_verbatim_type_file_checked\v!file{#3}% +%% \else +%% \buff_verbatim_type_file_checked{#1}{#3}% +%% \fi +%% \else +%% \buff_verbatim_type_file_checked\v!file{#3}% +%% \fi +%% \useindentnextparameter\typingparameter % needs checking +%% \endgroup +%% \dorechecknextindentation} % needs checking + +\permanent\tolerant\protected\def\typefile[#1]#*[#2]% + {\buff_verbatim_type_file{#1}{#2}} + +\def\buff_verbatim_type_file#1#2#3% {\begingroup - \ifsecondargument - \setuptyping[#1][#2]% - \buff_verbatim_type_file_checked{#1}{#3}% - \orelse\iffirstargument + \ifarguments + \buff_verbatim_type_file_checked\v!file{#3}% + \or \ifcondition\validassignment{#1}% \setuptyping[\v!file][#1]% \buff_verbatim_type_file_checked\v!file{#3}% \else \buff_verbatim_type_file_checked{#1}{#3}% \fi - \else - \buff_verbatim_type_file_checked\v!file{#3}% + \or + \setuptyping[#1][#2]% + \buff_verbatim_type_file_checked{#1}{#3}% \fi \useindentnextparameter\typingparameter % needs checking \endgroup @@ -609,7 +630,7 @@ {\buff_verbatim_type_file_indeed{#1}\askedtypingfile} {\showmessage\m!verbatims1{#2}}} -\unexpanded\def\doifelsetypingfile#1% +\permanent\protected\def\doifelsetypingfile#1% {\edef\askedtypingfile{\locfilename{#1}}% \ifempty\askedtypingfile \edef\askedtypingfile{\locfilename{#1.tex}}% downward compatible @@ -620,7 +641,7 @@ \expandafter\firstoftwoarguments \fi} -\let\doiftypingfileelse\doifelsetypingfile +\aliased\let\doiftypingfileelse\doifelsetypingfile \def\buff_verbatim_type_file_indeed#1#2% category name {\edef\currenttyping{#1}% @@ -651,7 +672,7 @@ \newconditional\verbatimnumberinglines -\def\beginofverbatimlinenumbering +\permanent\protected\def\beginofverbatimlinenumbering {\startlinenumbering [\currenttyping]% [\c!continue=\typingparameter\c!continue, @@ -660,7 +681,7 @@ \c!stop=\typingparameter\c!stop, % ? \c!step=\typingparameter\c!step]} -\def\endofverbatimlinenumbering +\overloaded\protected\def\endofverbatimlinenumbering {\stoplinenumbering} \def\buff_verbatim_setup_line_numbering @@ -675,8 +696,8 @@ \setfalse\verbatimnumberinglines \fi \ifconditional\verbatimnumberinglines - \let\beginofverbatimlines\beginofverbatimlinenumbering - \let\endofverbatimlines \endofverbatimlinenumbering + \enforced\let\beginofverbatimlines\beginofverbatimlinenumbering + \enforced\let\endofverbatimlines \endofverbatimlinenumbering \fi \fi} @@ -691,14 +712,14 @@ %D %D The definition is not that spectacular. -\unexpanded\def\filename#1{{\tttf\hyphenatedfilename{#1}}} +\permanent\protected\def\filename#1{{\tttf\hyphenatedfilename{#1}}} %D \macros %D {verbatim} %d %D And a bonus macro, an unexpanded detokenize: -\unexpanded\def\verbatim#1{\detokenize{#1}} +\permanent\protected\def\verbatim#1{\detokenize{#1}} %D The setups for display verbatim and file verbatim are shared. One can adapt the %D extra defined typing environments, but they also default to the values below. @@ -762,18 +783,12 @@ % [name] [settings] | [name] | [settings] -% \unexpanded\def\typebuffer -% {\dodoubleempty\buff_verbatim_type_buffer} - -\unexpanded\def\typebuffer +\permanent\protected\def\typebuffer {\begingroup \let\currenttyping\v!buffer - \dodoubleempty\buff_verbatim_type_buffer} - -\unexpanded\def\buff_verbatim_type_defined_buffer - {\dotripleempty\buff_verbatim_type_defined_buffer_indeed} + \buff_verbatim_type_buffer} -\unexpanded\def\typedefinedbuffer[#1]% +\protected\def\typedefinedbuffer[#1]% {\buff_verbatim_type_defined_buffer[\v!buffer][\thedefinedbuffer{#1}]}% \appendtoks @@ -784,32 +799,32 @@ \setuevalue{\e!type\currenttyping\v!buffer}{\buff_verbatim_type_buffer_class{\currenttyping}}% \to \everydefinetyping -\unexpanded\def\buff_verbatim_type_buffer[#1][#2]% - {\ifsecondargument - \setupcurrenttyping[#2]% - \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name] [settings] - \orelse\iffirstargument - \ifcondition\validassignment{#1}% +\tolerant\protected\def\buff_verbatim_type_buffer[#1]#*[#2]% + {\ifarguments + \buff_verbatim_type_buffer_indeed\currenttyping\empty% [] + \or + \ifhastok={#1}% \setupcurrenttyping[#1]% \buff_verbatim_type_buffer_indeed\currenttyping\empty% [settings] \else \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name] \fi - \else - \buff_verbatim_type_buffer_indeed\currenttyping\empty% [] + \or + \setupcurrenttyping[#2]% + \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\currenttyping}% [name] [settings] \fi \useindentnextparameter\typingparameter \endgroup \dorechecknextindentation} -\unexpanded\def\buff_verbatim_type_buffer_class#1% +\protected\def\buff_verbatim_type_buffer_class#1% {\begingroup \edef\currenttyping{#1}% - \dodoubleempty\buff_verbatim_type_buffer} + \buff_verbatim_type_buffer} -\unexpanded\def\buff_verbatim_type_defined_buffer_indeed[#1][#2][#3]% category name settings +\tolerant\protected\def\buff_verbatim_type_defined_buffer[#1]#*[#2]#*[#3]% category name settings {\begingroup - \ifthirdargument + \ifarguments\or\or\or \setuptyping[#1][#3]% \fi \buff_verbatim_type_buffer_indeed{#1}{#2}% @@ -817,7 +832,7 @@ \endgroup \dorechecknextindentation} -\unexpanded\def\buff_verbatim_type_buffer_indeed#1#2% category name +\protected\def\buff_verbatim_type_buffer_indeed#1#2% category name {\edef\currenttyping{#1}% \typingparameter\c!before \startpacked[\v!blank] @@ -843,15 +858,15 @@ \stoppacked \typingparameter\c!after} -\unexpanded\def\typeinlinebuffer +\permanent\protected\def\typeinlinebuffer {\dontleavehmode \begingroup \let\buff_verbatim_type_buffer_indeed\buff_verbatim_type_buffer_indeed_inline \let\setupcurrenttyping\setupcurrenttype % a terrible hack but it saves code \let\currenttype\empty - \dodoubleempty\buff_verbatim_type_buffer} + \buff_verbatim_type_buffer} -\unexpanded\def\buff_verbatim_type_buffer_indeed_inline#1#2% category name +\protected\def\buff_verbatim_type_buffer_indeed_inline#1#2% category name {\edef\currenttype{#1}% \buff_verbatim_initialize_type_one \dostarttaggedchained\t!verbatim\currenttype\??type @@ -871,24 +886,22 @@ % the next one is obsolete (bad name and used nowhere) so if it stays % the name will change -\unexpanded\def\processbuffer +\permanent\tolerant\protected\def\processbuffer[#1]#*[#2]% {\writestatus{nota bene}{\string\processbuffer\space is obsolete}% - \dodoubleempty\buff_verbatim_process} - -\def\buff_verbatim_process[#1][#2]% - {\begingroup - \ifsecondargument - \setuptyping[\v!buffer][#2]% - \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name] [settings] - \orelse\iffirstargument - \ifcondition\validassignment{#1}% + \begingroup + \ifarguments + \buff_verbatim_process_indeed\v!buffer\empty% [] + \or + %\ifcondition\validassignment{#1}% + \ifhastok={#1}% \setuptyping[\v!buffer][#1]% \buff_verbatim_process_indeed\v!buffer\empty% [settings] \else \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name] \fi - \else - \buff_verbatim_process_indeed\v!buffer\empty% [] + \or + \setuptyping[\v!buffer][#2]% + \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name] [settings] \fi \endgroup} @@ -908,7 +921,7 @@ \newcount\nofverbatimlines -\unexpanded\def\buff_verbatim_begin_of_line +\protected\def\buff_verbatim_begin_of_line {\ifconditional\verbatimnumberinglines \global\advance\nofverbatimlines\plusone \c_attr_verbatimline\nofverbatimlines @@ -917,10 +930,9 @@ \buff_verbatim_set_line_margin \the\everyline % maybe also after starttagged \strut % after starttagged, else break ! - \dostarttagged\t!verbatimline\empty - } + \dostarttagged\t!verbatimline\empty} -\unexpanded\def\buff_verbatim_end_of_line +\protected\def\buff_verbatim_end_of_line {\dostoptagged \obeyedline % still needed? \par @@ -928,7 +940,7 @@ \c_attr_verbatimline\attributeunsetvalue \fi} -\unexpanded\def\buff_verbatim_empty_line +\protected\def\buff_verbatim_empty_line {\dostoptagged \ifconditional\verbatimnumberinglines \par\strut\par % this will be an option where we use a signal instead of a strut @@ -937,7 +949,7 @@ \fi \dostarttagged\t!verbatimlines\empty} -% hooks: +% hooks (todo: frozen): \newcount \c_buff_verbatim_noflines \newcount \c_buff_verbatim_current @@ -945,25 +957,25 @@ \def\doverbatimspace {\obeyedspace} -\unexpanded\def\doinlineverbatimstart {} -\unexpanded\def\doinlineverbatimstop {} -\unexpanded\def\doinlineverbatimbeginline {} -\unexpanded\def\doinlineverbatimnewline {\obeyedspace} -\unexpanded\def\doinlineverbatimemptyline {\obeyedspace} - -\unexpanded\def\dodisplayverbatimstart {\advance\c_buff_verbatim_current\plusone - \buff_verbatim_begin_of_line} -\unexpanded\def\dodisplayverbatimstop {\buff_verbatim_end_of_line} -\unexpanded\def\dodisplayverbatimbeginline{\advance\c_buff_verbatim_current\plusone - \buff_verbatim_begin_of_line} -\unexpanded\def\dodisplayverbatimnewline {\buff_verbatim_end_of_line - \par - \ifconditional\c_buff_optimize_linebreaks - \buff_verbatim_inject_breaks - \fi} -\unexpanded\def\dodisplayverbatimemptyline{\buff_verbatim_empty_line} - -\unexpanded\def\buff_verbatim_inject_breaks +\protected\def\doinlineverbatimstart {} +\protected\def\doinlineverbatimstop {} +\protected\def\doinlineverbatimbeginline {} +\protected\def\doinlineverbatimnewline {\obeyedspace} +\protected\def\doinlineverbatimemptyline {\obeyedspace} + +\protected\def\dodisplayverbatimstart {\advance\c_buff_verbatim_current\plusone + \buff_verbatim_begin_of_line} +\protected\def\dodisplayverbatimstop {\buff_verbatim_end_of_line} +\protected\def\dodisplayverbatimbeginline{\advance\c_buff_verbatim_current\plusone + \buff_verbatim_begin_of_line} +\protected\def\dodisplayverbatimnewline {\buff_verbatim_end_of_line + \par + \ifconditional\c_buff_optimize_linebreaks + \buff_verbatim_inject_breaks + \fi} +\protected\def\dodisplayverbatimemptyline{\buff_verbatim_empty_line} + +\protected\def\buff_verbatim_inject_breaks {\ifnum\c_buff_verbatim_current=\plusone \nobreak \orelse\ifnum\c_buff_verbatim_noflines=\plusthree @@ -972,7 +984,7 @@ \nobreak \fi} -\unexpanded\def\dodisplayverbatiminitialize#1% +\protected\def\dodisplayverbatiminitialize#1% {\forgetparindent % maybe more \c_buff_verbatim_noflines#1\relax \c_buff_verbatim_current\zerocount} @@ -991,22 +1003,21 @@ % \setuevalue{\currentvisualizer}{\buff_verbatim_visualize{\currentvisualizer}}% % \to \everydefinevisualizer % -% \unexpanded\def\buff_verbatim_visualize#1% +% \protected\def\buff_verbatim_visualize#1% % {\bgroup % \def\currentvisualizer{#1}% % \usevisualizerstyleandcolor\c!style\c!color % \let\next} \appendtoks - %def\type#1{\letterbackslash\checkedstrippedcsname#1}% or maybe detokenize - \def\type#1{\detokenize\expandafter{\csstring#1}}% or maybe detokenize - \def\tex #1{\letterbackslash#1}% + \enforced\def\type#1{\detokenize\expandafter{\csstring#1}}% or maybe detokenize + \enforced\def\tex #1{\letterbackslash#1}% \to \everysimplifycommands \stopcontextdefinitioncode %D This is \type {\asciimode} without the double comment hackery: -\unexpanded\def\literalmode{\setcatcodetable\txtcatcodes} +\protected\def\literalmode{\setcatcodetable\txtcatcodes} \protect \endinput diff --git a/tex/context/base/mkiv/catc-ctx.mkiv b/tex/context/base/mkiv/catc-ctx.mkiv index 3492a4bc5..c86201a78 100644 --- a/tex/context/base/mkiv/catc-ctx.mkiv +++ b/tex/context/base/mkiv/catc-ctx.mkiv @@ -125,6 +125,7 @@ \catcodetable \ctxcatcodes \let \defaultcatcodetable \ctxcatcodes +% \defaultcatcodetable \ctxcatcodes % also an option % for the moment here: diff --git a/tex/context/base/mkiv/catc-ctx.mkxl b/tex/context/base/mkiv/catc-ctx.mkxl new file mode 100644 index 000000000..fcaec65d0 --- /dev/null +++ b/tex/context/base/mkiv/catc-ctx.mkxl @@ -0,0 +1,162 @@ +%D \module +%D [ file=catc-cys, +%D version=2006.09.18, +%D title=\CONTEXT\ Catcode Macros, +%D subtitle=Extra Tables, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D We prefer to define relevant catcode tables in this file instead +%D of everywhere around. + +\ifdefined \ctxcatcodes \else \newcatcodetable \ctxcatcodes \fi +\ifdefined \prtcatcodes \else \newcatcodetable \prtcatcodes \fi +\ifdefined \txtcatcodes \else \newcatcodetable \txtcatcodes \fi +%ifdefined \mthcatcodes \else \newcatcodetable \mthcatcodes \fi % math, not used, too tricky +\ifdefined \tpacatcodes \else \newcatcodetable \tpacatcodes \fi % { } +\ifdefined \tpbcatcodes \else \newcatcodetable \tpbcatcodes \fi % < > + +\setnewconstant \doublecommentsignal "10FF25 %% < 110000 (last valid range) + +\startcatcodetable \ctxcatcodes + \catcode\tabasciicode \spacecatcode + \catcode\endoflineasciicode \endoflinecatcode + \catcode\formfeedasciicode \endoflinecatcode + \catcode\spaceasciicode \spacecatcode + \catcode\endoffileasciicode \ignorecatcode + % \catcode\circumflexasciicode\superscriptcatcode + % \catcode\underscoreasciicode\subscriptcatcode + % \catcode\ampersandasciicode \alignmentcatcode + \catcode\underscoreasciicode\othercatcode + \catcode\circumflexasciicode\othercatcode + \catcode\ampersandasciicode \othercatcode + \catcode\backslashasciicode \escapecatcode + \catcode\leftbraceasciicode \begingroupcatcode + \catcode\rightbraceasciicode\endgroupcatcode + \catcode\dollarasciicode \mathshiftcatcode + \catcode\hashasciicode \parametercatcode + \catcode\commentasciicode \commentcatcode + \catcode\tildeasciicode \activecatcode + \catcode\barasciicode \activecatcode +\stopcatcodetable + +\startcatcodetable \prtcatcodes + \catcode\tabasciicode \spacecatcode + \catcode\endoflineasciicode \endoflinecatcode + \catcode\formfeedasciicode \endoflinecatcode + \catcode\spaceasciicode \spacecatcode + \catcode\endoffileasciicode \ignorecatcode + \catcode\circumflexasciicode \superscriptcatcode % candidate + \catcode\underscoreasciicode \lettercatcode + \catcode\ampersandasciicode \alignmentcatcode + \catcode\backslashasciicode \escapecatcode + \catcode\leftbraceasciicode \begingroupcatcode + \catcode\rightbraceasciicode \endgroupcatcode + \catcode\dollarasciicode \mathshiftcatcode + \catcode\hashasciicode \parametercatcode + \catcode\commentasciicode \commentcatcode + \catcode\atsignasciicode \lettercatcode + \catcode\exclamationmarkasciicode\lettercatcode + \catcode\questionmarkasciicode \lettercatcode + \catcode\tildeasciicode \activecatcode + \catcode\barasciicode \activecatcode +\stopcatcodetable + +\startcatcodetable \tpacatcodes + \catcode\tabasciicode \othercatcode + \catcode\endoflineasciicode \othercatcode + \catcode\formfeedasciicode \othercatcode + \catcode\spaceasciicode \othercatcode + \catcode\endoffileasciicode \othercatcode + \catcode\leftbraceasciicode \begingroupcatcode + \catcode\rightbraceasciicode\endgroupcatcode +\stopcatcodetable + +\startcatcodetable \tpbcatcodes + \catcode\tabasciicode \othercatcode + \catcode\endoflineasciicode \othercatcode + \catcode\formfeedasciicode \othercatcode + \catcode\spaceasciicode \othercatcode + \catcode\endoffileasciicode \othercatcode + \catcode\lessthanasciicode \begingroupcatcode + \catcode\morethanasciicode \endgroupcatcode +\stopcatcodetable + +\startcatcodetable \txtcatcodes + \catcode\tabasciicode \spacecatcode + \catcode\endoflineasciicode \endoflinecatcode + \catcode\formfeedasciicode \endoflinecatcode + \catcode\spaceasciicode \spacecatcode + \catcode\endoffileasciicode \ignorecatcode + \catcode\backslashasciicode \escapecatcode + \catcode\leftbraceasciicode \begingroupcatcode + \catcode\rightbraceasciicode\endgroupcatcode + \catcode\doublecommentsignal\commentcatcode +\stopcatcodetable + +\letcatcodecommand \ctxcatcodes \barasciicode \relax +\letcatcodecommand \ctxcatcodes \tildeasciicode \relax + +\pushoverloadmode + + \catcodetable \ctxcatcodes +\let \defaultcatcodetable \ctxcatcodes + +\popoverloadmode + +% for the moment here: + +\permanent\protected\def\starttexcode + {\pushcatcodetable + \catcodetable\prtcatcodes} + +\permanent\protected\def\stoptexcode + {\popcatcodetable} + +\permanent\protected\def\startcontextcode + {\pushcatcodetable + \catcodetable\ctxcatcodes} + +\permanent\protected\def\stopcontextcode + {\popcatcodetable} + +% not visible, only for special cases + +\newcatcodetable \ctdcatcodes % context definitions + +\startcatcodetable \ctdcatcodes + \catcode\tabasciicode \ignorecatcode + \catcode\endoflineasciicode \ignorecatcode + \catcode\formfeedasciicode \ignorecatcode + \catcode\spaceasciicode \ignorecatcode + \catcode\endoffileasciicode \ignorecatcode + \catcode\circumflexasciicode \superscriptcatcode % candidate + \catcode\underscoreasciicode \lettercatcode + \catcode\ampersandasciicode \alignmentcatcode +% \catcode\colonasciicode \lettercatcode % candidate + \catcode\backslashasciicode \escapecatcode + \catcode\leftbraceasciicode \begingroupcatcode + \catcode\rightbraceasciicode \endgroupcatcode + \catcode\dollarasciicode \mathshiftcatcode + \catcode\hashasciicode \parametercatcode + \catcode\commentasciicode \commentcatcode + \catcode\atsignasciicode \lettercatcode + \catcode\exclamationmarkasciicode\lettercatcode + \catcode\questionmarkasciicode \lettercatcode + \catcode\tildeasciicode \activecatcode + \catcode\barasciicode \activecatcode +\stopcatcodetable + +\permanent\protected\def\startcontextdefinitioncode + {\pushcatcodetable + \catcodetable\ctdcatcodes} + +\permanent\protected\def\stopcontextdefinitioncode + {\popcatcodetable} + +\endinput diff --git a/tex/context/base/mkiv/catc-ini.mkxl b/tex/context/base/mkiv/catc-ini.mkxl new file mode 100644 index 000000000..fb1b5b359 --- /dev/null +++ b/tex/context/base/mkiv/catc-ini.mkxl @@ -0,0 +1,329 @@ +%D \module +%D [ file=catc-ini, +%D version=2006.09.18, +%D title=\CONTEXT\ System Macros, +%D subtitle=Catcode Handling, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%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. + +\registerctxluafile{catc-ini}{} + +\unprotect + +%D A long standing wish has been the availability of catcode arrays. Because +%D traditional \TEX\ does not provide this we implement a fake method in the +%D \MKII\ file. There is some overlap in code with \MKII\ but we take that +%D for granted. Also, in \MKIV\ less active characters are used. + +% \begingroup +% +% \catcode\tabasciicode \activecatcode +% \catcode\formfeedasciicode \activecatcode +% \catcode\endoflineasciicode\activecatcode +% +% \letcharcode\tabasciicode \relax +% \letcharcode\newlineasciicode \relax +% \letcharcode\formfeedasciicode \relax +% \letcharcode\endoflineasciicode\relax +% +% \xdef\activetabtoken {\Uchar\tabasciicode } % \gdef\activetabtoken {^^I} +% \xdef\outputnewlinechar {\Uchar\newlineasciicode } % \gdef\outputnewlinechar {^^J} +% \xdef\activeformfeedtoken {\Uchar\formfeedasciicode } % \gdef\activeformfeedtoken {^^L} +% \xdef\activeendoflinetoken{\Uchar\endoflineasciicode} % \gdef\activeendoflinetoken{^^M} +% +% \endgroup + +\begingroup + \letcharcode\newlineasciicode\relax \xdef\outputnewlinechar{\Uchar\newlineasciicode} +\endgroup + +% \endlinechar = \endoflineasciicode % appended to input lines +% \newlinechar = \newlineasciicode % can be used in write + +% 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 + \newlinechar\newlineasciicode + \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>>} + +\installsystemnamespace {catcodelet} % let : \let +\installsystemnamespace {catcodedef} % def : \def +\installsystemnamespace {catcodeued} % ued : \protected\def +\installsystemnamespace {catcodeget} % \meaning + +\installsystemnamespace {catcodetablet} +\installsystemnamespace {catcodetablen} + +\newcount\c_syst_catcodes_n \c_syst_catcodes_n\zerocount % 0 = signal, so advance before allocate +\newcount\c_syst_catcodes_a +\newcount\c_syst_catcodes_b +\newcount\c_syst_catcodes_c + +\permanent\protected\def\newcatcodetable#1% we could move the cctdefcounter to lua + {\global\advance\c_syst_catcodes_n\plusone + \expandafter\xdef\csname\??catcodetablen\number\c_syst_catcodes_n\endcsname{\string#1}% logging + %\setnewconstant#1\c_syst_catcodes_n + \overloaded\integerdef#1\c_syst_catcodes_n + \ctxcommand{registercatcodetable("\expandafter\gobbleoneargument\string#1",\number#1)}} + +\newtoks \everysetdefaultcatcodes + +\everysetdefaultcatcodes % this might get dropped + {\catcode\backslashasciicode\othercatcode + \catcode\endoflineasciicode\othercatcode + \catcode\spaceasciicode \othercatcode + \catcode\commentasciicode \othercatcode + \catcode\delasciicode \othercatcode} + +\permanent\protected\def\startcatcodetable#1#2\stopcatcodetable + {\begingroup + \catcodetable\inicatcodes + \the\everysetdefaultcatcodes + #2% + \savecatcodetable#1\relax + \endgroup} + +\permanent\let\stopcatcodetable\relax + +\permanent\protected\def\startextendcatcodetable#1#2\stopextendcatcodetable + {\begingroup + \catcodetable#1\relax + \globaldefs\plusone + #2% + \globaldefs\zerocount + \endgroup} + +\permanent\let\stopextendcatcodetable\relax + +\permanent\protected\def\permitcircumflexescape % to be used grouped + {\catcode\circumflexasciicode\superscriptcatcode} + +\let\permitcaretescape\permitcircumflexescape + +% == +% +% \protected\def\startextendcatcodetable#1#2\stopextendcatcodetable +% {\bgroup +% \scratchcounter\the\catcodetable +% \catcodetable #1 #2 +% \catcodetable\scratchcounter +% \egroup} + +%D The next command can be defined in a cleaner way in the MkIV way but we want +%D to have a fast one with a minimal chance for interference. Do we still need +%D this complex mechanism? Probably not. Future versions of \MKIV\ might only use +%D active characters for very special cases. + +\setnewconstant\c_syst_catcodes_hack\tildeasciicode + +%D Once a catcode is assigned, the next assignments will happen faster. However, +%D redefinitions probably happen seldom so it's sort of overkill. + +\permanent\def\letcatcodecommand{\afterassignment\syst_catcodes_let_a\c_syst_catcodes_a} +\permanent\def\defcatcodecommand{\afterassignment\syst_catcodes_def_a\c_syst_catcodes_a} +\permanent\def\uedcatcodecommand{\afterassignment\syst_catcodes_ued_a\c_syst_catcodes_a} + +\def\syst_catcodes_let_a{\afterassignment\syst_catcodes_let_b\c_syst_catcodes_b} +\def\syst_catcodes_def_a{\afterassignment\syst_catcodes_def_b\c_syst_catcodes_b} +\def\syst_catcodes_ued_a{\afterassignment\syst_catcodes_ued_b\c_syst_catcodes_b} + +\def\syst_catcodes_let_b % each time + {\ifcsname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname + \expandafter\lastnamedcs + \else + \expandafter\syst_catcodes_let_c + \fi} + +\def\syst_catcodes_def_b % each time + {\ifcsname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname + \expandafter\lastnamedcs + \else + \expandafter\syst_catcodes_def_c + \fi} + +\def\syst_catcodes_ued_b % each time + {\ifcsname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname + \expandafter\lastnamedcs + \else + \expandafter\syst_catcodes_ued_c + \fi} + +\def\syst_catcodes_let_c % only first time + {\frozen\enforced\global\expandafter\def\csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname\expandafter + {\enforced\expandafter\let\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}% + \syst_catcodes_reinstate_unexpanded + \csname\??catcodelet\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname} + +\def\syst_catcodes_def_c % only first time (we could use \normalexpanded here) + {\frozen\enforced\global\expandafter\def\csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname + \expandafter##\expandafter1\expandafter + {\frozen\enforced\expandafter\def\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}% + \syst_catcodes_reinstate_normal + \csname\??catcodedef\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname} + +\def\syst_catcodes_ued_c % only first time + {\frozen\enforced\global\expandafter\def\csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname + \expandafter##\expandafter1\expandafter + {\frozen\enforced\protected\expandafter\def\csname\??catcodeget\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}% + \syst_catcodes_reinstate_unexpanded + \csname\??catcodeued\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname} + +\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) + +\def\syst_catcodes_reinstate_normal + {\begingroup + \edef\c_syst_char_code{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}% + \global\letcharcode\c_syst_catcodes_b\c_syst_char_code + \endgroup} + +\def\syst_catcodes_reinstate_unexpanded + {\begingroup + \protected\edef\c_syst_char_code{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}% + \global\letcharcode\c_syst_catcodes_b\c_syst_char_code + \endgroup} + +\newconstant\defaultcatcodetable + +\permanent\def\catcodecommand#1% + {\csname\??catcodeget\number + \ifcsname\??catcodeget\number\currentcatcodetable:\number#1\endcsname + \currentcatcodetable \else \defaultcatcodetable + \fi + :\number#1\endcsname} + +%D \macros +%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. + +\newcount\c_syst_catcodes_level + +\permanent\protected\def\pushcatcodetable + {\advance\c_syst_catcodes_level\plusone + \syst_catcodes_trace_push + \expandafter\chardef\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname\currentcatcodetable} + +\permanent\protected\def\popcatcodetable + {\ifcase\c_syst_catcodes_level + \syst_catcodes_trace_nesting_error + \else + \expandafter\catcodetable\csname\??catcodetablet\number\c_syst_catcodes_level\endcsname + \syst_catcodes_trace_pop + \advance\c_syst_catcodes_level\minusone + \fi} + +\protected\def\syst_catcodes_trace_nesting_error + {\immediate\write\statuswrite{}% + \immediate\write\statuswrite{Fatal error: catcode push/pop mismatch. Fix this! (restore level: \number\c_syst_catcodes_level)}\wait\end + \immediate\write\statuswrite{}} + +\permanent\protected\def\restorecatcodes % takes previous level + {\ifnum\c_syst_catcodes_level>\plusone + \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: +%D +%D \starttyping +%D \tracecatcodetables +%D \stoptyping + +\permanent\protected\def\tracecatcodetables + {\def\syst_catcodes_trace_set {\syst_catcodes_trace{set \catcodetablename\space at \number\c_syst_catcodes_level}}% + \def\syst_catcodes_trace_push{\syst_catcodes_trace{push \catcodetablename\space from \syst_catcodes_prev\space at \number\c_syst_catcodes_level}}% + \def\syst_catcodes_trace_pop {\syst_catcodes_trace{pop \catcodetablename\space to \syst_catcodes_prev\space at \number\c_syst_catcodes_level}}} + +\def\syst_catcodes_trace#1{\immediate\write\statuswrite{[#1]}} + +\def\syst_catcodes_prev + {\ifnum\numexpr\c_syst_catcodes_level-1\relax>\zerocount + \csname\??catcodetablen\number\csname\??catcodetablet\number\numexpr\c_syst_catcodes_level-1\relax\endcsname\endcsname + \else + -% + \fi} + +\def\catcodetablename + {\ifnum\currentcatcodetable>\zerocount + \csname\??catcodetablen\number\currentcatcodetable\endcsname + \else + -% + \fi} + +\let\syst_catcodes_trace_set \empty +\let\syst_catcodes_trace_push\empty +\let\syst_catcodes_trace_pop \empty + +% \tracecatcodetables + +\protect + +%D We still have to define these so let's do that now: + +\newcatcodetable \inicatcodes +\initcatcodetable\inicatcodes + +\let\currentcatcodetable\catcodetable + +\endinput diff --git a/tex/context/base/mkiv/char-def.lua b/tex/context/base/mkiv/char-def.lua index 51a227cb5..70e564399 100644 --- a/tex/context/base/mkiv/char-def.lua +++ b/tex/context/base/mkiv/char-def.lua @@ -429,7 +429,7 @@ characters.data={ direction="on", linebreak="al", mathclass="binary", - mathname="ast", +--mathname="ast", mathsymbol=0x2217, synonyms={ "star" }, unicodeslot=0x2A, @@ -4893,7 +4893,7 @@ characters.data={ { adobename="Vhook", category="lu", - contextname="Uhook", + contextname="Vhook", description="LATIN CAPITAL LETTER V WITH HOOK", direction="l", lccode=0x28B, @@ -10546,7 +10546,7 @@ characters.data={ direction="l", linebreak="al", mathclass="ordinary", - mathname="varkappa", +--mathname="varkappa", specials={ "compat", 0x3BA }, uccode=0x39A, unicodeslot=0x3F0, @@ -58794,7 +58794,6 @@ characters.data={ [0x1EF6]={ adobename="Yhookabove", category="lu", - contextname="Yhook", description="LATIN CAPITAL LETTER Y WITH HOOK ABOVE", direction="l", lccode=0x1EF7, @@ -58806,7 +58805,6 @@ characters.data={ [0x1EF7]={ adobename="yhookabove", category="ll", - contextname="yhook", description="LATIN SMALL LETTER Y WITH HOOK ABOVE", direction="l", linebreak="al", @@ -60767,7 +60765,7 @@ characters.data={ }, [0x1FBB]={ category="lu", - contextname="greekAlphatonos", + comment="conflict: greekAlphatonos", description="GREEK CAPITAL LETTER ALPHA WITH OXIA", direction="l", lccode=0x1F71, @@ -60897,7 +60895,7 @@ characters.data={ }, [0x1FC9]={ category="lu", - contextname="greekEpsilontonos", + comment="conflict: greekEpsilontonos", description="GREEK CAPITAL LETTER EPSILON WITH OXIA", direction="l", lccode=0x1F73, @@ -60919,7 +60917,7 @@ characters.data={ }, [0x1FCB]={ category="lu", - contextname="greekEtatonos", + comment="conflict: greekEtatonos", description="GREEK CAPITAL LETTER ETA WITH OXIA", direction="l", lccode=0x1F75, @@ -60950,7 +60948,7 @@ characters.data={ }, [0x1FCE]={ category="sk", - contextname="greekpsilitonos", + comment="conflict: greekpsilitonos", description="GREEK PSILI AND OXIA", direction="on", linebreak="al", @@ -61000,7 +60998,7 @@ characters.data={ }, [0x1FD3]={ category="ll", - contextname="greekiotadialytikatonos", + comment="conflict: greekiotadialytikatonos", description="GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA", direction="l", linebreak="al", @@ -61063,7 +61061,7 @@ characters.data={ }, [0x1FDB]={ category="lu", - contextname="greekIotatonos", + comment="conflict: greekIotatonos", description="GREEK CAPITAL LETTER IOTA WITH OXIA", direction="l", lccode=0x1F77, @@ -61083,7 +61081,7 @@ characters.data={ }, [0x1FDE]={ category="sk", - contextname="greekdasiatonos", + comment="conflict: greekdasiatonos", description="GREEK DASIA AND OXIA", direction="on", linebreak="al", @@ -61133,7 +61131,7 @@ characters.data={ }, [0x1FE3]={ category="ll", - contextname="greekupsilondialytikatonos", + comment="conflict: greekupsilondialytikatonos", description="GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA", direction="l", linebreak="al", @@ -61217,7 +61215,7 @@ characters.data={ }, [0x1FEB]={ category="lu", - contextname="greekUpsilontonos", + comment="conflict: greekUpsilontonos", description="GREEK CAPITAL LETTER UPSILON WITH OXIA", direction="l", lccode=0x1F7B, @@ -61248,7 +61246,7 @@ characters.data={ }, [0x1FEE]={ category="sk", - contextname="greekdialytikatonos", + comment="conflict: greekdialytikatonos", description="GREEK DIALYTIKA AND OXIA", direction="on", linebreak="al", @@ -61328,7 +61326,7 @@ characters.data={ }, [0x1FF9]={ category="lu", - contextname="greekOmicrontonos", + comment="conflict: greekOmicrontonos", description="GREEK CAPITAL LETTER OMICRON WITH OXIA", direction="l", lccode=0x1F79, @@ -61350,7 +61348,7 @@ characters.data={ }, [0x1FFB]={ category="lu", - contextname="greekOmegatonos", + comment="conflict: greekOmegatonos", description="GREEK CAPITAL LETTER OMEGA WITH OXIA", direction="l", lccode=0x1F7D, @@ -63212,10 +63210,10 @@ characters.data={ direction="nsm", linebreak="cm", mathspec={ - { - class="default", - name="bigcircle", - }, +-- { +-- class="default", +-- name="bigcircle", +-- }, { class="binary", name="bigcircle", @@ -65221,7 +65219,7 @@ characters.data={ [0x21B5]={ adobename="carriagereturn", category="so", - contextname="carriagereturn", + comment="conflict: carriagereturn", description="DOWNWARDS ARROW WITH CORNER LEFTWARDS", direction="on", linebreak="al", @@ -135799,7 +135797,7 @@ characters.data={ }, [0xFDF9]={ category="lo", - contextname="arabicsalla", + comment="conflict: arabicsalla", description="ARABIC LIGATURE SALLA ISOLATED FORM", direction="al", linebreak="al", diff --git a/tex/context/base/mkiv/char-ini.lua b/tex/context/base/mkiv/char-ini.lua index 58882cd30..1f8e72af7 100644 --- a/tex/context/base/mkiv/char-ini.lua +++ b/tex/context/base/mkiv/char-ini.lua @@ -766,7 +766,7 @@ local is_mark = allocate ( tohash { } ) local is_punctuation = allocate ( tohash { - "pc","pd","ps","pe","pi","pf","po", + "pc", "pd", "ps", "pe", "pi", "pf", "po", } ) local is_symbol = allocate ( tohash { diff --git a/tex/context/base/mkiv/char-ini.mkiv b/tex/context/base/mkiv/char-ini.mkiv index 5979b8685..aa3d31ba8 100644 --- a/tex/context/base/mkiv/char-ini.mkiv +++ b/tex/context/base/mkiv/char-ini.mkiv @@ -125,6 +125,8 @@ \clf_setactivecatcodes\notcatcodes \clf_setactivecatcodes\prtcatcodes +\clf_setcharacternames\ctxcatcodes + \def\chardescription#1{\clf_chardescription#1\relax} % experiment (watch out: this is global and very font dependent when used with diff --git a/tex/context/base/mkiv/char-ini.mkxl b/tex/context/base/mkiv/char-ini.mkxl new file mode 100644 index 000000000..1df5d4b01 --- /dev/null +++ b/tex/context/base/mkiv/char-ini.mkxl @@ -0,0 +1,130 @@ +%D \module +%D [ file=char-ini, +%D version=2006.08.20, +%D title=\CONTEXT\ Character Support, +%D subtitle=Initialization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Character Support / Initialization} + +\registerctxluafile{char-fio}{} +\registerctxluafile{char-map}{} % maybe we will load this someplace else +\registerctxluafile{char-tex}{} +\registerctxluafile{char-ent}{} + +\unprotect + +% ¨äëïöüÿ +% ´áćéíĺńóŕśúýź +% ˙ċėġiż +% ¯āēīōū +% ˝őű +% ˆâĉêĝĥîĵôŝûŵŷ +% `àèìòùỳ +% ¸çķļņŗşţ +% ˛ąęįų +% ˚åů +% ˘ăĕğĭŏŭ +% ˇčďěľňřšťž +% ˜ãĩñõũ + +% \def\checkedchar#1% #2% +% {\relax\iffontchar\font#1 \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi{\char#1}} +% +% impossible in math mode so there always fallback (till we have gyre): +% +% use \normalUchar when possible .. the next one is nice for documents and it also accepts +% 0x prefixed numbers + +\permanent\def\utfchar #1{\clf_utfchar {#1}} % todo: define public at lua end +\permanent\def\safechar#1{\clf_safechar{#1}} % todo: define public at lua end + +\permanent\protected\def\Ux #1{\Uchar\numexpr"#1\relax} % used in xml (sometimes overloaded) +\permanent \def\eUx#1{\Uchar\numexpr"#1\relax} % used in xml (sometimes overloaded) + +\permanent\def\expandUx{\enforced\let\Ux\eUx} + +\permanent \def\checkedchar {\relax\ifmmode\expandafter\checkedmathchar\else\expandafter\checkedtextchar\fi} % #1#2 +\permanent \def\checkedmathchar#1#2{#2} +%permanent \def\checkedtextchar #1{\iffontchar\font#1 \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi{\char#1}} +\permanent\protected\def\checkedtextchar #1{\clf_doifelsecharinfont\numexpr#1\relax{\char#1}} % {#2} + +\newconditional\prefermathovertextchar + +\permanent\protected\def\textormathchar#1% + {\begingroup + \scratchcounter#1\relax + \ifmmode + \char\scratchcounter + \else + \ifconditional\prefermathovertextchar + % dirty trick .. maybe let this adapt to bf too ? + \setfontid\fontid\textfont\c_font_fam_mr + \fi + \iffontchar\font\scratchcounter + \char\scratchcounter + \else + \normalstartimath\char\scratchcounter\normalstopimath + \fi + \fi + \endgroup} + +\permanent\protected\def\textormathchars#1% + {{\font_text_or_mathchars#1\relax}} + +\protected\def\font_text_or_mathchars#1#2\relax + {\relax\ifmmode + #1#2% + \orelse\iffontchar\font`#1\relax + #1#2\relax + \else + \normalstartimath#1#2\normalstopimath + \fi} + +%D The codes are stored in the format, so we don't need to reinitialize +%D them (unless of course we have adapted the table). It is on the agenda +%D to do this with \type {tex.lccode} cum suis once they're available. + +% \def\setcclcuc#1#2#3{\global\catcode#1=\lettercatcode\global\lccode#1=#2\global\uccode#1=#3\relax} +% \def\setcclcucself#1{\global\catcode#1=\lettercatcode\global\lccode#1=#1\global\uccode#1=#1\relax } + +% Is setting up vrb tpa and tpb needed? + +% move to lua side + +%clf_setcharactercodes + +\clf_setlettercatcodes\texcatcodes +\clf_setlettercatcodes\ctxcatcodes +\clf_setlettercatcodes\notcatcodes +%clf_setlettercatcodes\mthcatcodes +\clf_setlettercatcodes\vrbcatcodes +\clf_setlettercatcodes\prtcatcodes +\clf_setlettercatcodes\tpacatcodes +\clf_setlettercatcodes\tpbcatcodes +\clf_setlettercatcodes\txtcatcodes + +\clf_setactivecatcodes\ctxcatcodes +\clf_setactivecatcodes\notcatcodes +\clf_setactivecatcodes\prtcatcodes + +\clf_setcharacternames\ctxcatcodes + +\permanent\def\chardescription#1{\clf_chardescription#1\relax} + +% experiment (watch out: this is global and very font dependent when used with +% casing mechanisms) +% +% \overloaduppercase{0xDF}{0x1E9E}} +% \overloaduppercase{0xDF}{0x53,0x53} + +\permanent\protected\def\overloaduppercase{\clf_overloaduppercase} % todo: define public at lua end +\permanent\protected\def\overloadlowercase{\clf_overloadlowercase} % todo: define public at lua end + +\protect \endinput diff --git a/tex/context/base/mkiv/char-tex.lua b/tex/context/base/mkiv/char-tex.lua index b361a9a07..1e86ca171 100644 --- a/tex/context/base/mkiv/char-tex.lua +++ b/tex/context/base/mkiv/char-tex.lua @@ -573,88 +573,68 @@ if not csletters then local traditional = sfstate == "traditional" for u, chr in next, data do -- will move up - local fallback = chr.fallback - if fallback then - contextsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\checkedchar{",u,"}{",fallback,"}}}") - activated[#activated+1] = u - else - local contextname = chr.contextname - local category = chr.category - local isletter = is_letter[category] - if contextname then - if is_character[category] then - if chr.unicodeslot < 128 then - if isletter then - local c = utfchar(u) - texsetmacro(contextname,c) - csletters[c] = u - else - texsetchar(contextname,u) - end - else - local c = utfchar(u) - texsetmacro(contextname,c) - if isletter and u >= 32 and u <= 65536 then - csletters[c] = u - end - end - -- + local contextname = chr.contextname + local category = chr.category + local isletter = is_letter[category] + if contextname then + if is_character[category] then + if chr.unicodeslot < 128 then if isletter then - local lc = chr.lccode - local uc = chr.uccode - if not lc then - chr.lccode = u - lc = u - elseif type(lc) == "table" then - lc = u - end - if not uc then - chr.uccode = u - uc = u - elseif type(uc) == "table" then - uc = u - end - texsetlccode(u,lc,uc) - if traditional and category == "lu" then - texsetsfcode(code,999) - end + local c = utfchar(u) + csletters[c] = u end - -- - elseif is_command[category] and not forbidden[u] then - -- contextsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\",contextname,"}}") - -- activated[#activated+1] = u + else local c = utfchar(u) - texsetmacro(contextname,c) - elseif is_mark[category] then - texsetlccode(u,u,u) -- for hyphenation - end - -- elseif isletter and u >= 32 and u <= 65536 then - elseif isletter then - csletters[utfchar(u)] = u - -- - local lc, uc = chr.lccode, chr.uccode - if not lc then - chr.lccode = u - lc = u - elseif type(lc) == "table" then - lc = u - end - if not uc then - chr.uccode = u - uc = u - elseif type(uc) == "table" then - uc = u + if isletter and u >= 32 and u <= 65536 then + csletters[c] = u + end end - texsetlccode(u,lc,uc) - if traditional and category == "lu" then - texsetsfcode(code,999) + if isletter then + local lc = chr.lccode + local uc = chr.uccode + if not lc then + chr.lccode = u + lc = u + elseif type(lc) == "table" then + lc = u + end + if not uc then + chr.uccode = u + uc = u + elseif type(uc) == "table" then + uc = u + end + texsetlccode(u,lc,uc) + if traditional and category == "lu" then + texsetsfcode(code,999) + end end - -- + elseif is_command[category] and not forbidden[u] then + -- skip elseif is_mark[category] then - -- texsetlccode(u,u,u) -- for hyphenation - -- end + elseif isletter then + csletters[utfchar(u)] = u + local lc, uc = chr.lccode, chr.uccode + if not lc then + chr.lccode = u + lc = u + elseif type(lc) == "table" then + lc = u + end + if not uc then + chr.uccode = u + uc = u + elseif type(uc) == "table" then + uc = u + end + texsetlccode(u,lc,uc) + if traditional and category == "lu" then + texsetsfcode(code,999) + end + elseif is_mark[category] then + texsetlccode(u,u,u) -- for hyphenation end end @@ -690,6 +670,29 @@ if not csletters then storage.register("characters/csletters", csletters, "characters.csletters") end + function characters.setcharacternames(ctt) + for u, chr in next, data do -- will move up + local contextname = chr.contextname + local category = chr.category + local isletter = is_letter[category] + if contextname then + if is_character[category] then + if chr.unicodeslot < 128 then + if isletter then + texsetmacro(contextname,utfchar(u),"permanent") + else + texsetchar(contextname,u) + end + else + texsetmacro(contextname,utfchar(u),"permanent") + end + elseif is_command[category] and not forbidden[u] then + texsetmacro(contextname,utfchar(u),"permanent") + end + end + end + end + else mark(csletters) end @@ -826,9 +829,13 @@ end -- entities.gt = utfchar(characters.activeoffset + utfbyte(">")) -- end -implement { name = "setlettercatcodes", scope = "private", actions = characters.setlettercatcodes, arguments = "integer" } -implement { name = "setactivecatcodes", scope = "private", actions = characters.setactivecatcodes, arguments = "integer" } ---------- { name = "setcharactercodes", scope = "private", actions = characters.setcodes } +if characters.setcharacternames then -- only in ini mode + + implement { name = "setlettercatcodes", scope = "private", actions = characters.setlettercatcodes, arguments = "integer" } + implement { name = "setactivecatcodes", scope = "private", actions = characters.setactivecatcodes, arguments = "integer" } + implement { name = "setcharacternames", scope = "private", actions = characters.setcharacternames, arguments = "integer" } + +end -- experiment (some can move to char-ini.lua) diff --git a/tex/context/base/mkiv/chem-str.mkiv b/tex/context/base/mkiv/chem-str.mkiv index 71b104e47..17c80472e 100644 --- a/tex/context/base/mkiv/chem-str.mkiv +++ b/tex/context/base/mkiv/chem-str.mkiv @@ -449,7 +449,7 @@ \egroup} \appendtoks - \let|\chemicalbar % \SR{N|NH} + \let |\chemicalbar % \SR{N|NH} \let \+\chemicaloxidationplus \let \-\chemicaloxidationminus \let \[\chemicalforeveropen diff --git a/tex/context/base/mkiv/chem-str.mkxl b/tex/context/base/mkiv/chem-str.mkxl new file mode 100644 index 000000000..853887678 --- /dev/null +++ b/tex/context/base/mkiv/chem-str.mkxl @@ -0,0 +1,761 @@ +%D \module +%D [ file=chem-ini, +%D version=2009.05.13, +%D subtitle=Chemistry, +%D author=Hans Hagen \& Alan Braslau, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D The original \PPCHTEX\ code was written in pure \TEX\, although later we made +%D the move from \PICTEX\ to \METAPOST\. The current implementation is a mix between +%D \TEX\, \LUA\ and \METAPOST. Although the first objective is to get a compatible +%D but better implementation, later versions might provide more, + +%D NOT YET LMTX'd + +\writestatus{loading}{ConTeXt Chemistry Macros / Structure} + +\registerctxluafile{chem-str}{} + +% We have a slightly different interface. This is unchanged: +% +% \startchemical[axis=on] +% \chemical[SIX,ROT2,B,R6,SUB1,FIVE,ROT1,B][1] +% \stopchemical +% +% Here we use chemicalformula instead, so no longer a mix: +% +% \startchemicalformula +% \chemical{2H_2}{top}{bottom} +% \chemical{PLUS}{top}{bottom} +% \chemical{O_2}{top}{bottom} +% \chemical{GIVES}{top}{bottom} +% \chemical{2H_2O}{top}{bottom} +% \stopchemicalformula +% +% \startchemicalformula +% \chemical{2H_2} +% \chemical{PLUS} +% \chemical{O_2} +% \chemical{GIVES} +% \chemical{2H_2O} +% \stopchemicalformula +% +% The inline variant has only one argument: +% +% \chemical{2H_2,PLUS,O_2,GIVES,2H_2O} + +\unprotect + +\installcorenamespace{chemical} +\installcorenamespace{chemicalsymbol} +\installcorenamespace{chemicalframed} +\installcorenamespace{chemicalsize} + +% \installsimplecommandhandler \??chemical {chemical} \??chemical % no \define... +\installcommandhandler \??chemical {chemical} \??chemical % no \define... + +\let\setupchemicals \setupchemical +\let\definechemicals\definechemical + +%D We use a dedicated framed macro instead of inheriting one. This is both +%D a historical and practical reason (like shared keys with different meaning +%D that could clash, e.g.\ align). + +\defineMPinstance % not really needed as we set in lua + [chemistry] + [\s!format=metafun, + %\s!extensions=\v!yes, % Should we add extensions and initializations? + %\s!initializations=\v!yes, % Would this give EmWidth, etc.? + \c!method=\s!double] + +\startMPdefinitions{chemistry} + loadmodule "chem" ; +\stopMPdefinitions + +\defineframed + [\??chemicalframed] + [\c!align=\v!normal, + \c!strut=\v!no] + +\unexpanded\def\setupchemicalframed + {\setupframed[\??chemicalframed]} + +\unexpanded\overloaded\def\definechemical % is global (so we don't use the commandhandler) + {\dosingleargument\chem_define} + +\def\chem_define[#1]#2% + {\startnointerference + \edef\currentdefinedchemical{#1}% + \let\chemical\chem_chemical_nested + \clf_undefinechemical{#1}% + #2% flush + \stopnointerference} + +\unexpanded\def\chem_chemical_nested + {\dodoubleempty\chem_chemical_nested_indeed} + +\def\chem_chemical_nested_indeed[#1][#2]% + {\clf_definechemical{\currentdefinedchemical}{#1}{\detokenize{#2}}} + +% chemical symbols + +\unexpanded\def\definechemicalsymbol + {\dodoubleempty\chem_symbol_define} + +\def\chem_symbol_define[#1][#2]% + {\setvalue{\??chemicalsymbol#1}{#2}} + +\unexpanded\def\chemicalsymbol[#1]% + {\csname\??chemicalsymbol\ifcsname\??chemicalsymbol#1\endcsname#1\else\s!unknown\fi\endcsname} + +\definechemicalsymbol[\s!unknown][] % \char"FFFD empty + +% size (small medium big) + +\edef\chemicaltoplocation{t} +\edef\chemicalbotlocation{b} + +\unexpanded\def\chemicaltext#1% + {\mathematics + {\usechemicalstyleandcolor\c!style\c!color + \strut + \ifcase\currentxfontsize\or\scriptstyle\or\scriptscriptstyle\fi + #1}} + +\setvalue{\??chemicalsize\v!small }{\txx} +\setvalue{\??chemicalsize\v!medium}{\tx} +\setvalue{\??chemicalsize\v!big }{} + +\newtoks \everychemical +\newtoks \everystructurechemical +\newconditional\indisplaychemical + +\newtoks \t_chem_every_box +\newbox \b_chem_result +\newconditional\c_chem_some_text +\newdimen \d_chem_width +\newdimen \d_chem_height +\newdimen \d_chem_depth + +\unexpanded\def\startchemical + {\dodoubleempty\chem_start} + +\def\chem_start[#1][#2]% + {\ifmmode\vcenter\else\vbox\fi % vpack ? + \bgroup + \synchronizestrut{\chemicalparameter\c!strut}% + \dontcomplain + \settrue\indisplaychemical + \forgetall + \ifsecondargument + \doifelseassignment{#1} + {\setupcurrentchemical[#1]}% same as \currentchemical + {\edef\currentchemical{#1}% + \setupcurrentchemical[#2]}% + \else\iffirstargument + \doifelseassignment{#1} + {\setupcurrentchemical[#1]}% same as \currentchemical + {\edef\currentchemical{#1}}% + \fi\fi + \the\everystructurechemical + \setbox\b_chem_result\hpack\bgroup + \clf_startchemical + width {\chemicalparameter\c!width}% + height {\chemicalparameter\c!height}% + left {\chemicalparameter\c!left}% + right {\chemicalparameter\c!right}% + top {\chemicalparameter\c!top}% + bottom {\chemicalparameter\c!bottom}% + scale {\chemicalparameter\c!scale}% + rotation {\chemicalparameter\c!rotation}% + symalign {\chemicalparameter\c!symalign}% + axis {\chemicalparameter\c!axis}% was \MPcolor{...} + framecolor {\chemicalparameter\c!framecolor}% + rulethickness {\number\dimexpr\chemicalparameter\c!rulethickness}% + offset {\number\dimexpr\chemicalparameter\c!offset}% + unit {\number\dimexpr\chemicalparameter\c!unit}% + factor {\number\chemicalparameter\c!factor}% + \relax + \startnointerference} + +\unexpanded\def\stopchemical + {\stopnointerference + \clf_stopchemical + \egroup + \d_chem_width \wd\b_chem_result + \d_chem_height\ht\b_chem_result + \d_chem_depth \dp\b_chem_result + \the\t_chem_every_box + \doifelsenothing{\chemicalparameter\c!frame}\chem_framed_nop\chem_framed_yes + \egroup} + +\unexpanded\def\chem_framed_yes + {\localframedwithsettings + [\??chemicalframed]% + [\c!frame=\chemicalparameter\c!frame, + \c!rulethickness=\chemicalparameter\c!rulethickness, + \c!framecolor=\chemicalparameter\c!framecolor]% + {\vpack{\box\b_chem_result\vss}}} % remove depth + +\unexpanded\def\chem_framed_nop + {\directlocalframed + [\??chemicalframed]% + {\vpack{\box\b_chem_result\vss}}} % remove depth + +\let\startstructurechemical\startchemical +\let\stopstructurechemical \stopchemical + +\unexpanded\def\structurechemical + {\dotripleempty\strc_chem_indeed} + +\appendtoks + \let\chemical\structurechemical +\to\everystructurechemical + +\def\strc_chem_indeed + {\ifthirdargument + \expandafter\strc_chem_indeed_three + \else + \expandafter\strc_chem_indeed_two + \fi} + +\def\strc_chem_indeed_three[#1][#2][#3]% + {\writestatus\m!chemicals{hyperlinked chemicals not yet supported}% todo reference, for the moment ignored + \clf_chemicalcomponent + {#2}% + {\detokenize{#3}}% + {\the\dimexpr\chemicalparameter\c!rulethickness}% todo: scaled points + {\chemicalparameter\c!rulecolor}% + \relax + \ignorespaces} + +\def\strc_chem_indeed_two[#1][#2]% + {\clf_chemicalcomponent + {#1}% + {\detokenize{#2}}% + {\the\dimexpr\chemicalparameter\c!rulethickness}% todo: scaled points + {\chemicalparameter\c!rulecolor}% + \relax + \ignorespaces} + +\appendtoks + \setbox\b_chem_result\hpack{\raise\MPlly\box\b_chem_result}% + \d_chem_width \wd\b_chem_result + \d_chem_height\ht\b_chem_result + \d_chem_depth \dp\b_chem_result +\to \t_chem_every_box + +% kind of compatible, but text sizes instead of math sizes (i.e. tx is larger than scriptsize) + +\appendtoks + \edef\chemicalbodyfont{\chemicalparameter\c!bodyfont}% public? + \ifx\chemicalbodyfont\empty + \switchtobodyfont[\chemicalbodyfont]% + \fi + \getvalue{\??chemicalsize\chemicalparameter\c!size}% +% \to \everystructurechemical +\to \everychemical + +\def\chemicaltoptext#1{\global\settrue\c_chem_some_text\gdef\m_chem_top_text{#1}\ignorespaces} +\def\chemicalbottext#1{\global\settrue\c_chem_some_text\gdef\m_chem_bot_text{#1}\ignorespaces} +\def\chemicalmidtext#1{\global\settrue\c_chem_some_text\gdef\m_chem_mid_text{#1}\ignorespaces} + +\appendtoks + \let\toptext\chemicaltoptext \glet\m_chem_top_text\empty + \let\bottext\chemicalbottext \glet\m_chem_bot_text\empty + \let\midtext\chemicalmidtext \glet\m_chem_mid_text\empty + \global\setfalse\c_chem_some_text +\to \everystructurechemical + +\def\chem_add_texts + {\setbox2\hpack to \d_chem_width{\strut\hss\hbox{\strut\m_chem_mid_text}\hss}% + \setbox4\hpack to \d_chem_width{\strut\hss\hbox{\strut\m_chem_top_text}\hss}% + \setbox6\hpack to \d_chem_width{\strut\hss\hbox{\strut\m_chem_bot_text}\hss}% + \setbox\b_chem_result\hpack \bgroup + \box\b_chem_result + \hskip-\d_chem_width + \raise\d_chem_height\hpack{\lower\ht4\box4}% + \hskip-\d_chem_width + \lower.5\dimexpr\ht2-\dp2\relax\box2% + \hskip-\d_chem_width + \lower\d_chem_depth \hpack{\raise\dp6\box6}% + \hss + \egroup} % text on top of chemicals + +\appendtoks + \ifconditional\c_chem_some_text + \chem_add_texts + \d_chem_width \wd\b_chem_result + \d_chem_height\ht\b_chem_result + \d_chem_depth \dp\b_chem_result + \fi +\to \t_chem_every_box + +% todo: enspace or emspace + +\definechemicalsymbol[space] [\enspace\quad\enspace] +\definechemicalsymbol[plus] [\enspace+\enspace] +\definechemicalsymbol[minus] [\enspace-\enspace] +\definechemicalsymbol[gives] [\chem_arrow_construct\xrightarrow] +\definechemicalsymbol[equilibrium] [\chem_arrow_construct\xrightoverleftarrow] +\definechemicalsymbol[mesomeric] [\chem_arrow_construct\xleftrightarrow] +\definechemicalsymbol[opencomplex] [\mathematics{\Bigg[}] % not yet ok +\definechemicalsymbol[closecomplex][\mathematics{\Bigg]}] % not yet ok + +\definechemicalsymbol[SPACE] [{\chemicalsymbol[space]}] +\definechemicalsymbol[PLUS] [{\chemicalsymbol[plus]}] +\definechemicalsymbol[MINUS] [{\chemicalsymbol[minus]}] +\definechemicalsymbol[GIVES] [{\chemicalsymbol[gives]}] +\definechemicalsymbol[EQUILIBRIUM] [{\chemicalsymbol[equilibrium]}] +\definechemicalsymbol[MESOMERIC] [{\chemicalsymbol[mesomeric]}] +\definechemicalsymbol[OPENCOMPLEX] [{\chemicalsymbol[opencomplex]}] +\definechemicalsymbol[CLOSECOMPLEX][{\chemicalsymbol[closecomplex]}] + +\def\chem_arrow_construct#1#2#3% + {\enspace + \mathematics{#1% + {\strut\hbox \s!spread 2\emwidth{\hss\clf_inlinechemical{#3}\hss}}% {\strut\hbox \s!spread 2em{\hss#3\hss}}}% + {\strut\hbox \s!spread 2\emwidth{\hss\clf_inlinechemical{#2}\hss}}}% {\strut\hbox \s!spread 2em{\hss#2\hss}}% + \enspace} + +% special macros (probably needs some more work) + +\let\chem_box_normal_yes\hbox +\let\chem_box_visual_yes\hbox +\let\chem_box_visual_nop\relax + +\installtextracker + {chemistry.boxes} + {\let\chem_box_visual_yes\ruledhbox \let\chem_box_visual_nop\ruledhbox} + {\let\chem_box_visual_yes\hbox \let\chem_box_visual_nop\relax } + +\def\chem_top_construct#1#2#3#4% + {\hpack\bgroup + \setstrut + \setbox\scratchboxone\chem_box_visual_yes{\strut#3}% + \setbox\scratchboxtwo\chem_box_visual_yes{\strut\molecule{#4}}% + \setbox\scratchboxone\chem_box_normal_yes{\raise\dimexpr\dp\scratchboxone+\ht\scratchboxtwo\relax\hbox to \wd\scratchboxtwo{#1\box\scratchboxone#2}}% + \smashbox\scratchboxone + \box\scratchboxone + \box\scratchboxtwo + \egroup} + +\def\chem_bottom_construct#1#2#3#4% + {\hpack\bgroup + \setstrut + \setbox\scratchboxone\chem_box_visual_yes{\strut#3}% + \setbox\scratchboxtwo\chem_box_visual_yes{\strut\molecule{#4}}% + \setbox\scratchboxone\chem_box_normal_yes{\lower\dimexpr\dp\scratchboxtwo+\ht\scratchboxone\relax\hbox to \wd\scratchboxtwo{#1\box\scratchboxone#2}}% + \smashbox\scratchboxone + \box\scratchboxone + \box\scratchboxtwo + \egroup} + +\unexpanded\def\chemicalleft#1#2% redundant boxes thanks to visual + {\hbox\bgroup % hpack ? + \setstrut + \llap{\chem_box_visual_nop{\strut#1}}% + \chem_box_visual_nop{\strut#2}% + \egroup} + +\unexpanded\def\chemicalright#1#2% redundant boxes thanks to visual + {\hbox\bgroup % hpack ? + \setstrut + \chem_box_visual_yes{\strut#2}% + \rlap{\chem_box_visual_nop{\strut#1}}% + \egroup} + +\unexpanded\def\chemicaltop {\chem_top_construct \hss \hss } +\unexpanded\def\chemicallefttop {\chem_top_construct \relax \hss } +\unexpanded\def\chemicalrighttop {\chem_top_construct \hss \relax} +\unexpanded\def\chemicalbottom {\chem_bottom_construct \hss \hss } +\unexpanded\def\chemicalleftbottom {\chem_bottom_construct \relax \hss } +\unexpanded\def\chemicalrightbottom {\chem_bottom_construct \hss \relax} + +\unexpanded\def\chemicaltopleft #1{\chemicalleft {\chemicalrighttop {#1}{}}} +\unexpanded\def\chemicalbottomleft #1{\chemicalleft {\chemicalrightbottom{#1}{}}} +\unexpanded\def\chemicaltopright #1{\chemicalright{\chemicallefttop {#1}{}}} +\unexpanded\def\chemicalbottomright #1{\chemicalright{\chemicalleftbottom {#1}{}}} + +% \unexpanded\def\chemicalcentered #1{\hbox to \fontcharwd\font`C{\setstrut\strut\hss#1\hss}} +% \unexpanded\def\chemicalleftcentered #1{\hbox to \fontcharwd\font`C{\setstrut\strut #1\hss}} +% \unexpanded\def\chemicalrightcentered#1{\hbox to \fontcharwd\font`C{\setstrut\strut\hss#1}} + +% \let\chemicalsmashedmiddle\chemicalcentered +% \let\chemicalsmashedleft \chemicalleftcentered +% \let\chemicalsmashedright \chemicalrightcentered + +\unexpanded\def\chemicalalignedtext + {\ifmmode + \expandafter\chem_aligned_text_math + \else + \expandafter\chem_aligned_text_text + \fi} + +\let\chemicaltighttext\relax % maybe smaller strut + +\def\chem_aligned_text_text#1#2#3% + {\dontleavehmode + \begingroup + \usechemicalstyleandcolor\c!style\c!color + \chem_box_visual_yes to \fontcharwd\font`C\bgroup + \setstrut\strut + #1\molecule{#3}#2% + \egroup + \endgroup} + +\def\chem_aligned_text_math#1#2#3% + {\dontleavehmode + \begingroup + \scratchcounter\normalmathstyle + \usechemicalstyleandcolor\c!style\c!color + \chem_box_visual_yes to \fontcharwd\font`C\bgroup + \setstrut\strut + #1\mathematics{\tf\triggermathstyle\scratchcounter\molecule{#3}}#2% + \egroup + \endgroup} + +\unexpanded\def\chemicalcentered {\chemicalalignedtext\hss \hss } +\unexpanded\def\chemicalleftcentered {\chemicalalignedtext\relax\hss } +\unexpanded\def\chemicalrightcentered{\chemicalalignedtext\hss \relax} + +\let\chemicalsmashedmiddle\chemicalcentered +\let\chemicalsmashedleft \chemicalleftcentered +\let\chemicalsmashedright \chemicalrightcentered + +\unexpanded\def\chemicaloxidation#1#2#3% + {\chemicaltop{\txx\ifcase#2\relax0\else#1\convertnumber{I}{#2}\fi}{#3}} + +\unexpanded\def\chemicaloxidationplus {\dotriplegroupempty\chemicaloxidation{\textplus }} % {} needed! +\unexpanded\def\chemicaloxidationminus{\dotriplegroupempty\chemicaloxidation{\textminus}} % {} needed! +\unexpanded\def\chemicalforeveropen {\dotriplegroupempty\chemicalleft {$\big[$}} % {} needed! +\unexpanded\def\chemicalforeverclose {\dotriplegroupempty\chemicalright {$\big]$}} % {} needed! +\unexpanded\def\chemicaloxidationone {\chemicaloxidation\relax1} +\unexpanded\def\chemicaloxidationtwo {\chemicaloxidation\relax2} +\unexpanded\def\chemicaloxidationthree{\chemicaloxidation\relax3} +\unexpanded\def\chemicaloxidationfour {\chemicaloxidation\relax4} +\unexpanded\def\chemicaloxidationfive {\chemicaloxidation\relax5} +\unexpanded\def\chemicaloxidationsix {\chemicaloxidation\relax6} +\unexpanded\def\chemicaloxidationseven{\chemicaloxidation\relax7} + +\unexpanded\def\chemicalbar + {\hpack \s!spread .5\emwidth \bgroup + \hss + \vrule \s!height .9\strutht \s!depth .65\strutdp \s!width .1\exheight + \hss + \egroup} + +\appendtoks + \enforced\let |\chemicalbar % \SR{N|NH} + \enforced\let \+\chemicaloxidationplus + \enforced\let \-\chemicaloxidationminus + \enforced\let \[\chemicalforeveropen + \enforced\let \]\chemicalforeverclose + \enforced\let \1\chemicaloxidationone + \enforced\let \2\chemicaloxidationtwo + \enforced\let \3\chemicaloxidationthree + \enforced\let \4\chemicaloxidationfour + \enforced\let \5\chemicaloxidationfive + \enforced\let \6\chemicaloxidationsix + \enforced\let \7\chemicaloxidationseven + \enforced\let \X\chemicaltighttext + \enforced\let \T\chemicaltop + \enforced\let \B\chemicalbottom + \enforced\let \L\chemicalleft + \enforced\let\LC\chemicalleftcentered + \enforced\let \R\chemicalright + \enforced\let\RC\chemicalrightcentered + \enforced\let\TL\chemicaltopleft + \enforced\let\BL\chemicalbottomleft + \enforced\let\TR\chemicaltopright + \enforced\let\BR\chemicalbottomright + \enforced\let\LT\chemicallefttop + \enforced\let\LB\chemicalleftbottom + \enforced\let\RT\chemicalrighttop + \enforced\let\RB\chemicalrightbottom + \enforced\let\SL\chemicalsmashedleft + \enforced\let\SM\chemicalsmashedmiddle + \enforced\let\SR\chemicalsmashedright +\to \everychemical + +% Should these also be defined in lower case, so as to be case independent? + +\appendtoks + \the\everychemical +\to \everystructurechemical + +% inline + +% \unexpanded\def\chemical +% {\ifinformula +% \expandafter\displaychemical +% \else +% \expandafter\inlinechemical +% \fi} + +\unexpanded\def\chemical + {\ifinformula + \expandafter\indisplaychemical + \else + \expandafter\inlinechemical + \fi} + +\unexpanded\def\indisplaychemical + {\mathstylecommand\displaychemical\inlinechemical\inlinechemical} + +\unexpanded\def\inlinechemical#1% + {\dontleavehmode + \begingroup + \scratchcounter\normalmathstyle + \usechemicalstyleandcolor\c!style\c!color + \hbox{\mathematics{\tf\triggermathstyle\scratchcounter\clf_inlinechemical{#1}}}% + \endgroup} + +\unexpanded\def\displaychemical + {\dotriplegroupempty\chem_display} + +\def\chem_display#1#2#3% + {\the\everychemical + \everychemical\emptytoks + \quad + \vcenter\bgroup + \usechemicalstyleandcolor\c!style\c!color + \ifthirdargument + \ifsecondargument + \halign{\aligntab\hss\alignmark\alignmark\hss\cr#2\cr\molecule{#1}\cr#3\cr}% + \else + \halign{\aligntab\hss\alignmark\alignmark\hss \cr\molecule{#1}\cr#2\cr}% + \fi + \else + \hbox{\molecule{#1}}% + \fi + \egroup + \quad} + +\unexpanded\def\inlinechemical#1% + {\dontleavehmode + \hbox{\usechemicalstyleandcolor\c!style\c!color\clf_inlinechemical{#1}}} + +\unexpanded\def\chemicalbondrule + {\hpack{\vrule\s!height.75\exheight\s!depth-\dimexpr.75\exheight-\linewidth\relax\s!width\emwidth\relax}} + +\definechemicalsymbol[i:space] [\enspace\quad\enspace] +\definechemicalsymbol[i:plus] [\enspace\mathematics{+}\enspace] +\definechemicalsymbol[i:minus] [\enspace\mathematics{-}\enspace] +\definechemicalsymbol[i:equals] [\enspace\mathematics{=}\enspace] +\definechemicalsymbol[i:gives] [\enspace\mathematics{\xrightarrow{}{}}\enspace] +\definechemicalsymbol[i:equilibrium] [\enspace\mathematics{\xrightoverleftarrow{}{}}\enspace] +\definechemicalsymbol[i:mesomeric] [\enspace\mathematics{\xleftrightarrow{}{}}\enspace] +\definechemicalsymbol[i:single] [\chemicalbondrule] +\definechemicalsymbol[i:double] [\hpack{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}] +\definechemicalsymbol[i:triple] [\hpack{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}] + +\unexpanded\def\chemicalsinglebond {\chemicalsymbol[i:single]} +\unexpanded\def\chemicaldoublebond {\chemicalsymbol[i:double]} +\unexpanded\def\chemicaltriplebond {\chemicalsymbol[i:triple]} +\unexpanded\def\chemicalgives {\chemicalsymbol[i:gives]} +\unexpanded\def\chemicalmesomeric {\chemicalsymbol[i:mesomeric]} +\unexpanded\def\chemicalequilibrium{\chemicalsymbol[i:equilibrium]} +\unexpanded\def\chemicalplus {\chemicalsymbol[i:plus]} +\unexpanded\def\chemicalminus {\chemicalsymbol[i:minus]} +\unexpanded\def\chemicalequals {\chemicalsymbol[i:equals]} +\unexpanded\def\chemicalspace {\chemicalsymbol[i:space]} +\unexpanded\def\chemicalinline #1{#1} + +% display + +\newconditional\c_chem_has_top +\newconditional\c_chem_has_bot + +\newtoks\t_chem_top +\newtoks\t_chem_mid +\newtoks\t_chem_bot + +\newif\ifinchemicalformula + +\unexpanded\def\startchemicalformula + {\mathortext\vcenter\vbox\bgroup + \forgetall + \inchemicalformulatrue + \the\everychemical + \everychemical\emptytoks + \t_chem_top\emptytoks % not needed + \t_chem_mid\emptytoks % not needed + \t_chem_bot\emptytoks % not needed + \let\chemical\formulachemical + \setfalse\c_chem_has_top + \setfalse\c_chem_has_bot} + +\unexpanded\def\stopchemicalformula + {\tabskip\emwidth\relax + \nointerlineskip + \ifconditional\c_chem_has_top + \ifconditional\c_chem_has_bot + \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}% + \else + \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_top\cr\the\t_chem_mid\cr}% + \fi + \else + \ifconditional\c_chem_has_bot + \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_mid\cr\the\t_chem_bot\cr}% + \else + \halign{\aligntab\hss\usechemicalstyleandcolor\c!style\c!color\alignmark\alignmark\hss\cr\the\t_chem_mid\cr}% + \fi + \fi + \egroup} + +% for the moment we have a special set + +\definechemicalsymbol[d:space] [\enspace\quad\enspace] +\definechemicalsymbol[d:plus] [\enspace+\enspace] +\definechemicalsymbol[d:minus] [\enspace-\enspace] +\definechemicalsymbol[d:equals] [\enspace=\enspace] +\definechemicalsymbol[d:gives] [\rightarrowfill] % \chem_arrow_construct\xrightarrow +\definechemicalsymbol[d:equilibrium] [\rightoverleftarrowfill] % \chem_arrow_construct\xrightoverleftarrow +\definechemicalsymbol[d:mesomeric] [\leftarrowfill] % \chem_arrow_construct\xleftrightarrow +\definechemicalsymbol[d:single] [\chemicalbondrule] +\definechemicalsymbol[d:double] [\hpack{\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}] +\definechemicalsymbol[d:triple] [\hpack{\chemicalbondrule\hskip-1em\lower.5ex\chemicalbondrule\hskip-1em\raise.5ex\chemicalbondrule}] +\definechemicalsymbol[d:opencomplex] [\mathematics{\Bigg[}] % not yet ok +\definechemicalsymbol[d:closecomplex][\mathematics{\Bigg]}] % not yet ok + +\definechemicalsymbol[d:SPACE] [{\chemicalsymbol[d:space]}] +\definechemicalsymbol[d:PLUS] [{\chemicalsymbol[d:plus]}] +\definechemicalsymbol[d:MINUS] [{\chemicalsymbol[d:minus]}] +\definechemicalsymbol[d:EQUALS] [{\chemicalsymbol[d:equals]}] +\definechemicalsymbol[d:GIVES] [{\chemicalsymbol[d:gives]}] +\definechemicalsymbol[d:EQUILIBRIUM] [{\chemicalsymbol[d:equilibrium]}] +\definechemicalsymbol[d:MESOMERIC] [{\chemicalsymbol[d:mesomeric]}] +\definechemicalsymbol[d:SINGLE] [{\chemicalsymbol[d:single]}] +\definechemicalsymbol[d:DOUBLE] [{\chemicalsymbol[d:double]}] +\definechemicalsymbol[d:TRIPLE] [{\chemicalsymbol[d:triple]}] +\definechemicalsymbol[d:OPENCOMPLEX] [{\chemicalsymbol[d:opencomplex]}] +\definechemicalsymbol[d:CLOSECOMPLEX][{\chemicalsymbol[d:closecomplex]}] + +\unexpanded\def\formulachemical + {\relax\dotriplegroupempty\chem_formula} + +\def\chem_formula#1#2#3% we could do hboxes and measure + {\ifthirdargument + \doifelsenothing{#2}\chem_formula_top_nop{\chem_formula_top_yes{#2}}% + \doifelsenothing{#3}\chem_formula_bot_nop{\chem_formula_bot_yes{#3}}% + \else\ifsecondargument + \chem_formula_top_nop + \doifelsenothing{#2}\chem_formula_bot_nop{\chem_formula_bot_yes{#2}}% + \else + \chem_formula_top_nop + \chem_formula_bot_nop + \fi\fi + \ifcsname\??chemicalsymbol d:\detokenize{#1}\endcsname + \toksapp\t_chem_mid{\chemicalsymbol[d:#1]\aligntab}% + \else + \toksapp\t_chem_mid{\molecule{#1}\aligntab}% + \fi} + +\def\chem_formula_mid#1% + {\csname\??chemicalsymbol\detokenize{#1}\endcsname} + +\def\chem_formula_top_nop {\toksapp\t_chem_top{\aligntab}} +\def\chem_formula_bot_nop {\toksapp\t_chem_bot{\aligntab}} +\def\chem_formula_top_yes#1{\toksapp\t_chem_top{\chem_formula_top_indeed{#1}\aligntab}\settrue\c_chem_has_top} +\def\chem_formula_bot_yes#1{\toksapp\t_chem_bot{\chem_formula_bot_indeed{#1}\aligntab}\settrue\c_chem_has_bot} + +\def\chem_formula_top_indeed#1{\strut#1} +\def\chem_formula_bot_indeed#1{\strut#1} + +% Experimental: defaults might change. + +\definefloat + [\v!chemical] + [\v!chemicals] + +\setuplabeltext + [\v!chemical=] + +\setupfloat + [\v!chemical] + [\c!location=\v!here, + \c!inner=\hsize.8\textwidth\dontleavehmode, % brr + \c!align={\v!flushleft,\v!lohi}] + +\setupcaption + [\v!chemical] + [\c!location=\v!right, + \c!distance=\zeropoint, + \c!width=.2\textwidth, + \c!align=\v!flushright] + +% Can be used as for displayed math: \startplaceformula... to display a chemical formula +% or a chemical structure: +% +% \startplacechemical +% \startchemicalformula +% \chemical{2H_2} +% \chemical{PLUS} +% \chemical{O_2} +% \chemical{GIVES} +% \chemical{2H_2O} +% \stopchemicalformula +% \stopplacechemical + +% gone: state option resolution offset (now frame offset) alternative + +\setupchemicalframed + [\c!align=\v!normal, + \c!strut=\v!no, + \c!offset=\v!overlay, + \c!frame=\v!off] + +\definecolor % private color + [chemicalframecolor] + [r=.75,g=.85,b=.95] + +\setupchemical + [\c!frame=, + \c!width=\v!fit, % or unitless number, multiplies scale*unit + \c!height=\v!fit, % or unitless number, multiplies scale*unit + \c!left=\v!fit, % or unitless number, multiplies scale*unit + \c!right=\v!fit, % or unitless number, multiplies scale*unit + \c!top=\v!fit, % or unitless number, multiplies scale*unit + \c!bottom=\v!fit, % or unitless number, multiplies scale*unit + \c!bodyfont=, + \c!scale=\v!normal, % small, normal or medium, big, or unitless number (multiplies unit) + \c!size=\v!medium, + \c!textsize=\v!big, % how is textsize used?? + \c!axis=\v!off, + \c!style=\rm, + \c!rotation=0, % unitless number (interpreted as degrees) + \c!symalign=\v!auto, + \c!location=, % not yet used (was interaction related in mkii) + \c!offset=.25\emwidth, + \c!unit=\emwidth, + \c!factor=3, + \c!color=, + \c!strut=\v!yes, + \c!framecolor=chemicalframecolor, + \c!rulethickness=0.6pt, %1.5\linewidth, + \c!rulecolor=] + +%D Compatibility: + +\definechemical[+R] {\chemical[RR]} +\definechemical[-R] {\chemical[LR]} + +\definechemical[CARBON:CB] {\chemical[NEWMANSTAGGER,C,SB]} +\definechemical[NEWMANSTAGGER:CB] {\chemical[NEWMANSTAGGER,C,SB]} +\definechemical[NEWMANECLIPSED:CB]{\chemical[NEWMANECLIPSED,C,SB]} +\definechemical[CARBON:CB1] {\chemical[CARBON,C,SB,Z234,1.5MOV1,MIR0,C,SB,Z234]} + +\definechemical[NEWMAN] {\chemical[]} +\definechemical[STAGGER] {\chemical[NEWMANSTAGGER]} +\definechemical[ECLIPSE] {\chemical[NEWMANECLIPSED]} +\definechemical[ECLIPSED] {\chemical[NEWMANECLIPSED]} +\definechemical[SIX:FRONT] {\chemical[SIXFRONT]} +\definechemical[FIVE:FRONT] {\chemical[FIVEFRONT]} + +\protect \endinput diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua index 24092d852..77391580f 100644 --- a/tex/context/base/mkiv/cldf-ini.lua +++ b/tex/context/base/mkiv/cldf-ini.lua @@ -97,7 +97,6 @@ local tex = tex local texsprint = tex.sprint -- just appended (no space,eol treatment) local texprint = tex.print -- each arg a separate line (not last in directlua) ----- texwrite = tex.write -- all 'space' and 'character' -local texgetcount = tex.getcount local isnode = node.is_node local writenode = node.write @@ -114,6 +113,15 @@ local isprintable = tex.isprintable or function(n) return n and (type(n) == "string" or isnode(n) or istoken(n)) end +if tex.runlocal then + -- obselete names + tex.runtoks = tex.runlocal + tex.quittoks = tex.quitlocal +else + tex.runlocal = tex.runtoks + tex.quitlocal = tex.quittoks +end + local catcodenumbers = catcodes.numbers local ctxcatcodes = catcodenumbers.ctxcatcodes @@ -133,13 +141,15 @@ local report_cld = logs.reporter("cld","stack") local processlines = true -- experiments.register("context.processlines", function(v) processlines = v end) -local trialtypesettingstate = createtoken("trialtypesettingstate").index +local trialtypesetting = function() return false end -function context.trialtypesetting() - return texgetcount(trialtypesettingstate) ~= 0 - -- return texgetcount("trialtypesettingstate") ~= 0 +function context.settrialtypesettingmethod(f) + trialtypesetting = f + context.trialtypesetting = f end +context.trialtypesetting = function() return trialtypesetting() end -- can be aliased ! + local knownfunctions = (lua.getfunctionstable or lua.get_functions_table)(true) local showstackusage = false @@ -154,14 +164,12 @@ local usedstack = function() end local flushfunction = function(slot,arg) - if arg() then + if arg() or trialtypesetting() then -- keep - elseif texgetcount(trialtypesettingstate) == 0 then + else noffreed = noffreed + 1 freed[noffreed] = slot knownfunctions[slot] = false - else - -- keep end end @@ -181,13 +189,13 @@ local storefunction = function(arg) end local flushnode = function(slot,arg) - if texgetcount(trialtypesettingstate) == 0 then + if trialtypesetting() then + writenode(copynodelist(arg)) + else writenode(arg) noffreed = noffreed + 1 freed[noffreed] = slot knownfunctions[slot] = false - else - writenode(copynodelist(arg)) end end @@ -378,15 +386,61 @@ interfaces.namesofscanners = namesofscanners storage.register("interfaces/storedscanners", storedscanners, "interfaces.storedscanners") -local function registerscanner(name,action,protected,public,usage) -- todo: combine value and condition - rawset(interfacescanners,name,action) - local n = storedscanners[name] - n = registerfunction("interfaces.scanners."..name,true,n) - storedscanners[name] = n - namesofscanners[n] = name - name = public and name or (privatenamespace .. name) - -- print(">>",name,protected and "protected" or "",usage or "macro") - setluatoken(name,n,"global",protected and "protected" or "",usage or "macro") +-- local function registerscanner(name,action,protected,public,usage) -- todo: combine value and condition +-- rawset(interfacescanners,name,action) +-- local n = storedscanners[name] +-- n = registerfunction("interfaces.scanners."..name,true,n) +-- storedscanners[name] = n +-- namesofscanners[n] = name +-- name = public and name or (privatenamespace .. name) +-- -- print(">>",name,protected and "protected" or "",usage or "macro") +-- setluatoken(name,n,"global",protected and "protected" or "",usage or "macro") +-- end + +-- todo: bitmap + +local registerscanner if CONTEXTLMTXMODE > 0 then + + -- always permanent but we can consider to obey permanent==false + + local function toflags(specification) + local protected = specification.protected and "protected" -- or "" + local usage = specification.usage + if usage == "value" then + return "global", "value", "permanent", protected + elseif usage == "condition" then + return "global", "conditional", "permanent", protected + elseif specification.frozen then + return "global", "frozen", protected + elseif specification.permanent == false or specification.onlyonce then -- for now onlyonce here + return "global", protected + else + return "global", "permanent", protected + end + end + + + registerscanner = function(name,action,specification) + rawset(interfacescanners,name,action) + local n = registerfunction("interfaces.scanners."..name,true,storedscanners[name]) + storedscanners[name] = n + namesofscanners[n] = name + name = specification.public and name or (privatenamespace .. name) + setluatoken(name,n,toflags(specification)) + end + +else + + registerscanner = function(name,action,specification) + rawset(interfacescanners,name,action) + local n = storedscanners[name] + n = registerfunction("interfaces.scanners."..name,true,n) + storedscanners[name] = n + namesofscanners[n] = name + name = specification.public and name or (privatenamespace .. name) + setluatoken(name,n,"global",specification.protected and "protected" or "") + end + end interfaces.registerscanner = registerscanner @@ -696,7 +750,7 @@ end local containseol = patterns.containseol -local lua_expandable_call_code = tokens.commands.lua_expandable_call +local lua_call_code = tokens.commands.lua_expandable_call or tokens.commands.lua_call local sortedhashindeed = false @@ -793,7 +847,7 @@ local function writer(parent,command,...) -- already optimized before call local tj = ti[1] if type(tj) == "function" then tj = storefunction(tj) - flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_code),"]") + flush(currentcatcodes,"[",newtoken(tj,lua_call_code),"]") else flush(currentcatcodes,"[",tj,"]") end @@ -803,7 +857,7 @@ local function writer(parent,command,...) -- already optimized before call local tj = ti[j] if type(tj) == "function" then tj = storefunction(tj) - flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_code),j == tn and "]" or ",") + flush(currentcatcodes,"[",newtoken(tj,lua_call_code),j == tn and "]" or ",") else if j == tn then flush(currentcatcodes,tj,"]") @@ -816,7 +870,7 @@ local function writer(parent,command,...) -- already optimized before call elseif typ == "function" then -- todo: ctx|prt|texcatcodes ti = storefunction(ti) - flush(currentcatcodes,"{",newtoken(ti,lua_expandable_call_code),"}") + flush(currentcatcodes,"{",newtoken(ti,lua_call_code),"}") elseif typ == "boolean" then if ti then flushdirect(currentcatcodes,"\r") @@ -972,7 +1026,7 @@ local caller = function(parent,f,a,...) elseif typ == "function" then -- ignored: a ... f = storefunction(f) - flush(currentcatcodes,"{",newtoken(f,lua_expandable_call_code),"}") + flush(currentcatcodes,"{",newtoken(f,lua_call_code),"}") elseif typ == "boolean" then if f then if a ~= nil then @@ -1083,6 +1137,14 @@ statistics.register("traced context", function() end end) +-- The cmd names were synchronized with the normal call cmd names. + +local luacalls = { -- luatex luametatex + lua_expandable_call = true, -- normal + lua_call = true, -- protected normal + lua_protected_call = true, -- protected +} + local function userdata(argument) if isnode(argument) then return formatters["<< %s node %i>>"](nodes.nodecodes[argument.id],tonut(argument)) @@ -1092,8 +1154,7 @@ local function userdata(argument) -- return formatters["<<\\%s>>"](csname) return formatters["\\%s"](csname) end - local cmdname = argument.cmdname - if cmdname == "lua_expandable_call" or cmdname == "lua_call" then + if luacall[argument.cmdname] then return "<<function>>" -- argument.mode end return "<<token>>" @@ -1735,8 +1796,10 @@ do if CONTEXTLMTXMODE > 0 then - local prefixcodes = tex.getprefixvalues() - tex.prefixcodes = table.swapped(prefixcodes,prefixcodes) -- utilities.storage.allocate() + -- also elsewhere + + local flagcodes = tex.getflagvalues() + tex.flagcodes = table.swapped(flagcodes,flagcodes) -- utilities.storage.allocate() end diff --git a/tex/context/base/mkiv/cldf-ini.mkiv b/tex/context/base/mkiv/cldf-ini.mkiv index 0ec2d408b..70c9c12e3 100644 --- a/tex/context/base/mkiv/cldf-ini.mkiv +++ b/tex/context/base/mkiv/cldf-ini.mkiv @@ -1,8 +1,8 @@ %D \module -%D [ file=cldf-ini, -%D version=2010.10.19,, -%D title=\CONTEXT\ \LUA\ Document Functions, -%D subtitle=Initialization, +%D [ file=cldf-int, +%D version=2019.01.01, +%D title=\CONTEXT\ Data Macros, +%D subtitle=Integer, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] diff --git a/tex/context/base/mkiv/cldf-int.mkxl b/tex/context/base/mkiv/cldf-int.mkxl index 603c22afc..a564afc80 100644 --- a/tex/context/base/mkiv/cldf-int.mkxl +++ b/tex/context/base/mkiv/cldf-int.mkxl @@ -1,8 +1,8 @@ %D \module -%D [ file=mult-ini, -%D version=2008.10.22, % 1996.06.01, -%D title=\CONTEXT\ Multilingual Macros, -%D subtitle=Initialization, +%D [ file=cldf-int, +%D version=2019.01.01, +%D title=\CONTEXT\ Data Macros, +%D subtitle=Integer, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] @@ -15,17 +15,20 @@ \registerctxluafile{cldf-int}{autosuffix} +%D These are user commands so we don't add any protection against overloading +%D here. + \unprotect -\unexpanded\def\newluatable#1{\clf_newluatable#1\atendofgrouped{\disposeluatable#1}} -\unexpanded\def\useluatable#1{\clf_useluatable#1\atendofgrouped{\disposeluatable#1}} +\permanent\protected\def\newluatable#1{\clf_newluatable#1\atendofgrouped{\disposeluatable#1}} +\permanent\protected\def\useluatable#1{\clf_useluatable#1\atendofgrouped{\disposeluatable#1}} \installcorenamespace{datavalue} -\unexpanded\def\setdatavalue#1#2% #2 is a number (expression) - {\expandafter\letdatacode\csname\??datavalue#1\endcsname\numexpr#2\relax} +\permanent\protected\def\setdatavalue#1#2% #2 is a number (expression) + {\expandafter\integerdef\csname\??datavalue#1\endcsname\numexpr#2\relax} -\def\getdatavalue#1{\begincsname\??datavalue#1\endcsname} -\def\thedatavalue#1{\the\begincsname\??datavalue#1\endcsname} +\permanent\def\getdatavalue#1{\begincsname\??datavalue#1\endcsname} +\permanent\def\thedatavalue#1{\the\begincsname\??datavalue#1\endcsname} \protect \endinput diff --git a/tex/context/base/mkiv/cldf-lmt.lmt b/tex/context/base/mkiv/cldf-lmt.lmt index 9889131a5..f3121eadc 100644 --- a/tex/context/base/mkiv/cldf-lmt.lmt +++ b/tex/context/base/mkiv/cldf-lmt.lmt @@ -57,7 +57,7 @@ local skip_code = values.skip local boolean_code = values.boolean local float_code = values.float -local global_code = tex.prefixcodes.global +local global_code = tex.flagcodes.global local context = context @@ -428,8 +428,8 @@ local slots = { } local nofslots = 0 local nofgrouped = 0 -local getdata = tokens.getdata -local setdata = tokens.setdata +local getinteger = tokens.getinteger +local setinteger = tokens.setinteger local report = logs.reporter("lua table") @@ -448,7 +448,7 @@ local function newluatable(name,mt,dispose) t = nofgrouped end if mt then - mt = getdata(name) + mt = getinteger(name) if mt then mt = grouped[mt] if mt then @@ -457,7 +457,7 @@ local function newluatable(name,mt,dispose) end end grouped[t] = g - setdata(name,t) + setinteger(name,t) -- This is the slow part. Doing this at the TeX end saved 10% runtime. I'll -- think of something that we can set it at the Lua end. if dispose then @@ -466,7 +466,7 @@ local function newluatable(name,mt,dispose) end local function disposeluatable(name) - local t = getdata(name) + local t = getinteger(name) local g = grouped[t] if g then grouped[t] = false @@ -476,7 +476,7 @@ local function disposeluatable(name) end local function setluatable(name,kv) - local t = getdata(name) + local t = getinteger(name) local g = grouped[t] if g and kv then for k, v in next, kv do @@ -486,7 +486,7 @@ local function setluatable(name,kv) end local function getfromluatable(name,k) - local t = getdata(name) + local t = getinteger(name) local g = grouped[t] if g then local v = g[k] @@ -505,7 +505,7 @@ local function getfromluatable(name,k) end local function idxfromluatable(name,k) - local t = getdata(name) + local t = getinteger(name) local g = grouped[t] if g then local v = g[k] @@ -516,7 +516,7 @@ local function idxfromluatable(name,k) end local function getluatable(name,k) - local t = getdata(name) + local t = getinteger(name) local g = grouped[t] if g then return g @@ -524,7 +524,7 @@ local function getluatable(name,k) end local function inspectluatable(name) - local t = getdata(name) + local t = getinteger(name) local g = grouped[t] if g then report("%s", serialize(g,'[grouped slot ' .. t .. ']')) diff --git a/tex/context/base/mkiv/cldf-scn.lua b/tex/context/base/mkiv/cldf-scn.lua index fa7ff042c..84b2957ab 100644 --- a/tex/context/base/mkiv/cldf-scn.lua +++ b/tex/context/base/mkiv/cldf-scn.lua @@ -77,7 +77,8 @@ function interfaces.implement(specification) if knownscanner(name) and not specification.overload then report("warning: interface scanner %a is overloaded",name) end - register(name,scanner,specification.protected,specification.public,specification.usage) + -- register(name,scanner,specification.protected,specification.public,specification.usage) + register(name,scanner,specification) if private then return end diff --git a/tex/context/base/mkiv/colo-ini.mkiv b/tex/context/base/mkiv/colo-ini.mkiv index 46931d886..7faaa5c5a 100644 --- a/tex/context/base/mkiv/colo-ini.mkiv +++ b/tex/context/base/mkiv/colo-ini.mkiv @@ -1107,9 +1107,8 @@ %D \stopregistercolor %D \stoptyping -\let\maintextcolor \empty -\def\defaulttextcolor {black} -\def\s!themaintextcolor{themaintextcolor} +\let\maintextcolor \empty +\def\defaulttextcolor{black} \unexpanded\def\inheritmaintextcolor {\ifx\maintextcolor\empty\else\colo_helpers_activate\maintextcolor\fi} diff --git a/tex/context/base/mkiv/colo-ini.mkxl b/tex/context/base/mkiv/colo-ini.mkxl index 72ee3db32..e8ea71b8d 100644 --- a/tex/context/base/mkiv/colo-ini.mkxl +++ b/tex/context/base/mkiv/colo-ini.mkxl @@ -11,9 +11,6 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D We need to clean this up further but first we have to make sure that mkiv -%D code works ok. - \writestatus{loading}{ConTeXt Color Macros / Initialization} %D Todo: move color space in color attribute (last two bits) @@ -98,16 +95,7 @@ %D \stopcombination %D \stoptyping -\unexpanded\def\definecolor {\dodoubleargument\colo_basics_define} -\unexpanded\def\defineglobalcolor {\dodoubleargument\colo_basics_define_global} -\unexpanded\def\defineprocesscolor {\dotripleargument\colo_basics_define_process} -\unexpanded\def\definenamedcolor {\dodoubleargument\colo_basics_define_named} -\unexpanded\def\definespotcolor {\dotripleargument\colo_basics_define_spot} -\unexpanded\def\definemultitonecolor {\doquadrupleempty\colo_basics_define_multitone} -\unexpanded\def\definetransparency {\dodoubleargument\colo_basics_define_transpancy} -\unexpanded\def\defineglobaltransparency{\dodoubleargument\colo_basics_define_transpancy_global} - -\unexpanded\def\loadfoundcolorsetfile#1#2% name foundname / not a user command +\permanent\protected\def\loadfoundcolorsetfile#1#2% name foundname / not a user command {\startreadingfile \startcolorset[#1]% \input{#2}% @@ -135,11 +123,11 @@ \let\g_color\empty \let\g_style\empty -\unexpanded\def\switchtocolor[#1]{\begincsname#1\endcsname} +\protected\def\switchtocolor[#1]{\begincsname#1\endcsname} % transparency -\unexpanded\def\transparent[#1]% +\permanent\protected\def\transparent[#1]% {\bgroup \edef\currenttransparencyname{#1}% % the \relax catches a non existent csname @@ -150,7 +138,7 @@ \fi \let\nexttoken} -\unexpanded\def\starttransparent[#1]%$ +\permanent\protected\def\starttransparent[#1]%$ {\begingroup \edef\currenttransparencyname{#1}% \ifx\currenttransparencyname\v!reset @@ -159,12 +147,12 @@ \begincsname\??transparencysetter\currenttransparencyname\endcsname\relax \fi} -\unexpanded\def\stoptransparent +\permanent\protected\def\stoptransparent {\endgroup} % color -\unexpanded\def\coloronly[#1]% +\permanent\protected\def\coloronly[#1]% {\bgroup \edef\currentcolorname{#1}% \ifempty\currentcolorprefix @@ -174,7 +162,7 @@ \fi \let\nexttoken} -\unexpanded\def\startcoloronly[#1]%$ +\permanent\protected\def\startcoloronly[#1]%$ {\begingroup \edef\currentcolorname{#1}% \ifempty\currentcolorprefix @@ -183,12 +171,12 @@ \colo_helpers_activate_yes_only \fi} -\unexpanded\def\stopcoloronly +\permanent\protected\def\stopcoloronly {\endgroup} % color + transparency -\unexpanded\def\color[#1]% +\permanent\protected\def\color[#1]% {\bgroup \edef\currentcolorname{#1}% \ifempty\currentcolorprefix @@ -198,12 +186,12 @@ \fi \let\nexttoken} -\unexpanded\def\graycolor[#1]% +\permanent\protected\def\graycolor[#1]% {\bgroup \colo_helpers_set_model\s!gray\colo_helpers_activate{#1}% \let\nexttoken} -\unexpanded\def\startcolor[#1]%$ +\permanent\protected\def\startcolor[#1]%$ {\begingroup \edef\currentcolorname{#1}% \ifempty\currentcolorprefix @@ -212,24 +200,24 @@ \colo_helpers_activate_yes \fi} -\unexpanded\def\stopcolor +\permanent\protected\def\stopcolor {\endgroup} -\unexpanded\def\colored[#1]% +\permanent\protected\def\colored[#1]% {\bgroup \colo_basics_defined_and_activated{#1}% \let\nexttoken} -\unexpanded\def\fastcolored[#1]#2% +\permanent\protected\def\fastcolored[#1]#2% {\begingroup % is this command still needed? \colo_basics_defined_and_activated{#1}% #2% \endgroup} -\unexpanded\def\directcolored[#1]% +\permanent\protected\def\directcolored[#1]% {\colo_basics_defined_and_activated{#1}} -\unexpanded\def\fastcolor[#1]#2% +\permanent\protected\def\fastcolor[#1]#2% {\begingroup % is this command still needed? \edef\currentcolorname{#1}% \ifempty\currentcolorprefix @@ -240,7 +228,7 @@ #2% \endgroup} -\unexpanded\def\directcolor[#1]% +\permanent\protected\def\directcolor[#1]% {\edef\currentcolorname{#1}% \ifempty\currentcolorprefix \colo_helpers_activate_nop @@ -250,10 +238,10 @@ %D The following command is obsolete: -\unexpanded\def\startcolorpage{\startcolor[\ifempty\maintextcolor\defaulttextcolor\else\maintextcolor\fi]} -\unexpanded\def\stopcolorpage {\stopcolor} +\permanent\protected\def\startcolorpage{\startcolor[\ifempty\maintextcolor\defaulttextcolor\else\maintextcolor\fi]} +\permanent\protected\def\stopcolorpage {\stopcolor} -\unexpanded\def\getcolorattributevalue#1#2% obsolete, use \thecolorattribute instead ... +\permanent\protected\def\getcolorattributevalue#1#2% obsolete, use \thecolorattribute instead ... {\begingroup \colo_helpers_activate{#1}% \normalexpanded{\endgroup\edef\noexpand#2% @@ -264,8 +252,8 @@ %D \macros %D {startcurrentcolor,stopcurrentcolor} -\unexpanded\def\startcurrentcolor{\startcolor[\outercolorname]} -\unexpanded\def\stopcurrentcolor {\stopcolor} +\permanent\protected\def\startcurrentcolor{\startcolor[\outercolorname]} +\permanent\protected\def\stopcurrentcolor {\stopcolor} %D \macros %D {setupcolor} @@ -290,9 +278,9 @@ %D \usecolors[dem] %D \stoptyping -\unexpanded\def\startcolorset[#1]{\clf_startcolorset{#1}} -\unexpanded\def\stopcolorset {\clf_stopcolorset} -\unexpanded\def\usecolors [#1]{\clf_usecolors{#1}} +\permanent\protected\def\startcolorset[#1]{\clf_startcolorset{#1}} +\permanent\protected\def\stopcolorset {\clf_stopcolorset} +\permanent\protected\def\usecolors [#1]{\clf_usecolors{#1}} \let\setupcolor\usecolors @@ -351,7 +339,7 @@ \newcount\c_colo_nesting -\unexpanded\def\pushcolor[#1]% +\permanent\protected\def\pushcolor[#1]% {\global\advance\c_colo_nesting\plusone \expandafter\edef\csname\??colorstack\number\c_colo_nesting\endcsname {\c_attr_colormodel \the\c_attr_colormodel @@ -360,7 +348,7 @@ \relax}% stack \colo_helpers_activate{#1}} -\unexpanded\def\popcolor +\permanent\protected\def\popcolor {\csname\??colorstack\number\c_colo_nesting\endcsname \global\advance\c_colo_nesting\minusone} @@ -369,11 +357,11 @@ \newcount\c_colo_saved_attribute_color \newcount\c_colo_saved_attribute_transparency -\unexpanded\def\savecolor +\permanent\protected\def\savecolor {\c_colo_saved_attribute_color \c_attr_color \c_colo_saved_attribute_transparency\c_attr_transparency} -\unexpanded\def\restorecolor +\permanent\protected\def\restorecolor {\c_attr_color \c_colo_saved_attribute_color \c_attr_transparency\c_colo_saved_attribute_transparency} @@ -443,8 +431,10 @@ \let\c_colo_palet\relax \def\colo_palet_allocate#1% - {\expandafter\let \csname\??paletlist#1\endcsname\empty - \expandafter\newcount\csname\??paletsize#1\endcsname} + {\expandafter\let\csname\??paletlist#1\endcsname\empty + \ifcsname\??paletsize#1\endcsname\else + \expandafter\newcount\csname\??paletsize#1\endcsname + \fi} \def\colo_palet_prepare#1% {\edef\colo_palet_name{#1}% @@ -453,15 +443,16 @@ \else \colo_palet_allocate\colo_palet_name \fi - \edef\m_colo_palet{\begincsname\??paletlist\colo_palet_name\endcsname}% - \expandafter\let\expandafter\c_colo_palet\csname\??paletsize\colo_palet_name\endcsname} + \enforced\expandafter\let\expandafter\c_colo_palet\csname\??paletsize\colo_palet_name\endcsname + \edef\m_colo_palet{\begincsname\??paletlist\colo_palet_name\endcsname}} \def\colo_palet_extend#1% {\addtocommalist{#1}\m_colo_palet \expandafter\let\csname\??paletlist\colo_palet_name\endcsname\m_colo_palet + %\advance\csname\??paletsize\colo_palet_name\endcsname\plusone \advance\c_colo_palet\plusone} -\unexpanded\def\doifelsecolorpalet#1% +\permanent\protected\def\doifelsecolorpalet#1% {\ifcsname\??paletlist#1\endcsname \expandafter\firstoftwoarguments \else @@ -471,41 +462,75 @@ \let\paletlist\empty \let\paletsize\!!zerocount -\unexpanded\def\getpaletlist[#1]% +\permanent\protected\def\getpaletlist[#1]% {\edef\paletlist{\begincsname\??paletlist#1\endcsname}} -\unexpanded\def\getpaletsize[#1]% +\permanent\protected\def\getpaletsize[#1]% {\ifcsname\??paletsize#1\endcsname \edef\paletsize{\the\lastnamedcs}% \else \let\paletsize\!!zerocount \fi} -\unexpanded\def\definepalet - {\dotripleempty\colo_palets_define} - -\def\colo_palets_define - {\ifthirdargument - \expandafter\colo_palets_define_b - \else +%% \protected\def\definepalet +%% {\dotripleempty\colo_palets_define} +%% +%% \def\colo_palets_define +%% {\ifthirdargument +%% \expandafter\colo_palets_define_b +%% \else +%% \expandafter\colo_palets_define_a +%% \fi} +%% +%% \protected\def\colo_palets_define_a[#1][#2][#3]% +%% \protected\def\colo_palets_define_b[#1][#2][#3]% + +\permanent\tolerant\protected\def\definepalet[#1]#*[#2]#*[#3]% + {\ifarguments + \expandafter\gobblethreearguments + \or + \expandafter\gobblethreearguments + \or \expandafter\colo_palets_define_a - \fi} + \or + \expandafter\colo_palets_define_b + \fi{#1}{#2}{#3}} -\unexpanded\def\colo_palets_define_a[#1][#2][#3]% +\protected\def\colo_palets_define_a#1#2#3% {\colo_palet_prepare{#1}% \ifcondition\validassignment{#2}% \setevalue{\??colorpaletspecification#1}{#2}% \processcommalist[#2]{\colo_palets_define_one{#1}}% \orelse\ifcsname\??colorpaletspecification#2\endcsname - \normalexpanded{\colo_palets_define[#1][\lastnamedcs]}% + \normalexpanded{\colo_palets_define_b{#1}{\lastnamedcs}\empty}% \fi} -\unexpanded\def\colo_palets_define_b[#1][#2][#3]% +\protected\def\colo_palets_define_b#1#2#3% {\colo_palet_prepare{#1}% \setevalue{\??colorpaletspecification#1}{#2}% \colo_palet_extend{#2}% \colo_palets_define_assign{#1}{#2}{#3}} +% % or, it being not that critital, just this +% +% \permanent\tolerant\protected\def\definepalet[#1]#*[#2]#*[#3]% +% {\ifarguments +% \or +% \or +% \colo_palet_prepare{#1}% +% \ifcondition\validassignment{#2}% +% \setevalue{\??colorpaletspecification#1}{#2}% +% \processcommalist[#2]{\colo_palets_define_one{#1}}% +% \orelse\ifcsname\??colorpaletspecification#2\endcsname +% \normalexpanded{\colo_palets_define_b{#1}{\lastnamedcs}{}}% +% \fi +% \or +% \colo_palet_prepare{#1}% +% \setevalue{\??colorpaletspecification#1}{#2}% +% \colo_palet_extend{#2}% +% \colo_palets_define_assign{#1}{#2}{#3}% +% \fi} + \def\colo_palets_define_one#1#2% get rid of { } {\ifcondition\validassignment{#2}% catch empty entries \colo_palets_define_two{#1}[#2]% @@ -539,12 +564,9 @@ \newtoks\everysetuppalet -\unexpanded\def\setuppalet - {\dosingleempty\colo_palets_setup} - % \newtoks\t_colo_prefix % used in mp interface -\def\colo_palets_setup[#1]% +\permanent\tolerant\protected\def\setuppalet[#1]% {\edef\currentcolorpalet{#1}% \ifempty\currentcolorpalet % seems to be a reset @@ -631,10 +653,10 @@ %D %D These speak for themselves. See \type {colo-ext} for usage. -\unexpanded\def\negatecolorcomponent#1% #1 = \macro +\permanent\protected\def\negatecolorcomponent#1% #1 = \macro {\edef#1{\clf_negatecolorcomponent{#1}}} -\def\negatedcolorcomponent#1% +\permanent\def\negatedcolorcomponent#1% {\clf_negatecolorcomponent{#1}} %D \macros @@ -670,7 +692,7 @@ % draw btex test etex withprescript \mptexcolor{blue} ; % \stopMPpage -\unexpanded\def\setcolormodel[#1]% % beware, \setupcolors will overload this, so this one is +\permanent\protected\def\setcolormodel[#1]% % beware, \setupcolors will overload this, so this one is {\colo_helpers_set_model{#1}} % only for local usage \def\colo_helpers_set_model#1% direct @@ -790,12 +812,12 @@ \let\dousecolorparameter\colo_helpers_activate -\unexpanded\def\dousecolorhashparameter#1#2% +\permanent\protected\def\dousecolorhashparameter#1#2% {\ifcsname#1#2\endcsname \expandafter\dousecolorparameter\csname#1#2\endcsname \fi} -\unexpanded\def\dousecurrentcolorparameter +\permanent\protected\def\dousecurrentcolorparameter {\let\currentcolorname\currentcolorparameter % maybe only when success \ifcsname\??colorsetter\currentcolorprefix\currentcolorparameter\endcsname \lastnamedcs @@ -807,7 +829,7 @@ \let\dosetcolorattribute\dousecolorhashparameter % for a while -\unexpanded\def\deactivatecolor % sort of public but a bad name +\permanent\protected\def\deactivatecolor % sort of public but a bad name {\let\currentcolorname\s!black \c_attr_color \attributeunsetvalue \c_attr_transparency\attributeunsetvalue} @@ -833,99 +855,78 @@ \newcount\c_colo_protection -\unexpanded\def\startprotectedcolors - {\advance\c_colo_protection\plusone} - -\unexpanded\def\stopprotectedcolors - {\advance\c_colo_protection\minusone} +\permanent\protected\def\startprotectedcolors{\advance\c_colo_protection\plusone } +\permanent\protected\def\stopprotectedcolors {\advance\c_colo_protection\minusone} -\def\colo_basics_define[#1][#2]% -% {\edef\m_colo_old{#1}% -% \edef\m_colo_new{#2}% -% \ifx\m_colo_old\m_colo_new +\permanent\tolerant\protected\def\definecolor[#1]#*[#2]% {\iftok{#1}{#2}% % maybe a warning \else \clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax \colo_basics_synchronize{#1}% \ifcase\c_colo_protection - \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}% + \protected\setvalue{#1}{\colo_helpers_activate{#1}}% \fi \fi} -\def\colo_basics_define_global[#1][#2]% -% {\edef\m_colo_old{#1}% -% \edef\m_colo_new{#2}% -% \ifx\m_colo_old\m_colo_new +\permanent\tolerant\protected\def\defineglobalcolor[#1]#*[#2]% {\iftok{#1}{#2}% % maybe a warning \else \clf_defineprocesscolorglobal{#1}{#2}\v_colo_freeze_state\relax \colo_basics_synchronize{#1}% \ifcase\c_colo_protection - \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}% + \protected\setgvalue{#1}{\colo_helpers_activate{#1}}% \fi \fi} -\let\colo_basics_define_named\colo_basics_define - -\def\dodefinefastcolor[#1][#2]% still not fast but ok (might change) - {\clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax - \colo_basics_synchronize{#1}% - \ifcase\c_colo_protection - \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}% - \fi} +\let\definenamedcolor\definecolor \def\colo_basics_defined_and_activated#1% {\clf_defineprocesscolordummy{#1}% we could pass dummy here too \colo_basics_synchronize{\v_colo_dummy_name}% \colo_helpers_activate_dummy} -\def\colo_basics_define_process - {\ifthirdargument - \expandafter\colo_basics_define_process_yes - \else - \expandafter\colo_basics_define_process_nop - \fi} - -\def\colo_basics_define_process_yes[#1][#2][#3]% - {\clf_defineprocesscolorlocal{#1}{\processcolorcomponents{#2},#3}\v_colo_freeze_state\relax - \colo_basics_synchronize{#1}% - \ifcase\c_colo_protection - \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}% +\permanent\tolerant\protected\def\defineprocesscolor[#1]#*[#2]#*[#3]% + {\ifarguments\or + \colo_basics_define_process_wrapup{#1}\empty + \or + \colo_basics_define_process_wrapup{#1}{#2}% + \or % we could just pass #3 to clf_... also when it's empty ... todo after split + \colo_basics_define_process_wrapup{#1}{\processcolorcomponents{#2},#3}% \fi} -\def\colo_basics_define_process_nop[#1][#2][#3]% +\def\colo_basics_define_process_wrapup#1#2% {\clf_defineprocesscolorlocal{#1}{#2}\v_colo_freeze_state\relax \colo_basics_synchronize{#1}% \ifcase\c_colo_protection - \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}% + \protected\setvalue{#1}{\colo_helpers_activate{#1}}% \fi} %D Spotcolors used setxvalue but that messes up currentcolor and probably no global %D is needed either but they are global at the lua end (true argument) so we keep %D that if only because spot colors often are a document wide property -\def\colo_basics_define_spot[#1][#2][#3]% +\permanent\tolerant\protected\def\definespotcolor[#1]#*[#2]#*[#3]% {\clf_definespotcolorglobal{#1}{#2}{#3}% \colo_basics_synchronize{#1}% \ifcase\c_colo_protection - \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}% + \protected\setgvalue{#1}{\colo_helpers_activate{#1}}% \fi} -\def\colo_basics_define_multitone[#1][#2][#3][#4]% +\permanent\tolerant\protected\def\definemultitonecolor[#1]#*[#2]#*[#3]#*[#4]% {\clf_definemultitonecolorglobal{#1}{#2}{#3}{#4}% \colo_basics_synchronize{#1}% \ifcase\c_colo_protection - \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}% + \protected\setgvalue{#1}{\colo_helpers_activate{#1}}% \fi} %D Transparencies (only): -\def\colo_basics_define_transpancy[#1][#2]% +\permanent\tolerant\protected\def\definetransparency[#1]#*[#2]% {\clf_definetransparency{#1}{#2}} -\def\colo_basics_define_transpancy_global[#1][#2]% +\permanent\tolerant\protected\def\defineglobaltransparency[#1]#*[#2]% {\clf_definetransparencyglobal{#1}{#2}} % A goodie that replaces the startMPcolor hackery @@ -971,10 +972,7 @@ % % because the fractional definition results in a new definition. -\unexpanded\def\defineintermediatecolor - {\dotripleempty\colo_basics_define_intermediate} - -\def\colo_basics_define_intermediate[#1][#2][#3]% \dotripleempty adds {} inside [] +\permanent\tolerant\protected\def\defineintermediatecolor[#1]#*[#2]#*[#3] {\colo_basics_define_intermediate_indeed[#1][#2][#3]} \def\colo_basics_define_intermediate_indeed[#1][#2,#3,#4][#5]% @@ -989,7 +987,7 @@ \v_colo_freeze_state \relax \colo_basics_synchronize{#1}% - \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}} + \protected\setvalue{#1}{\colo_helpers_activate{#1}}} %D Here is a more efficient helper for pgf: %D @@ -1044,7 +1042,7 @@ %D Switching to a color is done by means of the following command. Later on we will %D explain the use of palets. We define ourselves a color conditional first. -\def\doifelsecolor#1% +\permanent\def\doifelsecolor#1% {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname \expandafter\firstoftwoarguments \orelse\ifcsname\??colorattribute#1\endcsname @@ -1055,7 +1053,7 @@ \let\doifcolorelse\doifelsecolor -\def\doifcolor#1% +\permanent\def\doifcolor#1% {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname \expandafter\firstofoneargument \orelse\ifcsname\??colorattribute#1\endcsname @@ -1088,14 +1086,13 @@ %D \stopregistercolor %D \stoptyping -\let\maintextcolor \empty -\def\defaulttextcolor {black} -\def\s!themaintextcolor{themaintextcolor} +\let\maintextcolor \empty +\def\defaulttextcolor{black} -\unexpanded\def\inheritmaintextcolor +\permanent\protected\def\inheritmaintextcolor {\ifempty\maintextcolor\else\colo_helpers_activate\maintextcolor\fi} -\unexpanded\def\onlyinheritmaintextcolor +\permanent\protected\def\onlyinheritmaintextcolor {\ifempty\maintextcolor \deactivatecolor \else @@ -1113,9 +1110,8 @@ \colo_helpers_activate\maintextcolor \clf_registermaintextcolor\thecolorattribute\maintextcolor\relax} -\unexpanded\def\starttextcolor[#1]% - {\doifsomething{#1} - {\colo_helpers_switch_to_maintextcolor{#1}}} +\permanent\protected\def\starttextcolor[#1]% + {\doifsomething{#1}{\colo_helpers_switch_to_maintextcolor{#1}}} \let\stoptextcolor\relax @@ -1140,16 +1136,6 @@ \def\colo_helpers_inherited_direct_ts#1{\ifcsname\??transparencysetter #1\endcsname\lastnamedcs\fi} \def\colo_helpers_inherited_direct_ta#1{\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\!!zerocount\fi} -% %def\colo_helpers_inherited_palet_cs#1#2{\csname\??colorsetter \ifcsname\??colorsetter \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname} -% %def\colo_helpers_inherited_palet_ca#1#2{\csname\??colorattribute \ifcsname\??colorattribute \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname} -% %def\colo_helpers_inherited_palet_ts#1#2{\csname\??transparencysetter \ifcsname\??transparencysetter \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname} -% %def\colo_helpers_inherited_palet_ta#1#2{\csname\??transparencyattribute\ifcsname\??transparencyattribute\??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname} -% -% \def\colo_helpers_inherited_palet_cs#1#2{\ifcsname\??colorsetter \??colorpalet#1:#2\endcsname\lastnamedcs\fi} -% \def\colo_helpers_inherited_palet_ca#1#2{\ifcsname\??colorattribute \??colorpalet#1:#2\endcsname\lastnamedcs\else\!!zerocount\fi} -% \def\colo_helpers_inherited_palet_ts#1#2{\ifcsname\??transparencysetter \??colorpalet#1:#2\endcsname\lastnamedcs} -% \def\colo_helpers_inherited_palet_ta#1#2{\ifcsname\??transparencyattribute\??colorpalet#1:#2\endcsname\lastnamedcs\else\!!zerocount\fi} - \let\colo_helpers_set_value\setvalue \appendtoks @@ -1202,20 +1188,20 @@ %D Low level defs: -\unexpanded\def\colordefalc#1#2{\setevalue{\??colorattribute #1}{#2}\setvalue {\??colorsetter #1}{\c_attr_color #2 }} -\unexpanded\def\colordefagc#1#2{\setxvalue{\??colorattribute #1}{#2}\setgvalue{\??colorsetter #1}{\c_attr_color #2 }} % was not g -\unexpanded\def\colordefalt#1#2{\setevalue{\??transparencyattribute#1}{#2}\setvalue {\??transparencysetter#1}{\c_attr_transparency#2 }} -\unexpanded\def\colordefagt#1#2{\setxvalue{\??transparencyattribute#1}{#2}\setgvalue{\??transparencysetter#1}{\c_attr_transparency#2 }} +\permanent\protected\def\colordefalc#1#2{\setevalue{\??colorattribute #1}{#2}\setvalue {\??colorsetter #1}{\c_attr_color #2 }} +\permanent\protected\def\colordefagc#1#2{\setxvalue{\??colorattribute #1}{#2}\setgvalue{\??colorsetter #1}{\c_attr_color #2 }} % was not g +\permanent\protected\def\colordefalt#1#2{\setevalue{\??transparencyattribute#1}{#2}\setvalue {\??transparencysetter#1}{\c_attr_transparency#2 }} +\permanent\protected\def\colordefagt#1#2{\setxvalue{\??transparencyattribute#1}{#2}\setgvalue{\??transparencysetter#1}{\c_attr_transparency#2 }} -\unexpanded\def\colordefflc#1#2{\setvalue {\??colorattribute #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter #1}{\colo_helpers_inherited_current_cs{#2}}} -\unexpanded\def\colordeffgc#1#2{\setgvalue{\??colorattribute #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter #1}{\colo_helpers_inherited_current_cs{#2}}} -\unexpanded\def\colordefflt#1#2{\setvalue {\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setvalue {\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}} -\unexpanded\def\colordeffgt#1#2{\setgvalue{\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setgvalue{\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}} +\permanent\protected\def\colordefflc#1#2{\setvalue {\??colorattribute #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter #1}{\colo_helpers_inherited_current_cs{#2}}} +\permanent\protected\def\colordeffgc#1#2{\setgvalue{\??colorattribute #1}{\colo_helpers_inherited_current_ca{#2}}\setvalue {\??colorsetter #1}{\colo_helpers_inherited_current_cs{#2}}} +\permanent\protected\def\colordefflt#1#2{\setvalue {\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setvalue {\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}} +\permanent\protected\def\colordeffgt#1#2{\setgvalue{\??transparencyattribute#1}{\colo_helpers_inherited_current_ta{#2}}\setgvalue{\??transparencysetter#1}{\colo_helpers_inherited_current_ts{#2}}} -\unexpanded\def\colordefrlc #1{\localundefine {\??colorattribute #1}\localundefine {\??colorsetter #1}} -\unexpanded\def\colordefrgc #1{\globalundefine{\??colorattribute #1}\globalundefine{\??colorsetter #1}} -\unexpanded\def\colordefrlt #1{\localundefine {\??transparencyattribute#1}\localundefine {\??transparencysetter#1}} -\unexpanded\def\colordefrgt #1{\globalundefine{\??transparencyattribute#1}\globalundefine{\??transparencysetter#1}} +\permanent\protected\def\colordefrlc #1{\localundefine {\??colorattribute #1}\localundefine {\??colorsetter #1}} +\permanent\protected\def\colordefrgc #1{\globalundefine{\??colorattribute #1}\globalundefine{\??colorsetter #1}} +\permanent\protected\def\colordefrlt #1{\localundefine {\??transparencyattribute#1}\localundefine {\??transparencysetter#1}} +\permanent\protected\def\colordefrgt #1{\globalundefine{\??transparencyattribute#1}\globalundefine{\??transparencysetter#1}} %D \macros %D {colorvalue, grayvalue} @@ -1241,71 +1227,54 @@ \let\colorformatseparator\space -\def\MPcolor#1% +\permanent\def\MPcolor#1% {\clf_mpcolor \c_attr_colormodel \colo_helpers_inherited_current_ca{#1} % \colo_helpers_inherited_current_ta{#1} } -\def\MPcoloronly#1% +\permanent\def\MPcoloronly#1% {\clf_mpcolor \c_attr_colormodel \colo_helpers_inherited_current_ca{#1} % \zerocount} -\def\MPtransparency#1% +\permanent\def\MPtransparency#1% {\clf_mpcolor \zerocount \zerocount \colo_helpers_inherited_current_ta{#1} } -\def\MPoptions#1% +\permanent\def\MPoptions#1% {\clf_mpoptions \c_attr_colormodel \colo_helpers_inherited_current_ca{#1} % \colo_helpers_inherited_current_ta{#1} } -\def\thecolormodelattribute {\the\c_attr_colormodel} +\permanent\def\thecolormodelattribute {\the\c_attr_colormodel} -\def\rawcolorattribute #1{\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi} -\def\rawtransparencyattribute#1{\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi} +\permanent\def\rawcolorattribute #1{\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi} +\permanent\def\rawtransparencyattribute#1{\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi} -\def\thecolorattribute #1{\number\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi} -\def\thetransparencyattribute#1{\number\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi} - -% \def\internalspotcolorname #1{\clf_spotcolorname \thecolorattribute{#1} } -% \def\internalspotcolorparent #1{\clf_spotcolorparent\thecolorattribute{#1} } -% \def\internalspotcolorsize #1{\clf_spotcolorvalue \thecolorattribute{#1} } -% -% \def\colorcomponents #1{\clf_colorcomponents \thecolorattribute {#1} } -% \def\transparencycomponents #1{\clf_transparencycomponents\thetransparencyattribute{#1} } -% \def\processcolorcomponents #1{\clf_processcolorcomponents\thecolorattribute {#1} } -% -% \def\colorvalue #1{\clf_formatcolor\thecolorattribute{#1}{\colorformatseparator}} -% \def\grayvalue #1{\clf_formatgray \thecolorattribute{#1}{\colorformatseparator}} -% -% \def\doifelseblack #1{\clf_doifelseblack\thecolorattribute{#1} } -% \def\doifelsedrawingblack {\clf_doifelsedrawingblack} -% -% \let\doifblackelse \doifelseblack -% \let\doifdrawingblackelse \doifelsedrawingblack +\permanent\def\thecolorattribute #1{\number\ifcsname\??colorattribute \currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??colorattribute #1\endcsname\lastnamedcs\else\zerocount\fi} +\permanent\def\thetransparencyattribute#1{\number\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\lastnamedcs\orelse\ifcsname\??transparencyattribute#1\endcsname\lastnamedcs\else\zerocount\fi} -\def\internalspotcolorname #1{\clf_spotcolorname \rawcolorattribute{#1}} -\def\internalspotcolorparent #1{\clf_spotcolorparent\rawcolorattribute{#1}} -\def\internalspotcolorsize #1{\clf_spotcolorvalue \rawcolorattribute{#1}} +\permanent\def\internalspotcolorname #1{\clf_spotcolorname \rawcolorattribute{#1}} +\permanent\def\internalspotcolorparent #1{\clf_spotcolorparent\rawcolorattribute{#1}} +\permanent\def\internalspotcolorsize #1{\clf_spotcolorvalue \rawcolorattribute{#1}} -\def\colorcomponents #1{\clf_colorcomponents \rawcolorattribute {#1}} -\def\transparencycomponents #1{\clf_transparencycomponents\rawtransparencyattribute{#1}} -\def\processcolorcomponents #1{\clf_processcolorcomponents\rawcolorattribute {#1}} +\permanent\def\colorcomponents #1{\clf_colorcomponents \rawcolorattribute {#1}} +\permanent\def\transparencycomponents #1{\clf_transparencycomponents\rawtransparencyattribute{#1}} +\permanent\def\processcolorcomponents #1{\clf_processcolorcomponents\rawcolorattribute {#1}} -\def\colorvalue #1{\clf_formatcolor\rawcolorattribute{#1}{\colorformatseparator}} -\def\grayvalue #1{\clf_formatgray \rawcolorattribute{#1}{\colorformatseparator}} +\permanent\def\colorvalue #1{\clf_formatcolor\rawcolorattribute{#1}{\colorformatseparator}} +\permanent\def\grayvalue #1{\clf_formatgray \rawcolorattribute{#1}{\colorformatseparator}} -\def\doifelseblack #1{\clf_doifelseblack\rawcolorattribute{#1}} -\def\doifelsedrawingblack {\clf_doifelsedrawingblack} +\permanent\def\doifelseblack #1{\clf_doifelseblack\rawcolorattribute{#1}} +\permanent\def\doifelsedrawingblack {\clf_doifelsedrawingblack} -\let\doifblackelse \doifelseblack -\let\doifdrawingblackelse \doifelsedrawingblack +\aliased\let\doifblackelse \doifelseblack +\aliased\let\doifdrawingblackelse \doifelsedrawingblack %D \macros %D {forcecolorhack} @@ -1327,15 +1296,14 @@ % \normal added else fails in metafun manual (leaders do a hard scan) -% \unexpanded\def\forcecolorhack{\leaders\hrule\hskip\zeropoint\relax} % relax is needed ! +% \protected\def\forcecolorhack{\leaders\hrule\hskip\zeropoint\relax} % relax is needed ! % % I really need to sort this out! -\unexpanded\def\forcecolorhack{\leaders\hrule\s!height\zeropoint\s!depth\zeropoint\hskip\zeropoint\relax} % relax is needed ! +\permanent\protected\def\forcecolorhack{\leaders\hrule\s!height\zeropoint\s!depth\zeropoint\hskip\zeropoint\relax} % relax is needed ! -%D We default to the colors defined in \type {colo-imp-rgb} and -%D support both \RGB\ and \CMYK\ output. Transparencies are defined -%D here: +%D We default to the colors defined in \type {colo-imp-rgb} and support both \RGB\ +%D and \CMYK\ output. Transparencies are defined here: \definecolor[black][s=0] \definecolor[white][s=1] diff --git a/tex/context/base/mkiv/cont-log.mkiv b/tex/context/base/mkiv/cont-log.mkiv index 42de5b434..3dbfdc604 100644 --- a/tex/context/base/mkiv/cont-log.mkiv +++ b/tex/context/base/mkiv/cont-log.mkiv @@ -302,7 +302,7 @@ \def\LuaTeX {LuaTeX}% \def\LuajitTeX {LuajitTeX}% \def\LuaMetaTeX{LuaMetaTeX}% - \let\wordboundary\empty + %\let\wordboundary\empty % primitive so we need to promote it to frozen (orjust preroll) \to \everysimplifycommands \protect \endinput diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index ca98de02e..d14c6b9c7 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.09.20 22:59} +\newcontextversion{2020.10.30 22:24} %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 @@ -35,10 +35,16 @@ \ifdefined\w \else \unexpanded\def\w{\mathortext\word\mathword} \fi \appendtoks - \let\t\mathtext - \let\w\mathword + \overloaded\let\t\mathtext + \overloaded\let\w\mathword \to \everymathematics +\pushoverloadmode + % charts needs these + \overloaded\unletfrozen\name % for now + \overloaded\frozen\let\type\type +\popoverloadmode + %D We're done. \protect \endinput diff --git a/tex/context/base/mkiv/cont-run.lua b/tex/context/base/mkiv/cont-run.lua index 3fef61672..eb0e143d5 100644 --- a/tex/context/base/mkiv/cont-run.lua +++ b/tex/context/base/mkiv/cont-run.lua @@ -190,9 +190,15 @@ else end -local preparejob preparejob = function() -- tricky: we need a hook for this +local function processjob() + + tokens.setters.macro("processjob","") -- make a + + environment.initializefilenames() -- todo: check if we really need to pre-prep the filename local arguments = environment.arguments + local suffix = environment.suffix + local filename = environment.filename -- hm, not inputfilename ! environment.lmtxmode = CONTEXTLMTXMODE @@ -207,25 +213,21 @@ local preparejob preparejob = function() -- tricky: we need a hook for this } end - preparejob = function() end - - job.prepare = preparejob + if CONTEXTLMTXMODE then -end + local overloadmode = arguments.overloadmode -job.prepare = preparejob - -local function processjob() - - tokens.setters.macro("processjob","") -- make a - - environment.initializefilenames() -- todo: check if we really need to pre-prep the filename + if overloadmode == "warning" then + overloadmode = 3 -- 5 + elseif overloadmode == "error" then + overloadmode = 4 -- 6 + else + overloadmode = tonumber(overloadmode) or 0 + end - local arguments = environment.arguments - local suffix = environment.suffix - local filename = environment.filename -- hm, not inputfilename ! + tex.set("overloadmode",overloadmode) - preparejob() + end if not filename or filename == "" then -- skip diff --git a/tex/context/base/mkiv/cont-run.mkiv b/tex/context/base/mkiv/cont-run.mkiv index f841ce530..fba9cfaa9 100644 --- a/tex/context/base/mkiv/cont-run.mkiv +++ b/tex/context/base/mkiv/cont-run.mkiv @@ -53,4 +53,16 @@ \unexpanded\def\blocksynctexfile[#1]% {\processcommacommand{#1}\synctexblockfilename} +\ifcase\contextlmtxmode + \def\continuewhenlmtxmode + {\starttext + \startTEXpage[\c!offset=2ex,\c!foregroundstyle=\tttf]% + This file needs \LuaMetaTeX\ and \ConTeXt\ \LMTX.% + \stopTEXpage + \stoptext + \endinput} +\else + \let\continuewhenlmtxmode\relax +\fi + \protect \endinput diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index 45f52a9c5..d22459a4b 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.09.20 22:59} +\edef\contextversion{2020.10.30 22:24} %D Kind of special: diff --git a/tex/context/base/mkiv/context.mkxl b/tex/context/base/mkiv/context.mkxl index dcf733d2e..793fc4d14 100644 --- a/tex/context/base/mkiv/context.mkxl +++ b/tex/context/base/mkiv/context.mkxl @@ -29,7 +29,12 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2020.09.20 22:59} +\edef\contextversion{2020.10.30 22:24} + +%overloadmode 1 % check frozen / warning +%overloadmode 2 % check frozen / error +%overloadmode 3 % check frozen, primitive, permanent / warning +\overloadmode 4 % check frozen, primitive, permanent / error %D Kind of special: @@ -89,10 +94,10 @@ \loadmarkfile{luat-lib} \loadmarkfile{luat-soc} -\loadmarkfile{catc-ini} +\loadmkxlfile{catc-ini} \loadmarkfile{catc-act} \loadmarkfile{catc-def} -\loadmarkfile{catc-ctx} +\loadmkxlfile{catc-ctx} \loadmarkfile{catc-sym} \loadmarkfile{toks-ini} @@ -129,12 +134,12 @@ \loadmarkfile{supp-dir} -\loadmarkfile{char-utf} % generic code (i.e. not much tex) ... could become unic-ini -\loadmarkfile{char-ini} % tex / context specific -\loadmarkfile{char-act} % even more specific +\loadmarkfile{char-utf} +\loadmkxlfile{char-ini} +\loadmarkfile{char-act} -\loadmarkfile{mult-ini} -\loadmarkfile{mult-sys} +\loadmkxlfile{mult-ini} +\loadmkxlfile{mult-sys} \loadmkxlfile{mult-aux} % LMTX \loadmarkfile{mult-def} \loadmarkfile{mult-chk} @@ -146,10 +151,10 @@ \loadmarkfile{toks-aux} -\loadmarkfile{attr-ini} +\loadmkxlfile{attr-ini} \loadmarkfile{core-ini} -\loadmarkfile{core-env} +\loadmkxlfile{core-env} \loadmarkfile{layo-ini} @@ -171,7 +176,7 @@ \loadmarkfile{attr-col} \loadmarkfile{attr-lay} \loadmarkfile{attr-neg} -\loadmarkfile{attr-eff} +\loadmkxlfile{attr-eff} \loadmarkfile{attr-mkr} \loadmarkfile{trac-tex} @@ -193,16 +198,16 @@ \loadmarkfile{typo-inj} -\loadmkvifile{file-syn} +\loadmklxfile{file-syn} \loadmkvifile{file-mod} \loadmarkfile{core-sys} -\loadmarkfile{core-con} +\loadmkxlfile{core-con} \loadmarkfile{cont-fil} \loadmarkfile{regi-ini} -\loadmarkfile{enco-ini} +\loadmkxlfile{enco-ini} \loadmkxlfile{hand-ini} \loadmkxlfile{lang-ini} % LMTX @@ -240,7 +245,7 @@ \loadmkvifile{pack-bck} \loadmarkfile{pack-fen} -\loadmarkfile{lxml-ini} +\loadmkxlfile{lxml-ini} \loadmarkfile{lxml-sor} \loadmkvifile{typo-prc} @@ -253,9 +258,9 @@ \loadmarkfile{strc-doc} \loadmarkfile{strc-num} \loadmarkfile{strc-mar} -\loadmarkfile{strc-sbe} +\loadmkxlfile{strc-sbe} \loadmkvifile{strc-lst} -\loadmarkfile{strc-sec} +\loadmkxlfile{strc-sec} \loadmarkfile{strc-pag} % hm, depends on core-num \loadmarkfile{strc-ren} \loadmarkfile{strc-xml} @@ -284,29 +289,29 @@ \loadmklxfile{strc-itm} % LMTX -\loadmkvifile{strc-con} -\loadmkvifile{strc-des} -\loadmkvifile{strc-enu} +\loadmklxfile{strc-con} +\loadmklxfile{strc-des} +\loadmklxfile{strc-enu} \loadmarkfile{strc-ind} -\loadmarkfile{strc-lab} -\loadmarkfile{strc-syn} +\loadmkxlfile{strc-lab} +\loadmkxlfile{strc-syn} % \loadmarkfile{core-sys} \loadmarkfile{page-var} \loadmkvifile{page-otr} -\loadmarkfile{page-ini} +\loadmkxlfile{page-ini} \loadmarkfile{page-ins} \loadmarkfile{page-fac} \loadmarkfile{page-brk} \loadmarkfile{page-col} \loadmarkfile{page-inf} \loadmarkfile{page-flt} -\loadmarkfile{page-bck} +\loadmkxlfile{page-bck} \loadmarkfile{page-not} \loadmarkfile{page-one} -\loadmarkfile{page-lay} +\loadmkxlfile{page-lay} \loadmkvifile{page-box} \loadmklxfile{page-txt} % LMTX \loadmarkfile{page-sid} % when @@ -371,7 +376,7 @@ \loadmkvifile{font-lib} % way too late but after language \loadmklxfile{font-fil} % LMTX \loadmkvifile{font-var} -\loadmkvifile{font-fea} +\loadmklxfile{font-fea} \loadmklxfile{font-mat} % LMTX \loadmklxfile{font-ini} % LMTX \loadmklxfile{font-sym} % LMTX @@ -391,18 +396,18 @@ \loadmarkfile{typo-tal} \loadmarkfile{typo-par} % par builders (uses fonts) -\loadmarkfile{tabl-com} +\loadmkxlfile{tabl-com} \loadmarkfile{tabl-pln} -\loadmarkfile{tabl-tab} % thrd-tab stripped and merged +\loadmkxlfile{tabl-tab} % thrd-tab stripped and merged \loadmkxlfile{tabl-tbl} % LMTX \loadmkxlfile{tabl-ntb} % LMTX -\loadmarkfile{tabl-nte} -\loadmarkfile{tabl-ltb} -\loadmarkfile{tabl-frm} +\loadmkxlfile{tabl-nte} +\loadmkxlfile{tabl-ltb} +\loadmkxlfile{tabl-frm} \loadmarkfile{tabl-tsp} -\loadmkvifile{tabl-xtb} +\loadmklxfile{tabl-xtb} \loadmarkfile{tabl-mis} \loadmarkfile{typo-lan} @@ -413,7 +418,7 @@ \loadmkxlfile{blob-ini} -\loadmarkfile{trac-vis} +\loadmkxlfile{trac-vis} \loadmarkfile{trac-jus} \loadmarkfile{typo-cln} @@ -430,7 +435,7 @@ \loadmarkfile{typo-drp} \loadmarkfile{typo-fln} \loadmarkfile{typo-sus} -\loadmarkfile{typo-lig} +\loadmkxlfile{typo-lig} \loadmarkfile{typo-chr} \loadmarkfile{typo-rub} \loadmkivfile{typo-fkr} @@ -463,7 +468,7 @@ \loadmarkfile{page-mrk} % depends on mp \loadmarkfile{page-flw} -\loadmarkfile{page-spr} +\loadmkxlfile{page-spr} \loadmarkfile{page-plg} \loadmarkfile{page-str} @@ -474,13 +479,13 @@ %loadmarkfile{anch-snc} % when needed this one will be redone \loadmkxlfile{math-ini} % way after font-pre ! -\loadmarkfile{math-pln} +\loadmkxlfile{math-pln} \loadmarkfile{math-for} \loadmarkfile{math-def} % also saves some meanings -\loadmarkfile{math-ali} +\loadmkxlfile{math-ali} %loadmarkfile{math-arr} \loadmkvifile{math-stc} -\loadmarkfile{math-frc} +\loadmkxlfile{math-frc} \loadmarkfile{math-mis} \loadmarkfile{math-scr} \loadmarkfile{math-int} @@ -498,7 +503,7 @@ \loadmarkfile{strc-mat} \loadmarkfile{chem-ini} -\loadmarkfile{chem-str} +\loadmkxlfile{chem-str} \loadmarkfile{typo-scr} \loadmarkfile{phys-dim} @@ -506,12 +511,12 @@ \loadmarkfile{node-rul} % beware, defined \underbar so after math \loadmkvifile{font-sol} % font solutions -\loadmkvifile{strc-not} +\loadmklxfile{strc-not} \loadmkvifile{strc-lnt} \loadmkivfile{strc-tnt} \loadmkivfile{strc-usr} -\loadmarkfile{pack-com} +\loadmkxlfile{pack-com} \loadmarkfile{typo-del} \loadmarkfile{grph-trf} @@ -519,9 +524,9 @@ \loadmarkfile{grph-fig} \loadmarkfile{grph-raw} \loadmarkfile{grph-rul} -\loadmarkfile{grph-pat} +\loadmkxlfile{grph-pat} -\loadmarkfile{pack-box} +\loadmkxlfile{pack-box} \loadmarkfile{pack-bar} \loadmarkfile{page-app} \loadmarkfile{meta-fig} @@ -611,4 +616,12 @@ \ctxlua{statistics.savefmtstatus("\jobname","\contextversion","context.mkxl","\contextbanner")}% can become automatic \to \everydump +% some day: +% +% \prependtoks +% \overloadmode 255 +% \to \everyjob + +\overloadmode 0 % for now + \errorstopmode \dump \endinput diff --git a/tex/context/base/mkiv/core-con.mkiv b/tex/context/base/mkiv/core-con.mkiv index fd45aed6c..da2648e87 100644 --- a/tex/context/base/mkiv/core-con.mkiv +++ b/tex/context/base/mkiv/core-con.mkiv @@ -223,8 +223,12 @@ %D \showsetup{month} %D \showsetup{MONTH} +\pushoverloadmode + \let\month\monthlong +\popoverloadmode + \unexpanded\def\MONTH #1{\WORD{\clf_monthname\numexpr#1\relax}} \unexpanded\def\MONTHLONG #1{\WORD{\clf_monthname\numexpr#1\relax}} \unexpanded\def\MONTHSHORT#1{\WORD{\clf_monthmnem\numexpr#1\relax}} diff --git a/tex/context/base/mkiv/core-con.mkxl b/tex/context/base/mkiv/core-con.mkxl new file mode 100644 index 000000000..0f836f0cc --- /dev/null +++ b/tex/context/base/mkiv/core-con.mkxl @@ -0,0 +1,1013 @@ +%D \module +%D [ file=core-con, +%D version=1997.26.08, +%D title=\CONTEXT\ Core Macros, +%D subtitle=Conversion, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Core Macros / Conversion} + +\registerctxluafile{core-con}{} + +% todo: iso date ranges (from/to) + +\unprotect + +\ifdefined\currentlanguage \else \let\currentlanguage\empty \fi +\ifdefined\labeltext \else \let\labeltext \firstofoneargument \fi + +%D This module deals with all kind of conversions from numbers and dates. I +%D considered splitting this module in a support one and a core one, but to keep +%D things simple as well as preserve the overview, I decided against splitting. + +\let\spr\firstofoneargument % separator +\let\stp\firstofoneargument % stopper + +% needed for arab: + +\permanent\protected\def\isolateseparators % even works with list separator overloading + {\def\spr##1{{##1}}% % we can probably best mess around with zwj + \def\stp##1{{##1}}} % and friends + +%D \macros +%D {numbers} +%D +%D First we deal with the dummy conversion of numbers using the \TEX\ primitive +%D \type{\number}. The uppercase alternative is only there for compatibility with +%D the other conversion macros. We could do without \type{#1} but this way we get +%D rid of unwanted braces. For the savety we also define a non||sence uppercase +%D alternative. +%D +%D \showsetup{numbers} +%D +%D \starttyping +%D \def\numbers#1{\number#1} +%D \def\Numbers#1{\number#1} +%D \stoptyping +%D +%D Due to read ahead, as in \type{[\pagenumber\space]} the space will disappear, +%D unless we use: + +\permanent\def\numbers#1{\purenumber{#1}} +\permanent\def\Numbers#1{\purenumber{#1}} + +%D \macros +%D {romannumerals,Romannumerals} +%D +%D \TEX\ the program uses a rather tricky conversion from numbers to their roman +%D counterparts. This conversion could of course be programmed in \TEX\ itself, but +%D I guess Knuth found the programming trick worth presenting. +%D +%D \showsetup{romannumerals} +%D \showsetup{Romannumerals} + +\permanent\def\romannumerals#1{\clf_romannumerals\numexpr#1\relax} +\permanent\def\Romannumerals#1{\clf_Romannumerals\numexpr#1\relax} + +%D Arabic etc: + +\permanent\def\abjadnumerals #1{\clf_abjadnumerals \numexpr#1\relax} +\permanent\def\abjadnodotnumerals#1{\clf_abjadnodotnumerals\numexpr#1\relax} +\permanent\def\abjadnaivenumerals#1{\clf_alphabetic \numexpr#1\relax{arabic}} % okay? + +\permanent\def\hebrewnumerals #1{\clf_hebrewnumerals\numexpr#1\relax} +\aliased \let\yiddishnumerals \hebrewnumerals + +\permanent\def\languagecharacters#1{\clf_alphabetic\numexpr#1\relax{\currentlanguage}} % new +\permanent\def\languageCharacters#1{\clf_Alphabetic\numexpr#1\relax{\currentlanguage}} % new + +\permanent\def\alphabeticnumerals#1{\clf_alphabetic\numexpr#1\relax{}} +\permanent\def\Alphabeticnumerals#1{\clf_Alphabetic\numexpr#1\relax{}} + +\permanent\def\thainumerals #1{\clf_alphabetic\numexpr#1\relax{thai}} +\permanent\def\devanagarinumerals#1{\clf_alphabetic\numexpr#1\relax{devanagari}} +\permanent\def\gurmurkhinumerals #1{\clf_alphabetic\numexpr#1\relax{gurmurkhi}} +\permanent\def\gujaratinumerals #1{\clf_alphabetic\numexpr#1\relax{gujarati}} +\permanent\def\tibetannumerals #1{\clf_alphabetic\numexpr#1\relax{tibetan}} +\permanent\def\greeknumerals #1{\clf_alphabetic\numexpr#1\relax{greek}} +\permanent\def\Greeknumerals #1{\clf_Alphabetic\numexpr#1\relax{greek}} +\permanent\def\arabicnumerals #1{\clf_alphabetic\numexpr#1\relax{arabic}} +\permanent\def\persiannumerals #1{\clf_alphabetic\numexpr#1\relax{persian}} +\permanent\def\arabicdecimals #1{\clf_decimals \numexpr#1\relax{arabic}} +\permanent\def\persiandecimals #1{\clf_decimals \numexpr#1\relax{persian}} + +\aliased \let\arabicexnumerals \persiannumerals + +\permanent\def\koreannumerals #1{\clf_alphabetic\numexpr#1\relax{korean}} +\permanent\def\koreannumeralsp #1{\clf_alphabetic\numexpr#1\relax{korean-parenthesis}} +\permanent\def\koreannumeralsc #1{\clf_alphabetic\numexpr#1\relax{korean-circle}} + +\aliased \let\koreanparentnumerals \koreannumeralsp +\aliased \let\koreanparenthesisnumerals\koreannumeralsp +\aliased \let\koreancirclenumerals \koreannumeralsc + +\permanent\def\chinesenumerals #1{\clf_chinesenumerals\numexpr#1\relax{normal}} +\permanent\def\chinesecapnumerals#1{\clf_chinesenumerals\numexpr#1\relax{cap}} +\permanent\def\chineseallnumerals#1{\clf_chinesenumerals\numexpr#1\relax{all}} + +%D \macros +%D {character,Character} +%D +%D Converting a number into a character can of course only be done with numbers +%D less or equal to~26. At the cost of much more macros a faster conversion is +%D possible, using: +%D +%D \starttyping +%D \setvalue{char1}{a} \def\character#1{\getvalue{char#1}} +%D \stoptyping +%D +%D But we prefer a simpel \type{\case}. +%D +%D \showsetup{character} +%D \showsetup{Character} + +\def\unknowncharacter{-} % else in lists \relax + +\permanent\def\character#1{\clf_character\numexpr#1\relax} +\permanent\def\Character#1{\clf_Character\numexpr#1\relax} + +%D \macros +%D {characters,Characters} +%D +%D Converting large numbers is supported by the next two macros. This time we +%D just count on: $\cdots$~x, y, z, aa, ab, ac~$\cdots$. +%D +%D \showsetup{characters} +%D \showsetup{Characters} + +\permanent\def\characters#1{\clf_characters\numexpr#1\relax} +\permanent\def\Characters#1{\clf_Characters\numexpr#1\relax} + +%D \macros +%D {greeknumerals,Greeknumerals} +%D +%D Why should we only honour the romans, and not the greek? + +% \let\greeknumerals\gobbleoneargument +% \let\Greeknumerals\gobbleoneargument + +%D \macros +%D {oldstylenumerals,oldstyleromannumerals} +%D +%D These conversions are dedicated to Frans Goddijn. + +\permanent\protected\def\oldstylenumerals#1% + {\begingroup + \os\number#1% + \endgroup} + +\permanent\protected\def\oldstyleromannumerals#1% will become obsolete + {\dontleavehmode + \hbox\bgroup + \ss\txx + \setbox\scratchbox\hbox \s!spread .15\emwidth{\hss\uppercased{\romannumerals{#1}}\hss}% + \scratchwidth \wd\scratchbox + \scratchheight\ht\scratchbox + \scratchdimen .1\exheight + \vrule\s!width\scratchwidth\s!height\dimexpr\scratchheight+\scratchdimen\relax\s!depth-\dimexpr\scratchheight-+\scratchdimen\relax + \hskip-\scratchwidth + \vrule\s!width\scratchwidth\s!height\scratchdimen\s!depth\scratchdimen + \hskip-\scratchwidth + \box\scratchbox + \egroup} + +%D \macros +%D {protectconversion} +%D +%D The previous two commands are not robust enough to be passed to \type +%D {\write} en \type{\message}. That's why we introduce: + +\permanent\protected\def\protectconversion + {\let\doconvertcharacters\firstofoneargument} + +%D \macros +%D {normaltime,normalyear,normalmonth,normalday} +%D +%D The last part of this module is dedicated to converting dates. Because we want to +%D use as meaningful commands as possible, and because \TEX\ already uses up some of +%D those, we save the original meanings. + +% \savenormalmeaning\time +% \savenormalmeaning\year +% \savenormalmeaning\month +% \savenormalmeaning\day + +%D \macros +%D {month,MONTH} +%D +%D Converting the month number into a month name is done using a case statement, +%D abstact values and the label mechanism. This way users can easily redefine a +%D label from for instance german into austrian. +%D +%D \starttyping +%D \setuplabeltext [de] [january=J\"anner] +%D \stoptyping +%D +%D Anyhow, the conversion looks like: + +\permanent\protected\def\monthlong #1{\clf_monthname\numexpr#1\relax} +\permanent\protected\def\monthshort#1{\clf_monthmnem\numexpr#1\relax} +\permanent\protected\def\daylong #1{\clf_dayname\numexpr#1\relax} +\permanent\protected\def\dayshort #1{\clf_daymnem\numexpr#1\relax} +\aliased \let\convertmonth\monthlong % for old times sake + +%D We redefine the \TEX\ primitive \type{\month} as: +%D +%D \showsetup{month} +%D \showsetup{MONTH} + +\pushoverloadmode + +\aliased\let\month\monthlong + +\popoverloadmode + +\permanent\protected\def\MONTH #1{\WORD{\clf_monthname\numexpr#1\relax}} +\permanent\protected\def\MONTHLONG #1{\WORD{\clf_monthname\numexpr#1\relax}} +\permanent\protected\def\MONTHSHORT#1{\WORD{\clf_monthmnem\numexpr#1\relax}} + +%D We never explicitly needed this, but Tobias Burnus pointed out that it would be +%D handy to convert to the day of the week. In doing so, we have to calculate the +%D total number of days, taking leapyears into account. For those who are curious: +%D +%D \startitemize[packed] +%D \item years that can be divided by 4 are leapyears +%D \item exept years that can be divided by 100 +%D \item unless years can be divided by 400 +%D \stopitemize + +%D \macros +%D {weekday,WEEKDAY} +%D +%D The first one is sort of redundant. It takes the day number argument. +%D +%D \showsetup{weekday} +%D \showsetup{WEEKDAY} + +\permanent\protected\def\weekday #1{\clf_dayname\numexpr#1\relax} +\permanent\protected\def\WEEKDAY #1{\WORD{\clf_dayname\numexpr#1\relax}} +\permanent\protected\def\DAYLONG #1{\WORD{\clf_dayname\numexpr#1\relax}} +\permanent\protected\def\DAYSHORT#1{\WORD{\clf_daymnem\numexpr#1\relax}} + +%D \macros +%D {getdayoftheweek, dayoftheweek} + +\newcount\normalweekday + +\permanent \def\dayoftheweek #1#2#3{\clf_weekdayname\numexpr#1\relax\numexpr#2\relax\numexpr#3\relax} % name +\permanent\protected\def\getdayoftheweek#1#2#3{\normalweekday\clf_weekday\numexpr#1\relax\numexpr#2\relax\numexpr#3\relax\relax} % number + +%D Using this macro in +%D +%D \startbuffer +%D monday: \dayoftheweek {4} {5} {1992} +%D friday: \dayoftheweek {16} {6} {1995} +%D monday: \dayoftheweek {25} {8} {1997} +%D saturday: \dayoftheweek {30} {8} {1997} +%D tuesday: \dayoftheweek {2} {1} {1996} +%D tuesday: \dayoftheweek {7} {1} {1997} +%D tuesday: \dayoftheweek {13} {1} {1998} +%D friday: \dayoftheweek {1} {1} {2000} +%D \stopbuffer +%D +%D \typebuffer +%D +%D gives +%D +%D \startlines +%D \getbuffer +%D \stoplines +%D +%D The macro \type {\getdayoftheweek} can be used to calculate the number \type +%D {\normalweekday}. + +%D \macros +%D {doifleapyearelse, +%D getdayspermonth} +%D +%D Sometimes we need to know if we're dealing with a leapyear, so here is a +%D testmacro: +%D +%D \starttyping +%D \doifleapyearelse{year}{yes}{no} +%D \stoptyping +%D +%D An example of its use can be seen in the macro +%D +%D \starttyping +%D \getdayspermonth{year}{month} +%D \stoptyping +%D +%D The number of days is available in the macro \type {\numberofdays}. + +\permanent\def\doifelseleapyear#1% expandable check + {\clf_doifelseleapyear\numexpr#1\relax} + +\aliased\let\doifleapyearelse\doifelseleapyear + +\permanent\protected\def\getdayspermonth#1#2% + {\edef\numberofdays{\clf_nofdays\numexpr#1\relax\numexpr#2\relax}} + +\permanent\def\dayspermonth#1#2% + {\clf_nofdays\numexpr#1\relax\numexpr#2\relax} + +% \dayoftheweek{2006}{9}{15} +% \doifleapyearelse{2000}{OK}{NOT OK} +% \doifleapyearelse{2100}{NOT OK}{OK} +% \doifleapyearelse{2004}{OK}{NOT OK} +% \doifleapyearelse{2003}{NOT OK}{OK} +% \dayspermonth{2000}{2} +% [\the\normaltime=\the\time] + +%D \macros +%D {currentdate, rawdate, date} +%D +%D We use these conversion macros in the date formatting macro: +%D +%D \showsetup{currentdate} +%D +%D This macro takes care of proper spacing and delivers for instance: +%D +%D \startbuffer +%D \currentdate[weekday,day,month,year] +%D \currentdate[WEEKDAY,day,MONTH,year] +%D \stopbuffer +%D +%D \startlines +%D \getbuffer +%D \stoplines +%D +%D depending of course on the keywords. Here we gave: +%D +%D \typebuffer +%D +%D If needed one can also add non||keywords, like in +%D +%D \startbuffer +%D \currentdate[dd,--,mm,--,yy] +%D \stopbuffer +%D +%D \typebuffer +%D +%D or typeset: \getbuffer. +%D +%D When no argument is passed, the current date is given as specified per +%D language (using \type{\installlanguage}). +%D +%D \showsetup{currentdate} +%D +%D \startbuffer +%D \date +%D \date[d=12,m=12,y=1998][weekday] +%D \date[d=12,m=12,y=1998] +%D \stopbuffer +%D +%D We can also typeset arbitrary dates, using the previous +%D command. +%D +%D \typebuffer +%D +%D The date is specified by one character keys. When no date is given, we get the +%D current date. +%D +%D \startlines +%D \getbuffer +%D \stoplines + +%D \starttabulate[|l|l|] +%D \HL +%D \NC year \NC (\currentdate[year]) \NC\NR +%D \NC yy \NC (\currentdate[yy]) \NC\NR +%D \NC y \NC (\currentdate[y]) \NC\NR +%D \NC Y \NC (\currentdate[Y]) \NC\NR +%D \HL +%D \NC month \NC (\currentdate[month]) \NC\NR +%D \NC mm \NC (\currentdate[mm]) \NC\NR +%D \NC m \NC (\currentdate[m]) \NC\NR +%D \NC M \NC (\currentdate[M]) \NC\NR +%D \HL +%D \NC day \NC (\currentdate[day]) \NC\NR +%D \NC dd \NC (\currentdate[dd]) \NC\NR +%D \NC d \NC (\currentdate[d]) \NC\NR +%D \NC D \NC (\currentdate[D]) \NC\NR +%D \HL +%D \NC weekday \NC (\currentdate[weekday]) \NC\NR +%D \NC w \NC (\currentdate[w]) \NC\NR +%D \NC W \NC (\currentdate[W]) \NC\NR +%D \HL +%D \NC referral \NC (\currentdate[referral]) \NC\NR +%D \HL +%D \NC day:mnem \NC (\currentdate[day:mnem]) \NC\NR +%D \NC dd:mnem \NC (\currentdate[dd:mnem]) \NC\NR +%D \NC d:mnem \NC (\currentdate[d:mnem]) \NC\NR +%D \NC D:mnem \NC (\currentdate[D:mnem]) \NC\NR +%D \HL +%D \stoptabulate +%D +%D \startbuffer +%D (\currentdate[D,.,M,.,Y]) +%D (\currentdate[day,month,year]) +%D (\currentdate[day,+,month,+,year]) +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D Some indirectness and abstraction: +%D +%D \starttyping +%D \definedate[crap][year] +%D \currentdate[crap] +%D \stoptyping + +\installcorenamespace{date} + +\permanent\tolerant\protected\def\definedate[#1]#*[#2]% + {\ifarguments\else\setvalue{\??date#1}{#2}\fi} + +\def\syst_converters_check_date_specification#1% + {\ifcsname\??date#1\endcsname + \edef#1{\lastnamedcs}% + \fi} + +\newtoks\everycurrentdate + +\permanent\tolerant\protected\def\currentdate[#1]% + {\dontleavehmode + \begingroup + \the\everycurrentdate + \edef\forceddatespecification{#1}% + \syst_converters_check_date_specification\forceddatespecification + \syst_converters_check_date_specification\currentdatespecification + \clf_currentdate + {\forceddatespecification}{\currentdatespecification}{\labellanguage}% + \normalyear\normalmonth\normalday + \endgroup} + +\permanent\tolerant\protected\def\date[#1][#2]% sets the date ! + {\dontleavehmode + \ifparameter#1\or + \begingroup + \letdummyparameter\c!d\normalday + \letdummyparameter\c!m\normalmonth + \letdummyparameter\c!y\normalyear + \getdummyparameters[#1]% + \normalexpanded + {\endgroup + \normalday \number\directdummyparameter\c!d\relax + \normalmonth\number\directdummyparameter\c!m\relax + \normalyear \number\directdummyparameter\c!y\relax}% + \fi + \begingroup + \the\everycurrentdate + \edef\forceddatespecification{#2}% + \syst_converters_check_date_specification\forceddatespecification + \syst_converters_check_date_specification\currentdatespecification + \clf_currentdate + {\forceddatespecification}{\currentdatespecification}{\labellanguage}% + \normalyear\normalmonth\normalday + \endgroup} + +\permanent\def\rawdate[#1]% expandable and no labels + {\clf_currentdate + {#1}{\currentdatespecification}{}% + \normalyear\normalmonth\normalday} + +%D \macros +%D {currenttime} +%D +%D The currenttime is actually the jobtime. You can specify a pattern similar +%D to the previous date macro using the keys \type {h}, \type {m} and a separator. + +\permanent\protected\def\calculatecurrenttime + {\edef\currenthour {\clf_hour }% + \edef\currentminute{\clf_minute}% + \edef\currentsecond{\clf_second}} + +\let\currenthour \!!plusone +\let\currentminute\!!plusone +\let\currentsecond\!!plusone + +% \def\currenttimespecification{h,:,m} + +\permanent\protected\def\currenttime + {\doifelsenextoptional\syst_converters_current_time_yes\syst_converters_current_time_nop} + +\protected\def\syst_converters_current_time_yes[#1]% + {\calculatecurrenttime + \processallactionsinset[#1][h=>\currenthour,m=>\currentminute,\s!unknown=>\commalistelement]} + +\protected\def\syst_converters_current_time_nop + {\normalexpanded{\syst_converters_current_time_yes[\currenttimespecification]}} + +%D Because we're dealing with dates, we also introduce a few day loops: +%D +%D \starttyping +%D \processmonth{year}{month}{command} +%D \processyear{year}{command}{before}{after} +%D \stoptyping +%D +%D The counters \type {\normalyear}, \type {\normalmonth} and \type {\normalday} +%D can be used for for date manipulations. + +\permanent\protected\def\processmonth#1#2#3% year month command + {\begingroup + \getdayspermonth{#1}{#2}% + \dostepwiserecurse\plusone\numberofdays\plusone + {\normalyear #1\relax + \normalmonth#2\relax + \normalday \recurselevel\relax + #3}% + \endgroup} + +\def\lastmonth{12} % can be set to e.g. 1 when testing + +\permanent\protected\def\processyear#1#2#3#4% year command before after + {\begingroup + \dorecurse\lastmonth + {\normalyear #1\relax + \normalmonth\recurselevel\relax + #3\processmonth\normalyear\normalmonth{#2}#4}% + \endgroup} + +%D \macros +%D {defineconversion, convertnumber} +%D +%D Conversion involves the macros that we implemented earlier in this module. +%D +%D \showsetup{defineconversion} +%D \showsetup{convertnumber} +%D +%D We can feed this command with conversion macros as well as a set of conversion +%D symbols. Both need a bit different treatment. +%D +%D \starttyping +%D \defineconversion [roman] [\romannumerals] +%D \defineconversion [set 1] [$\star$,$\bullet$,$\ast$] +%D \stoptyping +%D +%D You can define a language dependent conversion with: +%D +%D \starttyping +%D \defineconversion [en] [whatever] [\something] +%D \stoptyping + +\installcorenamespace {conversion} +\installcorenamespace {conversionarguments} +\installcorenamespace {conversionwords} + +%D It might be better to move more to \LUA\ as we also need conversion there and +%D doublicating logic doesn't make things cleaner. It means that all conversions +%D will get a language argument too. However, we permit definitions at the \TEX\ end +%D so we have to provide some hybrid method. + +% checkedconversion(method,n,language) + +\protected\def\defineconversion + {\dotripleempty\syst_converters_define_conversion} + +\def\syst_converters_define_conversion[#1][#2][#3]% from now on global (maybe local again some day) + {\ifthirdargument + \syst_converters_define_conversion_indeed{#1#2}{#1:#2}{#3}% + \else + \syst_converters_define_conversion_indeed{#1}{#1}{#2}% + \fi} + +\def\syst_converters_define_conversion_indeed#1#2#3% + {\doifelseinstring{,}{\detokenize{#3}} + {\clf_defineconversion{#2}{\detokenize{#3}}% a set e.g. of symbols + \setgvalue{\??conversion#1}{\syst_converters_checked_conversion{#2}}} + {\setgvalue{\??conversion#1}{#3}}} + +\def\syst_converters_checked_conversion#1#2% + {\clf_checkedconversion{#1}\numexpr#2\relax} + +%D If a conversion is just a font switch then we need to make sure that the number +%D is indeed ends up as number in the input, so we need to handle the second +%D argument. + +\permanent\def\convertnumber#1#2% expandable + {\csname\??conversionarguments + \ifcsname\??conversion\currentlanguage#1\endcsname1\else + \ifcsname\??conversion #1\endcsname2\else + 3\fi\fi + \endcsname{#1}{\number#2}} + +\protected\def\uconvertnumber % unexpandable + {\convertnumber} + +\setvalue{\??conversionarguments1}#1{\csname\??conversion\currentlanguage#1\endcsname} +\setvalue{\??conversionarguments2}#1{\csname\??conversion #1\endcsname} +\letvalue{\??conversionarguments3}\syst_converters_checked_conversion + +% we can also add a \ctxcommand{doifelseconversion("#1","\currentlanguage")} to check +% if we have definitions that are not matched at the lua end .. eventually we might do +% that when more shows up + +\permanent\def\doifelseconversiondefined#1% expandable + {\ifcsname\??conversion\currentlanguage#1\endcsname + \expandafter\firstoftwoarguments + \orelse\ifcsname\??conversion#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\permanent\def\doifelseconversionnumber#1#2% expandable + {\ifnum#2>\numexpr\clf_nofconversions{#1}\relax + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\aliased\let\doifconversiondefinedelse\doifelseconversiondefined +\aliased\let\doifconversionnumberelse \doifelseconversionnumber + +%D Handy. + +\setvalue{\??conversionwords\v!one }{1} +\setvalue{\??conversionwords\v!two }{2} +\setvalue{\??conversionwords\v!three}{3} +\setvalue{\??conversionwords\v!four }{4} +\setvalue{\??conversionwords\v!five }{5} + +%permanent\def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\csname\??conversionwords#1\endcsname\else#2\fi} +\permanent\def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\lastnamedcs\else#2\fi} + +% \defineconversion[ctx][c,o,n,t,e,x,t] +% +% \doloop{\doifelseconversionnumber{ctx}{\recurselevel}{[\recurselevel]}{\exitloop}} + +%D \macros +%D {ordinalnumber, highordinalstr, ordinalstr} +%D +%D Efficient general ordinal number converters are sometimes difficult to +%D implement. Fortunately dates never exceed the number~31. + +\permanent\def\highordinalstr#1{\high{\notsmallcapped{#1}}} +\permanent\def\ordinalstr #1{\notsmallcapped{#1}} +\permanent\def\ordinalnumber #1{\clf_ordinal\numexpr#1\relax{\currentlanguage}} +\permanent\def\Ordinalnumber #1{\Words{\clf_ordinal\numexpr#1\relax{\currentlanguage}}} + +\permanent\def\verbosenumber#1{\clf_verbose\numexpr#1\relax{\currentlanguage}} +\permanent\def\VerboseNumber#1{\Words{\clf_verbose\numexpr#1\relax{\currentlanguage}}} + +%D As longs as symbols are linked to levels or numbers, we can also use the +%D conversion mechanism, but in for instance the itemization macros, we prefer +%D symbols because they can more easier be (partially) redefined. Symbols are +%D implemented in another module. + +\permanent\def\smallcappedromannumerals#1{\smallcapped{\romannumerals{#1}}} +\permanent\def\smallcappedcharacters #1{\smallcapped{\characters {#1}}} + +\defineconversion [] [\numbers] % the default conversion +\defineconversion [\v!empty] [\gobbleoneargument] +\defineconversion [\v!none] [\numbers] +\defineconversion [\s!default] [\numbers] + +\defineconversion [month] [\monthlong] +\defineconversion [month:mnem] [\monthshort] + +\defineconversion [\v!character] [\character] +\defineconversion [\v!Character] [\Character] + +\defineconversion [\v!characters] [\characters] +\defineconversion [\v!Characters] [\Characters] + +\defineconversion [a] [\alphabeticnumerals] +\defineconversion [A] [\Alphabeticnumerals] +\defineconversion [AK] [\smallcappedcharacters] +\defineconversion [KA] [\smallcappedcharacters] + +\defineconversion [\v!alphabetic] [\alphabeticnumerals] +\defineconversion [\v!Alphabetic] [\Alphabeticnumerals] + +\defineconversion [\v!number] [\numbers] +\defineconversion [\v!numbers] [\numbers] +\defineconversion [\v!Numbers] [\Numbers] +\defineconversion [\v!mediaeval] [\mediaeval] + +\defineconversion [\v!word] [\verbosenumber] +\defineconversion [\v!words] [\verbosenumber] + +\defineconversion [\v!Word] [\VerboseNumber] +\defineconversion [\v!Words] [\VerboseNumber] + +\defineconversion[\v!ordinal] [\ordinalnumber] +\defineconversion[\v!Ordinal] [\Ordinalnumber] + +\defineconversion [n] [\numbers] +\defineconversion [N] [\Numbers] +\defineconversion [m] [\mediaeval] +\defineconversion [o] [\oldstylenumerals] +\defineconversion [O] [\oldstylenumerals] +\defineconversion [or] [\oldstyleromannumerals] + +\defineconversion [\v!romannumerals] [\romannumerals] +\defineconversion [\v!Romannumerals] [\Romannumerals] + +\defineconversion [i] [\romannumerals] +\defineconversion [I] [\Romannumerals] +\defineconversion [r] [\romannumerals] +\defineconversion [R] [\Romannumerals] + +\defineconversion [KR] [\smallcappedromannumerals] +\defineconversion [RK] [\smallcappedromannumerals] + +\defineconversion [\v!greek] [\greeknumerals] +\defineconversion [\v!Greek] [\Greeknumerals] + +\defineconversion [g] [\greeknumerals] +\defineconversion [G] [\Greeknumerals] + +%defineconversion [ñ] [\spanishnumerals] +%defineconversion [Ñ] [\Spanishnumerals] + +\defineconversion [abjadnumerals] [\abjadnumerals] +\defineconversion [abjadnodotnumerals] [\abjadnodotnumerals] +\defineconversion [abjadnaivenumerals] [\abjadnaivenumerals] + +\defineconversion [hebrewnumerals] [\hebrewnumerals] +\defineconversion [yiddishnumerals] [\yiddishnumerals] + +% users can do: \defineconversion [he] [\hebrewnumerals] +% users can do: \defineconversion [yi] [\hebrewnumerals] + +\defineconversion [thainumerals] [\thainumerals] +\defineconversion [devanagarinumerals] [\devanagarinumerals] +\defineconversion [gurmurkhinumerals] [\gurmurkhinumerals] +\defineconversion [gujaratinumerals] [\gujaratinumerals] +\defineconversion [tibetannumerals] [\tibetannumerals] +\defineconversion [greeknumerals] [\greeknumerals] +\defineconversion [Greeknumerals] [\Greeknumerals] +\defineconversion [arabicnumerals] [\arabicnumerals] +\defineconversion [persiannumerals] [\persiannumerals] +\defineconversion [arabicexnumerals] [\arabicexnumerals] +\defineconversion [arabicdecimals] [\arabicdecimals] +\defineconversion [persiandecimals] [\persiandecimals] + +\defineconversion [koreannumerals] [\koreannumerals] +\defineconversion [koreanparennumerals] [\koreanparenthesisnumerals] % for old times sake (for a while) +\defineconversion [koreanparenthesisnumerals] + [\koreanparenthesisnumerals] +\defineconversion [koreancirclenumerals] [\koreancirclenumerals] + +\defineconversion [kr] [\koreannumerals] +\defineconversion [kr-p] [\koreanparentnumerals] +\defineconversion [kr-c] [\koreancirclenumerals] + +\defineconversion [chinesenumerals] [\chinesenumerals] +\defineconversion [chinesecapnumerals] [\chinesecapnumerals] +\defineconversion [chineseallnumerals] [\chineseallnumerals] + +\defineconversion [cn] [\chinesenumerals] +\defineconversion [cn-c] [\chinesecapnumerals] +\defineconversion [cn-a] [\chineseallnumerals] + +%D Moved from lang-def.mkiv: +%D +%D Define these as the general character enumeration when language is Slovenian. If +%D you feel uncomfortable with this, mail Mojca, since she promised to to take the +%D heat. Pablo was next to request this. We changed characters to numerals for this +%D feature. We do need these definitions for mechanisms like itemize that check +%D for converters. + +\permanent\def\sloveniannumerals#1{\clf_alphabetic\numexpr#1\relax{sl}} +\permanent\def\slovenianNumerals#1{\clf_Alphabetic\numexpr#1\relax{sl}} + +\permanent\def\spanishnumerals #1{\clf_alphabetic\numexpr#1\relax{es}} +\permanent\def\spanishNumerals #1{\clf_Alphabetic\numexpr#1\relax{es}} + +\permanent\def\russiannumerals #1{\clf_alphabetic\numexpr#1\relax{ru}} +\permanent\def\russianNumerals #1{\clf_Alphabetic\numexpr#1\relax{ru}} + +%defineconversion [\s!sl] [character] [\sloveniannumerals] +%defineconversion [\s!sl] [Character] [\slovenianNumerals] +%defineconversion [\s!sl] [characters] [\sloveniannumerals] +%defineconversion [\s!sl] [Characters] [\slovenianNumerals] + +\defineconversion [\s!sl] [alphabetic] [\sloveniannumerals] +\defineconversion [\s!sl] [Alphabetic] [\slovenianNumerals] + +\defineconversion [\s!sl] [a] [\sloveniannumerals] +\defineconversion [\s!sl] [A] [\slovenianNumerals] +\defineconversion [\s!sl] [AK] [\smallcapped\sloveniannumerals] +\defineconversion [\s!sl] [KA] [\smallcapped\sloveniannumerals] + +%defineconversion [\s!es] [character] [\spanishnumerals] +%defineconversion [\s!es] [Character] [\spanishNumerals] +%defineconversion [\s!es] [characters] [\spanishnumerals] +%defineconversion [\s!es] [Characters] [\spanishNumerals] + +\defineconversion [\s!es] [alphabetic] [\spanishnumerals] +\defineconversion [\s!es] [Alphabetic] [\spanishNumerals] + +\defineconversion [\s!es] [a] [\spanishnumerals] +\defineconversion [\s!es] [A] [\spanishNumerals] +\defineconversion [\s!es] [AK] [\smallcapped\spanishnumerals] +\defineconversion [\s!es] [KA] [\smallcapped\spanishnumerals] + +%defineconversion [\s!ru] [character] [\russiannumerals] +%defineconversion [\s!ru] [Character] [\russianNumerals] +%defineconversion [\s!ru] [characters] [\russiannumerals] +%defineconversion [\s!ru] [Characters] [\russianNumerals] + +\defineconversion [\s!ru] [alphabetic] [\russiannumerals] +\defineconversion [\s!ru] [Alphabetic] [\russianNumerals] + +\defineconversion [\s!ru] [a] [\russiannumerals] +\defineconversion [\s!ru] [A] [\russianNumerals] +\defineconversion [\s!ru] [AK] [\smallcapped\russiannumerals] +\defineconversion [\s!ru] [KA] [\smallcapped\russiannumerals] + +\defineconversion [sloveniannumerals] [\sloveniannumerals] +\defineconversion [slovenianNumerals] [\slovenianNumerals] + +\defineconversion [spanishnumerals] [\spanishnumerals] +\defineconversion [spanishNumerals] [\spanishNumerals] + +\defineconversion [russiannumerals] [\russiannumerals] +\defineconversion [russianNumerals] [\russianNumerals] + +%D In case a font has no greek (WS): + +\defineconversion [mathgreek] + [\m{α},\m{β},\m{γ},\m{δ},\m{ε},\m{ζ}, + \m{η},\m{θ},\m{ι},\m{κ},\m{λ},\m{μ}, + \m{ν},\m{ξ},\m{ο},\m{π},\m{ρ},\m{σ}, + \m{τ},\m{υ},\m{φ},\m{χ},\m{ψ},\m{ω}] + +%D Handy too (expanded!): + +\permanent\def\unihex#1{\clf_unihex\numexpr#1\relax} + +%D Symbol sets: + +\ifdefined\symbol \else \def\symbol[#1]{#1} \fi % todo + +% \defineconversion +% [set 0] +% [{\symbol[bullet]}, +% {\symbol[dash]}, +% {\symbol[star]}, +% {\symbol[triangle]}, +% {\symbol[circle]}, +% {\symbol[medcircle]}, +% {\symbol[bigcircle]}, +% {\symbol[square]}, +% {\symbol[checkmark]}] + +% \defineconversion +% [set 1] +% [\mathematics{\star}, +% \mathematics{\star\star}, +% \mathematics{\star\star\star}, +% \mathematics{\ddagger}, +% \mathematics{\ddagger\ddagger}, +% \mathematics{\ddagger\ddagger\ddagger}, +% \mathematics{\ast}, +% \mathematics{\ast\ast}, +% \mathematics{\ast\ast\ast}] +% +% \defineconversion +% [set 2] +% [\mathematics{\ast}, +% \mathematics{\dag}, +% \mathematics{\ddag}, +% \mathematics{\ast\ast}, +% \mathematics{\dag\dag}, +% \mathematics{\ddag\ddag}, +% \mathematics{\ast\ast\ast}, +% \mathematics{\dag\dag\dag}, +% \mathematics{\ddag\ddag\ddag}, +% \mathematics{\ast\ast\ast\ast}, +% \mathematics{\dag\dag\dag\dag}, +% \mathematics{\ddag\ddag\ddag\ddag}] +% +% \defineconversion +% [set 3] +% [\mathematics{\star}, +% \mathematics{\star\star}, +% \mathematics{\star\star\star}, +% \mathematics{\ddagger}, +% \mathematics{\ddagger\ddagger}, +% \mathematics{\ddagger\ddagger\ddagger}, +% \mathematics{\P}, +% \mathematics{\P\P}, +% \mathematics{\P\P\P}, +% \mathematics{\S}, +% \mathematics{\S\S}, +% \mathematics{\S\S\S}, +% \mathematics{\ast}, +% \mathematics{\ast\ast}, +% \mathematics{\ast\ast\ast}] + +\defineconversion + [set 0] + [\symbol{bullet}, + \symbol{dash}, + \symbol{star}, + \symbol{triangle}, + \symbol{circle}, + \symbol{medcircle}, + \symbol{bigcircle}, + \symbol{square}, + \symbol{checkmark}] + +\defineconversion + [set 1] + [\textormathchars{⋆}, + \textormathchars{⋆⋆}, + \textormathchars{⋆⋆⋆}, + \textormathchars{‡}, + \textormathchars{‡‡}, + \textormathchars{‡‡‡}, + \textormathchars{∗}, + \textormathchars{∗∗}, + \textormathchars{∗∗∗}] + +\defineconversion + [set 2] + [\textormathchars{∗}, + \textormathchars{†}, + \textormathchars{‡}, + \textormathchars{∗∗}, + \textormathchars{††}, + \textormathchars{‡‡}, + \textormathchars{∗∗∗}, + \textormathchars{†††}, + \textormathchars{‡‡‡}, + \textormathchars{∗∗∗∗}, + \textormathchars{††††}, + \textormathchars{‡‡‡‡}] + +\defineconversion + [set 3] + [\textormathchars{⋆}, + \textormathchars{⋆⋆}, + \textormathchars{⋆⋆⋆}, + \textormathchars{‡}, + \textormathchars{‡‡}, + \textormathchars{‡‡‡}, + \textormathchars{¶}, + \textormathchars{¶¶}, + \textormathchars{¶¶¶}, + \textormathchars{§}, + \textormathchars{§§}, + \textormathchars{§§§}, + \textormathchars{∗}, + \textormathchars{∗∗}, + \textormathchars{∗∗∗}] + +%D Iteration of suggestion by WS on mailinglist 2010.12.22: +%D +%D \starttyping +%D \setupfloatsplitting[conversion=continued] +%D \stoptyping + +\permanent\protected\def\continuednumber#1% + {\labeltext{\ifcase#1\or\else\v!continued\fi}} + +\defineconversion + [\v!continued] + [\continuednumber] + +%D Taken from x-asciimath (see digits-001.tex for an example): + +\let\spaceddigitsmethod \empty % alternative methods : 1 default, 2 and 3 only when > 4 +\let\spaceddigitssymbol \empty % extra splitter symbol : {,} +\let\spaceddigitsseparator\empty % separator symbol : {\Uchar{"2008}} + +\permanent\protected\def\spaceddigits#1% + {\clf_spaceddigits + method {\spaceddigitsmethod}% + symbol {\spaceddigitssymbol}% + separator {\spaceddigitsseparator}% + data {#1}% + \relax} + +%D For those who sart counting at zero: +%D +%D \starttyping +%D \defineconversionset [zero] [n,zero] [n] +%D +%D \setuphead [sectionconversionset=zero] +%D +%D \starttext +%D \startchapter [title=Introduction] +%D \startsection [title=First topic] \stopsection +%D \startsection [title=Second topic] \stopsection +%D \stopchapter +%D \stoptext +%D \stoptyping + +\permanent\def\zeronumberconversion#1{\number\numexpr#1-\plusone\relax} + +\defineconversion [zero] [\zeronumberconversion] + +\protect \endinput diff --git a/tex/context/base/mkiv/core-dat.mkiv b/tex/context/base/mkiv/core-dat.mkiv index 9f4344b99..41a84c3e6 100644 --- a/tex/context/base/mkiv/core-dat.mkiv +++ b/tex/context/base/mkiv/core-dat.mkiv @@ -77,9 +77,12 @@ \installcommandhandler \??pagestate {pagestate} \??pagestate +% \def\syst_pagestates_allocate +% {\expandafter\newcount\csname\??pagestatecounter\currentpagestate\endcsname +% \expandafter\let\expandafter\c_syst_pagestate\csname\??pagestatecounter\currentpagestate\endcsname} + \def\syst_pagestates_allocate - {\expandafter\newcount\csname\??pagestatecounter\currentpagestate\endcsname - \expandafter\let\expandafter\c_syst_pagestate\csname\??pagestatecounter\currentpagestate\endcsname} + {\expandafter\newcount\csname\??pagestatecounter\currentpagestate\endcsname} \appendtoks \syst_pagestates_allocate @@ -91,19 +94,37 @@ \unexpanded\def\setpagestate {\dodoubleempty\syst_pagestates_set} +% \def\syst_pagestates_set[#1][#2]% +% {\begingroup +% \edef\currentpagestate{#1}% +% \ifcsname\??pagestatecounter\currentpagestate\endcsname +% \let\c_syst_pagestate\lastnamedcs +% \else +% \syst_pagestates_allocate +% \fi +% \global\advance\c_syst_pagestate\plusone +% \scratchcounter\lastnamedcs +% \clf_setpagestate +% name {\currentpagestate}% +% tag {\ifsecondargument#2\else\number\c_syst_pagestate\fi}% +% delay {\pagestateparameter\c!delay}% +% \relax +% \endgroup} + \def\syst_pagestates_set[#1][#2]% {\begingroup \edef\currentpagestate{#1}% \ifcsname\??pagestatecounter\currentpagestate\endcsname - \let\c_syst_pagestate\lastnamedcs + \scratchcounter\lastnamedcs + \advance\scratchcounter\plusone \else + \scratchcounter\plusone \syst_pagestates_allocate \fi - \global\advance\c_syst_pagestate\plusone - \scratchcounter\lastnamedcs + \global\csname\??pagestatecounter\currentpagestate\endcsname\scratchcounter \clf_setpagestate name {\currentpagestate}% - tag {\ifsecondargument#2\else\number\c_syst_pagestate\fi}% + tag {\ifsecondargument#2\else\number\scratchcounter\fi}% delay {\pagestateparameter\c!delay}% \relax \endgroup} diff --git a/tex/context/base/mkiv/core-def.mkiv b/tex/context/base/mkiv/core-def.mkiv index bb209a8ff..b1300d493 100644 --- a/tex/context/base/mkiv/core-def.mkiv +++ b/tex/context/base/mkiv/core-def.mkiv @@ -179,6 +179,6 @@ %D Till we fixed all styles: -\let\\=\crlf +\enforced\let\\\crlf % frozen or permanent? \protect \endinput diff --git a/tex/context/base/mkiv/core-env.lmt b/tex/context/base/mkiv/core-env.lmt new file mode 100644 index 000000000..194600c0a --- /dev/null +++ b/tex/context/base/mkiv/core-env.lmt @@ -0,0 +1,193 @@ +if not modules then modules = { } end modules ['core-env'] = { + version = 1.001, + comment = "companion to core-env.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- maybe this will move to the context name space although the +-- plurals are unlikely to clash with future tex primitives +-- +-- if tex.modes['xxxx'] then .... else .... end + +local rawset = rawset + +local P, C, S, lpegmatch, patterns = lpeg.P, lpeg.C, lpeg.S, lpeg.match, lpeg.patterns + +local context = context +local ctxcore = context.core + +local texgetcount = tex.getcount +local texgetintegervalue = token.get_integer -- todo: in tex namespace + +local allocate = utilities.storage.allocate +local setmetatableindex = table.setmetatableindex +local setmetatablenewindex = table.setmetatablenewindex +local setmetatablecall = table.setmetatablecall + +local createtoken = token.create +local isdefined = tokens.isdefined + +texmodes = allocate { } tex.modes = texmodes +texsystemmodes = allocate { } tex.systemmodes = texsystemmodes +texconstants = allocate { } tex.constants = texconstants +texconditionals = allocate { } tex.conditionals = texconditionals +texifs = allocate { } tex.ifs = texifs +texisdefined = allocate { } tex.isdefined = texisdefined + +local modes = { } +local systemmodes = { } + +-- we could use the built-in tex.is[count|dimen|skip|toks] here but caching +-- at the lua end is not that bad (and we need more anyway) + +local cache = tokens.cache + +-- we can have a modes cache too + +local iftrue = cache["iftrue"].index + +local dimencode = cache["scratchdimen"] .command -- tokens.commands.register_dimen +local countcode = cache["scratchcounter"].command -- tokens.commands.register_int +local tokencode = cache["scratchtoks"] .command -- tokens.commands.register_toks +local skipcode = cache["scratchskip"] .command -- tokens.commands.register_glue +local muskipcode = cache["scratchmuskip"] .command -- tokens.commands.register_mu_glue +local conditioncode = cache["iftrue"] .command -- tokens.commands.if_test + +local types = { + [dimencode] = "dimen", + [countcode] = "count", + [tokencode] = "token", + [skipcode] = "skip", + [muskipcode] = "muskip", + -- [attributecode] = "attribute", + [conditioncode] = "condition" +} + +setmetatableindex(texmodes, function(t,k) + local m = systemmodes[k] + if not m then + local n = "mode>" .. k + m = function() return texgetintegervalue(n) == 1 end + rawset(modes,k,m) + end + return m() +end) + +setmetatableindex(texsystemmodes, function(t,k) + local m = systemmodes[k] + if not m then + local n = "mode>*" .. k + m = function() return texgetintegervalue(n) == 1 end + rawset(modes,k,m) + end + return m() +end) + +-- also a call method + +context.settrialtypesettingmethod(function() return texsystemmodes.trialtypesetting end) + +setmetatablenewindex(texmodes, function(t,k) report_mode("you cannot set the %s named %a this way","mode", k) end) +setmetatablenewindex(texsystemmodes, function(t,k) report_mode("you cannot set the %s named %a this way","systemmode", k) end) +setmetatablenewindex(texconstants, function(t,k) report_mode("you cannot set the %s named %a this way","constant", k) end) +setmetatablenewindex(texconditionals, function(t,k) report_mode("you cannot set the %s named %a this way","conditional",k) end) +setmetatablenewindex(texifs, function(t,k) end) + +-- if we really need performance we can have a dedicated cache for each +-- kind of variable + +setmetatableindex(texconstants, function(t,k) + return cache[k].command == countcode and texgetcount(k) or 0 +end) + +setmetatableindex(texconditionals, function(t,k) -- 0 == true + return cache[k].command == countcode and texgetcount(k) == 0 +end) + +setmetatableindex(texifs, function(t,k) + local c = cache[k] + print(k) + inspect(c) + return c.command == conditioncode and c.index == iftrue +end) + +tex.isdefined = isdefined + +function tex.isdimen(name) + local hit = cache[name] + return hit.command == dimencode and hit.index or true +end + +function tex.iscount(name) + local hit = cache[name] + return hit.command == countcode and hit.index or true +end + +function tex.istoken(name) + local hit = cache[name] + return hit.command == tokencode and hit.index or true +end + +function tex.isskip(name) + local hit = cache[name] + return hit.command == skipcode and hit.index or true +end + +function tex.ismuskip(name) + local hit = cache[name] + return hit.command == muskipcode and hit.index or true +end + +function tex.type(name) + return types[cache[name].command] or "macro" +end + +function context.setconditional(name,value) + if value then + ctxcore.settruevalue(name) + else + ctxcore.setfalsevalue(name) + end +end + +function context.setmode(name,value) + if value then + ctxcore.setmode(name) + else + ctxcore.resetmode(name) + end +end + +function context.setsystemmode(name,value) + if value then + ctxcore.setsystemmode(name) + else + ctxcore.resetsystemmode(name) + end +end + +context.modes = texmodes +context.systemmodes = texsystemmodes +context.conditionals = texconditionals +-------.constants = texconstants +-------.ifs = texifs + +local sep = S("), ") +local str = C((1-sep)^1) +local tag = P("(") * C((1-S(")" ))^1) * P(")") +local arg = P("(") * C((1-S("){"))^1) * P("{") * C((1-P("}"))^0) * P("}") * P(")") + +local pattern = ( + P("lua") * tag / ctxcore.luasetup + + P("xml") * arg / ctxcore.setupwithargument -- or xmlw as xmlsetup has swapped arguments + + (P("tex") * tag + str) / ctxcore.texsetup + + sep^1 +)^1 + +interfaces.implement { + name = "autosetups", + actions = function(str) lpegmatch(pattern,str) end, + arguments = "string" +} diff --git a/tex/context/base/mkiv/core-env.lua b/tex/context/base/mkiv/core-env.lua index da10c26f5..1c5165ac8 100644 --- a/tex/context/base/mkiv/core-env.lua +++ b/tex/context/base/mkiv/core-env.lua @@ -47,13 +47,12 @@ local cache = tokens.cache local iftrue = cache["iftrue"].mode -local dimencode = cache["scratchdimen"] .command -- tokens.commands.assign_dimen -local countcode = cache["scratchcounter"] .command -- tokens.commands.assign_int -local tokencode = cache["scratchtoken"] .command -- tokens.commands.assign_toks -local skipcode = cache["scratchskip"] .command -- tokens.commands.assign_glue -local muskipcode = cache["scratchmuskip"] .command -- tokens.commands.assign_mu_glue ------ attributecode = cache["scratchattribute"].command -- tokens.commands.assign_attr -local conditioncode = cache["iftrue"] .command -- tokens.commands.if_test +local dimencode = cache["scratchdimen"] .command -- tokens.commands.register_dimen +local countcode = cache["scratchcounter"].command -- tokens.commands.register_int +local tokencode = cache["scratchtoks"] .command -- tokens.commands.register_toks +local skipcode = cache["scratchskip"] .command -- tokens.commands.register_glue +local muskipcode = cache["scratchmuskip"] .command -- tokens.commands.register_mu_glue +local conditioncode = cache["iftrue"] .command -- tokens.commands.if_test local types = { [dimencode] = "dimen", @@ -82,10 +81,6 @@ setmetatableindex(texmodes, function(t,k) end end) -setmetatablenewindex(texmodes, function(t,k) - report_mode("you cannot set the %s named %a this way","mode",k) -end) - setmetatableindex(texsystemmodes, function(t,k) local m = systemmodes[k] if m then @@ -101,59 +96,38 @@ setmetatableindex(texsystemmodes, function(t,k) end end) -setmetatablenewindex(texsystemmodes, function(t,k) - report_mode("you cannot set the %s named %a this way","systemmode",k) -end) - -setmetatablenewindex(texconstants, function(t,k) - report_mode("you cannot set the %s named %a this way","constant",k) -end) - -setmetatablenewindex(texconditionals, function(t,k) - report_mode("you cannot set the %s named %a this way","conditional",k) -end) - -setmetatablenewindex(texifs, function(t,k) - -- just ignore -end) +do -- we could do the same as in lmtx (use the mode) -if CONTEXTLMTXMODE > 0 then + local trialtypesettingstate = createtoken("trialtypesettingstate").index + local texgetcount = tex.getcount - iftrue = cache["iftrue"].index - - -- if we really need performance we can have a dedicated cache for each - -- kind of variable - - setmetatableindex(texconstants, function(t,k) - return cache[k].command == countcode and texgetcount(k) or 0 + context.settrialtypesettingmethod(function() + return texgetcount(trialtypesettingstate) ~= 0 end) - setmetatableindex(texconditionals, function(t,k) -- 0 == true - return cache[k].command == countcode and texgetcount(k) == 0 - end) - - setmetatableindex(texifs, function(t,k) - local c = cache[k] - print(k) - inspect(c) - return c.command == conditioncode and c.index == iftrue - end) +end -else +setmetatablenewindex(texmodes, function(t,k) report_mode("you cannot set the %s named %a this way","mode", k) end) +setmetatablenewindex(texsystemmodes, function(t,k) report_mode("you cannot set the %s named %a this way","systemmode", k) end) +setmetatablenewindex(texconstants, function(t,k) report_mode("you cannot set the %s named %a this way","constant", k) end) +setmetatablenewindex(texconditionals, function(t,k) report_mode("you cannot set the %s named %a this way","conditional",k) end) +setmetatablenewindex(texifs, function(t,k) end) - setmetatableindex(texconstants, function(t,k) - return cache[k].mode ~= 0 and texgetcount(k) or 0 - end) +setmetatablenewindex(texifs, function(t,k) + -- just ignore +end) - setmetatableindex(texconditionals, function(t,k) -- 0 == true - return cache[k].mode ~= 0 and texgetcount(k) == 0 - end) +setmetatableindex(texconstants, function(t,k) + return cache[k].mode ~= 0 and texgetcount(k) or 0 +end) - setmetatableindex(texifs, function(t,k) - return cache[k].mode == iftrue - end) +setmetatableindex(texconditionals, function(t,k) -- 0 == true + return cache[k].mode ~= 0 and texgetcount(k) == 0 +end) -end +setmetatableindex(texifs, function(t,k) + return cache[k].mode == iftrue +end) tex.isdefined = isdefined diff --git a/tex/context/base/mkiv/core-env.mkiv b/tex/context/base/mkiv/core-env.mkiv index 09de435e7..0f042f815 100644 --- a/tex/context/base/mkiv/core-env.mkiv +++ b/tex/context/base/mkiv/core-env.mkiv @@ -17,7 +17,7 @@ \unprotect -\def\wildcardsymbol{*} +\ifdefined\wildcardsymbol \else \def\wildcardsymbol{*} \fi %D Modes: %D @@ -104,10 +104,14 @@ % demo: trialtypesetting is a systemmode as well as an if +\pushoverloadmode + \newsystemmode{trialtypesetting} \expandafter\let\csname\??mode\systemmodeprefix trialtypesetting\endcsname\trialtypesettingstate +\popoverloadmode + \appendtoks \trialtypesettingstate\enabledmode \luacopyinputnodes\plusone @@ -588,13 +592,15 @@ \def\syst_setups_start_loc{\ifsecondargument\expandafter\syst_setups_start_loc_c\else\expandafter\syst_setups_start_loc_d\fi} \def\syst_setups_start_tex{\ifsecondargument\expandafter\syst_setups_start_tex_c\else\expandafter\syst_setups_start_tex_d\fi} +% no need for \the\t_syst_setups_lua in the next, now too often + \def\syst_setups_start_lua_a{\the\t_syst_setups_lua\dodoubleempty\syst_setups_start_lua} % [ ] delimited \def\syst_setups_start_xml_a{\the\t_syst_setups_xml\dodoubleempty\syst_setups_start_xml} % [ ] delimited \def\syst_setups_start_raw_a{\the\t_syst_setups_raw\dodoubleempty\syst_setups_start_raw} % [ ] delimited \def\syst_setups_start_loc_a{\the\t_syst_setups_loc\dodoubleempty\syst_setups_start_loc} % [ ] delimited \def\syst_setups_start_tex_a{\the\t_syst_setups_tex\dodoubleempty\syst_setups_start_tex} % [ ] delimited -% empty preserves inner {} (is removed by the \expandafter{#3}) +% empty preserves inner {} (is removed by the \expandafter{#3}) .. hm, looks old \def\syst_setups_start_lua_b#1 {\the\t_syst_setups_lua\syst_setups_start_lua_indeed\empty{#1}\empty} % space delimited \def\syst_setups_start_xml_b#1 {\the\t_syst_setups_xml\syst_setups_start_xml_indeed\empty{#1}\empty} % space delimited diff --git a/tex/context/base/mkiv/core-env.mkxl b/tex/context/base/mkiv/core-env.mkxl new file mode 100644 index 000000000..2d7c22afd --- /dev/null +++ b/tex/context/base/mkiv/core-env.mkxl @@ -0,0 +1,819 @@ +%D \module +%D [ file=core-env, % was core-new +%D version=1995.01.01, % wrong +%D title=\CONTEXT\ Core Macros, +%D subtitle=New ones, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Core Macros / Environments} + +\registerctxluafile{core-env}{autosuffix} + +\unprotect + +%D Modes: +%D +%D \starttyping +%D \enablemode[screen,paper,bound] +%D +%D \doifmodeelse {paper} {this} {that} +%D \doifmode {paper,screen} {this} +%D \doifnotmode {paper,bound} {that} +%D +%D \startmode [list] +%D \stopmode +%D +%D \startnotmode [list] +%D \stopnotmode +%D \stoptyping +%D +%D system modes have a * as prefix +%D +%D Sometimes, we want to prevent a mode for being set. Think of situations where a +%D style enables a mode, but an outer level style does not want that. Preventing can +%D be considered a permanent disabling on forehand. + +\aliased\let\systemmodeprefix\wildcardsymbol + +% we will have \installcorenamespace{mode} but need some hackery at the lua end then + +% TODO: make them mutable, also at the lua end + +\installcorenamespace{modestack} + +\immutable\def\??mode{mode>} % special namespace, also used at lua end + +\permanent\protected\def\newmode #1{\ifcsname \??mode#1\endcsname\else\setmode{#1}\fi} +\permanent\protected\def\setmode #1{\expandafter \integerdef\csname\??mode#1\endcsname\plusone} +\permanent\protected\def\resetmode #1{\expandafter \integerdef\csname\??mode#1\endcsname\zerocount} +\permanent\protected\def\globalsetmode #1{\global\expandafter\integerdef\csname\??mode#1\endcsname\plusone} +\permanent\protected\def\globalresetmode #1{\global\expandafter\integerdef\csname\??mode#1\endcsname\zerocount} + +\permanent\protected\def\newsystemmode #1{\ifcsname \??mode\systemmodeprefix#1\endcsname\else\setsystemmode{#1}\fi} +\permanent\protected\def\setsystemmode #1{\expandafter \integerdef\csname\??mode\systemmodeprefix#1\endcsname\plusone} +\permanent\protected\def\resetsystemmode #1{\expandafter \integerdef\csname\??mode\systemmodeprefix#1\endcsname\zerocount} +\permanent\protected\def\globalsetsystemmode #1{\global\expandafter\integerdef\csname\??mode\systemmodeprefix#1\endcsname\plusone} +\permanent\protected\def\globalresetsystemmode#1{\global\expandafter\integerdef\csname\??mode\systemmodeprefix#1\endcsname\zerocount} + +\expandafter \appendtoks + \expandafter\integerdef\csname\??mode\systemmodeprefix trialtypesetting\endcsname\plusone + \luacopyinputnodes\plusone +\to \everysettrialtypesetting + +\expandafter \appendtoks + \expandafter\integerdef\csname\??mode\systemmodeprefix trialtypesetting\endcsname\zerocount + \luacopyinputnodes\zerocount +\to \everyresettrialtypesetting + +\pushoverloadmode \newsystemmode{trialtypesetting} \popoverloadmode + +\the\everyresettrialtypesetting + +% user ones + +\mutable\let\syst_mode_prefix\relax + +\protected\def\preventmode{\unprotect\syst_modes_prevent} +\protected\def\enablemode {\unprotect\syst_modes_enable } +\protected\def\disablemode{\unprotect\syst_modes_disable} + +\protected\def\globalpreventmode{\let\syst_mode_prefix\global\unprotect\syst_modes_prevent} +\protected\def\globalenablemode {\let\syst_mode_prefix\global\unprotect\syst_modes_enable } +\protected\def\globaldisablemode{\let\syst_mode_prefix\global\unprotect\syst_modes_disable} + +\def\syst_modes_prevent[#1]{\protect\fastprocesscommacommand[#1]\syst_modes_prevent_indeed\let\syst_mode_prefix\relax} +\def\syst_modes_enable [#1]{\protect\fastprocesscommacommand[#1]\syst_modes_enable_indeed \let\syst_mode_prefix\relax} +\def\syst_modes_disable[#1]{\protect\fastprocesscommacommand[#1]\syst_modes_disable_indeed\let\syst_mode_prefix\relax} + +\def\syst_modes_prevent_indeed#1% + {\ifcsname\??mode#1\endcsname\else\setmode{#1}\fi + \syst_mode_prefix\expandafter\integerdef\lastnamedcs\plustwo} + +\def\syst_modes_enable_indeed#1% we can speed it up by moving the new outside + {\ifcsname\??mode#1\endcsname\else\setmode{#1}\fi + \ifnum\lastnamedcs=\plustwo\else + \syst_mode_prefix\expandafter\integerdef\lastnamedcs\plusone + \fi} + +\def\syst_modes_disable_indeed#1% + {\ifcsname\??mode#1\endcsname\else\setmode{#1}\fi + \ifnum\lastnamedcs=\plustwo\else + \syst_mode_prefix\expandafter\integerdef\lastnamedcs\zerocount + \fi} + +%D If you do a lot of mode testing, it makes sense to define modes (or disable them +%D explicitly if unset. This makes testing twice as fast. Often one enables modes +%D beforehand, in which case \type {\definemode} would reset the mode. The optional +%D second argument \type {keep} will prevent changing the already set mode but defines +%D it when undefined. + +\permanent\protected\def\definemode + {\unprotect + \syst_modes_define} + +\tolerant\def\syst_modes_define[#1]#*[#2]% + {\protect + \edef\m_modes_asked{#2}% + \fastprocesscommacommand[#1]\syst_modes_define_indeed} + +\def\syst_modes_define_indeed#1% + {\ifcsname\??mode#1\endcsname + % already set + \else + \newmode{#1}% + \fi + \ifx\m_modes_asked\v!keep + % not changes, disabled when undefined + \else + \expandafter\integerdef\lastnamedcs\ifx\m_modes_asked\v!yes\plusone\else\zerocount\fi + \fi} + +% handy for mp + +\def\booleanmodevalue#1% + {\ifcsname\??mode#1\endcsname + \ifcase\lastnamedcs + \s!false + \or + \s!true + \else + \s!false + \fi + \else + \s!false + \fi} + +% check macros + +\newconditional\c_checked_mode + +% one + +\def\syst_modes_check_indeed#1% + {\ifcsname\??mode#1\endcsname + \ifcase\lastnamedcs\else + \let\syst_modes_check_step\gobbleoneargument + \fi + \fi} + +\def\syst_modes_check_nop#1#2#3% + {\let\syst_modes_check_step\syst_modes_check_indeed + \fastprocesscommacommand[#3]\syst_modes_check_step + \ifx\syst_modes_check_step\gobbleoneargument + \expandafter#1% + \else + \expandafter#2% + \fi} + +\def\syst_modes_check_yes#1#2#3% + {\ifcase\lastnamedcs + \expandafter#2% + \or + \expandafter#1% + \else + \expandafter#2% + \fi} + +\def\syst_modes_check_lr#1#2#3% + {\ifcsname\??mode#3\endcsname + \expandafter\syst_modes_check_yes + \else + \expandafter\syst_modes_check_nop + \fi#1#2{#3}} + +\def\syst_modes_check_ss#1#2[#3]% + {\ifcsname\??mode#3\endcsname + \expandafter\syst_modes_check_yes + \else + \expandafter\syst_modes_check_nop + \fi#1#2{#3}} + +% all + +\def\syst_modes_check_all_indeed#1% + {\ifcsname\??mode#1\endcsname + \ifcase\lastnamedcs + \let\syst_modes_check_all_step\gobbleoneargument + \or + % enabled + \else + \let\syst_modes_check_all_step\gobbleoneargument + \fi + \else + \let\syst_modes_check_all_step\gobbleoneargument + \fi} + +\def\syst_modes_check_all_lr#1#2#3% + {\let\syst_modes_check_all_step\syst_modes_check_all_indeed + \fastprocesscommacommand[#3]\syst_modes_check_all_step + \ifx\syst_modes_check_all_step\gobbleoneargument + \expandafter#2% + \else + \expandafter#1% + \fi} + +\def\syst_modes_check_all_ss#1#2[#3]% + {\let\syst_modes_check_all_step\syst_modes_check_all_indeed + \fastprocesscommacommand[#3]\syst_modes_check_all_step + \ifx\syst_modes_check_all_step\gobbleoneargument + \expandafter#2% + \else + \expandafter#1% + \fi} + +\permanent\protected\def\doifelsemode {\syst_modes_check_lr \firstoftwoarguments \secondoftwoarguments} +\permanent\protected\def\doifmode {\syst_modes_check_lr \firstofoneargument \gobbleoneargument} +\permanent\protected\def\doifnotmode {\syst_modes_check_lr \gobbleoneargument \firstofoneargument} +\permanent\protected\def\startmode {\syst_modes_check_ss \donothing \syst_modes_stop_yes} +\permanent\protected\def\startnotmode {\syst_modes_check_ss \syst_modes_stop_nop \donothing} +\permanent\protected\def\doifelseallmodes{\syst_modes_check_all_lr\firstoftwoarguments \secondoftwoarguments} +\permanent\protected\def\doifallmodes {\syst_modes_check_all_lr\firstofoneargument \gobbleoneargument} +\permanent\protected\def\doifnotallmodes {\syst_modes_check_all_lr\gobbleoneargument \firstofoneargument} +\permanent\protected\def\startallmodes {\syst_modes_check_all_ss\donothing \syst_modes_stop_all_yes} +\permanent\protected\def\startnotallmodes{\syst_modes_check_all_ss\syst_modes_stop_all_nop\donothing} + +\aliased\let\doifmodeelse \doifelsemode +\aliased\let\doifallmodeselse\doifelseallmodes + +\permanent\protected\def\stopmode {} % no relax +\permanent\protected\def\stopnotmode {} % no relax +\permanent\protected\def\stopallmodes {} % no relax +\permanent\protected\def\stopnotallmodes{} % no relax + +\def\syst_modes_stop_yes #1\stopmode {} +\def\syst_modes_stop_nop #1\stopnotmode {} +\def\syst_modes_stop_all_yes#1\stopallmodes {} +\def\syst_modes_stop_all_nop#1\stopnotallmodes{} + +%D Pushing/popping: + +\permanent\protected\def\pushmode[#1]{\expandafter\pushmacro\csname\??mode#1\endcsname} +\permanent\protected\def\popmode [#1]{\expandafter\popmacro \csname\??mode#1\endcsname} + +\permanent\protected\def\pushsystemmode#1{\expandafter\pushmacro\csname\??mode\systemmodeprefix#1\endcsname} +\permanent\protected\def\popsystemmode #1{\expandafter\popmacro \csname\??mode\systemmodeprefix#1\endcsname} + +%D Here is a relatively new variant of mode checking: +%D +%D \starttyping +%D \enablemode[two] +%D +%D \startmodeset +%D [one] {1} +%D [two] {2} +%D [two] {2} +%D [three] {3} +%D [default] {?} +%D \stopmodeset +%D +%D \startmodeset +%D [one] {1} +%D [three] {3} +%D [default] {?} +%D \stopmodeset +%D +%D \startmodeset +%D [one] { +%D \input tufte +%D } +%D [two] { +%D \startmodeset +%D [one] {1} +%D [two] {2} +%D [two] {2} +%D [three] {3} +%D [default] {?} +%D \stopmodeset +%D } +%D [three] { +%D \input zapf +%D } +%D [default] { +%D \input ward +%D } +%D \stopmodeset +%D \stoptyping + +\newconditional\c_syst_modes_set_done % conditionals can be pushed/popped + +\permanent\protected\def\startmodeset + {\pushmacro\c_syst_modes_set_done + \setfalse\c_syst_modes_set_done + \doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit} + +\aliased\let\stopmodeset\relax + +\def\syst_modes_set_start[#1]% + {\edef\m_mode_case{#1}% + \unless\ifx\m_mode_case\s!default + \expandafter\syst_modes_set_check + \orelse\ifconditional\c_syst_modes_set_done + \expandafter\syst_modes_set_quit + \else + \expandafter\syst_modes_set_yes + \fi} + +\def\syst_modes_set_check + {\syst_modes_check_lr\syst_modes_set_yes\syst_modes_set_nop\m_mode_case} + +\def\syst_modes_set_yes#1% + {\settrue\c_syst_modes_set_done + #1% + \doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit} + +\def\syst_modes_set_nop#1% + {\doifelsenextoptionalcs\syst_modes_set_start\syst_modes_set_quit} + +\def\syst_modes_set_quit#-\stopmodeset + {\popmacro\c_syst_modes_set_done} + +%D Lets now set a mode: + +\enablemode[mkiv] \newsystemmode{mkiv} \setsystemmode{mkiv} + +%D Setups: + +\installcorenamespace{setup} % we can probably get rid of some :'s later on + +% \protected\def\startsetups{} % to please dep checker +% \protected\def\stopsetups {} % to please dep checker +% +% \protected\def\setups{\doifelsenextbgroup\syst_setups_a\syst_setups_b} % {..} or [..] +% \protected\def\setup {\doifelsenextbgroup\syst_setups \syst_setups_c} % {..} or [..] +% +% \def\syst_setups_a #1{\processcommacommand[#1]\syst_setups} % {..} +% \def\syst_setups_b[#1]{\processcommacommand[#1]\syst_setups} % [..] +% \def\syst_setups_c[#1]{\syst_setups{#1}} % [..] + +\permanent\protected\tolerant\def\setups[#1]#;#2{\processcommacommand[#1#2]\syst_setups} % {..} or [..] +\permanent\protected\tolerant\def\setup [#1]#;#2{\syst_setups{#1#2}} % {..} or [..] + +\letvalue{\??setup:\??empty}\gobbleoneargument + +\def\syst_setups#1% the grid option will be extended to other main modes + {\csname\??setup + \ifgridsnapping + \ifcsname\??setup\v!grid:#1\endcsname\v!grid:#1\else:\ifcsname\??setup:#1\endcsname#1\else\??empty\fi\fi + \else + :\ifcsname\??setup:#1\endcsname#1\else\??empty\fi + \fi + \endcsname\empty} % takes one argument + +% no checking and we assume it being defined: + +\def\fastsetup #1{\csname\??setup:#1\endcsname\empty} +\def\fastsetupwithargument #1{\csname\??setup:#1\endcsname} % swapped per 2015-08-30 +\def\fastsetupwithargumentswapped#1#2{\csname\??setup:#2\endcsname{#1}}% swapped per 2015-09-05 + +% the next one is meant for \c!setups situations, hence the check for +% a shortcut + +\let\m_syst_setups_asked\empty + +\def\doprocesslocalsetups#1% sort of public, fast local variant + {\edef\m_syst_setups_asked{#1}% + \ifx\m_syst_setups_asked\empty\else + \expandafter\syst_setups_process_local + \fi} + +\protected\def\usesetupsparameter#1% + {\edef\m_syst_setups_asked{#1\c!setups}% + \ifx\m_syst_setups_asked\empty\else + \expandafter\syst_setups_process_local + \fi} + +% setups=S1 +% setups=lua(S2) +% setups=S3 +% setups={S1,lua(S2),xml(test{123}),S3} + +\def\syst_setups_process_local + {\clf_autosetups{\m_syst_setups_asked}% + \relax} % let's prevent lookahead + +\def\autosetups#1% + {\clf_autosetups{#1}} + +\edef\setupwithargument#1% saves a few expansions + {\noexpand\csname\??setup:\noexpand\ifcsname\??setup:#1\endcsname#1\noexpand\else\??empty\noexpand\fi\endcsname} + +\edef\setupwithargumentswapped#1#2% saves a few expansions (can be \let) + {\noexpand\csname\??setup:\noexpand\ifcsname\??setup:#2\endcsname#2\noexpand\else\??empty\noexpand\fi\endcsname{#1}} + +\let\directsetup\syst_setups +\let\texsetup \syst_setups % nicer than \directsetup and more en par with xmlsetup and luasetup + +\protected\def\doifelsesetups#1% to be done: grid + {\ifcsname\??setup:#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\let\doifsetupselse\doifelsesetups + +\protected\def\doifsetups#1% to be done: grid + {\ifcsname\??setup:#1\endcsname + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\protected\def\doifnotsetups#1% to be done: grid + {\ifcsname\??setup:#1\endcsname + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +% maybe some day: +% +% \protected\def\fastsetupfallback#1#2% +% {\ifcsname\??setup:#1\endcsname +% \expandafter\lastnamedcs +% \else +% \csname\??setup:#2\expandafter\endcsname +% \fi} +% +% or +% +% \protected\def\fastsetupfallback#1#2#3% prefix preferred fallback +% {\ifcsname\??setup:#1#2\endcsname +% \expandafter\lastnamedcs +% \else +% \csname\??setup:#1#3\expandafter\endcsname +% \fi} + +% \startluasetups oeps +% context("DONE") +% a = 1 +% b = 1 +% \stopluasetups +% +% \luasetup{oeps} +% +% \startsetups xxx +% ziezo +% \stopsetups +% +% \directsetup{xxx} +% +% \startxmlsetups zzz +% [[#1]] +% \stopxmlsetups +% +% \xmlsetup{123}{zzz} +% +% \startbuffer[what] +% context("DONE") +% \stopbuffer +% +% \startbuffer +% context("MORE") +% \stopbuffer +% +% \ctxluabuffer[what] +% +% \ctxluabuffer + +\newtoks\t_syst_setups_tex \appendtoks + \catcode\endoflineasciicode \ignorecatcode +\to \t_syst_setups_tex + +\newtoks\t_syst_setups_loc \appendtoks + \catcode\endoflineasciicode \ignorecatcode +\to \t_syst_setups_loc + +\newtoks\t_syst_setups_raw \appendtoks + % nothing +\to \t_syst_setups_raw + +\newtoks\t_syst_setups_xml \appendtoks + \catcode\endoflineasciicode\ignorecatcode + \catcode\barasciicode \othercatcode +\to \t_syst_setups_xml + +\newtoks\t_syst_setups_lua \appendtoks + \obeylualines + \obeyluatokens +\to \t_syst_setups_lua + +% Is doglobal still relevant? Maybe always global? Or never? Anyway, it will become obsolete. + +% \protected\def\startluasetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_lua_a\syst_setups_start_lua_b} \let\stopluasetups \relax +% \protected\def\startxmlsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_xml_a\syst_setups_start_xml_b} \let\stopxmlsetups \relax +% \protected\def\startrawsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_raw_a\syst_setups_start_raw_b} \let\stoprawsetups \relax +% \protected\def\startlocalsetups{\begingroup\doifelsenextoptionalcs\syst_setups_start_loc_a\syst_setups_start_loc_b} \let\stoplocalsetups\relax +% \protected\def\startsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_tex_a\syst_setups_start_tex_b} \let\stopsetups \relax +% +% \def\syst_setups_start_lua_indeed#1#2#3\stopluasetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}} +% \def\syst_setups_start_xml_indeed#1#2#3\stopxmlsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}} +% \def\syst_setups_start_raw_indeed#1#2#3\stoprawsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}} +% \def\syst_setups_start_loc_indeed#1#2#3\stoplocalsetups{\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}} +% \def\syst_setups_start_tex_indeed#1#2#3\stopsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\expandafter\endcsname\expandafter##\expandafter1\expandafter{#3}} +% +% \def\syst_setups_start_lua{\ifsecondargument\expandafter\syst_setups_start_lua_c\else\expandafter\syst_setups_start_lua_d\fi} +% \def\syst_setups_start_xml{\ifsecondargument\expandafter\syst_setups_start_xml_c\else\expandafter\syst_setups_start_xml_d\fi} +% \def\syst_setups_start_raw{\ifsecondargument\expandafter\syst_setups_start_raw_c\else\expandafter\syst_setups_start_raw_d\fi} +% \def\syst_setups_start_loc{\ifsecondargument\expandafter\syst_setups_start_loc_c\else\expandafter\syst_setups_start_loc_d\fi} +% \def\syst_setups_start_tex{\ifsecondargument\expandafter\syst_setups_start_tex_c\else\expandafter\syst_setups_start_tex_d\fi} +% +% % no need for \the\t_syst_setups_lua in the next, now too often +% +% \def\syst_setups_start_lua_a{\the\t_syst_setups_lua\dodoubleempty\syst_setups_start_lua} % [ ] delimited +% \def\syst_setups_start_xml_a{\the\t_syst_setups_xml\dodoubleempty\syst_setups_start_xml} % [ ] delimited +% \def\syst_setups_start_raw_a{\the\t_syst_setups_raw\dodoubleempty\syst_setups_start_raw} % [ ] delimited +% \def\syst_setups_start_loc_a{\the\t_syst_setups_loc\dodoubleempty\syst_setups_start_loc} % [ ] delimited +% \def\syst_setups_start_tex_a{\the\t_syst_setups_tex\dodoubleempty\syst_setups_start_tex} % [ ] delimited +% +% % empty preserves inner {} (is removed by the \expandafter{#3}) +% +% \def\syst_setups_start_lua_b#1 {\the\t_syst_setups_lua\syst_setups_start_lua_indeed\empty{#1}\empty} % space delimited +% \def\syst_setups_start_xml_b#1 {\the\t_syst_setups_xml\syst_setups_start_xml_indeed\empty{#1}\empty} % space delimited +% \def\syst_setups_start_raw_b#1 {\the\t_syst_setups_raw\syst_setups_start_raw_indeed\empty{#1}\empty} % space delimited +% \def\syst_setups_start_loc_b#1 {\the\t_syst_setups_loc\syst_setups_start_loc_indeed\empty{#1}\empty} % space delimited +% \def\syst_setups_start_tex_b#1 {\the\t_syst_setups_tex\syst_setups_start_tex_indeed\empty{#1}\empty} % space delimited +% +% \def\syst_setups_start_lua_c[#1][#2]{\the\t_syst_setups_lua\syst_setups_start_lua_indeed{#1}{#2}\empty} % [..] [..] +% \def\syst_setups_start_xml_c[#1][#2]{\the\t_syst_setups_xml\syst_setups_start_xml_indeed{#1}{#2}\empty} % [..] [..] +% \def\syst_setups_start_raw_c[#1][#2]{\the\t_syst_setups_raw\syst_setups_start_raw_indeed{#1}{#2}\empty} % [..] [..] +% \def\syst_setups_start_loc_c[#1][#2]{\the\t_syst_setups_loc\syst_setups_start_loc_indeed{#1}{#2}\empty} % [..] [..] +% \def\syst_setups_start_tex_c[#1][#2]{\the\t_syst_setups_tex\syst_setups_start_tex_indeed{#1}{#2}\empty} % [..] [..] +% +% \def\syst_setups_start_lua_d[#1][#2]{\the\t_syst_setups_lua\syst_setups_start_lua_indeed\empty{#1}\empty} % [..] +% \def\syst_setups_start_xml_d[#1][#2]{\the\t_syst_setups_xml\syst_setups_start_xml_indeed\empty{#1}\empty} % [..] +% \def\syst_setups_start_raw_d[#1][#2]{\the\t_syst_setups_raw\syst_setups_start_raw_indeed\empty{#1}\empty} % [..] +% \def\syst_setups_start_loc_d[#1][#2]{\the\t_syst_setups_loc\syst_setups_start_loc_indeed\empty{#1}\empty} % [..] +% \def\syst_setups_start_tex_d[#1][#2]{\the\t_syst_setups_tex\syst_setups_start_tex_indeed\empty{#1}\empty} % [..] + +\permanent\protected\def\startluasetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_lua_yes\syst_setups_start_lua_nop} \aliased\let\stopluasetups \relax +\permanent\protected\def\startxmlsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_xml_yes\syst_setups_start_xml_nop} \aliased\let\stopxmlsetups \relax +\permanent\protected\def\startrawsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_raw_yes\syst_setups_start_raw_nop} \aliased\let\stoprawsetups \relax +\permanent\protected\def\startlocalsetups{\begingroup\doifelsenextoptionalcs\syst_setups_start_loc_yes\syst_setups_start_loc_nop} \aliased\let\stoplocalsetups\relax +\permanent\protected\def\startsetups {\begingroup\doifelsenextoptionalcs\syst_setups_start_tex_yes\syst_setups_start_tex_nop} \aliased\let\stopsetups \relax + +\def\syst_setups_start_lua_two#1#2#+\stopluasetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\endcsname##1{#3}} +\def\syst_setups_start_xml_two#1#2#+\stopxmlsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\endcsname##1{#3}} +\def\syst_setups_start_raw_two#1#2#+\stoprawsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\endcsname##1{#3}} +\def\syst_setups_start_loc_two#1#2#+\stoplocalsetups{\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\endcsname##1{#3}} +\def\syst_setups_start_tex_two#1#2#+\stopsetups {\endgroup\dodoglobal\expandafter\def\csname\??setup#1:#2\endcsname##1{#3}} + +\tolerant\def\syst_setups_start_lua_yes[#1]#*[#2]% + {\the\t_syst_setups_lua + \ifarguments\expandafter\syst_setups_start_lua_one + \or \expandafter\syst_setups_start_lua_one + \else \expandafter\syst_setups_start_lua_two + \fi{#1}{#2}} + +\tolerant\def\syst_setups_start_xml_yes[#1]#*[#2]% + {\the\t_syst_setups_xml + \ifarguments\expandafter\syst_setups_start_xml_one + \or \expandafter\syst_setups_start_xml_one + \else \expandafter\syst_setups_start_xml_two + \fi{#1}{#2}} + +\tolerant\def\syst_setups_start_raw_yes[#1]#*[#2]% + {\the\t_syst_setups_raw + \ifarguments\expandafter\syst_setups_start_raw_one + \or \expandafter\syst_setups_start_raw_one + \else \expandafter\syst_setups_start_raw_two + \fi{#1}{#2}} + +\tolerant\def\syst_setups_start_loc_yes[#1]#*[#2]% + {\the\t_syst_setups_loc + \ifarguments\expandafter\syst_setups_start_loc_one + \or \expandafter\syst_setups_start_loc_one + \else \expandafter\syst_setups_start_loc_two + \fi{#1}{#2}} + +\tolerant\def\syst_setups_start_tex_yes[#1]#*[#2]% + {\the\t_syst_setups_tex + \ifarguments\expandafter\syst_setups_start_tex_one + \or \expandafter\syst_setups_start_tex_one + \else \expandafter\syst_setups_start_tex_two + \fi{#1}{#2}} + +\def\syst_setups_start_lua_nop#1 {\the\t_syst_setups_lua\syst_setups_start_lua_two{}{#1}} % space delimited +\def\syst_setups_start_xml_nop#1 {\the\t_syst_setups_xml\syst_setups_start_xml_two{}{#1}} % space delimited +\def\syst_setups_start_raw_nop#1 {\the\t_syst_setups_raw\syst_setups_start_raw_two{}{#1}} % space delimited +\def\syst_setups_start_loc_nop#1 {\the\t_syst_setups_loc\syst_setups_start_loc_two{}{#1}} % space delimited +\def\syst_setups_start_tex_nop#1 {\the\t_syst_setups_tex\syst_setups_start_tex_two{}{#1}} % space delimited + +\def\syst_setups_start_lua_one#1#2{\syst_setups_start_lua_two{}{#1}} % [..] +\def\syst_setups_start_xml_one#1#2{\syst_setups_start_xml_two{}{#1}} % [..] +\def\syst_setups_start_raw_one#1#2{\syst_setups_start_raw_two{}{#1}} % [..] +\def\syst_setups_start_loc_one#1#2{\syst_setups_start_loc_two{}{#1}} % [..] +\def\syst_setups_start_tex_one#1#2{\syst_setups_start_tex_two{}{#1}} % [..] + +\def\luasetup#1{\ctxlua{\syst_setups{#1}}} + +%D System setups: + +\let\systemsetupsprefix\wildcardsymbol + +\def\systemsetups#1{\syst_setups{\systemsetupsprefix#1}} + +\protected\def\resetsetups[#1]% see x-fo for usage + {\ifcsname\??setup\ifgridsnapping\v!grid\fi:#1\endcsname + \dodoglobal\undefinevalue{\??setup\ifgridsnapping\v!grid\fi:#1}% + \else + \dodoglobal\undefinevalue{\??setup:#1}% + \fi} + +\protected\def\copysetups + {\dodoubleargument\syst_setups_copy} + +\def\syst_setups_copy[#1][#2]% + {\ifcsname\??setup:#2\endcsname + \expandafter\let\csname\??setup:#1\expandafter\endcsname\lastnamedcs + \fi} + +\protected\def\showsetupsdefinition[#1]% + {\showvalue{\??setup:#1}} % temp hack for debugging + +%D \macros +%D {setvariables,getvariable,getvariabledefault} +%D +%D \starttyping +%D \setvariables[xx][title=] +%D \setvariables[xx][title=test test] +%D \setvariables[xx][title=test $x=1$ test] % fatal error reported +%D \setvariables[xx][title=test {$x=1$} test] +%D \setvariables[xx][title] % fatal error reported +%D \setvariables[xx][titletitel=e] +%D \stoptyping + +\installcorenamespace{variables} + +\permanent\protected\def\setvariables {\syst_variables_set[\getrawparameters ]} +\permanent\protected\def\setevariables{\syst_variables_set[\getraweparameters]} +\permanent\protected\def\setgvariables{\syst_variables_set[\getrawgparameters]} +\permanent\protected\def\setxvariables{\syst_variables_set[\getrawxparameters]} + +% \protected\def\globalsetvariables % obsolete +% {\dotripleargument\syst_variables_set[\globalgetrawparameters]} + +\tolerant\def\syst_variables_set[#1]#*[#2]#*[#3]% tricky, test on s-pre-60 + {\doifelse{#2}\currentvariableclass + {#1[\??variables#2:][#3]}% + {\pushmacro\currentvariableclass + \def\currentvariableclass{#2}% + \getvariable{#2}\s!reset + #1[\??variables#2:][#3]% + \getvariable{#2}\s!set + \popmacro\currentvariableclass}} + +\permanent\protected\def\setvariable #1#2#3{\expandafter\def \csname\??variables#1:#2\endcsname{#3}} +\permanent\protected\def\setevariable#1#2#3{\expandafter\edef\csname\??variables#1:#2\endcsname{#3}} +\permanent\protected\def\setgvariable#1#2#3{\expandafter\gdef\csname\??variables#1:#2\endcsname{#3}} +\permanent\protected\def\setxvariable#1#2#3{\expandafter\xdef\csname\??variables#1:#2\endcsname{#3}} + +\permanent \def\getvariable #1#2{\begincsname\??variables#1:#2\endcsname} +\permanent\protected\def\showvariable#1#2{\showvalue{\begincsname\??variables#1:#2\endcsname}} + +\let\currentvariableclass\empty + +%D \macros +%D {checkvariables} +%D +%D I'll probably forget that this on exists. + +\let\m_syst_variables_temp\empty + +\permanent\tolerant\def\checkvariables[#1]#*[#2]% + {\dogetparameters\syst_variables_check_value[#1][#2]} + +\def\syst_variables_check_value#1#2#3% + {\ifcsname\??variables#1:#2\endcsname + \edef\m_syst_variables_temp{\lastnamedcs}% + \ifx\m_syst_variables_temp\empty + \expandafter\def\csname\??variables#1:#2\endcsname{#3}% + \fi + \else + \expandafter\def\csname\??variables#1:#2\endcsname{#3}% + \fi} + +%D \macros +%D {doifelsevariable,doifvariable,doifnotvariable} +%D +%D A few trivial macros: + +\permanent\protected\def\doifelsevariable#1#2% + {\ifcsname\??variables#1:#2\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifvariableelse\doifelsevariable + +\permanent\protected\def\doifvariable#1#2% + {\ifcsname\??variables#1:#2\endcsname + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\doifnotvariable#1#2% + {\ifcsname\??variables#1:#2\endcsname + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +%D A few more (we could use a public test variable so that we only need to expand +%D once, assuming expandable variables): + +\letvalue{\??variables:}\empty + +\permanent\protected\def\doifelseemptyvariable#1#2% + {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}% + \ifx\m_syst_string_one\empty + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifemptyvariableelse\doifelseemptyvariable + +\permanent\protected\def\doifemptyvariable#1#2% + {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}% + \ifx\m_syst_string_one\empty + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +\permanent\protected\def\doifnotemptyvariable#1#2% + {\edef\m_syst_string_one{\begincsname\??variables#1:#2\endcsname}% + \ifx\m_syst_string_one\empty + \expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\permanent\def\getvariabledefault#1#2% #3% can be command + {\ifcsname\??variables#1:#2\endcsname + \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\permanent\tolerant\protected\def\setupenv[#1]% + {\syst_variables_set[\getrawparameters][\s!environment][#1]} + +\permanent\protected\def\doifelseenv{\doifelsevariable \s!environment} +\permanent\protected\def\doifenv {\doifvariable \s!environment} +\permanent\protected\def\doifnotenv {\doifnotvariable \s!environment} +\permanent \def\env {\getvariable \s!environment} +\permanent \def\envvar {\getvariabledefault\s!environment} + +\aliased\let\doifenvelse\doifelseenv + +%D \macros +%D {defineselector,setupselector,select,directselect} +%D +%D \starttyping +%D \defineselector[caption][max=2,n=2] +%D +%D \start +%D \setupselector[caption][n=1] +%D \placelist[figure][criterium=all] +%D \stop +%D +%D \starttext +%D \placefigure +%D {\select{caption}{zapf}{\input zapf \relax}} +%D {} +%D \stoptext +%D \stoptyping + +\installcorenamespace{selector} + +\permanent\tolerant\protected\def\defineselector[#1]#*[#2]{\getparameters[\??selector#1][\c!max=\plusone,\c!n=\plusone,#2]} +\permanent\tolerant\protected\def\setupselector [#1]#*[#2]{\getparameters[\??selector#1][#2]} + +\permanent\protected\let\select\directselect % we promote to protected + +% \def\directselect#1% expandable +% {\filterfromnext % maybe add an \expanded +% {\csname\??selector\ifcsname\??selector#1\c!max\endcsname#1\fi\c!max\endcsname}% +% {\csname\??selector\ifcsname\??selector#1\c!n \endcsname#1\fi\c!n \endcsname}} +% +% this is more efficient when the arguments are used a few times (or passed along): + +\permanent\def\directselect#1% expandable + {\expandafter\filterfromnext + \csname\??selector\ifcsname\??selector#1\c!max\endcsname#1\fi\c!max\expandafter\endcsname + \csname\??selector\ifcsname\??selector#1\c!n \endcsname#1\fi\c!n \endcsname} + +\letvalue{\??selector\c!max}\plusone % \aliased ? +\letvalue{\??selector\c!n }\plusone % \aliased ? + +\protect \endinput diff --git a/tex/context/base/mkiv/core-ini.mkiv b/tex/context/base/mkiv/core-ini.mkiv index c4ab298bf..31ef501d9 100644 --- a/tex/context/base/mkiv/core-ini.mkiv +++ b/tex/context/base/mkiv/core-ini.mkiv @@ -191,7 +191,7 @@ %D %D This boolean can be used to bypass certain initializations. -\newif\ifproductionrun +% \newif\ifproductionrun % already defined \appendtoks \productionruntrue diff --git a/tex/context/base/mkiv/driv-shp.lmt b/tex/context/base/mkiv/driv-shp.lmt index c117405ba..0d3bddda4 100644 --- a/tex/context/base/mkiv/driv-shp.lmt +++ b/tex/context/base/mkiv/driv-shp.lmt @@ -44,6 +44,7 @@ local getdata = nuts.getdata local getreplace = nuts.getreplace local setreplace = nuts.setreplace local getfont = nuts.getfont +local getkerndimension = nuts.getkerndimension local setdirection = nuts.setdirection local setfield = nuts.setfield @@ -68,7 +69,6 @@ local parameters = fonthashes.parameters local nodecodes = nodes.nodecodes local whatsitcodes = nodes.whatsitcodes -local leadercodes = nodes.leadercodes local gluecodes = nodes.gluecodes local dircodes = nodes.dircodes local dirvalues = nodes.dirvalues @@ -92,10 +92,10 @@ local whatsit_code = nodecodes.whatsit ----- penalty_code = nodecodes.penalty ----- boundary_code = nodecodes.boundary -local leaders_code = leadercodes.leaders -local cleaders_code = leadercodes.cleaders -local xleaders_code = leadercodes.xleaders -local gleaders_code = leadercodes.gleaders +local leaders_code = gluecodes.leaders +local cleaders_code = gluecodes.cleaders +local xleaders_code = gluecodes.xleaders +local gleaders_code = gluecodes.gleaders local spaceskip_code = gluecodes.spaceskip @@ -586,7 +586,7 @@ local hlist_out, vlist_out do -- current = getlist(this_box) -- end - -- we can encounter localpar, boundary and penalty nodes but a special + -- we can encounter par, boundary and penalty nodes but a special -- iterator over content nodes won't save much for current, id, subtype in nextnode, current do if id == glyph_code then @@ -775,6 +775,8 @@ local hlist_out, vlist_out do end cur_h = cur_h + width elseif id == kern_code then + -- we can use getkerndimension(current) but then we get rounded values so for + -- now we calculate ourselves local kern, factor = getkern(current,true) if kern ~= 0 then if factor ~= 0 then @@ -893,7 +895,7 @@ local hlist_out, vlist_out do setlink(current,replace) setreplace(current) end - -- elseif id == localpar_code and start_of_par(current) then + -- elseif id == par_code and start_of_par(current) then -- local pardir = getdirection(current) or lefttoright_code -- if pardir == righttoleft_code then -- end diff --git a/tex/context/base/mkiv/enco-ini.mkiv b/tex/context/base/mkiv/enco-ini.mkiv index f78643975..e4343ba2d 100644 --- a/tex/context/base/mkiv/enco-ini.mkiv +++ b/tex/context/base/mkiv/enco-ini.mkiv @@ -314,7 +314,7 @@ % left-overs (some day in private unicode space, so that we can roundtrip) \unexpanded\def\textblacksquare {\dontleavehmode\hbox{\vrule\s!width.3\s!em\s!height.4\s!em\s!depth-.1\s!em}} -\unexpanded\def\schwa {\hbox{\rotate[\c!rotation=180,\c!location=\v!high]{\hbox{e}}}} +%unexpanded\def\schwa {\hbox{\rotate[\c!rotation=180,\c!location=\v!high]{\hbox{e}}}} \unexpanded\def\schwagrave {\buildtextgrave\schwa} \chardef\textcontrolspace"2423 diff --git a/tex/context/base/mkiv/enco-ini.mkxl b/tex/context/base/mkiv/enco-ini.mkxl new file mode 100644 index 000000000..609aa28da --- /dev/null +++ b/tex/context/base/mkiv/enco-ini.mkxl @@ -0,0 +1,570 @@ +%D \module +%D [ file=enco-ini, +%D version=2007.02.19, % 2000.12.27, % 1998.12.03, +%D title=\CONTEXT\ Encoding Macros, +%D subtitle=Initialization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This is stripped down version of th eoriginal enco-ini.tex file. For more details +%D you might want to study the \MKII\ file but since \LUATEX\ is unicode inside we +%D need less code. + +%D Much in here will disappear in \LMTX\ because we assume proper \UNICODE\ usage. + +% When dealing with characters we have four cases to take into account when moving +% from mkii to mkiv: + +% 1. <byte 200> => ref to slot 200 in current font +% 2. \char 200 => ref to slot 200 in current font +% 3. <active 200> => can (e.g.) map to another slot in current font +% 4. \namedglyph => can map to some slot in some font + +% Using case 2 for special characters is doomed to fail because we are not going +% to intercept these on the fly as happens automatically with traditional font +% encoding handling. We could do that in a node pass but it's not worth the effort +% because we seldom use this case in a document source. + +% We can consider using utf as internal format for mkii. The main reason for not +% doing this before was that it was slow. On the other hand, it would make dealing +% with utility files easier. However, we've now kind of frozen mkii. + +\writestatus{loading}{ConTeXt Encoding Macros / Initialization} + +\unprotect + +%D Obsolete (but sometimes used in styles) + +\let\defaultencoding\s!default + +%D \macros +%D {defineaccent, definecharacter, definecommand} +%D +%D Some of these are used at the \LUA\ end! + +\installcorenamespace{accents} + +\permanent\protected\def\defineaccent#1 #2 #3 % + {\dodefineaccentcommand{#1}% + \dodefineaccent{#1}{#2}{#3}} + +\permanent\protected\def\dodefineaccentcommand#1% + {\setevalue{\string#1}{\noexpand\dohandleaccent{\string#1}}} + +\permanent\protected\def\dodefineaccent#1#2#3% no spaces, used low level + {\setvalue{\??accents\string#1\string#2\empty}{#3}} + +% the following dirty trick is needed to catch \asciimath{\^{1/5}log}: + +\permanent\protected\def\dohandleaccent#1#2% expandable because we want them in the tuc file + {\csname\??accents + \ifcsname\??accents\string#1#2\empty\endcsname + \string#1#2\empty + \orelse\ifcsname\??accents\string#1\string#2\empty\endcsname + \string#1\string#2\empty + \else + \endcsname#2\csname\??accents % very dirty trick: ignore accent but keep char + \fi + \endcsname} + +\immutable\letvalue{\??accents}\empty + +\permanent\protected\def\dodefinecommand#1#2% + {\frozen\setuvalue{\string#1}{#2}} % not permanent as these are kind of obsolete + +\permanent\protected\def\definecharacter#1 #2 % + {\doifelsenumber{\string#2} + {\setevalue{\string#1}{\utfchar{#2}}} % or {\expandafter\chardef\csname#1\endcsname#2\relax} + {\setuvalue{\string#1}{#2}}} + +\permanent\protected\def\definecommand#1 #2 % + {\setuvalue{\string#1}{#2}} + +%D \macros +%D {everyuppercase, everylowercase, everysanitize} + +\newtoks \everyuppercase +\newtoks \everylowercase +\newtoks \everysanitize + +%D Accent handling (try to avoid this): + +% \buildtextaccent\greekdasia\greekalphamacron +% \buildtextaccent\textacute q + +%D We can use offsets in \LMTX\ but even that makes n o sense because we have +%D a virtual feature already in \MKIV. + +%D We define them frozen so that we can overload them. + +\newbox\b_enco_accent + +\permanent\protected\def\buildmathaccent#1% + {\mathaccent#1 } + +\permanent\protected\def\buildtextaccent#1#2% we could do all at the lua end + {\dontleavehmode\begingroup % but that's no fun (yet) + \setbox\scratchboxone\hbox{#1}% accent + \setbox\scratchboxtwo\hbox{#2}% character + \scratchheight\dimexpr\ht\scratchboxtwo-\ht\scratchboxone\relax + \scratchdepth \dimexpr\dp\scratchboxtwo-\dp\scratchboxone\relax + \scratchwidth \wd\scratchboxtwo + \hbox to \wd\ifdim\wd\scratchboxone>\wd\scratchboxtwo\scratchboxone\else\scratchboxtwo\fi\bgroup + \hss\box\scratchboxtwo\hss + \hskip-\scratchwidth + \hss + \ifdim\ht\scratchboxone>\exheight + % top accent + \raise\dimexpr\scratchheight+\exheight/3\relax + \else + \lower-\dimexpr\scratchdepth+\exheight/3\relax + \fi + \box\scratchboxone + \hss + \egroup + \endgroup} + +\permanent\protected\def\bottomaccent#1#2#3#4#5% down right slantcorrection accent char + {\dontleavehmode % why this align mess + \vtop + {\forgetall + \baselineskip\zeropoint + \lineskip#1% + \everycr\emptytoks + \tabskip\zeropoint + \lineskiplimit\zeropoint + \setbox0\hbox{#4}% + \halign + {##\crcr\hbox{#5}\crcr + \hidewidth + \hskip#2\wd0 + \hskip-#3\slantperpoint % in plain 1ex * dimenless value + \vpack to .2\exheight{\box0\vss}\hidewidth + \crcr}}} + +\permanent\protected\def\buildtextmacron {\bottomaccent{.25ex}{0}{15}{\textmacron}} +\permanent\protected\def\buildtextbottomdot {\bottomaccent{.25ex}{0}{5}{\textbottomdot}} +\permanent\protected\def\buildtextcedilla {\bottomaccent{0ex}{0}{5}{\textcedilla}} +\permanent\protected\def\buildtextogonek {\bottomaccent{-.1ex}{.5}{0}{\textogonek}} +\permanent\protected\def\buildtextbottomcomma{\bottomaccent{.15ex}{0}{5}{\tx,}} + +\aliased\let\d\buildtextbottomdot + +\permanent\protected\def\topaccent#1#2#3#4#5% down right slantcorrection accent char + {\dontleavehmode + \bgroup + \setbox0\hbox{#4}% + \setbox2\hbox{#5}% + \hbox to \wd2 \bgroup + \hss\copy2\hss + \hskip-\wd2 + \hss\hskip#2\wd0\hskip-#3\slantperpoint\raise#1\hbox{#4}\hss + \egroup + \egroup} + +\permanent\protected\def\buildtextgrave + {\topaccent{0pt}{0}{15}{\textgrave}} % e.g. + +\permanent\protected\def\definemathaccent#1 #2% + {\setvalue{#1}{\mathaccent#2 }} + +%D Math (will move): + +\definemathaccent acute \mathacute +\definemathaccent grave \mathgrave +\definemathaccent ddot \mathddot +\definemathaccent tilde \mathtilde +\definemathaccent bar \mathbar +\definemathaccent breve \mathbreve +\definemathaccent check \mathcheck +\definemathaccent hat \mathhat +\definemathaccent vec \mathvec +\definemathaccent dot \mathdot +%definemathaccent widetilde \mathwidetilde +%definemathaccent widehat \mathwidehat + +% from enco-def: + +% \aliased\let\i\dotlessi +% \aliased\let\j\dotlessj + +% \aliased\let\P\paragraphmark \aliased\let\textP\paragraphmark % obsolete (surfaced in bibliographic files) +% \aliased\let\S\sectionmark \aliased\let\textS\sectionmark % obsolete (surfaced in bibliographic files) + +\permanent\def\eszett {ß} \permanent\def\Eszett {SS} \permanent\def\Ssharp{SS} +\permanent\def\lslash {ł} \permanent\def\Lslash {Ł} +\permanent\def\dslash {đ} \permanent\def\Dslash {Đ} +%permanent\def\oslash {ø} %permanent\def\Oslash {Ø} % clashes with math: use \Ostroke +\permanent\def\dcroat {đ} \permanent\def\Dcroat {Đ} +\permanent\def\kcedilla{ķ} \permanent\def\Kcedilla{Ķ} +\permanent\def\lcedilla{ļ} \permanent\def\Lcedilla{Ļ} +\permanent\def\ncedilla{ņ} \permanent\def\Ncedilla{Ņ} +\permanent\def\rcedilla{ŗ} \permanent\def\Rcedilla{Ŗ} +\permanent\def\aumlaut {ä} \permanent\def\Aumlaut {Ä} +\permanent\def\eumlaut {ë} \permanent\def\Eumlaut {Ë} +\permanent\def\iumlaut {ï} \permanent\def\Iumlaut {Ï} +\permanent\def\oumlaut {ö} \permanent\def\Oumlaut {Ö} +\permanent\def\uumlaut {ü} \permanent\def\Uumlaut {Ü} + +% from enco-com: + +% \aliased\let\AE\AEligature \aliased\let\ae\aeligature +% \aliased\let\OE\OEligature \aliased\let\oe\oeligature +% \aliased\let\IJ\IJligature \aliased\let\ij\ijligature +% \aliased\let\AA\textAngstrom \aliased\let\aa\aring +% \aliased\let\CC\Ccedilla \aliased\let\cc\ccedilla +% \aliased\let\L \Lslash \aliased\let\l \lslash +% \aliased\let\O \Oslash \aliased\let\o \oslash +% \aliased\let\SZ\Eszett \aliased\let\sz\eszett % \aliased\let\SS\Ssharp + +% for old times sake (obsolete) + +\def\textflorin{ƒ} \def\florin {ƒ} +\def\pound {£} \def\sterling{£} +\def\promille {‰} \def\permille{‰} + +% tex specific + +\pushoverloadmode + +%D Was missing: + +\permanent\protected\def\ampersand{\mathortext\mathampersand\textampersand} + + +\ifdefined\textpercent + \permanent\let\percent \textpercent + \permanent\let\procent \textpercent + %\permanent\let\ampersand \textampersand + \permanent\let\dollar \textdollar + \permanent\let\hash \texthash +\else + \permanent\def\percent {\textpercent} + \permanent\def\procent {\textpercent} + %\permanent\def\ampersand {\textampersand} + \permanent\def\dollar {\textdollar} + \permanent\def\hash {\texthash} +\fi + +\popoverloadmode + +% from enco-mis: + +\permanent\protected\def\fakepercent + {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25\emwidth/\kern-.2\emwidth\normalsubscript{\scriptscriptstyle0}}} + +\permanent\protected\def\fakeperthousand + {\mathematics{\normalsuperscript{\scriptscriptstyle0}\kern-.25\emwidth/\kern-.2\emwidth\normalsubscript{\scriptscriptstyle00}}} + +\permanent\protected\def\fakepermine + {\dontleavehmode + \bgroup + \setbox\scratchbox\hbox + {\mathematics{+}}% + \hbox to \wd\scratchbox + {\hss + \mathematics{\normalsuperscript{\scriptscriptstyle-}\kern-.4\emwidth/\kern-.3\emwidth\normalsubscript{\scriptscriptstyle-}}% + \hss}% + \egroup} + +\def\permine{\fakepermine} + +% some more: what with freezing here? + +\ifdefined\softhyphen \else + \aliased\let\softhyphen\explicitdiscretionary +\fi + +\def\hyphen {\softhyphen} +\def\compoundwordmark {\hyphen} +\def\cwm {\hyphen} +\def\nonbreakinghyphen{\hyphen} +\def\breakinghyphen {\hyphen\prewordbreak} + +% quotes + +\def\lowerleftsingleninequote {\quotesinglebase} +\def\lowerleftdoubleninequote {\quotedblbase} +\def\lowerrightsingleninequote {\quotesinglebase} +\def\lowerrightdoubleninequote {\quotedblbase} + +\def\upperleftsingleninequote {\quoteright} +\def\upperleftdoubleninequote {\quotedblright} +\def\upperrightsingleninequote {\quoteright} +\def\upperrightdoubleninequote {\quotedblright} + +\def\upperleftsinglesixquote {\quoteleft} +\def\upperleftdoublesixquote {\quotedblleft} +\def\upperrightsinglesixquote {\quoteleft} +\def\upperrightdoublesixquote {\quotedblleft} + +\def\leftsubguillemot {\guilsingleleft} +\def\rightsubguillemot {\guilsingleright} + +% left-overs (some day in private unicode space, so that we can roundtrip) + +\permanent\protected\def\textblacksquare{\dontleavehmode\hbox{\vrule\s!width.3\s!em\s!height.4\s!em\s!depth-.1\s!em}} +%permanent\protected\def\schwa {\hbox{\rotate[\c!rotation=180,\c!location=\v!high]{\hbox{e}}}} +\permanent\protected\def\schwagrave {\buildtextgrave\schwa} + +\chardef\textcontrolspace"2423 + +\installcorenamespace{controlspace} + +% \protected\def\fallbackcontrolspace % beware: non-matching widths +% {\hbox to \interwordspace{\hss\getglyph{LMTypewriter-Regular}\textcontrolspace\hss}% + +\permanent\protected\def\fallbackcontrolspace % beware, current font, we also need to honor color + {\hbox to \interwordspace \bgroup + \hss + \ifcsname\??controlspace\number\interwordspace\endcsname + \csname\??controlspace\number\interwordspace\endcsname + \else + \enco_fast_control_space_define % only regular + \fi + \textcontrolspace + \hss + \egroup} + +\protected\def\enco_fast_control_space_define + {\scratchdimen\interwordspace + \definedfont[LMTypewriter-Regular at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody]% see font-sym.mkiv + \expandafter\glet\csname\??controlspace\number\scratchdimen\endcsname\lastrawfontcall} + +\permanent\protected\def\normalcontrolspace + {\iffontchar\font\textcontrolspace + \textcontrolspace + \else + \fallbackcontrolspace + \fi} + +\let\textvisiblespace\normalcontrolspace + +\permanent\protected\def\optionalcontrolspace + {\iffontchar\font\textcontrolspace + \textcontrolspace + \else + \asciispacechar % used for export ! + \fi} + +% \protected\def\fastcontrolspace % no glyph resolving after first (use grouped) +% {\enco_fast_control_space} +% +% \def\enco_fast_control_space +% {\iffontchar\font\textcontrolspace +% \enco_fast_control_space_nop +% \else +% \enco_fast_control_space_yes +% \fi +% \enco_fast_control_space} +% +% \newbox\b_enco_control_space +% +% \def\enco_fast_control_space_nop +% {\let\enco_fast_control_space\textcontrolspace} +% +% \def\enco_fast_control_space_yes +% {\setbox\b_enco_control_space\fallbackcontrolspace +% \let\enco_fast_control_space\flushcontrolspacebox} +% +% \def\flushcontrolspacebox +% {\copy\b_enco_control_space} + +% a few defaults (\<whatever>{}), we really need the verbose \empty as it will be +% stringified .. anyhow, we define this at the lua end now but keep it here as a +% reference +% +% \defineaccent ^ {\empty} {\textcircumflex} +% \defineaccent ` {\empty} {\textgrave} +% \defineaccent ~ {\empty} {\texttilde} +% \defineaccent " {\empty} {\textdiaeresis} +% \defineaccent ' {\empty} {\textacute} +% \defineaccent . {\empty} {\textdotaccent} +% \defineaccent = {\empty} {\textmacron} +% \defineaccent c {\empty} {\textcedilla} +% \defineaccent H {\empty} {\texthungarumlaut} +% \defineaccent k {\empty} {\textogonek} +% \defineaccent r {\empty} {\textring} +% \defineaccent u {\empty} {\textbreve} +% \defineaccent v {\empty} {\textcaron} + +\clf_defineaccents % one time + +%D A smaller and bolder variant, more like the math and monospaced ones. + +\permanent\protected\def\fakeunderscore + {\relax\ifmmode + \vrule\s!depth .12\fontexheight\mathstylefont\normalmathstyle\s!width \fontinterwordspace\mathstylefont\normalmathstyle\s!height\zeropoint\relax + \else + \dontleavehmode\hbox{\vrule\s!depth .12\fontexheight\font\s!width \fontinterwordspace\font\s!height\zeropoint}% + \fi} + +\permanent\protected\def\fakeunderscores{\let\_\fakeunderscore} +\permanent\protected\def\textunderscores{\let\_\textunderscore} + +\textunderscores + +\ifdefined\mathunderscore \else \aliased\let\mathunderscore\fakeunderscore \fi +\ifdefined\textunderscore \else \aliased\let\textunderscore\fakeunderscore \fi + +\permanent\protected\def\normalunderscore{\ifmmode\mathunderscore\else\textunderscore\fi} + +\let\_\normalunderscore + +%D To be sorted out: + +\pushoverloadmode + +\permanent\protected\def\textminus + {\char \iffontchar\font"2012 "2012 % figuredash + \else\iffontchar\font"2013 "2013 % endash + \else\iffontchar\font"2212 "2212 % math minus + "002D % hyphen + \fi\fi\fi} + +\permanent\protected\def\textplus + {\char"002B } % plus + +\popoverloadmode + +%D Moved from core-mis: + +\permanent\protected\def\celsius #1{#1\mathematics{^\circ}C} +\permanent\protected\def\inch {\mathematics{\prime\prime}} % was: \hbox{\rm\char125\relax} +\permanent\protected\def\fraction#1#2{\mathematics{#1\over#2}} + +% \def\periodswidth {.5em} +% \def\periodsdefault{3} % was 5, but now it's like \unknown +% +% \protected\def\periods +% {\dosingleempty\enco_periods} +% +% \def\doperiods[#1]% todo: also n=,width= or maybe just #1,#2 +% {\dontleavehmode +% \begingroup +% \scratchdimen\periodswidth +% \hbox to \iffirstargument#1\else\periodsdefault\fi \scratchdimen +% {\leaders\hbox to \scratchdimen{\hss\periodsymbol\hss}\hss}% +% \endgroup} +% +% better for export: +% +% \protected\def\enco_periods[#1]% todo: also n=,width= or maybe just #1,#2 +% {\dontleavehmode +% \hbox\bgroup +% \setbox\scratchbox\hbox to \periodswidth{\hss\periodsymbol\hss}% +% \dorecurse{\iffirstargument#1\else\periodsdefault\fi}{\copy\scratchbox}% +% \egroup} +% +% \protected\def\unknown +% {\periods\relax} % relax prevents lookahead for [] +% +% per request: + +%D \startbuffer +%D \startlines +%D x\periods x +%D x\periods[10]x +%D x\periods[n=10,symbol={,}]x +%D x\periods[n=4,symbol={!!},width=1em]x +%D x\periods[n=4,symbol={!!},width=fit]x +%D x\periods[n=4,symbol={!!},width=fit,distance=1em]x +%D x\unknown x +%D \stoplines +%D \stopbuffer +%D +%D \typbuffer \getbuffer + +\def\periodswidth {.5\emwidth} % downward compatible +\def\periodsdefault{3} % downward compatible + +\installcorenamespace {periods} + +\installsetuponlycommandhandler \??periods {periods} + +\setupperiods + [\c!n=\periodsdefault, + \c!width=\periodswidth, % can also be \v!fit + \c!distance=.25\emwidth, + \c!symbol=.] + +\permanent\protected\def\periods + {\dontleavehmode + \hbox\bgroup + \doifelsenextoptional\enco_periods_yes\enco_periods_nop} + +\protected\def\enco_periods_yes[#1]% + {\doifelseassignment{#1} + {\setupcurrentperiods[#1]% + \scratchcounter\periodsparameter\c!n} + {\doifelsenothing{#1} + {\scratchcounter\periodsparameter\c!n}% + {\scratchcounter#1}}% + \enco_periods_finish} + +\protected\def\enco_periods_nop + {\scratchcounter\periodsparameter\c!n + \enco_periods_finish} + +\protected\def\enco_periods_finish + {\edef\p_width{\periodsparameter\c!width}% + \ifx\p_width\v!fit + \enco_periods_finish_fit + \else + \enco_periods_finish_width + \fi + \egroup} + +\protected\def\enco_periods_finish_width + {\setbox\scratchbox\hbox to \p_width + {\hss\periodsparameter\c!symbol\hss}% + \dorecurse\scratchcounter{\copy\scratchbox}} + +\protected\def\enco_periods_finish_fit + {\edef\p_symbol{\periodsparameter\c!symbol}% + \scratchdistance\periodsparameter\c!distance + \hskip\scratchdistance + \dorecurse\scratchcounter{\p_symbol\hskip\scratchdistance}} + +\permanent\protected\def\unknown + {\dontleavehmode + \hbox\bgroup + \enco_periods_nop} + +%D Left-overs: + +\appendtoks + \enforced\let\buildtextaccent\secondoftwoarguments +\to \everysimplifycommands + +%D A plain one: + +% \protected\def\t#1{% +% \dontleavehmode +% \begingroup +% \setbox\scratchboxone\hpack{#1}% +% \setbox\scratchboxtwo\hpack\bgroup +% \iffontchar\font"0361\relax +% \char"0361\relax +% \else +% \iffontchar\font"2040\relax\else +% \the\textfont0 +% \fi +% \char"2040 +% \fi +% \egroup +% \scratchdimenone\wd\ifdim\wd\scratchboxone>\wd\scratchboxtwo\scratchboxone\else\scratchboxtwo\fi +% \scratchdimentwo\dimexpr-\ht\scratchboxtwo+\ht\scratchboxone+.45\exheight\relax +% \hpack to \scratchdimenone\bgroup +% \hpack to \scratchdimenone{\hss\box\scratchboxone\hss}% +% \hskip -\scratchdimenone +% \hpack to \scratchdimenone{\hss\raise\scratchdimentwo\box\scratchboxtwo\hss}% +% \egroup +% \endgroup} + +\protect \endinput diff --git a/tex/context/base/mkiv/file-ini.mkvi b/tex/context/base/mkiv/file-ini.mkvi index 5341cc07b..5fa5aa560 100644 --- a/tex/context/base/mkiv/file-ini.mkvi +++ b/tex/context/base/mkiv/file-ini.mkvi @@ -115,7 +115,7 @@ %D lines). So, instead of fixing that, we go for a redefinition of \type {\input}. %D Of course it's better to use \type {\readfile} or \type {\processfile}. -\unexpanded\def\input{\normalinput} +% \unexpanded\def\input{\normalinput} \def\inputgivenfile#name{\normalinput{#name}} diff --git a/tex/context/base/mkiv/file-job.mkvi b/tex/context/base/mkiv/file-job.mkvi index db5ac4db1..1f8da6b0c 100644 --- a/tex/context/base/mkiv/file-job.mkvi +++ b/tex/context/base/mkiv/file-job.mkvi @@ -133,10 +133,15 @@ \unexpanded\def\starttext {\clf_starttext} \unexpanded\def\stoptext {\clf_stoptext} \unexpanded\def\forcequitjob {\clf_forcequitjob} -\unexpanded\def\end {\clf_forceendjob} \unexpanded\def\autostarttext{\clf_autostarttext} \unexpanded\def\autostoptext {\clf_autostoptext} +\pushoverloadmode + +\unexpanded\def\end {\clf_forceendjob} + +\popoverloadmode + \unexpanded\def\finishjob{\stoptext} % nicer in luatex call commandline \newtoks\everystartnotext diff --git a/tex/context/base/mkiv/file-syn.mklx b/tex/context/base/mkiv/file-syn.mklx new file mode 100644 index 000000000..25f36f742 --- /dev/null +++ b/tex/context/base/mkiv/file-syn.mklx @@ -0,0 +1,61 @@ +%D \module +%D [ file=file-syn, % was core-fil, +%D version=20110701, % 1997.11.15, +%D title=\CONTEXT\ File Macros, +%D subtitle=Module Support, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt File Macros / Synonyms} + +\unprotect + +\registerctxluafile{file-syn}{} + +%D \macros +%D {definefilesynonym,definefilefallback} +%D +%D One of the problems with loading files is that their names can depend on the +%D interface language. We therefore need a method to define filesynonyms. The actual +%D synonyms are defined elsewhere, but look like: +%D +%D \starttyping +%D \definefilesynonym [chemic] [chemie] +%D \definefilesynonym [einheit] [unit] +%D \definefilesynonym [unit] [unit] +%D \stoptyping +%D +%D So we can say in english: +%D +%D \starttyping +%D \usemodules[pictex,chemic,unit] +%D \stoptyping +%D +%D and in dutch: +%D +%D \starttyping +%D \usemodules[pictex,chemie,unit] +%D \stoptyping + +\permanent\tolerant\def\definefilesynonym [#name]#spacer[#realname]{\clf_definefilesynonym {#name}{#realname}} +\permanent\tolerant\def\definefilefallback[#name]#spacer[#alternatives]{\clf_definefilefallback{#name}{#alternatives}} + +%D \macros +%D {truefilename} +%D +%D At the system level such a filename can be called upon by saying: +%D +%D \starttyping +%D \truefilename{filename/filesynonym} +%D \stoptyping +%D +%D The implementation shows that nesting is supported. + +\permanent\def\truefilename#1{\clf_truefilename{#1}} + +\protect \endinput diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua index eec967c1c..6c21bc0cc 100644 --- a/tex/context/base/mkiv/font-ctx.lua +++ b/tex/context/base/mkiv/font-ctx.lua @@ -334,9 +334,10 @@ end -- Watch out: in lmtx the font dimen array is no longer resized automatically. implement { - name = "resetnullfont", - onlyonce = true, - actions = function() + name = "resetnullfont", + onlyonce = true, + permanent = false, + actions = function() for i=1,7 do if CONTEXTLMTXMODE > 0 then font.setfontdimen(0,i,0) @@ -1020,7 +1021,8 @@ end local function splitcontext(features) -- presetcontext creates dummy here local n, sf - if find(features,",") then + -- We can have: "a=yes,b=yes" "a,b" "a" "a=yes" etc. + if find(features,"[,=]") then -- -- from elsewhere (!) -- diff --git a/tex/context/base/mkiv/font-emp.mklx b/tex/context/base/mkiv/font-emp.mklx index 8ceee2723..5656c168c 100644 --- a/tex/context/base/mkiv/font-emp.mklx +++ b/tex/context/base/mkiv/font-emp.mklx @@ -32,8 +32,8 @@ %D But we prefer: %D %D \starttyping -%D \unexpanded\def\emphasistypeface{\sl} -%D \unexpanded\def\emphasisboldface{\bs} +%D \protected\def\emphasistypeface{\sl} +%D \protected\def\emphasisboldface{\bs} %D \stoptyping %D %D or even better: @@ -52,33 +52,33 @@ \csname\m_font_emphasized_typeface\endcsname \fi} -\unexpanded\def\emphasistypeface{\font_emphasis_checked_typeface\sl\it} -\unexpanded\def\emphasisboldface{\font_emphasis_checked_typeface\bs\bi} +\permanent\protected\def\emphasistypeface{\font_emphasis_checked_typeface\sl\it} +\permanent\protected\def\emphasisboldface{\font_emphasis_checked_typeface\bs\bi} -\unexpanded\def\normalboldface % public +\permanent\protected\def\normalboldface % public {\relax \ifx\fontalternative\s!it\bi\orelse \ifx\fontalternative\s!sl\bs\else \bf\fi} -\unexpanded\def\normalitalicface % public +\permanent\protected\def\normalitalicface % public {\relax \ifx\fontalternative\s!tf\it\orelse \ifx\fontalternative\s!bf\bi\else \tf\fi} -\unexpanded\def\normalslantedface % public +\permanent\protected\def\normalslantedface % public {\relax \ifx\fontalternative\s!tf\sl \orelse\ifx\fontalternative\s!bf\bs \else \tf\fi} -\unexpanded\def\normaltypeface % public +\permanent\protected\def\normaltypeface % public {\relax \ifx\fontalternative\s!bi \it \orelse \ifx\fontalternative\s!bs \sl \else \tf \fi} -\unexpanded\def\swaptypeface % public +\permanent\protected\def\swaptypeface % public {\relax \ifx\fontalternative\s!it \tf \orelse \ifx\fontalternative\s!sl \tf \orelse @@ -93,14 +93,14 @@ \let\italicface \normalitalicface % public \let\swapface \swaptypeface % public -%D To be set with the default body font environment: \type -%D {em} being \type {slanted} or \type {italic}. +%D To be set with the default body font environment: \type {em} being \type +%D {slanted} or \type {italic}. % maybe a \csname...\fontalternative\endcsname \newconditional\c_font_emphasis_needed -\unexpanded\def\em +\permanent\protected\def\em {\relax \ifdim\slantperpoint>\zeropoint \settrue\c_font_emphasis_needed @@ -109,15 +109,15 @@ \fi \font_emphasis_set_emphasis_boldface % new \ifx\fontalternative\s!it - \unexpanded\def\emphasistypeface{\it}\tf + \enforced\permanent\protected\def\emphasistypeface{\it}\tf \orelse\ifx\fontalternative\s!sl - \unexpanded\def\emphasistypeface{\sl}\tf + \enforced\permanent\protected\def\emphasistypeface{\sl}\tf \orelse\ifx\fontalternative\s!bf \emphasisboldface \orelse\ifx\fontalternative\s!bs - \unexpanded\def\emphasisboldface{\bs}\bf + \enforced\permanent\protected\def\emphasisboldface{\bs}\bf \orelse\ifx\fontalternative\s!bi - \unexpanded\def\emphasisboldface{\bi}\bf + \enforced\permanent\protected\def\emphasisboldface{\bi}\bf \else \emphasistypeface \fi @@ -126,8 +126,8 @@ \fi \emphasiscorrection} -%D The next feature was not present in previous versions. It -%D takes care of \type {\em \bf ...} situations. +%D The next feature was not present in previous versions. It takes care of \type +%D {\em \bf ...} situations. \let\font_emphasis_saved_emphasis_boldface\relax @@ -136,7 +136,7 @@ \let\font_emphasis_set_emphasis_boldface\relax \let\bf\font_emphasis_bold_bold} -\unexpanded\def\font_emphasis_bold_bold +\protected\def\font_emphasis_bold_bold {%\relax \let\bf\relax % new \ifx\fontalternative\s!it @@ -154,7 +154,7 @@ \let\italiccorrection=\/ % tex primitive -\def\emphasiscorrection % public, not in raw alignment groups, else omit problem +\permanent\protected\def\emphasiscorrection % public, not in raw alignment groups, else omit problem {\ifhmode\ifnum\currentgrouptype=\aligngroupcode\else \expandafter\expandafter\expandafter\font_emphasis_look \fi\fi} @@ -224,24 +224,24 @@ %D The next emphasis alternatives are for \THANH. They adapt their style as good as %D possible. These macros are obsolete in \MKIV. -% \unexpanded\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}} -% \unexpanded\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}} -% \unexpanded\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}} -% \unexpanded\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}} -% \unexpanded\def\emph {\groupedcommand{\em}{}} +% \protected\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}} +% \protected\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}} +% \protected\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}} +% \protected\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}} +% \protected\def\emph {\groupedcommand{\em}{}} -\unexpanded\def\font_emphasis_bf{\bf\def\emphit{\bi}\def\emphsl{\bs}} -\unexpanded\def\font_emphasis_it{\it\def\emphbf{\bi}\def\emphsl{\sl}} -\unexpanded\def\font_emphasis_sl{\sl\def\emphbf{\bs}\def\emphit{\it}} -\unexpanded\def\font_emphasis_tf{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}} +\protected\def\font_emphasis_bf{\bf\def\emphit{\bi}\def\emphsl{\bs}} +\protected\def\font_emphasis_it{\it\def\emphbf{\bi}\def\emphsl{\sl}} +\protected\def\font_emphasis_sl{\sl\def\emphbf{\bs}\def\emphit{\it}} +\protected\def\font_emphasis_tf{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}} -\unexpanded\def\emphbf{\triggergroupedcommandcs\font_emphasis_bf} -\unexpanded\def\emphit{\triggergroupedcommandcs\font_emphasis_it} -\unexpanded\def\emphsl{\triggergroupedcommandcs\font_emphasis_sl} -\unexpanded\def\emphtf{\triggergroupedcommandcs\font_emphasis_tf} -\unexpanded\def\emph {\triggergroupedcommandcs\em} +\permanent\protected\def\emphbf{\triggergroupedcommandcs\font_emphasis_bf} +\permanent\protected\def\emphit{\triggergroupedcommandcs\font_emphasis_it} +\permanent\protected\def\emphsl{\triggergroupedcommandcs\font_emphasis_sl} +\permanent\protected\def\emphtf{\triggergroupedcommandcs\font_emphasis_tf} +\permanent\protected\def\emph {\triggergroupedcommandcs\em} -\unexpanded\def\emphasized{\bgroup\em\let\nexttoken} +\permanent\protected\def\emphasized{\bgroup\em\let\nexttoken} %D \startbuffer %D TEXT {\emphbf text \emphit text \emphtf text \emphsl text} TEXT diff --git a/tex/context/base/mkiv/font-fea.mklx b/tex/context/base/mkiv/font-fea.mklx new file mode 100644 index 000000000..010f95500 --- /dev/null +++ b/tex/context/base/mkiv/font-fea.mklx @@ -0,0 +1,380 @@ +%D \module +%D [ file=font-sty, +%D version=2011.01.13, % (copied fron font-ini) +%D title=\CONTEXT\ Font Macros, +%D subtitle=features, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Font Macros / Features} + +\unprotect + +%D Feature management. +%D +%D \starttyping +%D \definefontfeature[smallcaps][smcp=yes,script=latn] +%D \definefontfeature[smallcaps][SmallCapitals=yes,script=latn] +%D \definefontfeature[smallcaps][Small Capitals=yes,script=latn] +%D \definefontfeature[smallcaps][small capitals=yes,script=latn] +%D \definefontfeature[smallcaps][smallcapitals=yes,script=latn] +%D +%D \definedfont[cambria*smallcaps] test +%D +%D \starttext +%D \definefontfeature[basekerned][default][mode=base] +%D \definefontfeature[nodekerned][default][mode=node] +%D \definefontfeature[nonekerned][default][mode=base,kern=no] +%D \setupcolors[state=start] +%D \startoverlay +%D {\vbox{\red \definedfont[Serif*nonekerned at 12pt]\input tufte }} +%D {\vbox{\blue \definedfont[Serif*basekerned at 12pt]\input tufte }} +%D {\vbox{\green\definedfont[Serif*nodekerned at 12pt]\input tufte }} +%D \stopoverlay +%D \stoptext +%D +%D \enabletrackers[otf.kerns] +%D +%D \definefontfeature[withkern][default][mode=node] +%D \definefontfeature[nokern] [default][mode=node,kern=no] +%D \definefontfeature[single] [default][mode=node,cpsp=yes] +%D \definefontfeature[simple] [default][mode=node,cpsp=yes,kern=no] +%D +%D {\definedfont[Serif*default] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par} +%D {\definedfont[Serif*nokern] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par} +%D {\definedfont[Serif*single] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par} +%D {\definedfont[Serif*simple] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par} +%D \stoptyping + +% \definefontfeature[slanted] [default][slant=.25] +% \definefontfeature[stretched][default][stretch=2] +% +% \start \definedfont[SerifBold*slanted at 20pt] \ruledhbox{Test!} \stop +% \start \definedfont[SerifBold*stretched at 20pt] \ruledhbox{Test!} \stop +% +% \definefontfeature[default] [liga=yes,texligatures=yes,texquotes=yes] +% \definefontfeature[default-caps][liga=yes,texligatures=yes,texquotes=yes,smcp=yes,script=latn] +% +% \starttypescript [serif] [palatino-nova-regular] [name] +% \definefontsynonym[Serif] [palatinonova-regular][features=default] +% \definefontsynonym[SerifCaps][palatinonova-regular][features=default-caps] % also sets Serif +% \stoptypescript +% +% \starttypescript [serif] [palatino-nova-regular] [name] +% \definefontsynonym[Serif] [palatinonova-regular*default] +% \definefontsynonym[SerifCaps] [palatinonova-regular*default-caps] +% \stoptypescript +% +% \definetypeface[mainface][rm][serif][palatino-nova-regular][default] \setupbodyfont[mainface] +% +% \starttext +% ``Test'' -- --- ff fi fl \sc ``Test'' -- --- ff fi fl +% \stoptext +% +% \definefontfeature +% [default-base] +% [script=latn,language=dflt,liga=yes,kern=yes,tlig=yes,trep=yes] +% \definefontfeature +% [default-node] +% [script=latn,language=dflt,liga=yes,kern=yes,tlig=yes,trep=yes,mode=node] +% \definefontfeature +% [default-none] +% [script=latn,language=dflt,liga=yes,kern=no, tlig=yes,trep=yes] +% +% \startoverlay +% {\vtop{\color[red] {\font\test=name:lmroman12regular*default-node \test \input ward \input zapf \input linden }}} +% {\vtop{\color[green]{\font\test=name:lmroman12regular*default-base \test \input ward \input zapf \input linden }}} +% {\vtop{\color[blue] {\font\test=name:lmroman12regular*default-none \test \input ward \input zapf \input linden }}} +% \stopoverlay +% +% \blank +% +% \startoverlay +% {\vtop{\color[red] {\font\test=name:texgyrepagella*default-node \test \input ward \input zapf \input linden }}} +% {\vtop{\color[green]{\font\test=name:texgyrepagella*default-base \test \input ward \input zapf \input linden }}} +% {\vtop{\color[blue] {\font\test=name:texgyrepagella*default-none \test \input ward \input zapf \input linden }}} +% \stopoverlay +% +% \blank +% +% \startoverlay +% {\vtop{\color[red] {\font\test=name:palatinonovaregular*default-node \test \input ward \input zapf \input linden }}} +% {\vtop{\color[green]{\font\test=name:palatinonovaregular*default-base \test \input ward \input zapf \input linden }}} +% {\vtop{\color[blue] {\font\test=name:palatinonovaregular*default-none \test \input ward \input zapf \input linden }}} +% \stopoverlay +% +% \startoverlay +% {\vtop{\color[red] {\font\test=name:OfficinaSerifBookITC*default-node \test \input ward \input zapf \input linden }}} +% {\vtop{\color[green]{\font\test=name:OfficinaSerifBookITC*default-base \test \input ward \input zapf \input linden }}} +% {\vtop{\color[blue] {\font\test=name:OfficinaSerifBookITC*default-none \test \input ward \input zapf \input linden }}} +% \stopoverlay +% +% \definefontfeature[superdefault][default][compose=yes] +% +% {\font\oeps=name:lmroman10regular*default at 30pt \oeps test \char7683} +% {\font\oeps=name:lmroman10regular*superdefault at 30pt \oeps test \char7683} + +\permanent\tolerant\protected\def\definefontfeature[#featureset]#spacer[#parent]#spacer[#settings]% + {\clf_definefontfeature{#featureset}{#parent}{#settings}} + +\permanent\tolerant\protected\def\adaptfontfeature[#pattern]#spacer[#settings]% + {\clf_adaptfontfeature{#pattern}{#settings}} + +\permanent\protected\def\fontfeatureslist[#name]#spacer[#separator]% todo: arg voor type + {\clf_featurelist{#name}{\detokenize{#separator}}} + +\attribute\zerocount\attributeunsetvalue + +\glyphdatafield\zerocount + +\let\font_dynamic_value\glyphdatafield + +% beware: these are global features on top of existing font features + +\let\currentfeature \s!current +\let\m_font_feature_list \s!current +\let\m_font_feature_asked\empty + +\newconstant\c_font_feature_state + +% hashing at this end is slower + +\permanent\tolerant\protected\def\addfeature [#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_add} +\permanent\tolerant\protected\def\subtractfeature [#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_subtract} +\permanent\tolerant\protected\def\replacefeature [#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_replace} +\permanent\tolerant\protected\def\resetandaddfeature[#1]#;#2{\edef\m_font_feature_asked{#1#2}\font_feature_reset_add} +\permanent\tolerant\protected\def\feature [#1]#;#2{\begincsname\??featureshortcut##1#2\endcsname{#1#2}} + +% for old times sake + +\permanent\protected\def\doaddfeature #1{\edef\m_font_feature_asked{#1}\font_feature_add} +\permanent\protected\def\dosubtractfeature #1{\edef\m_font_feature_asked{#1}\font_feature_subtract} +\permanent\protected\def\doreplacefeature #1{\edef\m_font_feature_asked{#1}\font_feature_replace} +\permanent\protected\def\doresetandaddfeature#1{\edef\m_font_feature_asked{#1}\font_feature_reset_add} + +\protected\def\font_feature_add + {\ifnum\c_font_feature_state=\plusone + \ifx\m_font_feature_asked\currentfeature\else + \font_feature_add_indeed + \fi + \else + \font_feature_add_indeed + \fi} + +\protected\def\font_feature_add_indeed + {\clf_addfeature{\m_font_feature_list}{\m_font_feature_asked}% + \edef\m_font_feature_list{\m_font_feature_list+\m_font_feature_asked}% also + at the lua end + \c_font_feature_state\plusone + \let\currentfeature\m_font_feature_asked} + +\protected\def\font_feature_subtract + {\ifnum\c_font_feature_state=\minusone + \ifx\m_font_feature_asked\currentfeature\else + \font_feature_subtract_indeed + \fi + \else + \font_feature_subtract_indeed + \fi} + +\protected\def\font_feature_subtract_indeed + {\clf_subtractfeature{\m_font_feature_list}{\m_font_feature_asked}% + \edef\m_font_feature_list{\m_font_feature_list-\m_font_feature_asked}% also - at the lua end + \c_font_feature_state\minusone + \let\currentfeature\m_font_feature_asked} + +\protected\def\font_feature_replace + {\ifnum\c_font_feature_state=\zerocount + \ifx\m_font_feature_asked\currentfeature\else + \font_feature_replace_indeed + \fi + \else + \font_feature_replace_indeed + \fi} + +\protected\def\font_feature_replace_indeed + {\clf_replacefeature{\m_font_feature_list}{\m_font_feature_asked}% + \edef\m_font_feature_list{\m_font_feature_list=\m_font_feature_asked}% also = at the lua end + \c_font_feature_state\zerocount + \let\currentfeature\m_font_feature_asked} + +\protected\def\resetfeature + {\ifx\currentfeature\s!current \else + \font_feature_reset_indeed + \fi} + +\protected\def\font_feature_reset_indeed + {\let\m_font_feature_asked\empty + \let\currentfeature \s!current + \let\m_font_feature_list \s!current + \clf_resetfeature} + +\protected\def\revivefeature + {\ifx\currentfeature\s!current \else + \font_feature_revive_indeed + \fi} + +\protected\def\font_feature_revive_indeed + {\clf_revivefeature{\m_font_feature_list}} + +\protected\def\font_feature_reset_add + {\ifnum\c_font_feature_state=\plusone + \ifx\m_font_feature_asked\currentfeature\else + \font_feature_reset_add_indeed + \fi + \else + \font_feature_reset_add_indeed + \fi} + +\protected\def\font_feature_reset_add_indeed + {\clf_addfeature{\s!current}{\m_font_feature_asked}% + \edef\m_font_feature_list{\s!current+\m_font_feature_asked}% also + at the lua end + \c_font_feature_state\plusone + \let\currentfeature\m_font_feature_asked} + +\installcorenamespace{featureshortcut} + +\letvalue{\??featureshortcut +}\addfeature +\letvalue{\??featureshortcut -}\subtractfeature +\letvalue{\??featureshortcut =}\replacefeature +\letvalue{\??featureshortcut !}\resetandaddfeature +\letvalue{\??featureshortcut >}\revivefeature +\letvalue{\??featureshortcut <}\resetfeature + +\letvalue{\??featureshortcut\v!more }\addfeature % add set to previous set and combine with font set +\letvalue{\??featureshortcut\v!less }\subtractfeature % subtract set from previous set and combine with font set +\letvalue{\??featureshortcut\v!new }\replacefeature % replace font set +\letvalue{\??featureshortcut\v!reset }\resetfeature % forget sets and revert to font set +\letvalue{\??featureshortcut\v!default}\revivefeature % make sure the current set is used on top of the font set +\letvalue{\??featureshortcut\v!old }\revivefeature +\letvalue{\??featureshortcut\v!local }\resetandaddfeature +\letvalue{\??featureshortcut\s!unknown}\empty + +% experimental bonus: + +% \protected\def\addfflanguage +% {\ifnum\c_font_feature_state=\plusone +% \ifx\currentlanguage\currentfeature\else +% \font_feature_add_language_indeed +% \fi +% \else +% \font_feature_add_language_indeed +% \fi} +% +% \protected\def\font_feature_add_language_indeed +% {\clf_addfeature{\m_font_feature_list}{\currentlanguage}% +% \edef\m_font_feature_list{\m_font_feature_list+\currentlanguage}% also + at the lua end +% \c_font_feature_state\plusone +% \let\currentfeature\currentlanguage} +% +% some 3% slower: + +% \protected\def\addfflanguage +% {\let\m_font_feature_asked\currentlanguage +% \font_feature_add} + +\let\m_font_feature_language\currentlanguage + +\permanent\protected\def\addfflanguage + {\ifx\currentlanguage\m_font_feature_language\else + \let\m_font_feature_language\currentlanguage + \let\m_font_feature_asked \currentlanguage + \font_feature_add + \fi} + +% just for old times sake: + +\permanent\protected\def\featureattribute#feature% + {\clf_featureattribute{#feature}} + +\permanent\protected\def\setfontfeature#feature% + {\edef\currentfeature{#feature}% + \let\m_font_feature_list\currentfeature + \clf_setfontfeature{\currentfeature}} + +\let\resetfontfeature\resetfeature + +% these are obsolete (don't use them any longer) + +% \let\addfontfeaturetoset \font_feature_add_nop +% \let\subtractfontfeaturefromset \font_feature_subtract_nop +% \let\addfontfeaturetofont \font_feature_add_nop +% \let\subtractfontfeaturefromfont\font_feature_subtract_nop + +% also old, maybe some day a comptability module + +\let\setff\setfontfeature +\let\addfs\doaddfeature +\let\subfs\dosubtractfeature +\let\addff\doaddfeature +\let\subff\dosubtractfeature + +%D \macros +%D {os} +%D +%D In good old \TEX, the old style numerals were often taken +%D from the math fonts. No longer. + +\definefontfeature + [just-os] + [mode=node,onum=yes] + +%frozen\protected\def\sc{\setfontfeature{smallcaps}} +\permanent\protected\def\os{\setfontfeature{just-os}} + +% \doifelsecurrentfonthasfeature{smcp}{YES}{NO} +% \doifelsecurrentfonthasfeature{crap}{YES}{NO} +% \doifelsecurrentfonthasfeature{kern}{YES}{NO} + +\permanent\def\doifelsecurrentfonthasfeature#feature{\clf_doifelsecurrentfonthasfeature{#feature}} % expandable +\permanent\def\doifelsefontfeature #feature{\clf_doifelsefontfeature {#feature}} % expandable +\permanent\def\doifunknownfontfeature #feature{\clf_doifunknownfontfeature {#feature}} % expandable + +\let\doifcurrentfonthasfeatureelse\doifelsecurrentfonthasfeature +\let\doiffontfeatureelse \doifelsefontfeature + +% new: + +\clf_registerlanguagefeatures + +% also new + +\permanent\protected\def\useaddfontfeatureparameter#namespace% faster local variant + {\edef\m_font_feature_asked{#namespace\c!features}% + \ifx\m_font_feature_asked\empty\else + \font_feature_add + \fi} + +% let's put this here: + +\permanent\protected\def\slashedzero + {\dontleavehmode + \begingroup + %\addff{zero} + \doaddfeature{zero}% + 0% + \endgroup} + +% not nice but maybe handy + +% \starttyping +% \blockligatures[fi,ff] \blockligatures[fl] +% +% \definefontfeature[default:b][default][blockligatures=yes] +% +% \setupbodyfont[pagella] \showfontkerns +% +% \definedfont[Serif*default:b] +% +% \startTEXpage[offset=1em] +% fi ff fl +% \stopTEXpage +% \stoptyping + +\permanent\protected\def\blockligatures[#1]{\clf_blockligatures{#1}} + +\protect \endinput diff --git a/tex/context/base/mkiv/font-fil.mklx b/tex/context/base/mkiv/font-fil.mklx index 3bc5d8c26..7f08a9348 100644 --- a/tex/context/base/mkiv/font-fil.mklx +++ b/tex/context/base/mkiv/font-fil.mklx @@ -41,26 +41,22 @@ % % \setupbodyfont[palatino] -\unexpanded\def\startfontclass - {\dosingleempty\font_basics_start_font_class} - -\def\font_basics_start_font_class[#class]% +\permanent\protected\tolerant\protected\def\startfontclass[#class]% {\push_macro_fontclass \doifelse{#class}\v!each {\let\fontclass\empty} {\doifsomething{#class}{\def\fontclass{#class}}}} -\unexpanded\def\stopfontclass +\permanent\protected\def\stopfontclass {\pop_macro_fontclass} -\def\classfont#class#name{#class#name} % \definefont[whatever][\classfont{xx}{yy} at 10pt] +\permanent\def\classfont#class#name{#class#name} % \definefont[whatever][\classfont{xx}{yy} at 10pt] %D \macros %D {definefontsynonym, doifelsefontsynonym, %D expandfontsynonym, truefontname, truefontdata} %D -%D While looking for fonts, fontsynonyms are used for accessing -%D the files! +%D While looking for fonts, fontsynonyms are used for accessing the files! %D %D \starttyping %D \definefontsynonym[Serif][Lucida-Bright] @@ -75,7 +71,7 @@ \def \defaultfontfile{\truefontname{Normal}} % was cmtt10, but that one is gone \edef\nullfontname {\fontname\nullfont} -\unexpanded\def\definefontsynonym[#name]#crap[#file]% +\permanent\protected\def\definefontsynonym[#name]#spacer[#file]% {\edef\m_font_name{#name}% \edef\m_font_file{#file}% \ifempty\fontclass @@ -84,15 +80,15 @@ \expandafter\font_basics_define_font_synonym_yes \fi} -\unexpanded\def\font_basics_define_font_synonym_nop +\protected\def\font_basics_define_font_synonym_nop {\expandafter\let\csname\??fontfile\m_font_name\endcsname\m_font_file \doifelsenextoptionalcs\font_basics_define_font_synonym_nop_opt\font_basics_define_font_synonym_nop_nil} -\unexpanded\def\font_basics_define_font_synonym_yes +\protected\def\font_basics_define_font_synonym_yes {\expandafter\let\csname\??fontfile\fontclass\m_font_name\endcsname\m_font_file \doifelsenextoptionalcs\font_basics_define_font_synonym_yes_opt\font_basics_define_font_synonym_yes_nil} -\unexpanded\def\edefinefontsynonym[#name]#ignore[#file]% +\protected\def\edefinefontsynonym[#name]#spacer[#file]% {\edef\m_font_name{#name}% \edef\m_font_file{#file}% \ifempty\fontclass @@ -101,55 +97,22 @@ \expandafter\font_basics_define_font_synonym_yes_expanded \fi} -\unexpanded\def\font_basics_define_font_synonym_nop_expanded#ignore[#spec]% +\protected\def\font_basics_define_font_synonym_nop_expanded#ignore[#spec]% {\expandafter\let\csname\??fontfile\m_font_name\endcsname\m_font_file \normalexpanded{\font_basics_define_font_synonym_nop_opt[#spec]}} -\unexpanded\def\font_basics_define_font_synonym_yes_expanded#ignore[#spec]% +\protected\def\font_basics_define_font_synonym_yes_expanded#ignore[#spec]% {\expandafter\let\csname\??fontfile\fontclass\m_font_name\endcsname\m_font_file \normalexpanded{\font_basics_define_font_synonym_yes_opt[#spec]}} -% \unexpanded\def\font_basics_define_font_synonym_nop_opt[#specification]% -% {\let\p_features \undefined -% \let\p_fallbacks \undefined -% \let\p_goodies \undefined -% \let\p_designsize\undefined -% \expandafter\font_basics_get_font_parameter_nop#specification,]=,} -% -% \unexpanded\def\font_basics_define_font_synonym_yes_opt[#specification]% -% {\let\p_features \undefined -% \let\p_fallbacks \undefined -% \let\p_goodies \undefined -% \let\p_designsize\undefined -% \expandafter\font_basics_get_font_parameter_yes#specification,]=,} -% -% % todo: check if we can use \edef but then we need to protect \mathsizesuffix .. in fact that -% % can be default then: \let\mathsizesuffix\relax .. i need to play with it first -% -% \def\font_basics_get_font_parameter_nop#key=#value,% -% {\if]#key% -% \font_basics_get_font_parameter_nop_finish -% \else -% \expandafter\normaldef\csname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix -% \expandafter\font_basics_get_font_parameter_nop -% \fi} -% -% \def\font_basics_get_font_parameter_yes#key=#value,% -% {\if]#key% -% \font_basics_get_font_parameter_yes_finish -% \else -% \expandafter\normaldef\csname p_#key\endcsname{#value}% % no edef as we need to keep \mathsizesuffix -% \expandafter\font_basics_get_font_parameter_yes -% \fi} - -\unexpanded\def\font_basics_define_font_synonym_nop_opt[#specification]% +\protected\def\font_basics_define_font_synonym_nop_opt[#specification]% {\let\p_features \undefined \let\p_fallbacks \undefined \let\p_goodies \undefined \let\p_designsize\undefined \expandafter\font_basics_get_font_parameter_nop#specification,\ignorearguments} -\unexpanded\def\font_basics_define_font_synonym_yes_opt[#specification]% +\protected\def\font_basics_define_font_synonym_yes_opt[#specification]% {\let\p_features \undefined \let\p_fallbacks \undefined \let\p_goodies \undefined @@ -213,73 +176,23 @@ \expandafter\glet\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\p_designsize} %\definefontsynonym [KopFont] [\fontclassname{officina}{SerifBold}] -% %\defineclassfontsynonym [KopFont] [officina] [SerifBold] - -\unexpanded\def\defineclassfontsynonym - {\dotripleargument\font_basics_define_class_font_synonym} - %\definefontsynonym[#tag][\fontclassname{#class}{#fileortag}]} -\def\font_basics_define_class_font_synonym[#tag][#class][#fileortag]% needs testing +\permanent\tolerant\protected\def\defineclassfontsynonym[#tag]#spacer[#class]#spacer[#fileortag]% needs testing {\expandafter\normaldef\csname\??fontfile\fontclass#tag\endcsname{\fontclassname{#class}{#fileortag}}% \font_basics_define_font_synonym_yes_nil} -\let\definefontfile\definefontsynonym % dedicated to Taco Hoekwater - -\unexpanded\def\setupfontsynonym - {\dodoubleempty\dosetupfontsynonym} +\aliased\let\definefontfile\definefontsynonym % dedicated to Taco Hoekwater -\def\dosetupfontsynonym[#name][#settings]% not yet supported, will do when needed +\permanent\tolerant\protected\def\setupfontsynonym[#name]#spacer[#settings]% not yet supported, will do when needed {} % todo: replace * by ... less messy with features -% % no \ifempty here as #1 can be empty -% -% \def\truefontname#name% -% {\expandafter\font_helpers_true_fontname#name*\empty*\relax} -% -% \def\font_helpers_true_fontname#name*#first#rest*#crap\relax -% {\ifcsname\??fontfile\fontclass#name\endcsname -% \ifx#first\empty -% \expandafter\truefontname\lastnamedcs -% \else -% \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest% -% \fi -% \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname -% \ifx#first\empty -% \expandafter\truefontname\lastnamedcs -% \else -% \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest% -% \fi -% \orelse\ifcsname\??fontfile#name\endcsname -% \ifx#first\empty -% \expandafter\truefontname\lastnamedcs -% \else -% \expandafter\font_helpers_true_fontname_check\lastnamedcs*#first#rest% -% \fi -% \else -% #name\ifempty#first\else*#first#rest\fi -% \fi} -% -% \def\font_helpers_true_fontname_check#name% -% {\expandafter\font_helpers_true_fontname_check_indeed#name*\relax} -% -% \def\font_helpers_true_fontname_check_indeed#name*#crap\relax -% {\ifcsname\??fontfile\fontclass#name\endcsname -% \expandafter\font_helpers_true_fontname_check\lastnamedcs -% \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname -% \expandafter\font_helpers_true_fontname_check\lastnamedcs -% \orelse\ifcsname\??fontfile#name\endcsname -% \expandafter\font_helpers_true_fontname_check\lastnamedcs -% \else -% #name% -% \fi} - % no \ifempty here as #1 can be empty -\def\truefontname#name% +\permanent\def\truefontname#name% {\expandafter\font_helpers_true_fontname#name*\empty*\relax} \def\font_helpers_true_fontname#name*#first#rest*#ignore\relax @@ -320,31 +233,15 @@ \fi} % ok when the last lookup is not stripped .. we need to be able to define synonyms for symbols -% -% \def\truefontname#name% -% %{\normalexpanded{\noexpand\font_helpers_true_fontname{\clf_truefontname{#name}}}} -% {\expandafter\expandafter\expandafter\font_helpers_true_fontname\expandafter\expandafter\expandafter{\clf_truefontname{#name}}} -% -% \def\font_helpers_true_fontname#name% -% {\ifcsname\??fontfile\fontclass#name\endcsname -% \expandafter\font_helpers_true_fontname\expandafter{\lastnamedcs}% -% \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname -% \expandafter\font_helpers_true_fontname\expandafter{\lastnamedcs}% -% \orelse\ifcsname\??fontfile#name\endcsname -% \expandafter\font_helpers_true_fontname\expandafter{\lastnamedcs}% -% \else -% % \clf_truefontname{#name}% -% #name% so the last one can have features ! -% \fi} - -\def\expandfontsynonym#command#name% one level expansion + +\permanent\def\expandfontsynonym#command#name% one level expansion {\ifcsname\??fontfile\fontclass#name\endcsname \expandafter\normaldef\expandafter#command\expandafter{\lastnamedcs}% \orelse\ifcsname\??fontfile\defaultfontclass#2\endcsname \expandafter\normaldef\expandafter#command\expandafter{\lastnamedcs}% \fi} -\def\doifelsefontsynonym#name% +\permanent\def\doifelsefontsynonym#name% {\ifcsname\??fontfile\fontclass#name\endcsname \expandafter\firstoftwoarguments \orelse\ifcsname\??fontfile\defaultfontclass#name\endcsname @@ -353,14 +250,14 @@ \expandafter\secondoftwoarguments \fi} -\let\doiffontsynonymelse\doifelsefontsynonym +\aliased\let\doiffontsynonymelse\doifelsefontsynonym %D \macros %D {tracedfontname} %D %D A goody: -\def\tracedfontname#name% +\permanent\def\tracedfontname#name% {#name\ifcsname\??fontfile\fontclass#name\endcsname %\expandafter\tracedfontname\csname\??fontfile\fontclass#name\endcsname \expandafter\tracedfontname\lastnamedcs @@ -379,7 +276,7 @@ \let\fontclass \empty \let\defaultfontclass\empty -\def\fontclassname#class#name% tricky ... no lastnamedcs here due to nesting +\permanent\def\fontclassname#class#name% tricky ... no lastnamedcs here due to nesting {\ifcsname\??fontfile#class#name\endcsname \fontclassname{#class}{\csname\??fontfile#class#name\endcsname}% \orelse\ifcsname\??fontfile#name\endcsname @@ -394,8 +291,8 @@ %D They can inherit them. % Why these expanded and rscale not ... maybe not worth the trouble (delayed -% expansion actually would be better i.e. macros in feature specs). Test -% without pre-expansion. +% expansion actually would be better i.e. macros in feature specs). Test without +% pre-expansion. \def\font_helpers_update_font_class_parameters {\edef\m_font_class_direction {\begincsname\??fontclass\fontclass\fontstyle\s!direction \endcsname}% @@ -473,7 +370,7 @@ % we can pack them (don't use \setxvalue!) -\unexpanded\def\savefontclassparameters#style#rscale#features#fallbacks#goodies#designsize#direction% +\permanent\protected\def\savefontclassparameters#style#rscale#features#fallbacks#goodies#designsize#direction% {\letgvalue{\??fontclass\fontclass#style\s!rscale }#rscale% \letgvalue{\??fontclass\fontclass#style\s!features }#features% \letgvalue{\??fontclass\fontclass#style\s!fallbacks }#fallbacks% diff --git a/tex/context/base/mkiv/font-ini.mklx b/tex/context/base/mkiv/font-ini.mklx index 882f879a2..a9e01e7ec 100644 --- a/tex/context/base/mkiv/font-ini.mklx +++ b/tex/context/base/mkiv/font-ini.mklx @@ -12,6 +12,8 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. +% todo: frozen tolerant iftok etc + % todo: < 3 pt => 3pt % todo: check where more class usage % todo: split font-nam (style/alternative/size) @@ -326,12 +328,12 @@ \newtoks\t_font_tracers_definitions -\unexpanded\def\tracefontdefinitions +\permanent\protected\def\tracefontdefinitions {\the\t_font_tracers_definitions} %D Some housekeeping macros: -\unexpanded\def\setfontparameters +\permanent\protected\def\setfontparameters {\setfalse\c_font_synchronize \the\everybodyfont \settrue\c_font_synchronize} @@ -340,16 +342,22 @@ \installmacrostack\savedfont -\unexpanded\def\savefont - {\edef\savedfont{\the\font}% gives \csname +% \fontname\font : string +% \fontid \font : integer +% \the \font : token (reference to font) +% \fontspecifiedname : string +% \the \fontspecifiedsize : dimension + +\permanent\protected\def\savefont + {\edef\savedfont{\the\font}% \push_macro_savedfont} -\unexpanded\def\restorefont +\permanent\protected\def\restorefont {\pop_macro_savedfont \savedfont} -\unexpanded\def\pushcurrentfont - {\edef\popcurrentfont +\permanent\protected\def\pushcurrentfont + {\enforced\permanent\protected\edef\popcurrentfont {\def\noexpand\fontbody {\fontbody}% \def\noexpand\fontstyle {\fontstyle}% \def\noexpand\fontalternative{\fontalternative}% @@ -361,24 +369,20 @@ \let\thedefinedfont\relax % not to be confused with \everydefinefont -\unexpanded\def\definedfont - {\doifelsenextoptionalcs\font_basics_defined_font_yes\font_basics_defined_font_nop} - -\def\font_basics_defined_font_yes[#specification]% - {\c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly - \font_basics_define_font_without_parameters{thedefinedfont}{#specification}% - \thedefinedfont - \the\everydefinedfont} - -\def\font_basics_defined_font_nop - {\c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly +\permanent\tolerant\protected\def\definedfont[#specification]% + {\ifarguments + \c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly + \or + \c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly + \font_basics_define_font_without_parameters{thedefinedfont}{#specification}% + \fi \thedefinedfont \the\everydefinedfont} %D \macros{startfont} -\unexpanded\def\startfont{\begingroup\definedfont} -\unexpanded\def\stopfont {\endgroup} +\permanent\protected\def\startfont{\begingroup\definedfont} +\permanent\protected\def\stopfont {\endgroup} %D \macros %D {everybodyfont,everyglobalbodyfont} @@ -411,7 +415,7 @@ \installcorenamespace{fontnormalizedbody} -\def\normalizebodyfontsize#macro#body% +\protected\def\normalizebodyfontsize#macro#body% {\expandafter\let\expandafter#macro\csname\??fontnormalizedbody\number\dimexpr#body\endcsname \ifx#macro\relax \normalizebodyfontsize_indeed#macro{#body}% @@ -424,9 +428,9 @@ \def\thenormalizedbodyfontsize#body% {\clf_nbfs\dimexpr#body\relax} -\edef\normalizedglobalbodyfontsize{\thenormalizedbodyfontsize\bodyfontsize} -\edef\normalizedlocalbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize} -\edef\normalizedbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize} +\protected\edef\normalizedglobalbodyfontsize{\thenormalizedbodyfontsize\bodyfontsize} +\protected\edef\normalizedlocalbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize} +\protected\edef\normalizedbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize} %D \macros %D {mapfontsize} @@ -457,11 +461,8 @@ \installcorenamespace{mappedfontsize} -\unexpanded\def\mapfontsize - {\dodoubleargument\font_basics_map_fontsize} - -\def\font_basics_map_fontsize[#from][#to]% - {\setvalue{\??mappedfontsize\the\dimexpr#from\relax}{#to}} +\permanent\tolerant\protected\def\mapfontsize[#from]#spacer[#to]% + {\ifarguments\or\or\setvalue{\??mappedfontsize\the\dimexpr#from\relax}{#to}\fi} \def\font_basics_set_mapped_fontsize#from% {\ifcsname\??mappedfontsize\the\dimexpr#from\relax\endcsname @@ -555,10 +556,7 @@ \def\font_helpers_register_size #size{\expandafter\let\csname\??fontsizeknown #size\endcsname\empty} \def\font_helpers_register_alternative#alternative{\expandafter\let\csname\??fontalternativeknown#alternative\endcsname\empty} -\unexpanded\def\definefontstyle - {\dodoubleargument\font_basics_define_fontstyle} - -\def\font_basics_define_fontstyle[#commands][#style]% style: rm ss tt ... +\permanent\protected\def\definefontstyle[#commands]#spacer[#style]% style: rm ss tt ... {\ifcsname\??fontstyleknown#style\endcsname \else % can be delayed till used (cg, hw) \font_helpers_register_style{#style}% \toksapp\t_font_style_commands{\m_font_style_command{#style}}% @@ -569,21 +567,21 @@ {\setvalue{\??fontshortstyle#command}{#style}% \setvalue{\??fontstyle #command}{\csname#style\endcsname}} -\unexpanded\def\definefontsize[#size]% +\permanent\protected\def\definefontsize[#size]% {\ifcsname\??fontsizeknown#size\endcsname \else \font_helpers_register_size{#size}% \toksapp\t_font_size_commands{\m_font_size_command{#size}}% \fi \font_helpers_check_fontname_combinations} -\unexpanded\def\definefontalternative[#alternative]% +\permanent\protected\def\definefontalternative[#alternative]% {\ifcsname\??fontalternativeknown#alternative\endcsname \else \font_helpers_register_alternative{#alternative}% \toksapp\t_font_alternative_commands{\m_font_alternative_command{#alternative}}% \fi \font_helpers_check_fontname_combinations} -\unexpanded\def\font_helpers_check_fontname_combinations % we need to split math and text here ... todo (math only has mr and mb) +\protected\def\font_helpers_check_fontname_combinations % we need to split math and text here ... todo (math only has mr and mb) {\font_helpers_process_style_list\font_helpers_check_fontname_combinations_s} \def\font_helpers_check_fontname_combinations_s#style% @@ -692,7 +690,7 @@ \newconditional\c_font_body_scale \newfraction \f_font_body_scale -\unexpanded\def\font_helpers_low_level_define#specification#csname% +\protected\def\font_helpers_low_level_define#specification#csname% {% we can now set more at the lua end \glet\somefontname\defaultfontfile \let\somefontsize\empty @@ -895,7 +893,7 @@ %D %D The implementation looks as follows: -\unexpanded\def\definefont % [name][spec][1.6 | line=10pt | setup_id] +\protected\def\definefont % [name][spec][1.6 | line=10pt | setup_id] {\dotripleempty\font_basics_define_font} \def\font_basics_define_font @@ -925,22 +923,15 @@ %D Beware, in the frozen variants no settings are supported yet, but that might happen %D some day. -\unexpanded\def\definefrozenfont - {\dotripleempty\font_basics_define_frozen_font} - -% \def\font_basics_define_frozen_font[#name][#specification][#settings]% -% {\begingroup -% \font_basics_define_font[#name][#specification][#settings]% -% \csname#name\endcsname -% \expandafter\expandafter\expandafter\endgroup\expandafter\let\csname#name\endcsname\lastrawfontcall} - -\def\font_basics_define_frozen_font[#name][#specification][#settings]% - {\begingroup - \font_basics_define_font[#name][#specification][#settings]% - \csname#name\endcsname - \glet\lastglobalrawfontcall\lastrawfontcall - \endgroup - \expandafter\let\csname#name\endcsname\lastglobalrawfontcall} +\permanent\tolerant\protected\def\definefrozenfont[#name]#spacer[#specification]#spacer[#settings]% + {\ifparameter#name\or + \begingroup + \font_basics_define_font[#name][#specification][#settings]% + \csname#name\endcsname + \glet\lastglobalrawfontcall\lastrawfontcall + \endgroup + \expandafter\let\csname#name\endcsname\lastglobalrawfontcall + \fi} %D The instance namespace protection makes the switch local so that we can redefine a %D logical name and/or change the size in between. @@ -976,7 +967,7 @@ \the\everyfontswitch \let\v_font_identifier_basic\v_font_identifier_basic_saved} -\unexpanded\def\font_helpers_trigger#identifier% make a traced variant +\protected\def\font_helpers_trigger#identifier% make a traced variant {\edef\lastfontidentifier{#identifier}% \ifcsname\v_font_identifier_class\endcsname % \writestatus{fonts}{trigger: reusing \v_font_identifier_class}% @@ -1192,11 +1183,6 @@ \lastnamedcs\dimexpr#body\relax\fi % factor \relax} -\unexpanded\def\definebodyfontenvironment - {\dotripleempty\font_basics_define_body_font_environment} - -\let\setupbodyfontenvironment\definebodyfontenvironment - \installcorenamespace{fontenvironmentknown} \def\font_helpers_register_environment#class#body% @@ -1205,6 +1191,9 @@ \newmacro\m_font_body \newmacro\m_font_body_normalized +\permanent\protected\def\definebodyfontenvironment % todo + {\dotripleempty\font_basics_define_body_font_environment} + \def\font_basics_define_body_font_environment {\ifthirdargument \singleexpandafter\font_basics_define_body_font_environment_class @@ -1214,11 +1203,13 @@ \expandafter\font_basics_define_body_font_environment_unset \fi} +\let\setupbodyfontenvironment\definebodyfontenvironment + %D First we handle the class specific case. Beware: you can change values before %D a bodyfont is loaded but changing them afterwards can be sort of tricky as %D values are not consulted afterwards. -\def\processbodyfontenvironmentlist#1% no \unexpanded as then we cannot use it in alignments +\def\processbodyfontenvironmentlist#1% no \protected as then we cannot use it in alignments (still?) {\clf_processbodyfontsizes{\strippedcsname#1}} \def\bodyfontenvironmentlist @@ -1371,17 +1362,22 @@ % [class] [10pt,11pt] [settings] == [name] [rm] [settings] % [class] [10pt,11pt] [name] == [10pt,11pt] [rm] [name] -\unexpanded\def\definebodyfont - {\doquadrupleempty\font_basics_define_body_font} - -\def\font_basics_define_body_font[#1][#2][#3][#4]% - {\iffourthargument +\permanent\tolerant\protected\def\definebodyfont[#1]#*[#2]#*[#3]#*[#4]% + {\ifarguments + \or + \font_basics_define_body_font[#1][\s!rm][]% + \or + \font_basics_define_body_font[#1][\s!rm][#2]% + \or + \font_basics_define_body_font[#1][#2][#3]% + \or \processcommacommand[#1]{\font_basics_define_body_font_class_given[#2][#3][#4]}% - \else - \font_basics_define_body_font_class_known[#1][#2][#3]% \fi} -\def\font_basics_define_body_font_class_given[#1][#2][#3]#4% +\protected\def\font_basics_define_body_font[#whatever]% + {\doifelsenumber{#whatever}\font_basics_define_body_font_body\font_basics_define_body_font_name[#whatever]} + +\protected\def\font_basics_define_body_font_class_given[#1][#2][#3]#4% {\push_macro_fontclass \doifelse{#4}\s!default {\let\fontclass\empty} @@ -1389,28 +1385,7 @@ \definebodyfont[#1][#2][#3]% \pop_macro_fontclass} -\def\font_basics_define_body_font_class_known - {\ifthirdargument - \singleexpandafter\font_basics_define_body_font_a - \orelse\ifsecondargument - \expandafter\font_basics_define_body_font_b - \else - \expandafter\font_basics_define_body_font_c - \fi} - -\unexpanded\def\font_basics_define_body_font_b[#whatever][#specification][#dummy]% body|identifier defs|identifier - {\font_basics_define_body_font_a[#whatever][\s!rm][#specification]} - -\unexpanded\def\font_basics_define_body_font_c[#whatever][#dummya][#dummyb]% body|identifier - {\font_basics_define_body_font_a[#whatever][\s!rm][]} - -\unexpanded\def\font_basics_define_body_font_a[#whatever]% - {\doifelsenumber{#whatever}% - \font_basics_define_body_font_body - \font_basics_define_body_font_name - [#whatever]} - -\unexpanded\def\font_basics_define_body_font_body[#body][#style][#specification]% +\protected\def\font_basics_define_body_font_body[#body][#style][#specification]% {\ifcondition\validassignment{#specification}% \expandafter\font_basics_define_body_font_body_assignment \else @@ -1418,7 +1393,7 @@ \fi [#body][#style][#specification]}% -\unexpanded\def\font_basics_define_body_font_name[#name][#style][#specification]% +\protected\def\font_basics_define_body_font_name[#name][#style][#specification]% {\ifcondition\validassignment{#specification}% \expandafter\font_basics_define_body_font_name_assignment \else @@ -1426,41 +1401,41 @@ \fi [#name][#style][#specification]}% -\unexpanded\def\font_basics_define_body_font_body_assignment[#bodylist][#stylelist][#assignments]% +\protected\def\font_basics_define_body_font_body_assignment[#bodylist][#stylelist][#assignments]% {\processcommalist[#bodylist]{\font_basics_define_body_font_body_assignment_a{#stylelist}{#assignments}}} -\unexpanded\def\font_basics_define_body_font_body_assignment_a#stylelist#assignments#body% +\protected\def\font_basics_define_body_font_body_assignment_a#stylelist#assignments#body% {\normalizebodyfontsize\m_font_asked_body{#body}% % normally we define quite a lot in advance, i.e global defs \font_helpers_check_bodyfont_environment\m_font_asked_body\m_font_asked_body % !! \processcommalist[#stylelist]{\font_basics_define_body_font_body_assignment_b{#assignments}}} -\unexpanded\def\font_basics_define_body_font_body_assignment_b#assignments#style% +\protected\def\font_basics_define_body_font_body_assignment_b#assignments#style% {\edef\m_font_asked_style{#style}% \processcommalist[#assignments]\font_basics_define_body_font_defs} -\unexpanded\def\font_basics_define_body_font_defs +\protected\def\font_basics_define_body_font_defs {\ifempty\fontclass \expandafter\font_basics_define_body_font_defs_nop \else \expandafter\font_basics_define_body_font_defs_yes \fi} -\unexpanded\def\font_basics_define_body_font_defs_yes_normal#assignment% +\protected\def\font_basics_define_body_font_defs_yes_normal#assignment% {\ifx\m_font_asked_style\s!mm \expandafter\font_basics_define_body_font_yes_mm \else \expandafter\font_basics_define_body_font_yes_xx \fi[#assignment]} -\unexpanded\def\font_basics_define_body_font_defs_nop_normal#assignment% +\protected\def\font_basics_define_body_font_defs_nop_normal#assignment% {\ifx\m_font_asked_style\s!mm \expandafter\font_basics_define_body_font_nop_mm \else \expandafter\font_basics_define_body_font_nop_xx \fi[#assignment]} -\unexpanded\def\font_basics_define_body_font_defs_yes_traced#assignment% +\protected\def\font_basics_define_body_font_defs_yes_traced#assignment% {\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] [#assignment]}% \ifx\m_font_asked_style\s!mm \expandafter\font_basics_define_body_font_yes_mm @@ -1468,7 +1443,7 @@ \expandafter\font_basics_define_body_font_yes_xx \fi[#assignment]} -\unexpanded\def\font_basics_define_body_font_defs_nop_traced#assignment% +\protected\def\font_basics_define_body_font_defs_nop_traced#assignment% {\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] [#assignment]}% \ifx\m_font_asked_style\s!mm \expandafter\font_basics_define_body_font_nop_mm @@ -1488,29 +1463,29 @@ %D the style and the rest is a size, although in practice one will seldom define the %D size directly. We might even drop that as it gives faster code. -\unexpanded\def\font_basics_define_body_font_nop_xx[#one#two#rest=#value]% local +\protected\def\font_basics_define_body_font_nop_xx[#one#two#rest=#value]% local {\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname\undefined - \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname + \protected\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}% \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname\undefined - \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname + \protected\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}% \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname\undefined - \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname + \protected\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\noexpand\font_rscale_xx{\m_font_asked_style}}{\m_font_asked_body}{\normalunexpanded{#value}}}% } -\unexpanded\def\font_basics_define_body_font_yes_xx[#one#two#rest=#value]% global +\protected\def\font_basics_define_body_font_yes_xx[#one#two#rest=#value]% global {\ifcsname\m_font_asked_style#one#two#rest\endcsname\else\font_basics_check_fontname_combination\m_font_asked_style{#one#two}{#rest}\fi \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-1\endcsname\undefined - \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname + \protected\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-0\endcsname {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-0}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}% \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-2\endcsname\undefined - \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname + \protected\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-4\endcsname {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-4}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}% \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-3\endcsname\undefined - \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname + \protected\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest-5\endcsname {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest-5}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}% } @@ -1519,52 +1494,52 @@ %D Here the rest concerns rl or lr so in this case it is not a size specifier but %D a directional one. -\unexpanded\def\font_basics_define_body_font_nop_mm[#one#two#rest=#value]% local +\protected\def\font_basics_define_body_font_nop_mm[#one#two#rest=#value]% local {%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined % \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined % \expandafter\let\csname\??fontinstanceclass\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined - \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\s!mm-#one#two#rest\endcsname + \protected\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\s!mm-#one#two#rest\endcsname {\font_helpers_trigger{\m_font_asked_body-\s!mm-#one#two#rest}{\noexpand\font_rscale_mm}{\m_font_asked_body}{\normalunexpanded{#value}}}% } % \writestatus{fonts}{define \m_asked_style\space nop: \expandafter\meaning\csname\m_font_asked_body\m_font_asked_style#one#two#rest\endcsname}% -\unexpanded\def\font_basics_define_body_font_yes_mm[#one#two#rest=#value]% global +\protected\def\font_basics_define_body_font_yes_mm[#one#two#rest=#value]% global {%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined % \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined % \expandafter\glet\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-3\endcsname\undefined - \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\s!mm-#one#two#rest\endcsname + \protected\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\s!mm-#one#two#rest\endcsname {\font_helpers_trigger{\m_font_asked_body-\s!mm-#one#two#rest}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}% } % \writestatus{fonts}{define \m_asked_style\space yes: \expandafter\meaning\csname\fontclass\m_font_asked_body\m_font_asked_style#one#two#rest\endcsname}% -\unexpanded\def\font_basics_define_body_font_body_identifier[#bodylist][#stylelist][#name]% +\protected\def\font_basics_define_body_font_body_identifier[#bodylist][#stylelist][#name]% {\processcommalist[#bodylist]{\font_basics_define_body_font_body_identifier_a{#stylelist}{#name}}} -\unexpanded\def\font_basics_define_body_font_body_identifier_a#stylelist#name#body% +\protected\def\font_basics_define_body_font_body_identifier_a#stylelist#name#body% {\normalizebodyfontsize\m_font_asked_body{#body}% \font_helpers_check_bodyfont_environment\m_font_asked_body\m_font_asked_body % !! \processcommalist[#stylelist]{\font_basics_define_body_font_body_identifier_b{#name}}} -\unexpanded\def\font_basics_define_body_font_body_identifier_b#name#style% +\protected\def\font_basics_define_body_font_body_identifier_b#name#style% {\edef\m_font_asked_style{#style}% %\writestatus\m!fonts{[\fontclass] [\m_font_asked_body] [\m_font_asked_style] => [#name]}% \csname\??fontdefinitions#name:\m_font_asked_style\endcsname} % no checking -\unexpanded\def\font_basics_define_body_font_name_assignment[#name][#stylelist][#assignments]% +\protected\def\font_basics_define_body_font_name_assignment[#name][#stylelist][#assignments]% {\processcommalist[#stylelist]{\font_basics_define_body_font_name_assignment_a{#name}{#assignments}}} -\unexpanded\def\font_basics_define_body_font_name_assignment_a#name#assignments#style% +\protected\def\font_basics_define_body_font_name_assignment_a#name#assignments#style% {%\writestatus\m!fonts{[#name:#style] => [#assignments]}% \setevalue{\??fontdefinitions#name:#style}{\font_basics_define_body_font_default{#assignments}}} -\unexpanded\def\font_basics_define_body_font_name_identifier[#name][#stylelist][#identifier]% +\protected\def\font_basics_define_body_font_name_identifier[#name][#stylelist][#identifier]% {\processcommalist[#stylelist]{\font_basics_define_body_font_name_identifier_a{#name}{#identifier}}} -\unexpanded\def\font_basics_define_body_font_name_identifier_a#name#identifier#style% +\protected\def\font_basics_define_body_font_name_identifier_a#name#identifier#style% {%\writestatus\m!fonts{[#name:#style] => [##identifier:#style]}% \ifcsname\??fontdefinitions#name:#style\endcsname \expandafter\let\csname\??fontdefinitions#name:#style\expandafter\endcsname\csname\??fontdefinitions#identifier:#style\endcsname @@ -1577,7 +1552,7 @@ \newconditional\c_font_defining_unknown \newconditional\c_font_defining_state -\unexpanded\def\font_helpers_define_unknown_font#body% one level only +\protected\def\font_helpers_define_unknown_font#body% one level only {\font_helpers_register_fontbody{#body}% prevents loop, can go \setfalse\c_font_defining_state \font_helpers_process_relative_size_list{\font_helpers_define_unknown_check_sizes{#body}}% @@ -1615,20 +1590,13 @@ \settrue\c_font_defining_state \fi} -% \def\font_helpers_define_unknown_check_relatives#body#relativesize% -% {\ifcsname\??fontbodyknown\csname\??fontenvironments#body#relativesize\endcsname\endcsname \else -% % how \lastnamedcs here -% \expandafter\font_helpers_define_unknown_font\csname\??fontenvironments#body#relativesize\endcsname -% \settrue\c_font_defining_state -% \fi} - \def\font_helpers_define_unknown_check_relatives#body#relativesize% {\ifcsname\??fontbodyknown\csname\??fontenvironments#body#relativesize\endcsname\endcsname \else \expandafter\font_helpers_define_unknown_font\csname\??fontenvironments#body#relativesize\endcsname \settrue\c_font_defining_state \fi} -\unexpanded\def\font_basics_define_body_font_default#assignments% +\protected\def\font_basics_define_body_font_default#assignments% {\font_helpers_check_relative_font_size\m_font_asked_style % still needed here? \ifcsname\m_font_asked_style\endcsname\else \normalexpanded{\definefontstyle[\m_font_asked_style][\m_font_asked_style]}% @@ -1639,7 +1607,7 @@ %D These macros show that quite some definitions take place. Fonts are not loaded %D yet! This means that at format generation time, no font files are present. -\unexpanded\def\font_basics_switch_points#body% +\protected\def\font_basics_switch_points#body% {\ifcsname\??fontbodyknown#body\endcsname \else % we need to check the relative sizes for this body \font_helpers_define_unknown_font{#body}% @@ -1653,7 +1621,7 @@ \showmessage\m!fonts4{#body}% \fi} -\unexpanded\def\font_basics_switch_style#style% +\protected\def\font_basics_switch_style#style% {\ifcsname\??fontstyle#style\endcsname \lastnamedcs \edef\fontstyle{#style}% @@ -1702,7 +1670,7 @@ \newmacro\m_font_keyword -\unexpanded\def\font_helpers_set_font_set_font_option_keyword#method#keyword#message% +\protected\def\font_helpers_set_font_set_font_option_keyword#method#keyword#message% {\edef\m_font_keyword{#keyword}% \ifcsname\??fontenvironments\normalizedbodyfontsize\m_font_keyword\endcsname \edef\m_font_step{\font_bodyfontvariable\m_font_keyword}% @@ -1725,7 +1693,7 @@ \def\font_helpers_set_fontstyle_of_fontclass % will be overloaded later {\let\fontstyle\s!rm} -\unexpanded\def\font_helpers_set_font_set_font_option_body#method#body#message% +\protected\def\font_helpers_set_font_set_font_option_body#method#body#message% {\normalizebodyfontsize\normalizedsetfont{#body}% redundant for some calls \ifcsname\??fontbodyknown\normalizedsetfont\endcsname \else \font_helpers_define_unknown_font\normalizedsetfont @@ -1754,7 +1722,7 @@ \ifdefined\trycurrentfontclass \else - \unexpanded\def\trycurrentfontclass#typeface% + \protected\def\trycurrentfontclass#typeface% {\letvalueempty{\??fontclassnop#typeface}} \fi @@ -1766,7 +1734,7 @@ %D So far for synchronisation. (We can inline the following macros.) -\unexpanded\def\setcurrentfont#body#style#alternative#size% not used +\protected\def\setcurrentfont#body#style#alternative#size% not used {\edef\fontbody {#body}% \edef\fontstyle {#style}% \edef\fontalternative{#alternative}% @@ -1774,7 +1742,7 @@ \font_helpers_check_big_math_synchronization \font_helpers_synchronize_font} -\unexpanded\def\setcurrentfontbody#body% % not used +\protected\def\setcurrentfontbody#body% % not used {\edef\fontbody{#body}% \font_helpers_synchronize_font} @@ -1784,51 +1752,51 @@ \let\font_typescripts_inherit_check\gobbleoneargument % implemented in type-ini \fi -\unexpanded\def\font_helpers_set_current_font_style#style% +\protected\def\font_helpers_set_current_font_style#style% {\edef\fontstyle{#style}% \font_typescripts_inherit_check\fontstyle \ifmmode\mr\fi % otherwise \rm not downward compatible ... not adapted yet \font_helpers_synchronize_font} -\unexpanded\def\font_helpers_set_current_xsize_alternative#xsize#alternative% +\protected\def\font_helpers_set_current_xsize_alternative#xsize#alternative% {\edef\fontface{#xsize}% \edef\fontalternative{#alternative}% \font_helpers_synchronize_font} -\unexpanded\def\font_helpers_set_current_font_alternative#alternative% +\protected\def\font_helpers_set_current_font_alternative#alternative% {\edef\fontalternative{#alternative}% \font_helpers_synchronize_font} -\unexpanded\def\font_helpers_set_current_font_size#size% +\protected\def\font_helpers_set_current_font_size#size% {\edef\fontsize{#size}% \font_helpers_check_big_math_synchronization % double? better in everymath? \font_helpers_synchronize_font} -\unexpanded\def\font_helpers_set_current_font_style_alternative#style#alternative% \rmsl +\protected\def\font_helpers_set_current_font_style_alternative#style#alternative% \rmsl {\edef\fontstyle {#style}% \edef\fontalternative{#alternative}% \font_helpers_synchronize_font} -\unexpanded\def\font_helpers_set_current_font_style_size#style#size% \rma +\protected\def\font_helpers_set_current_font_style_size#style#size% \rma {\edef\fontstyle{#style}% \edef\fontsize {#size}% \font_helpers_check_big_math_synchronization % double? better in everymath? \font_helpers_synchronize_font} -\unexpanded\def\font_helpers_set_current_font_alternative_size#alternative#size% \sla +\protected\def\font_helpers_set_current_font_alternative_size#alternative#size% \sla {\edef\fontalternative{#alternative}% \edef\fontsize {#size}% \font_helpers_check_big_math_synchronization % double? better in everymath? \font_helpers_synchronize_font} -\unexpanded\def\font_helpers_set_current_font_style_alternative_size#style#alternative#size% \rmsla +\protected\def\font_helpers_set_current_font_style_alternative_size#style#alternative#size% \rmsla {\edef\fontstyle {#style}% \edef\fontalternative{#alternative}% \edef\fontsize {#size}% \font_helpers_check_big_math_synchronization % double? better in everymath? \font_helpers_synchronize_font} -\unexpanded\def\font_helpers_synchronize_font % we can have dups i.e. no need to let fontstrategy +\protected\def\font_helpers_synchronize_font % we can have dups i.e. no need to let fontstrategy {\ifempty\fontclass \applyfontstrategies \else @@ -2071,7 +2039,9 @@ \let\fontalternative\fontalternative \font_helpers_synchronize_font} -\unexpanded\def\tx +% to freeze or not ... + +\protected\def\tx {\currentxfontsize\plusone \ifmmode \scriptstyle @@ -2082,7 +2052,7 @@ \fi \let\tx\txx} -\unexpanded\def\txx +\protected\def\txx {\currentxfontsize\plustwo \ifmmode \scriptscriptstyle @@ -2094,7 +2064,7 @@ \let\tx \empty \let\txx\empty} -\unexpanded\def\sx +\protected\def\sx {\currentxfontsize\plusone \ifmmode \scriptstyle @@ -2104,7 +2074,7 @@ \let\tx\txx \let\sx\sxx} -\unexpanded\def\sxx +\protected\def\sxx {\currentxfontsize\plustwo \ifmmode \scriptscriptstyle @@ -2116,8 +2086,8 @@ \let\sx \empty \let\sxx\empty} -\unexpanded\def\useinheritxsizes{\settrue \c_font_inherit_scale} % not yet public, playground for WS and me -\unexpanded\def\usedefinedxsizes{\setfalse\c_font_inherit_scale} % not yet public, playground for WS and me +\permanent\protected\def\useinheritxsizes{\settrue \c_font_inherit_scale} % not yet public, playground for WS and me +\permanent\protected\def\usedefinedxsizes{\setfalse\c_font_inherit_scale} % not yet public, playground for WS and me \let\normaltx \tx \let\normaltxx\txx @@ -2139,7 +2109,7 @@ \installcorenamespace{fontbodyfaces} -\unexpanded\def\font_basics_complete_switch#size% +\protected\def\font_basics_complete_switch#size% {\bodyfontsize#size\relax \normalizebodyfontsize\normalizedbodyfontsize\bodyfontsize \expandafter\let\expandafter\font_basics_set_faces\csname\??fontbodyfaces\fontbody\endcsname @@ -2205,7 +2175,7 @@ % \newtoks \everysetupbodyfont % \newtoks \everyswitchtobodyfont -\unexpanded\def\setupbodyfont +\permanent\protected\def\setupbodyfont {\doifelsenextoptionalcs\font_basics_setupbodyfont_yes\font_basics_setupbodyfont_nop} \def\font_basics_setupbodyfont_nop @@ -2225,7 +2195,7 @@ \fi \the\everysetupbodyfont}} -\unexpanded\def\font_basics_switchtobodyfont#specification% +\protected\def\font_basics_switchtobodyfont#specification% {\edef\m_font_step{\font_bodyfontvariable{#specification}}% \ifempty\m_font_step \font_helpers_set_font\zerocount{#specification}% @@ -2235,10 +2205,10 @@ \the\everybodyfont \the\everyswitchtobodyfont} -\unexpanded\def\switchtobodyfont[#specification]% could become an ifx +\permanent\protected\def\switchtobodyfont[#specification]% could become an ifx {\doifsomething{#specification}{\font_basics_switchtobodyfont{#specification}}} -\unexpanded\def\usebodyfontparameter#1% +\permanent\protected\def\usebodyfontparameter#1% {\edef\m_font_bodyfont_asked{#1\c!bodyfont}% \ifempty\m_font_bodyfont_asked\else \font_basics_switchtobodyfont\m_font_bodyfont_asked @@ -2251,7 +2221,7 @@ %D The following alternative is meant for math||to||text switching and will be %D optimized. -\unexpanded\def\fastswitchtobodyfont#name% +\permanent\protected\def\fastswitchtobodyfont#name% {\ifcsname\??fontenvironments\normalizedbodyfontsize#name\endcsname %\edef\futurebodyfontsize{\csname\??fontenvironments\normalizedbodyfontsize#name\endcsname}% \edef\futurebodyfontsize{\lastnamedcs}% @@ -2284,7 +2254,7 @@ %D \stoptext %D \stoptyping -\unexpanded\def\usebodyfont[#1]% +\permanent\protected\def\usebodyfont[#1]% {\ifempty\fontclass \setupbodyfont[#1]% \else @@ -2292,7 +2262,7 @@ \fullrestoreglobalbodyfont \fi} -\unexpanded\def\showbodyfontstate +\permanent\protected\def\showbodyfontstate {\dontleavehmode \start \infofont @@ -2320,9 +2290,9 @@ %D %D This is an expandable command! -\unexpanded\def\fontchar #character{\clf_fontchar{#character}} -\unexpanded\def\fontcharbyindex #index{\clf_fontcharbyindex#index\relax} - \def\tochar #specifications{\clf_tochar{#specifications}} % expanded (also used in edef) +\permanent\protected\def\fontchar #character{\clf_fontchar{#character}} +\permanent\protected\def\fontcharbyindex #index{\clf_fontcharbyindex#index\relax} +\permanent \def\tochar #specifications{\clf_tochar{#specifications}} % expanded (also used in edef) %D The next auxilliary macro is an alternative to \type {\fontname}. @@ -2340,7 +2310,7 @@ %D {\sl text \switchstyleonly[sansserif]text} %D \stoptyping -\unexpanded\def\switchstyleonly +\permanent\protected\def\switchstyleonly {\doifelsenextoptionalcs\font_basics_switch_style_only_opt\font_basics_switch_style_only_arg} \def\font_basics_switch_style_only_arg#name% stupid version @@ -2363,10 +2333,7 @@ %D %D We don't support language specific synonyms here. -\unexpanded\def\definebodyfontswitch - {\dodoubleargument\font_basics_define_bodyfont_switch} - -\def\font_basics_define_bodyfont_switch[#command][#specification]% no longer a commalist (not useful) +\permanent\tolerant\protected\def\definebodyfontswitch[#command]#spacer[#specification]% no longer a commalist (not useful) {\setvalue{#command}{\switchtobodyfont[#specification]}}% %D \macros @@ -2384,10 +2351,10 @@ \font_basics_switch_points\m_font_step \font_basics_switch_style \fontstyle} -\unexpanded\def\setsmallbodyfont{\font_helpers_set_bodyfont_step\v!small\the\everybodyfont} -\unexpanded\def\setbigbodyfont {\font_helpers_set_bodyfont_step\v!big \the\everybodyfont} +\permanent\protected\def\setsmallbodyfont{\font_helpers_set_bodyfont_step\v!small\the\everybodyfont} +\permanent\protected\def\setbigbodyfont {\font_helpers_set_bodyfont_step\v!big \the\everybodyfont} -\unexpanded\def\setmainbodyfont +\permanent\protected\def\setmainbodyfont {\font_basics_switch_points\normalizedbodyfontsize \font_basics_switch_style\fontstyle \the\everybodyfont @@ -2409,7 +2376,7 @@ \let\globalfontstyle\s!rm -\unexpanded\def\fullrestoreglobalbodyfont +\permanent\protected\def\fullrestoreglobalbodyfont {\let\fontsize\defaultfontsize \let\fontbody\defaultfontbody \let\fontface\defaultfontface @@ -2423,7 +2390,7 @@ \the\everyglobalbodyfont \saveinterlinespace} -\unexpanded\def\partialrestoreglobalbodyfont +\permanent\protected\def\partialrestoreglobalbodyfont {\let\fontsize\defaultfontsize \let\fontbody\defaultfontbody \let\fontface\defaultfontface @@ -2434,7 +2401,7 @@ \the\everyglobalbodyfont % indeed needed \saveinterlinespace} -\unexpanded\def\restoreglobalbodyfont % ook style etc +\permanent\protected\def\restoreglobalbodyfont % ook style etc {\ifx\fontclass\globalfontclass \ifx\fontstyle\globalfontstyle \ifx\normalizedbodyfontsize\normalizedglobalbodyfontsize @@ -2466,26 +2433,26 @@ \installcorenamespace{predefinedfont} -\unexpanded\def\predefinefont[#1]#2[#3]% global ! - {\setugvalue{#1}{\font_basics_predefine{#1}{#3}}} +\permanent\protected\def\predefinefont[#1]#*[#2]% global ! + {\setugvalue{#1}{\font_basics_predefine{#1}{#2}}} -\unexpanded\def\predefinedfont[#1]% global ! +\permanent\protected\def\predefinedfont[#1]% global ! {\ifcsname\??predefinedfont#1\endcsname \lastnamedcs \else \font_basics_predefined{#1}% \fi} -\unexpanded\def\font_basics_predefine#1#2% +\protected\def\font_basics_predefine#1#2% {\font_basics_defined_font_yes[#2]% \expandafter\glet\csname#1\expandafter\endcsname\csname\v_font_identifier_basic\endcsname} -\unexpanded\def\font_basics_predefined#1% +\protected\def\font_basics_predefined#1% {\font_basics_predefine{\??predefinedfont#1}{#1}} %D Handy helper: -\unexpanded\def\savedefinedfont[#1]% +\permanent\protected\def\savedefinedfont[#1]% {\bgroup \definedfont[#1]% \xdef\saveddefinedfontid {\number\fontid\font}% @@ -2497,8 +2464,8 @@ %D Ugly helper: -\unexpanded\def\saverunningstyleandcolor - {\unexpanded\edef\restorerunningstyleandcolor +\permanent\protected\def\saverunningstyleandcolor + {\enforced\permanent\protected\edef\restorerunningstyleandcolor {\setfontid \number\fontid\font \c_attr_colormodel \the\c_attr_colormodel \c_attr_color \the\c_attr_color @@ -2515,10 +2482,10 @@ \let\getprivatemathchar \clf_getprivatemathchar % gives back a utf ! \let\getprivateslot \clf_getprivateslot % companion to fonts.helpers.addprivate -% \unexpanded\def\getprivatemathchar#1% +% \protected\def\getprivatemathchar#1% % {\begingroup\the\textfont\zerocount\getprivatechar{#1}\endgroup} -\def\privatechar % the text variant gets expanded to utf +\permanent\protected\def\privatechar % the text variant gets expanded to utf {\ifmmode \expandafter\getprivatemathchar \else @@ -2546,10 +2513,7 @@ %D \stopTEXpage %D \stoptyping -\unexpanded\def\definefontcolorpalette - {\dodoubleargument\font_define_color_palette} - -\def\font_define_color_palette[#1][#2]% +\permanent\tolerant\protected\def\definefontcolorpalette[#1]#*[#2]% {\clf_definefontcolorpalette{#1}{#2}} %D \macros @@ -2557,7 +2521,7 @@ %D %D A way to add a path at runtime (no need to generate database): -\unexpanded\def\usefontpath[#1]% +\permanent\protected\def\usefontpath[#1]% {\clf_addfontpath{#1}} \protect \endinput diff --git a/tex/context/base/mkiv/font-mat.mklx b/tex/context/base/mkiv/font-mat.mklx index c37b36ed6..8ee5f4043 100644 --- a/tex/context/base/mkiv/font-mat.mklx +++ b/tex/context/base/mkiv/font-mat.mklx @@ -40,10 +40,10 @@ \newtoks \t_font_math_strategies \newconditional\c_font_synchronize_math_fonts \settrue\c_font_synchronize_math_fonts -\unexpanded\def\font_helpers_synchronize_math % math stuff in mmode +\protected\def\font_helpers_synchronize_math % math stuff in mmode {\ifconditional\c_font_synchronize_math_fonts\the\t_font_math_strategies\fi} -\unexpanded\def\textonly{\setfalse\c_font_synchronize_math_fonts} % document this +\permanent\protected\def\textonly{\setfalse\c_font_synchronize_math_fonts} % document this %D The main math font definer. We have removed some optimized code simply because we %D now always have a fontclass. We could check for fontclass being default or empty @@ -67,6 +67,8 @@ \newconditional\c_font_bidirectional_mathstrategy % can be default, not that much overhead: \settrue\c_font_bidirectional_mathstrategy \newconditional\c_font_complete_bold_mathstrategy \settrue\c_font_complete_bold_mathstrategy +% \frozen ... + \def\mathtextsuffix {-text} \def\mathscriptsuffix {-script} \def\mathscriptscriptsuffix{-scriptscript} @@ -343,7 +345,7 @@ \fam\defaultmathfamily % all characters and symbols are in this family \to \everymathematics -\unexpanded\def\font_helpers_synchronize_math_family_mr +\protected\def\font_helpers_synchronize_math_family_mr {\c_attr_mathfamily\ifconditional\c_font_bidirectional_mathstrategy \ifconditional\c_math_right_to_left \plustwo @@ -354,7 +356,7 @@ \zerocount \fi} -\unexpanded\def\font_helpers_synchronize_math_family_mb +\protected\def\font_helpers_synchronize_math_family_mb {\c_attr_mathfamily\ifconditional\c_font_bidirectional_mathstrategy \ifconditional\c_math_right_to_left \ifconditional\c_font_pseudo_bold_math_state\pluseight\else\plusfive\fi @@ -415,7 +417,7 @@ \newconditional\c_math_bold -\unexpanded\def\mr % math regular +\protected\def\mr % math regular {\ifmmode \font_helpers_synchronize_math_family_mr \else @@ -424,7 +426,7 @@ \mathdefault \setfalse\c_math_bold} -\unexpanded\def\mb % math bold +\protected\def\mb % math bold {\ifmmode \font_helpers_synchronize_math_family_mb \else @@ -462,13 +464,13 @@ \fi \to \everymathematics -\unexpanded\def\nobigmath {\synchronizebigmathflag\zerocount} -\unexpanded\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath} -\unexpanded\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath} +\protected\def\nobigmath {\synchronizebigmathflag\zerocount} +\protected\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath} +\protected\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath} \let\bigmathfontsize\empty -\unexpanded\def\synchronizebigmath +\protected\def\synchronizebigmath {\ifx\bigmathfontsize\fontsize % already in sync \else @@ -476,7 +478,7 @@ \font_helpers_synchronize_math \fi} -\unexpanded\def\font_helpers_check_big_math_synchronization +\protected\def\font_helpers_check_big_math_synchronization {\ifcase\synchronizebigmathflag % never \or diff --git a/tex/context/base/mkiv/font-nod.lua b/tex/context/base/mkiv/font-nod.lua index bf0aa3ba0..f3cd37f17 100644 --- a/tex/context/base/mkiv/font-nod.lua +++ b/tex/context/base/mkiv/font-nod.lua @@ -55,7 +55,7 @@ local disc_code = nodecodes.disc local glue_code = nodecodes.glue local kern_code = nodecodes.kern local dir_code = nodecodes.dir -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local getnext = nuts.getnext local getprev = nuts.getprev @@ -396,7 +396,7 @@ function step_tracers.codes(i,command,space) local char, id = isglyph(c) if char then showchar(char,id) - elseif id == dir_code or (id == localpar_code and start_of_par(c)) then + elseif id == dir_code or (id == par_code and start_of_par(c)) then context("[%s]",getdirection(c) or "?") elseif id == disc_code then local pre, post, replace = getdisc(c) diff --git a/tex/context/base/mkiv/font-ocm.lua b/tex/context/base/mkiv/font-ocm.lua index 131b0ed13..2f6c29e65 100644 --- a/tex/context/base/mkiv/font-ocm.lua +++ b/tex/context/base/mkiv/font-ocm.lua @@ -188,7 +188,7 @@ local initializeoverlay do n = n + 1 ; t[n] = "}" end token.set_macro("typethreemacro",concat(t)) - tex.runtoks("typethreetoks") + tex.runlocal("typethreetoks") registertypethreeresource(specification,c,tex.saveboxresource(0,nil,lpdf.collectedresources(),true)) -- registertypethreefont(specification,mainid,lpdf.reference(lpdf.getfontobjnumber(mainid))) return 0, 0 diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua index 490f28de6..bb13a4801 100644 --- a/tex/context/base/mkiv/font-ots.lua +++ b/tex/context/base/mkiv/font-ots.lua @@ -251,7 +251,7 @@ local glue_code = nodecodes.glue local disc_code = nodecodes.disc local math_code = nodecodes.math local dir_code = nodecodes.dir -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local lefttoright_code = nodes.dirvalues.lefttoright local righttoleft_code = nodes.dirvalues.righttoleft @@ -500,9 +500,23 @@ end -- in the not discfound branch then. We now have skiphash too so we can be more -- selective if needed (todo). +-- we can have more granularity here but for now we only do a simple check + +local no_left_ligature_code = 1 +local no_right_ligature_code = 2 +local no_left_kern_code = 4 +local no_right_kern_code = 8 + +local has_glyph_option = node.direct.has_glyph_option or function(n,c) + if c == no_left_ligature_code or c == no_right_ligature_code then + return getattr(n,a_noligature) == 1 + else + return false + end +end + local function toligature(head,start,stop,char,dataset,sequence,skiphash,discfound,hasmarks) -- brr head - if getattr(start,a_noligature) == 1 then - -- so we can do: e\noligature{ff}e e\noligature{f}fie (we only look at the first) + if has_glyph_option(start,no_right_ligature_code) then return head, start end if start == stop and getchar(start) == char then @@ -902,81 +916,89 @@ function handlers.gsub_ligature(head,start,dataset,sequence,ligature,rlmode,skip end function handlers.gpos_single(head,start,dataset,sequence,kerns,rlmode,skiphash,step,injection) - local startchar = getchar(start) - local format = step.format - if format == "single" or type(kerns) == "table" then -- the table check can go - local dx, dy, w, h = setposition(0,start,factor,rlmode,kerns,injection) - if trace_kerns then - logprocess("%s: shifting single %s by %s xy (%p,%p) and wh (%p,%p)",pref(dataset,sequence),gref(startchar),format,dx,dy,w,h) - end + if has_glyph_option(start,no_right_kern_code) then + return head, start, false else - local k = (format == "move" and setmove or setkern)(start,factor,rlmode,kerns,injection) - if trace_kerns then - logprocess("%s: shifting single %s by %s %p",pref(dataset,sequence),gref(startchar),format,k) + local startchar = getchar(start) + local format = step.format + if format == "single" or type(kerns) == "table" then -- the table check can go + local dx, dy, w, h = setposition(0,start,factor,rlmode,kerns,injection) + if trace_kerns then + logprocess("%s: shifting single %s by %s xy (%p,%p) and wh (%p,%p)",pref(dataset,sequence),gref(startchar),format,dx,dy,w,h) + end + else + local k = (format == "move" and setmove or setkern)(start,factor,rlmode,kerns,injection) + if trace_kerns then + logprocess("%s: shifting single %s by %s %p",pref(dataset,sequence),gref(startchar),format,k) + end end + return head, start, true end - return head, start, true end function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,skiphash,step,injection) - local snext = getnext(start) - if not snext then + if has_glyph_option(start,no_right_kern_code) then return head, start, false else - local prev = start - while snext do - local nextchar = ischar(snext,currentfont) - if nextchar then - if skiphash and skiphash[nextchar] then -- includes marks too when flag - prev = snext - snext = getnext(snext) - else - local krn = kerns[nextchar] - if not krn then - break - end - local format = step.format - if format == "pair" then - local a = krn[1] - local b = krn[2] - if a == true then - -- zero - elseif a then -- #a > 0 - local x, y, w, h = setposition(1,start,factor,rlmode,a,injection) - if trace_kerns then - local startchar = getchar(start) - logprocess("%s: shifting first of pair %s and %s by xy (%p,%p) and wh (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections") - end + local snext = getnext(start) + if not snext then + return head, start, false + else + local prev = start + while snext do + local nextchar = ischar(snext,currentfont) + if nextchar then + if skiphash and skiphash[nextchar] then -- includes marks too when flag + prev = snext + snext = getnext(snext) + else + local krn = kerns[nextchar] + if not krn then + break end - if b == true then - -- zero - start = snext -- cf spec - elseif b then -- #b > 0 - local x, y, w, h = setposition(2,snext,factor,rlmode,b,injection) + local format = step.format + if format == "pair" then + local a = krn[1] + local b = krn[2] + if a == true then + -- zero + elseif a then -- #a > 0 + local x, y, w, h = setposition(1,start,factor,rlmode,a,injection) + if trace_kerns then + local startchar = getchar(start) + logprocess("%s: shifting first of pair %s and %s by xy (%p,%p) and wh (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections") + end + end + if b == true then + -- zero + start = snext -- cf spec + elseif b then -- #b > 0 + local x, y, w, h = setposition(2,snext,factor,rlmode,b,injection) + if trace_kerns then + local startchar = getchar(start) + logprocess("%s: shifting second of pair %s and %s by xy (%p,%p) and wh (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections") + end + start = snext -- cf spec + elseif forcepairadvance then + start = snext -- for testing, not cf spec + end + return head, start, true + elseif krn ~= 0 then + local k = (format == "move" and setmove or setkern)(snext,factor,rlmode,krn,injection) if trace_kerns then - local startchar = getchar(start) - logprocess("%s: shifting second of pair %s and %s by xy (%p,%p) and wh (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections") + logprocess("%s: inserting %s %p between %s and %s as %s",pref(dataset,sequence),format,k,gref(getchar(prev)),gref(nextchar),injection or "injections") end - start = snext -- cf spec - elseif forcepairadvance then - start = snext -- for testing, not cf spec - end - return head, start, true - elseif krn ~= 0 then - local k = (format == "move" and setmove or setkern)(snext,factor,rlmode,krn,injection) - if trace_kerns then - logprocess("%s: inserting %s %p between %s and %s as %s",pref(dataset,sequence),format,k,gref(getchar(prev)),gref(nextchar),injection or "injections") + return head, start, true + else -- can't happen + break end - return head, start, true - else -- can't happen - break end + else + break end - else - break end + return head, start, false end - return head, start, false end end @@ -1505,92 +1527,96 @@ function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup end function chainprocs.gpos_single(head,start,stop,dataset,sequence,currentlookup,rlmode,skiphash,chainindex) - local mapping = currentlookup.mapping - if mapping == nil then - mapping = getmapping(dataset,sequence,currentlookup) - end - if mapping then - local startchar = getchar(start) - local kerns = mapping[startchar] - if kerns then - local format = currentlookup.format - if format == "single" then - local dx, dy, w, h = setposition(0,start,factor,rlmode,kerns) -- currentlookup.flags ? - if trace_kerns then - logprocess("%s: shifting single %s by %s (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),format,dx,dy,w,h) - end - else -- needs checking .. maybe no kerns format for single - local k = (format == "move" and setmove or setkern)(start,factor,rlmode,kerns,injection) - if trace_kerns then - logprocess("%s: shifting single %s by %s %p",cref(dataset,sequence),gref(startchar),format,k) + if has_glyph_option(start,no_right_kern_code) then + local mapping = currentlookup.mapping + if mapping == nil then + mapping = getmapping(dataset,sequence,currentlookup) + end + if mapping then + local startchar = getchar(start) + local kerns = mapping[startchar] + if kerns then + local format = currentlookup.format + if format == "single" then + local dx, dy, w, h = setposition(0,start,factor,rlmode,kerns) -- currentlookup.flags ? + if trace_kerns then + logprocess("%s: shifting single %s by %s (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),format,dx,dy,w,h) + end + else -- needs checking .. maybe no kerns format for single + local k = (format == "move" and setmove or setkern)(start,factor,rlmode,kerns,injection) + if trace_kerns then + logprocess("%s: shifting single %s by %s %p",cref(dataset,sequence),gref(startchar),format,k) + end end + return head, start, true end - return head, start, true end end return head, start, false end function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlmode,skiphash,chainindex) -- todo: injections ? - local mapping = currentlookup.mapping - if mapping == nil then - mapping = getmapping(dataset,sequence,currentlookup) - end - if mapping then - local snext = getnext(start) - if snext then - local startchar = getchar(start) - local kerns = mapping[startchar] -- always 1 step - if kerns then - local prev = start - while snext do - local nextchar = ischar(snext,currentfont) - if not nextchar then - break - end - if skiphash and skiphash[nextchar] then - prev = snext - snext = getnext(snext) - else - local krn = kerns[nextchar] - if not krn then + if has_glyph_option(start,no_right_kern_code) then + local mapping = currentlookup.mapping + if mapping == nil then + mapping = getmapping(dataset,sequence,currentlookup) + end + if mapping then + local snext = getnext(start) + if snext then + local startchar = getchar(start) + local kerns = mapping[startchar] -- always 1 step + if kerns then + local prev = start + while snext do + local nextchar = ischar(snext,currentfont) + if not nextchar then break end - local format = currentlookup.format - if format == "pair" then - local a = krn[1] - local b = krn[2] - if a == true then - -- zero - elseif a then - local x, y, w, h = setposition(1,start,factor,rlmode,a,"injections") -- currentlookups flags? - if trace_kerns then - local startchar = getchar(start) - logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h) - end + if skiphash and skiphash[nextchar] then + prev = snext + snext = getnext(snext) + else + local krn = kerns[nextchar] + if not krn then + break end - if b == true then - -- zero - start = snext -- cf spec - elseif b then -- #b > 0 - local x, y, w, h = setposition(2,snext,factor,rlmode,b,"injections") + local format = currentlookup.format + if format == "pair" then + local a = krn[1] + local b = krn[2] + if a == true then + -- zero + elseif a then + local x, y, w, h = setposition(1,start,factor,rlmode,a,"injections") -- currentlookups flags? + if trace_kerns then + local startchar = getchar(start) + logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h) + end + end + if b == true then + -- zero + start = snext -- cf spec + elseif b then -- #b > 0 + local x, y, w, h = setposition(2,snext,factor,rlmode,b,"injections") + if trace_kerns then + local startchar = getchar(start) + logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h) + end + start = snext -- cf spec + elseif forcepairadvance then + start = snext -- for testing, not cf spec + end + return head, start, true + elseif krn ~= 0 then + local k = (format == "move" and setmove or setkern)(snext,factor,rlmode,krn) if trace_kerns then - local startchar = getchar(start) - logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h) + logprocess("%s: inserting %s %p between %s and %s",cref(dataset,sequence),format,k,gref(getchar(prev)),gref(nextchar)) end - start = snext -- cf spec - elseif forcepairadvance then - start = snext -- for testing, not cf spec - end - return head, start, true - elseif krn ~= 0 then - local k = (format == "move" and setmove or setkern)(snext,factor,rlmode,krn) - if trace_kerns then - logprocess("%s: inserting %s %p between %s and %s",cref(dataset,sequence),format,k,gref(getchar(prev)),gref(nextchar)) + return head, start, true + else + break end - return head, start, true - else - break end end end @@ -3759,7 +3785,7 @@ do local initialrl = 0 - if getid(head) == localpar_code and start_of_par(head) then + if getid(head) == par_code and start_of_par(head) then initialrl = pardirstate(head) elseif direction == righttoleft_code then initialrl = -1 @@ -3913,7 +3939,7 @@ do elseif id == dir_code then topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode) start = getnext(start) - -- elseif id == localpar_code and start_of_par(start) then + -- elseif id == par_code and start_of_par(start) then -- rlparmode, rlmode = pardirstate(start) -- start = getnext(start) else @@ -3997,7 +4023,7 @@ do elseif id == dir_code then topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode) start = getnext(start) - -- elseif id == localpar_code and start_of_par(start) then + -- elseif id == par_code and start_of_par(start) then -- rlparmode, rlmode = pardirstate(start) -- start = getnext(start) else @@ -4108,7 +4134,7 @@ do elseif id == dir_code then topstack, rlmode = txtdirstate(start,dirstack,topstack,rlparmode) start = getnext(start) - -- elseif id == localpar_code and start_of_par(start) then + -- elseif id == par_code and start_of_par(start) then -- rlparmode, rlmode = pardirstate(start) -- start = getnext(start) else diff --git a/tex/context/base/mkiv/font-pre.mkiv b/tex/context/base/mkiv/font-pre.mkiv index 749c66fe7..19d4f3f7e 100644 --- a/tex/context/base/mkiv/font-pre.mkiv +++ b/tex/context/base/mkiv/font-pre.mkiv @@ -931,10 +931,14 @@ \unexpanded\def\normalss{\font_helpers_set_current_font_style{\s!ss}} \unexpanded\def\normaltt{\font_helpers_set_current_font_style{\s!tt}} +\pushoverloadmode + \let\rm\normalrm \let\ss\normalss \let\tt\normaltt +\popoverloadmode + \protect \endinput % LM math vs CM math (analysis by Taco): diff --git a/tex/context/base/mkiv/font-sol.lua b/tex/context/base/mkiv/font-sol.lua index 643080788..c61873995 100644 --- a/tex/context/base/mkiv/font-sol.lua +++ b/tex/context/base/mkiv/font-sol.lua @@ -105,7 +105,7 @@ local disc_code = nodecodes.disc local kern_code = nodecodes.kern local hlist_code = nodecodes.hlist local dir_code = nodecodes.dir -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local whatsit_code = nodecodes.whatsit @@ -437,7 +437,7 @@ function splitters.split(head) -- best also pass the direction end local direction, pop = getdirection(current) r2l = not pop and direction == righttoleft_code - elseif id == localpar_code and start_of_par(current) then + elseif id == par_code and start_of_par(current) then if start then flush() -- very unlikely as this starts a paragraph end diff --git a/tex/context/base/mkiv/font-sty.mklx b/tex/context/base/mkiv/font-sty.mklx index f0fe65183..457217f8d 100644 --- a/tex/context/base/mkiv/font-sty.mklx +++ b/tex/context/base/mkiv/font-sty.mklx @@ -48,13 +48,10 @@ \setnewconstant \c_font_current_alternative_style_index \plusone -\unexpanded\def\definealternativestyle - {\dotripleempty\font_basics_define_alternative_style} - -\def\font_basics_define_alternative_style[#commands][#variantone][#varianttwo]% +\permanent\tolerant\protected\def\definealternativestyle[#commands]#spacer[#variantone]#spacer[#varianttwo]% {\processcommalist[#commands]{\font_basics_define_alternative_style_indeed{#variantone}{#varianttwo}}} -\let\definestyle\definealternativestyle % later redefined +% \let\definestyle\definealternativestyle % later redefined \newconstant\c_fonts_basics_alternative_style_method @@ -66,7 +63,7 @@ \ifthirdargument \setuevalue{#command}{\triggergroupedcommandcs\begincsname\??alternativestyle#command\endcsname}% \else - \setuvalue{#command}{\triggergroupedcommand{#variantone}}% + \setuvalue{#command}{\triggergroupedcommand{#variantone}}% \fi \else \setuvalue{#command}{\triggergroupedcommand{#variantone}}% @@ -83,7 +80,7 @@ \expandafter\firstoftwoarguments \fi} -\def\applyalternativestyle#name% public +\permanent\def\applyalternativestyle#name% public .. expandable? frozen? {\begincsname\??alternativestyle#name\endcsname} \appendtoks @@ -146,7 +143,7 @@ \let\m_current_convert_font \empty \let\m_current_convert_font_dt\empty -\unexpanded\def\doconvertfont#specification% takes second argument / this command is obsolete +\permanent\protected\def\doconvertfont#specification% takes second argument / this command is obsolete {\edef\m_current_convert_font{#specification}% \ifempty\m_current_convert_font %\expandafter\firstofoneargument @@ -174,30 +171,33 @@ %D \chapter{This is \TEX} %D \stoptyping -\unexpanded\def\dontconvertfont{\c_font_current_alternative_style_index\plustwo} % needs checking in usage -\unexpanded\def\redoconvertfont{\c_font_current_alternative_style_index\plusone} % needs checking in usage +\permanent\protected\def\dontconvertfont{\c_font_current_alternative_style_index\plustwo} % needs checking in usage +\permanent\protected\def\redoconvertfont{\c_font_current_alternative_style_index\plusone} % needs checking in usage %D The new one: \setfalse\fontattributeisset -\unexpanded\def\dousestyleparameter#value% +\let\currentstyleparameter \empty % these might become private (possible conflict with defines) +\let\currentdetokenizedstyleparameter\empty % these might become private (possible conflict with defines) + +\permanent\protected\def\dousestyleparameter#value% {\edef\currentstyleparameter{#value}% \ifempty\currentstyleparameter\else \expandafter\dousecurrentstyleparameter \fi} -\unexpanded\def\dousestylehashparameter#hash#parameter% +\permanent\protected\def\dousestylehashparameter#hash#parameter% {\ifcsname#hash#parameter\endcsname \expandafter\dousestyleparameter\lastnamedcs \fi} -\unexpanded\def\dousecurrentstyleparameter % empty check outside here - {\edef\detokenizedstyleparameter{\detokenize\expandafter{\currentstyleparameter}}% +\permanent\protected\def\dousecurrentstyleparameter % empty check outside here + {\edef\currentdetokenizedstyleparameter{\detokenize\expandafter{\currentstyleparameter}}% \settrue\fontattributeisset % reset is done elsewhere - \ifcsname\??alternativestyle\detokenizedstyleparameter\endcsname + \ifcsname\??alternativestyle\currentdetokenizedstyleparameter\endcsname \lastnamedcs - \orelse\ifcsname\detokenizedstyleparameter\endcsname + \orelse\ifcsname\currentdetokenizedstyleparameter\endcsname \lastnamedcs \else \currentstyleparameter @@ -241,24 +241,24 @@ \fi \to \everydefinestyle -\unexpanded\def\font_styles_apply_start#name% +\protected\def\font_styles_apply_start#name% {\begingroup \font_styles_use_defined{#name}} -\unexpanded\def\font_styles_apply_stop +\protected\def\font_styles_apply_stop {\endgroup} -\unexpanded\def\font_styles_apply_grouped#name% assumes that the next is { or \bgroup +\protected\def\font_styles_apply_grouped#name% assumes that the next is { or \bgroup {\bgroup \def\g_style{\font_styles_use_defined{#name}}% \afterassignment\g_style \let\nexttoken} -\unexpanded\def\font_styles_use_defined#name% +\protected\def\font_styles_use_defined#name% {\edef\currentstyle{#name}% \usestylestyleandcolor\c!style\c!color} -\unexpanded\def\font_styles_use_generic#specification% +\protected\def\font_styles_use_generic#specification% {\let\currentstyle\s!unknown % reasonable generic tag \letstyleparameter\c!style\empty \letstyleparameter\c!color\empty @@ -269,7 +269,7 @@ \installcorenamespace{styleargument} -\unexpanded\def\style[#name]% as this is can be a switch we use groupedcommand +\protected\def\style[#name]% as this is can be a switch we use groupedcommand % frozen? {\csname\??styleargument \ifcsname\??stylecheck#name\endcsname 2% defined as style @@ -282,15 +282,9 @@ \fi \endcsname{#name}} -% \setvalue{\??styleargument1}#name% -% {\groupedcommand{\begincsname#name\endcsname}{}} - \setvalue{\??styleargument1}#name% {\expandafter\triggergroupedcommandcs\begincsname#name\endcsname} -% \setvalue{\??styleargument2}#name% -% {\groupedcommand{\font_styles_use_defined{#name}}{}} % or {\font_styles_apply_grouped{#name}} - \setvalue{\??styleargument2}#name% {\triggergroupedcommand{\font_styles_use_defined{#name}}} % or {\font_styles_apply_grouped{#name}} @@ -313,7 +307,7 @@ \installcorenamespace{styleenvironment} -\unexpanded\def\startstyle[#name]% +\protected\def\startstyle[#name]% {\begingroup \csname\??styleenvironment \ifcsname\??stylecheck#name\endcsname @@ -325,7 +319,7 @@ \fi \endcsname{#name}} -\unexpanded\def\stopstyle +\protected\def\stopstyle {\endgroup \autoinsertnextspace} % will be configurable, maybe also in \definestartstop @@ -355,11 +349,8 @@ \installcorenamespace{stylecollection} -\unexpanded\def\definestylecollection - {\dosingleargument\font_styles_define_style_collection} - -\def\font_styles_define_style_collection[#name]% - {\iffirstargument +\permanent\tolerant\protected\def\definestylecollection[#name]% + {\ifarguments\or \setuvalue{#name}{\styleinstance[#name]}% \def\font_styles_define_style_collection_a#style% {\def\font_styles_define_style_collection_b#alternative{\undefinevalue{\??stylecollection#name:#style:#alternative}}% @@ -372,29 +363,19 @@ \let\font_styles_define_style_collection_a\relax \let\font_styles_define_style_collection_b\relax -\unexpanded\def\definestyleinstance - {\doquadrupleargument\font_styles_define_style_instance} - -\def\font_styles_define_style_instance[#instance][#2][#3][#4]% [name] [rm|ss|tt|..] [sl|bf|...] [whatever] - {\iffirstargument +\permanent\tolerant\protected\def\definestyleinstance[#instance]#*[#2]#*[#3]#*[#4]% [name] [rm|ss|tt|..] [sl|bf|...] [whatever] + {\ifparameter#instance\or + \ifarguments\or\or + \letvalueempty{\??stylecollection#instance::#2}% + \or + \setvalue{\??stylecollection#instance::#2}{#3}% + \or + \setvalue{\??stylecollection#instance:#2:#3}{#4}% + \fi \ifcsname#instance\endcsname\else\font_styles_define_style_collection[#instance]\fi - \fi - \iffourthargument - \setvalue{\??stylecollection#instance:#2:#3}{#4}% - \orelse\ifthirdargument - \setvalue{\??stylecollection#instance::#2}{#3}% - \orelse\ifsecondargument - \letvalueempty{\??stylecollection#instance::#2}% - \fi} - -% \unexpanded\def\styleinstance[#instance]% will be made faster -% {%\begingroup\normalexpanded{\noexpand\infofont[#1:\fontstyle:\fontalternative]}\endgroup -% \executeifdefined{\??stylecollection#instance:\fontstyle:\fontalternative}% -% {\executeifdefined{\??stylecollection#instance:\fontstyle:\s!default}% -% {\executeifdefined{\??stylecollection#instance::\fontalternative} -% {\getvalue {\??stylecollection#instance::\s!default}}}}} + \fi} -\unexpanded\def\styleinstance[#instance]% maybe \lastnamedcs here too +\permanent\protected\def\styleinstance[#instance]% maybe \lastnamedcs here too {\csname\??stylecollection#instance:% \ifcsname\??stylecollection#instance:\fontstyle:\fontalternative\endcsname \fontstyle:\fontalternative @@ -414,20 +395,20 @@ %D \mathematics {\utfchar{0x2229}\vsone{}} %D \stoptyping -\unexpanded\edef\vsone#character{#character\normalUchar"FE00 } % used -\unexpanded\edef\vstwo#character{#character\normalUchar"FE01 } % not used but handy for testing +\permanent\protected\edef\vsone#character{#character\normalUchar"FE00 } % used +\permanent\protected\edef\vstwo#character{#character\normalUchar"FE01 } % not used but handy for testing %D For historic reasons we keep the following around but they are no longer that -%D relevant for \MKIV. +%D relevant for \MKIV. But \unknown\ they will be dropped in \LMTX ! -\unexpanded\def\doattributes#1#2#3#4% +\permanent\protected\def\doattributes#1#2#3#4% {\begingroup % geen \bgroup, anders in mathmode lege \hbox \dousestylehashparameter{#1}{#2}% \dousecolorhashparameter{#1}{#3}% #4% \endgroup} -\unexpanded\def\dostartattributes#1#2#3% +\permanent\protected\def\dostartattributes#1#2#3% {\begingroup % geen \bgroup, anders in mathmode lege \hbox \dousestylehashparameter{#1}{#2}% \dousecolorhashparameter{#1}{#3}} @@ -438,16 +419,16 @@ \newconditional\c_font_styles_math -\unexpanded\def\font_styles_math_reset +\protected\def\font_styles_math_reset {\setfalse\c_font_styles_math} -\unexpanded\def\font_styles_math_start +\protected\def\font_styles_math_start {\ifconditional\c_font_styles_math \startimath \fi \relax} -\unexpanded\def\font_styles_math_stop +\protected\def\font_styles_math_stop {\relax \ifconditional\c_font_styles_math \stopimath diff --git a/tex/context/base/mkiv/font-sty.mkvi b/tex/context/base/mkiv/font-sty.mkvi index a24194355..519381a2e 100644 --- a/tex/context/base/mkiv/font-sty.mkvi +++ b/tex/context/base/mkiv/font-sty.mkvi @@ -181,6 +181,9 @@ \setfalse\fontattributeisset +\let\currentstyleparameter \empty % these might become private +\let\currentdetokenizedstyleparameter\empty % these might become private + \unexpanded\def\dousestyleparameter#value% {\edef\currentstyleparameter{#value}% \ifx\currentstyleparameter\empty\else @@ -193,11 +196,11 @@ \fi} \unexpanded\def\dousecurrentstyleparameter % empty check outside here - {\edef\detokenizedstyleparameter{\detokenize\expandafter{\currentstyleparameter}}% + {\edef\currentdetokenizedstyleparameter{\detokenize\expandafter{\currentstyleparameter}}% \settrue\fontattributeisset % reset is done elsewhere - \ifcsname\??alternativestyle\detokenizedstyleparameter\endcsname + \ifcsname\??alternativestyle\currentdetokenizedstyleparameter\endcsname \lastnamedcs - \else\ifcsname\detokenizedstyleparameter\endcsname + \else\ifcsname\currentdetokenizedstyleparameter\endcsname \lastnamedcs \else \currentstyleparameter diff --git a/tex/context/base/mkiv/font-sym.mklx b/tex/context/base/mkiv/font-sym.mklx index 33f8a62da..db80572e8 100644 --- a/tex/context/base/mkiv/font-sym.mklx +++ b/tex/context/base/mkiv/font-sym.mklx @@ -82,7 +82,9 @@ %D The next macro is used to map non latin fontnames on fonts. See \type %D {font-uni} for an example of its use. -\def\fontstylesuffix% why the \s!Regular ? see \getglyph +% \frozen ... + +\permanent\def\fontstylesuffix% why the \s!Regular ? see \getglyph {\ifx\fontalternative\s!tf \s!Regular \orelse \ifx\fontalternative\s!bf \s!Bold \orelse \ifx\fontalternative\s!sl \s!Slanted \orelse @@ -92,7 +94,7 @@ \ifx\fontalternative\s!sc \s!Caps \else \s!Regular \fi} -\def\glyphfontfile#base% appends +\permanent\def\glyphfontfile#base% appends {#base% \ifcsname\??fontfile#base\v_font_string_a\v_font_string_c\endcsname \v_font_string_a\v_font_string_c @@ -108,7 +110,7 @@ %D The next macro can be used to make decisions based on the shape: -\def\doifelseitalic#yes#nop% +\permanent\def\doifelseitalic#yes#nop% {\ifx\fontalternative\s!sl#yes\orelse \ifx\fontalternative\s!it#yes\orelse \ifx\fontalternative\s!bs#yes\orelse @@ -129,7 +131,7 @@ \let\thedefinedfont\relax -\def\setscaledstyledsymbolicfont#1#2#3% quite a slowdown, glyphfontfile +\permanent\protected\def\setscaledstyledsymbolicfont#1#2#3% quite a slowdown, glyphfontfile {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#3}} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}% \ifcsname\??symbolfont\askedsymbolfont\endcsname \lastnamedcs @@ -137,7 +139,7 @@ \font_basics_define_symbolic_font \fi} -\def\setscaleddirectsymbolicfont#1#2#3% quite a slowdown, glyphfontfile +\permanent\protected\def\setscaleddirectsymbolicfont#1#2#3% quite a slowdown, glyphfontfile {\edef\askedsymbolfont{\truefontname{#3} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}% \ifcsname\??symbolfont\askedsymbolfont\endcsname \lastnamedcs @@ -145,7 +147,7 @@ \font_basics_define_symbolic_font \fi} -\def\setstyledsymbolicfont#fontname% quite a slowdown, glyphfontfile +\permanent\protected\def\setstyledsymbolicfont#fontname% quite a slowdown, glyphfontfile {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#fontname}} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}% \ifcsname\??symbolfont\askedsymbolfont\endcsname \lastnamedcs @@ -153,7 +155,7 @@ \font_basics_define_symbolic_font \fi} -\def\setdirectsymbolicfont#fontname% +\permanent\protected\def\setdirectsymbolicfont#fontname% {\edef\askedsymbolfont{\truefontname{#fontname} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}% \ifcsname\??symbolfont\askedsymbolfont\endcsname \lastnamedcs @@ -166,16 +168,16 @@ \currentsymbolfont \expandafter\glet\csname\??symbolfont\askedsymbolfont\endcsname\lastrawfontcall} -\unexpanded\def\getnamedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_fontchar{#character}}} -\unexpanded\def\getnamedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_fontchar{#character}}} -\unexpanded\def\getglyphstyled #fontname#character{{\setstyledsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}} -\unexpanded\def\getglyphdirect #fontname#character{{\setdirectsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}} -\unexpanded\def\resolvedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_tochar{#character}}} -\unexpanded\def\resolvedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_tochar{#character}}} +\permanent\protected\def\getnamedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_fontchar{#character}}} +\permanent\protected\def\getnamedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_fontchar{#character}}} +\permanent\protected\def\getglyphstyled #fontname#character{{\setstyledsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}} +\permanent\protected\def\getglyphdirect #fontname#character{{\setdirectsymbolicfont{#fontname}\doifelsenumber{#character}\char\donothing#character}} +\permanent\protected\def\resolvedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\clf_tochar{#character}}} +\permanent\protected\def\resolvedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\clf_tochar{#character}}} % this one is wrong: -\unexpanded\def\getscaledglyph#scale#name#content% +\permanent\protected\def\getscaledglyph#scale#name#content% {{\setscaledstyledsymbolicfont\fontbody{#scale}{#name}\doifelsenumber{#content}\char\donothing#content}} \let\getglyph \getglyphstyled % old @@ -183,8 +185,7 @@ \let\symbolicsizedfont\setscaledstyledsymbolicfont % old \let\symbolicfont \setstyledsymbolicfont % old -\unexpanded\def\symbolicscaledfont{\setsscaledstyledsymbolicfont\fontbody} -\unexpanded\def\symbolicscaledfont{\setscaledstyledsymbolicfont\fontbody} +\permanent\protected\def\symbolicscaledfont{\setscaledstyledsymbolicfont\fontbody} %D The last implementation of \type {\getglyph} permits definitions like: %D @@ -215,7 +216,7 @@ %D Every now and then we want to define a font directly, for instance when we %D typeset title pages. The next macro saves some typing: -\unexpanded\def\setfont% geen \font_helpers_set_font mogelijk +\permanent\protected\def\setfont% geen \font_helpers_set_font mogelijk {\afterassignment\font_basics_set_font\font\nextfont=} \def\font_basics_set_font @@ -231,7 +232,7 @@ %D \macros{doiffontcharelse} -\unexpanded\def\doifelsefontchar#specification#unicode% this could be a direct lua call +\permanent\protected\def\doifelsefontchar#specification#unicode% this could be a direct lua call {\begingroup \font_basics_define_font_without_parameters{thedefinedfont}{#specification}% \iffontchar\font#unicode\relax @@ -240,6 +241,6 @@ \endgroup\expandafter\secondoftwoarguments \fi} -\let\doiffontcharelse\doifelsefontchar +\aliased\let\doiffontcharelse\doifelsefontchar \protect \endinput diff --git a/tex/context/base/mkiv/font-tra.mkiv b/tex/context/base/mkiv/font-tra.mkiv index 7d02cd140..99c7ab3c8 100644 --- a/tex/context/base/mkiv/font-tra.mkiv +++ b/tex/context/base/mkiv/font-tra.mkiv @@ -357,7 +357,7 @@ % new -\unexpanded\def\savefont[#1]% not yet in i-*.xml +\unexpanded\def\savefontdata[#1]% not yet in i-*.xml {\begingroup \getdummyparameters[#1]% \clf_savefont { diff --git a/tex/context/base/mkiv/grph-epd.lua b/tex/context/base/mkiv/grph-epd.lua index f8fa62953..0993270f1 100644 --- a/tex/context/base/mkiv/grph-epd.lua +++ b/tex/context/base/mkiv/grph-epd.lua @@ -40,7 +40,7 @@ local function mergegoodies(optionlist) end function figures.mergegoodies(optionlist) - -- todo: we can use runtoks instead + -- todo: we can use runlocal instead context.stepwise(function() -- we use stepwise because we might need to define symbols -- for stamps that have no default appearance diff --git a/tex/context/base/mkiv/grph-fig.mkiv b/tex/context/base/mkiv/grph-fig.mkiv index 3bf3248a6..c196d1420 100644 --- a/tex/context/base/mkiv/grph-fig.mkiv +++ b/tex/context/base/mkiv/grph-fig.mkiv @@ -256,6 +256,9 @@ \tpack{\vskip12\points\box2\vskip6\points}}% \endgroup} +\definesystemconstant {vwa} +\definesystemconstant {vwb} + \unexpanded\def\grph_steps_three_referring(#1,#2)#3(#4,#5)#6[#7]% {\advance\c_grph_steps_reference\plusone \position(#1,#2) diff --git a/tex/context/base/mkiv/grph-pat.mkxl b/tex/context/base/mkiv/grph-pat.mkxl new file mode 100644 index 000000000..df30258bc --- /dev/null +++ b/tex/context/base/mkiv/grph-pat.mkxl @@ -0,0 +1,119 @@ +%D \module +%D [ file=grph-par, +%D version=2016.07.08, +%D title=\CONTEXT\ Graphic Macros, +%D subtitle=Patterns, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This works ok in Okular and MuPDF but somehow xforms don't work in Acrobat +%D (full nor reader). Also the basic offset is kind of unspecified. So \unknown\ +%D we're dealing with a fragile feature. So, don't rely on where the first (ulr) +%D tile occurs. +%D +%D The two commands introduced here are not documented (yet). + +\writestatus{loading}{ConTeXt Graphic Macros / Patterns} + +\unprotect + +\registerctxluafile{grph-pat}{} + +\permanent\tolerant\protected\def\registerpattern[#1]#*[#2]% + {\begingroup + \letdummyparameter\c!name \s!dummy + \letdummyparameter\c!width \v!auto + \letdummyparameter\c!height \v!auto + \letdummyparameter\c!hoffset\zeropoint + \letdummyparameter\c!voffset\zeropoint + \unless\iftok{#2}\emptytoks + \setdummyparameter\c!name{#1}% + \getdummyparameters[#2]% + \orelse\ifhastok={#1}% + \getdummyparameters[#1]% + \else + \setdummyparameter\c!name{#1}% + \fi + \dowithnextboxcs\syst_boxes_registerpattern_indeed\hbox} + +\immutable\edef\v!auto_m{-\v!auto} + +\def\syst_boxes_registerpattern_indeed + {%\finalizeobjectbox\nextbox + \edef\p_width {\dummyparameter\c!width}% + \edef\p_height {\dummyparameter\c!height}% + \edef\p_hoffset{\dummyparameter\c!hoffset}% + \edef\p_voffset{\dummyparameter\c!voffset}% + \scratchwidth \dimexpr\ifx\p_width \v!auto\wd \nextbox \else\p_width \fi\relax + \scratchheight \dimexpr\ifx\p_height \v!auto\htdp\nextbox \else\p_height \fi\relax + \scratchhoffset\dimexpr\ifx\p_hoffset\v!auto\scratchwidth /2\else\ifx\p_hoffset\v!auto_m-\scratchwidth /2\else\p_hoffset\fi\fi\relax + \scratchvoffset\dimexpr\ifx\p_voffset\v!auto\scratchheight/2\else\ifx\p_voffset\v!auto_m-\scratchheight/2\else\p_voffset\fi\fi\relax + \clf_registerpattern + name {\dummyparameter\c!name} + number \nextbox + width \scratchwidth + height \scratchheight + hoffset \scratchhoffset + voffset \scratchvoffset + \relax + \endgroup} + +\permanent\tolerant\protected\def\applypattern[#1]#*[#2]% + {\hbox\bgroup + \letdummyparameter\c!name \s!dummy + \letdummyparameter\c!width \zeropoint + \letdummyparameter\c!height\zeropoint + \unless\iftok{#2}\emptytoks + \setdummyparameter\c!name{#1}% + \getdummyparameters[#2]% + \orelse\ifhastok={#1}% + \getdummyparameters[#1]% + \else + \setdummyparameter\c!name{#1}% + \fi + \clf_applypattern + name {\dummyparameter\c!name} + number \nextbox + width \dimexpr\dummyparameter\c!width\relax + height \dimexpr\dummyparameter\c!height\relax + \relax + \box\nextbox + \egroup} + +\protect + +\continueifinputfile{grph-pat.mkxl} + +\nopdfcompression + +\starttext + + \registerpattern[demo]{It \darkred Works!} + + \framed[offset=overlay]{\applypattern[demo][width=7cm,height=4cm]} + + \blank + + \registerpattern[name=more,hoffset=0bp,voffset=0pt]{\externalfigure[cow.pdf][width=1cm]} + + \framed[offset=overlay]{\applypattern[name=more,width=7cm,height=4cm]} + + \blank + + \registerpattern[name=more,hoffset=auto,voffset=auto]{\externalfigure[cow.pdf][width=1cm]} + + \framed[offset=overlay]{\applypattern[name=more,width=7cm,height=4cm]} + + \blank + + \registerpattern[name=more,hoffset=-auto,voffset=-auto]{\externalfigure[cow.pdf][width=1cm]} + + \framed[offset=overlay]{\applypattern[name=more,width=7cm,height=4cm]} + +\stoptext + diff --git a/tex/context/base/mkiv/grph-trf.mkiv b/tex/context/base/mkiv/grph-trf.mkiv index d6a6acd78..d1be7e1d7 100644 --- a/tex/context/base/mkiv/grph-trf.mkiv +++ b/tex/context/base/mkiv/grph-trf.mkiv @@ -234,11 +234,20 @@ {\ifdim\p_sx\onepoint=\onepoint\else\edef\p_width {\the\dimexpr\p_sx\d_grph_scale_wd}\fi \ifdim\p_sy\onepoint=\onepoint\else\edef\p_height{\the\dimexpr\p_sy\d_grph_scale_ht}\fi} -\def\grph_scale_rounded#1% - {\expandafter\expandafter\expandafter\grph_scale_rounded_indeed - \expandafter\WITHOUTPT\the\dimexpr#1\points*100+32768\scaledpoint\relax.\relax} +\ifcase\contextlmtxmode -\def\grph_scale_rounded_indeed#1.#2\relax{#1} + \def\grph_scale_rounded#1% + {\expandafter\expandafter\expandafter\grph_scale_rounded_indeed + \expandafter\WITHOUTPT\the\dimexpr#1\points*100+32768\scaledpoint\relax.\relax} + + \def\grph_scale_rounded_indeed#1.#2\relax{#1} + +\else + + \def\grph_scale_rounded#1% + {\thewithoutunit\dimexpr#1\points*100+32768\scaledpoint\relax} + +\fi \def\grph_scale_calculations_nop {\settrue\c_grph_scale_done diff --git a/tex/context/base/mkiv/hand-ini.mkxl b/tex/context/base/mkiv/hand-ini.mkxl index 9c291fed8..3fd82f239 100644 --- a/tex/context/base/mkiv/hand-ini.mkxl +++ b/tex/context/base/mkiv/hand-ini.mkxl @@ -37,26 +37,27 @@ \unprotect -%D New stuff. +%D Probbaly not yet used by many. -\unexpanded\def\setupfontexpansion {\dodoubleargument\font_expansion_setup } -\unexpanded\def\setupfontprotrusion{\dodoubleargument\font_protrusion_setup} - -\def\font_expansion_setup [#1][#2]{\clf_setupfontexpansion {#1}{#2}} -\def\font_protrusion_setup[#1][#2]{\clf_setupfontprotrusion{#1}{#2}} +\permanent\tolerant\protected\def\setupfontexpansion [#1]#*[#2]{\clf_setupfontexpansion {#1}{#2}} +\permanent\tolerant\protected\def\setupfontprotrusion[#1]#*[#2]{\clf_setupfontprotrusion{#1}{#2}} % \setupfontprotrusion[quality-upright][vector=quality] % \setupfontprotrusion[quality-slanted][vector=quality,right=1.5] -\let\adjustspacing\relax \newcount\adjustspacing % a little bit protection -\let\protrudechars\relax \newcount\protrudechars % a little bit protection +\pushoverloadmode + + \let\adjustspacing\relax \newcount\adjustspacing % a little bit protection + \let\protrudechars\relax \newcount\protrudechars % a little bit protection -% at some point we can introduce extreme expansion, i.e. \normaladjustspacing\plustwo +\popoverloadmode + +%D At some point we can introduce extreme expansion, i.e. \type {\normaladjustspacing\plustwo}. % 0 = disabled -% 1 = notused (thesis) +% 1 = notused (thesis) % 2 = glyph + kern -% 3 = glyph only +% 3 = glyph only (default) \def\font_expansion_enable {\normaladjustspacing\plusthree} \def\font_expansion_enable_k{\normaladjustspacing\plustwo} @@ -74,9 +75,9 @@ % % \let\fonthandling\empty % -% \unexpanded\def\startfonthandling #1{\fonthandlingerror\fonthandlingerror\gobbleuntil\stopfonthandling} % can't happen -% \unexpanded\def\definefonthandling {\dotripleempty\dodefinefonthandling} -% \unexpanded\def\setupfonthandling {\dodoubleempty\dosetupfonthandling } +% \protected\def\startfonthandling #1{\fonthandlingerror\fonthandlingerror\gobbleuntil\stopfonthandling} % can't happen +% \protected\def\definefonthandling {\dotripleempty\dodefinefonthandling} +% \protected\def\setupfonthandling {\dodoubleempty\dosetupfonthandling } % \def\dodefinefonthandling[#1][#2][#3]{\fonthandlingerror} % \def\dosetupfonthandling [#1][#2]{\fonthandlingerror} % \def\usehandling [#1]{\fonthandlingerror} @@ -102,10 +103,11 @@ % [\c!stretch=50, % \c!shrink=20] -\unexpanded\def\setexpansion - {\dosingleempty\font_expansion_set} +\permanent\tolerant\protected\def\setexpansion[#1]{\begincsname\??expansion:#1\endcsname} + +%D New in \LMTX: can be used grouped. -\unexpanded\def\font_expansion_set[#1]% - {\begincsname\??expansion:#1\endcsname} +\permanent\protected\def\noexpansion {\bitwiseflip\glyphoptions\noexpansioncode} +\permanent\protected\def\noprotrusion{\bitwiseflip\glyphoptions\noprotrusioncode} \protect \endinput diff --git a/tex/context/base/mkiv/lang-def.mkiv b/tex/context/base/mkiv/lang-def.mkiv index 35a634644..f2364a128 100644 --- a/tex/context/base/mkiv/lang-def.mkiv +++ b/tex/context/base/mkiv/lang-def.mkiv @@ -489,6 +489,22 @@ % Artificial Languages: Esperanto +\installlanguage + [\s!esperanto] + [%\c!spacing=\v!packed, + %\c!leftsentence=\emdash, + %\c!rightsentence=\emdash, + %\c!leftsubsentence=\emdash, + %\c!rightsubsentence=\emdash, + %\c!leftquote=\lowerleftdoubleninequote, + %\c!rightquote=\upperrightdoublesixquote, + %\c!leftquotation=\lowerleftdoubleninequote, + %\c!rightquotation=\upperrightdoublesixquote, + %\c!date={\v!year,~m.,\space,\v!month,\space,\v!day,~d.}, + \s!patterns=eo, + \s!lefthyphenmin=2, + \s!righthyphenmin=2] + % Baltic Languages: Lettish/Latvian, Lietuvių/Lithuanian \installlanguage diff --git a/tex/context/base/mkiv/lang-dis.lmt b/tex/context/base/mkiv/lang-dis.lmt new file mode 100644 index 000000000..263225691 --- /dev/null +++ b/tex/context/base/mkiv/lang-dis.lmt @@ -0,0 +1,222 @@ +if not modules then modules = { } end modules ['lang-dis'] = { + version = 1.001, + comment = "companion to lang-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local concat = table.concat + +local tex = tex +local nodes = nodes + +local tasks = nodes.tasks +local nuts = nodes.nuts + +local enableaction = tasks.enableaction +local setaction = tasks.setaction + +local setfield = nuts.setfield +local getnext = nuts.getnext +local getprev = nuts.getprev +local getid = nuts.getid +local getattr = nuts.getattr +local getsubtype = nuts.getsubtype +local setsubtype = nuts.setsubtype +local getchar = nuts.getchar +local setchar = nuts.setchar +local getdisc = nuts.getdisc +local setdisc = nuts.setdisc +local getlanguage = nuts.getlanguage +local getboth = nuts.getboth +local setlist = nuts.setlist +local setlink = nuts.setlink +local isglyph = nuts.isglyph + +local copy_node = nuts.copy +local remove_node = nuts.remove +local flush_list = nuts.flush_list +local flush_node = nuts.flush_node + +local nextdisc = nuts.traversers.disc + +local new_disc = nuts.pool.disc + +local nodecodes = nodes.nodecodes +local disccodes = nodes.disccodes + +local disc_code = nodecodes.disc +local glyph_code = nodecodes.glyph + +local explicitdisc_code = disccodes.explicit + +local a_visualize = attributes.private("visualizediscretionary") +local setattribute = tex.setattribute + +local getlanguagedata = languages.getdata +local prehyphenchar = language.prehyphenchar +local posthyphenchar = language.posthyphenchar + +local check_regular = true + +local setlistcolor = nodes.tracers.colors.setlist + +function languages.visualizediscretionaries(head) + for d in nextdisc, head do + if getattr(d,a_visualize) then + local pre, post, replace = getdisc(d) + if pre then + setlistcolor(pre,"darkred") + end + if post then + setlistcolor(post,"darkgreen") + end + if replace then + setlistcolor(replace,"darkblue") + end + end + end + return head +end + +local enabled = false + +function languages.showdiscretionaries(v) + if v == false then + setattribute(a_visualize,unsetvalue) + else -- also nil + if not enabled then + enableaction("processors","languages.visualizediscretionaries") + enabled = true + end + setattribute(a_visualize,1) + end +end + +interfaces.implement { + name = "showdiscretionaries", + actions = languages.showdiscretionaries +} + +do + + local toutf = nodes.listtoutf + local utfchar = utf.char + local f_disc = string.formatters["{%s}{%s}{%s}"] + local replace = lpeg.replacer( { + [utfchar(0x200C)] = "|", + [utfchar(0x200D)] = "|", + }, nil, true) + + local function convert(list) + return list and replace(toutf(list)) or "" + end + + function languages.serializediscretionary(d) -- will move to tracer + local pre, post, replace = getdisc(d) + return f_disc(convert(pre),convert(post),convert(replace)) + end + +end + +-- -- + +local wiped = 0 + +local flatten_discretionaries = nuts.flatten_discretionaries -- todo in nodes + +-- if flatten_discretionaries then + + function languages.flatten(head) + local h, n = flatten_discretionaries(head) + wiped = wiped + n + return h, n > 0 + end + +-- else +-- +-- local function wipe(head,delayed) +-- local p, n = getboth(delayed) +-- local _, _, h, _, _, t = getdisc(delayed,true) +-- if p or n then +-- if h then +-- setlink(p,h) +-- setlink(t,n) +-- setfield(delayed,"replace") +-- else +-- setlink(p,n) +-- end +-- end +-- if head == delayed then +-- head = h +-- end +-- wiped = wiped + 1 +-- flush_node(delayed) +-- return head +-- end +-- +-- function languages.flatten(head) +-- local delayed = nil +-- for d in nextdisc, head do +-- if delayed then +-- head = wipe(head,delayed) +-- end +-- delayed = d +-- end +-- if delayed then +-- return wipe(head,delayed), true +-- else +-- return head, false +-- end +-- end +-- +-- end + +function languages.nofflattened() + return wiped -- handy for testing +end + +-- experiment: for now not in not in export mode! + +local flatten = languages.flatten + +nodes.handlers.flattenline = flatten + +function nodes.handlers.flatten(head,where) + if head and (where == "box" or where == "adjusted_hbox") then + return flatten(head) + end + return head +end + +directives.register("hyphenator.flatten",function(v) + -- use with care + setaction("processors","nodes.handlers.flatten",v) + setaction("contributers","nodes.handlers.flattenline",v) +end) + +-- moved here: + +function languages.explicithyphen(template) + local pre, post + local disc = new_disc() + if template then + local langdata = getlanguagedata(getlanguage(template)) + local instance = langdata and langdata.instance + if instance then + local prechr = prehyphenchar(instance) + local postchr = posthyphenchar(instance) + if prechr >= 0 then + pre = copy_node(template) + setchar(pre,prechr) + end + if postchr >= 0 then + post = copy_node(template) + setchar(post,postchr) + end + end + end + setdisc(disc,pre,post,nil,explicitdisc_code,tex.exhyphenpenalty) + return disc +end diff --git a/tex/context/base/mkiv/lang-dis.lua b/tex/context/base/mkiv/lang-dis.lua index 90e84f65d..3e4678801 100644 --- a/tex/context/base/mkiv/lang-dis.lua +++ b/tex/context/base/mkiv/lang-dis.lua @@ -28,7 +28,7 @@ local getchar = nuts.getchar local setchar = nuts.setchar local getdisc = nuts.getdisc local setdisc = nuts.setdisc -local getlang = nuts.setlang +local getlanguage = nuts.getlanguage local getboth = nuts.getboth local setlist = nuts.setlist local setlink = nuts.setlink diff --git a/tex/context/base/mkiv/lang-exp.lua b/tex/context/base/mkiv/lang-exp.lua index 254961ee6..c2eb46990 100644 --- a/tex/context/base/mkiv/lang-exp.lua +++ b/tex/context/base/mkiv/lang-exp.lua @@ -116,7 +116,7 @@ if LUATEXVERSION < 1.005 then -- not loaded any more end end if template then - local language = template and getlang(template) + local language = template and getlanguage(template) local data = getlanguagedata(language) local prechar = data.prehyphenchar local postchar = data.posthyphenchar diff --git a/tex/context/base/mkiv/lang-hyp.lmt b/tex/context/base/mkiv/lang-hyp.lmt new file mode 100644 index 000000000..c2862f536 --- /dev/null +++ b/tex/context/base/mkiv/lang-hyp.lmt @@ -0,0 +1,1806 @@ +if not modules then modules = { } end modules ['lang-hyp'] = { + version = 1.001, + comment = "companion to lang-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- In an automated workflow hypenation of long titles can be somewhat problematic +-- especially when demands conflict. For that reason I played a bit with a Lua based +-- variant of the traditional hyphenation machinery. This mechanism has been extended +-- several times in projects, of which a good description can be found in TUGboat, +-- Volume 27 (2006), No. 2 — Proceedings of EuroTEX2006: Automatic non-standard +-- hyphenation in OpenOffice.org by László Németh. +-- +-- Being the result of two days experimenting the following implementation is probably +-- not completely okay yet. If there is demand I might add some more features and plugs. +-- The performance is quite okay but can probably improved a bit, although this is not +-- the most critital code. For instance, on a metafun manual run the overhead is about +-- 0.3 seconds on 19 seconds which is not that bad. +-- +-- In the procecess of wrapping up (for the ctx conference proceedings) I cleaned up +-- and extended the code a bit. It can be used in production. +-- +-- . a l g o r i t h m . +-- 4l1g4 +-- l g o3 +-- 1g o +-- 2i t h +-- 4h1m +-- --------------------- +-- 4 1 4 3 2 0 4 1 +-- a l-g o-r i t h-m + +-- . a s s z o n n y a l . +-- s1s z/sz=sz,1,3 +-- n1n y/ny=ny,1,3 +-- ----------------------- +-- 0 1 0 0 0 1 0 0 0/sz=sz,2,3,ny=ny,6,3 +-- a s-s z o n-n y a l/sz=sz,2,3,ny=ny,6,3 +-- +-- ab1cd/ef=gh,2,2 : acd - efd (pattern/replacement,start,length +-- +-- todo : support hjcodes (<32 == length) like luatex does now (no need/demand so far) +-- maybe : support hyphenation over range (can alsready be done using attributes/language) +-- maybe : reset dictionary.hyphenated when a pattern is added and/or forced reset option +-- todo : check subtypes (because they have subtle meanings in the line breaking) +-- +-- word start (in tex engine): +-- +-- boundary : yes when wordboundary +-- hlist : when hyphenationbounds 1 or 3 +-- vlist : when hyphenationbounds 1 or 3 +-- rule : when hyphenationbounds 1 or 3 +-- dir : when hyphenationbounds 1 or 3 +-- whatsit : when hyphenationbounds 1 or 3 +-- glue : yes +-- math : skipped +-- glyph : exhyphenchar (one only) : yes (so no -- ---) +-- otherwise : yes +-- +-- word end (in tex engine): +-- +-- boundary : yes +-- glyph : yes when different language +-- glue : yes +-- penalty : yes +-- kern : yes when not italic (for some historic reason) +-- hlist : when hyphenationbounds 2 or 3 +-- vlist : when hyphenationbounds 2 or 3 +-- rule : when hyphenationbounds 2 or 3 +-- dir : when hyphenationbounds 2 or 3 +-- whatsit : when hyphenationbounds 2 or 3 +-- ins : when hyphenationbounds 2 or 3 +-- adjust : when hyphenationbounds 2 or 3 + +local type, rawget, rawset, tonumber, next = type, rawget, rawset, tonumber, next + +local P, R, S, Cg, Cf, Ct, Cc, C, Carg, Cs = lpeg.P, lpeg.R, lpeg.S, lpeg.Cg, lpeg.Cf, lpeg.Ct, lpeg.Cc, lpeg.C, lpeg.Carg, lpeg.Cs +local lpegmatch = lpeg.match + +local context = context + +local concat = table.concat +local insert = table.insert +local remove = table.remove +local formatters = string.formatters +local utfchar = utf.char +local utfbyte = utf.byte + +if not characters then + require("char-ini") +end + +local setmetatableindex = table.setmetatableindex + +-- \enabletrackers[hyphenator.steps=silent] will not write to the terminal + +local trace_steps = false trackers.register("hyphenator.steps", function(v) trace_steps = v end) +local trace_visualize = false trackers.register("hyphenator.visualize",function(v) trace_visualize = v end) + +local report = logs.reporter("hyphenator") + +local implement = interfaces and interfaces.implement or function() end + +languages = languages or { } +local hyphenators = languages.hyphenators or { } +languages.hyphenators = hyphenators +local traditional = hyphenators.traditional or { } +hyphenators.traditional = traditional + +local dictionaries = setmetatableindex(function(t,k) + local v = { + patterns = { }, + hyphenated = { }, + specials = { }, + exceptions = { }, + loaded = false, + } + t[k] = v + return v +end) + +hyphenators.dictionaries = dictionaries + +local character = lpeg.patterns.utf8character +local digit = R("09") +local weight = digit/tonumber + Cc(0) +local fence = P(".") +local hyphen = P("-") +local space = P(" ") +local char = character - space +local validcharacter = (character - S("./")) +local keycharacter = character - S("/") +----- basepart = Ct( (Cc(0) * fence)^-1 * (weight * validcharacter)^1 * weight * (fence * Cc(0))^-1) +local specpart = (P("/") * Cf ( Ct("") * + Cg ( Cc("before") * C((1-P("="))^1) * P("=") ) * + Cg ( Cc("after") * C((1-P(","))^1) ) * + ( P(",") * + Cg ( Cc("start") * ((1-P(","))^1/tonumber) * P(",") ) * + Cg ( Cc("length") * ((1-P(-1) )^1/tonumber) ) + )^-1 + , rawset))^-1 + +local make_hashkey_p = Cs((digit/"" + keycharacter)^1) +----- make_pattern_p = basepart * specpart +local make_hashkey_e = Cs((hyphen/"" + keycharacter)^1) +local make_pattern_e = Ct(P(char) * (hyphen * Cc(true) * P(char) + P(char) * Cc(false))^1) -- catch . and char after - + +-- local make_hashkey_c = Cs((digit + keycharacter/"")^1) +-- local make_pattern_c = Ct((P(1)/tonumber)^1) + +-- local cache = setmetatableindex(function(t,k) +-- local n = lpegmatch(make_hashkey_c,k) +-- local v = lpegmatch(make_pattern_c,n) +-- t[k] = v +-- return v +-- end) +-- +-- local weight_n = digit + Cc("0") +-- local basepart_n = Cs( (Cc("0") * fence)^-1 * (weight * validcharacter)^1 * weight * (fence * Cc("0"))^-1) / cache +-- local make_pattern_n = basepart_n * specpart + +local make_pattern_c = Ct((P(1)/tonumber)^1) + +-- us + nl: 17664 entries -> 827 unique (saves some 3M) + +local cache = setmetatableindex(function(t,k) + local v = lpegmatch(make_pattern_c,k) + t[k] = v + return v +end) + +local weight_n = digit + Cc("0") +local fence_n = fence / "0" +local char_n = validcharacter / "" +local basepart_n = Cs(fence_n^-1 * (weight_n * char_n)^1 * weight_n * fence_n^-1) / cache +local make_pattern_n = basepart_n * specpart + +local function register_pattern(patterns,specials,str,specification) + local k = lpegmatch(make_hashkey_p,str) + -- local v1, v2 = lpegmatch(make_pattern_p,str) + local v1, v2 = lpegmatch(make_pattern_n,str) + patterns[k] = v1 -- is this key still ok for complex patterns + if specification then + specials[k] = specification + elseif v2 then + specials[k] = v2 + end +end + +local function unregister_pattern(patterns,specials,str) + local k = lpegmatch(make_hashkey_p,str) + patterns[k] = nil + specials[k] = nil +end + +local p_lower = lpeg.patterns.utf8lower + +local function register_exception(exceptions,str,specification) + local l = lpegmatch(p_lower,str) + local k = lpegmatch(make_hashkey_e,l) + local v = lpegmatch(make_pattern_e,l) + exceptions[k] = v +end + +local p_pattern = ((Carg(1) * Carg(2) * C(char^1)) / register_pattern + 1)^1 +local p_exception = ((Carg(1) * C(char^1)) / register_exception + 1)^1 +local p_split = Ct(C(character)^1) + +function traditional.loadpatterns(language,filename) + local dictionary = dictionaries[language] + if not dictionary.loaded then + if not filename or filename == "" then + filename = "lang-" .. language + end + filename = file.addsuffix(filename,"lua") + local fullname = resolvers.findfile(filename) + if fullname and fullname ~= "" then + local specification = dofile(fullname) + if specification then + local patterns = specification.patterns + if patterns then + local data = patterns.data + if data and data ~= "" then + lpegmatch(p_pattern,data,1,dictionary.patterns,dictionary.specials) + end + end + local exceptions = specification.exceptions + if exceptions then + local data = exceptions.data + if data and data ~= "" then + lpegmatch(p_exception,data,1,dictionary.exceptions) + end + end + end + end + dictionary.loaded = true + end + return dictionary +end + +local lcchars = characters.lcchars +local uccodes = characters.uccodes +local categories = characters.categories +local nofwords = 0 +local nofhashed = 0 + +local steps = nil +local f_show = formatters["%w%s"] + +local function show_log() + if trace_steps == true then + report() + local w = #steps[1][1] + for i=1,#steps do + local s = steps[i] + report("%s%w%S %S",s[1],w - #s[1] + 3,s[2],s[3] or "") + end + report() + end +end + +local function show_1(wsplit) + local u = concat(wsplit," ") + steps = { { f_show(0,u), f_show(0,u) } } +end + +local function show_2(c,m,wsplit,done,i,spec) + local s = lpegmatch(p_split,c) + local t = { } + local n = #m + local w = #wsplit + for j=1,n do + t[#t+1] = m[j] + t[#t+1] = s[j] + end + local m = 2*i-2 + local l = #t + local s = spec and table.sequenced(spec) or "" + if m == 0 then + steps[#steps+1] = { f_show(m, concat(t,"",2)), f_show(1,concat(done," ",2,#done),s) } + elseif i+1 == w then + steps[#steps+1] = { f_show(m-1,concat(t,"",1,#t-1)), f_show(1,concat(done," ",2,#done),s) } + else + steps[#steps+1] = { f_show(m-1,concat(t)), f_show(1,concat(done," ",2,#done),s) } + end +end + +local function show_3(wsplit,done) + local t = { } + local h = { } + local n = #wsplit + for i=1,n do + local w = wsplit[i] + if i > 1 then + local d = done[i] + t[#t+1] = i > 2 and d % 2 == 1 and "-" or " " + h[#h+1] = d + end + t[#t+1] = w + h[#h+1] = w + end + steps[#steps+1] = { f_show(0,concat(h)), f_show(0,concat(t)) } + show_log() +end + +local function show_4(wsplit,done) + steps = { { concat(wsplit," ") } } + show_log() +end + +function traditional.lasttrace() + return steps +end + +-- We could reuse the w table but as we cache the resolved words there is not much gain in +-- that complication. +-- +-- Beware: word can be a table and when n is passed to we can assume reuse so we need to +-- honor that n then. +-- +-- todo: a fast variant for tex ... less lookups (we could check is dictionary has changed) +-- ... although due to caching the already done words, we don't do much here + +local function hyphenate(dictionary,word,n) -- odd is okay + nofwords = nofwords + 1 + local hyphenated = dictionary.hyphenated + local isstring = type(word) == "string" + if isstring then + local done = hyphenated[word] + if done ~= nil then + return done + end + elseif n then + local done = hyphenated[concat(word,"",1,n)] + if done ~= nil then + return done + end + else + local done = hyphenated[concat(word)] + if done ~= nil then + return done + end + end + local key + if isstring then + key = word + word = lpegmatch(p_split,word) + if not n then + n = #word + end + else + if not n then + n = #word + end + key = concat(word,"",1,n) + end + local l = 1 + local w = { "." } + -- local d = dictionary.codehash + for i=1,n do + local c = word[i] + -- l = l + (d[c] or 1) + l = l + 1 + w[l] = lcchars[c] or c + end + l = l + 1 + w[l] = "." + local c = concat(w,"",2,l-1) + -- + local done = hyphenated[c] + if done ~= nil then + hyphenated[key] = done + nofhashed = nofhashed + 1 + return done + end + -- + local exceptions = dictionary.exceptions + local exception = exceptions[c] + if exception then + if trace_steps then + show_4(w,exception) + end + hyphenated[key] = exception + nofhashed = nofhashed + 1 + return exception + end + -- + if trace_steps then + show_1(w) + end + -- + local specials = dictionary.specials + local patterns = dictionary.patterns + -- + local spec + for i=1,l do + for j=i,l do + local c = concat(w,"",i,j) + local m = patterns[c] + if m then + local s = specials[c] + if not done then + done = { } + spec = nil + -- the string that we resolve has explicit fences (.) so done starts at + -- the first fence and runs upto the last one so we need one slot less + for i=1,l do + done[i] = 0 + end + end + -- we run over the pattern that always has a (zero) value for each character + -- plus one more as we look at both sides + for k=1,#m do + local new = m[k] + if not new then + break + elseif new == true then + report("fatal error") + break + elseif new > 0 then + local pos = i + k - 1 + local old = done[pos] + if not old then + -- break ? + elseif new > old then + done[pos] = new + if s then + local b = i + (s.start or 1) - 1 + if b > 0 then + local e = b + (s.length or 2) - 1 + if e > 0 then + if pos >= b and pos <= e then + if spec then + spec[pos] = { s, k - 1 } + else + spec = { [pos] = { s, k - 1 } } + end + end + end + end + end + end + end + end + if trace_steps and done then + show_2(c,m,w,done,i,s) + end + end + end + end + if trace_steps and done then + show_3(w,done) + end + if done then + local okay = false + for i=3,#done do + if done[i] % 2 == 1 then + done[i-2] = spec and spec[i] or true + okay = true + else + done[i-2] = false + end + end + if okay then + done[#done] = nil + done[#done] = nil + else + done = false + end + else + done = false + end + hyphenated[key] = done + nofhashed = nofhashed + 1 + return done +end + +function traditional.gettrace(language,word) + if not word or word == "" then + return + end + local dictionary = dictionaries[language] + if dictionary then + local hyphenated = dictionary.hyphenated + hyphenated[word] = nil + hyphenate(dictionary,word) + return steps + end +end + +local methods = setmetatableindex(function(t,k) local v = hyphenate t[k] = v return v end) + +function traditional.installmethod(name,f) + if rawget(methods,name) then + report("overloading %a is not permitted",name) + else + methods[name] = f + end +end + +local s_detail_1 = "-" +local f_detail_2 = formatters["%s-%s"] +local f_detail_3 = formatters["{%s}{%s}{}"] +local f_detail_4 = formatters["{%s%s}{%s%s}{%s}"] + +function traditional.injecthyphens(dictionary,word,specification) + if not word then + return false + end + if not specification then + return word + end + local hyphens = hyphenate(dictionary,word) + if not hyphens then + return word + end + + -- the following code is similar to code later on but here we have strings while there + -- we have hyphen specs + + local word = lpegmatch(p_split,word) + local size = #word + + local leftmin = specification.leftcharmin or 2 + local rightmin = size - (specification.rightcharmin or leftmin) + local leftchar = specification.leftchar + local rightchar = specification.rightchar + + local result = { } + local rsize = 0 + local position = 1 + + while position <= size do + if position >= leftmin and position <= rightmin then + local hyphen = hyphens[position] + if not hyphen then + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + elseif hyphen == true then + rsize = rsize + 1 + result[rsize] = word[position] + rsize = rsize + 1 + if leftchar and rightchar then + result[rsize] = f_detail_3(rightchar,leftchar) + else + result[rsize] = s_detail_1 + end + position = position + 1 + else + local o, h = hyphen[2] + if o then + h = hyphen[1] + else + h = hyphen + o = 1 + end + local b = position - o + (h.start or 1) + local e = b + (h.length or 2) - 1 + if b > 0 and e >= b then + for i=1,b-position do + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + end + rsize = rsize + 1 + if leftchar and rightchar then + result[rsize] = f_detail_4(h.before,rightchar,leftchar,h.after,concat(word,"",b,e)) + else + result[rsize] = f_detail_2(h.before,h.after) + end + position = e + 1 + else + -- error + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + end + end + else + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + end + end + return concat(result) +end + +do + + local word = C((1-space)^1) + local spaces = space^1 + + local u_pattern = (Carg(1) * Carg(2) * word / unregister_pattern + spaces)^1 + local r_pattern = (Carg(1) * Carg(2) * word * Carg(3) / register_pattern + spaces)^1 + local e_pattern = (Carg(1) * word / register_exception + spaces)^1 + + function traditional.registerpattern(language,str,specification) + local dictionary = dictionaries[language] + if specification == false then + lpegmatch(u_pattern,str,1,dictionary.patterns,dictionary.specials) + -- unregister_pattern(dictionary.patterns,dictionary.specials,str) + else + lpegmatch(r_pattern,str,1,dictionary.patterns,dictionary.specials,type(specification) == "table" and specification or false) + -- register_pattern(dictionary.patterns,dictionary.specials,str,specification) + end + end + + function traditional.registerexception(language,str) + lpegmatch(e_pattern,str,1,dictionaries[language].exceptions) + end + +end + +-- todo: unicodes or utfhash ? + +if context then + + local nodecodes = nodes.nodecodes + local disccodes = nodes.disccodes + + local glyph_code = nodecodes.glyph + local disc_code = nodecodes.disc + local math_code = nodecodes.math + local hlist_code = nodecodes.hlist + + local automaticdisc_code = disccodes.automatic + local regulardisc_code = disccodes.regular + + local nuts = nodes.nuts + local tonode = nodes.tonode + local nodepool = nuts.pool + + local new_disc = nodepool.disc + local new_penalty = nodepool.penalty + + local getfield = nuts.getfield + local getfont = nuts.getfont + local getid = nuts.getid + local getattr = nuts.getattr + local getnext = nuts.getnext + local getprev = nuts.getprev + local getsubtype = nuts.getsubtype + local getlist = nuts.getlist + local getlanguage = nuts.getlanguage + local getattrlist = nuts.getattrlist + local setattrlist = nuts.setattrlist + local isglyph = nuts.isglyph + local ischar = nuts.ischar + + local setchar = nuts.setchar + local setdisc = nuts.setdisc + local setlink = nuts.setlink + local setprev = nuts.setprev + local setnext = nuts.setnext + + local insert_before = nuts.insert_before + local insert_after = nuts.insert_after + local copy_node = nuts.copy + local copy_list = nuts.copy_list + local remove_node = nuts.remove + local end_of_math = nuts.end_of_math + local node_tail = nuts.tail + + local nexthlist = nuts.traversers.hlist + local nextdisc = nuts.traversers.disc + + local setcolor = nodes.tracers.colors.set + + local variables = interfaces.variables + local v_reset = variables.reset + local v_yes = variables.yes + local v_word = variables.word + local v_all = variables.all + + local settings_to_array = utilities.parsers.settings_to_array + + local unsetvalue = attributes.unsetvalue + local texsetattribute = tex.setattribute + + local prehyphenchar = language.prehyphenchar + local posthyphenchar = language.posthyphenchar + local preexhyphenchar = language.preexhyphenchar + local postexhyphenchar = language.postexhyphenchar + + local a_hyphenation = attributes.private("hyphenation") + + local interwordpenalty = 5000 + + function traditional.loadpatterns(language) + return dictionaries[language] + end + + -- for the moment we use an independent data structure + + setmetatableindex(dictionaries,function(t,k) + if type(k) == "string" then + -- this will force a load if not yet loaded (we need a nicer way) for the moment + -- that will do (nneeded for examples that register a pattern specification + languages.getnumber(k) + end + local specification = languages.getdata(k) + local dictionary = { + patterns = { }, + exceptions = { }, + hyphenated = { }, + specials = { }, + instance = false, + characters = { }, + unicodes = { }, + } + if specification then + local resources = specification.resources + if resources then + local characters = dictionary.characters or { } + local unicodes = dictionary.unicodes or { } + for i=1,#resources do + local r = resources[i] + if not r.in_dictionary then + r.in_dictionary = true + local patterns = r.patterns + if patterns then + local data = patterns.data + if data then + -- regular patterns + lpegmatch(p_pattern,data,1,dictionary.patterns,dictionary.specials) + end + local extra = patterns.extra + if extra then + -- special patterns + lpegmatch(p_pattern,extra,1,dictionary.patterns,dictionary.specials) + end + end + local exceptions = r.exceptions + if exceptions then + local data = exceptions.data + if data and data ~= "" then + lpegmatch(p_exception,data,1,dictionary.exceptions) + end + end + local usedchars = lpegmatch(p_split,patterns.characters) + for i=1,#usedchars do + local char = usedchars[i] + local code = utfbyte(char) + local upper = uccodes[code] + characters[char] = code + unicodes [code] = char + if type(upper) == "table" then + for i=1,#upper do + local u = upper[i] + unicodes[u] = utfchar(u) + end + else + unicodes[upper] = utfchar(upper) + end + end + end + end + dictionary.characters = characters + dictionary.unicodes = unicodes + setmetatableindex(characters,function(t,k) local v = k and utfbyte(k) t[k] = v return v end) + end + t[specification.number] = dictionary + dictionary.instance = specification.instance -- needed for hyphenchars + end + t[k] = dictionary + return dictionary + end) + + -- Beware: left and right min doesn't mean that in a 1 mmm hsize there can be snippets + -- with less characters than either of them! This could be an option but such a narrow + -- hsize doesn't make sense anyway. + + -- We assume that featuresets are defined global ... local definitions (also mid paragraph) + -- make not much sense anyway. For the moment we assume no predefined sets so we don't need + -- to store them. Nor do we need to hash them in order to save space ... no sane user will + -- define many of them. + + local featuresets = hyphenators.featuresets or { } + hyphenators.featuresets = featuresets + + storage.shared.noflanguagesfeaturesets = storage.shared.noflanguagesfeaturesets or 0 + + local noffeaturesets = storage.shared.noflanguagesfeaturesets + + storage.register("languages/hyphenators/featuresets",featuresets,"languages.hyphenators.featuresets") + + ----- hash = table.sequenced(featureset,",") -- no need now + + local function register(name,featureset) + noffeaturesets = noffeaturesets + 1 + featureset.attribute = noffeaturesets + featuresets[noffeaturesets] = featureset -- access by attribute + featuresets[name] = featureset -- access by name + storage.shared.noflanguagesfeaturesets = noffeaturesets + return noffeaturesets + end + + local function makeset(...) + -- a bit overkill, supporting variants but who cares + local set = { } + for i=1,select("#",...) do + local list = select(i,...) + local kind = type(list) + local used = nil + if kind == "string" then + if list == v_all then + -- not ok ... now all get ignored + return setmetatableindex(function(t,k) local v = utfchar(k) t[k] = v return v end) + elseif list ~= "" then + used = lpegmatch(p_split,list) + set = set or { } + for i=1,#used do + local char = used[i] + set[utfbyte(char)] = char + end + end + elseif kind == "table" then + if next(list) then + set = set or { } + for byte, char in next, list do + set[byte] = char == true and utfchar(byte) or char + end + elseif #list > 0 then + set = set or { } + for i=1,#list do + local l = list[i] + if type(l) == "number" then + set[l] = utfchar(l) + else + set[utfbyte(l)] = l + end + end + end + end + end + return set + end + + -- category pd (tex also sees --- and -- as hyphens but do we really want that + + local defaulthyphens = { + [0x002D] = true, -- HYPHEN-MINUS + [0x00AD] = 0x002D, -- SOFT HYPHEN (active in ConTeXt) + -- [0x058A] = true, -- ARMENIAN HYPHEN + -- [0x1400] = true, -- CANADIAN SYLLABICS HYPHEN + -- [0x1806] = true, -- MONGOLIAN TODO SOFT HYPHEN + [0x2010] = true, -- HYPHEN + -- [0x2011] = true, -- NON-BREAKING HYPHEN + -- [0x2012] = true, -- FIGURE DASH + [0x2013] = true, -- EN DASH + [0x2014] = true, -- EM DASH + -- [0x2015] = true, -- HORIZONTAL BAR + -- [0x2027] = true, -- HYPHENATION POINT + -- [0x2E17] = true, -- DOUBLE OBLIQUE HYPHEN + -- [0x2E1A] = true, -- HYPHEN WITH DIAERESIS + -- [0x2E3A] = true, -- TWO-EM DASH + -- [0x2E3B] = true, -- THREE-EM DASH + -- [0x2E40] = true, -- DOUBLE HYPHEN + -- [0x301C] = true, -- WAVE DASH + -- [0x3030] = true, -- WAVY DASH + -- [0x30A0] = true, -- KATAKANA-HIRAGANA DOUBLE HYPHEN + -- [0xFE31] = true, -- PRESENTATION FORM FOR VERTICAL EM DASH + -- [0xFE32] = true, -- PRESENTATION FORM FOR VERTICAL EN DASH + -- [0xFE58] = true, -- SMALL EM DASH + -- [0xFE63] = true, -- SMALL HYPHEN-MINUS + -- [0xFF0D] = true, -- FULLWIDTH HYPHEN-MINUS + } + + local defaultjoiners = { + [0x200C] = true, -- nzwj + [0x200D] = true, -- zwj + } + + local function somehyphenchar(c) + c = tonumber(c) + return c ~= 0 and c or nil + end + + local function definefeatures(name,featureset) + local extrachars = featureset.characters -- "[]()" + local hyphenchars = featureset.hyphens + local joinerchars = featureset.joiners + local alternative = featureset.alternative + local rightwordmin = tonumber(featureset.rightwordmin) + local charmin = tonumber(featureset.charmin) -- luatex now also has hyphenationmin + local leftcharmin = tonumber(featureset.leftcharmin) + local rightcharmin = tonumber(featureset.rightcharmin) + local leftchar = somehyphenchar(featureset.leftchar) + local rightchar = somehyphenchar(featureset.rightchar) + local rightchars = featureset.rightchars +local rightedge = featureset.rightedge +local autohyphen = v_yes -- featureset.autohyphen -- insert disc +local hyphenonly = v_yes -- featureset.hyphenonly -- don't hyphenate around + rightchars = rightchars == v_word and true or tonumber(rightchars) + joinerchars = joinerchars == v_yes and defaultjoiners or joinerchars -- table + hyphenchars = hyphenchars == v_yes and defaulthyphens or hyphenchars -- table + -- not yet ok: extrachars have to be ignored so it cannot be all) + featureset.extrachars = makeset(joinerchars or "",extrachars or "") + featureset.hyphenchars = makeset(hyphenchars or "") + featureset.alternative = alternative or "hyphenate" + featureset.rightwordmin = rightwordmin and rightwordmin > 0 and rightwordmin or nil + featureset.charmin = charmin and charmin > 0 and charmin or nil + featureset.leftcharmin = leftcharmin and leftcharmin > 0 and leftcharmin or nil + featureset.rightcharmin = rightcharmin and rightcharmin > 0 and rightcharmin or nil + featureset.rightchars = rightchars + featureset.leftchar = leftchar + featureset.rightchar = rightchar + -- featureset.strict = rightedge == "tex" +featureset.autohyphen = autohyphen == v_yes +featureset.hyphenonly = hyphenonly == v_yes + return register(name,featureset) + end + + local function setfeatures(n) + if not n or n == v_reset then + n = false + else + local f = featuresets[n] + if not f and type(n) == "string" then + local t = settings_to_array(n) + local s = { } + for i=1,#t do + local ti = t[i] + local fs = featuresets[ti] + if fs then + for k, v in next, fs do + s[k] = v + end + end + end + n = register(n,s) + else + n = f and f.attribute + end + end + texsetattribute(a_hyphenation,n or unsetvalue) + end + + traditional.definefeatures = definefeatures + traditional.setfeatures = setfeatures + + implement { + name = "definehyphenationfeatures", + actions = definefeatures, + arguments = { + "string", + { + { "characters" }, + { "hyphens" }, + { "joiners" }, + { "rightchars" }, + { "rightwordmin", "integer" }, + { "charmin", "integer" }, + { "leftcharmin", "integer" }, + { "rightcharmin", "integer" }, + { "leftchar", "integer" }, + { "rightchar", "integer" }, + { "alternative" }, + { "rightedge" }, + } + } + } + + implement { + name = "sethyphenationfeatures", + actions = setfeatures, + arguments = "string" + } + + implement { + name = "registerhyphenationpattern", + actions = traditional.registerpattern, + arguments = { "string", "string", "boolean" } + } + + implement { + name = "registerhyphenationexception", + actions = traditional.registerexception, + arguments = "2 strings", + } + + -- This is a relative large function with local variables and local functions. A previous + -- implementation had the functions outside but this is cleaner and as efficient. The test + -- runs 100 times over tufte.tex, knuth.tex, zapf.tex, ward.tex and darwin.tex in lower + -- and uppercase with a 1mm hsize. + -- + -- language=0 language>0 4 | 3 * slower + -- + -- tex 2.34 | 1.30 2.55 | 1.45 0.21 | 0.15 + -- lua 2.42 | 1.38 3.30 | 1.84 0.88 | 0.46 + -- + -- Of course we have extra overhead (virtual Lua machine) but also we check attributes and + -- support specific local options). The test puts the typeset text in boxes and discards + -- it. If we also flush the runtime is 4.31|2.56 and 4.99|2.94 seconds so the relative + -- difference is (somehow) smaller. The test has 536 pages. There is a little bit of extra + -- overhead because we store the patterns in a different way. + -- + -- As usual I will look for speedups. Some 0.01 seconds could be gained by sharing patterns + -- which is not impressive but it does save some 3M memory on this test. (Some optimizations + -- already brought the 3.30 seconds down to 3.14 but it all depends on aggressive caching.) + + -- As we kick in the hyphenator before fonts get handled, we don't look at implicit (font) + -- kerns or ligatures. + + local starttiming = statistics.starttiming + local stoptiming = statistics.stoptiming + + -- local strictids = { + -- [nodecodes.hlist] = true, + -- [nodecodes.vlist] = true, + -- [nodecodes.rule] = true, + -- [nodecodes.dir] = true, + -- [nodecodes.whatsit] = true, + -- [nodecodes.ins] = true, + -- [nodecodes.adjust] = true, + -- + -- [nodecodes.math] = true, + -- [nodecodes.disc] = true, + -- + -- [nodecodes.accent] = true, -- never used in context + -- } + + -- a lot of overhead when only one char + + function traditional.hyphenate(head) + + local first = head + local tail = nil + local last = nil + local current = first + local dictionary = nil + local instance = nil + local characters = nil + local unicodes = nil + local exhyphenchar = tex.exhyphenchar + local extrachars = nil + local hyphenchars = nil + local language = nil + local lastfont = nil + local start = nil + local stop = nil + local word = { } -- we reuse this table + local size = 0 + local leftchar = false + local rightchar = false -- utfbyte("-") + local leftexchar = false + local rightexchar = false -- utfbyte("-") + local leftmin = 0 + local rightmin = 0 + local charmin = 1 + local leftcharmin = nil + local rightcharmin = nil + ----- leftwordmin = nil + local rightwordmin = nil + local rightchars = nil + local leftchar = nil + local rightchar = nil + local attr = nil + local lastwordlast = nil + local hyphenated = hyphenate + ----- strict = nil + local exhyphenpenalty = tex.exhyphenpenalty + local hyphenpenalty = tex.hyphenpenalty + local autohyphen = false + local hyphenonly = false + + -- We cannot use an 'enabled' boolean (false when no characters or extras) because we + -- can have plugins that set a characters metatable and so) ... it doesn't save much + -- anyway. Using (unicodes and unicodes[code]) and a nil table when no characters also + -- doesn't save much. So there not that much to gain for languages that don't hyphenate. + -- + -- enabled = (unicodes and (next(unicodes) or getmetatable(unicodes))) + -- or (extrachars and next(extrachars)) + -- + -- This can be used to not add characters i.e. keep size 0 but then we need to check for + -- attributes that change it, which costs time too. Not much to gain there. + + starttiming(traditional) + + local function insertpenalty() + local p = new_penalty(interwordpenalty) + setattrlist(p,last) + if trace_visualize then + nuts.setvisual(p,"penalty") + end + last = getprev(last) + first, last = insert_after(first,last,p) + end + + local function synchronizefeatureset(a) + local f = a and featuresets[a] + if f then + hyphenated = methods[f.alternative or "hyphenate"] + extrachars = f.extrachars + hyphenchars = f.hyphenchars + rightwordmin = f.rightwordmin + charmin = f.charmin + leftcharmin = f.leftcharmin + rightcharmin = f.rightcharmin + leftchar = f.leftchar + rightchar = f.rightchar + -- strict = f.strict and strictids + rightchars = f.rightchars + autohyphen = f.autohyphen + hyphenonly = f.hyphenonly + if rightwordmin and rightwordmin > 0 and lastwordlast ~= rightwordmin then + -- so we can change mid paragraph but it's kind of unpredictable then + if not tail then + tail = node_tail(first) + end + last = tail + local inword = false + local count = 0 + while last and rightwordmin > 0 do + local id = getid(last) + if id == glyph_code then + count = count + 1 + inword = true + if trace_visualize then + setcolor(last,"darkgreen") + end + elseif inword then + inword = false + rightwordmin = rightwordmin - 1 + if rightchars == true then + if rightwordmin > 0 then + insertpenalty() + end + elseif rightchars and count <= rightchars then + insertpenalty() + end + end + last = getprev(last) + end + lastwordlast = rightwordmin + end + if not charmin or charmin == 0 then + charmin = 1 + end + else + hyphenated = methods.hyphenate + extrachars = false + hyphenchars = false + rightwordmin = false + charmin = 1 + leftcharmin = false + rightcharmin = false + leftchar = false + rightchar = false + -- strict = false + autohyphen = false + hyphenonly = false + end + + return a + end + + local function flush(hyphens) -- todo: no need for result + + local rightmin = size - rightmin + local result = { } + local rsize = 0 + local position = 1 + + -- todo: remember last dics and don't go back to before that (plus message) ... + -- for simplicity we also assume that we don't start with a dics node + -- + -- there can be a conflict: if we backtrack then we can end up in another disc + -- and get out of sync (dup chars and so) + + while position <= size do + if position >= leftmin and position <= rightmin then + local hyphen = hyphens[position] + if not hyphen then + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + elseif hyphen == true then + rsize = rsize + 1 + result[rsize] = word[position] + rsize = rsize + 1 + result[rsize] = true + position = position + 1 + else + local o, h = hyphen[2] + if o then + -- { hyphen, offset) + h = hyphen[1] + else + -- hyphen + h = hyphen + o = 1 + end + local b = position - o + (h.start or 1) + local e = b + (h.length or 2) - 1 + if b > 0 and e >= b then + for i=1,b-position do + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + end + rsize = rsize + 1 + result[rsize] = { + h.before or "", -- pre + h.after or "", -- post + concat(word,"",b,e), -- replace + h.right, -- optional after pre + h.left, -- optional before post + } + position = e + 1 + else + -- error + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + end + end + else + rsize = rsize + 1 + result[rsize] = word[position] + position = position + 1 + end + end + + local function serialize(replacement,leftchar,rightchar) + if not replacement then + return + elseif replacement == true then + local glyph = copy_node(stop) + setchar(glyph,leftchar or rightchar) + return glyph + end + local head = nil + local current = nil + if leftchar then + head = copy_node(stop) + current = head + setchar(head,leftchar) + end + local rsize = #replacement + if rsize == 1 then + local glyph = copy_node(stop) + setchar(glyph,characters[replacement]) + if head then + insert_after(current,current,glyph) + else + head = glyph + end + current = glyph + elseif rsize > 0 then + local list = lpegmatch(p_split,replacement) -- this is an utf split (could be cached) + for i=1,#list do + local glyph = copy_node(stop) + setchar(glyph,characters[list[i]]) + if head then + insert_after(current,current,glyph) + else + head = glyph + end + current = glyph + end + end + if rightchar then + local glyph = copy_node(stop) + insert_after(current,current,glyph) + setchar(glyph,rightchar) + end + return head + end + + local current = start + local attrnode = start -- will be different, just the first char + + for i=1,rsize do + local r = result[i] + if r == true then + local disc = new_disc() + local pre = nil + local post = nil + if rightchar then + pre = serialize(true,rightchar) + end + if leftchar then + post = serialize(true,leftchar) + end + setdisc(disc,pre,post,nil,regulardisc_code,hyphenpenalty) + if attrnode then + setattrlist(disc,attrnode) + end + -- could be a replace as well + insert_before(first,current,disc) + elseif type(r) == "table" then + local disc = new_disc() + local pre = r[1] + local post = r[2] + local replace = r[3] + local right = r[4] ~= false and rightchar + local left = r[5] ~= false and leftchar + if pre then + if pre ~= "" then + pre = serialize(pre,false,right) + else + pre = nil + end + end + if post then + if post ~= "" then + post = serialize(post,left,false) + else + post = nil + end + end + if replace then + if replace ~= "" then + replace = serialize(replace) + else + replace = nil + end + end + -- maybe regular code + setdisc(disc,pre,post,replace,regulardisc_code,hyphenpenalty) + if attrnode then + setattrlist(disc,attrnode) + end + insert_before(first,current,disc) + else + setchar(current,characters[r]) + if i < rsize then + current = getnext(current) + end + end + end + if current and current ~= stop then + local current = getnext(current) + local last = getnext(stop) + while current ~= last do + first, current = remove_node(first,current,true) + end + end + + end + + local function inject(leftchar,rightchar,code,attrnode) + if first ~= current then + local disc = new_disc() + first, current, glyph = remove_node(first,current) + first, current = insert_before(first,current,disc) + if trace_visualize then + setcolor(glyph,"darkred") -- these get checked + setcolor(disc,"darkgreen") -- in the colorizer + end + local pre = nil + local post = nil + local replace = glyph + if leftchar and leftchar > 0 then + post = copy_node(glyph) + setchar(post,leftchar) + end + pre = copy_node(glyph) + setchar(pre,rightchar and rightchar > 0 and rightchar or code) + setdisc(disc,pre,post,replace,automaticdisc_code,hyphenpenalty) -- ex ? + if attrnode then + setattrlist(disc,attrnode) + end + end + return current + end + + local function injectseries(current,last,next,attrnode) + local disc = new_disc() + local start = current + first, current = insert_before(first,current,disc) + setprev(start) + setnext(last) + if next then + setlink(current,next) + else + setnext(current) + end + local pre = copy_list(start) + local post = nil + local replace = start + setdisc(disc,pre,post,replace,automaticdisc_code,hyphenpenalty) -- ex ? + if attrnode then + setattrlist(disc,attrnode) + end + return current + end + + local a = getattr(first,a_hyphenation) + if a ~= attr then + attr = synchronizefeatureset(a) + end + + -- The first attribute in a word determines the way a word gets hyphenated and if + -- relevant, other properties are also set then. We could optimize for silly one-char + -- cases but it has no priority as the code is still not that much slower than the + -- native hyphenator and this variant also provides room for extensions. + + local skipping = false + + -- In "word word word." the sequences "word" and "." can be a different font! + + while current and current ~= last do -- and current + local code, id = isglyph(current) + if code then + if skipping then + current = getnext(current) + else + local lang = getlanguage(current) + local font = getfont(current) + if lang ~= language or font ~= lastfont then + if dictionary and size > charmin and leftmin + rightmin <= size then + -- only german has many words starting with an uppercase character + if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then + -- skip + else + local hyphens = hyphenated(dictionary,word,size) + if hyphens then + flush(hyphens) + end + end + end + lastfont = font + if language ~= lang and lang > 0 then + -- + dictionary = dictionaries[lang] + instance = dictionary.instance + characters = dictionary.characters + unicodes = dictionary.unicodes + -- + local a = getattr(current,a_hyphenation) + attr = synchronizefeatureset(a) + leftchar = leftchar or (instance and posthyphenchar (instance)) -- we can make this more + rightchar = rightchar or (instance and prehyphenchar (instance)) -- efficient if needed + leftexchar = (instance and preexhyphenchar (instance)) + rightexchar = (instance and postexhyphenchar(instance)) + leftmin = leftcharmin or getfield(current,"left") + rightmin = rightcharmin or getfield(current,"right") + if not leftchar or leftchar < 0 then + leftchar = false + end + if not rightchar or rightchar < 0 then + rightchar = false + end + -- + local char = unicodes[code] or (extrachars and extrachars[code]) + if char then + word[1] = char + size = 1 + start = current + else + size = 0 + end + else + size = 0 + end + language = lang + elseif language <= 0 then + -- + elseif size > 0 then + local char = unicodes[code] or (extrachars and extrachars[code]) + if char then + size = size + 1 + word[size] = char + elseif dictionary then + if not hyphenonly or code ~= exhyphenchar then + if size > charmin and leftmin + rightmin <= size then + if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then + -- skip + else + local hyphens = hyphenated(dictionary,word,size) + if hyphens then + flush(hyphens) + end + end + end + end + size = 0 + if code == exhyphenchar then -- normally the - + local next = getnext(current) + local last = current + local font = getfont(current) + while next and ischar(next,font) == code do + last = next + next = getnext(next) + end + if not autohyphen then + current = last + elseif current == last then + current = inject(leftexchar,rightexchar,code,current) + else + current = injectseries(current,last,next,current) + end + if hyphenonly then + skipping = true + end + elseif hyphenchars then + local char = hyphenchars[code] + if char == true then + char = code + end + if char then + current = inject(leftchar and char or nil,rightchar and char or nil,char,current) + end + end + end + else + local a = getattr(current,a_hyphenation) + if a ~= attr then + attr = synchronizefeatureset(a) -- influences extrachars + leftchar = leftchar or (instance and posthyphenchar (instance)) -- we can make this more + rightchar = rightchar or (instance and prehyphenchar (instance)) -- efficient if needed + leftexchar = (instance and preexhyphenchar (instance)) + rightexchar = (instance and postexhyphenchar(instance)) + leftmin = leftcharmin or getfield(current,"left") + rightmin = rightcharmin or getfield(current,"right") + if not leftchar or leftchar < 0 then + leftchar = false + end + if not rightchar or rightchar < 0 then + rightchar = false + end + end + -- + local char = unicodes[code] or (extrachars and extrachars[code]) + if char then + word[1] = char + size = 1 + start = current + end + end + stop = current + current = getnext(current) + end + else + if skipping then + skipping = false + end + if id == disc_code then + size = 0 + current = getnext(current) + if hyphenonly then + skipping = true + end + -- elseif strict and strict[id] then + -- current = id == math_code and getnext(end_of_math(current)) or getnext(current) + -- size = 0 + else + current = id == math_code and getnext(end_of_math(current)) or getnext(current) + end + if size > 0 then + if dictionary and size > charmin and leftmin + rightmin <= size then + if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then + -- skip + else + local hyphens = hyphenated(dictionary,word,size) + if hyphens then + flush(hyphens) + end + end + end + size = 0 + end + end + end + -- we can have quit due to last so we need to flush the last seen word, we could move + -- this in the loop and test for current but ... messy + if dictionary and size > charmin and leftmin + rightmin <= size then + if categories[word[1]] == "lu" and getfield(start,"uchyph") < 0 then + -- skip + else + local hyphens = hyphenated(dictionary,word,size) + if hyphens then + flush(hyphens) + end + end + end + + stoptiming(traditional) + + return head + end + + statistics.register("hyphenation",function() + if nofwords > 0 or statistics.elapsed(traditional) > 0 then + return string.format("%s words hyphenated, %s unique, used time %s", + nofwords,nofhashed,statistics.elapsedseconds(traditional) or 0) + end + end) + + local texmethod = "builders.kernel.hyphenation" + local oldmethod = texmethod + local newmethod = texmethod + + -- local newmethod = "languages.hyphenators.traditional.hyphenate" + -- + -- nodes.tasks.prependaction("processors","words",newmethod) + -- nodes.tasks.disableaction("processors",oldmethod) + -- + -- nodes.tasks.replaceaction("processors","words",oldmethod,newmethod) + + -- \enabledirectives[hyphenators.method=traditional] + -- \enabledirectives[hyphenators.method=builtin] + + -- push / pop ? check first attribute + + -- local replaceaction = nodes.tasks.replaceaction -- no longer overload this way (too many local switches) + + local hyphenate = language.hyphenate + local hyphenating = nuts.hyphenating + local methods = { } + local usedmethod = false + local stack = { } + + local original = hyphenating and + function(head) + return (hyphenating(head)) + end + or + function(head) + hyphenate(tonode(head)) + return head -- a nut + end + + -- local has_language = language.has_language + -- + -- local function original(head) -- kernel.hyphenation(head) + -- local h = tonode(head) + -- if has_language(h) then + -- hyphenate(h) + -- end + -- return head + -- end + + local getcount = tex.getcount + + hyphenators.methods = methods + local optimize = false + + directives.register("hyphenator.optimize", function(v) optimize = v end) + + function hyphenators.handler(head,groupcode) + if usedmethod then + if optimize and (groupcode == "hbox" or groupcode == "adjusted_hbox") then + if getcount("hyphenstate") > 0 then + forced = false + return usedmethod(head) + else + return head + end + else + return usedmethod(head) + end + else + return head + end + end + + methods.tex = original + methods.original = original + methods.expanded = original -- was expanded before 1.005 + methods.traditional = languages.hyphenators.traditional.hyphenate + methods.none = false -- function(head) return head, false end + + usedmethod = original + + local function setmethod(method) + usedmethod = type(method) == "string" and methods[method] + if usedmethod == nil then + usedmethod = methods.tex + end + end + local function pushmethod(method) + insert(stack,usedmethod) + usedmethod = type(method) == "string" and methods[method] + if usedmethod == nil then + usedmethod = methods.tex + end + end + local function popmethod() + usedmethod = remove(stack) or methods.tex + end + + hyphenators.setmethod = setmethod + hyphenators.pushmethod = pushmethod + hyphenators.popmethod = popmethod + + directives.register("hyphenators.method",setmethod) + + function hyphenators.setup(specification) + local method = specification.method + if method then + setmethod(method) + end + end + + implement { name = "sethyphenationmethod", actions = setmethod, arguments = "string" } + implement { name = "pushhyphenation", actions = pushmethod, arguments = "string" } + implement { name = "pophyphenation", actions = popmethod } + + -- can become a runtime loaded one: + + local context = context + local ctx_NC = context.NC + local ctx_NR = context.NR + local ctx_verbatim = context.verbatim + + function hyphenators.showhyphenationtrace(language,word) + if not word or word == "" then + return + end + local saved = trace_steps + trace_steps = "silent" + local steps = traditional.gettrace(language,word) + trace_steps = saved + if steps then + local n = #steps + if n > 0 then + context.starttabulate { "|r|l|l|l|" } + for i=1,n do + local s = steps[i] + ctx_NC() if i > 1 and i < n then context(i-1) end + ctx_NC() ctx_verbatim(s[1]) + ctx_NC() ctx_verbatim(s[2]) + ctx_NC() ctx_verbatim(s[3]) + ctx_NC() + ctx_NR() + end + context.stoptabulate() + end + end + end + + implement { + name = "showhyphenationtrace", + actions = hyphenators.showhyphenationtrace, + arguments = "2 strings", + } + + function nodes.stripdiscretionaries(head) + for l in nexthlist, head do + for d in nextdisc, getlist(l) do + remove_node(h,false,true) + end + end + return head + end + + +else + + -- traditional.loadpatterns("nl","lang-nl") + -- traditional.loadpatterns("de","lang-de") + -- traditional.loadpatterns("us","lang-us") + + -- traditional.registerpattern("nl","e1ë", { start = 1, length = 2, before = "e", after = "e" } ) + -- traditional.registerpattern("nl","oo7ë", { start = 2, length = 3, before = "o", after = "e" } ) + -- traditional.registerpattern("de","qqxc9xkqq",{ start = 3, length = 4, before = "ab", after = "cd" } ) + + -- local specification = { + -- leftcharmin = 2, + -- rightcharmin = 2, + -- leftchar = "<", + -- rightchar = ">", + -- } + + -- print("reëel", traditional.injecthyphens(dictionaries.nl,"reëel", specification),"r{e>}{<e}{eë}el") + -- print("reeëel", traditional.injecthyphens(dictionaries.nl,"reeëel", specification),"re{e>}{<e}{eë}el") + -- print("rooëel", traditional.injecthyphens(dictionaries.nl,"rooëel", specification),"r{o>}{<e}{ooë}el") + + -- print( "qxcxkq", traditional.injecthyphens(dictionaries.de, "qxcxkq", specification),"") + -- print( "qqxcxkqq", traditional.injecthyphens(dictionaries.de, "qqxcxkqq", specification),"") + -- print( "qqqxcxkqqq", traditional.injecthyphens(dictionaries.de, "qqqxcxkqqq", specification),"") + -- print("qqqqxcxkqqqq",traditional.injecthyphens(dictionaries.de,"qqqqxcxkqqqq",specification),"") + + -- print("kunstmatig", traditional.injecthyphens(dictionaries.nl,"kunstmatig", specification),"") + -- print("kunststofmatig", traditional.injecthyphens(dictionaries.nl,"kunststofmatig", specification),"") + -- print("kunst[stof]matig", traditional.injecthyphens(dictionaries.nl,"kunst[stof]matig", specification),"") + + -- traditional.loadpatterns("us","lang-us") + + -- local specification = { + -- leftcharmin = 2, + -- rightcharmin = 2, + -- leftchar = false, + -- rightchar = false, + -- } + + -- trace_steps = true + + -- print("components", traditional.injecthyphens(dictionaries.us,"components", specification),"") + -- print("single", traditional.injecthyphens(dictionaries.us,"single", specification),"sin-gle") + -- print("everyday", traditional.injecthyphens(dictionaries.us,"everyday", specification),"every-day") + -- print("associate", traditional.injecthyphens(dictionaries.us,"associate", specification),"as-so-ciate") + -- print("philanthropic", traditional.injecthyphens(dictionaries.us,"philanthropic", specification),"phil-an-thropic") + -- print("projects", traditional.injecthyphens(dictionaries.us,"projects", specification),"projects") + -- print("Associate", traditional.injecthyphens(dictionaries.us,"Associate", specification),"As-so-ciate") + -- print("Philanthropic", traditional.injecthyphens(dictionaries.us,"Philanthropic", specification),"Phil-an-thropic") + -- print("Projects", traditional.injecthyphens(dictionaries.us,"Projects", specification),"Projects") + +end + diff --git a/tex/context/base/mkiv/lang-hyp.lua b/tex/context/base/mkiv/lang-hyp.lua index 93457c7a2..ca9f519ce 100644 --- a/tex/context/base/mkiv/lang-hyp.lua +++ b/tex/context/base/mkiv/lang-hyp.lua @@ -644,7 +644,7 @@ if context then local getprev = nuts.getprev local getsubtype = nuts.getsubtype local getlist = nuts.getlist - local getlang = nuts.getlang + local getlanguage = nuts.getlanguage local getattrlist = nuts.getattrlist local setattrlist = nuts.setattrlist local isglyph = nuts.isglyph @@ -1410,7 +1410,7 @@ featureset.hyphenonly = hyphenonly == v_yes if skipping then current = getnext(current) else - local lang = getlang(current) + local lang = getlanguage(current) local font = getfont(current) if lang ~= language or font ~= lastfont then if dictionary and size > charmin and leftmin + rightmin <= size then diff --git a/tex/context/base/mkiv/lang-hyp.mkiv b/tex/context/base/mkiv/lang-hyp.mkiv index fbd83fe0c..d8fbb0b22 100644 --- a/tex/context/base/mkiv/lang-hyp.mkiv +++ b/tex/context/base/mkiv/lang-hyp.mkiv @@ -30,8 +30,8 @@ \writestatus{loading}{ConTeXt Language Macros / Initialization} -\registerctxluafile{lang-dis}{} -\registerctxluafile{lang-hyp}{} +\registerctxluafile{lang-dis}{autosuffix} +\registerctxluafile{lang-hyp}{autosuffix} \unprotect @@ -152,7 +152,7 @@ rightedge {\dummyparameter\c!rightedge}% {\clf_sethyphenationfeatures{#1}} \unexpanded\def\resethyphenationfeatures - {\hyphenationattribute\attributeunsetvalue} + {\attribute\hyphenationattribute\attributeunsetvalue} \resethyphenationfeatures diff --git a/tex/context/base/mkiv/lang-ini.lmt b/tex/context/base/mkiv/lang-ini.lmt new file mode 100644 index 000000000..5f2dd1a55 --- /dev/null +++ b/tex/context/base/mkiv/lang-ini.lmt @@ -0,0 +1,670 @@ +if not modules then modules = { } end modules ['lang-ini'] = { + version = 1.001, + comment = "companion to lang-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- needs a cleanup (share locals) +-- discard language when redefined + +-- 002D : hyphen-minus (ascii) +-- 2010 : hyphen +-- 2011 : nonbreakable hyphen +-- 2013 : endash (compound hyphen) + +--~ language:hyphenation(string) string = language:hyphenation() language:clear_hyphenation() + +-- todo: no foo:bar but foo(bar,...) + +local type, tonumber, next = type, tonumber, next +local utfbyte = utf.byte +local format, gsub, gmatch, find = string.format, string.gsub, string.gmatch, string.find +local concat, sortedkeys, sortedpairs, keys, insert = table.concat, table.sortedkeys, table.sortedpairs, table.keys, table.insert +local utfvalues, strip, utfcharacters = string.utfvalues, string.strip, utf.characters + +local context = context +local commands = commands +local implement = interfaces.implement + +local settings_to_array = utilities.parsers.settings_to_array +local settings_to_set = utilities.parsers.settings_to_set + +local trace_patterns = false trackers.register("languages.patterns", function(v) trace_patterns = v end) + +local report_initialization = logs.reporter("languages","initialization") + +local prehyphenchar = language.prehyphenchar -- global per language +local posthyphenchar = language.posthyphenchar -- global per language +local preexhyphenchar = language.preexhyphenchar -- global per language +local postexhyphenchar = language.postexhyphenchar -- global per language +----- lefthyphenmin = language.lefthyphenmin +----- righthyphenmin = language.righthyphenmin +local sethjcode = language.sethjcode +local currentlanguage = language.current -- or function() return tex.normallanguage or tex.language end + +local uccodes = characters.uccodes +local lccodes = characters.lccodes + +local new_language = language.new + +languages = languages or {} +local languages = languages + +languages.version = 1.010 + +languages.registered = languages.registered or { } +local registered = languages.registered + +languages.associated = languages.associated or { } +local associated = languages.associated + +languages.numbers = languages.numbers or { } +local numbers = languages.numbers + +languages.data = languages.data or { } +local data = languages.data + +storage.register("languages/registered",registered,"languages.registered") +storage.register("languages/associated",associated,"languages.associated") +storage.register("languages/numbers", numbers, "languages.numbers") +storage.register("languages/data", data, "languages.data") + +local variables = interfaces.variables + +local v_reset = variables.reset +local v_yes = variables.yes + +local nofloaded = 0 + +local function resolve(tag) + local data, instance = registered[tag], nil + if data then + instance = data.instance + if not instance then + instance = new_language(data.number) + data.instance = instance + end + end + return data, instance +end + +local function tolang(what) -- returns lang object + if not what then + what = currentlanguage() + end + local tag = numbers[what] + local data = tag and registered[tag] or registered[what] + if data then + local instance = data.instance -- .lang -- was this ok ? + if not instance then + instance = new_language(data.number) + data.instance = instance + end + return instance + end +end + +function languages.getdata(tag) -- or number + if tag then + return registered[tag] or registered[numbers[tag]] + else + return registered[numbers[currentlanguage()]] + end +end + +-- languages.tolang = tolang + +-- patterns=en +-- patterns=en,de + +local function validdata(loaded,what,tag) + local dataset = loaded[what] + if dataset then + local data = dataset.data + if not data or data == "" then + -- nothing + elseif dataset.compression == "zlib" then + data = zlib.decompress(data) + if dataset.length and dataset.length ~= #data then + report_initialization("compression error in %a for language %a","patterns",what,tag) + end + return data + else + return data + end + end +end + +-- languages.hjcounts[unicode].count + +-- hjcode: 0 not to be hyphenated +-- 1--31 length +-- 32 zero length +-- > 32 hyphenated with length 1 + +local function sethjcodes(instance,loaded,what,factor) + local l = loaded[what] + local c = l and l.characters + if c then + local hjcounts = factor and languages.hjcounts or false + -- + local h = loaded.codehash + if not h then + h = { } + loaded.codehash = h + end + -- + local function setcode(l) + local u = uccodes[l] + local s = l + if hjcounts then + local c = hjcounts[l] + if c then + c = c.count + if not c then + -- error, keep as 1 + elseif c <= 0 then + -- counts as 0 i.e. ignored + s = 32 + elseif c >= 31 then + -- counts as 31 + s = 31 + else + -- count c times + s = c + end + end + end + sethjcode(instance,l,s) + h[l] = s + if u ~= l and type(u) == "number" then + sethjcode(instance,u,s) + h[u] = lccodes[l] + end + end + -- + local s = tex.savinghyphcodes + tex.savinghyphcodes = 0 + if type(c) == "table" then + for l in next, c do + setcode(utfbyte(l)) + end + else + for l in utfvalues(c) do + setcode(l) + end + end + tex.savinghyphcodes = s + end +end + +-- 2'2 conflicts with 4' ... and luatex barks on it + +local P, R, Cs, Ct, lpegmatch, lpegpatterns = lpeg.P, lpeg.R, lpeg.Cs, lpeg.Ct, lpeg.match, lpeg.patterns + +local utfsplit = utf.split + +local space = lpegpatterns.space +local whitespace = lpegpatterns.whitespace^1 +local nospace = lpegpatterns.utf8char - whitespace +local digit = lpegpatterns.digit +----- endofstring = #whitespace + P(-1) +local endofstring = #whitespace + +local word = (digit/"")^0 * (digit/"" * endofstring + digit/" " + nospace)^1 +local anyword = (1-whitespace)^1 +local analyze = Ct((whitespace + Cs(word))^1) + +local function unique(tag,requested,loaded) + local nofloaded = #loaded + if nofloaded == 0 then + return "" + elseif nofloaded == 1 then + return loaded[1] + else + insert(loaded,1," ") -- no need then for special first word + -- insert(loaded, " ") + loaded = concat(loaded," ") + local t = lpegmatch(analyze,loaded) or { } + local h = { } + local b = { } + for i=1,#t do + local ti = t[i] + local hi = h[ti] + if not hi then + h[ti] = 1 + elseif hi == 1 then + h[ti] = 2 + b[#b+1] = utfsplit(ti," ") + end + end + -- sort + local nofbad = #b + if nofbad > 0 then + local word + for i=1,nofbad do + local bi = b[i] + local p = P(bi[1]) + for i=2,#bi do + p = p * digit * P(bi[i]) + end + if word then + word = word + p + else + word = p + end + report_initialization("language %a, patterns %a, discarding conflict (0-9)%{[0-9]}t(0-9)",tag,requested,bi) + end + t, h, b = nil, nil, nil -- permit gc + local someword = digit^0 * word * digit^0 * endofstring / "" + -- local strip = Cs(someword^-1 * (someword + anyword + whitespace)^1) + local strip = Cs((someword + anyword + whitespace)^1) + return lpegmatch(strip,loaded) or loaded + else + return loaded + end + end +end + +local shared = false + +local function loaddefinitions(tag,specification) + statistics.starttiming(languages) + local data, instance = resolve(tag) + local requested = specification.patterns or "" + local definitions = settings_to_array(requested) + if #definitions > 0 then + if trace_patterns then + report_initialization("pattern specification for language %a: %s",tag,specification.patterns) + end + local ploaded = instance:patterns() + local eloaded = instance:hyphenation() + if not ploaded or ploaded == "" then + ploaded = { } + else + ploaded = { ploaded } + end + if not eloaded or eloaded == "" then + eloaded = { } + else + eloaded = { eloaded } + end + local dataused = data.used + local ok = false + local resources = data.resources or { } + data.resources = resources + if not shared then + local found = resolvers.findfile("lang-exc.lua") + if found then + shared = dofile(found) + if type(shared) == "table" then + shared = concat(shared," ") + else + shared = true + end + else + shared = true + end + end + for i=1,#definitions do + local definition = definitions[i] + if definition == "" then + -- error + elseif definition == v_reset then + if trace_patterns then + report_initialization("clearing patterns for language %a",tag) + end + instance:clear_patterns() + instance:clear_hyphenation() + ploaded = { } + eloaded = { } + elseif not dataused[definition] then + dataused[definition] = definition + local filename = "lang-" .. definition .. ".lua" + local fullname = resolvers.findfile(filename) or "" + if fullname == "" then + fullname = resolvers.findfile(filename .. ".gz") or "" + end + if fullname ~= "" then + if trace_patterns then + report_initialization("loading definition %a for language %a from %a",definition,tag,fullname) + end + local suffix, gzipped = gzip.suffix(fullname) + local loaded = table.load(fullname,gzipped and gzip.load) + if loaded then -- todo: version test + ok, nofloaded = true, nofloaded + 1 + sethjcodes(instance,loaded,"patterns",specification.factor) + sethjcodes(instance,loaded,"exceptions",specification.factor) + local p = validdata(loaded,"patterns",tag) + local e = validdata(loaded,"exceptions",tag) + if p and p ~= "" then + ploaded[#ploaded+1] = p + end + if e and e ~= "" then + eloaded[#eloaded+1] = e + end + resources[#resources+1] = loaded -- so we can use them otherwise + else + report_initialization("invalid definition %a for language %a in %a",definition,tag,filename) + end + elseif trace_patterns then + report_initialization("invalid definition %a for language %a in %a",definition,tag,filename) + end + elseif trace_patterns then + report_initialization("definition %a for language %a already loaded",definition,tag) + end + end + if #ploaded > 0 then + -- why not always clear + instance:clear_patterns() + instance:patterns(unique(tag,requested,ploaded)) + end + if #eloaded > 0 then + -- why not always clear + instance:clear_hyphenation() + instance:hyphenation(concat(eloaded," ")) + end + if type(shared) == "string" then + instance:hyphenation(shared) + end + return ok + elseif trace_patterns then + report_initialization("no definitions for language %a",tag) + end + statistics.stoptiming(languages) +end + +storage.shared.noflanguages = storage.shared.noflanguages or 0 + +local noflanguages = storage.shared.noflanguages + +function languages.define(tag,parent) + noflanguages = noflanguages + 1 + if trace_patterns then + report_initialization("assigning number %a to %a",noflanguages,tag) + end + numbers[noflanguages] = tag + registered[tag] = { + tag = tag, + parent = parent or "", + patterns = "", + loaded = false, + used = { }, + dirty = true, + number = noflanguages, + instance = nil, -- luatex data structure + synonyms = { }, + } + storage.shared.noflanguages = noflanguages +end + +function languages.setsynonym(synonym,tag) -- convenience function + local l = registered[tag] + if l then + l.synonyms[synonym] = true -- maybe some day more info + end +end + +function languages.installed(separator) + return concat(sortedkeys(registered),separator or ",") +end + +function languages.current(n) + return numbers[n and tonumber(n) or currentlanguage()] +end + +function languages.associate(tag,script,language) -- not yet used + associated[tag] = { script, language } +end + +function languages.association(tag) -- not yet used + if not tag then + tag = numbers[currentlanguage()] + elseif type(tag) == "number" then + tag = numbers[tag] + end + local lat = tag and associated[tag] + if lat then + return lat[1], lat[2] + end +end + +function languages.loadable(tag,defaultlanguage) -- hack + local l = registered[tag] -- no synonyms + if l and resolvers.findfile("lang-"..l.patterns..".lua") then + return true + else + return false + end +end + +-- a bit messy, we will do all language setting in lua as we can now assign +-- and 'patterns' will go away here. + +function languages.unload(tag) + local l = registered[tag] + if l then + l.dirty = true + end +end + +if environment.initex then + + function languages.getnumber() + return 0 + end + +else + + function languages.getnumber(tag,default,patterns,factor) + local l = registered[tag] + if l then + if l.dirty then + l.factor = factor == v_yes and true or false + if trace_patterns then + report_initialization("checking patterns for %a with default %a",tag,default) + end + -- patterns is already resolved to parent patterns if applicable + if patterns and patterns ~= "" then + if l.patterns ~= patterns then + l.patterns = patterns + if trace_patterns then + report_initialization("loading patterns for %a using specification %a",tag,patterns) + end + loaddefinitions(tag,l) + else + -- unchanged + end + elseif l.patterns == "" then + l.patterns = tag + if trace_patterns then + report_initialization("loading patterns for %a using tag",tag) + end + local ok = loaddefinitions(tag,l) + if not ok and tag ~= default then + l.patterns = default + if trace_patterns then + report_initialization("loading patterns for %a using default",tag) + end + loaddefinitions(tag,l) + end + end + l.loaded = true + l.dirty = false + end + return l.number + else + return 0 + end + end + + numbers[0] = "null" + + registered.null = { + number = 0, + instance = new_language(0), + } + +end + +-- not that usefull, global values + +function languages.prehyphenchar (what) return prehyphenchar (tolang(what)) end +function languages.posthyphenchar (what) return posthyphenchar (tolang(what)) end +function languages.preexhyphenchar (what) return preexhyphenchar (tolang(what)) end +function languages.postexhyphenchar(what) return postexhyphenchar(tolang(what)) end +-------- languages.lefthyphenmin (what) return lefthyphenmin (tolang(what)) end +-------- languages.righthyphenmin (what) return righthyphenmin (tolang(what)) end + +-- e['implementer']= 'imple{m}{-}{-}menter' +-- e['manual'] = 'man{}{}{}' +-- e['as'] = 'a-s' +-- e['user-friendly'] = 'user=friend-ly' +-- e['exceptionally-friendly'] = 'excep-tionally=friend-ly' + +local invalid = { "{", "}", "-" } + +local function collecthjcodes(data,str) + local found = data.extras and data.extras.characters or { } + for s in utfcharacters(str) do + if not found[s] then + found[s] = true + end + end + for i=1,#invalid do -- less checks this way + local c = invalid[i] + if found[c] then + found[c] = nil + end + end + data.extras = { characters = found } + sethjcodes(data.instance,data,"extras",data.factor) +end + +function languages.loadwords(tag,filename) + local data, instance = resolve(tag) + if data then + statistics.starttiming(languages) + local str = io.loaddata(filename) or "" + collecthjcodes(data,str) + instance:hyphenation(str) + statistics.stoptiming(languages) + end +end + + +function languages.setexceptions(tag,str) + local data, instance = resolve(tag) + if data then + str = strip(str) -- we need to strip leading spaces + collecthjcodes(data,str) + instance:hyphenation(str) + end +end + +function languages.hyphenate(tag,str) + -- todo: does this still work? + local data, instance = resolve(tag) + if data then + return instance:hyphenate(str) + else + return str + end +end + +-- hyphenation.define ("zerolanguage") +-- hyphenation.loadpatterns ("zerolanguage") -- else bug +-- hyphenation.loadexceptions("zerolanguage") -- else bug + +languages.logger = languages.logger or { } + +function languages.logger.report() + local result, r = { }, 0 + for tag, l in sortedpairs(registered) do + if l.loaded then + r = r + 1 + result[r] = format("%s:%s:%s",tag,l.parent,l.number) + end + end + return r > 0 and concat(result," ") or "none" +end + +-- must happen at the tex end .. will use lang-def.lua + +languages.associate('en','latn','eng') +languages.associate('uk','latn','eng') +languages.associate('nl','latn','nld') +languages.associate('de','latn','deu') +languages.associate('fr','latn','fra') + +statistics.register("loaded patterns", function() + local result = languages.logger.report() + if result ~= "none" then + -- return result + return format("%s, load time: %s",result,statistics.elapsedtime(languages)) + end +end) + +-- statistics.register("language load time", function() +-- -- often zero so we can merge that in the above +-- return statistics.elapsedseconds(languages, format(", nofpatterns: %s",nofloaded)) +-- end) + +-- interface + +implement { + name = "languagenumber", + actions = { languages.getnumber, context }, + arguments = "4 strings" +} + +implement { + name = "installedlanguages", + actions = { languages.installed, context }, +} + +implement { + name = "definelanguage", + actions = languages.define, + arguments = "2 strings" +} + +implement { + name = "setlanguagesynonym", + actions = languages.setsynonym, + arguments = "2 strings" +} + +implement { + name = "unloadlanguage", + actions = languages.unload, + arguments = "string" +} + +implement { + name = "setlanguageexceptions", + actions = languages.setexceptions, + arguments = "2 strings" +} + +implement { + name = "currentprehyphenchar", + actions = function() + local c = prehyphenchar(tolang()) + if c and c > 0 then + context.char(c) + end + end +} + +implement { + name = "currentposthyphenchar", + actions = function() + local c = posthyphenchar(tolang()) + if c and c > 0 then + context.char(c) + end + end +} diff --git a/tex/context/base/mkiv/lang-ini.lua b/tex/context/base/mkiv/lang-ini.lua index ac5b2c113..7a8aab818 100644 --- a/tex/context/base/mkiv/lang-ini.lua +++ b/tex/context/base/mkiv/lang-ini.lua @@ -48,7 +48,6 @@ local sethjcode = lang.sethjcode local uccodes = characters.uccodes local lccodes = characters.lccodes -lang.exceptions = lang.hyphenation local new_language = lang.new languages = languages or {} diff --git a/tex/context/base/mkiv/lang-ini.mkxl b/tex/context/base/mkiv/lang-ini.mkxl index f5831a5ea..6d0649fa8 100644 --- a/tex/context/base/mkiv/lang-ini.mkxl +++ b/tex/context/base/mkiv/lang-ini.mkxl @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -%D This module needs a further cleanup (real split between ii/iv). +% We can protect \currentlanguage etc too. % \cldcontext{languages.numbers[tex.count.mainlanguagenumber]} @@ -22,7 +22,7 @@ \writestatus{loading}{ConTeXt Language Macros / Initialization} -\registerctxluafile{lang-ini}{} +\registerctxluafile{lang-ini}{autosuffix} \registerctxluafile{lang-def}{} \registerctxluafile{lang-cnt}{} @@ -74,14 +74,14 @@ \def\currentusedlanguage{\currentlanguage} -\def\defaultlanguage#1% +\permanent\def\defaultlanguage#1% {\ifcsname\??language#1\s!default\endcsname \expandafter\defaultlanguage\lastnamedcs \else #1% \fi} -\def\languageparameter#1% +\permanent\def\languageparameter#1% {\ifcsname\??language\currentlanguage#1\endcsname \lastnamedcs \orelse\ifcsname\??language\currentlanguage\s!default\endcsname @@ -90,7 +90,7 @@ \lastnamedcs \fi} -\def\specificlanguageparameter#1#2% +\permanent\def\specificlanguageparameter#1#2% {\ifcsname\??language#1#2\endcsname \lastnamedcs \orelse\ifcsname\??language#1\s!default\endcsname @@ -99,7 +99,7 @@ \lastnamedcs \fi} -\def\mainlanguageparameter#1% +\permanent\def\mainlanguageparameter#1% {\ifcsname\??language\currentmainlanguage#1\endcsname \lastnamedcs \orelse\ifcsname\??language\currentmainlanguage\s!default\endcsname @@ -108,9 +108,9 @@ \lastnamedcs \fi} -\let\usedlanguageparameter\languageparameter +\aliased\let\usedlanguageparameter\languageparameter -\def\askedlanguageparameter#1% assumes \currentusedlanguage being set +\permanent\def\askedlanguageparameter#1% assumes \currentusedlanguage being set {\ifcsname\??language\currentusedlanguage#1\endcsname \lastnamedcs \orelse\ifcsname\??language\currentusedlanguage\s!default\endcsname @@ -119,25 +119,25 @@ \lastnamedcs \fi} -\unexpanded\def\setusedlanguage#1% +\permanent\protected\def\setusedlanguage#1% {\edef\currentusedlanguage{\reallanguagetag{#1}}% \ifempty\currentusedlanguage \let\currentusedlanguage \currentlanguage - \let\usedlanguageparameter\languageparameter + \enforced\let\usedlanguageparameter\languageparameter \orelse\ifx\currentusedlanguage\v!global \let\currentusedlanguage \currentmainlanguage - \let\usedlanguageparameter\mainlanguageparameter + \enforced\let\usedlanguageparameter\mainlanguageparameter \orelse\ifx\currentusedlanguage\v!local \let\currentusedlanguage \currentlanguage - \let\usedlanguageparameter\languageparameter + \enforced\let\usedlanguageparameter\languageparameter \else - \let\usedlanguageparameter\askedlanguageparameter + \enforced\let\usedlanguageparameter\askedlanguageparameter \fi} -\unexpanded\def\setupcurrentlanguage[#1]% +\permanent\protected\def\setupcurrentlanguage[#1]% {\setcurrentlanguage\currentmainlanguage{#1}} -\unexpanded\def\setcurrentlanguage#1#2% sets modes: **id (currentmain) *id (current) +\permanent\protected\def\setcurrentlanguage#1#2% sets modes: **id (currentmain) *id (current) {\edef\xaskedlanguage{#1}% otherwise clash with \askedlanguage \ifempty\xaskedlanguage \else \ifempty\currentmainlanguage\else\resetsystemmode{\systemmodeprefix\currentmainlanguage}\fi @@ -176,9 +176,9 @@ \newtoks \everysetuplanguage -\def\installedlanguages{\clf_installedlanguages} +\aliased\let\installedlanguages\clf_installedlanguages % no need for \clf_ -\unexpanded\def\doifelselanguage#1% +\permanent\protected\def\doifelselanguage#1% {\ifcsname\??language#1\c!state\endcsname \expandafter\firstoftwoarguments \else @@ -187,15 +187,12 @@ \let\doiflanguageelse\doifelselanguage -\def\reallanguagetag#1% +\permanent\def\reallanguagetag#1% {\ifcsname\??languagelinked#1\endcsname\lastnamedcs\else#1\fi} % \language[#1] gave unwanted side effect of loading language specifics -\unexpanded\def\installlanguage - {\dodoubleargument\lang_basics_install} - -\def\lang_basics_install[#1][#2]% +\permanent\tolerant\protected\def\installlanguage[#1]#*[#2]% {\ifcondition\validassignment{#2}% \doifelselanguage{#1} {\getparameters[\??language#1][#2]} @@ -218,7 +215,7 @@ %D feature is present because we used dutch mnemonics in the dutch version, but %D nowadays conform a standard. -\unexpanded\def\doifelsepatterns#1% +\permanent\protected\def\doifelsepatterns#1% {\begingroup % will change \lang_basics_set_current[#1]% \ifnum\normallanguage>\zerocount @@ -227,7 +224,7 @@ \endgroup\expandafter\secondoftwoarguments \fi} -\let\doifpatternselse\doifelsepatterns +\aliased\let\doifpatternselse\doifelsepatterns %D \macros %D {setuplanguage} @@ -238,27 +235,26 @@ %D %D Beware, this command can only be used when a language is installed. -\unexpanded\def\setuplanguage - {\dodoubleempty\lang_basics_setup} - \ifdefined\lang_basics_synchronize \else \let\lang_basics_synchronize\relax % be nice for setups till we have one \fi \installmacrostack\currentlanguage -\def\lang_basics_setup[#1][#2]% - {\ifsecondargument +\permanent\tolerant\protected\def\setuplanguage[#1]#*[#2]% + {\ifarguments + % only synchronize + \or + \let\currentsetuplanguage\currentlanguage + \getparameters[\??language\currentsetuplanguage][#1]% + \the\everysetuplanguage + \or \push_macro_currentlanguage % can be default \edef\currentsetuplanguage{\reallanguagetag{#1}}% \getparameters[\??language\currentsetuplanguage][#2]% \the\everysetuplanguage \pop_macro_currentlanguage %\doif\currentsetuplanguage\currentlanguage we can have influenced inheritance (default) - \else - \let\currentsetuplanguage\currentlanguage - \getparameters[\??language\currentsetuplanguage][#1]% - \the\everysetuplanguage \fi \lang_basics_synchronize} @@ -316,8 +312,8 @@ %D %D Just to make things easy we can ask for the current date specification by saying: -\def\currentdatespecification{\languageparameter\c!date} -\def\currenttimespecification{\languageparameter\c!time} +\permanent\def\currentdatespecification{\languageparameter\c!date} +\permanent\def\currenttimespecification{\languageparameter\c!time} %D Carefull reading of these macros shows that it's legal to say %D @@ -398,9 +394,9 @@ % This is the old implementation: a hack that sets the min values, because we want % to keep the language set: % -% \unexpanded\def\nohyphens % nicer for url's +% \protected\def\nohyphens % nicer for url's % {\ifx\dohyphens\relax -% \unexpanded\edef\dohyphens +% \protected\edef\dohyphens % {\hyphenminoffset\the\hyphenminoffset\relax % \lang_basics_synchronize_min_max}% % \fi @@ -433,10 +429,10 @@ + \permitmathreplacehyphenationmodecode % and again we're more permissive \relax -\unexpanded\def\dohyphens{\hyphenationmode\completehyphenationmodecode} -\unexpanded\def\nohyphens{\hyphenationmode\zerocount} +\permanent\protected\def\dohyphens{\hyphenationmode\completehyphenationmodecode} +\permanent\protected\def\nohyphens{\hyphenationmode\zerocount} -\unexpanded\def\usehyphensparameter#1% +\permanent\protected\def\usehyphensparameter#1% {\edef\p_hyphens{#1\c!hyphens}% \ifx\p_hyhens\v!no \nohyphens @@ -446,17 +442,17 @@ %D The rest stays the same as in mkiv: -\unexpanded\def\lesshyphens +\permanent\protected\def\lesshyphens {\advance\hyphenminoffset\plusone \lang_basics_synchronize_min_max} -\unexpanded\def\morehyphens +\permanent\protected\def\morehyphens {\ifcase\hyphenminoffset \else \advance\hyphenminoffset\minusone \fi \lang_basics_synchronize_min_max} -\unexpanded\def\lang_basics_synchronize_min_max % maybe store this at the lua end +\protected\def\lang_basics_synchronize_min_max % maybe store this at the lua end {% these values are stored along with glyph nodes \lefthyphenmin \numexpr0\languageparameter\s!lefthyphenmin +\hyphenminoffset\relax \righthyphenmin\numexpr0\languageparameter\s!righthyphenmin+\hyphenminoffset\relax @@ -469,7 +465,7 @@ \lang_basics_synchronize_min_max \to \everylanguage -\unexpanded\def\unhyphenated +\permanent\protected\def\unhyphenated {\groupedcommand{\lefthyphenmin\maxdimen}\donothing} % \appendtoks @@ -509,7 +505,7 @@ % new experimental feature -\unexpanded\def\setuplanguages +\permanent\protected\def\setuplanguages {\setuplanguage[\s!default]} % \setuplanguages[\c!font=\v!auto] @@ -537,36 +533,40 @@ \fi \fi} -\unexpanded\def\uselanguageparameter#1% +\protected\def\uselanguageparameter#1% {\edef\askedlanguage{#1\c!language}% \ifempty\askedlanguage\else\lang_basics_switch_asked\fi} -\unexpanded\def\douselanguageparameter#1% fast setter +\protected\def\douselanguageparameter#1% fast setter {\edef\askedlanguage{#1}% \ifempty\askedlanguage\else\lang_basics_switch_asked\fi} -\unexpanded\def\lang_basics_set_current[#1]% +\protected\def\lang_basics_set_current[#1]% {\edef\askedlanguage{#1}% \ifempty\askedlanguage\else\lang_basics_switch_asked\fi} -\unexpanded\def\language - {\doifelsenextoptionalcs\lang_basics_set_current\normallanguage} +\pushoverloadmode -\let\setlanguage\language % we make these synonyms + \permanent\protected\def\language + {\doifelsenextoptionalcs\lang_basics_set_current\normallanguage} -\let\patterns\gobbleoneargument + \let\setlanguage\language % we make these synonyms + + \let\patterns\gobbleoneargument + +\popoverloadmode \newcount\mainlanguagenumber %D Beware: you might need to use \type {\dontleavehmode} outside and|/|or \type {\par} %D inside the group! -\unexpanded\def\startlanguage +\permanent\protected\def\startlanguage {\begingroup\language} -\let\stoplanguage\endgroup +\permanent\let\stoplanguage\endgroup -\unexpanded\def\mainlanguage[#1]% +\permanent\protected\def\mainlanguage[#1]% {\edef\askedlanguage{#1}% \ifempty\askedlanguage \orelse\ifcsname\??languagelinked\askedlanguage\endcsname @@ -590,10 +590,10 @@ %D Used at all? -\def\splitsequence#1#2% +\permanent\def\splitsequence#1#2% {\doifelse{#1}\v!no{#2}{\doifelse{#1}\v!yes{\languageparameter\c!limittext}{#1}}} -\def\splitsymbol#1% +\permanent\def\splitsymbol#1% {\splitsequence{#1}{\languageparameter\c!limittext}} %D Just like with subsentence boundary symbols, quotes placement depends on the @@ -704,25 +704,22 @@ %D \stoptable %D \protect -\unexpanded\def\nopatterns{\normallanguage\minusone} +\permanent\protected\def\nopatterns{\normallanguage\minusone} %D We default to the language belonging to the interface. This is one of the few %D places outside the interface modules where \type {\startinterface} is used. \setupcurrentlanguage[\s!en] -\unexpanded\def\initializemainlanguage +\permanent\protected\def\initializemainlanguage {\mainlanguage[\currentlanguage]% \showmessage\m!languages9\currentlanguage} %D New: -\let\stopexceptions\relax +\permanent\let\stopexceptions\relax -\unexpanded\def\startexceptions - {\dosingleempty\lang_basics_start_exceptions} - -\def\lang_basics_start_exceptions[#1]#2\stopexceptions % multilingual or not? +\tolerant\permanent\protected\def\startexceptions[#1]#:#2\stopexceptions {\begingroup \edef\askedlanguage{\reallanguagetag{#1}}% \ifempty\askedlanguage @@ -731,26 +728,38 @@ \clf_setlanguageexceptions{\askedlanguage}{#2}% \endgroup} -\unexpanded\def\hyphenation +\pushoverloadmode + +\permanent\protected\def\hyphenation {\clf_setlanguageexceptions{\currentlanguage}} +\popoverloadmode + %D New: -\unexpanded\def\traceddiscretionary#1#% +\permanent\protected\def\traceddiscretionary#1#% {\dontleavehmode\lang_basics_traced_discretionary{#1}} -\unexpanded\def\lang_basics_traced_discretionary#1#2#3#4% +\protected\def\lang_basics_traced_discretionary#1#2#3#4% {\normaldiscretionary#1{\darkred#2}{\darkgreen#3}{\darkblue#4}} \installtextracker {discretionaries} - {\let\discretionary\traceddiscretionary} - {\let\discretionary\normaldiscretionary} + {\enforced\let\discretionary\traceddiscretionary} + {\enforced\let\discretionary\normaldiscretionary} -\unexpanded\def\samplediscretionary +\permanent\protected\def\samplediscretionary {\traceddiscretionary {pre\clf_currentprehyphenchar}% {\clf_currentposthyphenchar post}% {replace}} +%D Also new: + +\immutable\chardef\nokerningcode \numexpr\noleftkerncode +\norightkerncode \relax +\immutable\chardef\noligaturingcode\numexpr\noleftligaturecode+\norightligaturecode\relax + +\permanent\protected\def\nokerning {\bitwiseflip\glyphoptions\nokerningcode} +\permanent\protected\def\noligaturing{\bitwiseflip\glyphoptions\noligaturingcode} + \protect \endinput diff --git a/tex/context/base/mkiv/lang-lab.mkxl b/tex/context/base/mkiv/lang-lab.mkxl index bf503c069..d627e5a42 100644 --- a/tex/context/base/mkiv/lang-lab.mkxl +++ b/tex/context/base/mkiv/lang-lab.mkxl @@ -21,7 +21,7 @@ %D Left-overs: \ifdefined\sixperemspace \else - \def\sixperemspace{\normalUchar"2006} + \permanent\def\sixperemspace{\normalUchar"2006} \fi %D In this module we deal with language dependant labels and prefixes, like in {\em @@ -62,14 +62,11 @@ \let\currentlabelcategory\empty -\unexpanded\def\definelabelclass - {\dodoubleempty\lang_labels_define_class} - -\def\lang_labels_define_class[#1][#2]% +\permanent\tolerant\protected\def\definelabelclass[#1]#*[#2]% {\normalexpanded {\lang_labels_define_class_indeed {#1}% - {\ifsecondargument#2\else\zerocount\fi}% + {\ifchknum#2\or#2\else\zerocount\fi}% \expandafter\noexpand\csname dogetupsome#1text\endcsname \expandafter\noexpand\csname #1language\endcsname \expandafter\noexpand\csname dodogetupsome#1text\endcsname @@ -82,11 +79,11 @@ \let\thetextprefix\empty -\unexpanded\def\lang_labels_define_class_indeed#1#2#3#4#5#6#7#8#9% - {\setuvalue{setup#1text}{\protecttextprefixes#2\def\currenttextprefixclass{#1}\dodoubleempty\lang_labels_text_prefix_setup}% - \setuvalue{preset#1text}{\protecttextprefixes1\def\currenttextprefixclass{#1}\dodoubleempty\lang_labels_text_prefix_setup}% - \setuvalue{copy#1text}{\protecttextprefixes1\def\currenttextprefixclass{#1}\dodoubleempty\lang_labels_text_prefix_copy}% - \setuvalue{start#1text}{\protecttextprefixes1\def\currenttextprefixclass{#1}\dotripleempty\lang_labels_text_prefix_start[#1]}% +\protected\def\lang_labels_define_class_indeed#1#2#3#4#5#6#7#8#9% + {\setuvalue {setup#1text}{\protecttextprefixes#2\def\currenttextprefixclass{#1}\lang_labels_text_prefix_setup}% + \setuvalue{preset#1text}{\protecttextprefixes 1\def\currenttextprefixclass{#1}\lang_labels_text_prefix_setup}% + \setuvalue {copy#1text}{\protecttextprefixes 1\def\currenttextprefixclass{#1}\lang_labels_text_prefix_copy }% + \setuvalue {start#1text}{\protecttextprefixes 1\def\currenttextprefixclass{#1}\lang_labels_text_prefix_start[#1]}% \letvalue{stop#1text}\relax \def#4{\reallanguagetag{\defaultlanguage\currentmainlanguage}}% \ifnum#2=\plustwo % used for math and tags @@ -117,27 +114,27 @@ \let#8\gobbletwoarguments \let#9#3% \else - \unexpanded\def#3{#5#4}% - \unexpanded\def#5##1##2% + \protected\def#3{#5#4}% + \protected\def#5##1##2% {\ifcsname\??label#1:##1:##2\endcsname %\expandafter\let\expandafter\thetextprefix\csname\??label#1:##1:##2\endcsname - \expandafter\let\expandafter\thetextprefix\lastnamedcs + \enforced\expandafter\let\expandafter\thetextprefix\lastnamedcs \orelse\ifcsname\??language#4\s!default\endcsname %\expandafter#5\csname\??language#4\s!default\endcsname{##2}% \expandafter#5\lastnamedcs{##2}% \orelse\ifcsname\??label#1:##2\endcsname %\expandafter\let\expandafter\thetextprefix\csname\??label#1:##2\endcsname - \expandafter\let\expandafter\thetextprefix\lastnamedcs + \enforced\expandafter\let\expandafter\thetextprefix\lastnamedcs \orelse\ifcsname\??label#1:\s!en:##2\endcsname %\expandafter\let\expandafter\thetextprefix\csname\??label#1:\s!en:##2\endcsname - \expandafter\let\expandafter\thetextprefix\lastnamedcs + \enforced\expandafter\let\expandafter\thetextprefix\lastnamedcs \else - \let\thetextprefix\dummytextprefix + \enforced\let\thetextprefix\dummytextprefix \fi}% - \unexpanded\def#6##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}% - \unexpanded\def#7##1{#3{##1}\expandafter\flushrightlabelclass\thetextprefix}% - \unexpanded\def#8##1{#3{##1}\expandafter\flushbothlabelclass \thetextprefix}% #2 - \unexpanded\def#9##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}% + \protected\def#6##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}% + \protected\def#7##1{#3{##1}\expandafter\flushrightlabelclass\thetextprefix}% + \protected\def#8##1{#3{##1}\expandafter\flushbothlabelclass \thetextprefix}% #2 + \protected\def#9##1{#3{##1}\expandafter\flushleftlabelclass \thetextprefix}% \fi \appendtoks \let#6\firstofoneargument % to be checked @@ -146,10 +143,14 @@ \let#9\firstofoneargument % to be checked \to \everysimplifycommands} +% why not lang_* ? + \let\flushleftlabelclass \firstoftwoarguments \let\flushrightlabelclass\secondoftwoarguments -\def\flushbothlabelclass #1#2#3{#1#3#2} -\def\dummytextprefix {\empty\empty} + +\permanent\def\flushbothlabelclass#1#2#3{#1#3#2} + +\permanent\def\dummytextprefix{\empty\empty} %D \macros %D {headtext, labeltext, leftlabeltext, rightlabeltext, labeltexts} @@ -172,13 +173,13 @@ \let\currenttextprefixtag \s!unknown \let\currenttextprefixclass\s!unknown -\def\lang_labels_text_prefix_start[#1][#2][#3]% class language name - {\ifthirdargument - \edef\currenttextprefixtag{\reallanguagetag{#2}}% - \edef\currenttextprefixname{#3}% - \else +\tolerant\def\lang_labels_text_prefix_start[#1]#*[#2]#*[#3]% class language name + {\ifarguments\or\or \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}% \edef\currenttextprefixname{#2}% + \else + \edef\currenttextprefixtag{\reallanguagetag{#2}}% + \edef\currenttextprefixname{#3}% \fi \grabuntil{stop#1text}\lang_labels_text_prefix_start_indeed} @@ -186,13 +187,13 @@ {\expandafter\edef\csname\??label\currenttextprefixclass:\currenttextprefixtag:\currenttextprefixname\endcsname% {{\clf_strip{#1}}\empty}} -\def\lang_labels_text_prefix_setup[#1][#2]% - {\ifsecondargument - \edef\currenttextprefixtag{\reallanguagetag{#1}}% - \processcommalist[#2]\lang_labels_text_prefix_setup_indeed - \else +\tolerant\def\lang_labels_text_prefix_setup[#1]#*[#2]% + {\ifarguments\or \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}% \processcommalist[#1]\lang_labels_text_prefix_setup_indeed + \else + \edef\currenttextprefixtag{\reallanguagetag{#1}}% + \processcommalist[#2]\lang_labels_text_prefix_setup_indeed \fi} \def\lang_labels_text_prefix_setup_indeed#1% @@ -240,17 +241,17 @@ \def\lang_labels_text_prefix_assign_dumb#1[#2,#3]% {\expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{#2}} -\unexpanded\def\setlabeltextpair#1#2#3#4#5% a fast one for usage at the Lua end +\permanent\protected\def\setlabeltextpair#1#2#3#4#5% a fast one for usage at the Lua end {%\writestatus{!!!!}{#1:\reallanguagetag{#2}:#3}% \expandafter\def\csname\??label#1:\reallanguagetag{#2}:#3\endcsname{{#4}{#5}}} % class tag key left right -\def\lang_labels_text_prefix_copy[#1][#2]% - {\ifsecondargument - \edef\currenttextprefixtag{\reallanguagetag{#1}}% - \processcommalist[#2]\lang_labels_text_prefix_copy_indeed - \else +\tolerant\def\lang_labels_text_prefix_copy[#1]#*[#2]% + {\ifarguments\or \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}% \processcommalist[#1]\lang_labels_text_prefix_copy_indeed + \else + \edef\currenttextprefixtag{\reallanguagetag{#1}}% + \processcommalist[#2]\lang_labels_text_prefix_copy_indeed \fi} \def\lang_labels_text_prefix_copy_indeed#1% @@ -298,10 +299,7 @@ \installcorenamespace{translation} -\unexpanded\def\translate - {\dosingleempty\lang_translate} - -\def\lang_translate[#1]% +\permanent\tolerant\protected\def\translate[#1]% {\getparameters[\??translation][#1]% \ifcsname\??translation\currentlanguage\endcsname \lastnamedcs @@ -328,7 +326,9 @@ %D \assigntranslation[en=something,nl=iets]\to\command %D \stoptyping -\unexpanded\def\assigntranslation[#1]\to#2% bad, this \to +% nicer is \edef\command{\translated[...]} ... todo + +\permanent\protected\def\assigntranslation[#1]\to#2% bad, this \to {\getparameters[\??translation][#1]% \edef#2{\begincsname\??translation\currentlanguage\endcsname}} @@ -352,10 +352,7 @@ %D \getbuffer %D \stoplines -\unexpanded\def\commalistsentence - {\dodoubleempty\typo_helpers_concat_comma_list} - -\def\typo_helpers_concat_comma_list[#1][#2]% +\permanent\tolerant\protected\def\commalistsentence[#1]#*[#2]% {\clf_concatcommalist text {#1}% separators {#2}% @@ -370,6 +367,6 @@ %D Goodie (handy at \LUA\ end): -\unexpanded\def\LABELTEXT#1{\WORD{\labeltext{#1}}} % only for simple cases! +\permanent\protected\def\LABELTEXT#1{\WORD{\labeltext{#1}}} % only for simple cases! \protect \endinput diff --git a/tex/context/base/mkiv/lang-mis.mkiv b/tex/context/base/mkiv/lang-mis.mkiv index 3ec29a782..4d81c01fa 100644 --- a/tex/context/base/mkiv/lang-mis.mkiv +++ b/tex/context/base/mkiv/lang-mis.mkiv @@ -254,12 +254,12 @@ \def\lang_discretionaries_check_after {\setfalse\punctafterdiscretionary \setfalse\spaceafterdiscretionary - \ifx\blankspace\nextnext \settrue \spaceafterdiscretionary \else - \ifx\space \nextnext \settrue \spaceafterdiscretionary \else - \ifx .\nextnext \settrue \punctafterdiscretionary \else - \ifx ,\nextnext \settrue \punctafterdiscretionary \else - \ifx :\nextnext \settrue \punctafterdiscretionary \else - \ifx ;\nextnext \settrue \punctafterdiscretionary \fi\fi\fi\fi\fi\fi} + \ifx\blankspace\nexttoken \settrue \spaceafterdiscretionary \else + \ifx\space \nexttoken \settrue \spaceafterdiscretionary \else + \ifx .\nexttoken \settrue \punctafterdiscretionary \else + \ifx ,\nexttoken \settrue \punctafterdiscretionary \else + \ifx :\nexttoken \settrue \punctafterdiscretionary \else + \ifx ;\nexttoken \settrue \punctafterdiscretionary \fi\fi\fi\fi\fi\fi} \letvalue{\??discretionarymode m}\handlemathmodediscretionary @@ -268,7 +268,7 @@ \let\nextnextnext\egroup \def\next##1#1% {\def\next{\activedododotextmodediscretionary#1{##1}}% - \futurelet\nextnext\next}% + \futurelet\nexttoken\next}% \next} \let\discretionarytoken \relax @@ -279,7 +279,7 @@ \def\textmodediscretionary{\handletextmodediscretionary{#1}}% \lang_discretionaries_check_after \ifx\discretionarytoken\empty - \ifx#1\nextnext % takes care of ||| and +++ and ...... + \ifx#1\nexttoken % takes care of ||| and +++ and ...... \ifcsname\??discretionaryaction\string#1\endcsname \lastnamedcs \else\ifconditional\spaceafterdiscretionary @@ -296,7 +296,7 @@ \else \lang_discretionaries_check_before % the next line has been changed (20050203) - % \prewordbreak\hbox{\textmodediscretionary\nextnext}\postwordbreak + % \prewordbreak\hbox{\textmodediscretionary\nexttoken}\postwordbreak % but an hbox blocks a possible \discretionary \ifcsname\??discretionaryaction\endcsname \lastnamedcs diff --git a/tex/context/base/mkiv/lang-mis.mkxl b/tex/context/base/mkiv/lang-mis.mkxl index 5ed131d25..9515a1f8e 100644 --- a/tex/context/base/mkiv/lang-mis.mkxl +++ b/tex/context/base/mkiv/lang-mis.mkxl @@ -150,8 +150,8 @@ % hm why ex -\ifx\compoundhyphen \undefined - \unexpanded\def\compoundhyphen {\hbox{-\kern-.10775\emwidth-}} % .25\exheight +\ifx\compoundhyphen\undefined + \permanent\protected\def\compoundhyphen{\hbox{-\kern-.10775\emwidth-}} % .25\exheight \fi %D The last two variables are needed for subsentences |<|like this one|>| which we @@ -159,12 +159,12 @@ %D compound characters like |-| or || to be separated from the words. \TEX\ hackers %D will recognise the next two macro's: -\ifx\prewordbreak \undefined \unexpanded\def\prewordbreak {\penalty\plustenthousand\hskip\zeropoint\relax} \fi -\ifx\postwordbreak\undefined \unexpanded\def\postwordbreak {\penalty\zerocount \hskip\zeropoint\relax} \fi -\ifx\hspaceamount \undefined \def\hspaceamount#1#2{.16667\emwidth} \fi % language specific +\ifx\prewordbreak \undefined \permanent\protected\def\prewordbreak {\penalty\plustenthousand\hskip\zeropoint\relax} \fi +\ifx\postwordbreak\undefined \permanent\protected\def\postwordbreak {\penalty\zerocount \hskip\zeropoint\relax} \fi +\ifx\hspaceamount \undefined \def\hspaceamount#1#2{.16667\emwidth} \fi % will be overloaded -%unexpanded\def\permithyphenation{\ifhmode\prewordbreak\fi} % doesn't remove spaces -\unexpanded\def\permithyphenation{\ifhmode\wordboundary\fi} % doesn't remove spaces +%frozen\protected\def\permithyphenation{\ifhmode\prewordbreak\fi} % doesn't remove spaces +\permanent\protected\def\permithyphenation{\ifhmode\wordboundary\fi} % doesn't remove spaces %D \macros %D {beginofsubsentence,endofsubsentence, @@ -191,22 +191,22 @@ \installcorenamespace{discretionaryboth} \installcorenamespace{discretionarymode} -\unexpanded\def\installdiscretionary#1#2% +\permanent\protected\def\installdiscretionary#1#2% {\setevalue{\??discretionarymath\detokenize{#1}}{\detokenize{#1}}% ? \setvalue {\??discretionarytext\detokenize{#1}}{#2}% \setvalue {\??discretionaryboth\detokenize{#1}}{\lang_discretionaries_command#1}% \scratchcounter\expandafter`\detokenize{#1}% \expandafter\uedcatcodecommand\expandafter\ctxcatcodes\expandafter\scratchcounter\csname\??discretionaryboth\detokenize{#1}\endcsname} -\unexpanded\def\handlemathmodediscretionary#1{\ifcsname\??discretionarymath\detokenize{#1}\endcsname\lastnamedcs} -\unexpanded\def\handletextmodediscretionary#1{\ifcsname\??discretionarytext\detokenize{#1}\endcsname\lastnamedcs} +\permanent\protected\def\handlemathmodediscretionary#1{\ifcsname\??discretionarymath\detokenize{#1}\endcsname\lastnamedcs} +\permanent\protected\def\handletextmodediscretionary#1{\ifcsname\??discretionarytext\detokenize{#1}\endcsname\lastnamedcs} -\unexpanded\def\installdiscretionaries#1#2{\writestatus\m!system{use \string \installdiscretionary}} % obsolete +\permanent\protected\def\installdiscretionaries#1#2{\writestatus\m!system{use \string \installdiscretionary}} % obsolete \setnewconstant\discretionarymode\plusone -\unexpanded\def\ignorediscretionaries{\discretionarymode\zerocount} -\unexpanded\def\obeydiscretionaries {\discretionarymode\plusone} +\permanent\protected\def\ignorediscretionaries{\discretionarymode\zerocount} +\permanent\protected\def\obeydiscretionaries {\discretionarymode\plusone} \def\lang_discretionaries_command {% if direct if, we need \relax for lookahead in math mode @@ -252,12 +252,12 @@ \def\lang_discretionaries_check_after {\setfalse\punctafterdiscretionary \setfalse\spaceafterdiscretionary - \ifx\blankspace\nextnext \settrue \spaceafterdiscretionary \orelse - \ifx\space \nextnext \settrue \spaceafterdiscretionary \orelse - \ifx .\nextnext \settrue \punctafterdiscretionary \orelse - \ifx ,\nextnext \settrue \punctafterdiscretionary \orelse - \ifx :\nextnext \settrue \punctafterdiscretionary \orelse - \ifx ;\nextnext \settrue \punctafterdiscretionary \fi} + \ifx\blankspace\nexttoken \settrue \spaceafterdiscretionary \orelse + \ifx\space \nexttoken \settrue \spaceafterdiscretionary \orelse + \ifx .\nexttoken \settrue \punctafterdiscretionary \orelse + \ifx ,\nexttoken \settrue \punctafterdiscretionary \orelse + \ifx :\nexttoken \settrue \punctafterdiscretionary \orelse + \ifx ;\nexttoken \settrue \punctafterdiscretionary \fi} \letvalue{\??discretionarymode m}\handlemathmodediscretionary @@ -266,18 +266,18 @@ \let\nextnextnext\egroup \def\next##1#1% {\def\next{\activedododotextmodediscretionary#1{##1}}% - \futurelet\nextnext\next}% + \futurelet\nexttoken\next}% \next} \let\discretionarytoken \relax \let\textmodediscretionary\relax -\unexpanded\def\activedododotextmodediscretionary#1#2% +\permanent\protected\def\activedododotextmodediscretionary#1#2% {\edef\discretionarytoken{\detokenize{#2}}% \def\textmodediscretionary{\handletextmodediscretionary{#1}}% \lang_discretionaries_check_after \ifx\discretionarytoken\empty - \ifx#1\nextnext % takes care of ||| and +++ and ...... + \ifx#1\nexttoken % takes care of ||| and +++ and ...... \ifcsname\??discretionaryaction\string#1\endcsname \lastnamedcs \orelse\ifconditional\spaceafterdiscretionary @@ -294,7 +294,7 @@ \else \lang_discretionaries_check_before % the next line has been changed (20050203) - % \prewordbreak\hbox{\textmodediscretionary\nextnext}\postwordbreak + % \prewordbreak\hbox{\textmodediscretionary\nexttoken}\postwordbreak % but an hbox blocks a possible \discretionary \ifcsname\??discretionaryaction\endcsname \lastnamedcs @@ -333,7 +333,7 @@ %D In those situations where the nature of characters is less predictable, we can %D use the more direct approach: -\unexpanded\def\directdiscretionary +\permanent\protected\def\directdiscretionary {\csname\??discretionarymode \ifcase\discretionarymode n% @@ -342,7 +342,7 @@ \fi \endcsname} -\unexpanded\def\indirectdiscretionary +\permanent\protected\def\indirectdiscretionary {\csname\??discretionarymode \ifcase\discretionarymode n% @@ -365,7 +365,7 @@ {\wordboundary\discretionary{\hbox{#1}}{}{\hbox{#1}}\wordboundary} %{\discretionary options \plusthree{\hbox{#1}}{}{\hbox{#1}}} -\unexpanded\def\definetextmodediscretionary #1 +\permanent\protected\def\definetextmodediscretionary #1 {\setvalue{\??discretionaryaction\detokenize{#1}}} % \start \hsize 1mm @@ -479,7 +479,7 @@ %D \installdiscretionary | + %D \installdiscretionary + = -\def\defaultdiscretionaryhyphen{\compoundhyphen} +\permanent\protected\def\defaultdiscretionaryhyphen{\compoundhyphen} \installdiscretionary | \defaultdiscretionaryhyphen % installs in ctx and prt will fall back on it @@ -494,11 +494,11 @@ %D \goto{Some||Long||Word} %D \stoptyping -\unexpanded\def\fakecompoundhyphen - {\def\|{\mathortext\vert\lang_compounds_fake_hyphen}} +\permanent\protected\def\fakecompoundhyphen + {\enforced\permanent\protected\def\|{\mathortext\vert\lang_compounds_fake_hyphen}} \def\lang_compounds_fake_hyphen - {\def##1|% + {\enforced\permanent\protected\def##1|% {\doifelsenothing{##1}\compoundhyphen{##1}% \kern\compoundbreakpoint\allowbreak}} @@ -510,7 +510,7 @@ %D but, like the ones implemented earlier, this one also looks ahead for spaces and %D grouping tokens. -\unexpanded\def\midworddiscretionary +\permanent\protected\def\midworddiscretionary {\futurelet\nexttoken\lang_discretionaries_mid_word} \def\lang_discretionaries_mid_word @@ -552,10 +552,10 @@ \catcode\barasciicode\activecatcode - \unexpanded\gdef\compound#1{|#1|} + \permanent\protected\gdef\compound#1{|#1|} \doglobal \appendtoks - \def|#1|{\ifx#1\empty\empty-\else#1\fi}% + \enforced\permanent\protected\def|#1|{\ifx#1\empty\empty-\else#1\fi}% \to \everysimplifycommands \egroup @@ -575,7 +575,7 @@ %D %D \typebuffer \blank {\hsize3mm\getbuffer\par} \blank -\unexpanded\def\compounddiscretionary +\permanent\protected\def\compounddiscretionary {\discretionary options \plusthree {\ifnum\prehyphenchar >\zerocount\char\prehyphenchar \fi}% diff --git a/tex/context/base/mkiv/lang-rep.lua b/tex/context/base/mkiv/lang-rep.lua index a48215781..2a3c8a7fa 100644 --- a/tex/context/base/mkiv/lang-rep.lua +++ b/tex/context/base/mkiv/lang-rep.lua @@ -164,50 +164,6 @@ function languages.replacements.addlist(category,list) end end -local function hit(a,head) - local tree = trees[a] - if tree then - local root = tree[getchar(head)] - if root then - local current = getnext(head) - local lastrun = false - local lastfinal = false - while current do - local char, id = isglyph(current) - if not char and id == glue_code then - local s = getsubtype(current) - if s == spaceskip_code or s == xspaceskip_code then - char = 32 -- if needed we can also deal with spaces and special nbsp and such - end - end - if char then - local newroot = root[char] - if not newroot then - return lastrun, lastfinal - else - local final = newroot.final - if final then - if trace_details then - report_replacement("hitting word %a, replacement %a",final.word,final.replacement) - end - lastrun = current - lastfinal = final - else - root = newroot - end - end - current = getnext(current) - else - break - end - end - if lastrun then - return lastrun, lastfinal - end - end - end -end - local function tonodes(list,template) local head, current for i=1,#list do @@ -222,120 +178,241 @@ local function tonodes(list,template) return head end +local is_punctuation = characters.is_punctuation + +-- We can try to be clever and use the fact that there is no match to skip +-- over to the next word but it is gives fuzzy code so for now I removed +-- that optimization (when I really need a high performance version myself +-- I will look into it (but so far I never used this mechanism myself). +-- +-- We used to have the hit checker as function but is got messy when checks +-- for punctuation was added. + +local function replace(head,first,last,final,hasspace,overload) + local current = first + local prefirst = getprev(first) or head + local postlast = getnext(last) + local oldlength = final.oldlength + local newcodes = final.newcodes + local newlength = newcodes and #newcodes or 0 + if trace_replacements then + report_replacement("replacing word %a by %a",final.word,final.replacement) + end + if hasspace or final.special then + -- It's easier to delete and insert so we do just that. On the todo list is + -- turn injected spaces into glue but easier might be to let the char break + -- handler do that ... + local prev = getprev(current) + local next = getnext(last) + local list = current + setnext(last) + setlink(prev,next) + current = prev + if not current then + head = nil + end + local i = 1 + while i <= newlength do + local codes = newcodes[i] + if type(codes) == "table" then + local method = codes[1] + if method == "discretionary" then + local pre, post, replace = codes[2], codes[3], codes[4] + if pre then + pre = tonodes(pre,first) + end + if post then + post = tonodes(post,first) + end + if replace then + replace = tonodes(replace,first) + end + -- todo: also set attr + local new = new_disc(pre,post,replace) + setattrlist(new,first) + head, current = insert_after(head,current,new) + elseif method == "noligature" then + -- not that efficient to copy but ok for testing + local list = codes[2] + if list then + for i=1,#list do + local new = copy_node(first) + setchar(new,list[i]) + setattr(new,a_noligature,1) + head, current = insert_after(head,current,new) + end + else + local new = copy_node(first) + setchar(new,zwnj) + head, current = insert_after(head,current,new) + end + else + report_replacement("unknown method %a",method or "?") + end + else + local new = copy_node(first) + setchar(new,codes) + head, current = insert_after(head,current,new) + end + i = i + 1 + end + flush_list(list) + elseif newlength == 0 then + -- we overload + elseif oldlength == newlength then + if final.word ~= final.replacement then + for i=1,newlength do + setchar(current,newcodes[i]) + current = getnext(current) + end + end + current = getnext(final) + elseif oldlength < newlength then + for i=1,newlength-oldlength do + local n = copy_node(current) + setchar(n,newcodes[i]) + head, current = insert_node_before(head,current,n) + current = getnext(current) + end + for i=newlength-oldlength+1,newlength do + setchar(current,newcodes[i]) + current = getnext(current) + end + else + for i=1,oldlength-newlength do + head, current = remove_node(head,current,true) + end + for i=1,newlength do + setchar(current,newcodes[i]) + current = getnext(current) + end + end + if overload then + overload(final,getnext(prefirst),getprev(postlast)) + end + return head, postlast +end + +-- we handle just one space + function replacements.handler(head) - local current = head - local overload = attributes.applyoverloads + local current = head + local overload = attributes.applyoverloads + local mode = false -- we're in word or punctuation mode + local wordstart = false + local wordend = false + local prevend = false + local prevfinal = false + local tree = false + local root = false + local hasspace = false while current do - if getid(current) == glyph_code then + local id = getid(current) -- or use the char getter + if id == glyph_code then local a = getattr(current,a_replacements) if a then - local last, final = hit(a,current) - if last then - local precurrent = getprev(current) or head - local oldlength = final.oldlength - local newcodes = final.newcodes - local newlength = newcodes and #newcodes or 0 - if trace_replacement then - report_replacement("replacing word %a by %a",final.word,final.replacement) - end - if final.special then - -- easier is to delete and insert (a simple callout to tex would be more efficient) - -- maybe just walk over a replacement string instead - local prev = getprev(current) - local next = getnext(last) - local list = current - setnext(last) - setlink(prev,next) - current = prev - if not current then - head = nil - end - local i = 1 - while i <= newlength do - local codes = newcodes[i] - if type(codes) == "table" then - local method = codes[1] - if method == "discretionary" then - local pre, post, replace = codes[2], codes[3], codes[4] - if pre then - pre = tonodes(pre,last) - end - if post then - post = tonodes(post,last) - end - if replace then - replace = tonodes(replace,last) - end - -- todo: also set attr - local new = new_disc(pre,post,replace) - setattrlist(new,last) - head, current = insert_after(head,current,new) - elseif method == "noligature" then - -- not that efficient to copy but ok for testing - local list = codes[2] - if list then - for i=1,#list do - local new = copy_node(last) - setchar(new,list[i]) - setattr(new,a_noligature,1) - head, current = insert_after(head,current,new) - end - else - local new = copy_node(last) - setchar(new,zwnj) - head, current = insert_after(head,current,new) - end - else - -- todo + -- we have a run + tree = trees[a] + if tree then + local char = getchar(current) + local punc = is_punctuation[char] + if mode == "punc" then + if not punc then + if root then + local final = root.final + if final then + head = replace(head,wordstart,wordend,final,hasspace,overload) + elseif prevfinal then + head = replace(head,wordstart,prevend,prevfinal,hasspace,overload) end - else - local new = copy_node(last) - setchar(new,codes) - head, current = insert_after(head,current,new) + prevfinal = false + root = false end - i = i + 1 + mode = "word" end - flush_list(list) - -- elseif newlength == 0 then - -- -- nothing gets replaced - -- current = getnext(last) - elseif oldlength == newlength then -- #old == #new - if final.word == final.replacement then - -- nothing to do but skip - else - for i=1,newlength do - setchar(current,newcodes[i]) - current = getnext(current) + elseif mode == "word" then + if punc then + if root then + local final = root.final + if final then + head = replace(head,wordstart,wordend,final,hasspace,overload) + elseif prevfinal then + head = replace(head,wordstart,prevend,prevfinal,hasspace,overload) + end + prevfinal = false + root = false end + mode = "punc" end - elseif oldlength < newlength then -- #old < #new - for i=1,newlength-oldlength do - local n = copy_node(current) - setchar(n,newcodes[i]) - head, current = insert_node_before(head,current,n) - current = getnext(current) - end - for i=newlength-oldlength+1,newlength do - setchar(current,newcodes[i]) - current = getnext(current) + else + mode = punc and "punc" or "word" + end + if root then + root = root[char] + if root then + wordend = current end - else -- #old > #new or #new == 0 - for i=1,oldlength-newlength do - head, current = remove_node(head,current,true) + else + if prevfinal then + head = replace(head,wordstart,prevend,prevfinal,hasspace,overload) + prevfinal = false end - for i=1,newlength do - setchar(current,newcodes[i]) - current = getnext(current) + root = tree[char] + if root then + wordstart = current + wordend = current + prevend = false + hasspace = false end end - if overload then - overload(final,getnext(precurrent),getprev(current)) + else + root= false + end + else + tree = false + end + current = getnext(current) + elseif root then + local final = root.final + if mode == "word" and id == glue_code then + local s = getsubtype(current) + if s == spaceskip_code or s == xspaceskip_code then + local r = root[32] -- maybe more types + if r then + if not prevend then + local f = root.final + if f then + prevend = wordend + prevfinal = f + end + end + wordend = current + root = r + hasspace = true + goto moveon end end end + if final then + head, current = replace(head,wordstart,wordend,final,hasspace,overload) + elseif prevfinal then + head, current = replace(head,wordstart,prevend,prevfinal,hasspace,overload) + end + prevfinal = false + root = false + ::moveon:: + current = getnext(current) + else + current = getnext(current) + end + end + if root then + local final = root.final + if final then + head = replace(head,wordstart,wordend,final,hasspace,overload) + elseif prevfinal then + head = replace(head,wordstart,prevend,prevfinal,hasspace,overload) end - -- we're one ahead now but we need to because we handle words - current = getnext(current) end return head end diff --git a/tex/context/base/mkiv/lang-url.lua b/tex/context/base/mkiv/lang-url.lua index 7428d64ab..7a8b7ca86 100644 --- a/tex/context/base/mkiv/lang-url.lua +++ b/tex/context/base/mkiv/lang-url.lua @@ -9,7 +9,9 @@ if not modules then modules = { } end modules ['lang-url'] = { local utfcharacters, utfbyte, utfchar = utf.characters, utf.byte, utf.char local min, max = math.min, math.max -local context = context +local context = context +local ctx_pushcatcodes = context.pushcatcodes +local ctx_popcatcodes = context.popcatcodes local implement = interfaces.implement local variables = interfaces.variables @@ -190,9 +192,9 @@ local function action(hyphenatedurl,str,left,right,disc) end end if dodi then - list[i] = "\\d" + list[i] = "\\lang_url_d " else - list[i] = "\\" .. what .. "{" .. utfbyte(char) .. "}" + list[i] = "\\lang_url_" .. what .. "{" .. utfbyte(char) .. "}" end prev = char end @@ -200,7 +202,9 @@ local function action(hyphenatedurl,str,left,right,disc) report("old : %s",str) report("new : %t",list) end + ctx_pushcatcodes("prtcatcodes") context("%t",list) + ctx_popcatcodes() end -- urls.action = function(_,...) action(...) end -- sort of obsolete diff --git a/tex/context/base/mkiv/lang-url.mkiv b/tex/context/base/mkiv/lang-url.mkiv index 6afef63ce..c3ec02da4 100644 --- a/tex/context/base/mkiv/lang-url.mkiv +++ b/tex/context/base/mkiv/lang-url.mkiv @@ -47,19 +47,19 @@ \resetfontfeature \resetcharacterspacing % - \let\&\letterampersand - \let\#\letterhash - \let\~\lettertilde - \let\\\letterbackslash - \let\$\letterdollar - \let\^\letterhat - \let\_\letterunderscore - \let\{\letterleftbrace - \let\}\letterrightbrace - \let\|\letterbar - \let~=\lettertilde - \let|=\letterbar - \let\Ux\eUx + \enforced\let\&\letterampersand + \enforced\let\#\letterhash + \enforced\let\~\lettertilde + \enforced\let\\\letterbackslash + \enforced\let\$\letterdollar + \enforced\let\^\letterhat + \enforced\let\_\letterunderscore + \enforced\let\{\letterleftbrace + \enforced\let\}\letterrightbrace + \enforced\let\|\letterbar + \enforced\let~=\lettertilde + \enforced\let|=\letterbar + \enforced\let\Ux\eUx \to \everyhyphenatedurl \let\hyphenatedurlseparator \empty % \periodcentered @@ -100,22 +100,17 @@ {\dontleavehmode \begingroup \the\everyhyphenatedurl - \normallanguage\zerocount - \let\a\lang_url_a % after - \let\b\lang_url_b % before - \let\d\lang_url_d % disc - \let\l\lang_url_l % letter - \let\c\lang_url_c % character - \let\L\lang_url_L % letter_nobreak - \let\C\lang_url_C % character_nobreak + \normallanguage\zerocount % \nohyphens in mkiv \scratchskipone\zeropoint\s!plus\dimexpr\emwidth/12\s!minus\dimexpr\emwidth/24\relax % 1.00pt @ 12pt \scratchskiptwo\zeropoint\s!plus\dimexpr\emwidth/48\s!minus\dimexpr\emwidth/96\relax % 0.25pt @ 12pt + \unprotect \normalexpanded{\noexpand\clf_hyphenatedurl {\noexpand\detokenize{#1}}% \hyphenatedurllefthyphenmin \hyphenatedurlrighthyphenmin {\hyphenatedurldiscretionary}% }% + \protect \endgroup} %D \macros diff --git a/tex/context/base/mkiv/lang-wrd.lua b/tex/context/base/mkiv/lang-wrd.lua index 9fbced2ce..1c440bd7f 100644 --- a/tex/context/base/mkiv/lang-wrd.lua +++ b/tex/context/base/mkiv/lang-wrd.lua @@ -39,7 +39,7 @@ local getid = nuts.getid local getchar = nuts.getchar local setattr = nuts.setattr ----- getattr = nuts.getattr -local getlang = nuts.getlang +local getlanguage = nuts.getlanguage local ischar = nuts.ischar local nextnode = nuts.traversers.node @@ -163,7 +163,7 @@ local function mark_words(head,whenfound) -- can be optimized and shared while current do local code, id = ischar(current) -- not isglyph because otherwise we can run into if code then -- processed streams (\about[foo] does that) - local a = getlang(current) + local a = getlanguage(current) if a then if a ~= language then if s > 0 then diff --git a/tex/context/base/mkiv/lpdf-epa.lua b/tex/context/base/mkiv/lpdf-epa.lua index 45000aebc..0ff764e1d 100644 --- a/tex/context/base/mkiv/lpdf-epa.lua +++ b/tex/context/base/mkiv/lpdf-epa.lua @@ -510,7 +510,7 @@ local validstamps = { ForPublicRelease = true, } --- todo: we can use runtoks instead of steps +-- todo: we can use runlocal instead of steps local function validStamp(v) local name = "Stamped" -- fallback diff --git a/tex/context/base/mkiv/luat-cnf.lua b/tex/context/base/mkiv/luat-cnf.lua index ebce83ca8..16448c429 100644 --- a/tex/context/base/mkiv/luat-cnf.lua +++ b/tex/context/base/mkiv/luat-cnf.lua @@ -37,7 +37,7 @@ texconfig.save_size = 500000 texconfig.stack_size = 100000 texconfig.buffer_size = 10000000 texconfig.token_size = 10000000 -texconfig.node_size = 20000000 +texconfig.node_size = 50000000 texconfig.max_pool = 10000000 else @@ -121,15 +121,17 @@ function texconfig.init() }, basictex = { -- always - "callback", "font", "lang", "lua", "node", "status", "tex", "texconfig", "texio", "token", - -- not in luametatex - "img", "pdf", + "callback", "font", "lua", "node", "status", "tex", "texconfig", "texio", "token", + -- not in luametatex + "img", "pdf", "lang", + -- in luametatex + "language", }, extralua = { -- not in luametatex "unicode", "utf", "gzip", "zip", "zlib", -- in luametatex - "xzip", "xmath", "xcomplex", "basexx", + "xzip", "xmath", "xcomplex", "xdecimal", "basexx", -- maybe some day in luametatex "lz4", "lzo", -- always (mime can go) diff --git a/tex/context/base/mkiv/luat-cod.lmt b/tex/context/base/mkiv/luat-cod.lmt index 9b7564483..e4432345e 100644 --- a/tex/context/base/mkiv/luat-cod.lmt +++ b/tex/context/base/mkiv/luat-cod.lmt @@ -27,7 +27,7 @@ texconfig.save_size = 500000 texconfig.stack_size = 100000 texconfig.buffer_size = 10000000 texconfig.token_size = 10000000 -texconfig.node_size = 20000000 +texconfig.node_size = 50000000 texconfig.max_print_line = 100000 texconfig.max_strings = 500000 @@ -190,7 +190,7 @@ if not environment.luafilechunk then fullname = sourcepath .. "/" .. filename end local data = loadfile(fullname) - texio.write("term and log","<",data and "+ " or "- ",fullname,">") + texio.write("terminal_and_logfile","<",data and "+ " or "- ",fullname,">") if data then -- package.loaded[gsub(filename,"%..-$"] = data() @@ -297,7 +297,7 @@ callback.register("trace_memory", function(what,success) logs.report("tex memory","bumping category %a %s, details: %s", what,success,table.sequenced(status["get"..what.."state"]())) elseif texio then - texio.write_nl(format("bumping tex %a memory %s", + texio.write_nl(format("bumping tex '%s' memory %s", what,success)) end -- os.exit() diff --git a/tex/context/base/mkiv/luat-cod.mkxl b/tex/context/base/mkiv/luat-cod.mkxl index 3d3a5dd6b..fec88aecd 100644 --- a/tex/context/base/mkiv/luat-cod.mkxl +++ b/tex/context/base/mkiv/luat-cod.mkxl @@ -17,28 +17,28 @@ \newif\ifproductionrun -\let\ctxdirectlua \directlua -\let\ctxlatelua \latelua -\def\ctxsprint #1{\directlua{tex.sprint(tex.ctxcatcodes,#1)}} % saves tokens -\def\ctxwrite #1{\directlua{tex.write(#1)}} % saves tokens -\def\ctxcommand #1{\directlua{commands.#1}} % saves tokens -\def\ctxdirectcommand#1{\directlua{commands.#1}} % saves tokens -\def\ctxlatecommand #1{\latelua {commands.#1}} % saves tokens -\def\ctxreport #1{\directlua{logs.writer[[#1]]}} +\permanent\let\ctxdirectlua \directlua +\permanent\let\ctxlatelua \latelua +\permanent\def\ctxsprint #1{\directlua{tex.sprint(tex.ctxcatcodes,#1)}} % saves tokens +\permanent\def\ctxwrite #1{\directlua{tex.write(#1)}} % saves tokens +\permanent\def\ctxcommand #1{\directlua{commands.#1}} % saves tokens +\permanent\def\ctxdirectcommand#1{\directlua{commands.#1}} % saves tokens +\permanent\def\ctxlatecommand #1{\latelua {commands.#1}} % saves tokens +\permanent\def\ctxreport #1{\directlua{logs.writer[[#1]]}} %D Take your choice \unknown -\let\ctxlua \ctxdirectlua -\let\luacode \ctxdirectlua -\let\lateluacode \ctxlatelua -\let\directluacode\ctxdirectlua +\aliased\let\ctxlua \ctxdirectlua +\aliased\let\luacode \ctxdirectlua +\aliased\let\lateluacode \ctxlatelua +\aliased\let\directluacode\ctxdirectlua %D Reporting the version of \LUA\ that we use is done as follows: -\def\luaversion{\ctxwrite{LUAVERSION}} +\permanent\def\luaversion{\ctxwrite{LUAVERSION}} -\def\registerctxluafile#1#2{\ctxlua{lua.registercode("#1","#2")}} -\def\ctxloadluafile #1{\ctxlua{lua.registercode("#1")}} +\permanent\def\registerctxluafile#1#2{\ctxlua{lua.registercode("#1","#2")}} +\permanent\def\ctxloadluafile #1{\ctxlua{lua.registercode("#1")}} \registerctxluafile{luat-cod.lmt}{autosuffix} diff --git a/tex/context/base/mkiv/luat-fmt.lua b/tex/context/base/mkiv/luat-fmt.lua index 815ff10db..30792931e 100644 --- a/tex/context/base/mkiv/luat-fmt.lua +++ b/tex/context/base/mkiv/luat-fmt.lua @@ -178,8 +178,9 @@ function environment.make_format(formatname) -- because we can have half qualified paths (in lxc) local binarypath = validbinarypath() report_format("changing to format path %a",validformatpath) - lfs.chdir(validformatpath) - if dir.current() ~= validformatpath then + -- lfs.chdir(validformatpath) + -- if dir.current() ~= validformatpath then + if not lfs.chdir(validformatpath) then return fatalerror(startupdir,"unable to change to format path %a",validformatpath) end -- now we can generate the format, where we use a couple of flags, diff --git a/tex/context/base/mkiv/luat-ini.mkiv b/tex/context/base/mkiv/luat-ini.mkiv index d1b02ec7e..053e2ea4d 100644 --- a/tex/context/base/mkiv/luat-ini.mkiv +++ b/tex/context/base/mkiv/luat-ini.mkiv @@ -77,21 +77,25 @@ \edef\lua_letter_seven {\string\7} \edef\lua_letter_eight {\string\8} \edef\lua_letter_nine {\string\9} \edef\lua_letter_zero {\string\0} +\pushoverloadmode + \let\-\explicitdiscretionary +\popoverloadmode + \everyluacode {% \appendtoks - \let\\\lua_letter_backslash - \let\|\lua_letter_bar \let\-\lua_letter_dash - \let\(\lua_letter_lparent \let\)\lua_letter_rparent - \let\{\lua_letter_lbrace \let\}\lua_letter_rbrace - \let\'\lua_letter_squote \let\"\lua_letter_dquote - \let\n\lua_letter_n \let\r\lua_letter_r - \let\f\lua_letter_f \let\t\lua_letter_t - \let\a\lua_letter_a \let\b\lua_letter_b - \let\v\lua_letter_v \let\s\lua_letter_s - \let\1\lua_letter_one \let\2\lua_letter_two - \let\3\lua_letter_three \let\4\lua_letter_four - \let\5\lua_letter_five \let\6\lua_letter_six - \let\7\lua_letter_seven \let\8\lua_letter_eight - \let\9\lua_letter_nine \let\0\lua_letter_zero + \enforced\let\\\lua_letter_backslash + \enforced\let\|\lua_letter_bar \enforced\let\-\lua_letter_dash + \enforced\let\(\lua_letter_lparent \enforced\let\)\lua_letter_rparent + \enforced\let\{\lua_letter_lbrace \enforced\let\}\lua_letter_rbrace + \enforced\let\'\lua_letter_squote \enforced\let\"\lua_letter_dquote + \enforced\let\n\lua_letter_n \enforced\let\r\lua_letter_r + \enforced\let\f\lua_letter_f \enforced\let\t\lua_letter_t + \enforced\let\a\lua_letter_a \enforced\let\b\lua_letter_b + \enforced\let\v\lua_letter_v \enforced\let\s\lua_letter_s + \enforced\let\1\lua_letter_one \enforced\let\2\lua_letter_two + \enforced\let\3\lua_letter_three \enforced\let\4\lua_letter_four + \enforced\let\5\lua_letter_five \enforced\let\6\lua_letter_six + \enforced\let\7\lua_letter_seven \enforced\let\8\lua_letter_eight + \enforced\let\9\lua_letter_nine \enforced\let\0\lua_letter_zero } % \to \everyluacode \protected\def\obeyluatokens diff --git a/tex/context/base/mkiv/luat-lib.mkiv b/tex/context/base/mkiv/luat-lib.mkiv index ac60374d0..e89747de7 100644 --- a/tex/context/base/mkiv/luat-lib.mkiv +++ b/tex/context/base/mkiv/luat-lib.mkiv @@ -24,7 +24,7 @@ \registerctxluafile{util-dim}{} \registerctxluafile{trac-set}{} -\registerctxluafile{trac-log}{} +\registerctxluafile{luat-log}{autosuffix} \registerctxluafile{trac-inf}{autosuffix} \registerctxluafile{util-lua}{} \registerctxluafile{util-deb}{} % could also be done in trac-deb.mkiv @@ -99,8 +99,8 @@ \registerctxluafile{lxml-aux}{} \registerctxluafile{lxml-mis}{} -\protected\def\writestatus#1#2{\ctxlua{logs.status([==[#1]==],[==[#2]==])}} -\protected\def\writestring #1{\ctxlua{logs.writer([==[#1]==],"\string\n")}} -\protected\def\writeline {\ctxlua{logs.newline()}} +\frozen\overloaded\protected\def\writestatus#1#2{\ctxlua{logs.status([==[#1]==],[==[#2]==])}} +\frozen\overloaded\protected\def\writestring #1{\ctxlua{logs.writer([==[#1]==],"\string\n")}} +\frozen\overloaded\protected\def\writeline {\ctxlua{logs.newline()}} \endinput diff --git a/tex/context/base/mkiv/luat-log.lmt b/tex/context/base/mkiv/luat-log.lmt new file mode 100644 index 000000000..684b2ac8d --- /dev/null +++ b/tex/context/base/mkiv/luat-log.lmt @@ -0,0 +1,739 @@ +if not modules then modules = { } end modules ['luat-log'] = { + version = 1.001, + comment = "companion to trac-log.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- In fact all writes could go through lua and we could write the console and +-- terminal handler in lua then. Ok, maybe it's slower then, so a no-go. + +-- This used to be combined in trac-log but as we also split between mkiv and lmtx +-- we now have dedicated files. A side effect is a smaller format and a smaller +-- mtxrun. +-- +-- We use different targets: "terminal" "logfile", "both" and have no number +-- channel. + +local next, type, select, print = next, type, select, print +local format, gmatch, find = string.format, string.gmatch, string.find +local concat, insert, remove = table.concat, table.insert, table.remove +local topattern = string.topattern +local utfchar = utf.char +local datetime = os.date +local openfile = io.open + +local write_nl = texio.write_nl +local write = texio.write + +local setmetatableindex = table.setmetatableindex +local formatters = string.formatters +local settings_to_hash = utilities.parsers.settings_to_hash +local sortedkeys = table.sortedkeys + +-- variant is set now + +local variant = "default" +----- variant = "ansi" + +logs = logs or { } +local logs = logs + +-- we extend the formatters: + +formatters.add ( + formatters, "unichr", + [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]] +) + +formatters.add ( + formatters, "chruni", + [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]] +) + +-- basic loggers + +local function ignore() end + +setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end) + +local report, subreport, status, settarget, setformats, settranslations + +local direct, subdirect, writer, pushtarget, poptarget, setlogfile, settimedlog, setprocessor, setformatters, newline + +-- we use formatters but best check for % then because for simple messages but +-- we don't want this overhead for single messages (not that there are that +-- many; we could have a special weak table) + +local function ansisupported(specification) + if specification ~= "ansi" and specification ~= "ansilog" then + return false + elseif os and os.enableansi then + return os.enableansi() + else + return false + end +end + +do + + if arg and ansisupported then + -- we're don't have environment.arguments yet + for k, v in next, arg do -- k can be negative ! + if v == "--ansi" or v == "--c:ansi" then + if ansisupported("ansi") then + variant = "ansi" + end + break + elseif v == "--ansilog" or v == "--c:ansilog" then + if ansisupported("ansilog") then + variant = "ansilog" + end + break + end + end + end + + local whereto = "both" + local target = nil + local targets = nil + + local formats = table.setmetatableindex("self") + local translations = table.setmetatableindex("self") + + local report_yes, subreport_yes, direct_yes, subdirect_yes, status_yes + local report_nop, subreport_nop, direct_nop, subdirect_nop, status_nop + + local variants = { + default = { + formats = { + report_yes = formatters["%-15s > %s\n"], + report_nop = formatters["%-15s >\n"], + direct_yes = formatters["%-15s > %s"], + direct_nop = formatters["%-15s >"], + subreport_yes = formatters["%-15s > %s > %s\n"], + subreport_nop = formatters["%-15s > %s >\n"], + subdirect_yes = formatters["%-15s > %s > %s"], + subdirect_nop = formatters["%-15s > %s >"], + status_yes = formatters["%-15s : %s\n"], + status_nop = formatters["%-15s :\n"], + }, + targets = setmetatableindex( { + logfile = "logfile", + log = "logfile", + file = "logfile", + console = "terminal", + terminal = "terminal", + both = "terminal_and_logfile", + }, function(t,k) t[k] = "terminal_and_logfile" end), + }, + ansi = { + formats = { + report_yes = formatters["[0;33m%-15s [0;1m>[0m %s\n"], + report_nop = formatters["[0;33m%-15s [0;1m>[0m\n"], + direct_yes = formatters["[0;33m%-15s [0;1m>[0m %s"], + direct_nop = formatters["[0;33m%-15s [0;1m>[0m"], + subreport_yes = formatters["[0;33m%-15s [0;1m>[0;35m %s [0;1m>[0m %s\n"], + subreport_nop = formatters["[0;33m%-15s [0;1m>[0;35m %s [0;1m>[0m\n"], + subdirect_yes = formatters["[0;33m%-15s [0;1m>[0;35m %s [0;1m>[0m %s"], + subdirect_nop = formatters["[0;33m%-15s [0;1m>[0;35m %s [0;1m>[0m"], + status_yes = formatters["[0;33m%-15s [0;1m:[0m %s\n"], + status_nop = formatters["[0;33m%-15s [0;1m:[0m\n"], + }, + targets = setmetatableindex( { + logfile = false, + log = false, + file = false, + console = "terminal", + terminal = "terminal", + both = "terminal", + }, function(t,k) t[k] = "terminal" end), + } + } + + variants.ansilog = { + formats = variants.ansi.formats, + targets = variants.default.targets, + } + + logs.flush = io.flush + + writer = function(...) + if target then + write_nl(target,...) + end + end + + newline = function() + if target then + write_nl(target,"\n") + end + end + + report = function(a,b,c,...) + if not target then + -- ignore + elseif c ~= nil then + write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...))) + elseif b then + write_nl(target,report_yes(translations[a],formats[b])) + elseif a then + write_nl(target,report_nop(translations[a])) + else + write_nl(target,"\n") + end + end + + direct = function(a,b,c,...) + if not target then + return "" + elseif c ~= nil then + return direct_yes(translations[a],formatters[formats[b]](c,...)) + elseif b then + return direct_yes(translations[a],formats[b]) + elseif a then + return direct_nop(translations[a]) + else + return "" + end + end + + subreport = function(a,s,b,c,...) + if not target then + -- ignore + elseif c ~= nil then + write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...))) + elseif b then + write_nl(target,subreport_yes(translations[a],translations[s],formats[b])) + elseif a then + write_nl(target,subreport_nop(translations[a],translations[s])) + else + write_nl(target,"\n") + end + end + + subdirect = function(a,s,b,c,...) + if not target then + return "" + elseif c ~= nil then + return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...)) + elseif b then + return subdirect_yes(translations[a],translations[s],formats[b]) + elseif a then + return subdirect_nop(translations[a],translations[s]) + else + return "" + end + end + + status = function(a,b,c,...) + if not target then + -- ignore + elseif c ~= nil then + write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...))) + elseif b then + write_nl(target,status_yes(translations[a],formats[b])) + elseif a then + write_nl(target,status_nop(translations[a])) + else + write_nl(target,"\n") + end + end + + settarget = function(askedwhereto) + whereto = askedwhereto or whereto or "both" + target = targets[whereto] + if not target then + whereto = "both" + target = targets[whereto] + end + if target == "terminal" or target == "terminal_and_logfile" then + logs.flush = io.flush + else + logs.flush = ignore + end + end + + local stack = { } + + pushtarget = function(newtarget) + insert(stack,target) + settarget(newtarget) + end + + poptarget = function() + if #stack > 0 then + settarget(remove(stack)) + end + end + + setformats = function(f) + formats = f + end + + settranslations = function(t) + translations = t + end + + setprocessor = function(f) + local writeline = write_nl + write_nl = function(target,...) + if target then + writeline(target,f(...)) + end + end + end + + setformatters = function(specification) + local t = nil + local f = nil + local d = variants.default + if not specification then + -- + elseif type(specification) == "table" then + t = specification.targets + f = specification.formats or specification + else + if not ansisupported(specification) then + specification = "default" + end + local v = variants[specification] + if v then + t = v.targets + f = v.formats + variant = specification + end + end + targets = t or d.targets + target = targets[whereto] + if f then + d = d.formats + else + f = d.formats + d = f + end + setmetatableindex(f,d) + report_yes = f.report_yes + report_nop = f.report_nop + subreport_yes = f.subreport_yes + subreport_nop = f.subreport_nop + direct_yes = f.direct_yes + direct_nop = f.direct_nop + subdirect_yes = f.subdirect_yes + subdirect_nop = f.subdirect_nop + status_yes = f.status_yes + status_nop = f.status_nop + settarget(whereto) + end + + setformatters(variant) + + setlogfile = ignore + settimedlog = ignore + +end + +logs.report = report +logs.subreport = subreport +logs.status = status +logs.settarget = settarget +logs.pushtarget = pushtarget +logs.poptarget = poptarget +logs.setformats = setformats +logs.settranslations = settranslations + +logs.setlogfile = setlogfile +logs.settimedlog = settimedlog +logs.setprocessor = setprocessor +logs.setformatters = setformatters + +logs.direct = direct +logs.subdirect = subdirect +logs.writer = writer +logs.newline = newline + +local data = { } +local states = nil +local force = false + +function logs.reporter(category,subcategory) + local logger = data[category] + if not logger then + local state = states == true + if not state and type(states) == "table" then + for c, _ in next, states do + if find(category,c) then + state = true + break + end + end + end + logger = { + reporters = { }, + state = state, + } + data[category] = logger + end + local reporter = logger.reporters[subcategory or "default"] + if not reporter then + if subcategory then + reporter = function(...) + if force or not logger.state then + subreport(category,subcategory,...) + end + end + logger.reporters[subcategory] = reporter + else + local tag = category + reporter = function(...) + if force or not logger.state then + report(category,...) + end + end + logger.reporters.default = reporter + end + end + return reporter +end + +logs.new = logs.reporter -- for old times sake + +-- context specicific: this ends up in the macro stream + +local ctxreport = logs.writer + +function logs.setmessenger(m) + ctxreport = m +end + +function logs.messenger(category,subcategory) + -- we need to avoid catcode mess (todo: fast context) + if subcategory then + return function(...) + ctxreport(subdirect(category,subcategory,...)) + end + else + return function(...) + ctxreport(direct(category,...)) + end + end +end + +-- so far + +local function setblocked(category,value) -- v.state == value == true : disable + if category == true or category == "all" then + -- lock all + category, value = "*", true + elseif category == false then + -- unlock all + category, value = "*", false + elseif value == nil then + -- lock selective + value = true + end + if category == "*" then + states = value + for k, v in next, data do + v.state = value + end + else + alllocked = false + states = settings_to_hash(category,type(states)=="table" and states or nil) + for c in next, states do + local v = data[c] + if v then + v.state = value + else + c = topattern(c,true,true) + for k, v in next, data do + if find(k,c) then + v.state = value + end + end + end + end + end +end + +function logs.disable(category,value) + setblocked(category,value == nil and true or value) +end + +function logs.enable(category) + setblocked(category,false) +end + +function logs.categories() + return sortedkeys(data) +end + +function logs.show() + local n, c, s, max = 0, 0, 0, 0 + for category, v in table.sortedpairs(data) do + n = n + 1 + local state = v.state + local reporters = v.reporters + local nc = #category + if nc > c then + c = nc + end + for subcategory, _ in next, reporters do + local ns = #subcategory + if ns > c then + s = ns + end + local m = nc + ns + if m > max then + max = m + end + end + local subcategories = concat(sortedkeys(reporters),", ") + if state == true then + state = "disabled" + elseif state == false then + state = "enabled" + else + state = "unknown" + end + -- no new here + report("logging","category %a, subcategories %a, state %a",category,subcategories,state) + end + report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max) +end + +local delayed_reporters = { } + +setmetatableindex(delayed_reporters,function(t,k) + local v = logs.reporter(k.name) + t[k] = v + return v +end) + +function utilities.setters.report(setter,...) + delayed_reporters[setter](...) +end + +directives.register("logs.blocked", function(v) + setblocked(v,true) +end) + +directives.register("logs.target", function(v) + settarget(v) +end) + +do + + local report = logs.reporter("pages") -- not needed but saves checking when we grep for it + local texgetcount = tex and tex.getcount + + local real, user, sub = 0, 0, 0 + + function logs.start_page_number() + real = texgetcount("realpageno") + user = texgetcount("userpageno") + sub = texgetcount("subpageno") + end + + local timing = false + local usage = false + local lasttime = nil + + logs.private = { + enablepagetiming = function() + usage = true + end, + getpagetiming = function() + return type(usage) == "table" and usage + end, + } + + trackers.register("pages.timing", function() timing = "" end) + + function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average + if timing or usage then + local elapsed = statistics.currenttime(statistics) + local average, page + if not lasttime or real < 2 then + average = elapsed + page = elapsed + else + average = elapsed / (real - 1) + page = elapsed - lasttime + end + lasttime = elapsed + if timing then + timing = formatters[", total %0.03f, page %0.03f, average %0.03f"](elapsed,page,average) + end + if usage then + usage = { + page = { + real = real, + user = user, + sub = sub, + }, + time = { + elapsed = elapsed, + page = page, + average = average, + } + } + end + end + if real <= 0 then + report("flushing page%s",timing) + elseif user <= 0 then + report("flushing realpage %s%s",real,timing) + elseif sub <= 0 then + report("flushing realpage %s, userpage %s%s",real,user,timing) + else + report("flushing realpage %s, userpage %s, subpage %s%s",real,user,sub,timing) + end + logs.flush() + end + +end + +-- we don't have show_open and show_close callbacks yet + +do + local texerror = tex and tex.error or print + local formatters = string.formatters + + function logs.texerrormessage(fmt,first,...) -- for the moment we put this function here + texerror(first and formatters[fmt](first,...) or fmt) + end + +end + +-- this is somewhat slower but prevents out-of-order messages when print is mixed +-- with texio.write + +-- io.stdout:setvbuf('no') +-- io.stderr:setvbuf('no') + +-- windows: > nul 2>&1 +-- unix : > null 2>&1 + +if package.helpers.report then + package.helpers.report = logs.reporter("package loader") -- when used outside mtxrun +end + +do + + local finalactions = { } + local fatalerrors = { } + local possiblefatal = { } + local loggingerrors = false + + function logs.loggingerrors() + return loggingerrors + end + + directives.register("logs.errors",function(v) + loggingerrors = v + if type(v) == "string" then + fatalerrors = settings_to_hash(v) + else + fatalerrors = { } + end + end) + + function logs.registerfinalactions(...) + insert(finalactions,...) -- so we can force an order if needed + end + + local what = nil + local report = nil + local state = nil + local target = nil + + local function startlogging(t,r,w,s) + target = t + state = force + force = true + report = type(r) == "function" and r or logs.reporter(r) + what = w + pushtarget(target) + newline() + if s then + report("start %s: %s",what,s) + else + report("start %s",what) + end + if target == "logfile" then + newline() + end + return report + end + + local function stoplogging() + if target == "logfile" then + newline() + end + report("stop %s",what) + if target == "logfile" then + newline() + end + poptarget() + state = oldstate + end + + function logs.startfilelogging(...) + return startlogging("logfile", ...) + end + + logs.stopfilelogging = stoplogging + + local done = false + + function logs.starterrorlogging(r,w,...) + if not done then + pushtarget("terminal") + newline() + logs.report("error logging","start possible issues") + poptarget() + done = true + end + if fatalerrors[w] then + possiblefatal[w] = true + end + return startlogging("terminal",r,w,...) + end + + logs.stoperrorlogging = stoplogging + + function logs.finalactions() + if #finalactions > 0 then + for i=1,#finalactions do + finalactions[i]() + end + if done then + pushtarget("terminal") + newline() + logs.report("error logging","stop possible issues") + poptarget() + end + return next(possiblefatal) and sortedkeys(possiblefatal) or false + end + end + +end + +-- just in case we load from context + +local dummy = function() end + +function logs.application(t) + return { + name = t.name or tex.jobname, + banner = t.banner, + report = logs.reporter(t.name), + moreinfo = dummy, + export = dummy, + help = dummy, + identify = dummy, + version = dummy, + } +end diff --git a/tex/context/base/mkiv/luat-log.lua b/tex/context/base/mkiv/luat-log.lua new file mode 100644 index 000000000..fd3b73d3d --- /dev/null +++ b/tex/context/base/mkiv/luat-log.lua @@ -0,0 +1,795 @@ +if not modules then modules = { } end modules ['luat-log'] = { + version = 1.001, + comment = "companion to trac-log.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- In fact all writes could go through lua and we could write the console and +-- terminal handler in lua then. Ok, maybe it's slower then, so a no-go. + +-- This used to be combined in trac-log but as we also split between mkiv and lmtx +-- we now have dedicated files. A side effect is a smaller format and a smaller +-- mtxrun. + +local next, type, select, print = next, type, select, print +local format, gmatch, find = string.format, string.gmatch, string.find +local concat, insert, remove = table.concat, table.insert, table.remove +local topattern = string.topattern +local utfchar = utf.char +local datetime = os.date +local openfile = io.open + +local write_nl = texio and texio.write_nl +local write = texio and texio.write + +local setmetatableindex = table.setmetatableindex +local formatters = string.formatters +local settings_to_hash = utilities.parsers.settings_to_hash +local sortedkeys = table.sortedkeys + +-- variant is set now + +local variant = "default" +----- variant = "ansi" + +logs = logs or { } +local logs = logs + +-- we extend the formatters: + +formatters.add ( + formatters, "unichr", + [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]] +) + +formatters.add ( + formatters, "chruni", + [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]] +) + +-- basic loggers + +local function ignore() end + +setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end) + +local report, subreport, status, settarget, setformats, settranslations + +local direct, subdirect, writer, pushtarget, poptarget, setlogfile, settimedlog, setprocessor, setformatters, newline + +-- we use formatters but best check for % then because for simple messages but +-- we don't want this overhead for single messages (not that there are that +-- many; we could have a special weak table) + +local function ansisupported(specification) + if specification ~= "ansi" and specification ~= "ansilog" then + return false + elseif os and os.enableansi then + return os.enableansi() + else + return false + end +end + +do + + if texio.setescape then + texio.setescape(0) -- or (false) + end + + if arg and ansisupported then + -- we're don't have environment.arguments yet + for k, v in next, arg do -- k can be negative ! + if v == "--ansi" or v == "--c:ansi" then + if ansisupported("ansi") then + variant = "ansi" + end + break + elseif v == "--ansilog" or v == "--c:ansilog" then + if ansisupported("ansilog") then + variant = "ansilog" + end + break + end + end + end + + local function useluawrites() + + -- quick hack, awaiting speedup in engine (8 -> 6.4 sec for --make with console2) + -- still needed for luajittex .. luatex should not have that ^^ mess + + local texio_write_nl = texio.write_nl + local texio_write = texio.write + local io_write = io.write + + write_nl = function(target,...) + if not io_write then + io_write = io.write + end + if target == "term and log" then + texio_write_nl("log",...) + texio_write_nl("term","") + io_write(...) + elseif target == "log" then + texio_write_nl("log",...) + elseif target == "term" then + texio_write_nl("term","") + io_write(...) + elseif type(target) == "number" then + texio_write_nl(target,...) -- a tex output channel + elseif target ~= "none" then + texio_write_nl("log",target,...) + texio_write_nl("term","") + io_write(target,...) + end + end + + write = function(target,...) + if not io_write then + io_write = io.write + end + if target == "term and log" then + texio_write("log",...) + io_write(...) + elseif target == "log" then + texio_write("log",...) + elseif target == "term" then + io_write(...) + elseif type(target) == "number" then + texio_write(target,...) -- a tex output channel + elseif target ~= "none" then + texio_write("log",target,...) + io_write(target,...) + end + end + + texio.write = write + texio.write_nl = write_nl + + useluawrites = ignore + + end + + -- local format = string.formatter + + local whereto = "both" + local target = nil + local targets = nil + + local formats = table.setmetatableindex("self") + local translations = table.setmetatableindex("self") + + local report_yes, subreport_yes, direct_yes, subdirect_yes, status_yes + local report_nop, subreport_nop, direct_nop, subdirect_nop, status_nop + + local variants = { + default = { + formats = { + report_yes = formatters["%-15s > %s\n"], + report_nop = formatters["%-15s >\n"], + direct_yes = formatters["%-15s > %s"], + direct_nop = formatters["%-15s >"], + subreport_yes = formatters["%-15s > %s > %s\n"], + subreport_nop = formatters["%-15s > %s >\n"], + subdirect_yes = formatters["%-15s > %s > %s"], + subdirect_nop = formatters["%-15s > %s >"], + status_yes = formatters["%-15s : %s\n"], + status_nop = formatters["%-15s :\n"], + }, + targets = { + logfile = "log", + log = "log", + file = "log", + console = "term", + terminal = "term", + both = "term and log", + }, + }, + ansi = { + formats = { + report_yes = formatters["[0;33m%-15s [0;1m>[0m %s\n"], + report_nop = formatters["[0;33m%-15s [0;1m>[0m\n"], + direct_yes = formatters["[0;33m%-15s [0;1m>[0m %s"], + direct_nop = formatters["[0;33m%-15s [0;1m>[0m"], + subreport_yes = formatters["[0;33m%-15s [0;1m>[0;35m %s [0;1m>[0m %s\n"], + subreport_nop = formatters["[0;33m%-15s [0;1m>[0;35m %s [0;1m>[0m\n"], + subdirect_yes = formatters["[0;33m%-15s [0;1m>[0;35m %s [0;1m>[0m %s"], + subdirect_nop = formatters["[0;33m%-15s [0;1m>[0;35m %s [0;1m>[0m"], + status_yes = formatters["[0;33m%-15s [0;1m:[0m %s\n"], + status_nop = formatters["[0;33m%-15s [0;1m:[0m\n"], + }, + targets = { + logfile = "none", + log = "none", + file = "none", + console = "term", + terminal = "term", + both = "term", + }, + } + } + + variants.ansilog = { + formats = variants.ansi.formats, + targets = variants.default.targets, + } + + logs.flush = io.flush + + writer = function(...) + write_nl(target,...) + end + + newline = function() + write_nl(target,"\n") + end + + report = function(a,b,c,...) + if c ~= nil then + write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...))) + elseif b then + write_nl(target,report_yes(translations[a],formats[b])) + elseif a then + write_nl(target,report_nop(translations[a])) + else + write_nl(target,"\n") + end + end + + direct = function(a,b,c,...) + if c ~= nil then + return direct_yes(translations[a],formatters[formats[b]](c,...)) + elseif b then + return direct_yes(translations[a],formats[b]) + elseif a then + return direct_nop(translations[a]) + else + return "" + end + end + + subreport = function(a,s,b,c,...) + if c ~= nil then + write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...))) + elseif b then + write_nl(target,subreport_yes(translations[a],translations[s],formats[b])) + elseif a then + write_nl(target,subreport_nop(translations[a],translations[s])) + else + write_nl(target,"\n") + end + end + + subdirect = function(a,s,b,c,...) + if c ~= nil then + return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...)) + elseif b then + return subdirect_yes(translations[a],translations[s],formats[b]) + elseif a then + return subdirect_nop(translations[a],translations[s]) + else + return "" + end + end + + status = function(a,b,c,...) + if c ~= nil then + write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...))) + elseif b then + write_nl(target,status_yes(translations[a],formats[b])) + elseif a then + write_nl(target,status_nop(translations[a])) + else + write_nl(target,"\n") + end + end + + settarget = function(askedwhereto) + whereto = askedwhereto or whereto or "both" + target = targets[whereto] + if not target then + whereto = "both" + target = targets[whereto] + end + if target == "term" or target == "term and log" then + logs.flush = io.flush + else + logs.flush = ignore + end + end + + local stack = { } + + pushtarget = function(newtarget) + insert(stack,target) + settarget(newtarget) + end + + poptarget = function() + if #stack > 0 then + settarget(remove(stack)) + end + end + + setformats = function(f) + formats = f + end + + settranslations = function(t) + translations = t + end + + setprocessor = function(f) + local writeline = write_nl + write_nl = function(target,...) + writeline(target,f(...)) + end + end + + setformatters = function(specification) + local t = nil + local f = nil + local d = variants.default + if not specification then + -- + elseif type(specification) == "table" then + t = specification.targets + f = specification.formats or specification + else + if not ansisupported(specification) then + specification = "default" + end + local v = variants[specification] + if v then + t = v.targets + f = v.formats + variant = specification + end + end + targets = t or d.targets + target = targets[whereto] or target + if f then + d = d.formats + else + f = d.formats + d = f + end + setmetatableindex(f,d) + report_yes = f.report_yes + report_nop = f.report_nop + subreport_yes = f.subreport_yes + subreport_nop = f.subreport_nop + direct_yes = f.direct_yes + direct_nop = f.direct_nop + subdirect_yes = f.subdirect_yes + subdirect_nop = f.subdirect_nop + status_yes = f.status_yes + status_nop = f.status_nop + if variant == "ansi" or variant == "ansilog" then + useluawrites() -- because tex escapes ^^, not needed in lmtx + end + settarget(whereto) + end + + setformatters(variant) + + setlogfile = ignore + settimedlog = ignore + + -- settimedlog = function() + -- local localtime = os.localtime + -- local writeline = write_nl + -- write_nl = function(f,...) + -- writeline(f,localtime() .. " | " .. concat { ... }) + -- end + -- settimedlog = ignore + -- end + +end + +logs.report = report +logs.subreport = subreport +logs.status = status +logs.settarget = settarget +logs.pushtarget = pushtarget +logs.poptarget = poptarget +logs.setformats = setformats +logs.settranslations = settranslations + +logs.setlogfile = setlogfile +logs.settimedlog = settimedlog +logs.setprocessor = setprocessor +logs.setformatters = setformatters + +logs.direct = direct +logs.subdirect = subdirect +logs.writer = writer +logs.newline = newline + +local data = { } +local states = nil +local force = false + +function logs.reporter(category,subcategory) + local logger = data[category] + if not logger then + local state = states == true + if not state and type(states) == "table" then + for c, _ in next, states do + if find(category,c) then + state = true + break + end + end + end + logger = { + reporters = { }, + state = state, + } + data[category] = logger + end + local reporter = logger.reporters[subcategory or "default"] + if not reporter then + if subcategory then + reporter = function(...) + if force or not logger.state then + subreport(category,subcategory,...) + end + end + logger.reporters[subcategory] = reporter + else + local tag = category + reporter = function(...) + if force or not logger.state then + report(category,...) + end + end + logger.reporters.default = reporter + end + end + return reporter +end + +logs.new = logs.reporter -- for old times sake + +-- context specicific: this ends up in the macro stream + +local ctxreport = logs.writer + +function logs.setmessenger(m) + ctxreport = m +end + +function logs.messenger(category,subcategory) + -- we need to avoid catcode mess (todo: fast context) + if subcategory then + return function(...) + ctxreport(subdirect(category,subcategory,...)) + end + else + return function(...) + ctxreport(direct(category,...)) + end + end +end + +-- so far + +local function setblocked(category,value) -- v.state == value == true : disable + if category == true or category == "all" then + -- lock all + category, value = "*", true + elseif category == false then + -- unlock all + category, value = "*", false + elseif value == nil then + -- lock selective + value = true + end + if category == "*" then + states = value + for k, v in next, data do + v.state = value + end + else + alllocked = false + states = settings_to_hash(category,type(states)=="table" and states or nil) + for c in next, states do + local v = data[c] + if v then + v.state = value + else + c = topattern(c,true,true) + for k, v in next, data do + if find(k,c) then + v.state = value + end + end + end + end + end +end + +function logs.disable(category,value) + setblocked(category,value == nil and true or value) +end + +function logs.enable(category) + setblocked(category,false) +end + +function logs.categories() + return sortedkeys(data) +end + +function logs.show() + local n, c, s, max = 0, 0, 0, 0 + for category, v in table.sortedpairs(data) do + n = n + 1 + local state = v.state + local reporters = v.reporters + local nc = #category + if nc > c then + c = nc + end + for subcategory, _ in next, reporters do + local ns = #subcategory + if ns > c then + s = ns + end + local m = nc + ns + if m > max then + max = m + end + end + local subcategories = concat(sortedkeys(reporters),", ") + if state == true then + state = "disabled" + elseif state == false then + state = "enabled" + else + state = "unknown" + end + -- no new here + report("logging","category %a, subcategories %a, state %a",category,subcategories,state) + end + report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max) +end + +local delayed_reporters = { } + +setmetatableindex(delayed_reporters,function(t,k) + local v = logs.reporter(k.name) + t[k] = v + return v +end) + +function utilities.setters.report(setter,...) + delayed_reporters[setter](...) +end + +directives.register("logs.blocked", function(v) + setblocked(v,true) +end) + +directives.register("logs.target", function(v) + settarget(v) +end) + +do + + local report = logs.reporter("pages") -- not needed but saves checking when we grep for it + local texgetcount = tex and tex.getcount + + local real, user, sub = 0, 0, 0 + + function logs.start_page_number() + real = texgetcount("realpageno") + user = texgetcount("userpageno") + sub = texgetcount("subpageno") + end + + local timing = false + local usage = false + local lasttime = nil + + logs.private = { + enablepagetiming = function() + usage = true + end, + getpagetiming = function() + return type(usage) == "table" and usage + end, + } + + trackers.register("pages.timing", function() timing = "" end) + + function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average + if timing or usage then + local elapsed = statistics.currenttime(statistics) + local average, page + if not lasttime or real < 2 then + average = elapsed + page = elapsed + else + average = elapsed / (real - 1) + page = elapsed - lasttime + end + lasttime = elapsed + if timing then + timing = formatters[", total %0.03f, page %0.03f, average %0.03f"](elapsed,page,average) + end + if usage then + usage = { + page = { + real = real, + user = user, + sub = sub, + }, + time = { + elapsed = elapsed, + page = page, + average = average, + } + } + end + end + if real <= 0 then + report("flushing page%s",timing) + elseif user <= 0 then + report("flushing realpage %s%s",real,timing) + elseif sub <= 0 then + report("flushing realpage %s, userpage %s%s",real,user,timing) + else + report("flushing realpage %s, userpage %s, subpage %s%s",real,user,sub,timing) + end + logs.flush() + end + +end + +-- we don't have show_open and show_close callbacks yet + +do + local texerror = tex and tex.error or print + local formatters = string.formatters + + function logs.texerrormessage(fmt,first,...) -- for the moment we put this function here + texerror(first and formatters[fmt](first,...) or fmt) + end + +end + +-- this is somewhat slower but prevents out-of-order messages when print is mixed +-- with texio.write + +-- io.stdout:setvbuf('no') +-- io.stderr:setvbuf('no') + +-- windows: > nul 2>&1 +-- unix : > null 2>&1 + +if package.helpers.report then + package.helpers.report = logs.reporter("package loader") -- when used outside mtxrun +end + +do + + local finalactions = { } + local fatalerrors = { } + local possiblefatal = { } + local loggingerrors = false + + function logs.loggingerrors() + return loggingerrors + end + + directives.register("logs.errors",function(v) + loggingerrors = v + if type(v) == "string" then + fatalerrors = settings_to_hash(v) + else + fatalerrors = { } + end + end) + + function logs.registerfinalactions(...) + insert(finalactions,...) -- so we can force an order if needed + end + + local what = nil + local report = nil + local state = nil + local target = nil + + local function startlogging(t,r,w,s) + target = t + state = force + force = true + report = type(r) == "function" and r or logs.reporter(r) + what = w + pushtarget(target) + newline() + if s then + report("start %s: %s",what,s) + else + report("start %s",what) + end + if target == "logfile" then + newline() + end + return report + end + + local function stoplogging() + if target == "logfile" then + newline() + end + report("stop %s",what) + if target == "logfile" then + newline() + end + poptarget() + state = oldstate + end + + function logs.startfilelogging(...) + return startlogging("logfile", ...) + end + + logs.stopfilelogging = stoplogging + + local done = false + + function logs.starterrorlogging(r,w,...) + if not done then + pushtarget("terminal") + newline() + logs.report("error logging","start possible issues") + poptarget() + done = true + end + if fatalerrors[w] then + possiblefatal[w] = true + end + return startlogging("terminal",r,w,...) + end + + logs.stoperrorlogging = stoplogging + + function logs.finalactions() + if #finalactions > 0 then + for i=1,#finalactions do + finalactions[i]() + end + if done then + pushtarget("terminal") + newline() + logs.report("error logging","stop possible issues") + poptarget() + end + return next(possiblefatal) and sortedkeys(possiblefatal) or false + end + end + +end + +-- just in case we load from context + +local dummy = function() end + +function logs.application(t) + return { + name = t.name or tex.jobname, + banner = t.banner, + report = logs.reporter(t.name), + moreinfo = dummy, + export = dummy, + help = dummy, + identify = dummy, + version = dummy, + } +end diff --git a/tex/context/base/mkiv/luat-mac.lua b/tex/context/base/mkiv/luat-mac.lua index c754f602c..3c50a41f8 100644 --- a/tex/context/base/mkiv/luat-mac.lua +++ b/tex/context/base/mkiv/luat-mac.lua @@ -72,23 +72,60 @@ local stack, top, n, hashes = { }, nil, 0, { } -- end -- end -local function set(s) - if top then - local ns = #stack - local h = hashes[ns] - if not h then - h = rep("#",2^(ns-1)) - hashes[ns] = h +local set = CONTEXTLMTXMODE > 0 and + function(s) + if top then + local ns = #stack + local h = hashes[ns] + if not h then + h = rep("#",2^(ns-1)) + hashes[ns] = h + end + if s == "ignore" then + return h .. "-" + elseif s == "spacer" then + return h .. "*" + elseif s == "pickup" then + return h .. ":" + else + n = n + 1 + if n > 9 then + report_macros("number of arguments > 9, ignoring %s",s) + elseif s == "discard" then + top[s] = "" + return h .. "0" + elseif s == "keepbraces" then + top[s] = "" + return h .. "+" + elseif s == "mandate" then + top[s] = "" + return h .. "=" + elseif s == "keepmandate" then + top[s] = "" + return h .. "_" + elseif s == "prunespacing" then + top[s] = "" + return h .. "/" + else + local m = h .. n + top[s] = m + return m + end + end end - if s == "ignore" then - return h .. "-" - else + end +or + function(s) + if top then + local ns = #stack + local h = hashes[ns] + if not h then + h = rep("#",2^(ns-1)) + hashes[ns] = h + end n = n + 1 if n > 9 then report_macros("number of arguments > 9, ignoring %s",s) - elseif s == "discard" then - top[s] = "" - return h .. "0" else local m = h .. n top[s] = m @@ -96,7 +133,6 @@ local function set(s) end end end -end local function get(s) if s == "ignore" or s == "discard" then @@ -262,7 +298,7 @@ end function macros.convertfile(oldname,newname) -- beware, no testing on oldname == newname local data = loadtexfile(oldname) - data = interfaces.preprocessed(data) or "" -- interfaces not yet defined + data = macros.preprocessed(data) or "" -- interfaces not yet defined savedata(newname,data) end diff --git a/tex/context/base/mkiv/luat-run.lua b/tex/context/base/mkiv/luat-run.lua index cb947f318..cce6ab73b 100644 --- a/tex/context/base/mkiv/luat-run.lua +++ b/tex/context/base/mkiv/luat-run.lua @@ -293,6 +293,32 @@ end) -- end -- end) +local report = logs.reporter("csname overload") +local reported = { } + +callback.register("handle_overload", function(fatal,overload,csname,flags) + if not reported[csname] then + logs.newline() + local readstate = status.readstate + local filename = readstate.filename + local linenumber = readstate.linenumber + if filename and linenumber then + report("%s, protection level %i, control sequence %a, properties '% t', file %a, line %i", + fatal and "fatal error" or "warning",overload,csname,tokens.flags(csname),filename,linenumber) + else + report("%s, protection level %i, control sequence %a, properties '% t'", + fatal and "fatal error" or "warning",overload,csname,tokens.flags(csname)) + end + reported[csname] = true + logs.newline() + if fatal then + cleanup_run() + osexit(1) + end + end +end) + +-- bonus if environment.initex then diff --git a/tex/context/base/mkiv/luat-usr.mkiv b/tex/context/base/mkiv/luat-usr.mkiv index f3868ccf4..ebd96e031 100644 --- a/tex/context/base/mkiv/luat-usr.mkiv +++ b/tex/context/base/mkiv/luat-usr.mkiv @@ -38,13 +38,14 @@ %D \macros %D {definenamedlua} %D -%D We provide an interface for defining instances: +%D We provide an interface for defining instances. We don't have the definers yet +%D so we do itlow level: \def\s!lua {lua} \def\s!code {code} \def\s!data {data} -%def\s!start{start} -%def\s!stop {stop} +\def\s!start{start} +\def\s!stop {stop} %D Beware: because \type {\expanded} is een convert command, the error %D message will show \type{<inserted text>} as part of the message. diff --git a/tex/context/base/mkiv/lxml-ini.mkxl b/tex/context/base/mkiv/lxml-ini.mkxl new file mode 100644 index 000000000..01e2024bf --- /dev/null +++ b/tex/context/base/mkiv/lxml-ini.mkxl @@ -0,0 +1,544 @@ +%D \module +%D [ file=lxml-ini, +%D version=2007.08.17, +%D title=\CONTEXT\ \XML\ Support, +%D subtitle=Initialization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D Todo: auto apply setups (manage at lua end) +%D Todo: manuak: \xmlinclusion \xmlinclusions + +\writestatus{loading}{ConTeXt XML Support / Initialization} + +%registerctxluafile{lxml-tab}{} % loader +%registerctxluafile{lxml-lpt}{} % parser +%registerctxluafile{lxml-xml}{} % xml finalizers +%registerctxluafile{lxml-aux}{} % extras using parser +%registerctxluafile{lxml-mis}{} % extras independent of parser +\registerctxluafile{lxml-ent}{} % entity hacks +\registerctxluafile{lxml-tex}{} % tex finalizers +\registerctxluafile{lxml-dir}{} % ctx hacks +\registerctxluafile{lxml-ini}{} % interface + +\unprotect + +% todo: { } mandate so that we can alias + +% undocumented: + +\def\ctxlxml #1{\ctxlua{lxml.#1}} + +% for now indirect .. this will change when we have updated luatex (scan_argument) + +\permanent\def\xmlconcat #1#2#3{\clf_xmlconcat {#1}{#2}{\detokenize{#3}}} +\permanent\def\xmlconcatrange #1#2#3#4#5{\clf_xmlconcatrange{#1}{#2}{#3}{#4}{\detokenize{#5}}} + +%D Maybe I should add \type {\protected} here: + +\permanent\def\xmlloadfile #1#2{\clf_xmlloadfile {#1}{#2}{\directxmlparameter\c!compress}} +\permanent\def\xmlloadbuffer#1#2{\clf_xmlloadbuffer{#1}{#2}{\directxmlparameter\c!compress}} +\permanent\def\xmlloaddata #1#2{\clf_xmlloaddata {#1}{#2}{\directxmlparameter\c!compress}} + +\aliased\let\xmlload\xmlloadfile + +% aliased + +%let\xmlall \clf_xmlall +%let\xmlatt \clf_xmlatt +%let\xmlattdef \clf_xmlattdef +%let\xmlattribute \clf_xmlattribute +%let\xmlattributedef \clf_xmlattributedef +%let\xmlbadinclusions \clf_xmlbadinclusions +%let\xmlchainatt \clf_xmlchainatt +%let\xmlchainattdef \clf_xmlchainattdef +%let\xmlchecknamespace \clf_xmlchecknamespace +%let\xmlcommand \clf_xmlcommand +%let\xmlcontext \clf_xmlcontext +%let\xmlcount \clf_xmlcount +%let\xmldelete \clf_xmldelete +%let\xmldirect \clf_xmldirect % in loops, not dt but root +%let\xmldirectives \clf_xmldirectives +%let\xmldirectivesafter \clf_xmldirectivesafter +%let\xmldirectivesbefore \clf_xmldirectivesbefore +%let\xmldisplayverbatim \clf_xmldisplayverbatim +%let\xmlelement \clf_xmlelement +%let\xmlfilter \clf_xmlfilter +%let\xmlfilterlist \clf_xmlfilterlist +%let\xmlfirst \clf_xmlfirst +%let\xmlflush \clf_xmlflush +%let\xmlflushcontext \clf_xmlflushcontext +%let\xmlflushlinewise \clf_xmlflushlinewise +%let\xmlflushpure \clf_xmlflushpure +%let\xmlflushspacewise \clf_xmlflushspacewise +%let\xmlflushtext \clf_xmlflushtext +%let\xmlfunction \clf_xmlfunction +%let\xmlinclude \clf_xmlinclude +%let\xmlincludeoptions \clf_xmlincludeoptions +%let\xmlinclusion \clf_xmlinclusion +%let\xmlinclusionbase \clf_xmlinclusionbase +%let\xmlinclusions \clf_xmlinclusions +%let\xmlindex \clf_xmlindex +%let\xmlinlineverbatim \clf_xmlinlineverbatim +%let\xmllast \clf_xmllast +%let\xmllastatt \clf_xmllastatt +%let\xmllastmatch \clf_xmllastmatch +%let\xmllastpar \clf_xmllastpar +%let\xmlloaddirectives \clf_xmlloaddirectives +%let\xmlmain \clf_xmlmain +%let\xmlmatch \clf_xmlmatch +%let\xmlname \clf_xmlname +%let\xmlnamespace \clf_xmlnamespace +%let\xmlnonspace \clf_xmlnonspace +%let\xmlpar \clf_xmlpar +%let\xmlparam \clf_xmlparam +%let\xmlpath \clf_xmlpath +%let\xmlpopmatch \clf_xmlpopmatch +%let\xmlpos \clf_xmlpos +%let\xmlpure \clf_xmlpure +%let\xmlpushmatch \clf_xmlpushmatch +%let\xmlraw \clf_xmlraw +%let\xmlrefatt \clf_xmlrefatt +%let\xmlregisterns \clf_xmlregisterns % document +%let\xmlremapname \clf_xmlremapname % element +%let\xmlremapnamespace \clf_xmlremapnamespace % document +%let\xmlsave \clf_xmlsave +%let\xmlsetatt \clf_xmlsetatt +%let\xmlsetattribute \clf_xmlsetattribute +%let\xmlsetpar \clf_xmlsetpar +%let\xmlsetparam \clf_xmlsetparam +%let\xmlsetsetup \clf_xmlsetsetup +%let\xmlsnippet \clf_xmlsnippet +%let\xmlstrip \clf_xmlstrip +%let\xmlstripanywhere \clf_xmlstripanywhere +%let\xmlstripnolines \clf_xmlstripnolines +%let\xmlstripped \clf_xmlstripped +%let\xmlstrippednolines \clf_xmlstrippednolines +%let\xmltag \clf_xmltag +%let\xmltext \clf_xmltext +%let\xmltobuffer \clf_xmltobuffer % id pattern name +%let\xmltobuffertextonly \clf_xmltobuffertextonly % id pattern name +%let\xmltobufferverbose \clf_xmltobufferverbose % id pattern name +%let\xmltofile \clf_xmltofile % id pattern filename +%let\xmltoparameters \clf_xmltoparameters +%let\xmlverbatim \clf_xmlverbatim + +\let\xmlposition \xmlindex + +\permanent\protected\def\xmlinfo#1{\hbox{\ttxx[\xmlname{#1}]}} +\permanent\protected\def\xmlshow#1{\startpacked\ttx\xmlverbatim{#1}\stoppacked} + +% the next one is handy for mode runs because it enforces a consistent +% #1 indexing (needed when using \xmltext{main:123}{...} like calls + +%let\xmladdindex \clf_xmladdindex + +% we need to pass the last argument as function, so + +\protected\def\xmlsetfunction#1#2#3{\ctxcommand{xmlsetfunction("#1",\!!bs#2\!!es,#3)}} + +% goodie: + +\immutable\def\xmltempbuffername{xml-temp} + +\permanent\protected\def\prettyprintbuffer#1#2% only used here + {\ifdefined\scitebuffer + \scitebuffer[#2][#1]% + \else + \typebuffer[#1][\c!option=#2]% + \fi} + +\permanent\protected\def\xmlprettyprint#1#2% + {\xmltobufferverbose{#1}{.}{\xmltempbuffername}% + \prettyprintbuffer\xmltempbuffername{#2}} + +\permanent\protected\def\xmlprettyprinttext#1#2% + {\xmltobuffertextonly{#1}{.}{\xmltempbuffername}% + \prettyprintbuffer\xmltempbuffername{#2}} + +\permanent\protected\def\inlineprettyprintbuffer#1#2% only used here + {\ifdefined\sciteinlinebuffer + \sciteinlinebuffer[#2][#1]% + \else + \typeinlinebuffer[#1][\c!option=#2]% + \fi} + +\permanent\protected\def\xmlinlineprettyprint#1#2% + {\xmltobufferverbose{#1}{.}{\xmltempbuffername}% + \inlineprettyprintbuffer\xmltempbuffername{#2}} + +\permanent\protected\def\xmlinlineprettyprinttext#1#2% + {\xmltobuffertextonly{#1}{.}{\xmltempbuffername}% + \inlineprettyprintbuffer\xmltempbuffername{#2}} + +% kind of special: + +\aliased\let\xmlstartraw\clf_xmlstartraw +\aliased\let\xmlstopraw \clf_xmlstopraw + +\aliased\let\startxmlraw\clf_xmlstartraw +\aliased\let\stopxmlraw \clf_xmlstopraw + +% these are expandable! todo: \xmldoifelseattribute + +%let\xmldoif \clf_xmldoif +%let\xmldoifnot \clf_xmldoifnot +%let\xmldoifelse \clf_xmldoifelse +%let\xmldoiftext \clf_xmldoiftext +%let\xmldoifnottext \clf_xmldoifnottext +%let\xmldoifelsetext \clf_xmldoifelsetext + +%let\xmldoifatt \clf_xmldoifatt +%let\xmldoifnotatt \clf_xmldoifnotatt +%let\xmldoifelseatt \clf_xmldoifelseatt + +%let\xmldoifempty \clf_xmldoifempty +%let\xmldoifnotempty \clf_xmldoifnotempty +%let\xmldoifelseempty \clf_xmldoifelseempty +%let\xmldoifselfempty \clf_xmldoifselfempty +%let\xmldoifnotselfempty \clf_xmldoifnotselfempty +%let\xmldoifelseselfempty \clf_xmldoifelseselfempty + +\aliased\let\xmldoiftextelse \xmldoifelsetext +\aliased\let\xmldoifemptyelse \xmldoifelseempty +\aliased\let\xmldoifselfemptyelse \xmldoifelseselfempty + +% \startxmlsetups xml:include +% \xmlinclude{main}{include}{filename|href} +% \stopxmlsetups +% +% \xmlprependsetup{xml:include} + +% \let\xmlgrab\xmlsetsetup % obsolete +% \let\xmlself\s!unknown % obsolete + +\aliased\let\xmlsetup\setupwithargumentswapped +\aliased\let\xmls \setupwithargumentswapped % hardly any faster +\aliased\let\xmlw \setupwithargument % hardly any faster + +% todo: 1:xml:whatever always before 3:xml:something + +\permanent\protected\def\xmlprependsetup #1{\clf_xmlprependsetup{*}{#1}} +\permanent\protected\def\xmlappendsetup #1{\clf_xmlappendsetup {*}{#1}} +\permanent\protected\def\xmlbeforesetup #1#2{\clf_xmlbeforesetup {*}{#1}{#2}} +\permanent\protected\def\xmlaftersetup #1#2{\clf_xmlaftersetup {*}{#1}{#2}} +\permanent\protected\def\xmlremovesetup #1{\clf_xmlremovesetup {*}{#1}} +\permanent\protected\def\xmlresetsetups {\clf_xmlresetsetups {*}} + +\permanent\protected\def\xmlprependdocumentsetup #1#2{\clf_xmlprependsetup{#1}{#2}} +\permanent\protected\def\xmlappenddocumentsetup #1#2{\clf_xmlappendsetup {#1}{#2}} +\permanent\protected\def\xmlbeforedocumentsetup #1#2#3{\clf_xmlbeforesetup {#1}{#2}{#3}} +\permanent\protected\def\xmlafterdocumentsetup #1#2#3{\clf_xmlaftersetup {#1}{#2}{#3}} +\permanent\protected\def\xmlremovedocumentsetup #1#2{\clf_xmlremovesetup {#1}{#2}} +\permanent\protected\def\xmlresetdocumentsetups #1{\clf_xmlresetsetups {#1}} + +\permanent\protected\def\xmlflushsetups #1{\clf_xmlflushsetups {#1}{*}{}} % #1 == id where to apply * +\permanent\protected\def\xmlflushdocumentsetups #1#2{\clf_xmlflushsetups {#1}{*}{#2}} % #1 == id where to apply * and #2 + +\aliased\let\xmlregistersetup \xmlappendsetup +\aliased\let\xmlregisterdocumentsetup\xmlappenddocumentsetup + +\def\xmldocument{main} + +\permanent\protected\def\xmlregisteredsetups + {\xmlstarttiming + \xmlflushsetups\xmldocument + \xmldefaulttotext\xmldocument % after include + \xmlstoptiming} + +\permanent\protected\def\xmlregistereddocumentsetups#1#2% id setups + {\xmlstarttiming + % todo: test for duplicates ! + \xmlflushdocumentsetups{#1}{#2}% + \xmldefaulttotext{#1}% after include + \xmlstoptiming} + +\permanent\protected\def\xmlstarttiming{\clf_xmlstarttiming} % undocumented +\permanent\protected\def\xmlstoptiming {\clf_xmlstoptiming} % undocumented + +\def\lxml_process#1#2#3#4#5% flag \loader id name what initializersetup + {\begingroup + \edef\xmldocument{#3}% #2 can be \xmldocument and set as such + %xmlpushdocument{#3}% + #2{#3}{#4}% + \setcatcodetable\notcatcodes + \doifelsenothing{#5}% + {\xmlsetup{#3}{xml:process}}% + {\xmlsetup{#3}{#5}}% + %xmlpopdocument + \endgroup} + +\permanent\protected\def\xmlprocessfile {\lxml_process\plusone \xmlload} +\permanent\protected\def\xmlprocessdata {\lxml_process\zerocount\xmlloaddata} +\permanent\protected\def\xmlprocessbuffer{\lxml_process\zerocount\xmlloadbuffer} +\aliased \let\xmlprocess \xmlprocessfile + +\startxmlsetups xml:flush + \xmlflush{#1} +\stopxmlsetups + +\startxmlsetups xml:process + \xmlregistereddocumentsetups{#1}{#1} + \xmlmain{#1} +\stopxmlsetups + +\permanent\protected\def\xmlloadonly#1#2#3% + {\xmlload{#1}{#2}% + \xmlregistereddocumentsetups{#1}{#3}} + +% replaced by concat +% +% \protected\def\xmlconnect#1#2#3% inefficient +% {\scratchcounter\xmlcount{#1}{#2}\relax +% \ifcase\scratchcounter \or +% \xmlall{#1}{#2}% +% \else +% \dorecurse \scratchcounter +% {\ifnum\recurselevel>\plusone#3\fi +% \xmlidx{#1}{#2}\recurselevel}% +% \fi} + +\permanent\protected\def\xmlcdataobeyedline {\obeyedline} +\permanent\protected\def\xmlcdataobeyedspace{\strut\obeyedspace} +\permanent\protected\def\xmlcdatabefore {\begingroup\tt} +\permanent\protected\def\xmlcdataafter {\endgroup} + +% verbatim (dodo:pre/post whitespace, maybe splot verbatim and +% cdata commands), experimental: +% +% \xmlsetfunction{main}{verbatim}{lxml.displayverbatim} +% \xmlsetfunction{main}{verb} {lxml.inlineverbatim} + +% we use an xml: namespace so one has to define a suitable verbatim, say +% +% \definetyping[xml:verbatim][typing] +% +% this is experimental! + +\permanent\tolerant\protected\def\startxmldisplayverbatim[#1]% + {\startpacked + \edef\currenttyping{#1}% + \ifx\currenttyping\empty + \let\currenttyping\v!typing + \else % maybe test for existence + \edef\currenttyping{xml:\currenttyping}% + \fi + \protected\def\stopxmldisplayverbatim + {\endofverbatimlines + \stoppacked}% + \doinitializeverbatim + \beginofverbatimlines} + +\let\stopxmldisplayverbatim\relax + +\permanent\tolerant\protected\def\startxmlinlineverbatim[#1]% + {\begingroup + \edef\currenttype{#1}% + \ifx\currenttype\empty + \let\currenttype\v!type + \else % maybe test for existence + \edef\currenttype{xml:\currenttype}% + \fi + \let\stopxmlinlineverbatim\endgroup + \doinitializeverbatim} + +\let\stopxmlinlineverbatim\relax + +% processing instructions + +\permanent\protected\def\xmlinstalldirective#1#2% + {\clf_xmlinstalldirective{#1}{\csstring#2}} + +% an example: + +% <?context-tex-directive bgroup ?> + +\appendtoks + \xmlinstalldirective{tex}{xmltexcommand}% +\to \everyjob + +\permanent\def\xmltexcommand#1{\begincsname#1\endcsname} + +% \def\xmlcontextdirective#1% kind class key value +% {\executeifdefined{xml#1directive}\gobblethreearguments} + +% setting up xml: +% +% \setupxml[\c!default=] % mkiv only == text +% \setupxml[\c!default=\v!none] % mkiv only, undefined -> hidden +% \setupxml[\c!default=\v!text] % mkiv only, undefined -> text + +% \def\xmlctxdirective#1#2#3{\doif{#1}{clue}{\doif{#2}{page}}{\page[#3]}} + +\newconstant\xmlprocessingmode % 0=unset, 1=text, 2=hidden + +\installcorenamespace{xml} +\installcorenamespace{xmldefaults} +\installcorenamespace{xmlmapvalue} + +\installdirectcommandhandler \??xml {xml} + +\letvalue{\??xmldefaults\v!normal}\zerocount +\letvalue{\??xmldefaults\v!none }\zerocount +\letvalue{\??xmldefaults\v!text }\plusone +\letvalue{\??xmldefaults\v!hidden}\plustwo + +\permanent\protected\def\xmldefaulttotext + {\ifcase\xmlprocessingmode + \expandafter\gobbleoneargument % 0 (none) + \or + \expandafter\clf_xmlsetcommandtotext % 1 (normal) + \or + \expandafter\clf_xmlsetcommandtonone % 2 (hidden) + \else + \expandafter\gobbleoneargument % (none) + \fi} + +\appendtoks + \xmlprocessingmode\executeifdefined{\??xmldefaults\directxmlparameter\c!default}\plusone +\to \everysetupxml + +\setupxml + [\c!default=, % flush all + \c!compress=\v!no, % strip comment + \c!entities=\v!no] % load big entity file + +\appendtoks + \doif{\directxmlparameter\c!entities}\v!yes\clf_xmlloadentities +\to \everysetupxml + +\permanent\def\xmlmapvalue #1#2#3{\setvalue{\??xmlmapvalue#1:#2}{#3}} % keep #3 to grab spaces +\permanent\def\xmldoifelsevalue #1#2{\ifcsname\??xmlmapvalue#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} + +\permanent\def\xmlvalue#1#2% #3 + {\ifcsname\??xmlmapvalue#1:#2\endcsname + \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument + \else + \expandafter\firstofoneargument + \fi} + +\permanent\def\xmlmappedvalue#1#2#3% + {\ifcsname\??xmlmapvalue#1:#2\endcsname + \expandafter\lastnamedcs + \else + \csname\??xmlmapvalue#1:#3\expandafter\endcsname + \fi} + +\aliased\let\xmldoifvalueelse\xmldoifelsevalue + +\aliased\let\xmlmapval\xmlmapvalue +\aliased\let\xmlval \xmlvalue + +%D Experimental: + +\permanent\def\xmlgetindex #1{\clf_xmlgetindex {\xmldocument}{#1}} +\permanent\def\xmlwithindex #1#2{\clf_xmlwithindex{\xmldocument}{#1}{#2}} +\permanent\def\xmlreference #1#2{\string\xmlwithindex{#1}{#2}} + +%D Entities: +%D +%D \starttyping +%D \xmlsetentity{tex}{\TEX{}} % {} needed +%D \stoptyping + +\permanent\protected\def\xmlsetentity#1#2{\clf_xmlsetentity{#1}{\detokenize{#2}}} +\permanent\protected\def\xmltexentity#1#2{\clf_xmltexentity{#1}{\detokenize{#2}}} + +%D The following might change (or even disappear) so we keep it undocumented. + +\setnewconstant\xmlautoentities\plusone % 0=off, 1=upper, 2=upper,lower + +\permanent\protected\def\xmle + {\ifcase\xmlautoentities + \expandafter\lxml_e_none + \or + \expandafter\lxml_e_upper + \or + \expandafter\lxml_e_upperlower + \else + \expandafter\lxml_e_none + \fi} + +\def\lxml_e_none#1#2% safe + {#1} + +\def\lxml_e_upper#1#2% can be abbreviation + {\ifcsname#2\endcsname + \csname#2\expandafter\endcsname + \else + #1% + \fi} + +\def\lxml_e_upperlower#1#2% can be anything, so unsafe + {\ifcsname#2\endcsname + \csname#2\expandafter\endcsname + \orelse\ifcsname#1\endcsname + \csname#1\expandafter\endcsname + \else + #1% + \fi} + +%D We keep these around as there are also MP, LUA and TEX variants but they are not +%D the same as in \MKII. + +\permanent\tolerant\protected\def\processXMLbuffer[#1]{\xmlprocessbuffer{temp}{#1}{}} +\permanent \protected\def\processXMLfile #1{\xmlprocessfile {temp}{#1}{}} +\permanent \protected\def\XMLdata #1{\xmlprocessdata {temp}{#1}{}} + +\aliased\let\processxmlbuffer\processXMLbuffer +\aliased\let\processxmlfile \processXMLfile +\aliased\let\xmldata \XMLdata + +\permanent\protected\def\xmlsetinjectors [#1]{\clf_xmlsetinjectors{#1}} +\permanent\protected\def\xmlresetinjectors {\clf_xmlresetinjectors{}} + +% \def\xmlinjector#1{\executeifdefined{#1}\donothing} + +\permanent\def\xmlinjector#1{\fastsetup{xml:directive:injector:#1}} + +\startsetups xml:directive:injector:page + \page +\stopsetups + +\startsetups xml:directive:injector:column + \column +\stopsetups + +\startsetups xml:directive:injector:blank + \blank +\stopsetups + +\startsetups xml:directive:injector:noline + \vskip-\lineheight +\stopsetups + +\aliased\let\xmlapplyselectors\clf_xmlapplyselectors + +% \let\xmlcatcodes\notcatcodes + +\protect \endinput + +% \newcount\charactersactiveoffset \charactersactiveoffset="10000 +% +% \startextendcatcodetable\ctxcatcodes +% \catcode\numexpr\charactersactiveoffset+`<\relax=13 +% \catcode\numexpr\charactersactiveoffset+`&\relax=13 +% \catcode\numexpr\charactersactiveoffset+`>\relax=13 +% \stopextendcatcodetable +% +% \startextendcatcodetable\xmlcatcodes % not needed +% \catcode\numexpr\charactersactiveoffset+`<\relax=13 +% \catcode\numexpr\charactersactiveoffset+`&\relax=13 +% \catcode\numexpr\charactersactiveoffset+`>\relax=13 +% \stopextendcatcodetable +% +% \ctxlua { % entities are remembered in the format +% commands.remapentity("<",characters.activeoffset + utf.byte("<")) +% commands.remapentity("&",characters.activeoffset + utf.byte("&")) +% commands.remapentity(">",characters.activeoffset + utf.byte(">")) +% } diff --git a/tex/context/base/mkiv/math-ali.mkxl b/tex/context/base/mkiv/math-ali.mkxl new file mode 100644 index 000000000..997ecd3d7 --- /dev/null +++ b/tex/context/base/mkiv/math-ali.mkxl @@ -0,0 +1,1893 @@ +%D \module +%D [ file=math-ali, +%D version=2008.10.20, +%D title=\CONTEXT\ Math Macros, +%D subtitle=Math Alignments, +%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan}, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Math Macros / Math Alignments} + +\unprotect + +%D The code here has been moved from other files. Beware: the \MKII\ and \MKIV\ code +%D is not gathered in files with the same name. In the meantime this code has been +%D adapted to \MKIV\ but more is possible. The code is somewhat complicated by the +%D fact that alignments are tricky with rspect to tagging. + +% export: +% +% alignment : ok +% cases : +% matrix : ok +% substack : + +%D \macros +%D {definemathalignment, setupmathalignment, startmathalignment} +%D +%D Modules may provide additional alignment features. The following mechanisms are +%D provided by the core. + +\newtoks\t_math_align_a +\newtoks\t_math_align_b +\newtoks\t_math_align_c + +\newskip\d_math_eqalign_distance + +\protected\def\math_eqalign_distance + {\relax + \ifdim\d_math_eqalign_distance>\zeropoint + % \hskip\d_math_eqalign_distance + \tabskip\d_math_eqalign_distance + \fi + \mathalignmentparameter\c!separator + \relax} + +\def\displayopenupvalue{.25\bodyfontsize} + +\def\math_build_eqalign + {\scratchtoks\emptytoks + \d_math_eqalign_distance\mathalignmentparameter\c!distance\relax + \scratchcounterone\mathalignmentparameter\c!m + \scratchcountertwo\mathalignmentparameter\c!n + \etoksapp\scratchtoks{\the\t_math_align_a}% + \scratchcounter\plusone + \dorecurse{\numexpr\scratchcounterone*\scratchcountertwo-\plusone\relax} + {\ifnum\scratchcounter=\scratchcountertwo + \scratchcounter\plusone + \etoksapp\scratchtoks{\math_eqalign_distance}% + \else + \advance\scratchcounter\plusone + \fi + \etoksapp\scratchtoks{\the\t_math_align_b}}% + \etoksapp\scratchtoks{\the\t_math_align_c}} + +\def\math_math_in_eqalign#1% + {\startforceddisplaymath + \tabskip\zeropoint + \everycr\emptytoks + {{}#1{}}% + \stopforceddisplaymath} + +\def\math_text_in_eqalign#1% + {\startimath + \tabskip\zeropoint + \everycr\emptytoks + #1% + \stopimath} + +\def\eqalign#1% why no halign here, probably because of displaywidth + {\emptyhbox + \mskip\thinmuskip + \vcenter + {\math_openup\displayopenupvalue % was: \openup\jot + \mathsurround\zeropoint + \ialign{% + \strut + \hfil + \startforceddisplaymath{\alignmark\alignmark}\stopforceddisplaymath + \aligntab + \startforceddisplaymath{{}\alignmark\alignmark{}}\stopforceddisplaymath + \hfil\crcr + #1\crcr}% + }% + \mskip\thinmuskip} + +% preamble is scanned for tabskips so we need the span to prevent an error message + +\setnewconstant\eqalignmode\plusone + +% use zeroskipplusfill + +\def\math_prepare_r_eqalign_no + {\t_math_align_a + {\strut + \tabskip\zeropoint + \alignmark\alignmark % for picking up the number + \aligntab + \math_first_in_eqalign + \hfil + \math_left_of_eqalign + \span + \math_math_in_eqalign{\alignmark\alignmark}% + \math_right_of_eqalign + \tabskip\zeropoint}% + \t_math_align_b + {\aligntab + \math_next_in_eqalign + \math_left_of_eqalign + \span + \math_math_in_eqalign{\alignmark\alignmark}% + \math_right_of_eqalign + \tabskip\zeropoint}% + \ifnum\mathraggedstatus=\plusone + \t_math_align_c + {\hfil + \aligntab + \span + \math_text_in_eqalign{\alignmark\alignmark}% + \tabskip\zeropoint}% + \orelse\ifnum\mathraggedstatus=\plusthree + \t_math_align_c + {\hfil + \tabskip\zeropoint\s!plus 1\s!fill + \aligntab + \span + \math_text_in_eqalign{\alignmark\alignmark}% + \tabskip\zeropoint}% + \else + \t_math_align_c + {\hfil + \tabskip\centering + \aligntab + \span + \llap{\math_text_in_eqalign{\alignmark\alignmark}}% + \tabskip\zeropoint}% + \fi + \math_build_eqalign + \the\mathdisplayaligntweaks + \tabskip\centering} + +\def\math_prepare_l_eqalign_no % \checkeddisplaymath + {\t_math_align_a + {\strut + \tabskip\zeropoint + \alignmark\alignmark % for picking up the number + \aligntab + \math_first_in_eqalign + \hfil + \math_left_of_eqalign + \span + \math_math_in_eqalign{\alignmark\alignmark}% + \math_right_of_eqalign + \tabskip\zeropoint}% + \t_math_align_b + {\aligntab + \math_next_in_eqalign + \math_left_of_eqalign + \span + \math_math_in_eqalign{\alignmark\alignmark}% + \math_right_of_eqalign + \tabskip\zeropoint}% + \ifnum\mathraggedstatus=\plusone + \t_math_align_c + {\hfil + \aligntab + \kern-\displaywidth + \span + \rlap{\math_text_in_eqalign{\alignmark\alignmark}}% + \tabskip\displaywidth}% + \orelse\ifnum\mathraggedstatus=\plusthree + \t_math_align_c + {\hfil + \tabskip\zeropoint\s!plus 1\s!fill + \aligntab + \kern-\displaywidth + \span + \math_rlap{\math_text_in_eqalign{\alignmark\alignmark}}% + \tabskip\displaywidth}% + \else + \t_math_align_c + {\hfil + \tabskip\centering + \aligntab + \kern-\displaywidth + \span + \rlap{\math_text_in_eqalign{\alignmark\alignmark}}% + \tabskip\displaywidth}% + \fi + \math_build_eqalign + \the\mathdisplayaligntweaks + \tabskip\centering} + +\def\math_halign_checked + {\halign \ifcase\eqalignmode \or to \checkeddisplaywidth \fi} + +\def\math_both_eqalign_no_normal#1#2% + {\ifmmode + \the\mathdisplayaligntweaks + \vcenter\bgroup + \enforced\let\math_finish_eqalign_no\egroup + \else + \enforced\let\math_finish_eqalign_no\relax + \fi + #1% + \math_halign_checked\expandafter\bgroup\the\scratchtoks\crcr#2\crcr\egroup + \math_finish_eqalign_no} + +\installcorenamespace {mathalignlocation} + +\setvalue{\??mathalignlocation\v!top }{\let\math_alignment_halign_method\halign\tpack} +\setvalue{\??mathalignlocation\v!bottom}{\let\math_alignment_halign_method\halign\vpack} +\setvalue{\??mathalignlocation\v!center}{\let\math_alignment_halign_method\halign\vcenter} + +\def\math_both_eqalign_no_aligned#1% + {\let\math_alignment_halign_method\math_halign_checked + \ifmmode + \the\mathdisplayaligntweaks + \global\mathnumberstatus\plusone + \ifcase\mathraggedstatus + \def\math_finish_eqalign_no{\crcr\egroup}% + \else % we're in a mathbox + \ifcsname\??mathalignlocation\mathalignmentparameter\c!location\endcsname + \lastnamedcs % top|bottom|center as suggested by HM + \else + \vcenter + \fi + \bgroup + \def\math_finish_eqalign_no{\crcr\egroup\egroup}% + \fi + \fi + #1% + \math_alignment_halign_method\expandafter\bgroup\the\scratchtoks\crcr} + +\def\math_rlap#1% + {\setbox\scratchbox\hbox{#1}% + \ifdim\wd\scratchbox>\d_math_number_correction + \global\d_math_number_correction\wd\scratchbox + \fi + \box\scratchbox + \global\mathnumberstatus\plustwo} + +\def\math_handle_eqalign_no_r_normal {\math_both_eqalign_no_normal \math_prepare_r_eqalign_no} +\def\math_handle_eqalign_no_l_normal {\math_both_eqalign_no_normal \math_prepare_l_eqalign_no} +\def\math_handle_eqalign_no_r_aligned{\math_both_eqalign_no_aligned\math_prepare_r_eqalign_no} +\def\math_handle_eqalign_no_l_aligned{\math_both_eqalign_no_aligned\math_prepare_l_eqalign_no} +\def\math_finish_eqalign_no {\crcr\egroup} + +\let\reqalignno\relax +\let\leqalignno\relax +\let\eqalignno \relax + +%D Here we implement the user interface part. We start with basic math alignments: + +\newcount \c_math_eqalign_column +\newconditional\c_math_eqalign_first + +\newtoks \everymathalignment +\newtoks \everymathalignmentdone + +\permanent\tolerant\protected\def\math_alignment_NN[#1]#*[#2]% + {\aligntab + \strc_formulas_place_number_nested{#1}{#2}} + +\permanent\tolerant\protected\def\math_alignment_NR[#1]#*[#2]% + {\aligntab + \dostoptagged % finish cell + \strc_formulas_place_number_nested{#1}{#2}% + \math_number_right_of_eqalign + \global\settrue\c_math_eqalign_first + \crcr + \dostoptagged} % finish row + +\permanent\protected\def\math_alignment_NC + {\relax + \ifconditional\c_math_eqalign_first + \ifx\p_math_alignment_number\v!auto + \strc_formulas_place_number_nested{+}{}% + \fi + \global\setfalse\c_math_eqalign_first + \fi + \math_number_left_of_eqalign + \aligntab} + +\permanent\protected\def\math_alignment_EQ + {\NC=} + +\installmacrostack\NC % maybe more to shared table definitions +\installmacrostack\NN % maybe more to shared table definitions +\installmacrostack\EQ % maybe more to shared table definitions +\installmacrostack\NR % maybe more to shared table definitions +\installmacrostack\BC % maybe more to shared table definitions +\installmacrostack\EC % maybe more to shared table definitions + +\appendtoks + \push_macro_NC + \push_macro_NN + \push_macro_EQ + \push_macro_NR + \enforced\let\NC\math_alignment_NC + \enforced\let\NN\math_alignment_NN + \enforced\let\EQ\math_alignment_EQ + \enforced\let\NR\math_alignment_NR + \global\settrue\c_math_eqalign_first +\to \everymathalignment + +\appendtoks + \pop_macro_NR + \pop_macro_EQ + \pop_macro_NN + \pop_macro_NC +\to \everymathalignmentdone + +\let\math_alignment_snap_start\relax +\let\math_alignment_snap_stop \relax + +% % experimental: +% +% \def\math_alignment_snap_start +% {\ifgridsnapping +% \edef\p_math_alignment_grid{\mathalignmentparameter\c!grid}% +% \ifx\p_math_alignment_grid\v!no\else +% \snaptogrid[\p_math_alignment_grid]\vbox\bgroup +% \fi +% \fi} +% +% \def\math_alignment_snap_stop +% {\ifgridsnapping +% \ifx\p_math_alignment_grid\v!no\else +% \egroup +% \fi +% \fi} +% +% % doesn't work well, so: + +\let\math_alignment_snap_start\relax +\let\math_alignment_snap_stop \relax + +% end of experimental + +\newconditional\c_math_alignment_auto_number + +% \begingroup not permitted ($$...assignments...\halign... ).. check in luametatex + +\permanent\tolerant\protected\def\math_alignment_start[#1]#*[#2]% + {\edef\currentmathalignment{#1}% + \ifarguments\or\or + \setupmathalignment[#1][#2]% bad! ungrouped + \fi + \math_alignment_snap_start + \the\everymathalignment + \c_math_eqalign_column\zerocount + \edef\p_math_alignment_number{\mathalignmentparameter\c!number}% + \processcommacommand + [\mathalignmentparameter\c!align]% + {\advance\c_math_eqalign_column\plusone\math_eqalign_set_column}% takes argument + \global\c_math_eqalign_column\plusone + \dostarttagged\t!math\empty + \dostarttagged\t!mathtable\currentmathalignment + \numberedeqalign} + +\def\math_alignment_stop + {\math_finish_eqalign_no + \dostoptagged + \dostoptagged + \the\everymathalignmentdone + \math_alignment_snap_stop} + +\installcorenamespace{mathalignment} +\installcorenamespace{mathalignmentvariant} + +\installcommandhandler \??mathalignment {mathalignment} \??mathalignment + +\appendtoks + \setuevalue{\e!start\currentmathalignment}{\math_alignment_start[\currentmathalignment]}% + \setvalue {\e!stop \currentmathalignment}{\math_alignment_stop}% +\to \everydefinemathalignment + +\setupmathalignment + [\c!n=2, + \c!m=1, + \c!distance=\emwidth, + \c!grid=\v!math] + +\definemathalignment[align] % default case (this is what amstex users expect) +\definemathalignment[\v!mathalignment] % prefered case (this is cleaner, less clashing) + +% special case.. in case one mistypes .. + +\ifdefined \startalignment + + \let\align_math_normal_start\startalign + \let\align_math_normal_stop \stopalign + + \let\align_text_normal_start\startalignment + \let\align_text_normal_stop \stopalignment + + \permanent\overloaded\protected\def\startalign + {\ifmmode + \enforced\let\stopalign\align_math_normal_stop % cannot be an unexpanded def ... lookahead in align + \expandafter\align_math_normal_start + \orelse\ifinformula + \enforced\let\stopalign\align_math_normal_stop + \expandafter\align_math_normal_start + \else + \enforced\let\stopalign\align_text_normal_stop + \expandafter\align_text_normal_start + \fi} + + \overloaded\let\stopalign\relax + + \permanent\overloaded\protected\def\startalignment + {\ifmmode + \enforced\let\stopalignment\align_math_normal_stop % cannot be an unexpanded def ... lookahead in align + \expandafter\align_math_normal_start + \orelse\ifinformula + \enforced\let\stopalignment\align_math_normal_stop % cannot be an unexpanded def ... lookahead in align + \expandafter\align_math_normal_start + \else + \enforced\let\stopalignment\align_text_normal_stop + \expandafter\align_text_normal_start + \fi} + + \overloaded\let\stopalignment\relax + +\fi + +% + +\permanent\protected\def\numberedeqalign + {\doifelse{\formulaparameter\c!location}\v!left + \math_handle_eqalign_no_l_aligned + \math_handle_eqalign_no_r_aligned} + +\def\math_first_in_eqalign + {\global\c_math_eqalign_column\plusone + \dostarttagged\t!mathtablerow \empty + \dostarttagged\t!mathtablecell\empty} + +\def\math_next_in_eqalign + {\global\advance\c_math_eqalign_column\plusone + \dostoptagged % finish cell + \dostarttagged\t!mathtablecell\empty} + +\def\math_left_of_eqalign + {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname + \ifcase\lastnamedcs \or \relax \or \hfill \or \hfill \fi + \fi} + +\def\math_right_of_eqalign + {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname + \ifcase\lastnamedcs \or \hfill \or \relax \or \hfill \fi + \fi} + +\newconditional\c_math_alignment_local_number % not used but when true puts in front (todo) + +\def\math_number_right_of_eqalign + {\ifcase\wd\b_strc_formulas_number\else + \ifconditional\c_math_alignment_local_number + \ifcase\c_strc_math_number_location\or\or + \box\b_strc_formulas_number + \fi + \else + \box\b_strc_formulas_number + \fi + \fi} + +\def\math_number_left_of_eqalign + {\ifcase\wd\b_strc_formulas_number\else + \ifconditional\c_math_alignment_local_number + \ifcase\c_strc_math_number_location\or + \box\b_strc_formulas_number + \fi + \fi + \fi} + +% \def\math_eqalign_set_column#1% we could just add to the preamble (as with other alignments) +% {\expandafter\let\csname\??mathalignmentvariant\number\c_math_eqalign_column\expandafter\endcsname +% \csname\??mathalignmentvariant\ifcsname\??mathalignmentvariant#1\endcsname#1\else\v!normal\fi\endcsname} + +\def\math_eqalign_set_column#1% we could just add to the preamble (as with other alignments) + {\expandafter\chardef\csname\??mathalignmentvariant\number\c_math_eqalign_column\expandafter\expandafter\expandafter\endcsname + \ifcsname\??mathalignmentvariant#1\endcsname\lastnamedcs\else\zerocount\fi\relax} + +\letvalue{\??mathalignmentvariant\v!normal}\zerocount +\letvalue{\??mathalignmentvariant\v!left }\plusone +\letvalue{\??mathalignmentvariant\v!right }\plustwo +\letvalue{\??mathalignmentvariant\v!middle}\plusthree + +\permanent\protected\def\math_align_NR_generic[#1][#2]% + {\strc_formulas_place_number_nested{#1}{#2}\crcr} + +%D \starttyping +%D \placeformula[eqn0]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn0] +%D \placeformula[eqn1]\startformula \startalign[n=1] a\NR \stopalign \stopformula See \in[eqn1] +%D \placeformula \startformula \startalign[n=1] a\NR[eqn2] \stopalign \stopformula See \in[eqn2] +%D \placeformula[eqn3]\startformula \startalign[n=1] a\NR[+] \stopalign \stopformula See \in[eqn3] +%D \stoptyping + +%D \startbuffer +%D \placeformula \startformula \eqalignno { +%D a &= b & \formulanumber \cr +%D c &= d \cr +%D &= e \cr +%D &= f & \formulanumber +%D } \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula \startalign +%D \NC a \EQ b \NR[+] +%D \NC c \EQ d \NR +%D \NC \EQ f \NR[for:demo-a-1] +%D \NC \EQ g \NR[for:demo-a-2][a] +%D \NC \EQ h \NR[for:demo-a-3][b] +%D \NC \EQ i \NR +%D \stopalign \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula \startalign +%D \NC a \EQ b \NR[+] +%D \NC c \EQ d \NR +%D \NC \EQ f \NR +%D \NC \EQ g \NR +%D \NC \EQ h \NR +%D \NC \EQ i \NR[+] +%D \stopalign \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula \startalign +%D \NC a \NC \eq b \NR[+] +%D \NC c \NC \neq d \NR +%D \NC \NC \neq f \NR[for:demo-b-1] +%D \NC \NC \geq g \NR[for:demo-b-2][a] +%D \NC \NC \leq h \NR[for:demo-b-3][b] +%D \NC \NC \neq i \NR +%D \stopalign \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula \startalign[n=3,align={left,middle,right}] +%D \NC l \NC = \NC r \NR +%D \NC left \NC = \NC right \NR +%D \stopalign \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula \startalign[n=3,align={right,middle,left}] +%D \NC l \NC = \NC r \NR +%D \NC left \NC = \NC right \NR +%D \stopalign \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula \startalign[n=3,align={middle,middle,middle}] +%D \NC l \NC = \NC r \NR +%D \NC left \NC = \NC right \NR +%D \stopalign \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula +%D \startformula +%D \startalign[n=3,align={middle,middle,middle}] +%D \NC a \NC = \NC b \NR[+] +%D \NC 2a \NC = \NC 2b \NR +%D \stopalign +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula +%D \startformulas +%D \setupmathalignment[n=3,align={middle,middle,middle}]% +%D \startformula +%D \startalign +%D \NC a \NC = \NC b \NR[+] +%D \NC 2a \NC = \NC 2b \NR +%D \stopalign +%D \stopformula +%D \startformula +%D \startalign +%D \NC a \NC = \NC b \NR[+] +%D \NC 2a \NC = \NC 2b \NR +%D \stopalign +%D \stopformula +%D \stopformulas +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula +%D \startformulas +%D \dorecurse{5}{\startformula +%D \startalign[n=3,align={middle,middle,middle}] +%D \NC a \NC = \NC b \NR[+] +%D \NC 2a \NC = \NC 2b \NR +%D \stopalign +%D \stopformula} +%D \stopformulas +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \macros +%D {definemathcases, setupmathcases, startmathcases} +%D +%D Another wish \unknown + +\installcorenamespace{mathcases} + +\installcommandhandler \??mathcases {mathcases} \??mathcases + +\setupmathcases + [\c!distance=\emwidth, + \c!strut=\v!yes, % new + \c!numberdistance=2.5\emwidth, + \c!left={\left\{\mskip\thinmuskip}, + \c!right={\right.}] + +\appendtoks + \setuevalue{\e!start\currentmathcases}{\math_cases_start[\currentmathcases]}% + \setvalue {\e!stop \currentmathcases}{\math_cases_stop}% +\to \everydefinemathcases + +\permanent\protected\def\math_cases_NC_zero + {\math_cases_NC} + +\permanent\protected\def\math_cases_MC_zero + {\math_cases_NC + \ifmmode\else + \startimath + \enforced\let\math_cases_end_math\stopimath + \fi} + +\let\math_cases_end_math\relax + +\permanent\protected\def\math_cases_NR_zero + {\unskip + \math_cases_end_math + \aligntab + \global\enforced\let\math_cases_NC\math_cases_NC_first + \dodirectdoubleempty\math_cases_NR} + +\permanent\protected\def\math_cases_NC_first + {\global\enforced\let\math_cases_NC\math_cases_NC_second} + +\permanent\protected\def\math_cases_NC_second + {\math_cases_end_math\aligntab} + +\let\math_cases_NR\math_align_NR_generic + +\installmacrostack\math_cases_NC + +\permanent\tolerant\protected\def\math_cases_start[#1]#*[#2]% + {\begingroup + \edef\currentmathcases{#1}% + \ifarguments\or\or + \setupcurrentmathcases[#2]% + \fi + \edef\p_strut{\mathcasesparameter\c!strut}% + \ifx\p_strut\v!yes + \enforced\let\math_cases_strut\strut + \else + \enforced\let\math_cases_strut\relax + \fi + \mathcasesparameter\c!left + \vcenter\bgroup + \push_macro_math_cases_NC + \enforced\let\endmath\relax + \enforced\let\NC\math_cases_NC_zero + \enforced\let\MC\math_cases_MC_zero + \enforced\let\NR\math_cases_NR_zero + \global\enforced\let\math_cases_NC\math_cases_NC_first + \normalbaselines + \mathsurround\zeropoint + \everycr\emptytoks + \tabskip\zeropoint + \global\c_math_eqalign_column\plusone + \halign\bgroup + \startimath + \mathcasesparameter\c!style + \alignmark\alignmark + \stopimath + \hfil + \aligntab + \hskip\mathcasesparameter\c!distance\relax + \pop_macro_math_cases_NC + \math_cases_strut % looks better + \alignmark\alignmark + \hfil + \aligntab + \hskip\mathcasesparameter\c!numberdistance\relax + \let\formuladistance\!!zeropoint + \span\math_text_in_eqalign{\alignmark\alignmark}% + \crcr} % todo: number + +\def\math_cases_stop + {\crcr + \egroup + \popmacro\math_cases_NC + \egroup + \mathcasesparameter\c!right + \endgroup} + +\definemathcases[cases] +\definemathcases[\v!mathcases] + +%D \startbuffer +%D \placeformula \startformula \startcases +%D \NC 2 \NC $ y > 0 $ \NR +%D \NC 7 \NC $ x = 7 $ \NR[+] +%D \NC 4 \NC otherwise \NR +%D \stopcases \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula x \startcases +%D \NC 2 \NC $ y > 0 $ \NR[+] +%D \NC 7 \NC $ x = 7 $ \NR +%D \NC 4 \NC otherwise \NR +%D \stopcases \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula \startcases +%D \NC 2 \NC $ y > 0 $ \NR +%D \NC 7 \NC $ x = 7 $ \NR +%D \NC 4 \NC otherwise \NR +%D \stopcases \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \placeformula \startformula x \startcases +%D \NC 2 \NC $ y > 0 $ \NR +%D \NC 7 \NC $ x = 7 $ \NR +%D \NC 4 \NC otherwise \NR +%D \stopcases \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \macros +%D {definemathmatrix, setupmathmatrix, startmathmatrix} +%D +%D Yet another one \unknown. This time we implement the lot a bit +%D different which is a side effect of getting the tagging right. In +%D retrospect the main alignment could be done this way but \unknown + +\installcorenamespace{mathmatrix} + +\installcommandhandler \??mathmatrix {mathmatrix} \??mathmatrix + +\setupmathmatrix + [\c!distance=\emwidth, + \c!left=, + \c!right=, + \c!align=\v!middle] + +\appendtoks + \setuevalue{\e!start\currentmathmatrix}{\math_matrix_start[\currentmathmatrix]}% + \setvalue {\e!stop \currentmathmatrix}{\math_matrix_stop}% no u else lookahead problem +\to \everydefinemathmatrix + +\def\math_matrix_start_table + {\global\c_math_eqalign_column\zerocount + \dostarttagged\t!math\empty + \dostarttagged\t!mathtable\empty} + +\def\math_matrix_stop_table + {\dostoptagged + \dostoptagged} + +\def\math_matrix_start_row + {\noalign{\global\c_math_eqalign_column\zerocount}% + \dostarttagged\t!mathtablerow\empty} + +\def\math_matrix_stop_row + {\dostoptagged} + +\protected\def\math_matrix_start_cell + {\dostarttagged\t!mathtablecell\empty + \hss + \math_left_of_eqalign + \startimath + \math_matrix_set_style + \tabskip\zeropoint + \everycr\emptytoks} + +\protected\def\math_matrix_stop_cell + {\stopimath + \math_right_of_eqalign + \hss + \dostoptagged} + +% We could construct a preamble with alignment and such embedded but the number +% of matrices with many rows is normally so low that it doesn't pay of at all. + +\protected\def\math_matrix_distance + {\relax + \ifdim\d_math_eqalign_distance>\zeropoint + \hskip\d_math_eqalign_distance + \fi + \relax} + +\def\math_matrix_preamble + {\math_matrix_strut + \global\advance\c_math_eqalign_column\plusone + \math_matrix_start_cell + \alignmark\alignmark + \math_matrix_stop_cell + \aligntab + \aligntab + \math_matrix_distance + \global\advance\c_math_eqalign_column\plusone + \math_matrix_start_cell + \alignmark\alignmark + \math_matrix_stop_cell} + +\newconditional\c_math_matrix_first + +\permanent\protected\def\math_matrix_NR + {\aligntab\omit + \math_matrix_stop_row + \math_matrix_pickup + \crcr + \math_matrix_start_row} + +\permanent\protected\def\math_matrix_NC + {\ifconditional\c_math_matrix_first + \expandafter\math_matrix_NC_yes + \else + \expandafter\math_matrix_NC_nop + \fi} + +\permanent\protected\def\math_matrix_pickup{\global\settrue \c_math_matrix_first} +\permanent\protected\def\math_matrix_NC_yes{\global\setfalse\c_math_matrix_first} +\permanent\protected\def\math_matrix_NC_nop{\aligntab} % avoids lookahead + +% \def\math_matrix_stop_wrapup +% {\crcr +% \strut +% \crcr +% \noalign{\vskip-\struthtdp}} + +\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\endmath\relax + % + \setbox\nextbox\vbox\bgroup + \math_matrix_start_table + \halign \bgroup + % preamble + \span\math_matrix_preamble + % done + \crcr + \math_matrix_start_row} + +\def\math_matrix_stop_processing + {%\math_matrix_stop_wrapup % optional + \math_matrix_stop_row + \egroup + \math_matrix_stop_table + \egroup + \mathmatrixleft + \math_matrix_finish_nextbox + \mathmatrixright + \egroup} + +\let\math_matrix_strut \strut +\let\math_matrix_set_style\relax + +\def\math_matrix_check_settings + {\edef\p_strut{\mathmatrixparameter\c!strut}% + \ifx\p_strut\v!no + \enforced\let\math_matrix_strut\relax + \else + \enforced\let\math_matrix_strut\strut + \ifx\p_strut\v!yes\else + \spacing\p_strut + \fi + \fi + \d_math_eqalign_distance\mathmatrixparameter\c!distance\relax + \edef\math_matrix_set_style{\mathmatrixparameter\c!style}} + +\def\math_matrix_set_defaults + {\normalbaselines % hm, spacing ? + \mathsurround\zeropoint + \tabskip\zeropoint} + +\def\math_matrix_set_columns_step + {\advance\c_math_eqalign_column\plusone + %\c_math_matrix_columns\c_math_eqalign_column + \math_eqalign_set_column} + +\def\math_matrix_set_columns + {\c_math_eqalign_column\zerocount + \rawprocesscommacommand[\mathmatrixparameter\c!align]\math_matrix_set_columns_step} + +\newcount\c_math_eqalign_column_saved + +% \installglobalmacrostack\c_math_matrix_first + +\tolerant\protected\def\math_matrix_start[#1]#*[#2]% + {\begingroup + \globalpushmacro\c_math_matrix_first % hm, does that work? + \c_math_eqalign_column_saved\c_math_eqalign_column + \globalpushmacro\c_math_eqalign_first + \edef\currentmathmatrix{#1}% + \setupcurrentmathmatrix[#2]% + \math_matrix_check_settings + \math_matrix_set_defaults + \math_matrix_set_columns + \math_matrix_start_processing} + +\def\math_matrix_stop + {\math_matrix_stop_processing + \globalpushmacro\c_math_eqalign_first + \global\c_math_eqalign_column\c_math_eqalign_column_saved + \globalpopmacro\c_math_matrix_first + \endgroup} + +% vcenter: +% +% delta = (height(v) + depth(v))/2 +% axis = math_axis_size(cur_size) +% height(v) = delta + axis +% depth(v) = delta - axis + +\installcorenamespace{mathmatrixalignlocation} + +\let\mathmatrixleft \empty % experimental hook +\let\mathmatrixright\empty % experimental hook + +\setvalue{\??mathmatrixalignlocation\v!top }{\raise\dimexpr(\nextboxdp-\nextboxht)/2 +\mathaxisheight\mathstyle\relax} +\setvalue{\??mathmatrixalignlocation\v!high }{\raise\dimexpr(\nextboxdp-\nextboxht)/2\relax} +\setvalue{\??mathmatrixalignlocation\v!center}{\relax} +\setvalue{\??mathmatrixalignlocation\v!lohi} {\relax} +\setvalue{\??mathmatrixalignlocation\v!normal}{\relax} +\setvalue{\??mathmatrixalignlocation\v!bottom}{\lower\dimexpr(\nextboxdp-\nextboxht)/2 +\mathaxisheight\mathstyle\relax} +\setvalue{\??mathmatrixalignlocation\v!low }{\lower\dimexpr(\nextboxdp-\nextboxht)/2\relax} + +\def\math_matrix_finish_nextbox + {\begincsname\??mathmatrixalignlocation\mathmatrixparameter\c!location\endcsname\hbox\bgroup + \normalstartimath + \mathmatrixparameter\c!left + \vcenter{\box\nextbox}% + \mathmatrixparameter\c!right + \normalstopimath + \egroup} + +\definemathmatrix[matrix] +\definemathmatrix[\v!mathmatrix] + +%D \startbuffer +%D \placeformula \startformula[-] \startmatrix +%D \NC 1 \NC x \NC a \NR +%D \NC 2 \NC y \NC b \NR +%D \NC 3 \NC z \NC c \NR +%D \stopmatrix \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \definemathmatrix[bmatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]},strut=1.25] +%D +%D \startbuffer +%D \placeformula \startformula[-] \startbmatrix +%D \NC 1 \NC x \NC a \NR +%D \NC 2 \NC y \NC b \NR +%D \NC 3 \NC z \NC c \NR +%D \stopbmatrix \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D Taco added some code (dedicated to Aditya Mahajan) that gives more +%D control over aligments: + +%D \startbuffer +%D \startformula +%D \startmatrix +%D \NC a + x \NC = \NC a + d \NR +%D \NC y \NC = \NC d \NR +%D \stopmatrix +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \startbuffer +%D \startformula +%D \startmatrix [distance=3pt,align={right,left}] +%D \NC a + x \NC = a + d \NR +%D \NC y \NC = d \NR +%D \stopmatrix +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \startbuffer +%D \startformula +%D \startmatrix [left=\left(,right=\right)] +%D \NC a + x \NR +%D \NC y \NR +%D \stopmatrix +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D A bit more complex code: +%D +%D \startbuffer +%D \startformula +%D \text{Let }{\cal R} = \bigcup_{P_{X_1},P_{X_2}} +%D \left\{ (R_1, R_2) : +%D \startmatrix[distance=1em,align={left,left,right}] +%D \NC R_1 \NC < I(X_1 ; Y \mid X_2) \NC R_1 \NR +%D \NC \hfill Q_2 \NC < I(X_2 ; Y \mid X_1) \NC R_2 \NR +%D \NC R_1 + R_2 \NC < I(X_1 ; Y) \NC R_1 + R_2 \NR +%D \stopmatrix +%D \right\} +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \macros +%D {startmatrices} +%D +%D Just a handy keystroke safer: + +\permanent\protected\def\startmatrices + {\begingroup + \setupmathmatrix} + +\permanent\protected\def\stopmatrices + {\endgroup} + +%D \startbuffer +%D \startformula +%D \startmatrix[left={\left(},right={\right)}] +%D \NC A \NC B \NR \NC C \NC D \NR +%D \stopmatrix +%D = +%D \startmatrix[left={\left(},right={\right)},location=low] +%D \NC A \NC B \NR \NC C \NC D \NR +%D \stopmatrix +%D = +%D \startmatrix[left={\left(},right={\right)},location=high] +%D \NC A \NC B \NR \NC C \NC D \NR +%D \stopmatrix +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \startformula +%D \startmatrices[left={\left(},right={\right)}] +%D \startmatrix +%D \NC A \NC B \NR \NC C \NC D \NR +%D \stopmatrix +%D = +%D \startmatrix[location=bottom] +%D \NC A \NC B \NR \NC C \NC D \NR +%D \stopmatrix +%D = +%D \startmatrix[location=top] +%D \NC A \NC B \NR \NC C \NC D \NR +%D \stopmatrix +%D \stopmatrices +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer % does not run well: \getbuffer + +%D Handy for the \type {m-matrix} module: + +\permanent\tolerant\protected\def\startnamedmatrix[#1]#*[#2]% + {\begingroup + \edef\currentmathmatrix{#1}% + \setupcurrentmathmatrix[#2]% + \math_matrix_start[\currentmathmatrix]} + +\permanent\protected\def\stopnamedmatrix + {\math_matrix_stop + \endgroup} + +%D The following code is derived from Aditya's simplematrix prototype but +%D adapted to regular mathmatrices (which saves some code so it can go into +%D the core): + +\def\math_matrix_simple_row#1% + {\rawprocesscommalist[#1]\math_matrix_simple_col + \toksapp\scratchtoks{\NR}} + +\def\math_matrix_simple_col#1% + {\toksapp\scratchtoks{\NC#1}} + +\permanent\tolerant\protected\def\math_matrix_simple[#1]#*[#2]#:#3% + {\begingroup + \edef\currentmathmatrix{#1}% + \setupcurrentmathmatrix[#2]% + \scratchtoks\emptytoks + \processlist[];\math_matrix_simple_row[#3]% + \math_matrix_start[\currentmathmatrix]% + \the\scratchtoks + \math_matrix_stop + \endgroup} + +%D We hook it into the normal mathmatrix code: + +\appendtoks + \edef\p_simplecommand{\mathmatrixparameter\c!simplecommand}% + \ifx\p_simplecommand\empty\else + \setuevalue{\p_simplecommand}{\math_matrix_simple[\currentmathmatrix]}% + \fi +\to \everydefinemathmatrix + +%D And predefine some matrices: + +\definemathmatrix[matrix:parentheses][\c!left={\left(\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right)},\c!align=\v!middle] +\definemathmatrix[matrix:brackets] [\c!left={\left[\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right]},\c!align=\v!middle] +\definemathmatrix[matrix:bars] [\c!left={\left|\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right|},\c!align=\v!middle] + +\definemathmatrix[thematrix][matrix:parentheses][\c!simplecommand=thematrix] + +%D \startbuffer +%D \startformula +%D \thematrix{1,2,3,4;5,6,7,8;9,10,11,12} +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D \startbuffer +%D \startformula +%D \startthematrix +%D \NC 1\NC 2\NC 3\NC 4\NR +%D \NC 5\NC 6\NC 7\NC 8\NR +%D \NC 9\NC10\NC11\NC12\NR +%D \stopthematrix +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +%D \macros +%D {startintertext} +%D +%D Preliminary feature: +%D +%D {\em example code} +%D +%D The intertext commands have to be expandable (in aligment lookahead) so +%D we cannot use \type {\protected}. + +\permanent\def\startintertext#1\stopintertext + {\noalign{\math_intertext{#1}}} + +\permanent\let\stopintertext\relax + +\permanent\def\intertext#1% + {\noalign{\math_intertext{#1}}} + +\protected\def\math_intertext#1% + {\penalty\postdisplaypenalty + \afterdisplayspace + \vbox{\forgetall\noindent#1\par}% + \penalty\predisplaypenalty + \beforedisplayspace} + +%D \macros +%D {substack} +%D +%D Preliminary code: +%D +%D \startbuffer +%D \startformula +%D \sum_{% +%D \startsubstack +%D i = 1 \NR +%D i \neq n \NR +%D i \neq m +%D \stopsubstack +%D }a_i +%D \stopformula +%D \stopbuffer +%D +%D \getbuffer which was typed as \typebuffer +%D +%D Notice that these macros give the correct spacing for +%D subscripts. Compare for example +%D +%D \startbuffer +%D \startformula +%D \sum_{\startsubstack a \NR b \NR \stopsubstack} +%D \text{ and } +%D \sum_{\scriptstyle a \atop \scriptstyle} +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer which gives \getbuffer + +% no tagging yet : how is it supposed to be coded? + +\permanent\protected\def\startsubstack + {\begingroup + \vcenter\bgroup + \baselineskip\mathstacktotal + \lineskip\mathstackvgap + \lineskiplimit\lineskip + \mathsurround\zeropoint + \everycr\emptytoks + \enforced\let\NC\relax + \enforced\let\MC\relax + \enforced\let\NR\crcr + \halign\bgroup\hfil\normalstartimath\scriptstyle\alignmark\alignmark\normalstopimath\hfil\crcr} + +\permanent\def\stopsubstack % todo: \protected and delayed + {\crcr + \egroup + \egroup + \endgroup} + +% %D \macros +% %D {bordermatrix} +% %D +% %D In \PLAIN\ \TEX\ the width of a parenthesis is stored in +% %D the \DIMENSION\ \type{\mathparentwd}. This value is derived from +% %D the width of \type{\tenrm B}, so let's take care of it now: +% +% \ifx\mathparentwd\undefined \newdimen\mathparentwd \fi +% +% \let\normalbordermatrix\bordermatrix % move that code to here instead +% +% \protected\def\bordermatrix +% {\begingroup +% \setbox\scratchbox\hbox{\mr\char"239C}% +% \global\mathparentwd\wd\scratchbox +% \endgroup +% \normalbordermatrix} +% +% \def\bordermatrix +% {\begingroup +% \mr +% \global\mathparentwd\fontcharwd\font"239C\relax +% \endgroup +% \normalbordermatrix} + +%D \macros{overset, underset} +%D +%D The macros \type{\overset} and \type{\underset} are provided by +%D \AMS\ packages in \LATEX. These macro allows you to place a symbol +%D above or below another symbol, irrespective of whether the other +%D symbol is a relation or something else, and without influencing the +%D spacing. For most cases there is a better way to do such things +%D (declaring a math command with limop option, or using accents), but +%D occasionally these macros can be useful, for example: +%D +%D \startbuffer +%D \startformula +%D \overset{*}{X} \underset{*}{X} +%D \stopformula +%D \stopbuffer +%D \typebuffer \getbuffer +%D +%D Use these macros sparingly. Remember, \TEX\ was designed for +%D mathematics, so there is usually a proper method for typesetting +%D common math notation. +%D +%D These macros are a cleaner version of \type {\binrel@} and +%D \type {\binrel@@} macros in \AMSTEX\ packages. + +\def\math_binrel_apply#1% + {\begingroup + \setbox\scratchbox\hbox + {\thinmuskip 0mu + \medmuskip -1mu + \thickmuskip -1mu + \setbox\scratchbox\hbox{\normalstartimath#1\mathsurround\zeropoint\normalstopimath}% + \kern-\wd\scratchbox + \normalstartimath{}#1{}\mathsurround\zeropoint\normalstopimath}% + \ifdim\wd\scratchbox<\zeropoint + \endgroup + \expandafter\mathbin + \orelse\ifdim\wd\scratchbox>\zeropoint + \endgroup + \doubleexpandafter\mathrel + \else + \endgroup + \doubleexpandafter\firstofoneargument + \fi} + +\permanent\protected\def\overset#1#2% + {\math_binrel_apply{#2}{\mathop{\kern\zeropoint#2}\limits\normalsuperscript{#1}}} + +\permanent\protected\def\underset#1#2% + {\math_binrel_apply{#2}{\mathop{\kern\zeropoint#2}\limits\normalsubscript {#1}}} + +%D The following code comes from \type {math-str.mkiv}. +%D +%D Here we implement a basic math alignment mechanism. Numbers are also handled. The macros +%D \type {\startinnermath} and \type {\stopinnermath} can be overloaded in specialized +%D modules. + +\installcorenamespace{mathinnerstart} +\installcorenamespace{mathinnerstop} + +% \protected\def\startinnermath{\csname\??mathinnerstart\formulaparameter\c!align\endcsname} +% \protected\def\stopinnermath {\csname\??mathinnerstop \formulaparameter\c!align\endcsname} + +\permanent\protected\def\startinnermath{\expandnamespaceparameter\??mathinnerstart\formulaparameter\c!align\v!normal} +\permanent\protected\def\stopinnermath {\expandnamespaceparameter\??mathinnerstop \formulaparameter\c!align\v!normal} + +\permanent\protected\def\mathinnerstrut + {\doif{\formulaparameter\c!strut}\v!yes\strut} + +\permanent\protected\def\defineinnermathhandler#1#2#3% + {\setvalue{\??mathinnerstart#1}{#2}% + \setvalue{\??mathinnerstop #1}{#3}} + +\installtextracker + {formulas.boxes} + {\enforced\let\math_hbox\ruledhbox} + {\enforced\let\math_hbox\hbox} + +\let\math_hbox\hbox + +\newconstant\mathraggedstatus % normal left center right +\newconstant\mathnumberstatus % nothing normal shift_right + +\newdimen\d_math_number_correction + +\def\math_box_llapped_math_no + {\ifcase\mathraggedstatus\or + \box\b_strc_formulas_number + \or + \llap{\box\b_strc_formulas_number}% + \or + \llap{\box\b_strc_formulas_number}% + \fi} + +\def\math_box_rlapped_math_no + {\ifcase\mathraggedstatus\or + \rlap{\box\b_strc_formulas_number}% + \or + \rlap{\box\b_strc_formulas_number}% + \or + \box\b_strc_formulas_number + \fi} + +\newconditional\c_strc_math_has_number +\newconditional\c_strc_math_display_overflow +\newconstant \c_strc_math_number_location +\newdimen \d_strc_math_number_width +\newdimen \d_strc_math_display_width +\newbox \b_strc_math_display +\newconstant \c_strc_formulas_frame_mode +\newdimen \d_strc_math_indent +\newconditional\c_strc_math_indent + +\let\d_strc_math_framed_width\displaywidth + +\setvalue{\??formulaoption\v!frame}% + {\edef\p_frame{\formulaparameter\c!frame}% + \ifx\p_frame\v!number + \c_strc_formulas_frame_mode\plustwo % inside frame + \else + \c_strc_formulas_frame_mode\plusone % outside frame + \fi} + +% mode: 0=no frame | 1=number inside frame | 2=number outside frame + +\def\strc_math_flush_aligned + {\ifcase\c_strc_math_vertical + \ifcase\mathraggedstatus\or\hfill\or\hfill\fi + \box\b_strc_math_display + \ifcase\mathraggedstatus\or\or\hfill\or\hfill\fi + \else + \ifconditional\c_strc_math_indent + \ifzeropt\d_strc_math_indent\else + \hangafter\plusone + \hangindent\d_strc_math_indent + \fi + \fi + \edef\p_interlinespace{\formulaparameter\c!interlinespace}% + \ifx\p_interlinespace\empty\else\baselineskip\p_interlinespace\fi + \global\d_strc_math_indent\zeropoint + \ifcase\mathraggedstatus\or\raggedleft\or\raggedcenter\or\raggedright\fi + \unhbox\b_strc_math_display + \fi} + +\def\strc_math_flush_box_normal + {\ifcase\c_strc_math_vertical + \hbox to \displaywidth\bgroup + \strc_math_flush_aligned + \egroup + \else + \strc_math_flush_aligned + \fi} + +\def\strc_math_flush_box_framed_common + {\setformulaframedparameter\c!align{\formulaparameter\c!align}% + \letformulaframedparameter\c!strut\v!no + \d_framed_formula\ht\b_strc_math_display + \ifcase\mathraggedstatus\or\hfill\or\hfill \fi + \inheritedformulaframedframed{\box\b_strc_math_display}% + \ifcase\mathraggedstatus\or \or\hfill\or\hfill\fi} + +% \def\strc_math_flush_box_framed_inline +% {\letformulaframedparameter\c!location\empty +% \letformulaframedparameter\c!width\displaywidth +% \strc_math_flush_box_framed_common} + +\def\strc_math_flush_box_framed_display + {\let\currentformulaframed\currentformula + \letformulaframedparameter\c!location\v!formula + \setformulaframedparameter\c!width{\d_strc_math_framed_width}% + \strc_math_flush_box_framed_common} + +\def\strc_math_flush_box_framed_fit_inline + {\let\currentformulaframed\currentformula + \letformulaframedparameter\c!location\empty + \letformulaframedparameter\c!width\v!fit + \strc_math_flush_box_framed_common} + +\def\strc_math_flush_box_framed_fit_display + {\let\currentformulaframed\currentformula + \letformulaframedparameter\c!location\v!formula + \letformulaframedparameter\c!width\v!fit + \strc_math_flush_box_framed_common} + +% combiners + +\def\strc_math_flush_box + {\ifcase\c_strc_formulas_frame_mode + \strc_math_flush_box_normal + \else + \strc_math_flush_box_framed_display + \fi} + +\def\strc_math_number_right_normal + {\strc_math_flush_aligned + \hss % hss makes room for number + \math_box_llapped_math_no} + +\def\strc_math_number_left_normal + {\math_box_rlapped_math_no + \strc_math_flush_aligned + \hss} % hss makes room for number + +\def\strc_math_number_right_normal_outside + {\ifconditional\c_strc_formulas_tight + \strc_math_flush_box_framed_fit_display + \else + \strc_math_flush_box_framed_display + \fi + \hss % hss makes room for number + \math_box_llapped_math_no} + +\def\strc_math_number_left_normal_outside + {\math_box_rlapped_math_no + \hss % hss makes room for number + \ifconditional\c_strc_formulas_tight + \strc_math_flush_box_framed_fit_display + \else + \strc_math_flush_box_framed_display + \fi} + +\def\strc_math_number_right_normal_inside + {\setbox\b_strc_math_display\hpack to \dimexpr\displaywidth-\d_framed_locator_lo-\d_framed_locator_ro\relax\bgroup + \strc_math_flush_aligned + \hss + \math_box_llapped_math_no + \egroup + \strc_math_flush_box_framed_fit_inline} + +\def\strc_math_number_left_normal_inside + {\setbox\b_strc_math_display\hpack to \dimexpr\displaywidth-\d_framed_locator_lo-\d_framed_locator_ro\relax\bgroup + \math_box_rlapped_math_no + \hss + \strc_math_flush_aligned + \egroup + \strc_math_flush_box_framed_fit_inline} + +\def\strc_math_number_right_overflow + {\vpack\bgroup + \strc_math_flush_box + \par + \hpack to \displaywidth\bgroup + \hss + \math_box_llapped_math_no + \egroup + \egroup} + +\def\strc_math_number_left_overflow + {\vpack\bgroup + \hpack to \displaywidth\bgroup + \math_box_rlapped_math_no + \hss + \egroup + \strc_math_flush_box + \egroup} + +\def\strc_math_number_right_overflow_outside + {\vpack\bgroup + \strc_math_flush_box_framed_fit_inline + %\hskip\zeropoint % nicely breaks the line without introducing funny vertical spacing ... why o why + \hpack to \displaywidth\bgroup + \hss + \math_box_llapped_math_no + \egroup + \egroup} + +\def\strc_math_number_left_overflow_outside + {\vpack\bgroup + \hpack to \dimexpr\displaywidth-\d_framed_locator_lo\relax\bgroup + \math_box_rlapped_math_no + \hss + \egroup + \hskip\zeropoint % nicely breaks the line without introducing funny vertical spacing ... why o why + \strc_math_flush_box_framed_fit_inline + \egroup} + +\def\strc_math_number_right_overflow_inside + {\setbox\b_strc_math_display\vpack\bgroup + \box\b_strc_math_display + \hpack to \displaywidth\bgroup + \hss + \math_box_llapped_math_no + \hskip\d_framed_locator_ro + \egroup + \egroup + \strc_math_flush_box_framed_fit_inline} + +\def\strc_math_number_left_overflow_inside + {\setbox\b_strc_math_display\vpack\bgroup + \hpack to \displaywidth\bgroup + % \hskip\d_framed_locator_lo + \math_box_rlapped_math_no + \hss + \egroup + \box\b_strc_math_display + \egroup + \strc_math_flush_box_framed_fit_inline} + +% checkers + +\def\strc_math_number_check + {\d_strc_math_display_width\wd\b_strc_math_display + \ifconditional\c_strc_formulas_tight + \ifdim\d_strc_math_display_width>\displaywidth + \settrue\c_strc_math_display_overflow + \else + \displaywidth\d_strc_math_display_width + \setfalse\c_strc_math_display_overflow + \fi + \else + \ifdim\d_strc_math_display_width>\displaywidth + \settrue\c_strc_math_display_overflow + \else + \setfalse\c_strc_math_display_overflow + \fi + \fi} + +\def\strc_math_number_check_outside + {\d_strc_math_display_width\naturalwd\b_strc_math_display + \ifdim\dimexpr\d_strc_math_display_width+\d_framed_locator_lo+\d_framed_locator_ro\relax>\displaywidth + \settrue\c_strc_math_display_overflow + \else + \setfalse\c_strc_math_display_overflow + \fi + % still ok? + \ifnum\mathraggedstatus=\plustwo + \edef\d_strc_math_framed_width{\the\dimexpr\displaywidth-2\wd\b_strc_formulas_number\relax}% + \else + \edef\d_strc_math_framed_width{\the\dimexpr\displaywidth-\wd\b_strc_formulas_number\relax}% + \fi} + +\let\strc_math_number_check_inside\strc_math_number_check_outside + +% offsets + +\def\strc_math_number_check_offsets + {\begingroup + \setbox\scratchbox\hbox + {\inheritedformulaframedframed + {\pack_framed_locator_set_lo\pack_framed_locator_set_ro}}% + \endgroup} + +% tracing + +\def\strc_math_traced_state_yes + {\llap{\setbox\scratchbox\hbox{\infofont + \ifcase\mathraggedstatus unset\or right\or middle\or left\fi + \space + \ifcase\c_strc_formulas_frame_mode no\or out\or in\fi + \space + \ifconditional\c_strc_math_display_overflow overflow\else fit\fi + \quad}\ht\scratchbox\zeropoint\dp\scratchbox\zeropoint\box\scratchbox}} + +\let\strc_math_traced_state\relax + +\installtextracker + {formulas.framed} + {\let\strc_math_traced_state\strc_math_traced_state_yes} + {\let\strc_math_traced_state\relax} + +% packaging + +\protected\def\strc_math_box_start#1% + {\hsize\displaywidth % \checkeddisplaymath + \global\mathnumberstatus\plusone + \mathraggedstatus#1\relax + % + \global\d_math_number_correction\zeropoint + % + \edef\p_location{\formulaparameter\c!location}% + \useformulacolorparameter\c!color + \c_strc_math_number_location\ifx\p_location\v!left\plusone\orelse\ifx\p_location\v!right\plustwo\else\zerocount\fi + % + %\strc_formulas_place_number % not here as we can have inner alignment numbers + \dontcomplain + \setbox\b_strc_math_display\math_hbox\bgroup % \checkeddisplaymath + \mathinnerstrut + \startforceddisplaymath} + +\def\strc_math_flush_number_no + {\ifcase\c_strc_math_vertical + \ifconditional\c_strc_math_display_overflow + \ifcase\c_strc_formulas_frame_mode + \strc_math_flush_box_normal + \else + \strc_math_flush_box_framed_fit_inline + \fi + \else + \ifcase\c_strc_formulas_frame_mode + %\ifconditional\c_strc_formulas_tight + % \strc_math_flush_box_normal + %\else + \strc_math_flush_box_normal + %\fi + \else + \ifconditional\c_strc_formulas_tight + \strc_math_flush_box_framed_fit_inline + \else + \strc_math_flush_box_framed_display + \fi + \fi + \fi + \else + \strc_math_flush_box + \fi} + +\def\strc_math_flush_number_left + {\ifcase\c_strc_math_vertical + \ifconditional\c_strc_math_display_overflow + \ifcase\c_strc_formulas_frame_mode + \strc_math_number_left_overflow + \or + \strc_math_number_left_overflow_outside + \or + \strc_math_number_left_overflow_inside + \fi + \else + \ifcase\c_strc_formulas_frame_mode + \strc_math_number_left_normal + \or + \strc_math_number_left_normal_outside + \or + \strc_math_number_left_normal_inside + \fi + \fi + \else + \box\b_strc_formulas_number + \hfill + \strc_math_flush_aligned + \fi} + +\def\strc_math_flush_number_right + {\ifcase\c_strc_math_vertical + \ifconditional\c_strc_math_display_overflow + \ifcase\c_strc_formulas_frame_mode + \strc_math_number_right_overflow + \or + \strc_math_number_right_overflow_outside + \or + \strc_math_number_right_overflow_inside + \fi + \else + \ifcase\c_strc_formulas_frame_mode + \strc_math_number_right_normal + \or + \strc_math_number_right_normal_outside + \or + \strc_math_number_right_normal_inside + \fi + \fi + \else + \strc_math_flush_aligned + \hfill + \box\b_strc_formulas_number + \fi} + +\protected\def\strc_math_box_stop + {\stopforceddisplaymath + \egroup + % check number + \d_strc_math_number_width\wd\b_strc_formulas_number + % + \ifcase\mathnumberstatus + \setfalse\c_strc_math_has_number + \or\ifzeropt\d_strc_math_number_width + \setfalse\c_strc_math_has_number + \else + \settrue\c_strc_math_has_number + \fi\fi + % preroll left and right offsets + \ifcase\c_strc_formulas_frame_mode + % no frame + \else + \strc_math_number_check_offsets + \fi + \ifcase\c_strc_formulas_frame_mode + \strc_math_number_check + \or + \strc_math_number_check_outside + \else + \strc_math_number_check_inside + \fi + \noindent % \noindentation % not \dontleavehmode + \hskip\d_strc_formulas_display_margin_left % was kern but that doesn't indent + \strc_math_traced_state + \ifcase\c_strc_math_vertical + \hbox to \displaywidth \bgroup + \or + \vbox \bgroup \hsize\displaywidth + \or + \bgroup \hsize\displaywidth + \fi + \ifcase\mathnumberstatus + \strc_math_flush_box + \or % status 1 + \ifcase\c_strc_math_number_location + \strc_math_flush_box + \or % number left + \ifzeropt\wd\b_strc_formulas_number + \strc_math_flush_number_no + \else + \strc_math_flush_number_left + \fi + \else % number right + \ifzeropt\wd\b_strc_formulas_number + \strc_math_flush_number_no + \else + \strc_math_flush_number_right + \fi + \fi + \or % status 2 + \hskip\d_math_number_correction % probably no longer used + \strc_math_flush_box + \hss + \else + \strc_math_flush_box + \fi + \ifcase\c_strc_math_vertical + \or + \or + \par + \fi + \egroup} + +\defineinnermathhandler\v!left {\strc_math_box_start\plusone }{\strc_math_box_stop} +\defineinnermathhandler\v!middle {\strc_math_box_start\plustwo }{\strc_math_box_stop} +\defineinnermathhandler\v!right {\strc_math_box_start\plusthree}{\strc_math_box_stop} +\defineinnermathhandler\v!flushleft {\strc_math_box_start\plusthree}{\strc_math_box_stop} +\defineinnermathhandler\v!center {\strc_math_box_start\plustwo }{\strc_math_box_stop} +\defineinnermathhandler\v!flushright{\strc_math_box_start\plusone }{\strc_math_box_stop} +\defineinnermathhandler\v!normal {\strc_math_box_start\plustwo }{\strc_math_box_stop} + +%D Some inline math tweak. + +\appendtoks + \ifcase\mathnestinglevel\or + % 4=disable 6=only when no spaces + \mathsurroundskip\mathematicsparameter\c!textdistance\relax + \ifzeropt\mathsurroundskip + \ifzeropt\gluestretch\mathsurroundskip + \ifzeropt\glueshrink\mathsurroundskip + \mathsurroundmode\plussix + \else + \mathsurroundskip\zeropoint + \mathsurroundmode\plusfour + \fi + \else + \mathsurroundmode\plussix + \fi + \else + \mathsurroundmode\plussix + \fi + \else + \mathsurroundmode\plusfour + \mathsurroundskip\zeropoint + \fi +\to \everymathematics + +\setupmathematics + [\c!textdistance=\zeropoint] + +%D This is an experiment. No fancy spacing and alignments here. If we ever +%D go that route it might result in incompatible rendering. + +\permanent\protected\def\startsplitformula + {\ifhmode + \par + \fi + \begingroup + \beforedisplayspace + % subset of \everydisplay: + \c_attr_mathmode\plusone + \settrue \indisplaymath + % end of subset + \informulatrue} + +\permanent\protected\def\stopsplitformula + {\afterdisplayspace + \endgroup} + +\protect \endinput + +% \placeformula \startformula[-] \startmatrix +% \NC 1 \NC x \NC a \NR +% \NC 2 \NC y \NC b \NR +% \NC 3 \NC z \NC c \NR +% \stopmatrix \stopformula + +% \definemathmatrix[bordermatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]}] + +% \placeformula \startformula[-] \startbordermatrix +% \NC 1 \NC x \NC a \NR +% \NC 2 \NC y \NC b \NR +% \NC 3 \NC z \NC c \NR +% \stopbordermatrix \stopformula diff --git a/tex/context/base/mkiv/math-def.mkiv b/tex/context/base/mkiv/math-def.mkiv index 641f7411e..14ceeb61e 100644 --- a/tex/context/base/mkiv/math-def.mkiv +++ b/tex/context/base/mkiv/math-def.mkiv @@ -1,4 +1,4 @@ -%D \module + %D \module %D [ file=math-tex, %D version=2001.04.12, %D title=\CONTEXT\ Math Macros, @@ -80,6 +80,8 @@ {\savenormalmeaning{#1}% \expandafter\def\expandafter#1\expandafter{\csname normal\csstring#1\endcsname#2}} +\pushoverloadmode + \setoperatorlimits \int \intlimits \setoperatorlimits \iint \intlimits \setoperatorlimits \iiint \intlimits @@ -90,6 +92,8 @@ \setoperatorlimits \ointclockwise \intlimits \setoperatorlimits \ointctrclockwise \intlimits +\popoverloadmode + %D \macros %D {centercolon, colonminus, minuscolon, colonequals, equalscolon, %D colonapprox, approxcolon, colonsim, simcolon, coloncolon, @@ -131,6 +135,8 @@ %D The next macros take care of the space between the colon and the %D relation symbol. +\pushoverloadmode + \definemathcommand [colonsep] {\mkern-1.2mu} \definemathcommand [doublecolonsep] {\mkern-0.9mu} @@ -154,6 +160,8 @@ \definemathcommand [coloncolonsim] [rel] {\coloncolon\colonsep\sim} \definemathcommand [simcoloncolon] [rel] {\sim\coloncolon\colonsep} +\popoverloadmode + % \appendtoks % \def\over{\primitive\over}% % \to \everymathematics diff --git a/tex/context/base/mkiv/math-fen.mkiv b/tex/context/base/mkiv/math-fen.mkiv index 246ff989d..d7c67b7e3 100644 --- a/tex/context/base/mkiv/math-fen.mkiv +++ b/tex/context/base/mkiv/math-fen.mkiv @@ -335,6 +335,8 @@ %D A bonus: +\pushoverloadmode + \unexpanded\def\Lparenthesis {\math_fenced_fenced_start{parenthesis}} \unexpanded\def\Rparenthesis {\math_fenced_fenced_stop {parenthesis}} \unexpanded\def\Lbracket {\math_fenced_fenced_start{bracket}} \unexpanded\def\Rbracket {\math_fenced_fenced_stop {bracket}} \unexpanded\def\Lbrace {\math_fenced_fenced_start{brace}} \unexpanded\def\Rbrace {\math_fenced_fenced_stop {brace}} @@ -394,14 +396,20 @@ % \left| \frac{1}{e} \right| % \stopformula +\popoverloadmode + \installcorenamespace{mathleft} \installcorenamespace{mathright} \installcorenamespace{mathmiddle} +\pushoverloadmode + \unexpanded\def\left {\afterassignment\math_left \let\nexttoken} \unexpanded\def\right {\afterassignment\math_right \let\nexttoken} \unexpanded\def\middle{\afterassignment\math_middle\let\nexttoken} +\popoverloadmode + \let\leftorright\relax \newconditional\c_math_fenced_done @@ -565,6 +573,8 @@ % The names in char-def.lua (historic mess): +\pushoverloadmode + \let\lbrack \lbracket \let\rbrack \rbracket \let\lceiling \lceil @@ -634,6 +644,8 @@ \installmathfencepair \< \Langle \> \Rangle \installmathfencepair \| \Lbar \| \Rbar +\popoverloadmode + %D As we have overloaded \type {\left} and \type {\right} we also need a more %D clever version of the following: diff --git a/tex/context/base/mkiv/math-frc.mkiv b/tex/context/base/mkiv/math-frc.mkiv index 8b068bc6c..1b0149f96 100644 --- a/tex/context/base/mkiv/math-frc.mkiv +++ b/tex/context/base/mkiv/math-frc.mkiv @@ -630,8 +630,6 @@ %D More fracking (for Alan): -\def\s!vfrac{vfrac} - \unexpanded\def\math_frac_colored_vulgar#1#2% {\savecolor \colo_helpers_activate\p_math_fractions_color diff --git a/tex/context/base/mkiv/math-frc.mkxl b/tex/context/base/mkiv/math-frc.mkxl new file mode 100644 index 000000000..b6c77f4bb --- /dev/null +++ b/tex/context/base/mkiv/math-frc.mkxl @@ -0,0 +1,753 @@ +%D \module +%D [ file=math-frc, +%D version=2013.04.06, % 2007.07.19, +%D title=\CONTEXT\ Math Macros, +%D subtitle=Fractions, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Math Macros / Fractions} + +\unprotect + +%D I need to check it all again as there was a bug in luatex with dimensions that could +%D resulted in side effects that made me mess with spacing. + +\unexpanded\def\topstrut{\vrule\s!width\zeropoint\s!height\strutht\s!depth\zeropoint\relax} +\unexpanded\def\botstrut{\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\strutdp\relax} + +\unexpanded\def\mathtopstrut{\setbox\scratchbox\mathstylehbox{(}\vrule\s!width\zeropoint\s!height\ht\scratchbox\s!depth\zeropoint\relax} +\unexpanded\def\mathbotstrut{\setbox\scratchbox\mathstylehbox{(}\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\dp\scratchbox\relax} + +%D This module is reimplemented in \MKIV\ style. + +\registerctxluafile{math-frc}{} + +%D \macros +%D {frac, xfrac, xxfrac} +%D +%D This is another one Tobias asked for. It replaces the primitive \type +%D {\over}. We also take the opportunity to handle math style restoring, +%D which makes sure units and chemicals come out ok. The \type {\frac} +%D macro kind of replaces the awkward \type {\over} primitive. Say that +%D we have the following formulas: +%D +%D \startbuffer[sample] +%D test $\frac {1}{2}$ test $$1 + \frac {1}{2} = 1.5$$ +%D test $\xfrac {1}{2}$ test $$1 + \xfrac {1}{2} = 1.5$$ +%D test $\xxfrac{1}{2}$ test $$1 + \xxfrac{1}{2} = 1.5$$ +%D \stopbuffer +%D +%D \typebuffer[sample] +%D +%D With the most straightforward definitions, we get: +%D +%D \startbuffer[code] +%D \def\dofrac#1#2#3{\relax\mathematics{{{#1{#2}}\over{#1{#3}}}}} +%D +%D \def\frac {\dofrac\mathstyle} +%D \def\xfrac {\dofrac\scriptstyle} +%D \def\xxfrac{\dofrac\scriptscriptstyle} +%D \stopbuffer +%D +%D \typebuffer[code] \getbuffer[code,sample] +%D +%D Since this does not work well, we can try: +%D +%D \startbuffer[code] +%D \def\xfrac #1#2{\hbox{$\dofrac\scriptstyle {#1}{#2}$}} +%D \def\xxfrac#1#2{\hbox{$\dofrac\scriptscriptstyle{#1}{#2}$}} +%D \stopbuffer +%D +%D \typebuffer[code] \getbuffer[code,sample] +%D +%D This for sure looks better than: +%D +%D \startbuffer[code] +%D \def\xfrac #1#2{{\scriptstyle \dofrac\relax{#1}{#2}}} +%D \def\xxfrac#1#2{{\scriptscriptstyle\dofrac\relax{#1}{#2}}} +%D \stopbuffer +%D +%D \typebuffer[code] \getbuffer[code,sample] +%D +%D So we stick to the next definitions (watch the local overloading of +%D \type {\xfrac}). +%D +%D In the meantime, in \LUATEX, we have better control over styles so the +%D following macros are different from the \MKII\ ones. + +% obsolete, is now c!mathstyle +% +% 0=auto, 1=displaystyle, 2=textstyle, 3=scriptstyle, 4=scriptscriptstyle, 5=mathstyle +% +% $\mathfracmode0 \frac{1}{2}$ +% $\mathfracmode1 \frac{1}{2}$ +% $\mathfracmode2 \frac{1}{2}$ +% $\mathfracmode3 \frac{1}{2}$ +% $\mathfracmode4 \frac{1}{2}$ +% $\mathfracmode5 \frac{1}{2}$ +% +% we keep the constant for a while + +\setnewconstant\mathfracmode\zerocount + +\installcorenamespace{mathfractions} +\installcorenamespace{mathfractionstyle} +\installcorenamespace{mathfractionalternative} + +\installcommandhandler \??mathfractions {mathfraction} \??mathfractions + +\let\setupmathfractions\setupmathfraction + +% color only applies to rule, use regular color for rest + +\setupmathfractions + [\c!mathstyle=, + \c!alternative=\v!inner, + \c!margin=\zeropoint, + \c!rulethickness=.25\exheight, + \c!left=0x2E, + \c!right=0x2E, + \c!strut=\v!yes, + \c!topdistance=, + \c!bottomdistance=, + \c!rule=\v!auto] + +\appendtoks + \setuevalue{\currentmathfraction}{\math_frac{\currentmathfraction}}% +\to \everydefinemathfraction + +% Sometimes users want control over the distances: + +\let\math_fraction_set_distance\relax + +\appendtoks + \math_fraction_set_distance +\to \everymathematics + +% why only displaystyle .. a bit weak + +\unexpanded\def\math_fraction_set_distance_top + {\Umathfractionnumup \displaystyle\m_math_fraction_distance_top + \relax} + +\unexpanded\def\math_fraction_set_distance_bot + {\Umathfractiondenomdown\displaystyle\m_math_fraction_distance_bot + \relax} + +\unexpanded\def\math_fraction_set_distance_all + {\Umathfractionnumup \displaystyle\m_math_fraction_distance_top + \Umathfractiondenomdown\displaystyle\m_math_fraction_distance_bot + \relax} + +\appendtoks + \ifx\currentmathfraction\empty + \edef\m_math_fraction_distance_top{\mathfractionparameter\c!topdistance}% + \edef\m_math_fraction_distance_bot{\mathfractionparameter\c!bottomdistance}% + \ifx\m_math_fraction_distance_top\empty + \ifx\m_math_fraction_distance_bot\empty + \let\math_fraction_set_distance\relax + \else + \let\math_fraction_set_distance\math_fraction_set_distance_bot + \fi + \else + \ifx\m_math_fraction_distance_bot\empty + \let\math_fraction_set_distance\math_fraction_set_distance_top + \else + \let\math_fraction_set_distance\math_fraction_set_distance_all + \fi + \fi + \fi +\to \everysetupmathfraction + +% So far for control. + +\installcorenamespace{mathfractionstrut} + +\def\math_frac_no_strut + {\enforced\let\m_fractions_strut_top\relax + \enforced\let\m_fractions_strut_bot\relax} + +\setvalue{\??mathfractionstrut\v!yes}% + {\enforced\let\m_fractions_strut_top\mathstrut + \enforced\let\m_fractions_strut_bot\mathstrut} + +\setvalue{\??mathfractionstrut\v!math}% + {\enforced\let\m_fractions_strut_top\mathstrut + \enforced\let\m_fractions_strut_bot\mathstrut} + +\letvalue{\??mathfractionstrut\v!no}\math_frac_no_strut + +\setvalue{\??mathfractionstrut\v!tight}% + {\enforced\let\m_fractions_strut_top\mathbotstrut % indeed swapped name + \enforced\let\m_fractions_strut_bot\mathtopstrut} % indeed swapped name + +\math_frac_no_strut + +\newdimen\d_math_fraction_margin + +\unexpanded\def\math_frac#1% + {\begingroup + \edef\currentmathfraction{#1}% + % + \edef\p_math_fraction_fences{\mathfractionparameter\c!fences}% + \ifx\p_math_fraction_fences\empty \else + \math_fenced_fenced_start\p_math_fraction_fences + \fi + % + \d_math_fraction_margin\mathfractionparameter\c!margin + % + \edef\p_math_fractions_color{\mathfractionparameter\c!color}% + % + \edef\p_math_fractions_strut{\mathfractionparameter\c!strut}% + \ifcsname\??mathfractionstrut\p_math_fractions_strut\endcsname + \lastnamedcs + \else + \math_frac_no_strut + \fi + % + \ifx\p_math_fractions_color\empty + \expandafter\math_frac_normal + \else + \expandafter\math_frac_colored + \fi} + +\unexpanded\def\math_frac_wrapup + {\ifx\p_math_fraction_fences\empty \else + \math_fenced_fenced_stop\p_math_fraction_fences + \fi + \endgroup} + +\unexpanded\def\math_frac_colored#1#2% + {\savecolor + \colo_helpers_activate\p_math_fractions_color + \math_frac_normal{\restorecolor#1}{\restorecolor#2}} + +\unexpanded\def\math_frac_normal + {\expandnamespaceparameter\??mathfractionalternative\mathfractionparameter\c!alternative\v!inner} + +% we use utfchar anyway so we can as well do all at the lua end + +\def\math_frac_no_delim{0x2E} + +\def\math_frac_command + {\clf_mathfraction + {\mathfractionparameter\c!rule}% + \ifx\p_math_fraction_fences\empty + \mathfractionparameter\c!left \space + \mathfractionparameter\c!right\space + \else + \math_frac_no_delim\space + \math_frac_no_delim\space + \fi + \dimexpr\mathfractionparameter\c!rulethickness\relax + \relax} + +% Having a \withmarginornot{#1}{#2} makes not much sense nor do 4 tests or 4 redundant +% kerns (longer node lists plus possible interference). A split in normal and margin +% also makes testing easier. When left and right margins are needed we might merge the +% variants again. After all, these are not real installers. + +% the denominator is in cramped! + +\setvalue{\??mathfractionalternative\v!inner}% + {\ifcase\d_math_fraction_margin + \expandafter\math_fraction_inner_normal + \else + \expandafter\math_fraction_inner_margin + \fi} + +\setvalue{\??mathfractionalternative\v!outer}% + {\ifcase\d_math_fraction_margin + \expandafter\math_fraction_outer_normal + \else + \expandafter\math_fraction_outer_margin + \fi} + +\setvalue{\??mathfractionalternative\v!both}% + {\ifcase\d_math_fraction_margin + \expandafter\math_fraction_both_normal + \else + \expandafter\math_fraction_both_margin + \fi} + +% todo: store first state and reuse second time + +\def\math_fraction_inner_normal#1#2% + {\Ustack{% + {% + {\usemathstyleparameter\mathfractionparameter{\m_fractions_strut_top#1}}% + \math_frac_command + {\usemathstyleparameter\mathfractionparameter{\m_fractions_strut_bot#2}}% + }% + }% + \math_frac_wrapup} + +\def\math_fraction_outer_normal#1#2% + {\Ustack{% + \usemathstyleparameter\mathfractionparameter + {% + {\m_fractions_strut_top#1}% + \math_frac_command + {\m_fractions_strut_bot#2}% + }% + }% + \math_frac_wrapup} + +\def\math_fraction_both_normal#1#2% + {\Ustack{% + \usemathstyleparameter\mathfractionparameter + {% + {\usemathstyleparameter\mathfractionparameter\m_fractions_strut_top#1}% + \math_frac_command + {\usemathstyleparameter\mathfractionparameter\m_fractions_strut_bot#2}% + }% + }% + \math_frac_wrapup} + +\def\math_fraction_inner_margin#1#2% + {\Ustack{% + {% + {\kern\d_math_fraction_margin + \usemathstyleparameter\mathfractionparameter{\m_fractions_strut_top#1}% + \kern\d_math_fraction_margin}% + \math_frac_command + {\kern\d_math_fraction_margin + \usemathstyleparameter\mathfractionparameter{\m_fractions_strut_bot#2}% + \kern\d_math_fraction_margin}% + }% + }% + \math_frac_wrapup} + +\def\math_fraction_outer_margin#1#2% + {\Ustack{% + \usemathstyleparameter\mathfractionparameter + {% + {\kern\d_math_fraction_margin + \m_fractions_strut_top#1% + \kern\d_math_fraction_margin}% + \math_frac_command + {\kern\d_math_fraction_margin + \m_fractions_strut_bot#2% + \kern\d_math_fraction_margin}% + }% + }% + \math_frac_wrapup} + +\def\math_fraction_both_margin#1#2% + {\Ustack{% + \usemathstyleparameter\mathfractionparameter + {% + {\kern\d_math_fraction_margin + \usemathstyleparameter\mathfractionparameter\m_fractions_strut_top#1% + \kern\d_math_fraction_margin}% + \math_frac_command + {\kern\d_math_fraction_margin + \usemathstyleparameter\mathfractionparameter\m_fractions_strut_bot#2% + \kern\d_math_fraction_margin}% + }% + }% + \math_frac_wrapup} + +\definemathfraction[xfrac] [\c!alternative=\v!inner,\c!mathstyle=\s!script] +\definemathfraction[xxfrac][\c!alternative=\v!inner,\c!mathstyle=\s!scriptscript] + +\let\normalxfrac\xfrac + +\unexpanded\def\xfrac#1#2{\normalxfrac{\let\xfrac\xxfrac#1}{\let\xfrac\xxfrac#2}} + +%D Spacing (sensitive for definition of \triggermathstyle: + +% \ifcase\contextlmtxmode + +\unexpanded\def\nomathfractiongaps {\normalexpanded{\math_no_fraction_gaps \mathstyletrigger\mathstyle}} % maybe collect settings +\unexpanded\def\overlaymathfractiongaps{\normalexpanded{\math_overlay_fraction_gaps\mathstyletrigger\mathstyle}} % maybe collect settings + +\unexpanded\def\math_no_fraction_gaps#1% + {\Umathfractionnumup #1\zeropoint + \Umathfractiondenomdown#1\zeropoint} + +\unexpanded\def\math_overlay_fraction_gaps#1% + {\Umathfractionnumup #1\zeropoint + \Umathfractionnumvgap #1\zeropoint + %Umathfractionrule #1\zeropoint + \Umathfractiondenomvgap#1\zeropoint + \Umathfractiondenomdown#1\zeropoint} + +% \else + +% \unexpanded\def\math_no_fraction_gaps +% {\Umathfractionnumup \mathstyle\zeropoint +% \Umathfractiondenomdown\mathstyle\zeropoint} +% +% \unexpanded\def\math_overlay_fraction_gaps +% {\Umathfractionnumup \mathstyle\zeropoint +% \Umathfractionnumvgap \mathstyle\zeropoint +% %Umathfractionrule \mathstyle\zeropoint +% \Umathfractiondenomvgap\mathstyle\zeropoint +% \Umathfractiondenomdown\mathstyle\zeropoint} + +% \fi + +\installcorenamespace{mathfractiondistance} + +\letvalue{\??mathfractiondistance\v!none }\nomathfractiongaps +\letvalue{\??mathfractiondistance\v!no }\nomathfractiongaps +\letvalue{\??mathfractiondistance\v!overlay}\overlaymathfractiongaps + +\setupmathfractions + [\c!distance=\v!none] + +\appendtoks + \edef\p_distance{\rootmathfractionparameter\c!distance}% + \ifx\p_distance\empty\else + \ifcsname\??mathfractiondistance\p_distance\endcsname + \lastnamedcs + \fi + \fi +\to \everymathematics + +% theshold is new! + +\let\math_fraction_set_threshold_inline \relax +\let\math_fraction_set_threshold_display\relax + +\appendtoks + \math_fraction_set_threshold_inline + \math_fraction_set_threshold_display +\to \everymathematics + +\appendtoks + \ifx\currentmathfraction\empty + \edef\p_threshold{\mathfractionparameter\c!inlinethreshold}% + \ifx\p_threshold\empty + \let\math_fraction_set_threshold_inline\relax + \else\ifx\p_threshold\v!auto + \let\math_fraction_set_threshold_inline\relax + \else + \let\math_fraction_set_threshold_inline\math_fraction_set_theshold_inline + \fi\fi + \edef\p_threshold{\mathfractionparameter\c!displaythreshold}% + \ifx\p_threshold\empty + \let\math_fraction_set_threshold_display\relax + \else\ifx\p_threshold\v!auto + \let\math_fraction_set_threshold_display\relax + \else + \let\math_fraction_set_threshold_display\math_fraction_set_theshold_display + \fi\fi + \fi +\to \everysetupmathfraction + +\def\math_fraction_set_theshold_inline + {\edef\p_threshold{\mathfractionparameter\c!inlinethreshold}% + \Umathfractiondelsize\textstyle \p_threshold\dimexpr\textface\relax + \Umathfractiondelsize\scriptstyle \p_threshold\dimexpr\scriptface\relax + \Umathfractiondelsize\scriptscriptstyle\p_threshold\dimexpr\scriptscriptface\relax} + +\def\math_fraction_set_theshold_display + {\edef\p_threshold{\mathfractionparameter\c!displaythreshold}% + \Umathfractiondelsize\displaystyle \p_threshold\dimexpr\textface\relax} + +%D \macros +%D {dfrac, tfrac, frac, dbinom, tbinom, binom} +%D +%D \startbuffer +%D $\dfrac {1}{2} \tfrac {1}{2} \frac {1}{2}$ +%D $\dbinom{1}{2} \tbinom{1}{2} \binom{1}{2}$ +%D \stopbuffer +%D +%D \typebuffer +%D \getbuffer + +% $$ +% {{a}\over{b}} + +% {{a}\overwithdelims(){b}} + +% {{a}\atopwithdelims(){b}} + +% {{a}\abovewithdelims()\zeropoint{b}} + +% \left({{a}\over{b}}\right) +% $$ + +% \dorecurse {10} { % weird +% $$ {{a}\abovewithdelims()#1pt{b}} $$ +% } + +\definemathfraction[i:frac] [\c!alternative=\v!inner,\c!mathstyle=] % was script and then small but nothing needed +\definemathfraction[i:tfrac][\c!alternative=\v!inner,\c!mathstyle=\s!text] % was script (before luatex fix) +\definemathfraction[i:sfrac][\c!alternative=\v!inner,\c!mathstyle=\s!scriptscript] +\definemathfraction[i:dfrac][\c!alternative=\v!inner,\c!mathstyle=\s!display] + +\definemathfraction[d:frac] [\c!alternative=\v!inner,\c!mathstyle=\s!cramped] % was cramped,text +\definemathfraction[d:tfrac][\c!alternative=\v!both ,\c!mathstyle={\s!cramped,\s!text}] % was cramped,script (before luatex fix) +\definemathfraction[d:sfrac][\c!alternative=\v!both ,\c!mathstyle={\s!cramped,\s!scriptscript}] +\definemathfraction[d:dfrac][\c!alternative=\v!inner,\c!mathstyle=\s!display] + +%D \unexpanded\def\ShowMathFractions#1#2% +%D {\dontleavehmode +%D \begingroup +%D \showmathstruts +%D \mathematics{x+\tfrac{#1}{#2}+1+\frac{#1}{#2}+2+\sfrac{#1}{#2}+g}% +%D \endgroup} +%D +%D The default \type {tfrac}, \type {frac} and \type \sfrac} look like this: +%D +%D \blank +%D \ShowMathFractions{a}{a}\par +%D \ShowMathFractions{1}{x}\par +%D \ShowMathFractions{a}{b}\par +%D \ShowMathFractions{1}{b}\par +%D \blank + +\unexpanded\def\frac {\csname\inlineordisplaymath id:frac\endcsname} +\unexpanded\def\tfrac{\csname\inlineordisplaymath id:tfrac\endcsname} +\unexpanded\def\sfrac{\csname\inlineordisplaymath id:sfrac\endcsname} +\unexpanded\def\dfrac{\csname\inlineordisplaymath id:dfrac\endcsname} + +\definemathfraction[ams] [\c!strut=\v!no,\c!alternative=\v!outer] +\definemathfraction[i:ams:frac][ams][\c!mathstyle={\s!cramped,\s!text}] +\definemathfraction[d:ams:frac][ams][\c!mathstyle={\s!cramped,\s!display}] + +\unexpanded\def\ctxfrac{\csname\inlineordisplaymath id:frac\endcsname} +\unexpanded\def\amsfrac{\csname\inlineordisplaymath id:ams:frac\endcsname} + +% \appendtoks +% \doifelse{\mathfractionparameter\c!option}{ams}% +% {\let\frac\amsfrac}% +% {\let\frac\ctxfrac}% +% \to \everysetupmathfraction + +\appendtoks + \doifelse{\mathematicsparameter\c!fractions}{ams}% + {\let\frac\amsfrac}% + {\let\frac\ctxfrac}% +\to \everysetupmathematics + +% \definemathfraction[ddfrac][\c!mathstyle=\s!display] +% \definemathfraction[ttfrac][\c!mathstyle=\s!text] +% \definemathfraction[ssfrac][\c!mathstyle=\s!script] + +% \unexpanded\def\binom #1#2{{\Ustack {{#1}\normalabovewithdelims()\zeropoint{#2}}}} +% \unexpanded\def\dbinom#1#2{{\displaystyle{{#1}\normalabovewithdelims()\zeropoint{#2}}}} +% \unexpanded\def\tbinom#1#2{{\textstyle {{#1}\normalabovewithdelims()\zeropoint{#2}}}} + +\definemathfraction + [binom] + [\c!alternative=\v!outer, + \c!rule=\v!no, + \c!left=0x28, + \c!right=0x29, + \c!mathstyle=\s!auto] + +\definemathfraction + [dbinom] + [binom] + [\c!mathstyle=\s!display] + +\definemathfraction + [tbinom] + [binom] + [\c!mathstyle=\s!text] + +%D \macros +%D {cfrac} +%D +%D \startbuffer +%D $\cfrac{12}{3} \cfrac[l]{12}{3} \cfrac[c]{12}{3} \cfrac[r]{12}{3}$ +%D $\cfrac{1}{23} \cfrac[l]{1}{23} \cfrac[c]{1}{23} \cfrac[r]{1}{23}$ +%D \stopbuffer +%D +%D \typebuffer +%D +%D \getbuffer +%D +%D Now we can align every combination we want: +%D +%D \startbuffer +%D $\cfrac{12}{3} \cfrac[l]{12}{3} \cfrac[c]{12}{3} \cfrac[r]{12}{3}$ +%D $\cfrac{1}{23} \cfrac[l]{1}{23} \cfrac[c]{1}{23} \cfrac[r]{1}{23}$ +%D $\cfrac[cl]{12}{3} \cfrac[cc]{12}{3} \cfrac[cr]{12}{3}$ +%D $\cfrac[lc]{1}{23} \cfrac[cc]{1}{23} \cfrac[rc]{1}{23}$ +%D \stopbuffer +%D +%D \typebuffer +%D +%D \getbuffer + +\unexpanded\def\cfrac + {\doifelsenextoptionalcs\math_cfrac_yes\math_cfrac_nop} + +\def\math_cfrac_nop {\math_cfrac_indeed[cc]} +\def\math_cfrac_yes[#1]{\math_cfrac_indeed[#1cc]} + +\def\math_cfrac_indeed[#1#2#3]#4#5% + {{\displaystyle + \frac + {\strut + \ifx r#1\hfill\fi#4\ifx l#1\hfill\fi}% + {\ifx r#2\hfill\fi#5\ifx l#2\hfill\fi}% + \kern-\nulldelimiterspace}} + +%D \macros +%D {splitfrac, splitdfrac} +%D +%D Occasionally one needs to typeset multi||line fractions. +%D These commands use \tex{genfrac} to create such fractions. +%D +%D \startbuffer +%D \startformula +%D a=\frac{ +%D \splitfrac{xy + xy + xy + xy + xy} +%D {+ xy + xy + xy + xy} +%D } +%D {z} +%D =\frac{ +%D \splitdfrac{xy + xy + xy + xy + xy} +%D {+ xy + xy + xy + xy} +%D } +%D {z} +%D \stopformula +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D These macros are based on Michael J.~Downes posting on +%D comp.text.tex on 2001/12/06 but adapted a bit. + +\unexpanded\def\splitfrac #1#2% + {{\textstyle {{\textstyle#1\quad\hfill}\normalabove\zeropoint{\textstyle\hfill\quad\mathstrut#2}}}} + +\unexpanded\def\splitdfrac#1#2% + {{\displaystyle{{ #1\quad\hfill}\normalabove\zeropoint{ \hfill\quad\mathstrut#2}}}} + +%D For testing: + +% \unexpanded\def\ShowMathFractions#1#2% +% {\mathematics{x+\tfrac{#1}{#2}+1+\frac{#1}{#2}+2+\sfrac{#1}{#2}+g}} + +%D More fracking (for Alan): + +\unexpanded\def\math_frac_colored_vulgar#1#2% + {\savecolor + \colo_helpers_activate\p_math_fractions_color + {\restorecolor#1}\Uskewed/{\restorecolor#2}} + +\unexpanded\def\math_frac_normal_vulgar#1#2% + {{#1}\Uskewed/{#2}} + +\unexpanded\def\vfrac#1#2% + {\bgroup + \edef\p_math_fractions_color{\namedmathfractionparameter\s!vfrac\c!color}% + \ifx\p_math_fractions_color\empty + \expandafter\math_frac_normal_vulgar + \else + \expandafter\math_frac_colored_vulgar + \fi + {#1}% + {#2}% + \egroup} + +\appendtoks + \edef\p_hfactor{\namedmathfractionparameter\s!vfrac\c!hfactor}% + \edef\p_vfactor{\namedmathfractionparameter\s!vfrac\c!vfactor}% + \Umathskewedfractionhgap\textstyle \p_hfactor\fontemwidth \mathstylefont\textstyle + \Umathskewedfractionhgap\scriptstyle \p_hfactor\fontemwidth \mathstylefont\scriptstyle + \Umathskewedfractionhgap\scriptscriptstyle\p_hfactor\fontemwidth \mathstylefont\scriptscriptstyle + \Umathskewedfractionvgap\textstyle \p_vfactor\fontexheight\mathstylefont\textstyle + \Umathskewedfractionvgap\scriptstyle \p_vfactor\fontexheight\mathstylefont\scriptstyle + \Umathskewedfractionvgap\scriptscriptstyle\p_vfactor\fontexheight\mathstylefont\scriptscriptstyle +\to \everysetupmathfraction + +\setupmathfraction + [\s!vfrac] + [\c!hfactor=.2, + \c!vfactor=.1] + +\protect \endinput + +% I have no clue what \mthfrac and \mthsqrt are supposed to do but +% I guess that it can be done with tweaking luatex's math parameters. +% Otherwise I'll write something from scratch. + +% \def\math_stylebuilders_frac#1#2#3#4#5#6#7% +% {\begingroup +% \mathsurround\zeropoint +% \setbox0\hbox{$#1 #6$}% +% \setbox2\hbox{$#1 #7$}% +% \dimen0\wd\ifdim\wd2>\wd0 2\else 0\fi +% \setbox4\hbox to \dimen0{\leaders\hbox{#4}\hss#5}% +% \mathord{\vcenter{{\offinterlineskip +% \hbox to \dimen0{\hss\box0\hss}% +% \kern\ht4% +% \hbox to \dimen0{\hss\copy4\hss}% +% \kern\ht4% +% \hbox to \dimen0{\hss\box2\hss}}}}% +% \endgroup} +% +% \def\math_stylebuilders_sqrt#1#2#3#4#5% +% {\begingroup +% \mathsurround\zeropoint +% \setbox0\hbox{$#1 #5$}% +% \ht0\dimexpr1.05\ht0+\onepoint\relax +% \dp0\dimexpr1.05\dp0+\onepoint\relax +% \setbox4\hbox to \wd0{\mr#2\leaders\hbox{#3}\hfill#4}% +% \delimitershortfall\zeropoint +% \nulldelimiterspace\zeropoint +% \setbox2\hbox{$\left\delimiter"0270370 \vrule \s!height\ht0 \s!depth \dp0 \s!width\zeropoint\right.$}% is this the right code point? +% \mathord{\vcenter{\hbox{\copy2\rlap{\raise\dimexpr\ht2-\ht4\relax\copy4}\copy0}}}% +% \endgroup} +% +% \def\mthfrac#1#2#3#4#5{\mathchoice +% {\math_stylebuilders_frac\displaystyle \textface {#1}{#2}{#3}{#4}{#5}}% +% {\math_stylebuilders_frac\textstyle \textface {#1}{#2}{#3}{#4}{#5}}% +% {\math_stylebuilders_frac\scriptstyle \scriptface {#1}{#2}{#3}{#4}{#5}}% +% {\math_stylebuilders_frac\scriptscriptstyle\scriptscriptface{#1}{#2}{#3}{#4}{#5}}} +% +% \def\mthsqrt#1#2#3{\mathchoice +% {\math_stylebuilders_sqrt\displaystyle \textface{#1}{#2}{#3}}% +% {\math_stylebuilders_sqrt\textstyle \textface{#1}{#2}{#3}}% +% {\math_stylebuilders_sqrt\scriptstyle \textface{#1}{#2}{#3}}% +% {\math_stylebuilders_sqrt\scriptscriptstyle\textface{#1}{#2}{#3}}} + +% \unexpanded\def\mthfrac#1#2#3{[mthfrac: #1 #2 #3]} +% \unexpanded\def\mthsqrt#1#2#3{[mthsqrt: #1 #2 #3]} + +% used for prototyping \Uskewed +% +% \unexpanded\def\skewedfractiona#1#2{% +% \raise +% \Umathskewedfractionvgap\textstyle +% \hbox\bgroup +% $\scriptstyle#1\hskip\dimexpr\Umathskewedfractionhgap\scriptstyle/2\relax$% +% \egroup +% \hbox to \zeropoint\bgroup +% \hss$\textstyle/$\hss +% \egroup +% \lower +% \Umathskewedfractionvgap\textstyle +% \hbox\bgroup +% $\hskip\dimexpr\Umathskewedfractionhgap\scriptstyle/2\relax\scriptstyle#2$% +% \egroup +% } +% +% \unexpanded\def\skewedfractionb#1#2{% +% \raise +% \Umathskewedfractionvgap\textstyle +% \hbox\bgroup +% $\scriptstyle#1\hskip\dimexpr\Umathskewedfractionhgap\textstyle/2\relax$% +% \egroup +% \hbox to \zeropoint\bgroup +% \hss$\textstyle/$\hss +% \egroup +% \lower +% \Umathskewedfractionvgap\textstyle +% \hbox\bgroup +% $\hskip\dimexpr\Umathskewedfractionhgap\textstyle/2\relax\scriptstyle#2$% +% \egroup +% } +% +% $\skewedfractiona{1}{2}$ +% $\skewedfractionb{1}{2}$ diff --git a/tex/context/base/mkiv/math-ini.lua b/tex/context/base/mkiv/math-ini.lua index 0af9a2121..4f7e803d0 100644 --- a/tex/context/base/mkiv/math-ini.lua +++ b/tex/context/base/mkiv/math-ini.lua @@ -243,6 +243,8 @@ local f_root = formatters[ [[\ugdef\%s{\Uroot "%X "%X }]] ] ----- f_char = formatters[ [[\ugdef\%s{\Umathchar "%X "%X "%X }]] local f_char = formatters[ [[\Umathchardef\%s "%X "%X "%X ]] ] +local texmathchardef = tex.mathchardef + local setmathsymbol = function(name,class,family,slot) -- hex is nicer for tracing if class == classes.accent then ctx_sprint(f_accent(name,family,slot)) @@ -264,6 +266,8 @@ local setmathsymbol = function(name,class,family,slot) -- hex is nicer for traci ctx_sprint(f_radical(name,family,slot)) elseif class == classes.root then ctx_sprint(f_root(name,family,slot)) + elseif texmathchardef then + texmathchardef(name,class,family,slot,"permanent") else -- beware, open/close and other specials should not end up here ctx_sprint(f_char(name,class,family,slot)) diff --git a/tex/context/base/mkiv/math-ini.mkxl b/tex/context/base/mkiv/math-ini.mkxl index 427d79d45..6e6018896 100644 --- a/tex/context/base/mkiv/math-ini.mkxl +++ b/tex/context/base/mkiv/math-ini.mkxl @@ -32,7 +32,7 @@ % % plus two new math styles: larger/smaller % -% \unexpanded\def\Umathshow#1% +% \protected\def\Umathshow#1% % {\hbox{\infofont(\string#1:\the#1\textstyle,\the#1\scriptstyle,\the#1\scriptscriptstyle)}} %D This module provides namespaces for math fonts, thereby permitting mixed usage of @@ -72,8 +72,8 @@ \registerctxluafile{math-ttv}{} \registerctxluafile{math-map}{optimize} \registerctxluafile{math-ren}{} -\registerctxluafile{math-noa}{optimize} -\registerctxluafile{math-tag}{} +\registerctxluafile{math-noa}{autosuffix,optimize} +\registerctxluafile{math-tag}{autosuffix} \registerctxluafile{math-fbk}{} \registerctxluafile{math-dir}{} \registerctxluafile{math-spa}{} @@ -100,7 +100,7 @@ \def\Umathbotaccent{\Umathaccent \s!bottom } \def\Umathtopaccent{\Umathaccent \s!top } -\def\Umathaccents {\Umathaccent \s!both } +\def\Umathaccents {\Umathaccent \s!both } % strange highlighting \ifdefined\Umathcharclass \else \def\Umathcharclass{\numexpr\cldcontext{tex.getmathcode(token.scan_int())[1]}\relax} @@ -142,9 +142,9 @@ \c_attr_displaymath\plusone \to \everybeforedisplayformula -\setnewconstant\defaultmathfamily \zerocount % 255 +\defaultmathfamily \zerocount % 255 -\unexpanded\def\resetmathattributes{\clf_resetmathattributes} +\permanent\protected\def\resetmathattributes{\clf_resetmathattributes} % handy @@ -158,25 +158,25 @@ \settrue\indisplaymath \to \everydisplay -\def\inlineordisplaymath{\ifconditional\indisplaymath\expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments\fi} +\permanent\def\inlineordisplaymath{\ifconditional\indisplaymath\expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments\fi} -\unexpanded\def\forcedisplaymath +\permanent\protected\def\forcedisplaymath {\ifmmode \displaystyle \settrue\indisplaymath \fi} -\unexpanded\def\startforceddisplaymath +\permanent\protected\def\startforceddisplaymath {\startimath \displaystyle \begingroup \settrue\indisplaymath} -\unexpanded\def\stopforceddisplaymath +\permanent\protected\def\stopforceddisplaymath {\endgroup \stopimath} -\unexpanded\def\startpickupmath % for the moment private +\permanent\protected\def\startpickupmath % for the moment private {\ifconditional\indisplaymath \startforceddisplaymath \let\stoppickupmath\stopforceddisplaymath @@ -187,7 +187,7 @@ \let\stoppickupmath\relax -% \unexpanded\def\rawmathcharacter#1% slow but only for tracing +% \protected\def\rawmathcharacter#1% slow but only for tracing % {\begingroup % \ifmmode % \resetmathattributes\Uchar#1% @@ -196,7 +196,7 @@ % \fi % \endgroup} -\unexpanded\def\rawmathematics#1% slow but only for tracing +\permanent\protected\def\rawmathematics#1% slow but only for tracing {\begingroup \ifmmode \clf_resetmathattributes#1% @@ -221,22 +221,22 @@ \installswitchcommandhandler \??mathematics {mathematics} \??mathematics -\unexpanded\def\startmathematics % no grouping, if ever then also an optional second +\permanent\protected\def\startmathematics % no grouping, if ever then also an optional second {\doifelsenextoptionalcs\math_mathematics_start_yes\math_mathematics_start_nop} \installmacrostack\currentmathematics -\unexpanded\def\math_mathematics_start_yes[#1]% +\protected\def\math_mathematics_start_yes[#1]% {\push_macro_currentmathematics \edef\currentmathematics{#1}% check for valid \the\everyswitchmathematics} -\unexpanded\def\math_mathematics_start_nop +\protected\def\math_mathematics_start_nop {\push_macro_currentmathematics \let\currentmathematics\empty \the\everyswitchmathematics} -\unexpanded\def\stopmathematics +\permanent\protected\def\stopmathematics {\pop_macro_currentmathematics \the\everyswitchmathematics} @@ -244,7 +244,7 @@ % Now we redefine \type {\mathematics} and \type {\m}: -\unexpanded\def\mathematics +\permanent\protected\def\mathematics {\doifelsenextoptionalcs\math_m_yes\math_m_nop} \def\math_m_yes @@ -258,18 +258,6 @@ \def\math_m_yes_math[#1]#2% {#2} -% \def\math_m_yes_text[#1]% -% {\begingroup -% \doifassignmentelse{#1}% -% {\setupcurrentmathematics[#1]}% -% {\edef\currentmathematics{#1}}% check for valid -% \edef\p_openup{\mathematicsparameter\c!openup}% -% \ifx\p_openup\v!yes -% \expandafter\math_m_yes_text_openedup -% \else -% \expandafter\math_m_yes_text_normal -% \fi} - \def\math_m_yes_text[#1]% {\begingroup \ifcondition\validassignment{#1}% @@ -418,21 +406,21 @@ % todo: only in mmode % these commands are semi-public but should not be used directly (lua names wil change) -\unexpanded\def\math_set_attribute #1#2{\ifmmode\clf_setmathattribute{#1}{#2}\fi} -\unexpanded\def\math_set_alphabet #1{\ifmmode\clf_setmathalphabet{#1}\fi} -\unexpanded\def\math_set_font_style #1{\ifmmode\clf_setmathstyle{#1}\fi} -\unexpanded\def\math_set_font_alternate#1{\ifmmode\clf_setmathalternate\defaultmathfamily{#1}\fi} +\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} \installcorenamespace{mathstylealternative} % might become a setuphandler -\unexpanded\def\math_set_font_style_alternate#1% +\protected\def\math_set_font_style_alternate#1% {\ifcsname\??mathstylealternative\fontclass:#1\endcsname \expandafter\math_set_font_alternate\lastnamedcs \orelse\ifcsname\??mathstylealternative#1\endcsname \expandafter\math_set_font_alternate\lastnamedcs \fi} -\unexpanded\def\setupmathrendering % the name might change +\protected\def\setupmathrendering % the name might change {\dodoubleargument\math_setup_rendering} \def\math_setup_rendering[#1][#2]% @@ -462,24 +450,31 @@ % \setupmathematics[stylealternative={reset,calligraphic,italic}]$x+\mathcal A$ % \stopTEXpage -\unexpanded\def\mathaltcalligraphic{\math_set_font_alternate{calligraphic}\cal} % set via goody file -\unexpanded\def\mathaltitalic {\math_set_font_alternate{italic}} % set via goody file -\unexpanded\def\mathslashedzero {\begingroup\math_set_font_alternate{zero}∅\endgroup} % set via goody file or automatic -\unexpanded\def\mathdotless {\math_set_font_alternate{dotless}} % set via goody file or automatic -\unexpanded\def\mathdotlessi {\begingroup\mathdotless i\endgroup} -\unexpanded\def\mathdotlessj {\begingroup\mathdotless j\endgroup} +% no longer needed now we have enforce so the next few lines will go + +\pushoverloadmode + \enforced\let\dotlessi\dotlessi + \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\mathdotlessi {\begingroup\mathdotless i\endgroup} +\permanent\protected\def\mathdotlessj {\begingroup\mathdotless j\endgroup} -\let\mathaltcal\mathaltcalligraphic -\let\mathaltit \mathaltitalic +\aliased\let\mathaltcal\mathaltcalligraphic +\aliased\let\mathaltit \mathaltitalic -%let\textslashedzero\slashedzero \unexpanded\def\autoslashedzero{\mathortext\mathslashedzero\textslashedzero} -\let\textdotlessi \dotlessi \unexpanded\def\autodotlessi {\mathortext\mathdotlessi \textdotlessi} -\let\textdotlessj \dotlessj \unexpanded\def\autodotlessj {\mathortext\mathdotlessj \textdotlessj} +%aliased\let\textslashedzero\slashedzero \permanent\protected\def\autoslashedzero{\mathortext\mathslashedzero\textslashedzero} +\aliased\let\textdotlessi \dotlessi \permanent\protected\def\autodotlessi {\mathortext\mathdotlessi \textdotlessi} +\aliased\let\textdotlessj \dotlessj \permanent\protected\def\autodotlessj {\mathortext\mathdotlessj \textdotlessj} \appendtoks - %let\slashedzero\autoslashedzero - \let\dotlessi \autodotlessi - \let\dotlessj \autodotlessj + %enforced\let\slashedzero\autoslashedzero + \enforced\let\dotlessi\autodotlessi + \enforced\let\dotlessj\autodotlessj \to \everymathematics \let\setmathattribute \math_set_attribute @@ -492,72 +487,72 @@ \let\mathalternate \math_set_font_alternate -\unexpanded\def\mathupright {\math_set_attribute\s!regular\s!tf\math_set_font_style_alternate\s!tf} -\unexpanded\def\mathitalic {\math_set_attribute\s!regular\s!it\math_set_font_style_alternate\s!it} -\unexpanded\def\mathscript {\math_set_alphabet \s!script \math_set_font_style_alternate\s!script} -\unexpanded\def\mathfraktur {\math_set_alphabet \s!fraktur \math_set_font_style_alternate\s!fraktur} -\unexpanded\def\mathblackboard{\math_set_alphabet \s!blackboard \math_set_font_style_alternate\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} -\unexpanded\def\mathrm {\math_set_attribute\s!rm\s!tf \math_set_font_style_alternate\s!tf} -\unexpanded\def\mathss {\math_set_attribute\s!ss\s!tf \math_set_font_style_alternate\s!tf} -\unexpanded\def\mathtt {\math_set_attribute\s!tt\s!tf \math_set_font_style_alternate\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} -\unexpanded\def\mathtf {\math_set_font_style\s!tf \math_set_font_style_alternate\s!tf} -\unexpanded\def\mathsl {\math_set_font_style\s!it \math_set_font_style_alternate\s!it} % no sl -\unexpanded\def\mathit {\math_set_font_style\s!it \math_set_font_style_alternate\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} -\unexpanded\def\mathbf {\math_set_font_style\s!bf \math_set_font_style_alternate\s!bf} -\unexpanded\def\mathbs {\math_set_font_style\s!bi \math_set_font_style_alternate\s!bi} % no sl -\unexpanded\def\mathbi {\math_set_font_style\s!bi \math_set_font_style_alternate\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 \appendtoks \edef\p_default{\mathematicsparameter\c!default}% \ifx\p_default\v!normal - \let\mathdefault\mathupright + \enforced\let\mathdefault\mathupright \else - \let\mathdefault\mathitalic + \enforced\let\mathdefault\mathitalic \fi \to \everysetupmathematics \setupmathematics [\c!default=\v!italic] -\let\tfmath\mathtf % maybe a grouped command -\let\slmath\mathsl -\let\itmath\mathit +\aliased\let\tfmath\mathtf % maybe a grouped command +\aliased\let\slmath\mathsl +\aliased\let\itmath\mathit -\let\bfmath\mathbf -\let\bsmath\mathbs -\let\bimath\mathbi +\aliased\let\bfmath\mathbf +\aliased\let\bsmath\mathbs +\aliased\let\bimath\mathbi -\let\Bbb\mathblackboard +\aliased\let\Bbb\mathblackboard -\unexpanded\def\frak {\ifmmode\expandafter\mathfraktur \fi} -\unexpanded\def\cal {\ifmmode\expandafter\mathscript \fi} -\unexpanded\def\bbd {\ifmmode\expandafter\mathblackboard\fi} -\unexpanded\def\blackboard{\ifmmode\expandafter\mathblackboard\fi} -\unexpanded\def\fraktur {\ifmmode\expandafter\mathfraktur \fi} -\unexpanded\def\gothic {\ifmmode\expandafter\mathfraktur \fi} +\permanent\protected\def\frak {\ifmmode\expandafter\mathfraktur \fi} +\permanent\protected\def\cal {\ifmmode\expandafter\mathscript \fi} +\permanent\protected\def\bbd {\ifmmode\expandafter\mathblackboard\fi} +\permanent\protected\def\blackboard{\ifmmode\expandafter\mathblackboard\fi} +\permanent\protected\def\fraktur {\ifmmode\expandafter\mathfraktur \fi} +\permanent\protected\def\gothic {\ifmmode\expandafter\mathfraktur \fi} -\unexpanded\def\mathcal #1{{\mathscript #1}} % for AMS compatibility -\unexpanded\def\mathfrak#1{{\mathfraktur #1}} % for AMS compatibility -\unexpanded\def\mathbb #1{{\mathblackboard#1}} % for AMS compatibility +\permanent\protected\def\mathcal #1{{\mathscript #1}} % for AMS compatibility +\permanent\protected\def\mathfrak#1{{\mathfraktur #1}} % for AMS compatibility +\permanent\protected\def\mathbb #1{{\mathblackboard#1}} % for AMS compatibility -\ifdefined\normaltf\else\let\normaltf\tf\fi \unexpanded\def\tf{\ifmmode\mathtf\else\normaltf\fi} -\ifdefined\normalbf\else\let\normalbf\bf\fi \unexpanded\def\bf{\ifmmode\mathbf\else\normalbf\fi} -\ifdefined\normalit\else\let\normalit\it\fi \unexpanded\def\it{\ifmmode\mathit\else\normalit\fi} -\ifdefined\normalsl\else\let\normalsl\sl\fi \unexpanded\def\sl{\ifmmode\mathsl\else\normalsl\fi} -\ifdefined\normalbi\else\let\normalbi\bi\fi \unexpanded\def\bi{\ifmmode\mathbi\else\normalbi\fi} -\ifdefined\normalbs\else\let\normalbs\bs\fi \unexpanded\def\bs{\ifmmode\mathbs\else\normalbs\fi} +\ifdefined\normaltf \else \permanent\let\normaltf\tf \fi \permanent\protected\def\tf{\ifmmode\mathtf\else\normaltf\fi} +\ifdefined\normalbf \else \permanent\let\normalbf\bf \fi \permanent\protected\def\bf{\ifmmode\mathbf\else\normalbf\fi} +\ifdefined\normalit \else \permanent\let\normalit\it \fi \permanent\protected\def\it{\ifmmode\mathit\else\normalit\fi} +\ifdefined\normalsl \else \permanent\let\normalsl\sl \fi \permanent\protected\def\sl{\ifmmode\mathsl\else\normalsl\fi} +\ifdefined\normalbi \else \permanent\let\normalbi\bi \fi \permanent\protected\def\bi{\ifmmode\mathbi\else\normalbi\fi} +\ifdefined\normalbs \else \permanent\let\normalbs\bs \fi \permanent\protected\def\bs{\ifmmode\mathbs\else\normalbs\fi} -\unexpanded\def\rm{\ifmmode\mathrm\else\normalrm\fi} -\unexpanded\def\ss{\ifmmode\mathss\else\normalss\fi} -\unexpanded\def\tt{\ifmmode\mathtt\else\normaltt\fi} +\permanent\protected\def\rm{\ifmmode\mathrm\else\normalrm\fi} +\permanent\protected\def\ss{\ifmmode\mathss\else\normalss\fi} +\permanent\protected\def\tt{\ifmmode\mathtt\else\normaltt\fi} -\ifdefined\mr \else \let\mr\relax \fi -\ifdefined\mb \else \let\mb\relax \fi +\ifdefined\mr \else \let\mr\relax \fi % hm ... permanent +\ifdefined\mb \else \let\mb\relax \fi % hm ... permanent % 1: $\setmathattribute{ss}{bf}3$ % 2: $\setmathattribute{ss}{bf}\setmathfontstylealternate{bf}3$ @@ -608,39 +603,39 @@ \let\mathboldsymbol\relax % yet unsupported, will be -\unexpanded\def\boldsymbol +\permanent\protected\def\boldsymbol {\mathortext\mathboldsymbol\bold} %D Helpers -\def\utfmathclass #1{\clf_utfmathclass {#1}} -\def\utfmathstretch#1{\clf_utfmathstretch{#1}} -\def\utfmathcommand#1{\clf_utfmathcommand{#1}} -\def\utfmathfiller #1{\clf_utfmathfiller {#1}} +\permanent\def\utfmathclass #1{\clf_utfmathclass {#1}} +\permanent\def\utfmathstretch#1{\clf_utfmathstretch{#1}} +\permanent\def\utfmathcommand#1{\clf_utfmathcommand{#1}} +\permanent\def\utfmathfiller #1{\clf_utfmathfiller {#1}} -\def\utfmathcommandabove #1{\clf_utfmathcommandabove {#1}} -\def\utfmathcommandbelow #1{\clf_utfmathcommandbelow {#1}} -\def\utfmathcommandfiller#1{\clf_utfmathcommandfiller{#1}} +\permanent\def\utfmathcommandabove #1{\clf_utfmathcommandabove {#1}} +\permanent\def\utfmathcommandbelow #1{\clf_utfmathcommandbelow {#1}} +\permanent\def\utfmathcommandfiller#1{\clf_utfmathcommandfiller{#1}} -\unexpanded\def\doifelseutfmathaccent#1{\clf_doifelseutfmathaccent{#1}} -\unexpanded\def\doifelseutfmathabove #1{\clf_doifelseutfmathabove {#1}} -\unexpanded\def\doifelseutfmathbelow #1{\clf_doifelseutfmathbelow {#1}} -\unexpanded\def\doifelseutfmathfiller#1{\clf_doifelseutfmathfiller{#1}} -\unexpanded\def\doifelseutfmathlimop #1{\clf_doifelseutfmathlimop {#1}} +\permanent\protected\def\doifelseutfmathaccent#1{\clf_doifelseutfmathaccent{#1}} +\permanent\protected\def\doifelseutfmathabove #1{\clf_doifelseutfmathabove {#1}} +\permanent\protected\def\doifelseutfmathbelow #1{\clf_doifelseutfmathbelow {#1}} +\permanent\protected\def\doifelseutfmathfiller#1{\clf_doifelseutfmathfiller{#1}} +\permanent\protected\def\doifelseutfmathlimop #1{\clf_doifelseutfmathlimop {#1}} -\let\doifutfmathaccentelse \doifelseutfmathaccent -\let\doifutfmathaboveelse \doifelseutfmathabove -\let\doifutfmathbelowelse \doifelseutfmathbelow -\let\doifutfmathfillerelse \doifelseutfmathfiller -\let\doifutfmathlimopelse \doifelseutfmathlimop +\aliased\let\doifutfmathaccentelse \doifelseutfmathaccent +\aliased\let\doifutfmathaboveelse \doifelseutfmathabove +\aliased\let\doifutfmathbelowelse \doifelseutfmathbelow +\aliased\let\doifutfmathfillerelse \doifelseutfmathfiller +\aliased\let\doifutfmathlimopelse \doifelseutfmathlimop %D Not used that much: \installcorenamespace{mathcodecommand} -\unexpanded\def\mathlimop#1{\mathop{#1}} %no \limits -\unexpanded\def\mathbox #1{\dontleavehmode\hbox\Ustartmath\mathsurround\zeropoint#1\Ustopmath} -\unexpanded\def\mathnolop#1{\mathop{#1}\nolimits} +\permanent\protected\def\mathlimop#1{\mathop{#1}} %no \limits +\permanent\protected\def\mathbox #1{\dontleavehmode\hbox\Ustartmath\mathsurround\zeropoint#1\Ustopmath} +\permanent\protected\def\mathnolop#1{\mathop{#1}\nolimits} \let\mathnothing\firstofoneunexpanded \let\mathalpha \firstofoneunexpanded @@ -663,9 +658,9 @@ \setnewconstant\mathaccentcode \pluseight \setnewconstant\mathradicalcode \plusnine - \def\mathcodenumber #1{\the\csname math#1code\endcsname} -\unexpanded\def\mathcodecommand#1{\csname\??mathcodecommand#1\endcsname} - \def\mathcodechecked#1{\ifcsname math#1code\endcsname\lastnamedcs\else#1\fi} +\permanent \def\mathcodenumber #1{\the\csname math#1code\endcsname} +\permanent\protected\def\mathcodecommand#1{\csname\??mathcodecommand#1\endcsname} +\permanent \def\mathcodechecked#1{\ifcsname math#1code\endcsname\lastnamedcs\else#1\fi} % \startlines % $\mathopnolimits{\rm d}x$ @@ -681,11 +676,10 @@ \installcorenamespace{mathcommand} -\unexpanded\def\definemathcommand - {\dotripleempty\math_define_command} +% todo: define these commands as frozen! -\def\math_define_command[#1][#2][#3]#4% command class args meaning - {\ifthirdargument +\permanent\tolerant\protected\def\definemathcommand[#1]#*[#2]#*[#3]#:#*#4% command class args meaning + {\ifparameter#3\or \edef\nofmathcommandarguments{#3}% \ifx\nofmathcommandarguments\v!one \setuvalue{\??mathcommand#1}##1{\mathcodecommand{#2}{#4{##1}}}% @@ -694,14 +688,16 @@ \else \setuvalue{\??mathcommand#1}{\mathcodecommand{#2}{#4}}% \fi - \orelse\ifsecondargument + \orelse\ifparameter#2\or \setuvalue{\??mathcommand#1}{\mathcodecommand{#2}{#4}}% \else \setuvalue{\??mathcommand#1}{\mathcodecommand{nothing}{#4}}% \fi - \letcsnamecsname\csname#1\endcsname\csname\??mathcommand#1\endcsname} + \ifparameter#1\or % safeguard + \letcsnamecsname\csname#1\endcsname\csname\??mathcommand#1\endcsname + \fi} -\unexpanded\def\mathcommand#1% +\permanent\protected\def\mathcommand#1% {\begincsname\??mathcommand#1\endcsname} %D Let's define a few comands here: @@ -712,17 +708,17 @@ \chardef\c_math_strut"28 -\unexpanded\def\math_strut_htdp#1% +\protected\def\math_strut_htdp#1% {\s!height\fontcharht#1\c_math_strut \s!depth \fontchardp#1\c_math_strut} -\unexpanded\def\math_strut_normal +\protected\def\math_strut_normal {\vrule \s!width \zeropoint \normalexpanded{\math_strut_htdp{\mathstylefont\normalmathstyle}}% \relax} -\unexpanded\def\math_strut_visual +\protected\def\math_strut_visual {\hskip-.01\emwidth \vrule \s!width .02\emwidth @@ -730,19 +726,23 @@ \relax \hskip-.01\emwidth} -\unexpanded\def\showmathstruts % let's not overload \math_strut_normal - {\let\math_strut\math_strut_visual} +\protected\def\showmathstruts % let's not overload \math_strut_normal + {\enforced\let\math_strut\math_strut_visual} \let\math_strut\math_strut_normal -% \unexpanded\def\mathstrut{\mathcodecommand{nothing}{\math_strut}} +% \protected\def\mathstrut{\mathcodecommand{nothing}{\math_strut}} + +\pushoverloadmode + + \definemathcommand [mathstrut] {\math_strut} -\definemathcommand [mathstrut] {\math_strut} +\popoverloadmode %D We could have a arg variant \unknown\ but not now. -\unexpanded\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits} -\unexpanded\def\stackrel #1#2{\mathrel{\mathop{#2}\limits^{#1}}} +\permanent\protected\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits} +\permanent\protected\def\stackrel #1#2{\mathrel{\mathop{#2}\limits^{#1}}} %D Moved from font-ini.mkiv: %D @@ -751,14 +751,13 @@ %D %D Todo: -\unexpanded\def\mf - {\begincsname\fontalternative\endcsname} +\protected\def\mf{\begincsname\fontalternative\endcsname} % todo: \frozen % \let\normalmathop\mathop % already defined % no longer needed as we no longer switch fonts % -% \unexpanded\def\mathop +% \protected\def\mathop % {\normalmathop % \bgroup % % no: \let\rm\mf @@ -768,7 +767,7 @@ % this one too: \letvalue{\??mathcodecommand op}\mathop ? -\unexpanded\def\normalmbox +\permanent\protected\def\normalmbox {\normalhbox\bgroup \usemathematicsstyleandcolor\c!textstyle\c!textcolor % new \dowithnextboxcs\math_mbox_finish\normalhbox} @@ -777,16 +776,16 @@ {\flushnextbox \egroup} -\unexpanded\def\mbox % we cannot add \dontleavehmode ... else no \setbox0\mbox possible +\permanent\protected\def\mbox % we cannot add \dontleavehmode ... else no \setbox0\mbox possible {\ifmmode\normalmbox\else\normalhbox\fi} -\unexpanded\def\enablembox +\permanent\protected\def\enablembox {\toksapp\everymathematics{\math_enable_mbox}} -\def\math_enable_mbox - {\let\hbox\mbox} +\permanent\def\math_enable_mbox % brrrr + {\enforced\let\hbox\mbox} -\unexpanded\def\snappedmath#1% sort of \struttedbox +\permanent\protected\def\snappedmath#1% sort of \struttedbox {\dontleavehmode \begingroup \setbox\scratchbox\normalhbox\bgroup @@ -797,7 +796,7 @@ \box\scratchbox \endgroup} -\unexpanded\def\mtext#1% +\permanent\protected\def\mtext#1% {\text{\usemathematicsstyleandcolor\c!textstyle\c!textcolor#1}} %D The next hack is needed needed for sine, cosine etc. @@ -810,8 +809,8 @@ \let\math_tags_mo\firstofoneunexpanded \let\math_tags_mi\firstofoneunexpanded -\unexpanded\def\math_tags_mn#1{\begingroup\mathupright\math_set_o_both#1\endgroup} -\unexpanded\def\math_tags_ms#1{\begingroup\mathupright\math_set_p_both#1\endgroup} +\protected\def\math_tags_mn#1{\begingroup\mathupright\math_set_o_both#1\endgroup} +\protected\def\math_tags_ms#1{\begingroup\mathupright\math_set_p_both#1\endgroup} % Once this is stable we can store the number at the tex end which is % faster. Functions getnumbers >= 1000. @@ -824,7 +823,7 @@ \c!functionstyle=, % rm ss etc i.e. known alternatives, otherwise math \c!functioncolor=] -\unexpanded\def\math_mfunction_styled +\protected\def\math_mfunction_styled {\begingroup \usemathematicscolorparameter\c!functioncolor \edef\p_functionstyle{\mathematicsparameter\c!functionstyle}% @@ -836,28 +835,28 @@ \doubleexpandafter\math_mfunction_styled_math \fi} -\unexpanded\def\math_mfunction_styled_text#1% +\protected\def\math_mfunction_styled_text#1% %{\mathoptext{\csname\??alternativestyle\p_functionstyle\endcsname#1}% {\expandafter\mathoptext\expandafter{\lastnamedcs#1}% \endgroup} -\unexpanded\def\math_mfunction_styled_math#1% +\protected\def\math_mfunction_styled_math#1% {\p_functionstyle #1% \endgroup} -\unexpanded\def\math_mfunction_styled_none#1% +\protected\def\math_mfunction_styled_none#1% {\mathupright #1% \endgroup} -\unexpanded\def\mfunction#1% +\permanent\protected\def\mfunction#1% {\begingroup \math_tags_mfunctiontxt{#1}\c_apply_function \math_mfunction_styled{#1}% \endgroup} -\unexpanded\def\mfunctionlabeltext#1% +\permanent\protected\def\mfunctionlabeltext#1% {\begingroup \math_tags_mfunctionlab{#1}\c_apply_function \math_mfunction_styled{\mathlabeltext{#1}}% @@ -866,14 +865,14 @@ \let\math_tags_mfunctiontxt\gobbletwoarguments \let\math_tags_mfunctionlab\gobbletwoarguments -\unexpanded\def\math_tags_mo_indeed#1{\begingroup \c_attr_mathcategory\plusone #1\endgroup} -\unexpanded\def\math_tags_mi_indeed#1{\begingroup \c_attr_mathcategory\plustwo #1\endgroup} -\unexpanded\def\math_tags_mn_indeed#1{\begingroup\mathupright\c_attr_mathcategory\plusthree\math_set_o_both#1\endgroup} -\unexpanded\def\math_tags_ms_indeed#1{\begingroup\mathupright\c_attr_mathcategory\plusfour \math_set_p_both#1\endgroup} % todo: mathoptext +\permanent\protected\def\math_tags_mo_indeed#1{\begingroup \c_attr_mathcategory\plusone #1\endgroup} +\permanent\protected\def\math_tags_mi_indeed#1{\begingroup \c_attr_mathcategory\plustwo #1\endgroup} +\permanent\protected\def\math_tags_mn_indeed#1{\begingroup\mathupright\c_attr_mathcategory\plusthree\math_set_o_both#1\endgroup} +\permanent\protected\def\math_tags_ms_indeed#1{\begingroup\mathupright\c_attr_mathcategory\plusfour \math_set_p_both#1\endgroup} % todo: mathoptext \newconditional\c_apply_function -\unexpanded\def\math_tags_apply#1#2% +\permanent\protected\def\math_tags_apply#1#2% {\begingroup \settrue\c_apply_function #1% @@ -884,20 +883,20 @@ \endgroup} \appendtoks - \let\math_tags_mfunctiontxt\clf_tagmfunctiontxt - \let\math_tags_mfunctionlab\clf_tagmfunctionlab - \let\math_tags_mo \math_tags_mo_indeed - \let\math_tags_mi \math_tags_mi_indeed - \let\math_tags_mn \math_tags_mn_indeed - \let\math_tags_ms \math_tags_ms_indeed + \enforced\let\math_tags_mfunctiontxt\clf_tagmfunctiontxt + \enforced\let\math_tags_mfunctionlab\clf_tagmfunctionlab + \enforced\let\math_tags_mo \math_tags_mo_indeed + \enforced\let\math_tags_mi \math_tags_mi_indeed + \enforced\let\math_tags_mn \math_tags_mn_indeed + \enforced\let\math_tags_ms \math_tags_ms_indeed \to \everyenableelements \appendtoks - \let\mo \math_tags_mo - \let\mi \math_tags_mi - \let\mn \math_tags_mn - \let\ms \math_tags_ms - \let\apply\math_tags_apply + \enforced\let\mo \math_tags_mo + \enforced\let\mi \math_tags_mi + \enforced\let\mn \math_tags_mn + \enforced\let\ms \math_tags_ms + \enforced\let\apply\math_tags_apply \to\everymathematics % \def\mlimitsfunction #1{\mathlimopcomm{{\mr#1}} @@ -908,11 +907,11 @@ % % \def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option % -% \unexpanded\def\math_function_style_opnolimits #1{\mathop{\mscaledtext{#1}}\nolimits} -% \unexpanded\def\math_function_style_mfunction #1{\mscaledtext{\math_tags_function{#1}}} -% \unexpanded\def\math_function_style_mfunctionlabeltext#1{\mscaledtext{\math_tags_functionlabeltext{#1}}} +% \protected\def\math_function_style_opnolimits #1{\mathop{\mscaledtext{#1}}\nolimits} +% \protected\def\math_function_style_mfunction #1{\mscaledtext{\math_tags_function{#1}}} +% \protected\def\math_function_style_mfunctionlabeltext#1{\mscaledtext{\math_tags_functionlabeltext{#1}}} % -% \unexpanded\def\setmathfunctionstyle#1% rm ss tt (can be made faster if needed) +% \protected\def\setmathfunctionstyle#1% rm ss tt (can be made faster if needed) % {\doifsomething{#1} % {\def\currentmscaledstyle{#1}% % \let\mathopnolimits \math_function_style_opnolimits @@ -921,14 +920,14 @@ \def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option -\unexpanded\def\mscaledtext#1% +\permanent\protected\def\mscaledtext#1% {\mathchoice {\hbox{\csname\currentmscaledstyle\endcsname\tf #1}} {\hbox{\csname\currentmscaledstyle\endcsname\tf #1}} {\hbox{\csname\currentmscaledstyle\endcsname\tfx #1}} {\hbox{\csname\currentmscaledstyle\endcsname\tfxx#1}}} -\unexpanded\def\setmathfunctionstyle#1% +\permanent\protected\def\setmathfunctionstyle#1% {\setupmathematics[\c!functionstyle=#1]} % for old times sake %D Usage: @@ -965,12 +964,12 @@ \newtoks\activatedmathcharacters -\unexpanded\def\activatemathcharacter#1% +\permanent\protected\def\activatemathcharacter#1% {\appendtoks \global\mathcode#1=\activemathcharcode \to \activatedmathcharacters} -\def\activatemathcharacters +\permanent\def\activatemathcharacters {\the\activatedmathcharacters} % beware, not runtime, so has to happen at format generation @@ -1121,7 +1120,7 @@ % \let\prime\math_prime_indeed % so this is needed % \to \everydump % -% \unexpanded\def\math_prime_indeed +% \protected\def\math_prime_indeed % {\iffontchar\textfont\zerocount"FE325\relax % ^\bgroup % \expandafter\math_prime_indeed_virtual % virtual mess (using funny signal) @@ -1167,7 +1166,7 @@ % $\char26$ gives an error because it expands to an active character that % then becomes an & which is then seen as an alignment character; anyway, -% even when we switch like this the diufferen tmeaning only happens when +% even when we switch like this the different meaning only happens when % we're in math mode which can be delayed till we're in a cell \bgroup @@ -1178,19 +1177,19 @@ \glet\specialmathaligntab\normalmathaligntab - \unexpanded\gdef\obeymathcatcodes + \permanent\protected\gdef\obeymathcatcodes {\let _\normalsubscript \let ^\normalsuperscript \def &\specialmathaligntab } - \doglobal \appendtoks - \let _\normalsubscript - \let ^\normalsuperscript - \let &\specialmathaligntab - \to \everymathematics + \doglobal\appendtoks + \enforced\let _\normalsubscript + \enforced\let ^\normalsuperscript + \enforced\let &\specialmathaligntab + \to \everymathematics - % \unexpanded\gdef\normalmathampersands + % \permanent\protected\gdef\normalmathampersands % {\let\specialmathaligntab\mathampersand} \egroup @@ -1262,43 +1261,43 @@ %D Even more drastic (this code will move as nonknuthmode is default now) -% \unexpanded\def\enableasciimode +% \protected\def\enableasciimode % {\ctxlua{resolvers.macros.enablecomment()}% % \glet\enableasciimode\relax} % -% \unexpanded\def\asciimode +% \protected\def\asciimode % {\catcodetable\txtcatcodes % \enableasciimode % \nonknuthmode} % -% \unexpanded\def\startasciimode +% \protected\def\startasciimode % {\pushcatcodetable % \catcodetable\txtcatcodes % \enableasciimode % \nonknuthmode} % -% \unexpanded\def\stopasciimode +% \protected\def\stopasciimode % {\popcatcodetable % \ifconditional\knuthmode\else\donknuthmode\fi} -\unexpanded\def\enableasciimode +\permanent\protected\def\enableasciimode {\clf_enableasciimode} % relaxes itself -\unexpanded\def\asciimode +\permanent\protected\def\asciimode {\catcodetable\txtcatcodes \clf_enableasciimode} -\unexpanded\def\startasciimode +\permanent\protected\def\startasciimode {\pushcatcodetable \catcodetable\txtcatcodes \clf_enableasciimode} -\unexpanded\def\stopasciimode +\permanent\protected\def\stopasciimode {\popcatcodetable} %D Needed for unicode: -\def\nulloperator{\mathortext{\mathop{\emptyhbox}}{\emptyhbox}} +\permanent\def\nulloperator{\mathortext{\mathop{\emptyhbox}}{\emptyhbox}} %D Memory saver: @@ -1361,7 +1360,7 @@ \fi \to \everyswitchmathematics -\unexpanded\def\math_basics_synchronize_direction +\protected\def\math_basics_synchronize_direction {\mathdirection\ifconditional\c_math_right_to_left\directionrighttoleft\else\directionlefttoright\fi} % Not \everymathematics as it comes too late and I'm not in the mood for a mixed mode @@ -1444,9 +1443,9 @@ % only used local -\unexpanded\def\mathgreekupright{\c_attr_mathgreek"222\relax} -\unexpanded\def\mathgreekitalic {\c_attr_mathgreek"333\relax} -\unexpanded\def\mathgreekdefault{\c_attr_mathgreek"000\relax} +\permanent\protected\def\mathgreekupright{\c_attr_mathgreek"222\relax} +\permanent\protected\def\mathgreekitalic {\c_attr_mathgreek"333\relax} +\permanent\protected\def\mathgreekdefault{\c_attr_mathgreek"000\relax} \let\mathgreeknormal\mathgreekupright \let\mathgreeknone \mathgreekdefault @@ -1581,8 +1580,8 @@ % \newconditional\automathpunctuation % -% \unexpanded\def\enablemathpunctuation {\settrue \automathpunctuation} -% \unexpanded\def\disablemathpunctuation{\setfalse\automathpunctuation} +% \protected\def\enablemathpunctuation {\settrue \automathpunctuation} +% \protected\def\disablemathpunctuation{\setfalse\automathpunctuation} % % \appendtoks % \doifelse{\mathematicsparameter\v!autopunctuation}\v!yes\settrue\setfalse\automathpunctuation @@ -1593,8 +1592,8 @@ % % \def\math_punctuation_next{\ifx\nexttoken\blankspace\signalcharacter\fi} % -% \unexpanded\def\math_punctuation_comma {\textcomma \futurelet\nexttoken\math_punctuation_next} -% \unexpanded\def\math_punctuation_period{\textperiod\futurelet\nexttoken\math_punctuation_next} +% \protected\def\math_punctuation_comma {\textcomma \futurelet\nexttoken\math_punctuation_next} +% \protected\def\math_punctuation_period{\textperiod\futurelet\nexttoken\math_punctuation_next} % % \setnewconstant\c_math_comma "002C % \setnewconstant\c_math_period "002E @@ -1605,17 +1604,17 @@ % \catcode\c_math_comma \activecatcode % \catcode\c_math_period\activecatcode % -% \unexpanded\gdef\math_punctuation_initialize_indeed +% \protected\gdef\math_punctuation_initialize_indeed % {\mathcode\c_math_comma \c_math_special % \mathcode\c_math_period\c_math_special % \let,\math_punctuation_comma % \let.\math_punctuation_period % \c_attr_mathpunctuation\plustwo} % -% \unexpanded\gdef\math_punctuation_initialize_yes +% \protected\gdef\math_punctuation_initialize_yes % {\c_attr_mathpunctuation\plustwo} % -% \unexpanded\gdef\math_punctuation_initialize_nop +% \protected\gdef\math_punctuation_initialize_nop % {\c_attr_mathpunctuation\plusone} % % \egroup @@ -1636,11 +1635,11 @@ % \def\math_punctuation_comma_next {\ifx\nexttoken\blankspace\mathpunct\else\mathord\fi{\textcomma }} % \def\math_punctuation_period_next{\ifx\nexttoken\blankspace\mathpunct\else\mathord\fi{\textperiod}} % -% \unexpanded\def\math_punctuation_nop_comma {\mathpunct{\textcomma}} -% \unexpanded\def\math_punctuation_nop_period{\mathord{\textperiod}} +% \protected\def\math_punctuation_nop_comma {\mathpunct{\textcomma}} +% \protected\def\math_punctuation_nop_period{\mathord{\textperiod}} % -% \unexpanded\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next} -% \unexpanded\def\math_punctuation_all_period{\futurelet\nexttoken\math_punctuation_period_next} +% \protected\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next} +% \protected\def\math_punctuation_all_period{\futurelet\nexttoken\math_punctuation_period_next} % % \let\math_punctuation_yes_comma \math_punctuation_all_comma % \let\math_punctuation_yes_period\math_punctuation_nop_period @@ -1665,19 +1664,19 @@ \edef\math_set_o_both {\math_set_o_period\math_set_o_comma} \edef\math_set_p_both {\math_set_p_period\math_set_p_comma} -\unexpanded\def\math_punctuation_nop_comma {\begingroup\math_set_p_comma ,\endgroup} -\unexpanded\def\math_punctuation_nop_period {\begingroup\math_set_o_period .\endgroup} -\unexpanded\def\math_punctuation_nop_semicolon{\begingroup\math_set_p_semicolon;\endgroup} +\protected\def\math_punctuation_nop_comma {\begingroup\math_set_p_comma ,\endgroup} +\protected\def\math_punctuation_nop_period {\begingroup\math_set_o_period .\endgroup} +\protected\def\math_punctuation_nop_semicolon{\begingroup\math_set_p_semicolon;\endgroup} % todo: use new lookahead stuff -\unexpanded\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next} -\unexpanded\def\math_punctuation_all_period {\futurelet\nexttoken\math_punctuation_period_next} -\unexpanded\def\math_punctuation_all_semicolon{\futurelet\nexttoken\math_punctuation_semicolon_next} +\protected\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next} +\protected\def\math_punctuation_all_period {\futurelet\nexttoken\math_punctuation_period_next} +\protected\def\math_punctuation_all_semicolon{\futurelet\nexttoken\math_punctuation_semicolon_next} - \let\math_punctuation_yes_comma \math_punctuation_all_comma - \let\math_punctuation_yes_period \math_punctuation_nop_period - \let\math_punctuation_yes_semicolon\math_punctuation_all_semicolon + \let\math_punctuation_yes_comma \math_punctuation_all_comma + \let\math_punctuation_yes_period \math_punctuation_nop_period + \let\math_punctuation_yes_semicolon\math_punctuation_all_semicolon \def\math_punctuation_comma_next {\begingroup\Umathcode\c_math_comma \ifx\nexttoken\blankspace\mathordcode\else\mathordcode\fi\zerocount\c_math_comma ,\endgroup} \def\math_punctuation_period_next {\begingroup\Umathcode\c_math_period \ifx\nexttoken\blankspace\mathordcode\else\mathordcode\fi\zerocount\c_math_period .\endgroup} @@ -1815,7 +1814,7 @@ % 6 = scriptscript % 7 = crampedscriptscript -\def\uncramped#1% +\permanent\def\uncramped#1% {{\ifmathstyle \or \displaystyle \or \or \textstyle \or @@ -1823,7 +1822,7 @@ \or \scriptscriptstyle \fi #1}} -\def\cramped#1% +\permanent\def\cramped#1% {{\ifmathstyle \crampeddisplaystyle \or \or % 0 -> 1 \crampedtextstyle \or \or % 2 -> 3 @@ -1831,11 +1830,11 @@ \crampedscriptscriptstyle \fi % 6 -> 7 #1}} -\def\triggermathstyle#1{\Ustyle\numexpr#1\relax} -%def\mathstyletrigger#1{\numexpr#1\relax} -\let\mathstyletrigger \firstofoneargument +\permanent\def\triggermathstyle#1{\Ustyle\numexpr#1\relax} +%permanent\def\mathstyletrigger#1{\numexpr#1\relax} +\permanent\let\mathstyletrigger \firstofoneargument -\def\triggeredmathstyleparameter#1% to bypass the relax +\permanent\def\triggeredmathstyleparameter#1% to bypass the relax {\ifcase\numexpr\normalmathstyle\relax #1\displaystyle \or % 0 #1\crampeddisplaystyle \or % 1 @@ -1848,7 +1847,7 @@ % error \fi} -\def\mathstylefont#1% #1 is number (\normalmathstyle) +\permanent\def\mathstylefont#1% #1 is number (\normalmathstyle) {\ifcase\numexpr#1\relax \textfont \or \textfont \or @@ -1861,7 +1860,7 @@ \textfont \fi\fam} % was \zerocount -\def\somemathstylefont#1% #1 is number (\normalmathstyle) +\permanent\def\somemathstylefont#1% #1 is number (\normalmathstyle) {\ifcase\numexpr#1\relax \textfont \or \textfont \or @@ -1874,7 +1873,7 @@ \textfont \fi} -\def\mathsmallstylefont#1% #1 is number (\normalmathstyle) +\permanent\def\mathsmallstylefont#1% #1 is number (\normalmathstyle) {\ifcase\numexpr#1\relax \scriptfont \or \scriptfont \or @@ -1887,7 +1886,7 @@ \scriptfont \fi\fam} % was \zerocount -\def\mathstyleface#1% #1 is number (\normalmathstyle) +\permanent\def\mathstyleface#1% #1 is number (\normalmathstyle) {\ifcase\numexpr#1\relax \textface \or \textface \or @@ -1900,7 +1899,7 @@ \textface \fi} -\def\mathsmallstyleface#1% #1 is number (\normalmathstyle) +\permanent\def\mathsmallstyleface#1% #1 is number (\normalmathstyle) {\ifcase\numexpr#1\relax \scriptface \or \scriptface \or @@ -1913,7 +1912,7 @@ \scriptface \fi} -\def\mathstylecommand#1#2#3% +\permanent\def\mathstylecommand#1#2#3% {\ifcase\numexpr\normalmathstyle\relax \expandafter#1\or \expandafter#1\or @@ -1925,7 +1924,7 @@ \expandafter#3\else \expandafter#1\fi} -% \def\textstyleface#1% #1 is number (\normalmathstyle) +% \permanent\def\textstyleface#1% #1 is number (\normalmathstyle) % {\ifcase\numexpr#1\relax % \tf \or % \tf \or @@ -1938,7 +1937,7 @@ % \tf % \fi} -\unexpanded\def\verbosemathstyle#1% #1 is number (\normalmathstyle) +\permanent\protected\def\verbosemathstyle#1% #1 is number (\normalmathstyle) {{\normalexpanded{\relax\darkgray\ttxx[\number#1:\ifcase\numexpr#1\relax display\or % 0 crampeddisplay\or % 1 @@ -1950,13 +1949,13 @@ crampedscriptscript\else % 7 unknown\fi]}}} -\unexpanded\def\showmathstyle{\verbosemathstyle\normalmathstyle} +\permanent\protected\def\showmathstyle{\verbosemathstyle\normalmathstyle} %D Handy too: -\def\mathcharwd{\fontcharwd\mathstylefont\normalmathstyle} -\def\mathcharht{\fontcharht\mathstylefont\normalmathstyle} -\def\mathchardp{\fontchardp\mathstylefont\normalmathstyle} +\permanent\def\mathcharwd{\fontcharwd\mathstylefont\normalmathstyle} +\permanent\def\mathcharht{\fontcharht\mathstylefont\normalmathstyle} +\permanent\def\mathchardp{\fontchardp\mathstylefont\normalmathstyle} %D Some dimension fun: @@ -1965,7 +1964,7 @@ %D A plain inheritance: -\def\mathpalette#1#2% +\permanent\def\mathpalette#1#2% {\mathchoice {#1\displaystyle {#2}}% {#1\textstyle {#2}}% @@ -1982,40 +1981,40 @@ % to be tested: {#1} but it could have side effects -% \unexpanded\def\mathstylehbox#1% sensitive for: a \over b => {a\over b} or \frac{a}{b} +% \protected\def\mathstylehbox#1% sensitive for: a \over b => {a\over b} or \frac{a}{b} % {\normalexpanded{\hbox\bgroup % \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup} -\unexpanded\def\mathstylehbox#1#% sensitive for: a \over b => {a\over b} or \frac{a}{b} +\permanent\protected\def\mathstylehbox#1#% sensitive for: a \over b => {a\over b} or \frac{a}{b} {\math_style_hbox{#1}} -\unexpanded\def\math_style_hbox#1#2% sensitive for: a \over b => {a\over b} or \frac{a}{b} +\protected\def\math_style_hbox#1#2% sensitive for: a \over b => {a\over b} or \frac{a}{b} {\normalexpanded{\hbox#1\bgroup \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#2\stopimath\egroup} -\unexpanded\def\mathstylevbox#1% +\permanent\protected\def\mathstylevbox#1% {\normalexpanded{\vbox\bgroup \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup} -\unexpanded\def\mathstylevcenter#1% +\permanent\protected\def\mathstylevcenter#1% {\normalexpanded{\vcenter\bgroup \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup} -\unexpanded\def\mathstylevcenteredhbox#1% +\permanent\protected\def\mathstylevcenteredhbox#1% {\normalexpanded{\vcenter\bgroup\hbox\bgroup \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup} -\unexpanded\def\mathstylevcenteredvbox#1% +\permanent\protected\def\mathstylevcenteredvbox#1% {\normalexpanded{\vcenter\bgroup\vbox\bgroup \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup} -\unexpanded\def\setmathsmalltextbox#1#2#% +\permanent\protected\def\setmathsmalltextbox#1#2#% {\normalizebodyfontsize\m_math_text_choice_face{\mathsmallstyleface\normalmathstyle}% \setbox#1#2\bgroup \font_basics_switchtobodyfont\m_math_text_choice_face \let\next} -\unexpanded\def\setmathtextbox#1#2#% +\permanent\protected\def\setmathtextbox#1#2#% {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}% \setbox#1#2\bgroup \font_basics_switchtobodyfont\m_math_text_choice_face @@ -2042,7 +2041,7 @@ %D \HL %D \stoptabulate -\def\triggerdisplaystyle +\permanent\def\triggerdisplaystyle {\ifmathstyle \displaystyle \or \crampeddisplaystyle \or @@ -2054,7 +2053,7 @@ \crampeddisplaystyle \or \fi} -\def\triggertextstyle +\permanent\def\triggertextstyle {\ifmathstyle \textstyle \or \crampedtextstyle \or @@ -2066,7 +2065,7 @@ \crampedtextstyle \else \fi} -\def\triggerscriptstyle +\permanent\def\triggerscriptstyle {\ifmathstyle \scriptstyle \or \crampedscriptstyle \or @@ -2078,7 +2077,7 @@ \crampedscriptstyle \or \fi} -\def\triggerscriptscriptstyle +\permanent\def\triggerscriptscriptstyle {\ifmathstyle \scriptscriptstyle \or \crampedscriptscriptstyle \or @@ -2090,21 +2089,21 @@ \crampedscriptscriptstyle \or \fi} -\def\triggeruncrampedstyle +\permanent\def\triggeruncrampedstyle {\ifmathstyle \or \displaystyle \or \or \textstyle \or \or \scriptstyle \or \or \scriptscriptstyle \fi} -\def\triggercrampedstyle +\permanent\def\triggercrampedstyle {\ifmathstyle \crampeddisplaystyle \or \or \crampedtextstyle \or \or \crampedscriptstyle \or \or \crampedscriptscriptstyle \fi} -\def\triggersmallstyle +\permanent\def\triggersmallstyle {\ifmathstyle \scriptstyle \or \crampedscriptstyle \or @@ -2116,7 +2115,7 @@ \crampedscriptscriptstyle \or \fi} -\def\triggeruncrampedsmallstyle +\permanent\def\triggeruncrampedsmallstyle {\ifmathstyle \scriptstyle \or \scriptstyle \or @@ -2128,7 +2127,7 @@ \scriptscriptstyle \or \fi} -\def\triggercrampedsmallstyle +\permanent\def\triggercrampedsmallstyle {\ifmathstyle \crampedscriptstyle \or \crampedscriptstyle \or @@ -2140,7 +2139,7 @@ \crampedscriptscriptstyle \or \fi} -\def\triggerbigstyle +\permanent\def\triggerbigstyle {\ifmathstyle \displaystyle \or \crampeddisplaystyle \or @@ -2152,7 +2151,7 @@ \crampedscriptstyle \or \fi} -\def\triggeruncrampedbigstyle +\permanent\def\triggeruncrampedbigstyle {\ifmathstyle \displaystyle \or \displaystyle \or @@ -2164,7 +2163,7 @@ \scriptstyle \or \fi} -\def\triggercrampedbigstyle +\permanent\def\triggercrampedbigstyle {\ifmathstyle \crampeddisplaystyle \or \crampeddisplaystyle \or @@ -2178,10 +2177,10 @@ \newcount\c_math_saved_style -\unexpanded\def\pushmathstyle % assumes begingroup .. endgroup +\permanent\protected\def\pushmathstyle % assumes begingroup .. endgroup {\c_math_saved_style\mathstyle} -\unexpanded\def\popmathstyle +\permanent\protected\def\popmathstyle {\ifnum\mathstyle=\c_math_saved_style\else \triggermathstyle\c_math_saved_style \fi} @@ -2266,7 +2265,7 @@ \fi } -\unexpanded\def\math_style_set#1% +\protected\def\math_style_set#1% {\edef\m_math_style_asked{#1}% \ifempty\m_math_style_asked \else \math_style_set_indeed @@ -2274,7 +2273,7 @@ \let\setmathstyle\math_style_set -\def\installmathstyle#1#2% +\permanent\def\installmathstyle#1#2% {\ifcsname\??mathstylecommand#1\endcsname \else \setvalue{\??mathstylecommand#1}{#2}% \fi} @@ -2295,13 +2294,13 @@ \setvalue{\??mathstylecommand\v!small }{\c_math_styles_state_size \plusone} \setvalue{\??mathstylecommand\v!big }{\c_math_styles_state_size \plustwo} -\unexpanded\def\setupmathstyle[#1]% +\permanent\protected\def\setupmathstyle[#1]% {\edef\m_math_style_asked{#1}% \ifempty\m_math_style_asked \else \math_style_set_indeed \fi} -\unexpanded\def\usemathstyleparameter#1% faster local variant +\permanent\protected\def\usemathstyleparameter#1% faster local variant {\edef\m_math_style_asked{#1\c!mathstyle}% \ifempty\m_math_style_asked \else \math_style_set_indeed @@ -2317,10 +2316,7 @@ \installcorenamespace {mathstyle} -\unexpanded\def\definemathstyle - {\dodoubleargument\math_style_define} - -\def\math_style_define[#1][#2]% +\permanent\tolerant\protected\def\definemathstyle[#1]#*[#2]% {\c_math_styles_state_style \zerocount \c_math_styles_state_cramped\zerocount \c_math_styles_state_size \zerocount @@ -2386,7 +2382,7 @@ %D %D \typebuffer \getbuffer -\unexpanded\def\startmathstyle[#1]% +\permanent\protected\def\startmathstyle[#1]% {\edef\m_math_style_asked{#1}% \ifempty\m_math_style_asked \let\stopmathstyle\relax @@ -2398,7 +2394,7 @@ \let\stopmathstyle\relax -\unexpanded\def\startusemathstyleparameter#1% +\permanent\protected\def\startusemathstyleparameter#1% {\edef\m_math_style_asked{#1\c!mathstyle}% \ifempty\m_math_style_asked \let\stopusemathstyleparameter\relax @@ -2482,32 +2478,34 @@ %mathscriptboxmode \plusthree % lists and boxes with \boundary=1 (also for testing and demo) \mathrulethicknessmode\plusone % adaptive -\unexpanded\def\mathtext {\mathortext{\math_text_choice_font\relax}\hbox} -\unexpanded\def\mathword {\mathortext{\math_text_choice_word\relax}\hbox} +\permanent\protected\def\mathtext {\mathortext{\math_text_choice_font\relax}\hbox} +\permanent\protected\def\mathword {\mathortext{\math_text_choice_word\relax}\hbox} -\unexpanded\def\mathtexttf{\mathortext{\math_text_choice_font\tf}\hbox} -\unexpanded\def\mathtextit{\mathortext{\math_text_choice_font\it}\hbox} -\unexpanded\def\mathtextsl{\mathortext{\math_text_choice_font\sl}\hbox} -\unexpanded\def\mathtextbf{\mathortext{\math_text_choice_font\bf}\hbox} -\unexpanded\def\mathtextbi{\mathortext{\math_text_choice_font\bi}\hbox} -\unexpanded\def\mathtextbs{\mathortext{\math_text_choice_font\bs}\hbox} +\permanent\protected\def\mathtexttf{\mathortext{\math_text_choice_font\tf}\hbox} +\permanent\protected\def\mathtextit{\mathortext{\math_text_choice_font\it}\hbox} +\permanent\protected\def\mathtextsl{\mathortext{\math_text_choice_font\sl}\hbox} +\permanent\protected\def\mathtextbf{\mathortext{\math_text_choice_font\bf}\hbox} +\permanent\protected\def\mathtextbi{\mathortext{\math_text_choice_font\bi}\hbox} +\permanent\protected\def\mathtextbs{\mathortext{\math_text_choice_font\bs}\hbox} -\unexpanded\def\mathwordtf{\mathortext{\math_text_choice_word\tf}\hbox} -\unexpanded\def\mathwordit{\mathortext{\math_text_choice_word\it}\hbox} -\unexpanded\def\mathwordsl{\mathortext{\math_text_choice_word\sl}\hbox} -\unexpanded\def\mathwordbf{\mathortext{\math_text_choice_word\bf}\hbox} -\unexpanded\def\mathwordbi{\mathortext{\math_text_choice_word\bi}\hbox} -\unexpanded\def\mathwordbs{\mathortext{\math_text_choice_word\bs}\hbox} +\permanent\protected\def\mathwordtf{\mathortext{\math_text_choice_word\tf}\hbox} +\permanent\protected\def\mathwordit{\mathortext{\math_text_choice_word\it}\hbox} +\permanent\protected\def\mathwordsl{\mathortext{\math_text_choice_word\sl}\hbox} +\permanent\protected\def\mathwordbf{\mathortext{\math_text_choice_word\bf}\hbox} +\permanent\protected\def\mathwordbi{\mathortext{\math_text_choice_word\bi}\hbox} +\permanent\protected\def\mathwordbs{\mathortext{\math_text_choice_word\bs}\hbox} %D Safeguard against redefinitions: \appendtoks - \let\_\normalunderscore % is textunderscore or fakeunderscore + \enforced\let\_\normalunderscore % is textunderscore or fakeunderscore \to \everymathematics %D Because we may overload \type {\text} in other (structuring) macros, we say: -\appendtoks \let\text\mathtext \to \everymathematics +\appendtoks + \enforced\let\text\mathtext +\to \everymathematics %D The next code is derived from plain \TEX. The names will change! @@ -2537,7 +2535,7 @@ % this can become an option: -\unexpanded\def\math_display_align_hack % I don't like the global, maybe we should push and pop +\protected\def\math_display_align_hack % I don't like the global, maybe we should push and pop {\glet\math_display_align_hack_indeed\math_display_align_hack_remove_skip \math_openup\displayopenupvalue % was \math_openup\jot \everycr{\noalign{\math_display_align_hack_indeed}}} @@ -2557,7 +2555,7 @@ %D Text in math: -\unexpanded\def\mathortext +\permanent\protected\def\mathortext {\ifmmode \expandafter\firstoftwoarguments \else @@ -2570,9 +2568,9 @@ \ifdefined\text\else \let\text\hbox \fi -% \unexpanded\def\mathoptext#1{\mathop{\text{#1}}} +% \protected\def\mathoptext#1{\mathop{\text{#1}}} -\unexpanded\def\mathoptext +\permanent\protected\def\mathoptext {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}% %\showmathstyle \dowithnextbox @@ -2597,15 +2595,15 @@ % new: -\unexpanded\def\smallmathsymbol#1% +\permanent\protected\def\smallmathsymbol#1% {\mathematics{\mathbin{\normalexpanded{\raise.15\exheight\hbox{\normalstartimath \triggermathstyle{\the\numexpr\normalmathstyle+2\relax}#1% \normalstopimath}}}}} % this should be a primitive: -\def\mathextensiblecode#1#2{\clf_extensiblecode\numexpr#1\relax\numexpr#2\relax} -\def\mathhorizontalcode#1#2{\clf_horizontalcode\numexpr#1\relax\numexpr#2\relax} +\permanent\def\mathextensiblecode#1#2{\clf_extensiblecode\numexpr#1\relax\numexpr#2\relax} +\permanent\def\mathhorizontalcode#1#2{\clf_horizontalcode\numexpr#1\relax\numexpr#2\relax} % experimental: @@ -2662,18 +2660,18 @@ {\let\math_inline_openup_start_yes\math_inline_openup_traced_start} {\let\math_inline_openup_start_yes\math_inline_openup_normal_start} -\unexpanded\def\math_inline_openup_normal_start +\protected\def\math_inline_openup_normal_start {\scratchheight\dimexpr\ht\scratchbox+\m_math_inline_openup_ht\relax \scratchdepth \dimexpr\dp\scratchbox+\m_math_inline_openup_dp\relax \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax \begingroup \let\math_inline_openup_stop\math_inline_openup_normal_stop} -\unexpanded\def\math_inline_openup_normal_stop +\protected\def\math_inline_openup_normal_stop {\endgroup \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax} -\unexpanded\def\math_inline_openup_traced_start +\protected\def\math_inline_openup_traced_start {\scratchtopoffset \ht\scratchbox \scratchbottomoffset\dp\scratchbox \scratchheight \dimexpr\scratchtopoffset +\m_math_inline_openup_ht\relax @@ -2687,7 +2685,7 @@ \begingroup \let\math_inline_openup_stop\math_inline_openup_traced_stop} -\unexpanded\def\math_inline_openup_traced_stop +\protected\def\math_inline_openup_traced_stop {\endgroup \kern-\emwidth \begingroup @@ -2702,7 +2700,7 @@ \def\math_inline_openup_start_nop {\let\math_inline_openup_stop\relax} -\unexpanded\def\openedupimath +\permanent\protected\def\openedupimath {\dontleavehmode \begingroup \ifmmode @@ -2711,7 +2709,7 @@ \expandafter\openedupimath_text \fi} -\unexpanded\def\openedupimath_math#1% +\protected\def\openedupimath_math#1% {\setbox\scratchbox\mathstylehbox{#1}% \ifdim\ht\scratchbox>\strutht \math_inline_openup_start_yes @@ -2724,7 +2722,7 @@ \math_inline_openup_stop \endgroup} -\unexpanded\def\openedupimath_text#1% +\protected\def\openedupimath_text#1% {\setbox\scratchbox\hbox{\startimath#1\stopimath}% \ifdim\ht\scratchbox>\strutht \math_inline_openup_start_yes @@ -2743,14 +2741,14 @@ % % 0x002B=plus 0x2212=minus 0x2013=endash -\unexpanded\def\mathplus {+} -\unexpanded\def\mathminus {\ifmmode –\orelse\iffontchar\font`−−\else –\fi} -\unexpanded\def\mathplusminus{±} +\permanent\protected\def\mathplus {+} +\permanent\protected\def\mathminus {\ifmmode –\orelse\iffontchar\font`−−\else –\fi} +\permanent\protected\def\mathplusminus{±} %D The \type {\displaywidth} is only known inside a display formula, so we need to catch %D it when still zero. -\def\checkeddisplaywidth % hsize if zero +\permanent\def\checkeddisplaywidth % hsize if zero {\dimexpr \ifzeropt\displaywidth \hsize @@ -2759,7 +2757,7 @@ \fi \relax} -\def\maximizeddisplaywidth % larger than zero but within hsize +\permanent\def\maximizeddisplaywidth % larger than zero but within hsize {\dimexpr \ifzeropt\displaywidth \hsize @@ -2801,7 +2799,7 @@ \installcorenamespace{mathrules} -\unexpanded\def\enablemathrules{\letgvalue{\??mathrules\fontclass}\plusone} +\permanent\protected\def\enablemathrules{\letgvalue{\??mathrules\fontclass}\plusone} \appendtoks \mathrulesmode\ifcsname\??mathrules\fontclass\endcsname @@ -2824,10 +2822,10 @@ % \NC \tex {f6} \tex {emspace} \NC \tex {b6} \NC {\darkred\vl}\f6{\darkblue\vl} \NC ${\darkred\vl}\f6{\darkblue\vl}$ \NC \NR % \stoptabulate -% \unexpanded\def\negenspace{\kern-.5\emwidth} -% \unexpanded\def\negemspace{\kern- \emwidth} +% \protected\def\negenspace{\kern-.5\emwidth} +% \protected\def\negemspace{\kern- \emwidth} % -% \unexpanded\def\math_f#1% +% \protected\def\math_f#1% % {\ifcase#1\or % \hairspace % \or @@ -2842,7 +2840,7 @@ % \emspace % \fi} % -% \unexpanded\def\math_b#1% +% \protected\def\math_b#1% % {\ifcase#1\or % \neghairspace % \or @@ -2864,16 +2862,16 @@ %D Experiment -\unexpanded\def\math_scripts_stack +\permanent\protected\def\math_scripts_stack {\c_attr_mathunstack\attributeunsetvalue} -\unexpanded\def\math_scripts_unstack +\permanent\protected\def\math_scripts_unstack {\clf_enablescriptunstacking \c_attr_mathunstack\plusone} \appendtoks - \let\stackscripts \math_scripts_stack - \let\unstackscripts\math_scripts_unstack + \enforced\let\stackscripts \math_scripts_stack + \enforced\let\unstackscripts\math_scripts_unstack \to \everymathematics %D Expensive (tracing and inject) but a primitive (using factors) is tricky as we @@ -2916,7 +2914,7 @@ %D $\mathopenupparameter\Umathradicalvgap{10.5}\sqrt[3]{x}$ %D \stoptyping -\unexpanded\def\mathopenupparameter#1#2% +\permanent\protected\def\mathopenupparameter#1#2% {\ifmathparameter#1\displaystyle \or\frozen#1\displaystyle #2#1\displaystyle \fi \ifmathparameter#1\crampeddisplaystyle \or\frozen#1\crampeddisplaystyle #2#1\crampeddisplaystyle \fi \ifmathparameter#1\textstyle \or\frozen#1\textstyle #2#1\textstyle \fi @@ -2942,13 +2940,13 @@ %D \getbuffer %D \stoplines -\unexpanded\def\tomathord {\Umathclass\zerocount} -\unexpanded\def\tomathop {\Umathclass\plusone } % \mathinfix -\unexpanded\def\tomathbin {\Umathclass\plustwo } -\unexpanded\def\tomathrel {\Umathclass\plusthree} -\unexpanded\def\tomathopen {\Umathclass\plusfour } % \mathprefix -\unexpanded\def\tomathclose{\Umathclass\plusfive } % \mathsuffix -\unexpanded\def\tomathpunct{\Umathclass\plussix } +\permanent\protected\def\tomathord {\Umathclass\zerocount} +\permanent\protected\def\tomathop {\Umathclass\plusone } % \mathinfix +\permanent\protected\def\tomathbin {\Umathclass\plustwo } +\permanent\protected\def\tomathrel {\Umathclass\plusthree} +\permanent\protected\def\tomathopen {\Umathclass\plusfour } % \mathprefix +\permanent\protected\def\tomathclose{\Umathclass\plusfive } % \mathsuffix +\permanent\protected\def\tomathpunct{\Umathclass\plussix } %D Prescripts. These work in \CONTEXT\ because we have the super- and subscript %D triggers enabled as active characters but when we would have @@ -2991,14 +2989,14 @@ % \newtoks \everystartimath % \newtoks \everystopimath % -% \unexpanded\def\startimath{\Ustartmath\the\everystartimath} -% \unexpanded\def\stopimath {\the\everystopimath\Ustopmath} +% \protected\def\startimath{\Ustartmath\the\everystartimath} +% \protected\def\stopimath {\the\everystopimath\Ustopmath} % -% \unexpanded\def\m% +% \protected\def\m% % {\relax % \ifmmode\expandafter\math_m_stay\else\expandafter\math_m_math\fi} % -% \unexpanded\def\math_m_math#1% +% \protected\def\math_m_math#1% % {\startimath#1\stopimath} % % \let\math_m_stay\firstofoneargument diff --git a/tex/context/base/mkiv/math-noa.lmt b/tex/context/base/mkiv/math-noa.lmt new file mode 100644 index 000000000..25e1823e2 --- /dev/null +++ b/tex/context/base/mkiv/math-noa.lmt @@ -0,0 +1,2399 @@ +if not modules then modules = { } end modules ['math-noa'] = { + version = 1.001, + optimize = true, + comment = "companion to math-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- beware: this is experimental code and there will be a more generic (attribute value +-- driven) interface too but for the moment this is ok (sometime in 2015-2016 i will +-- start cleaning up as by then the bigger picture is clear and code has been used for +-- years; the main handlers will get some extensions) +-- +-- we will also make dedicated processors (faster) +-- +-- beware: names will change as we wil make noads.xxx.handler i.e. xxx +-- subnamespaces + +-- 20D6 -> 2190 +-- 20D7 -> 2192 + +-- todo: most is mathchar_code so we can have simple dedicated loops + +-- nota bene: uunderdelimiter uoverdelimiter etc are radicals (we have 5 types) + +local next, tonumber = next, tonumber +local utfchar, utfbyte = utf.char, utf.byte +local formatters, gmatch = string.formatters, string.gmatch +local sortedhash = table.sortedhash +local insert, remove = table.insert, table.remove +local div, round = math.div, math.round +local bor, band = bit32.bor, bit32.band + +local fonts = fonts +local nodes = nodes +local node = node +local mathematics = mathematics +local context = context + +local otf = fonts.handlers.otf +local otffeatures = fonts.constructors.features.otf +local registerotffeature = otffeatures.register + +local privateattribute = attributes.private +local registertracker = trackers.register +local registerdirective = directives.register +local logreporter = logs.reporter +local setmetatableindex = table.setmetatableindex + +local colortracers = nodes.tracers.colors + +local trace_remapping = false registertracker("math.remapping", function(v) trace_remapping = v end) +local trace_processing = false registertracker("math.processing", function(v) trace_processing = v end) +local trace_analyzing = false registertracker("math.analyzing", function(v) trace_analyzing = v end) +local trace_normalizing = false registertracker("math.normalizing", function(v) trace_normalizing = v end) +local trace_collapsing = false registertracker("math.collapsing", function(v) trace_collapsing = v end) +local trace_fixing = false registertracker("math.fixing", function(v) trace_foxing = v end) +local trace_patching = false registertracker("math.patching", function(v) trace_patching = v end) +local trace_goodies = false registertracker("math.goodies", function(v) trace_goodies = v end) +local trace_variants = false registertracker("math.variants", function(v) trace_variants = v end) +local trace_alternates = false registertracker("math.alternates", function(v) trace_alternates = v end) +local trace_italics = false registertracker("math.italics", function(v) trace_italics = v end) +local trace_kernpairs = false registertracker("math.kernpairs", function(v) trace_kernpairs = v end) +local trace_domains = false registertracker("math.domains", function(v) trace_domains = v end) +local trace_families = false registertracker("math.families", function(v) trace_families = v end) +local trace_fences = false registertracker("math.fences", function(v) trace_fences = v end) +local trace_unstacking = false registertracker("math.unstack", function(v) trace_unstacking = v end) + +local check_coverage = true registerdirective("math.checkcoverage", function(v) check_coverage = v end) + +local report_processing = logreporter("mathematics","processing") +local report_remapping = logreporter("mathematics","remapping") +local report_normalizing = logreporter("mathematics","normalizing") +local report_collapsing = logreporter("mathematics","collapsing") +local report_fixing = logreporter("mathematics","fixing") +local report_patching = logreporter("mathematics","patching") +local report_goodies = logreporter("mathematics","goodies") +local report_variants = logreporter("mathematics","variants") +local report_alternates = logreporter("mathematics","alternates") +local report_italics = logreporter("mathematics","italics") +local report_kernpairs = logreporter("mathematics","kernpairs") +local report_domains = logreporter("mathematics","domains") +local report_families = logreporter("mathematics","families") +local report_fences = logreporter("mathematics","fences") +local report_unstacking = logreporter("mathematics","unstack") + +local a_mathrendering = privateattribute("mathrendering") +local a_exportstatus = privateattribute("exportstatus") + +local nuts = nodes.nuts +local nodepool = nuts.pool +local tonut = nuts.tonut +local nutstring = nuts.tostring + +local setfield = nuts.setfield +local setlink = nuts.setlink +local setlist = nuts.setlist +local setnext = nuts.setnext +local setprev = nuts.setprev +local setchar = nuts.setchar +local setfam = nuts.setfam +local setsubtype = nuts.setsubtype +local setattr = nuts.setattr +local setattrlist = nuts.setattrlist +local setwidth = nuts.setwidth +local setheight = nuts.setheight +local setdepth = nuts.setdepth + +local getfield = nuts.getfield +local getnext = nuts.getnext +local getprev = nuts.getprev +local getboth = nuts.getboth +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local getchar = nuts.getchar +local getfont = nuts.getfont +local getfam = nuts.getfam +local getattr = nuts.getattr +local getattrs = nuts.getattrs +local getlist = nuts.getlist +local getwidth = nuts.getwidth +local getheight = nuts.getheight +local getdepth = nuts.getdepth + +local getnucleus = nuts.getnucleus +local getsub = nuts.getsub +local getsup = nuts.getsup +local getsubpre = nuts.getsubpre +local getsuppre = nuts.getsuppre + +local setnucleus = nuts.setnucleus +local setsub = nuts.setsub +local setsup = nuts.setsup +local setsubpre = nuts.setsubpre +local setsuppre = nuts.setsuppre + +local flush_node = nuts.flush +local copy_node = nuts.copy +local slide_nodes = nuts.slide +local set_visual = nuts.setvisual + +local mlist_to_hlist = nuts.mlist_to_hlist + +local new_kern = nodepool.kern +local new_submlist = nodepool.submlist +local new_noad = nodepool.noad +local new_delimiter = nodepool.delimiter +local new_fence = nodepool.fence + +local fonthashes = fonts.hashes +local fontdata = fonthashes.identifiers +local fontcharacters = fonthashes.characters +local fontitalics = fonthashes.italics + +local variables = interfaces.variables +local texsetattribute = tex.setattribute +local texgetattribute = tex.getattribute +local getfontoffamily = tex.getfontoffamily +local unsetvalue = attributes.unsetvalue +local implement = interfaces.implement + +local v_reset = variables.reset + +local chardata = characters.data + +noads = noads or { } -- todo: only here +local noads = noads + +noads.processors = noads.processors or { } +local processors = noads.processors + +noads.handlers = noads.handlers or { } +local handlers = noads.handlers + +local tasks = nodes.tasks +local enableaction = tasks.enableaction +local setaction = tasks.setaction + +local nodecodes = nodes.nodecodes +local noadcodes = nodes.noadcodes +local fencecodes = nodes.fencecodes + +local ordnoad_code = noadcodes.ord +local opdisplaylimitsnoad_code = noadcodes.opdisplaylimits +local oplimitsnoad_code = noadcodes.oplimits +local opnolimitsnoad_code = noadcodes.opnolimits +local binnoad_code = noadcodes.bin +local relnode_code = noadcodes.rel +local opennoad_code = noadcodes.open +local closenoad_code = noadcodes.close +local punctnoad_code = noadcodes.punct +local innernoad_code = noadcodes.inner +local undernoad_code = noadcodes.under +local overnoad_code = noadcodes.over +local vcenternoad_code = noadcodes.vcenter +local ordlimitsnoad_code = noadcodes.ordlimits or oplimitsnoad_code + +local noad_code = nodecodes.noad -- attr nucleus sub sup +local accent_code = nodecodes.accent -- attr nucleus sub sup accent +local radical_code = nodecodes.radical -- attr nucleus sub sup left degree +local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right +local subbox_code = nodecodes.subbox -- attr list +local submlist_code = nodecodes.submlist -- attr list +local mathchar_code = nodecodes.mathchar -- attr fam char +local mathtextchar_code = nodecodes.mathtextchar -- attr fam char +local delimiter_code = nodecodes.delimiter -- attr small_fam small_char large_fam large_char +----- style_code = nodecodes.style -- attr style +----- parameter_code = nodecodes.parameter -- attr style +local math_choice = nodecodes.choice -- attr display text script scriptscript +local fence_code = nodecodes.fence -- attr subtype + +local leftfence_code = fencecodes.left +local middlefence_code = fencecodes.middle +local rightfence_code = fencecodes.right + +-- local mathclasses = mathematics.classes +-- local fenceclasses = { +-- [leftfence_code] = mathclasses.open, +-- [middlefence_code] = mathclasses.middle, +-- [rightfence_code] = mathclasses.close, +-- } + +-- this initial stuff is tricky as we can have removed and new nodes with the same address +-- the only way out is a free-per-page list of nodes (not bad anyway) + +-- local gf = getfield local gt = setmetatableindex("number") getfield = function(n,f) gt[f] = gt[f] + 1 return gf(n,f) end mathematics.GETFIELD = gt +-- local sf = setfield local st = setmetatableindex("number") setfield = function(n,f,v) st[f] = st[f] + 1 sf(n,f,v) end mathematics.SETFIELD = st + +local function process(start,what,n,parent) + + if n then + n = n + 1 + else + n = 0 + end + -- + local initial = start + -- + slide_nodes(start) -- we still miss a prev in noads -- fences test code + -- + while start do + local id = getid(start) + if trace_processing then + if id == noad_code then + report_processing("%w%S, class %a",n*2,nutstring(start),noadcodes[getsubtype(start)]) + elseif id == mathchar_code then + local char = getchar(start) + local font = getfont(start) + local fam = getfam(start) + report_processing("%w%S, family %a, font %a, char %a, shape %c",n*2,nutstring(start),fam,font,char,char) + else + report_processing("%w%S",n*2,nutstring(start)) + end + end + local proc = what[id] + if proc then + -- report_processing("start processing") + local done, newstart, newinitial = proc(start,what,n,parent) -- prev is bugged: or getprev(start) + if newinitial then + initial = newinitial -- temp hack .. we will make all return head + if newstart then + start = newstart + -- report_processing("stop processing (new start)") + else + -- report_processing("quit processing (done)") + break + end + else + if newstart then + start = newstart + -- report_processing("stop processing (new start)") + else + -- report_processing("stop processing") + end + end + elseif id == noad_code then + -- single characters are like this + local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list + noad = getsup (start) if noad then process(noad,what,n,start) end -- list + noad = getsub (start) if noad then process(noad,what,n,start) end -- list + if getsubpre then + noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list + noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list + end + elseif id == mathchar_code or id == mathtextchar_code or id == delimiter_code then + break + elseif id == subbox_code or id == submlist_code then + local noad = getlist(start) if noad then process(noad,what,n,start) end -- list (not getlist !) + elseif id == fraction_code then + local noad = getfield(start,"num") if noad then process(noad,what,n,start) end -- list + noad = getfield(start,"denom") if noad then process(noad,what,n,start) end -- list + noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter + noad = getfield(start,"right") if noad then process(noad,what,n,start) end -- delimiter + elseif id == math_choice then + local noad = getfield(start,"display") if noad then process(noad,what,n,start) end -- list + noad = getfield(start,"text") if noad then process(noad,what,n,start) end -- list + noad = getfield(start,"script") if noad then process(noad,what,n,start) end -- list + noad = getfield(start,"scriptscript") if noad then process(noad,what,n,start) end -- list + elseif id == fence_code then + local noad = getfield(start,"delimiter") if noad then process(noad,what,n,start) end -- delimiter + elseif id == radical_code then + local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list + noad = getsup (start) if noad then process(noad,what,n,start) end -- list + noad = getsub (start) if noad then process(noad,what,n,start) end -- list + if getsubpre then + noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list + noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list + end + noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter + noad = getfield(start,"degree") if noad then process(noad,what,n,start) end -- list + elseif id == accent_code then + local noad = getnucleus(start) if noad then process(noad,what,n,start) end -- list + noad = getsup (start) if noad then process(noad,what,n,start) end -- list + noad = getsub (start) if noad then process(noad,what,n,start) end -- list + if getsubpre then + noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list + noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list + end + noad = getfield(start,"accent") if noad then process(noad,what,n,start) end -- list + noad = getfield(start,"bot_accent") if noad then process(noad,what,n,start) end -- list + -- elseif id == style_code then + -- -- has a next + -- elseif id == parameter_code then + -- -- has a next + -- else + -- -- glue, penalty, etc + end + start = getnext(start) + end + if not parent then + return initial -- only first level -- for now + end +end + +local function processnested(current,what,n) + local noad = nil + local id = getid(current) + if id == noad_code then + noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list + noad = getsup (current) if noad then process(noad,what,n,current) end -- list + noad = getsub (current) if noad then process(noad,what,n,current) end -- list + if getsubpre then + noad = getsuppre (current) if noad then process(noad,what,n,current) end -- list + noad = getsubpre (current) if noad then process(noad,what,n,current) end -- list + end + elseif id == subbox_code or id == submlist_code then + noad = getlist(current) if noad then process(noad,what,n,current) end -- list (not getlist !) + elseif id == fraction_code then + noad = getfield(current,"num") if noad then process(noad,what,n,current) end -- list + noad = getfield(current,"denom") if noad then process(noad,what,n,current) end -- list + noad = getfield(current,"left") if noad then process(noad,what,n,current) end -- delimiter + noad = getfield(current,"right") if noad then process(noad,what,n,current) end -- delimiter + elseif id == math_choice then + noad = getfield(current,"display") if noad then process(noad,what,n,current) end -- list + noad = getfield(current,"text") if noad then process(noad,what,n,current) end -- list + noad = getfield(current,"script") if noad then process(noad,what,n,current) end -- list + noad = getfield(current,"scriptscript") if noad then process(noad,what,n,current) end -- list + elseif id == fence_code then + noad = getfield(current,"delimiter") if noad then process(noad,what,n,current) end -- delimiter + elseif id == radical_code then + noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list + noad = getsup (current) if noad then process(noad,what,n,current) end -- list + noad = getsub (current) if noad then process(noad,what,n,current) end -- list + if getsubpre then + noad = getsuppre (current) if noad then process(noad,what,n,current) end -- list + noad = getsubpre (current) if noad then process(noad,what,n,current) end -- list + end + noad = getfield(current,"left") if noad then process(noad,what,n,current) end -- delimiter + noad = getfield(current,"degree") if noad then process(noad,what,n,current) end -- list + elseif id == accent_code then + noad = getnucleus(current) if noad then process(noad,what,n,current) end -- list + noad = getsup (current) if noad then process(noad,what,n,current) end -- list + noad = getsub (current) if noad then process(noad,what,n,current) end -- list + if getsubpre then + noad = getsuppre (current) if noad then process(noad,what,n,current) end -- list + noad = getsubpre (current) if noad then process(noad,what,n,current) end -- list + end + noad = getfield(current,"accent") if noad then process(noad,what,n,current) end -- list + noad = getfield(current,"bot_accent") if noad then process(noad,what,n,current) end -- list + end +end + +local function processstep(current,process,n,id) + local noad = nil + local id = id or getid(current) + if id == noad_code then + noad = getnucleus(current) if noad then process(noad,n,current) end -- list + noad = getsup (current) if noad then process(noad,n,current) end -- list + noad = getsub (current) if noad then process(noad,n,current) end -- list + if getsubpre then + noad = getsuppre (current) if noad then process(noad,n,current) end -- list + noad = getsubpre (current) if noad then process(noad,n,current) end -- list + end + elseif id == subbox_code or id == submlist_code then + noad = getlist(current) if noad then process(noad,n,current) end -- list (not getlist !) + elseif id == fraction_code then + noad = getfield(current,"num") if noad then process(noad,n,current) end -- list + noad = getfield(current,"denom") if noad then process(noad,n,current) end -- list + noad = getfield(current,"left") if noad then process(noad,n,current) end -- delimiter + noad = getfield(current,"right") if noad then process(noad,n,current) end -- delimiter + elseif id == math_choice then + noad = getfield(current,"display") if noad then process(noad,n,current) end -- list + noad = getfield(current,"text") if noad then process(noad,n,current) end -- list + noad = getfield(current,"script") if noad then process(noad,n,current) end -- list + noad = getfield(current,"scriptscript") if noad then process(noad,n,current) end -- list + elseif id == fence_code then + noad = getfield(current,"delimiter") if noad then process(noad,n,current) end -- delimiter + elseif id == radical_code then + noad = getnucleus(current) if noad then process(noad,n,current) end -- list + noad = getsup (current) if noad then process(noad,n,current) end -- list + noad = getsub (current) if noad then process(noad,n,current) end -- list + if getsubpre then + noad = getsuppre (current) if noad then process(noad,n,current) end -- list + noad = getsubpre (current) if noad then process(noad,n,current) end -- list + end + noad = getfield(current,"left") if noad then process(noad,n,current) end -- delimiter + noad = getfield(current,"degree") if noad then process(noad,n,current) end -- list + elseif id == accent_code then + noad = getnucleus(current) if noad then process(noad,n,current) end -- list + noad = getsup (current) if noad then process(noad,n,current) end -- list + noad = getsub (current) if noad then process(noad,n,current) end -- list + if getsubpre then + noad = getsuppre (current) if noad then process(noad,n,current) end -- list + noad = getsubpre (current) if noad then process(noad,n,current) end -- list + end + noad = getfield(current,"accent") if noad then process(noad,n,current) end -- list + noad = getfield(current,"bot_accent") if noad then process(noad,n,current) end -- list + end +end + +local function processnoads(head,actions,banner) + if trace_processing then + report_processing("start %a",banner) + head = process(head,actions) + report_processing("stop %a",banner) + else + head = process(head,actions) + end + return head +end + +noads.process = processnoads +noads.processnested = processnested +noads.processouter = process + +-- experiment (when not present fall back to fam 0) -- needs documentation + +local unknowns = { } +local checked = { } -- simple case +local tracked = false trackers.register("fonts.missing", function(v) tracked = v end) +local cached = setmetatableindex("table") -- complex case + +local function errorchar(font,char) + local done = unknowns[char] + if done then + unknowns[char] = done + 1 + else + unknowns[char] = 1 + end + if tracked then + -- slower as we check each font too and we always replace as math has + -- more demands than text + local fake = cached[font][char] + if fake then + return fake + else + local kind, fake = fonts.checkers.placeholder(font,char) + if not fake or kind ~= "char" then + fake = 0x3F + end + cached[font][char] = fake + return fake + end + else + -- only simple checking, report at the end so one should take + -- action anyway ... we can miss a few checks but that is ok + -- as there is at least one reported + if not checked[char] then + if trace_normalizing then + report_normalizing("character %C is not available",char) + end + checked[char] = true + end + return 0x3F + end +end + +-- 0-2 regular +-- 3-5 bold +-- 6-8 pseudobold + +-- this could best be integrated in the remapper, and if we run into problems, we +-- might as well do this + +do + + local families = { } + local a_mathfamily = privateattribute("mathfamily") + local boldmap = mathematics.boldmap + + local familymap = { [0] = + "regular", + "regular", + "regular", + "bold", + "bold", + "bold", + "pseudobold", + "pseudobold", + "pseudobold", + } + + families[fraction_code] = function(pointer,what,n,parent) + local a = getattr(pointer,a_mathfamily) + if a and a >= 0 then + if a > 0 then + setattr(pointer,a_mathfamily,0) + if a > 5 then + a = a - 3 + end + end + setfam(pointer,a) + end + processnested(pointer,families,n+1) + end + + families[noad_code] = function(pointer,what,n,parent) + local a = getattr(pointer,a_mathfamily) + if a and a >= 0 then + if a > 0 then + setattr(pointer,a_mathfamily,0) + if a > 5 then + a = a - 3 + end + end + setfam(pointer,a) + end + processnested(pointer,families,n+1) + end + + families[mathchar_code] = function(pointer) + if getfam(pointer) == 0 then + local a = getattr(pointer,a_mathfamily) + if a and a > 0 then + setattr(pointer,a_mathfamily,0) + if a > 5 then + local char = getchar(pointer) + local bold = boldmap[char] + local newa = a - 3 + if not bold then + if trace_families then + report_families("no bold replacement for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa]) + end + setfam(pointer,newa) + elseif not fontcharacters[getfontoffamily(newa)][bold] then + if trace_families then + report_families("no bold character for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa]) + end + if newa > 3 then + setfam(pointer,newa-3) + end + else + setattr(pointer,a_exportstatus,char) + setchar(pointer,bold) + if trace_families then + report_families("replacing %C by bold %C, family %s with remap %s becomes %s with remap %s",char,bold,a,familymap[a],newa,familymap[newa]) + end + setfam(pointer,newa) + end + else + local char = getchar(pointer) + if not fontcharacters[getfontoffamily(a)][char] then + if trace_families then + report_families("no bold replacement for %C",char) + end + else + if trace_families then + report_families("family of %C becomes %s with remap %s",char,a,familymap[a]) + end + setfam(pointer,a) + end + end + end + end + end + families[delimiter_code] = function(pointer) + if getfield(pointer,"small_fam") == 0 then + local a = getattr(pointer,a_mathfamily) + if a and a > 0 then + setattr(pointer,a_mathfamily,0) + if a > 5 then + -- no bold delimiters in unicode + a = a - 3 + end + local char = getfield(pointer,"small_char") + local okay = fontcharacters[getfontoffamily(a)][char] + if okay then + setfield(pointer,"small_fam",a) + elseif a > 2 then + setfield(pointer,"small_fam",a-3) + end + local char = getfield(pointer,"large_char") + local okay = fontcharacters[getfontoffamily(a)][char] + if okay then + setfield(pointer,"large_fam",a) + elseif a > 2 then + setfield(pointer,"large_fam",a-3) + end + else + setfield(pointer,"small_fam",0) + setfield(pointer,"large_fam",0) + end + end + end + + -- will become: + + -- families[delimiter_code] = function(pointer) + -- if getfam(pointer) == 0 then + -- local a = getattr(pointer,a_mathfamily) + -- if a and a > 0 then + -- setattr(pointer,a_mathfamily,0) + -- if a > 5 then + -- -- no bold delimiters in unicode + -- a = a - 3 + -- end + -- local char = getchar(pointer) + -- local okay = fontcharacters[getfontoffamily(a)][char] + -- if okay then + -- setfam(pointer,a) + -- elseif a > 2 then + -- setfam(pointer,a-3) + -- end + -- else + -- setfam(pointer,0) + -- end + -- end + -- end + + families[mathtextchar_code] = families[mathchar_code] + + function handlers.families(head,style,penalties) + processnoads(head,families,"families") + return true -- not needed + end + +end + +-- character remapping + +do + + local a_mathalphabet = privateattribute("mathalphabet") + local a_mathgreek = privateattribute("mathgreek") + + local relocate = { } + + local remapalphabets = mathematics.remapalphabets + local fallbackstyleattr = mathematics.fallbackstyleattr + local setnodecolor = colortracers.set + + local function report_remap(tag,id,old,new,extra) + report_remapping("remapping %s in font (%s,%s) from %C to %C%s", + tag,id,fontdata[id].properties.fontname or "",old,new,extra) + end + + local function checked(pointer) + local char = getchar(pointer) + local font = getfont(pointer) + local data = fontcharacters[font] + if not data[char] then + local specials = characters.data[char].specials + if specials and (specials[1] == "char" or specials[1] == "font") then + local newchar = specials[#specials] + if trace_remapping then + report_remap("fallback",font,char,newchar) + end + if trace_analyzing then + setnodecolor(pointer,"font:isol") + end + setattr(pointer,a_exportstatus,char) -- testcase: exponentiale + setchar(pointer,newchar) + return true + end + end + end + + -- We can optimize this if we really think that math is a bottleneck which it never + -- really is. + + relocate[mathchar_code] = function(pointer) + local g = getattr(pointer,a_mathgreek) or 0 + local a = getattr(pointer,a_mathalphabet) or 0 + -- local g, a = getattrs(pointer,a_mathgreek,a_mathalphabet) + -- if not a then a = 0 end + -- if not g then g = 0 end + local char = getchar(pointer) + local font = getfont(pointer) + local characters = fontcharacters[font] + if a > 0 or g > 0 then + if a > 0 then + -- not really critital but we could use properties + setattr(pointer,a_mathgreek,0) + end + if g > 0 then + -- not really critital but we could use properties + setattr(pointer,a_mathalphabet,0) + end + local newchar = remapalphabets(char,a,g) + if newchar then + local newchardata = characters[newchar] + if newchardata then + if trace_remapping then + report_remap("char",font,char,newchar,newchardata.commands and " (virtual)" or "") + end + if trace_analyzing then + setnodecolor(pointer,"font:isol") + end + setchar(pointer,newchar) + return true + else + local fallback = fallbackstyleattr(a) + if fallback then + local newchar = remapalphabets(char,fallback,g) + if newchar then + if characters[newchar] then + if trace_remapping then + report_remap("char",font,char,newchar," (fallback remapping used)") + end + if trace_analyzing then + setnodecolor(pointer,"font:isol") + end + setchar(pointer,newchar) + return true + elseif trace_remapping then + report_remap("char",font,char,newchar," fails (no fallback character)") + end + elseif trace_remapping then + report_remap("char",font,char,newchar," fails (no fallback remap character)") + end + elseif trace_remapping then + report_remap("char",font,char,newchar," fails (no fallback style)") + end + end + elseif trace_remapping then + local chardata = characters[char] + if chardata and chardata.commands then + report_remap("char",font,char,char," (virtual)") + end + end + end + if not characters[char] then + setchar(pointer,errorchar(font,char)) + end + if trace_analyzing then + setnodecolor(pointer,"font:medi") + end + if check_coverage then + return checked(pointer) + end + end + + relocate[mathtextchar_code] = function(pointer) + if trace_analyzing then + setnodecolor(pointer,"font:init") + end + end + + relocate[delimiter_code] = function(pointer) + if trace_analyzing then + setnodecolor(pointer,"font:fina") + end + end + + function handlers.relocate(head,style,penalties) + processnoads(head,relocate,"relocate") + return true -- not needed + end + +end + +-- rendering (beware, not exported) + +do + + local render = { } + + local rendersets = mathematics.renderings.numbers or { } -- store + + render[mathchar_code] = function(pointer) + local attr = getattr(pointer,a_mathrendering) + if attr and attr > 0 then + local char = getchar(pointer) + local renderset = rendersets[attr] + if renderset then + local newchar = renderset[char] + if newchar then + local font = getfont(pointer) + local characters = fontcharacters[font] + if characters and characters[newchar] then + setchar(pointer,newchar) + setattr(pointer,a_exportstatus,char) + end + end + end + end + end + + function handlers.render(head,style,penalties) + processnoads(head,render,"render") + return true -- not needed + end + +end + +-- some resize options (this works ok because the content is +-- empty and no larger next will be forced) +-- +-- beware: we don't use \delcode but \Udelcode and as such have +-- no large_fam; also, we need to check for subtype and/or +-- small_fam not being 0 because \. sits in 0,0 by default +-- +-- todo: just replace the character by an ord noad +-- and remove the right delimiter as well + +do + + local a_mathsize = privateattribute("mathsize") -- this might move into other fence code + local resize = { } + + resize[fence_code] = function(pointer) + local subtype = getsubtype(pointer) + if subtype == leftfence_code or subtype == rightfence_code then + local a = getattr(pointer,a_mathsize) + if a and a > 0 then + local method = div(a,100) + local size = a % 100 + setattr(pointer,a_mathsize,0) + local delimiter = getfield(pointer,"delimiter") + local chr = getchar(delimiter) + if chr > 0 then + local fam = getfam(delimiter) + local id = getfontoffamily(fam) + if id > 0 then + local data = fontdata[id] + local char = mathematics.big(data,chr,size,method) + local ht = getheight(pointer) + local dp = getdepth(pointer) + if ht == 1 or dp == 1 then -- 1 scaled point is a signal + local chardata = data.characters[char] + if ht == 1 then + setheight(pointer,chardata.height) + end + if dp == 1 then + setdepth(pointer,chardata.depth) + end + end + if trace_fences then + report_fences("replacing %C by %C using method %a and size %a",chr,char,method,size) + end + setchar(delimiter,char) + end + end + end + end + end + + function handlers.resize(head,style,penalties) + processnoads(head,resize,"resize") + return true -- not needed + end + +end + +-- still not perfect: + +do + + local a_autofence = privateattribute("mathautofence") + local autofences = { } + local dummyfencechar = 0x2E + + local function makefence(what,char) + local d = new_delimiter() -- todo: attr + local f = new_fence() -- todo: attr + if char then + local sym = getnucleus(char) + local chr = getchar(sym) + local fam = getfam(sym) + if chr == dummyfencechar then + chr = 0 + end + setchar(d,chr) + setfam(d,fam) + flush_node(sym) + end + setattrlist(d,char) + setattrlist(f,char) + setsubtype(f,what) + setfield(f,"delimiter",d) + setfield(f,"class",-1) -- tex itself does this, so not fenceclasses[what] + return f + end + + local function show(where,pointer) + print("") + local i = 0 + for n in nuts.traverse(pointer) do + i = i + 1 + print(i,where,nuts.tonode(n)) + end + print("") + end + + local function makelist(middle,noad,f_o,o_next,c_prev,f_c) +-- report_fences( +-- "middle %s, noad %s, open %s, opennext %s, closeprev %s, close %s", +-- middle or "?", +-- noad or "?", +-- f_o or "?", +-- o_next or "?", +-- c_prev or "?", +-- f_c or "?" +-- ) + local list = new_submlist() + setsubtype(noad,innernoad_code) + setnucleus(noad,list) + setlist(list,f_o) + setlink(f_o,o_next) -- prev of list is nil + setlink(c_prev,f_c) -- next of list is nil +-- show("list",f_o) + if middle and next(middle) then + local prev = f_o + local current = o_next + while current ~= f_c do + local midl = middle[current] + local next = getnext(current) + if midl then + local fence = makefence(middlefence_code,current) + setnucleus(current) + flush_node(current) + middle[current] = nil + -- replace_node + setlink(prev,fence,next) + prev = fence + else + prev = current + end + current = next + end + end + return noad + end + + -- relinking is now somewhat overdone + + local function convert_both(open,close,middle) + local o_next = getnext(open) + if o_next == close then + return close + else + local c_prev, c_next = getboth(close) + local f_o = makefence(leftfence_code,open) + local f_c = makefence(rightfence_code,close) + makelist(middle,open,f_o,o_next,c_prev,f_c) + setnucleus(close) + flush_node(close) + -- open is now a list + setlink(open,c_next) + return open + end + end + + local function convert_open(open,last,middle) -- last is really last (final case) + local f_o = makefence(leftfence_code,open) + local f_c = makefence(rightfence_code) + local o_next = getnext(open) + makelist(middle,open,f_o,o_next,last,nil) + -- open is now a list + setlink(open,l_next) + return open + end + + local function convert_close(first,close,middle) + local f_o = makefence(leftfence_code) + local f_c = makefence(rightfence_code,close) + local c_prev = getprev(close) + local f_next = getnext(first) + makelist(middle, close, f_o,f_next,c_prev,f_c) + -- close is now a list + if c_prev ~= first then + setlink(first,close) + end + return close + end + + local stacks = setmetatableindex("table") + + -- 1=open 2=close 3=middle 4=both + + local function processfences(pointer,n,parent) + local current = pointer + local last = pointer + local start = pointer + local done = false + local initial = pointer + local stack = nil + local middle = nil -- todo: use properties + while current do +-- show("before",pointer) + local id = getid(current) + if id == noad_code then + local a = getattr(current,a_autofence) + if a and a > 0 then + local stack = stacks[n] + setattr(current,a_autofence,0) -- hm, better use a property + local level = #stack + if a == 1 then + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"open","open") + end + insert(stack,current) + elseif a == 2 then + local open = remove(stack) + if open then + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"close","both") + end + current = convert_both(open,current,middle) + elseif current == start then + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"close","skip") + end + else + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"close","close") + end + current = convert_close(initial,current,middle) + if not parent then + initial = current + end + end + elseif a == 3 then + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"middle","middle") + end + if middle then + middle[current] = last + else + middle = { [current] = last } + end + elseif a == 4 then + if not stack or #stack == 0 then + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"both","open") + end + insert(stack,current) + else + local open = remove(stack) + if open then + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"both","both") + end + current = convert_both(open,current,middle) + elseif current == start then + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"both","skip") + end + else + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,level,"both","close") + end + current = convert_close(initial,current,middle) + if not parent then + initial = current + end + end + end + end + done = true + else + processstep(current,processfences,n+1,id) + end + else + -- next at current level + processstep(current,processfences,n,id) + end +-- show("after",pointer) + last = current + current = getnext(current) + end + if done then + local stack = stacks[n] + local s = #stack + if s > 0 then + for i=1,s do + local open = remove(stack) + if trace_fences then + report_fences("%2i: level %i, handling %s, action %s",n,#stack,"flush","open") + end + last = convert_open(open,last,middle) + end +-- show("done",pointer) + end + end + end + + -- we can have a first changed node .. an option is to have a leading dummy node in math + -- lists like the par node as it can save a lot of mess + + local enabled = false + + implement { + name = "enableautofences", + onlyonce = true, + actions = function() + enableaction("math","noads.handlers.autofences") + enabled = true + end + } + + function handlers.autofences(head,style,penalties) + if enabled then -- tex.modes.c_math_fences_auto + -- inspect(nodes.totree(head)) + processfences(head,1) + -- inspect(nodes.totree(head)) + end + end + +end + +-- normalize scripts + +do + + local unscript = { } noads.processors.unscript = unscript + local superscripts = characters.superscripts + local subscripts = characters.subscripts + local fractions = characters.fractions + local replaced = { } + + local function replace(pointer,what,n,parent) + pointer = parent -- we're following the parent list (chars trigger this) + local next = getnext(pointer) + local start_super, stop_super, start_sub, stop_sub + local mode = "unset" + while next and getid(next) == noad_code do + local nextnucleus = getnucleus(next) + if nextnucleus and getid(nextnucleus) == mathchar_code and not getsub(next) and not getsup(next) then + local char = getchar(nextnucleus) + local s = superscripts[char] + if s then + if not start_super then + start_super = next + mode = "super" + elseif mode == "sub" then + break + end + stop_super = next + next = getnext(next) + setchar(nextnucleus,s) + replaced[char] = (replaced[char] or 0) + 1 + if trace_normalizing then + report_normalizing("superscript %C becomes %C",char,s) + end + else + local s = subscripts[char] + if s then + if not start_sub then + start_sub = next + mode = "sub" + elseif mode == "super" then + break + end + stop_sub = next + next = getnext(next) + setchar(nextnucleus,s) + replaced[char] = (replaced[char] or 0) + 1 + if trace_normalizing then + report_normalizing("subscript %C becomes %C",char,s) + end + else + break + end + end + else + break + end + end + if start_super then + if start_super == stop_super then + setsup(pointer,getnucleus(start_super)) + else + local list = new_submlist() -- todo attr + setlist(list,start_super) + setsup(pointer,list) + end + if mode == "super" then + setnext(pointer,getnext(stop_super)) + end + setnext(stop_super) + end + if start_sub then + +-- if mode == "sub" then +-- local sup = getsup(pointer) +-- if sup and not getsub(pointer) then +-- local nxt = getnext(pointer) +-- local new = new_noad(pointer) +-- setnucleus(new,new_submlist()) +-- setlink(pointer,new,nxt) +-- pointer = new +-- end +-- end + + if start_sub == stop_sub then + setsub(pointer,getnucleus(start_sub)) + else + local list = new_submlist() -- todo attr + setlist(list,start_sub) + setsub(pointer,list) + end + if mode == "sub" then + setnext(pointer,getnext(stop_sub)) + end + setnext(stop_sub) + end + -- we could return stop + end + + unscript[mathchar_code] = replace -- not noads as we need to recurse + + function handlers.unscript(head,style,penalties) + processnoads(head,unscript,"unscript") + return true -- not needed + end + +end + +do + + local unstack = { } noads.processors.unstack = unstack + local enabled = false + local a_unstack = privateattribute("mathunstack") + + unstack[noad_code] = function(pointer) + if getattr(pointer,a_unstack) then + local sup = getsup(pointer) + local sub = getsub(pointer) + if sup and sub then + -- if trace_unstacking then + -- report_unstacking() -- todo ... what to show ... + -- end + local nxt = getnext(pointer) + local new = new_noad(pointer) + setnucleus(new,new_submlist()) + setsub(pointer) + setsub(new,sub) + setlink(pointer,new,nxt) + end + end + end + + function handlers.unstack(head,style,penalties) + if enabled then + processnoads(head,unstack,"unstack") + return true -- not needed + end + end + + implement { + name = "enablescriptunstacking", + onlyonce = true, + actions = function() + enableaction("math","noads.handlers.unstack") + enabled = true + end + } + +end + +do + + local function collected(list) + if list and next(list) then + local n, t = 0, { } + for k, v in sortedhash(list) do + n = n + 1 + t[n] = formatters["%C"](k) + end + return formatters["% t (n=%s)"](t,n) + end + end + + statistics.register("math script replacements", function() + return collected(replaced) + end) + + statistics.register("unknown math characters", function() + return collected(unknowns) + end) + +end + +-- math alternates: (in xits lgf: $ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$) +-- math alternates: (in lucidaot lgf: $ABC \mathalternate{italic} ABC$) + +-- todo: set alternate for specific symbols +-- todo: no need to do this when already loaded +-- todo: use a fonts.hashes.mathalternates + +do + + local last = 0 + + local known = setmetatableindex(function(t,k) + local v = bor(0,2^last) + t[k] = v + last = last + 1 + return v + end) + + local defaults = { + dotless = { feature = 'dtls', value = 1, comment = "Mathematical Dotless Forms" }, + -- zero = { feature = 'zero', value = 1, comment = "Slashed or Dotted Zero" }, -- in no math font (yet) + } + + local function initializemathalternates(tfmdata) + local goodies = tfmdata.goodies + local autolist = defaults -- table.copy(defaults) + + local function setthem(newalternates) + local resources = tfmdata.resources -- was tfmdata.shared + local mathalternates = resources.mathalternates + local alternates, attributes, registered, presets + if mathalternates then + alternates = mathalternates.alternates + attributes = mathalternates.attributes + registered = mathalternates.registered + else + alternates, attributes, registered = { }, { }, { } + mathalternates = { + attributes = attributes, + alternates = alternates, + registered = registered, + presets = { }, + resets = { }, + hashes = setmetatableindex("table") + } + resources.mathalternates = mathalternates + end + -- + for name, data in sortedhash(newalternates) do + if alternates[name] then + -- ignore + else + local attr = known[name] + attributes[attr] = data + alternates[name] = attr + registered[#registered+1] = attr + end + end + end + + if goodies then + local done = { } + for i=1,#goodies do + -- first one counts + -- we can consider sharing the attributes ... todo (only once scan) + local mathgoodies = goodies[i].mathematics + local alternates = mathgoodies and mathgoodies.alternates + if alternates then + if trace_goodies then + report_goodies("loading alternates for font %a",tfmdata.properties.name) + end + for k, v in next, autolist do + if not alternates[k] then + alternates[k] = v + end + end + setthem(alternates) + return + end + end + end + + if trace_goodies then + report_goodies("loading default alternates for font %a",tfmdata.properties.name) + end + setthem(autolist) + + end + + registerotffeature { + name = "mathalternates", + description = "additional math alternative shapes", + initializers = { + base = initializemathalternates, + node = initializemathalternates, + } + } + + -- local getalternate = otf.getalternate (runtime new method so ...) + + -- todo: not shared but copies ... one never knows + + local a_mathalternate = privateattribute("mathalternate") + local alternate = { } -- processors.alternate = alternate + local fontdata = fonts.hashes.identifiers + local fontresources = fonts.hashes.resources + + local function getalternate(fam,tag,current) + local resources = fontresources[getfontoffamily(fam)] + local attribute = unsetvalue + if resources then + local mathalternates = resources.mathalternates + if mathalternates then + local presets = mathalternates.presets + if presets then + local resets = mathalternates.resets + attribute = presets[tag] + if not attribute then + attribute = 0 + local alternates = mathalternates.alternates + for s in gmatch(tag,"[^, ]+") do + if s == v_reset then + resets[tag] = true + current = unsetvalue + else + local a = alternates[s] -- or known[s] + if a then + attribute = bor(attribute,a) + end + end + end + if attribute == 0 then + attribute = unsetvalue + end + presets[tag] = attribute + elseif resets[tag] then + current = unsetvalue + end + end + end + end + if attribute > 0 and current and current > 0 then + return bor(current,attribute) + else + return attribute + end + end + + local function presetalternate(fam,tag) + texsetattribute(a_mathalternate,getalternate(fam,tag)) + end + + implement { + name = "presetmathalternate", + actions = presetalternate, + arguments = { "integer", "string" } + } + + local function setalternate(fam,tag) + local a = texgetattribute(a_mathalternate) + local v = getalternate(fam,tag,a) + texsetattribute(a_mathalternate,v) + end + + implement { + name = "setmathalternate", + actions = setalternate, + arguments = { "integer", "string" } + } + + alternate[mathchar_code] = function(pointer) -- slow + local a = getattr(pointer,a_mathalternate) + if a and a > 0 then + setattr(pointer,a_mathalternate,0) + local fontid = getfont(pointer) + local resources = fontresources[fontid] + if resources then + local mathalternates = resources.mathalternates + if mathalternates then + local attributes = mathalternates.attributes + local registered = mathalternates.registered + local hashes = mathalternates.hashes + for i=1,#registered do + local r = registered[i] + if band(a,r) ~= 0 then + local char = getchar(pointer) + local alt = hashes[i][char] + if alt == nil then + local what = attributes[r] + alt = otf.getalternate(fontdata[fontid],char,what.feature,what.value) or false + if alt == char then + alt = false + end + hashes[i][char] = alt + end + if alt then + if trace_alternates then + local what = attributes[r] + report_alternates("alternate %a, value %a, replacing glyph %U by glyph %U", + tostring(what.feature),tostring(what.value),getchar(pointer),alt) + end + setchar(pointer,alt) + break + end + end + end + end + end + end + end + + function handlers.alternates(head,style,penalties) + processnoads(head,alternate,"alternate") + return true -- not needed + end + +end + +-- italics: we assume that only characters matter +-- +-- = we check for correction first because accessing nodes is slower +-- = the actual glyph is not that important (we can control it with numbers) + +-- Italic correction in luatex math is (was) a mess. There are all kind of assumptions based on +-- old fonts and new fonts. Eventually there should be a flag that can signal to ignore all +-- those heuristics. We want to deal with it ourselves also in the perspective of mixed math +-- and text. Also, for a while in context we had to deal with a mix of virtual math fonts and +-- real ones. + +-- in opentype the italic correction of a limop is added to the width and luatex does +-- some juggling that we want to avoid but we need to do something here (in fact, we could +-- better fix the width of the character) + +do + + local a_mathitalics = privateattribute("mathitalics") + + local italics = { } + local default_factor = 1/20 + + local setcolor = colortracers.set + local resetcolor = colortracers.reset + local italic_kern = new_kern + + local c_positive_d = "trace:dg" + local c_negative_d = "trace:dr" + + local function insert_kern(current,kern) + local sub = new_submlist() -- todo: attr + local noad = new_noad() -- todo: attr + setlist(sub,kern) + setnext(kern,noad) + setnucleus(noad,current) + return sub + end + + registertracker("math.italics.visualize", function(v) + if v then + italic_kern = function(k) + local n = new_kern(k) -- todo: attr + set_visual(n,"italic") + return n + end + else + italic_kern = new_kern + end + end) + + local function getcorrection(method,font,char) -- -- or character.italic -- (this one is for tex) + + local visual = chardata[char].visual + + if method == 1 then + -- check on state + local italics = fontitalics[font] + if italics then + local character = fontcharacters[font][char] + if character then + local correction = character.italic + if correction and correction ~= 0 then + return correction, visual + end + end + end + elseif method == 2 then + -- no check + local character = fontcharacters[font][char] + if character then + local correction = character.italic + if correction and correction ~= 0 then + return correction, visual + end + end + elseif method == 3 then + -- check on visual + if visual == "it" or visual == "bi" then + local character = fontcharacters[font][char] + if character then + local correction = character.italic + if correction and correction ~= 0 then + return correction, visual + end + end + end + elseif method == 4 then + -- combination of 1 and 3 + local italics = fontitalics[font] + if italics and (visual == "it" or visual == "bi") then + local character = fontcharacters[font][char] + if character then + local correction = character.italic + if correction and correction ~= 0 then + return correction, visual + end + end + end + end + + end + + italics[mathchar_code] = function(pointer,what,n,parent) + local method = getattr(pointer,a_mathitalics) + if method and method > 0 and method < 100 then + local char = getchar(pointer) + local font = getfont(pointer) + local correction, visual = getcorrection(method,font,char) + if correction and correction ~= 0 then + local next_noad = getnext(parent) + if not next_noad then + if n == 1 then + -- only at the outer level .. will become an option (always,endonly,none) + if trace_italics then + report_italics("method %a, flagging italic correction %p between %C and end math",method,correction,char) + end + if correction > 0 then + correction = correction + 100 + else + correction = correction - 100 + end + correction = round(correction) + setattr(pointer,a_mathitalics,correction) + setattr(parent,a_mathitalics,correction) + return -- so no reset later on + end + end + end + end + setattr(pointer,a_mathitalics,unsetvalue) + end + + function handlers.italics(head,style,penalties) + processnoads(head,italics,"italics") + return true -- not needed + end + + local enable = function() + enableaction("math", "noads.handlers.italics") + if trace_italics then + report_italics("enabling math italics") + end + -- we enable math (unless already enabled elsewhere) + typesetters.italics.enablemath() + enable = false + end + + -- best do this only on math mode (less overhead) + + function mathematics.setitalics(name) + if enable then + enable() + end + texsetattribute(a_mathitalics,name and name ~= v_reset and tonumber(name) or unsetvalue) -- maybe also v_none + end + + function mathematics.getitalics(name) + if enable then + enable() + end + context(name and name ~= v_reset and tonumber(name) or unsetvalue) + end + + function mathematics.resetitalics() + texsetattribute(a_mathitalics,unsetvalue) + end + + implement { + name = "initializemathitalics", + actions = enable, + onlyonce = true, + } + + implement { + name = "setmathitalics", + actions = mathematics.setitalics, + arguments = "string", + } + + implement { + name = "getmathitalics", + actions = mathematics.getitalics, + arguments = "string", + } + + implement { + name = "resetmathitalics", + actions = mathematics.resetitalics + } + +end + +do + + -- math kerns (experiment) in goodies: + -- + -- mathematics = { + -- kernpairs = { + -- [0x1D44E] = { + -- [0x1D44F] = 400, -- 𝑎𝑏 + -- } + -- }, + -- } + + local a_kernpairs = privateattribute("mathkernpairs") + local kernpairs = { } + + local function enable() + enableaction("math", "noads.handlers.kernpairs") + if trace_kernpairs then + report_kernpairs("enabling math kern pairs") + end + enable = false + end + + implement { + name = "initializemathkernpairs", + actions = enable, + onlyonce = true, + } + + local hash = setmetatableindex(function(t,font) + local g = fontdata[font].goodies + local m = g and g[1] and g[1].mathematics + local k = m and m.kernpairs + t[font] = k + return k + end) + + -- no correction after prime because that moved to a superscript + + kernpairs[mathchar_code] = function(pointer,what,n,parent) + if getattr(pointer,a_kernpairs) == 1 then + local font = getfont(pointer) + local list = hash[font] + if list then + local first = getchar(pointer) + local found = list[first] + if found then + local next = getnext(parent) + if next and getid(next) == noad_code then + pointer = getnucleus(next) + if pointer then + if getfont(pointer) == font then + local second = getchar(pointer) + local kern = found[second] + if kern then + kern = kern * fonts.hashes.parameters[font].hfactor + if trace_kernpairs then + report_kernpairs("adding %p kerning between %C and %C",kern,first,second) + end + setlink(parent,new_kern(kern),getnext(parent)) -- todo: attr + end + end + end + end + end + end + end + end + + function handlers.kernpairs(head,style,penalties) + processnoads(head,kernpairs,"kernpairs") + return true -- not needed + end + +end + +-- primes and such + +do + + -- is validpair stil needed? + + local a_mathcollapsing = privateattribute("mathcollapsing") + local collapse = { } + local mathlists = characters.mathlists + local validpair = { + [ordnoad_code] = true, + [opdisplaylimitsnoad_code] = true, + [oplimitsnoad_code] = true, + [opnolimitsnoad_code] = true, + [binnoad_code] = true, -- new + [relnode_code] = true, + [opennoad_code] = true, -- new + [closenoad_code] = true, -- new + [punctnoad_code] = true, -- new + [innernoad_code] = false, + [undernoad_code] = false, + [overnoad_code] = false, + [vcenternoad_code] = false, + [ordlimitsnoad_code] = true, + } + + local reported = setmetatableindex("table") + + collapse[mathchar_code] = function(pointer,what,n,parent) + + if parent and mathlists[getchar(pointer)] then + local found, last, lucleus, lsup, lsub, category + local tree = mathlists + local current = parent + while current and validpair[getsubtype(current)] do + local nucleus = getnucleus(current) -- == pointer + local sub = getsub(current) + local sup = getsup(current) + local char = getchar(nucleus) + if char then + local match = tree[char] + if match then + local method = getattr(current,a_mathcollapsing) + if method and method > 0 and method <= 3 then + local specials = match.specials + local mathlist = match.mathlist + local ligature + if method == 1 then + ligature = specials + elseif method == 2 then + ligature = specials or mathlist + else -- 3 + ligature = mathlist or specials + end + if ligature then + category = mathlist and "mathlist" or "specials" + found = ligature + last = current + lucleus = nucleus + lsup = sup + lsub = sub + end + tree = match + if sub or sup then + break + else + current = getnext(current) + end + else + break + end + else + break + end + else + break + end + end + if found and last and lucleus then + local id = getfont(lucleus) + local characters = fontcharacters[id] + local replace = characters and characters[found] + if not replace then + if not reported[id][found] then + reported[id][found] = true + report_collapsing("%s ligature %C from %s","ignoring",found,category) + end + elseif trace_collapsing then + report_collapsing("%s ligature %C from %s","creating",found,category) + end + setchar(pointer,found) + local l = getnext(last) + local c = getnext(parent) + if lsub then + setsub(parent,lsub) + setsub(last) + end + if lsup then + setsup(parent,lsup) + setsup(last) + end + while c ~= l do + local n = getnext(c) + flush_node(c) + c = n + end + setlink(parent,l) + end + end + end + + function noads.handlers.collapse(head,style,penalties) + processnoads(head,collapse,"collapse") + return true -- not needed + end + + local enable = function() + enableaction("math", "noads.handlers.collapse") + if trace_collapsing then + report_collapsing("enabling math collapsing") + end + enable = false + end + + implement { + name = "initializemathcollapsing", + actions = enable, + onlyonce = true, + } + +end + +do + -- inner under over vcenter + + local fixscripts = { } + local movesub = { + -- primes + [0x2032] = 0xFE932, + [0x2033] = 0xFE933, + [0x2034] = 0xFE934, + [0x2057] = 0xFE957, + -- reverse primes + [0x2035] = 0xFE935, + [0x2036] = 0xFE936, + [0x2037] = 0xFE937, + } + + mathematics.virtualize(movesub) + + local options_supported = tokens.defined("Unosuperscript") + + local function fixsupscript(parent,current,current_char,new_char) + if new_char ~= current_char and new_char ~= true then + setchar(current,new_char) + if trace_fixing then + report_fixing("fixing subscript, replacing superscript %U by %U",current_char,new_char) + end + else + if trace_fixing then + report_fixing("fixing subscript, superscript %U",current_char) + end + end + if options_supported then + setfield(parent,"options",0x08+0x22) + end + end + + -- local function movesubscript(parent,current_nucleus,oldchar,newchar) + -- local prev = getprev(parent) + -- if prev and getid(prev) == noad_code then + -- local psup = getsup(prev) + -- local psub = getsub(prev) + -- if not psup and not psub then + -- fixsupscript(prev,current_nucleus,oldchar,newchar) + -- local nucleus = getnucleus(parent) + -- local sub = getsub(parent) + -- setsup(prev,nucleus) + -- setsub(prev,sub) + -- local dummy = copy_node(nucleus) + -- setchar(dummy,0) + -- setnucleus(parent,dummy) + -- setsub(parent) + -- elseif not psup then + -- fixsupscript(prev,current_nucleus,oldchar,newchar) + -- local nucleus = getnucleus(parent) + -- setsup(prev,nucleus) + -- local dummy = copy_node(nucleus) + -- setchar(dummy,0) + -- setnucleus(parent,dummy) + -- end + -- end + -- end + + local function move_none_none(parent,prev,nuc,oldchar,newchar) + fixsupscript(prev,nuc,oldchar,newchar) + local sub = getsub(parent) + setsup(prev,nuc) + setsub(prev,sub) + local dummy = copy_node(nuc) + setchar(dummy,0) + setnucleus(parent,dummy) + setsub(parent) + end + + local function move_none_psub(parent,prev,nuc,oldchar,newchar) + fixsupscript(prev,nuc,oldchar,newchar) + setsup(prev,nuc) + local dummy = copy_node(nuc) + setchar(dummy,0) + setnucleus(parent,dummy) + end + + fixscripts[mathchar_code] = function(pointer,what,n,parent,nested) -- todo: switch to turn in on and off + if parent then + local oldchar = getchar(pointer) + local newchar = movesub[oldchar] + if newchar then + local nuc = getnucleus(parent) + if pointer == nuc then + local sub = getsub(pointer) + local sup = getsup(pointer) + if sub then + if sup then + -- print("[char] sub sup") + else + -- print("[char] sub ---") + end + elseif sup then + -- print("[char] --- sup") + else + local prev = getprev(parent) + if prev and getid(prev) == noad_code then + local psub = getsub(prev) + local psup = getsup(prev) + if psub then + if psup then + -- print("sub sup [char] --- ---") + else + -- print("sub --- [char] --- ---") + move_none_psub(parent,prev,nuc,oldchar,newchar) + end + elseif psup then + -- print("--- sup [char] --- ---") + else + -- print("[char] --- ---") + move_none_none(parent,prev,nuc,oldchar,newchar) + end + else + -- print("no prev [char]") + end + end + else + -- print("[char]") + end + end + end + end + + function noads.handlers.fixscripts(head,style,penalties) + processnoads(head,fixscripts,"fixscripts") + return true -- not needed + end + +end + +-- variants + +do + + local variants = { } + local validvariants = { -- fast check on valid + [0x2229] = 0xFE00, [0x222A] = 0xFE00, + [0x2268] = 0xFE00, [0x2269] = 0xFE00, + [0x2272] = 0xFE00, [0x2273] = 0xFE00, + [0x228A] = 0xFE00, [0x228B] = 0xFE00, + [0x2293] = 0xFE00, [0x2294] = 0xFE00, + [0x2295] = 0xFE00, + [0x2297] = 0xFE00, + [0x229C] = 0xFE00, + [0x22DA] = 0xFE00, [0x22DB] = 0xFE00, + [0x2A3C] = 0xFE00, [0x2A3D] = 0xFE00, + [0x2A9D] = 0xFE00, [0x2A9E] = 0xFE00, + [0x2AAC] = 0xFE00, [0x2AAD] = 0xFE00, + [0x2ACB] = 0xFE00, [0x2ACC] = 0xFE00, + } + + variants[mathchar_code] = function(pointer,what,n,parent) -- also set export value + local char = getchar(pointer) + local selector = validvariants[char] + if selector then + local next = getnext(parent) + if next and getid(next) == noad_code then + local nucleus = getnucleus(next) + if nucleus and getid(nucleus) == mathchar_code and getchar(nucleus) == selector then + local variant + local tfmdata = fontdata[getfont(pointer)] + local mathvariants = tfmdata.resources.variants -- and variantdata + if mathvariants then + mathvariants = mathvariants[selector] + if mathvariants then + variant = mathvariants[char] + end + end + if variant then + setchar(pointer,variant) + setattr(pointer,a_exportstatus,char) -- we don't export the variant as it's visual markup + if trace_variants then + report_variants("variant (%U,%U) replaced by %U",char,selector,variant) + end + else + if trace_variants then + report_variants("no variant (%U,%U)",char,selector) + end + end + setprev(next,pointer) + setnext(parent,getnext(next)) + flush_node(next) + end + end + end + end + + function handlers.variants(head,style,penalties) + processnoads(head,variants,"unicode variant") + return true -- not needed + end + +end + +-- for manuals + +do + + local classes = { } + local colors = { + [relnode_code] = "trace:dr", + [ordnoad_code] = "trace:db", + [binnoad_code] = "trace:dg", + [opennoad_code] = "trace:dm", + [closenoad_code] = "trace:dm", + [punctnoad_code] = "trace:dc", + -- [opdisplaylimitsnoad_code] = "", + -- [oplimitsnoad_code] = "", + -- [opnolimitsnoad_code] = "", + -- [ordlimitsnoad_code] = "", + -- [innernoad_code = "", + -- [undernoad_code] = "", + -- [overnoad_code] = "", + -- [vcenternoad_code] = "", + } + + local setcolor = colortracers.set + local resetcolor = colortracers.reset + + classes[mathchar_code] = function(pointer,what,n,parent) + local color = colors[getsubtype(parent)] + if color then + setcolor(pointer,color) + else + resetcolor(pointer) + end + end + + function handlers.classes(head,style,penalties) + processnoads(head,classes,"classes") + return true -- not needed + end + + registertracker("math.classes",function(v) + setaction("math","noads.handlers.classes",v) + end) + +end + +-- experimental + +do + + -- mathematics.registerdomain { + -- name = "foo", + -- parents = { "bar" }, + -- characters = { + -- [0x123] = { char = 0x234, class = binary }, + -- }, + -- } + + local domains = { } + local categories = { } + local numbers = { } + local a_mathdomain = privateattribute("mathdomain") + mathematics.domains = categories + local permitted = { + ordinary = ordnoad_code, + binary = binnoad_code, + relation = relnode_code, + punctuation = punctnoad_code, + inner = innernoad_code, + } + + function mathematics.registerdomain(data) + local name = data.name + if not name then + return + end + local attr = #numbers + 1 + categories[name] = data + numbers[attr] = data + data.attribute = attr + -- we delay hashing + return attr + end + + local enable + + enable = function() + enableaction("math", "noads.handlers.domains") + if trace_domains then + report_domains("enabling math domains") + end + enable = false + end + + function mathematics.setdomain(name) + if enable then + enable() + end + local data = name and name ~= v_reset and categories[name] + texsetattribute(a_mathdomain,data and data.attribute or unsetvalue) + end + + function mathematics.getdomain(name) + if enable then + enable() + end + local data = name and name ~= v_reset and categories[name] + context(data and data.attribute or unsetvalue) + end + + implement { + name = "initializemathdomain", + actions = enable, + onlyonce = true, + } + + implement { + name = "setmathdomain", + arguments = "string", + actions = mathematics.setdomain, + } + + implement { + name = "getmathdomain", + arguments = "string", + actions = mathematics.getdomain, + } + + local function makehash(data) + local hash = { } + local parents = data.parents + if parents then + local function merge(name) + if name then + local c = categories[name] + if c then + local hash = c.hash + if not hash then + hash = makehash(c) + end + for k, v in next, hash do + hash[k] = v + end + end + end + end + if type(parents) == "string" then + merge(parents) + elseif type(parents) == "table" then + for i=1,#parents do + merge(parents[i]) + end + end + end + local characters = data.characters + if characters then + for k, v in next, characters do + -- local chr = n.char + local cls = v.class + if cls then + v.code = permitted[cls] + else + -- invalid class + end + hash[k] = v + end + end + data.hash = hash + return hash + end + + domains[mathchar_code] = function(pointer,what,n,parent) + local attr = getattr(pointer,a_mathdomain) + if attr then + local domain = numbers[attr] + if domain then + local hash = domain.hash + if not hash then + hash = makehash(domain) + end + local char = getchar(pointer) + local okay = hash[char] + if okay then + local chr = okay.char + local cls = okay.code + if chr and chr ~= char then + setchar(pointer,chr) + end + if cls and cls ~= getsubtype(parent) then + setsubtype(parent,cls) + end + end + end + end + end + + function handlers.domains(head,style,penalties) + processnoads(head,domains,"domains") + return true -- not needed + end + +end + +-- just for me + +function handlers.showtree(head,style,penalties) + inspect(nodes.totree(tonut(head))) +end + +registertracker("math.showtree",function(v) + setaction("math","noads.handlers.showtree",v) +end) + +-- also for me + +do + + local applyvisuals = nuts.applyvisuals + local visual = false + + function handlers.makeup(head) + applyvisuals(head,visual) + end + + registertracker("math.makeup",function(v) + visual = v + setaction("math","noads.handlers.makeup",v) + end) + +end + +-- the normal builder + +do + + local force_penalties = false + + -- registertracker("math.penalties",function(v) + -- force_penalties = v + -- end) + + function builders.kernel.mlist_to_hlist(head,style,penalties) + return mlist_to_hlist(head,style,force_penalties or penalties) + end + + -- function builders.kernel.mlist_to_hlist(head,style,penalties) + -- local h = mlist_to_hlist(head,style,force_penalties or penalties) + -- inspect(nodes.totree(h,true,true,true)) + -- return h + -- end + + implement { + name = "setmathpenalties", + arguments = "integer", + actions = function(p) + force_penalties = p > 0 + end, + } + +end + +local actions = tasks.actions("math") -- head, style, penalties + +local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming + +function processors.mlist_to_hlist(head,style,penalties) + starttiming(noads) + head = actions(head,style,penalties) + stoptiming(noads) + return head +end + +callbacks.register('mlist_to_hlist',processors.mlist_to_hlist,"preprocessing math list") + +-- tracing + +statistics.register("math processing time", function() + return statistics.elapsedseconds(noads) +end) diff --git a/tex/context/base/mkiv/math-noa.lua b/tex/context/base/mkiv/math-noa.lua index 188363847..1fb763a3b 100644 --- a/tex/context/base/mkiv/math-noa.lua +++ b/tex/context/base/mkiv/math-noa.lua @@ -203,7 +203,7 @@ local subbox_code = nodecodes.subbox -- attr list local submlist_code = nodecodes.submlist -- attr list local mathchar_code = nodecodes.mathchar -- attr fam char local mathtextchar_code = nodecodes.mathtextchar -- attr fam char -local delim_code = nodecodes.delim -- attr small_fam small_char large_fam large_char +local delimiter_code = nodecodes.delimiter -- attr small_fam small_char large_fam large_char ----- style_code = nodecodes.style -- attr style ----- parameter_code = nodecodes.parameter -- attr style local math_choice = nodecodes.choice -- attr display text script scriptscript @@ -282,7 +282,7 @@ local function process(start,what,n,parent) noad = getsuppre (start) if noad then process(noad,what,n,start) end -- list noad = getsubpre (start) if noad then process(noad,what,n,start) end -- list end - elseif id == mathchar_code or id == mathtextchar_code or id == delim_code then + elseif id == mathchar_code or id == mathtextchar_code or id == delimiter_code then break elseif id == subbox_code or id == submlist_code then local noad = getlist(start) if noad then process(noad,what,n,start) end -- list (not getlist !) @@ -583,7 +583,7 @@ do end end end - families[delim_code] = function(pointer) + families[delimiter_code] = function(pointer) if getfield(pointer,"small_fam") == 0 then local a = getattr(pointer,a_mathfamily) if a and a > 0 then @@ -615,7 +615,7 @@ do -- will become: - -- families[delim_code] = function(pointer) + -- families[delimiter_code] = function(pointer) -- if getfam(pointer) == 0 then -- local a = getattr(pointer,a_mathfamily) -- if a and a > 0 then @@ -758,7 +758,7 @@ do end end - relocate[delim_code] = function(pointer) + relocate[delimiter_code] = function(pointer) if trace_analyzing then setnodecolor(pointer,"font:fina") end diff --git a/tex/context/base/mkiv/math-pln.mkxl b/tex/context/base/mkiv/math-pln.mkxl new file mode 100644 index 000000000..2e090c224 --- /dev/null +++ b/tex/context/base/mkiv/math-pln.mkxl @@ -0,0 +1,245 @@ +%D \module +%D [ file=math-pln, +%D version=2001.11.16, +%D title=\CONTEXT\ Math Macros, +%D subtitle=Plain Helpers, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D Here we collect some Plain \TEX\ leftovers. + +\writestatus{loading}{ConTeXt Math Macros / Plain Helpers} + +\unprotect + +% we need proper unicode: + +\def\relbar{\mathrel{\smash-}} % - has the same height as + .. no clue what this refers to + +% might change + +\protected\def\hrulefill{\leaders\hrule\hfill} +\protected\def\dotfill {\cleaders\hbox{\normalstartimath\mathsurround\zeropoint\mkern1.5mu.\mkern1.5mu\normalstopimath}\hfill} + +% will move + +\def\oalign#1% + {\leavevmode % plain tex uses this + \vtop + {\baselineskip\zeroskip + \lineskip.25\exheight + \ialign{\alignmark\alignmark\crcr#1\crcr}}} + +\def\ooalign % chars over each other + {\lineskiplimit-\maxdimen + \oalign} + +% needs checking + +\def\choose{\atopwithdelims()} +\def\brack {\atopwithdelims[]} +\def\brace {\atopwithdelims\{\}} + +% needs checking + +\protected\def\buildrel#1\over#2% + {\mathrel{\mathop{\kern\zeropoint#2}\limits^{#1}}} + +\protected\def\bmod + {\nonscript + \mskip-\medmuskip + \mkern5mu + \mfunction{mod}% + \penalty900 + \mkern5mu + \nonscript + \mskip-\medmuskip} + +\protected\def\pmod#1% + {\allowbreak + \mkern18mu + (\mfunction{mod}\mskip\medmuskip#1)} + +\protected\def\cases#1% + {\left\{% + \mskip\thinmuskip + \vcenter + {\normalbaselines + \mathsurround\zeropoint + \ialign{% + \normalstartimath\alignmark\alignmark\hfil\normalstopimath + \aligntab + \quad\alignmark\alignmark\hfil + \crcr + #1% + \crcr}}% + \right.} + +\protected\def\matrix#1% + {\emptyhbox + \mskip\thinmuskip + \vcenter + {\normalbaselines + \mathsurround\zeropoint + \ialign{% + \hfil\normalstartimath\alignmark\alignmark\normalstopimath\hfil + \aligntab + \aligntab + \quad\hfil\normalstartimath\alignmark\alignmark\normalstopimath\hfil + \crcr + \mathstrut + \crcr + \noalign{\kern-\baselineskip} + #1\crcr + \mathstrut + \crcr + \noalign{\kern-\baselineskip}}}% + \mskip\thinmuskip} + +\protected\def\pmatrix#1% + {\left(\matrix{#1}\right)} + +% \protected\def\openup +% {\afterassignment\math_openup\scratchdimen=} +% +% \def\math_openup +% {\advance\lineskip \scratchdimen +% \advance\baselineskip \scratchdimen +% \advance\lineskiplimit\scratchdimen} + +\let\math_closeup\relax + +\protected\def\math_openup + {\afterassignment\math_openup_indeed\scratchdimen} + +\def\math_openup_indeed + {\protected\edef\math_closeup + {\lineskip \the\lineskip + \baselineskip \the\baselineskip + \lineskiplimit\the\lineskiplimit + \relax}% + \advance \lineskip \scratchdimen + \advance \baselineskip \scratchdimen + \advance \lineskiplimit \scratchdimen} + +\let\openup \math_openup +\def\closeup{\math_closeup} % dynamic + +\protected\def\displaylines#1% + {\the\mathdisplayaligntweaks + \tabskip\zeroskip + \halign + {\hbox to \displaywidth{% + \normalstartimath\tabskip\zeroskip\everycr\emptytoks\hfil\displaystyle\alignmark\alignmark\hfil\normalstopimath}\crcr + #1\crcr}} + +%D This comes from plain but I gave it a \CONTEXT\ touch: + +\permanent\def\math_border_NC_indeed + {\enforced\global\def\math_border_NC{\aligntab}} + +\aliased\let\math_border_NC\math_border_NC_indeed + +\permanent\def\math_border_NR + {\enforced\global\let\math_border_NC\math_border_NC_indeed + \cr} + +\protected\def\math_border_matrix#1#2#3% adapted plain + {\begingroup + % + \setbox\scratchbox\hbox\bgroup + \mr B% + \egroup + \scratchdimenone\wd\scratchbox + % + \scratchdimentwo.2\bodyfontsize + % + \mathsurround\zeropoint + % + \enforced\def\NC{\math_border_NC}% + \enforced\def\NR{\math_border_NR}% + % + \gdef\m_math_border_matrix + {\kern\scratchdimentwo + \glet\m_math_border_matrix\relax}% + % + \setbox\scratchboxone\vbox\bgroup + \everycr{\noalign\bgroup\m_math_border_matrix\egroup}% + \tabskip \zeroskip + \halign{% \ialign resets everycr + \startimath\alignmark\alignmark\stopimath + \hfil + \kern\dimexpr\scratchdimentwo+\scratchdimenone\relax + \aligntab + \thinspace + \hfil + \startimath\alignmark\alignmark\stopimath + \hfil + \aligntab + \aligntab + \quad + \hfil + \startimath\alignmark\alignmark\stopimath + \hfil + \crcr + \omit + \strut + \hfil + \crcr + \noalign{\kern-\baselineskip}% + #3\crcr + \omit + \strut + \cr}% + \egroup + \setbox\scratchboxtwo\vbox\bgroup + \unvcopy\scratchboxone + \global\setbox\globalscratchbox\lastbox + \egroup + \setbox\scratchboxtwo\hbox\bgroup + \unhbox\globalscratchbox + \unskip + \global\setbox\globalscratchbox\lastbox + \egroup + \setbox\scratchboxtwo\hbox\bgroup + \startimath + \kern\dimexpr\wd\globalscratchbox-\scratchdimenone\relax + \left#1\relax + \kern-\wd\globalscratchbox + \global\setbox\globalscratchbox\vbox\bgroup + \box\globalscratchbox + \kern\scratchdimentwo + \egroup + \vcenter\bgroup + \kern-\ht\globalscratchbox + \unvbox\scratchboxone + \kern-\baselineskip + \egroup + \thinspace + \right#2\relax + \stopimath + \egroup + \null + \thickspace + \vbox\bgroup + \kern\ht\globalscratchbox + \box\scratchboxtwo + \egroup + % + \endgroup} + +\permanent\protected\def\bordermatrix {\math_border_matrix()} +\permanent\protected\def\bbordermatrix{\math_border_matrix[]} + +\permanent\protected\def\startbordermatrix #1\stopbordermatrix {\math_border_matrix(){#1}} +\permanent\protected\def\startbbordermatrix#1\stopbbordermatrix{\math_border_matrix[]{#1}} + +\permanent\let\stopbordermatrix \relax +\permanent\let\stopbbordermatrix\relax + +\protect \endinput diff --git a/tex/context/base/mkiv/math-tag.lmt b/tex/context/base/mkiv/math-tag.lmt new file mode 100644 index 000000000..eb58b5450 --- /dev/null +++ b/tex/context/base/mkiv/math-tag.lmt @@ -0,0 +1,596 @@ +if not modules then modules = { } end modules ['math-tag'] = { + version = 1.001, + comment = "companion to math-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- todo: have a local list with local tags that then get appended +-- todo: use tex.getmathcodes (no table) + +-- use lpeg matchers + +local find, match = string.find, string.match +local insert, remove, concat = table.insert, table.remove, table.concat + +local attributes = attributes +local nodes = nodes + +local nuts = nodes.nuts +local tonut = nuts.tonut + +local getnext = nuts.getnext +local getid = nuts.getid +local getchar = nuts.getchar +local getfont = nuts.getfont +local getlist = nuts.getlist +local getfield = nuts.getfield +local getdisc = nuts.getdisc +local getsubtype = nuts.getsubtype +local getattr = nuts.getattr +local getattrlist = nuts.getattrlist +local setattr = nuts.setattr +----- getcomponents = nuts.getcomponents -- not really needed +local getwidth = nuts.getwidth + +local getnucleus = nuts.getnucleus +local getsub = nuts.getsub +local getsup = nuts.getsup + +local set_attributes = nuts.setattributes + +local nextnode = nuts.traversers.node + +local nodecodes = nodes.nodecodes + +local noad_code = nodecodes.noad -- attr nucleus sub sup +local accent_code = nodecodes.accent -- attr nucleus sub sup accent +local radical_code = nodecodes.radical -- attr nucleus sub sup left degree +local fraction_code = nodecodes.fraction -- attr nucleus sub sup left right +local subbox_code = nodecodes.subbox -- attr list +local submlist_code = nodecodes.submlist -- attr list +local mathchar_code = nodecodes.mathchar -- attr fam char +local mathtextchar_code = nodecodes.mathtextchar -- attr fam char +local delimiter_code = nodecodes.delimiter -- attr small_fam small_char large_fam large_char +local style_code = nodecodes.style -- attr style +local choice_code = nodecodes.choice -- attr display text script scriptscript +local fence_code = nodecodes.fence -- attr subtype + +local accentcodes = nodes.accentcodes +local fencecodes = nodes.fencecodes + +local fixedtopaccent_code = accentcodes.fixedtop +local fixedbottomaccent_code = accentcodes.fixedbottom +local fixedbothaccent_code = accentcodes.fixedboth + +local leftfence_code = fencecodes.left +local middlefence_code = fencecodes.middle +local rightfence_code = fencecodes.right + +local kerncodes = nodes.kerncodes + +local fontkern_code = kerncodes.fontkern +local italickern_code = kerncodes.italickern + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local glyph_code = nodecodes.glyph +local disc_code = nodecodes.disc +local glue_code = nodecodes.glue +local kern_code = nodecodes.kern +local math_code = nodecodes.math + +local processnoads = noads.process + +local a_tagged = attributes.private('tagged') +local a_mathcategory = attributes.private('mathcategory') +local a_mathmode = attributes.private('mathmode') + +local tags = structures.tags + +local start_tagged = tags.start +local restart_tagged = tags.restart +local stop_tagged = tags.stop +local taglist = tags.taglist + +local chardata = characters.data + +local getmathcodes = tex.getmathcodes +local mathcodes = mathematics.codes +local ordinary_mathcode = mathcodes.ordinary +local variable_mathcode = mathcodes.variable + +local fromunicode16 = fonts.mappings.fromunicode16 +local fontcharacters = fonts.hashes.characters + +local report_tags = logs.reporter("structure","tags") + +local process + +local function processsubsup(start) + -- At some point we might need to add an attribute signaling the + -- super- and subscripts because TeX and MathML use a different + -- order. The mrows are needed to keep mn's separated. + local nucleus = getnucleus(start) + local sup = getsup(start) + local sub = getsub(start) + if sub then + if sup then + setattr(start,a_tagged,start_tagged("msubsup")) + -- start_tagged("mrow") + process(nucleus) + -- stop_tagged() + start_tagged("mrow", { subscript = true }) + process(sub) + stop_tagged() + start_tagged("mrow", { superscript = true }) + process(sup) + stop_tagged() + stop_tagged() + else + setattr(start,a_tagged,start_tagged("msub")) + -- start_tagged("mrow") + process(nucleus) + -- stop_tagged() + start_tagged("mrow") + process(sub) + stop_tagged() + stop_tagged() + end + elseif sup then + setattr(start,a_tagged,start_tagged("msup")) + -- start_tagged("mrow") + process(nucleus) + -- stop_tagged() + start_tagged("mrow") + process(sup) + stop_tagged() + stop_tagged() + else + process(nucleus) + end +end + +-- todo: check function here and keep attribute the same + +-- todo: variants -> original + +local actionstack = { } +local fencesstack = { } + +-- glyph nodes and such can happen in under and over stuff + +-- local function getunicode(n) -- instead of getchar +-- local char = getchar(n) +-- -- local font = getfontoffamily(getfield(n,"fam")) +-- local font = getfont(n) +-- local data = fontcharacters[font][char] +-- return data.unicode or char +-- end + +local function getunicode(n) -- instead of getchar + -- local char, font = isglyph(n) -- no, we have a mathchar + local char, font = getchar(n), getfont(n) + local data = fontcharacters[font][char] + return data.unicode or char -- can be a table but unlikely for math characters +end + +------------------- + +local content = { } +local found = false + +content[mathchar_code] = function() found = true end + +local function hascontent(head) + found = false + processnoads(head,content,"content") + return found +end + +-------------------- + +-- todo: use properties + +-- local function showtag(n,id,old) +-- local attr = getattr(n,a_tagged) +-- local curr = tags.current() +-- report_tags("%s, node %s, attr %s:%s (%s), top %s (%s)", +-- old and "before" or "after ", +-- nodecodes[id], +-- getattrlist(n), +-- attr or "?",attr and taglist[attr].tagname or "?", +-- curr or "?",curr and taglist[curr].tagname or "?" +-- ) +-- end + +process = function(start) -- we cannot use the processor as we have no finalizers (yet) + local mtexttag = nil + while start do + local id = getid(start) +-- showtag(start,id,true) + if id == glyph_code or id == disc_code then + if not mtexttag then + mtexttag = start_tagged("mtext") + end + setattr(start,a_tagged,mtexttag) + elseif mtexttag and id == kern_code and (getsubtype(start) == fontkern_code or getsubtype(start) == italickern_code) then -- italickern + setattr(start,a_tagged,mtexttag) + else + if mtexttag then + stop_tagged() + mtexttag = nil + end + if id == mathchar_code then + local char = getchar(start) + local code = getmathcodes(char) + local tag + if code == ordinary_mathcode or code == variable_mathcode then + local ch = chardata[char] + local mc = ch and ch.mathclass + if mc == "number" then + tag = "mn" + elseif mc == "variable" or not mc then -- variable is default + tag = "mi" + else + tag = "mo" + end + else + tag = "mo" + end + local a = getattr(start,a_mathcategory) + if a then + setattr(start,a_tagged,start_tagged(tag,{ mathcategory = a })) + else + setattr(start,a_tagged,start_tagged(tag)) -- todo: a_mathcategory + end + stop_tagged() + -- showtag(start,id,false) + break -- okay? + elseif id == mathtextchar_code then -- or id == glyph_code + -- check for code + local a = getattr(start,a_mathcategory) + if a then + setattr(start,a_tagged,start_tagged("ms",{ mathcategory = a })) -- mtext + else + setattr(start,a_tagged,start_tagged("ms")) -- mtext + end + stop_tagged() + -- showtag(start,id,false) + break + elseif id == delimiter_code then + -- check for code + setattr(start,a_tagged,start_tagged("mo")) + stop_tagged() + -- showtag(start,id,false) + break + elseif id == style_code then + -- has a next + elseif id == noad_code then + -- setattr(start,a_tagged,tags.current()) + processsubsup(start) + elseif id == subbox_code or id == hlist_code or id == vlist_code then + -- keep an eye on subbox_code and see what ends up in there + local attr = getattr(start,a_tagged) + if not attr then + -- just skip + else + local specification = taglist[attr] + if specification then + local tag = specification.tagname + if tag == "formulacaption" then + -- skip + elseif tag == "mstacker" then + local list = getlist(start) + if list then + process(list) + end + else + if tag ~= "mstackertop" and tag ~= "mstackermid" and tag ~= "mstackerbot" then + tag = "mtext" + end + local text = start_tagged(tag) + setattr(start,a_tagged,text) + local list = getlist(start) + if not list then + -- empty list + elseif not attr then + -- box comes from strange place + set_attributes(list,a_tagged,text) -- only the first node ? + else + -- Beware, the first node in list is the actual list so we definitely + -- need to nest. This approach is a hack, maybe I'll make a proper + -- nesting feature to deal with this at another level. Here we just + -- fake structure by enforcing the inner one. + -- + -- todo: have a local list with local tags that then get appended + -- + local tagdata = specification.taglist + local common = #tagdata + 1 + local function runner(list,depth) -- quite inefficient + local cache = { } -- we can have nested unboxed mess so best local to runner + local keep = nil + -- local keep = { } -- win case we might need to move keep outside + for n, id, subtype in nextnode, list do + local mth = id == math_code and subtype + if mth == 0 then -- hm left_code + -- insert(keep,text) + keep = text + text = start_tagged("mrow") + common = common + 1 + end + local aa = getattr(n,a_tagged) + if aa then + local ac = cache[aa] + if not ac then + local tagdata = taglist[aa].taglist + local extra = #tagdata + if common <= extra then + for i=common,extra do + ac = restart_tagged(tagdata[i]) -- can be made faster + end + for i=common,extra do + stop_tagged() -- can be made faster + end + else + ac = text + end + cache[aa] = ac + end + setattr(n,a_tagged,ac) + else + setattr(n,a_tagged,text) + end + if id == hlist_code or id == vlist_code then + runner(getlist(n),depth+1) + elseif id == glyph_code then + -- this should not be needed + -- local components = getcomponents(n) -- unlikely set + -- if components then + -- runner(getcomponent,depth+1) + -- end + elseif id == disc_code then + -- this should not be needed + local pre, post, replace = getdisc(n) + if pre then + runner(pre,depth+1) + end + if post then + runner(post,depth+1) + end + if replace then + runner(replace,depth+1) + end + end + if mth == 1 then + stop_tagged() + -- text = remove(keep) + text = keep + common = common - 1 + end + end + end + runner(list,0) + end + stop_tagged() + end + end + end + elseif id == submlist_code then -- normally a hbox + local list = getlist(start) + if list then + local attr = getattr(start,a_tagged) + local last = attr and taglist[attr] + if last then + local tag = last.tagname + local detail = last.detail + if tag == "maction" then + if detail == "" then + setattr(start,a_tagged,start_tagged("mrow")) + process(list) + stop_tagged() + elseif actionstack[#actionstack] == action then + setattr(start,a_tagged,start_tagged("mrow")) + process(list) + stop_tagged() + else + insert(actionstack,action) + setattr(start,a_tagged,start_tagged("mrow",{ detail = action })) + process(list) + stop_tagged() + remove(actionstack) + end + elseif tag == "mstacker" then -- or tag == "mstackertop" or tag == "mstackermid" or tag == "mstackerbot" then + -- looks like it gets processed twice + -- do we still end up here ? + setattr(start,a_tagged,restart_tagged(attr)) -- so we just reuse the attribute + process(list) + stop_tagged() + else + setattr(start,a_tagged,start_tagged("mrow")) + process(list) + stop_tagged() + end + else -- never happens, we're always document + setattr(start,a_tagged,start_tagged("mrow")) + process(list) + stop_tagged() + end + end + elseif id == fraction_code then + local num = getfield(start,"num") + local denom = getfield(start,"denom") + local left = getfield(start,"left") + local right = getfield(start,"right") + if left then + setattr(left,a_tagged,start_tagged("mo")) + process(left) + stop_tagged() + end + setattr(start,a_tagged,start_tagged("mfrac")) + process(num) + process(denom) + stop_tagged() + if right then + setattr(right,a_tagged,start_tagged("mo")) + process(right) + stop_tagged() + end + elseif id == choice_code then + local display = getfield(start,"display") + local text = getfield(start,"text") + local script = getfield(start,"script") + local scriptscript = getfield(start,"scriptscript") + if display then + process(display) + end + if text then + process(text) + end + if script then + process(script) + end + if scriptscript then + process(scriptscript) + end + elseif id == fence_code then + local subtype = getsubtype(start) + local delim = getfield(start,"delimiter") + if subtype == leftfence_code then + -- left + local properties = { } + insert(fencesstack,properties) + setattr(start,a_tagged,start_tagged("mfenced",properties)) -- needs checking + if delim then + start_tagged("ignore") + local chr = getchar(delim) + if chr ~= 0 then + properties.left = chr + end + process(delim) + stop_tagged() + end + start_tagged("mrow") -- begin of subsequence + elseif subtype == middlefence_code then + -- middle + if delim then + start_tagged("ignore") + local top = fencesstack[#fencesstack] + local chr = getchar(delim) + if chr ~= 0 then + local mid = top.middle + if mid then + mid[#mid+1] = chr + else + top.middle = { chr } + end + end + process(delim) + stop_tagged() + end + stop_tagged() -- end of subsequence + start_tagged("mrow") -- begin of subsequence + elseif subtype == rightfence_code then + local properties = remove(fencesstack) + if not properties then + report_tags("missing right fence") + properties = { } + end + if delim then + start_tagged("ignore") + local chr = getchar(delim) + if chr ~= 0 then + properties.right = chr + end + process(delim) + stop_tagged() + end + stop_tagged() -- end of subsequence + stop_tagged() + else + -- can't happen + end + elseif id == radical_code then + local left = getfield(start,"left") + local degree = getfield(start,"degree") + if left then + start_tagged("ignore") + process(left) -- root symbol, ignored + stop_tagged() + end + if degree and hascontent(degree) then + setattr(start,a_tagged,start_tagged("mroot")) + processsubsup(start) + process(degree) + stop_tagged() + else + setattr(start,a_tagged,start_tagged("msqrt")) + processsubsup(start) + stop_tagged() + end + elseif id == accent_code then + local subtype = getsubtype(start) + local accent = getfield(start,"accent") + local bot_accent = getfield(start,"bot_accent") + if bot_accent then + if accent then + setattr(start,a_tagged,start_tagged("munderover", { + accent = true, + top = getunicode(accent), + bottom = getunicode(bot_accent), + topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code, + bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code, + })) + processsubsup(start) + process(bot_accent) + process(accent) + stop_tagged() + else + setattr(start,a_tagged,start_tagged("munder", { + accent = true, + bottom = getunicode(bot_accent), + bottomfixed = subtype == fixedbottomaccent_code or subtype == fixedbothaccent_code, + })) + processsubsup(start) + process(bot_accent) + stop_tagged() + end + elseif accent then + setattr(start,a_tagged,start_tagged("mover", { + accent = true, + top = getunicode(accent), + topfixed = subtype == fixedtopaccent_code or subtype == fixedbothaccent_code, + })) + processsubsup(start) + process(accent) + stop_tagged() + else + processsubsup(start) + end + elseif id == glue_code then + -- setattr(start,a_tagged,start_tagged("mspace",{ width = getwidth(start) })) + setattr(start,a_tagged,start_tagged("mspace")) + stop_tagged() + else + setattr(start,a_tagged,start_tagged("merror", { detail = nodecodes[i] })) + stop_tagged() + end + end +-- showtag(start,id,false) + start = getnext(start) + end + if mtexttag then + stop_tagged() + end +end + +function noads.handlers.tags(head,style,penalties) + start_tagged("math", { mode = (getattr(head,a_mathmode) == 1) and "display" or "inline" }) + setattr(head,a_tagged,start_tagged("mrow")) +-- showtag(head,getid(head),true) + process(head) +-- showtag(head,getid(head),false) + stop_tagged() + stop_tagged() +end diff --git a/tex/context/base/mkiv/math-tag.lua b/tex/context/base/mkiv/math-tag.lua index 9267e0f39..41373fcb5 100644 --- a/tex/context/base/mkiv/math-tag.lua +++ b/tex/context/base/mkiv/math-tag.lua @@ -52,7 +52,7 @@ local subbox_code = nodecodes.subbox -- attr list local submlist_code = nodecodes.submlist -- attr list local mathchar_code = nodecodes.mathchar -- attr fam char local mathtextchar_code = nodecodes.mathtextchar -- attr fam char -local delim_code = nodecodes.delim -- attr small_fam small_char large_fam large_char +local delimiter_code = nodecodes.delimiter -- attr small_fam small_char large_fam large_char local style_code = nodecodes.style -- attr style local choice_code = nodecodes.choice -- attr display text script scriptscript local fence_code = nodecodes.fence -- attr subtype @@ -259,7 +259,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer stop_tagged() -- showtag(start,id,false) break - elseif id == delim_code then + elseif id == delimiter_code then -- check for code setattr(start,a_tagged,start_tagged("mo")) stop_tagged() diff --git a/tex/context/base/mkiv/math-toy.mkxl b/tex/context/base/mkiv/math-toy.mkxl index 4cc65aaa6..510872e3b 100644 --- a/tex/context/base/mkiv/math-toy.mkxl +++ b/tex/context/base/mkiv/math-toy.mkxl @@ -27,19 +27,18 @@ %D $\dorecurse{199}{x_{#1} \ifodd#1\relax\Plus\else\Minus\fi} x_{200} \Equal n$ \blank %D \stoptyping -\unexpanded\def\definemathtoysymbol - {\dotripleargument\math_toy_define_symbol} +\permanent\tolerant\protected\def\definemathtoysymbol[#1]#*[#2]#*[#3]% + {\ifarguments\or\or\or + \setuevalue{#1}{\math_toy_define_symbol_indeed{\mathcodechecked{#2}}{#3}}% + \fi} -\def\math_toy_define_symbol[#1][#2][#3]% - {\setuevalue{#1}{\math_toy_define_symbol_indeed{\mathcodechecked{#2}}{#3}}} - -\unexpanded\def\math_toy_define_symbol_traced#1#2% +\protected\def\math_toy_define_symbol_traced#1#2% {\normalexpanded{\discretionary class #1 % {$\Ustyle\number\mathstyle \darkred #2$}% {$\Ustyle\number\mathstyle \darkblue #2$}% {$\Ustyle\number\mathstyle \darkgreen #2$}}} -\unexpanded\def\math_toy_define_symbol_normal#1#2% +\protected\def\math_toy_define_symbol_normal#1#2% {\normalexpanded{\discretionary class #1 % {$\Ustyle\number\mathstyle #2$}% {$\Ustyle\number\mathstyle #2$}% diff --git a/tex/context/base/mkiv/meta-blb.lua b/tex/context/base/mkiv/meta-blb.lua index 9ee57d80d..c690f3902 100644 --- a/tex/context/base/mkiv/meta-blb.lua +++ b/tex/context/base/mkiv/meta-blb.lua @@ -293,7 +293,7 @@ function mp.mf_inject_blob(category,str) newblob(category,str) -- only for tracing mp_category = category mp_str = str - tex.runtoks("mpblobtext") + tex.runlocal("mpblobtext") end interfaces.implement { diff --git a/tex/context/base/mkiv/meta-ini.mkxl b/tex/context/base/mkiv/meta-ini.mkxl index 28fe09b9e..2ca54a38b 100644 --- a/tex/context/base/mkiv/meta-ini.mkxl +++ b/tex/context/base/mkiv/meta-ini.mkxl @@ -11,6 +11,8 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. +%D Some lmtx upgrading work needs to be done here. + % initializations: % % - pass settings from tex to mp (delayed expansion) @@ -87,10 +89,7 @@ %D Anyway, the whole multiple engine mechanism is to keep her gnuplot from %D interfering. -\unexpanded\def\startMPdefinitions - {\dosinglegroupempty\meta_start_definitions} - -\def\meta_start_definitions#1#2\stopMPdefinitions +\permanent\tolerant\protected\def\startMPdefinitions#=#:#2\stopMPdefinitions {\let\m_meta_saved_instance\currentMPinstance \edef\currentMPinstance{#1}% \ifempty\currentMPinstance @@ -99,65 +98,48 @@ \gtoksapp\t_meta_definitions{#2}% \let\currentMPinstance\m_meta_saved_instance} -\let\stopMPdefinitions\relax - -\unexpanded\def\startMPextensions - {\dosinglegroupempty\meta_start_extensions} +\permanent\let\stopMPdefinitions\relax -\def\meta_start_extensions#1#2\stopMPextensions % we could use buffers instead +\permanent\tolerant\protected\def\startMPextensions#=#:#2\stopMPextensions % we could use buffers instead {\clf_setmpextensions{#1}{#2}} -\let\stopMPextensions\relax +\permanent\let\stopMPextensions\relax -\unexpanded\def\startMPinitializations#1\stopMPinitializations % for all instances, when enabled +\permanent\protected\def\startMPinitializations#1\stopMPinitializations % for all instances, when enabled {\gtoksapp\t_meta_initializations{#1}} -\let\stopMPinitializations\relax - -\unexpanded\def\startMPinclusions - {\dosingleempty\meta_start_inclusions} - -\unexpanded\def\meta_start_inclusions[#1]% - {\edef\m_meta_option{#1}% - \dosinglegroupempty\meta_start_inclusions_indeed} +\permanent\let\stopMPinitializations\relax -\def\meta_start_inclusions_indeed#1#2\stopMPinclusions - {\let\m_meta_saved_instance\currentMPinstance - \edef\currentMPinstance{#1}% +\permanent\tolerant\protected\def\startMPinclusions[#1]#*#=#:#3\stopMPinclusions + {\let\m_meta_saved_instance\currentMPinstance % \pushmacro + \edef\currentMPinstance{#2}% \ifempty\currentMPinstance \let\currentMPinstance\defaultMPinstance \fi - \ifx\m_meta_option\!!plustoken \else + \iftok{#1}{+}\else \global\t_meta_inclusions\emptytoks \fi - \gtoksapp\t_meta_inclusions{#2}% - \let\currentMPinstance\m_meta_saved_instance} + \gtoksapp\t_meta_inclusions{#3}% + \let\currentMPinstance\m_meta_saved_instance} % \popmacro -\let\stopMPinclusions\relax +\permanent\let\stopMPinclusions\relax % The next was broken since we added instances so it will go away! -\unexpanded\def\MPinclusions - {\dosingleempty\meta_inclusions} - -\def\meta_inclusions[#1]% - {\edef\m_meta_option{#1}% - \dodoublegroupempty\meta_inclusions_indeed} - -\def\meta_inclusions_indeed#1#2% +\permanent\tolerant\protected\def\MPinclusions[#1]#:#*#=#:#*#=% {\let\m_meta_saved_instance\currentMPinstance - \ifx\m_meta_option\!!plustoken \else + \iftok{#1}{+}\else \global\t_meta_inclusions\emptytoks \fi - \ifsecondargument - \edef\currentMPinstance{#1}% - \ifx\currentMPinstance\empty + \ifparameter#3\or + \edef\currentMPinstance{#2}% + \ifempty\currentMPinstance \let\currentMPinstance\defaultMPinstance \fi - \gtoksapp\t_meta_inclusions{#2}% + \gtoksapp\t_meta_inclusions{#3}% \else \let\currentMPinstance\defaultMPinstance - \gtoksapp\t_meta_inclusions{#1}% + \gtoksapp\t_meta_inclusions{#2}% \fi \let\currentMPinstance\m_meta_saved_instance} @@ -184,7 +166,7 @@ \t_meta_inclusions \emptytoks % in case we redefine \to \everydefineMPinstance -\unexpanded\def\resetMPinstance[#1]% +\permanent\protected\def\resetMPinstance[#1]% {\writestatus\m!metapost{reset will be implemented when needed}} \def\meta_analyze_graphicname[#1]% @@ -201,7 +183,7 @@ {\let\meta_show_properties\meta_show_properties_indeed} {\let\meta_show_properties\donothing} -\unexpanded\def\meta_analyze_graphicname_indeed[#1::#2::#3]% instance :: +\protected\def\meta_analyze_graphicname_indeed[#1::#2::#3]% instance :: {\edef\currentMPgraphicname{#2}% \ifempty\currentMPgraphicname \edef\currentMPgraphicname{#1}% @@ -296,7 +278,7 @@ \meta_relocate_graphic \popMPboundingbox} -\unexpanded\def\meta_process_graphic_instance#1% +\protected\def\meta_process_graphic_instance#1% {\edef\currentMPinstance{#1}% \ifempty\currentMPinstance \let\currentMPinstance\defaultMPinstance @@ -304,7 +286,7 @@ \edef\currentMPformat{\MPinstanceparameter\s!format}% \meta_process_graphic} -\unexpanded\def\meta_process_graphic#1% todo: extensions and inclusions outside beginfig +\protected\def\meta_process_graphic#1% todo: extensions and inclusions outside beginfig {\meta_start_current_graphic \forgetall \edef\p_extensions{\MPinstanceparameter\s!extensions}% @@ -329,7 +311,7 @@ \let\meta_process_graphic_figure_start\relax \let\meta_process_graphic_figure_stop \relax -\unexpanded\def\processMPfigurefile#1% special case: obeys beginfig .. endfig and makes pages +\permanent\protected\def\processMPfigurefile#1% special case: obeys beginfig .. endfig and makes pages {\begingroup \let\normal_meta_process_graphic_start\meta_process_graphic_start \let\normal_meta_process_graphic_stop \meta_process_graphic_stop @@ -348,7 +330,7 @@ % \csname\??mpgraphic#1\endcsname ; % ; is safeguard % \fi} % -% \unexpanded\def\meta_enable_include % public +% \protected\def\meta_enable_include % public % {\let\meta_handle_use_graphic \thirdofthreearguments % \let\meta_handle_reusable_graphic\thirdofthreearguments} % @@ -363,7 +345,7 @@ % so we cannot overload unless we let back to the original meanings each graphic % ... a better solution is: -\def\includeMPgraphic#1% gets expanded ! +\permanent\def\includeMPgraphic#1% gets expanded ! {\ifcsname\??mpgraphic#1\endcsname \doubleexpandafter\fourthoffourarguments\lastnamedcs ; % ; is safeguard \fi} @@ -374,31 +356,31 @@ \newif\ifMPdrawingdone \MPdrawingdonefalse -\unexpanded\def\finalizeMPdrawing +\permanent\protected\def\finalizeMPdrawing {\MPdrawingdonetrue} \let\MPdrawingdata\empty -\unexpanded\def\resetMPdrawing +\permanent\protected\def\resetMPdrawing {\glet\MPdrawingdata\empty \global\MPdrawingdonefalse} -\unexpanded\def\pushMPdrawing +\permanent\protected\def\pushMPdrawing {\globalpushmacro\MPdrawingdata \glet\MPdrawingdata\empty} -\unexpanded\def\popMPdrawing +\permanent\protected\def\popMPdrawing {\globalpopmacro\MPdrawingdata} -\unexpanded\def\getMPdrawing +\permanent\protected\def\getMPdrawing {\ifMPdrawingdone \expandafter\meta_process_graphic\expandafter{\MPdrawingdata}% is this expansion still needed? \fi} -\def\startMPdrawing - {\dosingleempty\meta_start_drawing} +\permanent\tolerant\def\startMPdrawing[#1]% todo: use pickup #: + {\meta_start_drawing#1} -\def\meta_start_drawing[#1]#2\stopMPdrawing % to be redone, this ascii stuff +\def\meta_start_drawing#1#2\stopMPdrawing % to be redone, this ascii stuff {\relax \bgroup \meta_enable_include @@ -406,21 +388,21 @@ \xdef\MPdrawingdata{\MPdrawingdata\asciia}% \egroup} -\let\stopMPdrawing\relax +\permanent\let\stopMPdrawing\relax -\def\MPdrawing#1% +\permanent\def\MPdrawing#1% {\relax \bgroup \meta_enable_include \xdef\MPdrawingdata{\MPdrawingdata#1}% \egroup} -\unexpanded\def\startMPclip#1#2\stopMPclip % todo: store at the lua end or just store less +\permanent\protected\def\startMPclip#1#2\stopMPclip % todo: store at the lua end or just store less {\setgvalue{\??mpclip#1}{#2}} -\let\stopMPclip\relax +\permanent\let\stopMPclip\relax -\unexpanded\def\meta_grab_clip_path#1#2#3% +\protected\def\meta_grab_clip_path#1#2#3% {\begingroup \d_overlay_width #2\relax \d_overlay_height#3\relax @@ -458,7 +440,7 @@ %D Since we want labels to follow the document settings, we also set the font %D related variables. -\unexpanded\def\MPfontsizehskip#1% +\permanent\protected\def\MPfontsizehskip#1% {\dontleavehmode \begingroup \definedfont[#1]% @@ -509,41 +491,33 @@ \def\meta_prepare_variable_default{\MPcolor{black}} % just to be sure we use a color but ... -\unexpanded\def\setupMPvariables - {\dodoubleempty\meta_setup_variables} - -\def\meta_setup_variables[#1][#2]% - {\ifsecondargument - \getrawparameters[\??graphicvariable#1:][#2]% - \else +\permanent\tolerant\protected\def\setupMPvariables[#1]#*[#2]% + {\ifarguments + \or \getrawparameters[\??graphicvariable:][#1]% + \else + \getrawparameters[\??graphicvariable#1:][#2]% \fi} -\unexpanded\def\presetMPvariable - {\dodoubleargument\meta_preset_variable} - -\def\meta_preset_variable[#1][#2=#3]% +\permanent\tolerant\protected\def\presetMPvariable[#1]#*[#2=#3]% {\ifcsname\??graphicvariable#1:#2\endcsname \else \setvalue{\??graphicvariable#1:#2}{#3}% \fi} -\def\MPrawvar#1#2% no checking +\permanent\def\MPrawvar#1#2% no checking {\begincsname\??graphicvariable#1:#2\endcsname} -\def\MPvariable#1% todo: could be a framed chain +\permanent\def\MPvariable#1% todo: could be a framed chain {\begincsname\??graphicvariable\currentmpvariableclass:#1\endcsname} -\unexpanded\def\useMPvariables - {\dodoubleargument\meta_use_variables} - -\def\meta_use_variables[#1][#2]% +\permanent\tolerant\protected\def\useMPvariables[#1]#*[#2]% {\edef\currentmpvariableclass{#1}% \meta_prepare_variables{#2}} -\unexpanded\def\meta_prepare_variables#1% +\protected\def\meta_prepare_variables#1% {\processcommalist[#1]\meta_prepare_variable} -\unexpanded\def\meta_prepare_variable#1% +\protected\def\meta_prepare_variable#1% {\edef\m_meta_current_variable_template {\??graphicvariable\currentmpvariableclass:#1}% \edef\m_meta_current_variable @@ -554,10 +528,10 @@ \expandafter\meta_prepare_variable_yes \fi} -\unexpanded\def\meta_prepare_instance_variables +\protected\def\meta_prepare_instance_variables {\expandafter\processcommalist\expandafter[\m_meta_instance_variables]\meta_prepare_instance_variable} -\unexpanded\def\meta_prepare_instance_variable#1% +\protected\def\meta_prepare_instance_variable#1% {\edef\m_meta_current_variable_template {\??graphicvariable\currentmpvariableclass:#1}% \edef\m_meta_current_variable @@ -617,6 +591,8 @@ %D \stopuniqueMPgraphic %D \stoptyping +% todo: frozen or not? + \def\overlaystamp % watch the \MPcolor, since colors can be redefined {\the\d_overlay_width :% \the\d_overlay_height :% @@ -647,39 +623,39 @@ % hm, isn't this already done elsewhere? -\unexpanded\def\meta_obey_box_depth +\protected\def\meta_obey_box_depth {\setbox\b_meta_graphic\hpack\bgroup \raise\MPlly\box\b_meta_graphic \egroup} -\unexpanded\def\meta_ignore_box_depth +\protected\def\meta_ignore_box_depth {\normalexpanded - {\meta_obey_box_depth % hence the \unexpanded + {\meta_obey_box_depth % hence the \protected \wd\b_meta_graphic\the\wd\b_meta_graphic \ht\b_meta_graphic\the\ht\b_meta_graphic \dp\b_meta_graphic\the\dp\b_meta_graphic}} -\unexpanded\def\meta_obey_box_origin +\protected\def\meta_obey_box_origin {\setbox\b_meta_graphic\hpack\bgroup \kern\MPllx\raise\MPlly\box\b_meta_graphic \egroup} -\unexpanded\def\obeyMPboxdepth {\let\meta_relocate_box\meta_obey_box_depth} -\unexpanded\def\ignoreMPboxdepth{\let\meta_relocate_box\meta_ignore_box_depth} -\unexpanded\def\obeyMPboxorigin {\let\meta_relocate_box\meta_obey_box_origin} -\unexpanded\def\normalMPboxdepth{\let\meta_relocate_box\relax} +\permanent\protected\def\obeyMPboxdepth {\let\meta_relocate_box\meta_obey_box_depth} +\permanent\protected\def\ignoreMPboxdepth{\let\meta_relocate_box\meta_ignore_box_depth} +\permanent\protected\def\obeyMPboxorigin {\let\meta_relocate_box\meta_obey_box_origin} +\permanent\protected\def\normalMPboxdepth{\let\meta_relocate_box\relax} \let\meta_relocate_box\relax -\unexpanded\def\meta_place_graphic % the converter also displaces so in fact we revert +\protected\def\meta_place_graphic % the converter also displaces so in fact we revert {\meta_relocate_box \box\b_meta_graphic} -\unexpanded\def\meta_reuse_box#1#2#3#4#5% space delimiting would save some tokens +\protected\def\meta_reuse_box#1#2#3#4#5% space delimiting would save some tokens {\MPllx#2\MPlly#3\MPurx#4\MPury#5% \hpack{\forcecolorhack\getobject{MP}{#1}}} % else no proper color intent -\unexpanded\def\meta_use_box +\protected\def\meta_use_box {\setunreferencedobject{MP}} \def\meta_handle_unique_graphic#1#2#3% when there are too many, we can store data at the lua end, although, @@ -697,21 +673,20 @@ \fi \endgroup} -\unexpanded\def\startuniqueMPgraphic +% todo: we partially expand + +\protected\def\startuniqueMPgraphic {\dodoublegroupempty\meta_start_unique_graphic} -\let\stopuniqueMPgraphic\relax +\permanent\let\stopuniqueMPgraphic\relax \def\meta_start_unique_graphic#1% {\normalexpanded{\meta_start_unique_graphic_indeed{#1}}} -\unexpanded\def\meta_start_unique_graphic_indeed#1#2#3\stopuniqueMPgraphic +\permanent\protected\def\meta_start_unique_graphic_indeed#1#2#3\stopuniqueMPgraphic {\setgvalue{\??mpgraphic#1}{\meta_handle_unique_graphic{#1}{#2}{#3}}} -\unexpanded\def\uniqueMPgraphic - {\dodoublegroupempty\meta_unique_graphic} - -\def\meta_unique_graphic#1#2% +\permanent\tolerant\protected\def\uniqueMPgraphic#=#*#=% {\meta_begin_graphic_group{#1}% \setupMPvariables[#1][#2]% \begincsname\??mpgraphic#1\endcsname\empty @@ -728,26 +703,26 @@ \meta_process_graphic{#3}% \endgroup} -\unexpanded\def\startuseMPgraphic +\permanent\protected\def\startuseMPgraphic % todo, modernize {\dodoublegroupempty\meta_start_use_graphic} -\let\stopuseMPgraphic\relax +\permanent\let\stopuseMPgraphic\relax \def\meta_start_use_graphic#1% {\normalexpanded{\meta_start_use_graphic_indeed{#1}}} -\unexpanded\def\meta_start_use_graphic_indeed#1#2#3\stopuseMPgraphic +\protected\def\meta_start_use_graphic_indeed#1#2#3\stopuseMPgraphic {\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}} -\unexpanded\def\startusableMPgraphic % redundant but handy +\permanent\protected\def\startusableMPgraphic % redundant but handy % todo, modernize {\dodoublegroupempty\meta_start_usable_graphic} -\let\stopusableMPgraphic\relax +\permanent\let\stopusableMPgraphic\relax \def\meta_start_usable_graphic#1% {\normalexpanded{\meta_start_usable_graphic_indeed{#1}}} -\unexpanded\def\meta_start_usable_graphic_indeed#1#2#3\stopusableMPgraphic +\protected\def\meta_start_usable_graphic_indeed#1#2#3\stopusableMPgraphic {\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}} \def\meta_handle_reusable_graphic#1#2#3% @@ -764,21 +739,18 @@ \csname\??mpgraphic#1\endcsname\empty \endgroup} -\unexpanded\def\startreusableMPgraphic +\permanent\protected\def\startreusableMPgraphic % todo, modernize {\dodoublegroupempty\meta_start_reusable_graphic} -\let\stopreusableMPgraphic\relax +\permanent\let\stopreusableMPgraphic\relax \def\meta_start_reusable_graphic#1% {\normalexpanded{\meta_start_reusable_graphic_indeed{#1}}} -\unexpanded\def\meta_start_reusable_graphic_indeed#1#2#3\stopreusableMPgraphic +\protected\def\meta_start_reusable_graphic_indeed#1#2#3\stopreusableMPgraphic {\setgvalue{\??mpgraphic#1}{\meta_handle_reusable_graphic{#1}{#2}{#3}}} -\unexpanded\def\useMPgraphic - {\dodoublegroupempty\meta_use_graphic} - -\def\meta_use_graphic#1#2% +\permanent\tolerant\protected\def\useMPgraphic#=#*#=% {\meta_begin_graphic_group{#1}% \ifcsname\??mpgraphic#1\endcsname \edef\usedMPgraphicname{#1}% @@ -795,8 +767,8 @@ \fi \meta_end_graphic_group} -\let\reuseMPgraphic \useMPgraphic % we can save a setup here if needed -\let\reusableMPgraphic\reuseMPgraphic % we can save a setup here if needed +\aliased\let\reuseMPgraphic \useMPgraphic % we can save a setup here if needed +\aliased\let\reusableMPgraphic\reuseMPgraphic % we can save a setup here if needed %D \macros %D {startuniqueMPpagegraphic,uniqueMPpagegraphic} @@ -815,22 +787,19 @@ \MPcolor\overlaycolor :% \MPcolor\overlaylinecolor} -\unexpanded\def\startuniqueMPpagegraphic +\permanent\tolerant\protected\def\startuniqueMPpagegraphic % todo the modern way {\dodoublegroupempty\meta_start_unique_page_graphic} -\let\stopuniqueMPpagegraphic\relax +\permanent\let\stopuniqueMPpagegraphic\relax \def\meta_start_unique_page_graphic#1% {\normalexpanded{\meta_start_unique_page_graphic_indeed{#1}}} -\unexpanded\def\meta_start_unique_page_graphic_indeed#1#2#3\stopuniqueMPpagegraphic % inefficient, double storage - {\setgvalue{\??mpgraphic o:#1}{\meta_handle_unique_graphic{o:#1}{#2}{#3}}% % but these also keep the state - \setgvalue{\??mpgraphic e:#1}{\meta_handle_unique_graphic{e:#1}{#2}{#3}}} % and meaning will be redefined +\protected\def\meta_start_unique_page_graphic_indeed#1#2#3\stopuniqueMPpagegraphic % inefficient, double storage + {\setgvalue{\??mpgraphic o:#1}{\meta_handle_unique_graphic{o:#1}{#2}{#3}}% % but these also keep the state + \setgvalue{\??mpgraphic e:#1}{\meta_handle_unique_graphic{e:#1}{#2}{#3}}} % and meaning will be redefined -\unexpanded\def\uniqueMPpagegraphic - {\dodoublegroupempty\meta_unique_page_graphic} - -\def\meta_unique_page_graphic#1#2% +\permanent\tolerant\protected\def\uniqueMPpagegraphic#=#=% {\meta_begin_graphic_group{#1}% \let\overlaystamp\overlaypagestamp \setupMPvariables[\m_meta_page_prefix:#1][#2]% prefix is new here @@ -849,36 +818,30 @@ %D Since we need to feed \METAPOST\ with expanded dimensions, we introduce a %D dedicated expansion engine. We redefine \type {\extendMPoverlaystamp} to -\unexpanded\def\extendMPoverlaystamp#1% +\permanent\protected\def\extendMPoverlaystamp#1% {\processcommalist[#1]\meta_extend_overlay_stamp} \def\meta_extend_overlay_stamp#1% {\meta_prepare_instance_variable{#1}% \edef\overlaystamp{\overlaystamp:\MPvariable{#1}}} -\unexpanded\def\getMPdata {\clf_getMPdata} - \let\rawMPdata \clf_getMPdata +\permanent\protected\def\getMPdata {\clf_getMPdata} + \let\rawMPdata \clf_getMPdata % we need frozen at the lua end -\unexpanded\def\getMPstored{\clf_getMPstored} - \let\rawMPstored \clf_getMPstored +\permanent\protected\def\getMPstored{\clf_getMPstored} + \let\rawMPstored \clf_getMPstored % we need frozen at the lua end %D We need this trick because we need to make sure that the tex scanner sees %D newlines and does not quit. Also, we do need to flush the buffer under a normal %D catcode regime in order to expand embedded tex macros. As usual with buffers, %D \type {#1} can be a list. -\unexpanded\def\processMPbuffer - {\dosingleempty\meta_process_buffer} - -\def\meta_process_buffer[#1]% +\permanent\tolerant\protected\def\processMPbuffer[#1]% {\meta_begin_graphic_group{#1}% \meta_process_graphic{\clf_feedback{\currentMPgraphicname}}% \meta_end_graphic_group} -\unexpanded\def\runMPbuffer - {\dosingleempty\meta_run_buffer} - -\def\meta_run_buffer[#1]% processing only +\permanent\tolerant\protected\def\runMPbuffer[#1]% {\startnointerference\meta_process_buffer[#1]\stopnointerference} %D \macros @@ -887,12 +850,12 @@ %D In order to synchronize the main \TEX\ run and the runs local to \METAPOST, %D environments can be passed. -\unexpanded\def\startMPenvironment +\protected\def\startMPenvironment {\begingroup - \catcode\endoflineasciicode \ignorecatcode - \dosingleempty\meta_start_environment} + \catcode\endoflineasciicode\ignorecatcode + \meta_start_environment} -\def\meta_start_environment[#1]#2\stopMPenvironment +\tolerant\def\meta_start_environment[#1]#:#2\stopMPenvironment {\endgroup \edef\m_meta_option{#1} \ifx\m_meta_option\s!reset @@ -904,12 +867,12 @@ \fi \clf_mptexset{\detokenize{#2}}} -\let\stopMPenvironment\relax +\permanent\let\stopMPenvironment\relax -\unexpanded\def\resetMPenvironment +\protected\def\resetMPenvironment {\clf_mptexreset} -\unexpanded\def\useMPenvironmentbuffer[#1]% +\protected\def\useMPenvironmentbuffer[#1]% {\clf_mptexsetfrombuffer{#1}} %D This command takes \type {[reset]} as optional argument. @@ -926,56 +889,35 @@ %D %D The most simple case: -\unexpanded\def\startMPcode - {\dosinglegroupempty\meta_start_code} - -\let\stopMPcode\relax - -\def\meta_start_code - {\iffirstargument - \expandafter\meta_start_code_instance - \else - \expandafter\meta_start_code_standard - \fi} - -\def\meta_start_code_instance#1#2\stopMPcode +\permanent\tolerant\protected\def\startMPcode#=#:#2\stopMPcode {\begingroup \edef\currentMPinstance{#1}% + \ifempty\currentMPinstance + \let\currentMPinstance\defaultMPinstance + \fi \let\currentMPgraphicname\empty \edef\currentMPformat{\MPinstanceparameter\s!format}% \meta_enable_include \meta_process_graphic{#2}% \endgroup} -\def\meta_start_code_standard#1#2\stopMPcode - {\begingroup - \let\currentMPinstance\defaultMPinstance - \let\currentMPgraphicname\empty - \edef\currentMPformat{\MPinstanceparameter\s!format}% - \meta_process_graphic{#2}% - \endgroup} +\permanent\let\stopMPcode\relax -\unexpanded\def\MPcode - {\dodoublegroupempty\meta_code} +%D This one is not optimized because it's only used for small snippets, if it +%D is used at all. -\def\meta_code - {\ifsecondargument - \expandafter\meta_code_instance +\permanent\tolerant\protected\def\MPcode#=#:#*#=% + {\ifparameter#1\or + \meta_begin_graphic_group{#1}% + \meta_enable_include + \meta_process_graphic{#2}% + \meta_end_graphic_group \else - \expandafter\meta_code_standard + \let\currentMPinstance\defaultMPinstance + \meta_enable_include + \meta_process_graphic{#1}% \fi} -\def\meta_code_instance#1#2% - {\meta_begin_graphic_group{#1}% - \meta_enable_include - \meta_process_graphic{#2}% - \meta_end_graphic_group} - -\def\meta_code_standard#1#2% - {\let\currentMPinstance\defaultMPinstance - \meta_enable_include - \meta_process_graphic{#1}} - % a bit nasty (also needed for compatibility: % \startMPrun input mp-www.mp ; \stopMPrun @@ -986,25 +928,16 @@ \let\MPruninstance\defaultMPinstance -\unexpanded\def\useMPrun#1#2% name n +\permanent\protected\def\useMPrun#1#2% name n {\begingroup \def\MPaskedfigure{#2}% - \doifelsenothing{#1} - {\useMPgraphic{mprun}}% - {\useMPgraphic{#1}}% + \normalexpanded{\useMPgraphic{\iftok{#1}\emptytoks mprun\else#1\fi}}% \endgroup} -\unexpanded\def\startMPrun - {\dosinglegroupempty\meta_start_run} - -\def\meta_start_run#1#2\stopMPrun - {\iffirstargument - \startuseMPgraphic{#1}#2\stopuseMPgraphic - \else - \startuseMPgraphic{mprun}#2\stopuseMPgraphic - \fi} +\permanent\tolerant\protected\def\startMPrun#=#:#2\stopMPrun + {\normalexpanded{\startuseMPgraphic{\iftok{#1}\emptytoks mprun\else#1\fi}}#2\stopuseMPgraphic} -\let\stopMPrun\relax +\permanent\let\stopMPrun\relax %D The \type {\resetMPenvironment} is a quick way to erase %D the token list. @@ -1031,7 +964,7 @@ %D Loading specific \METAPOST\ related definitions is %D accomplished by: -\unexpanded\def\useMPlibrary[#1]{\clf_useMPlibrary{#1}} +\permanent\protected\def\useMPlibrary[#1]{\clf_useMPlibrary{#1}} %D \macros %D {setMPtext, MPtext, MPstring, MPbetex} @@ -1048,13 +981,13 @@ \installcorenamespace{mptext} -\unexpanded\def\setMPtext#1#2% todo : #1 must be made : safe - {\defconvertedargument\ascii{#2}% +\permanent\protected\def\setMPtext#1#2% todo : #1 must be made : safe + {\defconvertedargument\ascii{#2}% hm, kind of old fashioned, this \dodoglobal\letvalue{\??mptext#1}\ascii} -\def\MPtext #1{\begincsname\??mptext#1\endcsname\empty} -\def\MPstring#1{"\begincsname\??mptext#1\endcsname\empty"} -\def\MPbetex #1{btex \begincsname\??mptext#1\endcsname\space etex} +\permanent\def\MPtext #1{\begincsname\??mptext#1\endcsname\empty} +\permanent\def\MPstring#1{"\begincsname\??mptext#1\endcsname\empty"} +\permanent\def\MPbetex #1{btex \begincsname\??mptext#1\endcsname\space etex} %D In order to communicate conveniently with the \TEX\ engine, we introduce some %D typesetting variables. @@ -1139,11 +1072,11 @@ \to \everyMPgraphic \appendtoks - \let \# \letterhash - \let \_ \letterunderscore - \let \& \letterampersand - \let \{ \letteropenbrace - \let \} \letterclosebrace + \enforced\let\#\letterhash + \enforced\let\_\letterunderscore + \enforced\let\&\letterampersand + \enforced\let\{\letteropenbrace + \enforced\let\}\letterclosebrace \to \everyMPgraphic %D \macros @@ -1205,7 +1138,7 @@ %D You won't believe me if I tell you what funny side effects can occur. One took me %D over a day to uncover when processing the screen version of the \METAFUN\ manual. -\def\doifelseMPgraphic#1% +\permanent\def\doifelseMPgraphic#1% {\ifcsname\??mpgraphic #1\endcsname\expandafter\firstoftwoarguments \orelse \ifcsname\??mpgraphic o:#1\endcsname\expandafter\firstoftwoarguments \orelse \ifcsname\??mpgraphic e:#1\endcsname\expandafter\firstoftwoarguments \else @@ -1285,22 +1218,16 @@ %D %D \typebuffer \getbuffer -\unexpanded\def\startstaticMPfigure#1#2\stopstaticMPfigure +\permanent\protected\def\startstaticMPfigure#1#2\stopstaticMPfigure {\startreusableMPgraphic{\??mpstaticgraphic#1}#2\stopreusableMPgraphic} -\unexpanded\def\startstaticMPgraphic - {\dodoublegroupempty\meta_start_static_graphic} - -\def\meta_start_static_graphic#1#2#3\stopstaticMPgraphic +\permanent\tolerant\protected\def\startstaticMPgraphic#=#:#=#:#3\stopstaticMPgraphic {\startreusableMPgraphic{\??mpstaticgraphic#1}{#2}#3\stopreusableMPgraphic} -\let\stopstaticMPfigure \relax -\let\stopstaticMPgraphic\relax - -\unexpanded\def\usestaticMPfigure - {\dodoubleempty\meta_use_static_figure} +\permanent\let\stopstaticMPfigure \relax +\permanent\let\stopstaticMPgraphic\relax -\def\meta_use_static_figure[#1][#2]% +\permanent\tolerant\protected\def\usestaticMPfigure[#1]#*[#2]% {\ifsecondargument \scale[#2]{\reuseMPgraphic{\??mpstaticgraphic#1}}% \else @@ -1309,8 +1236,8 @@ %D Goody for preventing overflows: -%def\MPdivten[#1]{\withoutpt\the\dimexpr#1pt/10\relax} -\def\MPdivten[#1]{\thewithoutunit\dimexpr#1pt/10\relax} +%frozen\def\MPdivten[#1]{\withoutpt\the\dimexpr#1pt/10\relax} +\permanent\def\MPdivten[#1]{\thewithoutunit\dimexpr#1pt/10\relax} %D There is no way to distinguish the black color that you get when you issue a %D \type {draw} without color specification from a color that has an explicit black @@ -1384,9 +1311,9 @@ %D $(x,y) = (\MPrunset{point}{,})$ %D \stoptyping -\def\MPrunvar #1{\clf_mprunvar{#1}} \let\mprunvar\MPrunvar -\def\MPruntab#1#2{\clf_mpruntab{#1}#2\relax} \let\mpruntab\MPruntab % #2 is number -\def\MPrunset#1#2{\clf_mprunset{#1}{#2}} \let\mprunset\MPrunset +\permanent\def\MPrunvar #1{\clf_mprunvar{#1}} \let\mprunvar\MPrunvar +\permanent\def\MPruntab#1#2{\clf_mpruntab{#1}#2\relax} \let\mpruntab\MPruntab % #2 is number +\permanent\def\MPrunset#1#2{\clf_mprunset{#1}{#2}} \let\mprunset\MPrunset \prependtoks \clf_mppushvariables \to \everybeforepagebody \appendtoks \clf_mppopvariables \to \everyafterpagebody @@ -1396,22 +1323,13 @@ %D We also provide an outputless run: -\unexpanded\def\startMPcalculation +\permanent\tolerant\protected\def\startMPcalculation#=#:#2\stopMPcalculation {\begingroup \setbox\nextbox\hpack\bgroup - \dosinglegroupempty\meta_start_calculation} - -\let\stopMPcalculation\relax - -\def\meta_start_calculation - {\iffirstargument - \expandafter\meta_start_calculation_instance - \else - \expandafter\meta_start_calculation_standard - \fi} - -\def\meta_start_calculation_instance#1#2\stopMPcalculation - {\edef\currentMPinstance{#1}% + \edef\currentMPinstance{#1}% + \ifempty\currentMPinstance + \let\currentMPinstance\defaultMPinstance + \fi \let\currentMPgraphicname\empty \edef\currentMPformat{\MPinstanceparameter\s!format}% \meta_enable_include @@ -1419,13 +1337,7 @@ \egroup \endgroup} -\def\meta_start_calculation_standard#1#2\stopMPcalculation - {\let\currentMPinstance\defaultMPinstance - \let\currentMPgraphicname\empty - \edef\currentMPformat{\MPinstanceparameter\s!format}% - \meta_process_graphic{#2;draw origin}% - \egroup - \endgroup} +\permanent\let\stopMPcalculation\relax %D \macros %D {setupMPgraphics} @@ -1466,9 +1378,9 @@ %D Some more helpers (see \type {meta-grd.mkiv} for an example of usage): -\def\MPdpar#1#2{\the\dimexpr#1#2\relax\empty} -\def\MPnpar#1#2{\the\numexpr#1#2\relax\empty} -\def\MPspar#1#2{"#1#2"} +\permanent\def\MPdpar#1#2{\the\dimexpr#1#2\relax\empty} +\permanent\def\MPnpar#1#2{\the\numexpr#1#2\relax\empty} +\permanent\def\MPspar#1#2{"#1#2"} %D Done. diff --git a/tex/context/base/mkiv/meta-mac.mkxl b/tex/context/base/mkiv/meta-mac.mkxl index 7ced2aff9..76b7396ae 100644 --- a/tex/context/base/mkiv/meta-mac.mkxl +++ b/tex/context/base/mkiv/meta-mac.mkxl @@ -13,40 +13,16 @@ \unprotect -\unexpanded\def\defineMPparameterset[#1]{\clf_lmt_parameters_define{#1}} -\unexpanded\def\presetMPparameters [#1]{\clf_lmt_parameters_preset{#1}} -\unexpanded\def\resetMPparameters [#1]{\clf_lmt_parameters_reset {#1}} +\permanent\protected\def\defineMPparameterset[#1]{\clf_lmt_parameters_define{#1}} +\permanent\protected\def\presetMPparameters [#1]{\clf_lmt_parameters_preset{#1}} +\permanent\protected\def\resetMPparameters [#1]{\clf_lmt_parameters_reset {#1}} -% \unexpanded\def\useMPgraphic -% {\doifnextoptionalelse\meta_use_MP_graphic_yes\meta_use_MP_graphic_nop} - -% \def\meta_use_MP_graphic_nop -% {\dodoublegroupempty\meta_use_graphic} - -% \def\meta_use_MP_graphic_yes -% {\dodoubleempty\meta_use_graphic_new} - -% \def\meta_use_graphic_new[#1][#2]% -% {\begingroup -% % If really needed weh can use grouplevel but normally these graphics are -% % not nested. -% \clf_lmt_parameters_preset{#1}[#2]% -% \meta_use_graphic{#1}{}% -% \clf_lmt_parameters_reset{#1}% -% \endgroup} - -\unexpanded\def\useMPmacro - {\dotripleempty\meta_use_macro} - -\def\meta_use_macro[#1][#2][#3]% - {\ifthirdargument - \meta_begin_graphic_group{#1}% +\permanent\tolerant\protected\def\useMPmacro[#1]#*[#2]#*[#3]% + {\ifarguments\or + \let\currentMPinstance\defaultMPinstance \meta_enable_include - \clf_lmt_parameters_preset{#2}[#3]% - \meta_process_graphic{lmt_#2;}% - \clf_lmt_parameters_reset{#2}% - \meta_end_graphic_group - \orelse\ifsecondargument + \meta_process_graphic{lmt_#1;}% + \or \doifelseassignment{#2} {\let\currentMPinstance\defaultMPinstance \meta_enable_include @@ -57,10 +33,13 @@ \meta_enable_include \meta_process_graphic{lmt_#1;}% \meta_end_graphic_group}% - \else - \let\currentMPinstance\defaultMPinstance + \or + \meta_begin_graphic_group{#1}% \meta_enable_include - \meta_process_graphic{lmt_#1;}% + \clf_lmt_parameters_preset{#2}[#3]% + \meta_process_graphic{lmt_#2;}% + \clf_lmt_parameters_reset{#2}% + \meta_end_graphic_group \fi} \protect diff --git a/tex/context/base/mkiv/mlib-pdf.lua b/tex/context/base/mkiv/mlib-pdf.lua index 3945ffcfe..e737b5d86 100644 --- a/tex/context/base/mkiv/mlib-pdf.lua +++ b/tex/context/base/mkiv/mlib-pdf.lua @@ -363,18 +363,20 @@ end local stack = { } local function pushproperties(figure) + -- maybe there will be getters in lmtx local boundingbox = figure:boundingbox() + local slot = figure:charcode() or 0 local properties = { llx = boundingbox[1], lly = boundingbox[2], urx = boundingbox[3], ury = boundingbox[4], - slot = figure:charcode(), + slot = slot, width = figure:width(), height = figure:height(), depth = figure:depth(), - italic = figure:italcorr(), - number = figure:charcode() or 0, + italic = figure:italcorr(), -- figure:italic() in lmtx + number = slot, } insert(stack,properties) metapost.properties = properties diff --git a/tex/context/base/mkiv/mlib-pdf.mkxl b/tex/context/base/mkiv/mlib-pdf.mkxl index 763e7ecdd..90a5b5a86 100644 --- a/tex/context/base/mkiv/mlib-pdf.mkxl +++ b/tex/context/base/mkiv/mlib-pdf.mkxl @@ -30,7 +30,7 @@ \ifdefined\MPbox \else \newbox \MPbox \fi -\unexpanded\def\setMPboundingbox#1#2#3#4% at some point we might pass them as base or scaled points +\permanent\protected\def\setMPboundingbox#1#2#3#4% at some point we might pass them as base or scaled points {\global\MPllx #1\onebasepoint \global\MPlly #2\onebasepoint \global\MPurx #3\onebasepoint @@ -38,7 +38,7 @@ \global\MPwidth \dimexpr\MPurx-\MPllx\relax \global\MPheight\dimexpr\MPury-\MPlly\relax} -\unexpanded\def\resetMPboundingbox +\permanent\protected\def\resetMPboundingbox {\global\MPwidth \zeropoint \global\MPheight\zeropoint \global\MPllx \zeropoint @@ -48,8 +48,8 @@ \let\popMPboundingbox\relax -\unexpanded\def\pushMPboundingbox - {\edef\popMPboundingbox +\permanent\protected\def\pushMPboundingbox + {\enforced\permanent\protected\edef\popMPboundingbox {\global\MPwidth \the\MPwidth \global\MPheight\the\MPheight \global\MPllx \the\MPllx @@ -60,14 +60,14 @@ % we need to combine these -\unexpanded\def\repositionMPboxindeed +\permanent\protected\def\repositionMPboxindeed {\setbox\MPbox\hpack\bgroup \kern-\MPllx \raise-\MPlly \box\MPbox \egroup} -\unexpanded\def\repositionMPbox +\permanent\protected\def\repositionMPbox {\ifzeropt\MPllx \ifzeropt\MPlly % okay @@ -78,20 +78,9 @@ \repositionMPboxindeed \fi} -\unexpanded\def\finalizeMPbox - {\repositionMPbox - \setbox\MPbox\vpack to \MPheight\bgroup - \vfill - \hsize\MPwidth - \smashbox\MPbox - \box\MPbox - \egroup - \wd\MPbox\MPwidth - \ht\MPbox\MPheight} - % combined -\unexpanded\def\finalizeMPbox +\permanent\protected\def\finalizeMPbox {\boxxoffset\MPbox-\MPllx\relax \boxyoffset\MPbox\dimexpr\boxyoffset\MPbox-\MPheight-\MPlly\relax \wd\MPbox\MPwidth @@ -99,9 +88,9 @@ % MPLIB specific: -\def\MPLIBtoPDF{\clf_mpflushliteral} % expanded +\permanent\def\MPLIBtoPDF{\clf_mpflushliteral} % expanded -\unexpanded\def\startMPLIBtoPDF#1#2#3#4% +\permanent\protected\def\startMPLIBtoPDF#1#2#3#4% {\meta_process_graphic_figure_start \dostarttagged\t!mpgraphic\empty \naturalhpack attr \imageattribute \plusone \bgroup @@ -111,7 +100,7 @@ % \forgetall % already done elsewhere \noindent} % forces the proper cm in the backend -\unexpanded\def\stopMPLIBtoPDF +\permanent\protected\def\stopMPLIBtoPDF {\egroup \finalizeMPbox \box\MPbox @@ -119,7 +108,7 @@ \dostoptagged \meta_process_graphic_figure_stop} -\def\MPLIBflushreset % This can (will) move to the Lua end. +\permanent\protected\def\MPLIBflushreset % This can (will) move to the Lua end. {\clf_mpflushreset} %D Kind of special: @@ -136,19 +125,21 @@ % \directMPgraphic{input "test.mp" ;} % \stoptext -\let\normalstartMPLIBtoPDF\startMPLIBtoPDF -\let\normalstopMPLIBtoPDF \stopMPLIBtoPDF +\aliased\let\normalstartMPLIBtoPDF\startMPLIBtoPDF +\aliased\let\normalstopMPLIBtoPDF \stopMPLIBtoPDF + +\permanent\protected\def\directstartMPLIBtoPDF{\startTEXpage\normalstartMPLIBtoPDF} +\permanent\protected\def\directstopMPLIBtoPDF {\normalstopMPLIBtoPDF\stopTEXpage} -\unexpanded\def\directstartMPLIBtoPDF{\startTEXpage\normalstartMPLIBtoPDF} -\unexpanded\def\directstopMPLIBtoPDF {\normalstopMPLIBtoPDF\stopTEXpage} +% can become \permanent\protected\def\directMPgraphic#=#*#=% but best test first -\unexpanded\def\directMPgraphic +\permanent\protected\def\directMPgraphic {\dodoublegroupempty\mlib_direct_graphic} \def\mlib_direct_graphic#1#2% makes pages (todo: make boxes) {\meta_begin_graphic_group{#1}% - \let\startMPLIBtoPDF\directstartMPLIBtoPDF - \let\stopMPLIBtoPDF \directstopMPLIBtoPDF + \enforced\let\startMPLIBtoPDF\directstartMPLIBtoPDF + \enforced\let\stopMPLIBtoPDF \directstopMPLIBtoPDF \meta_start_current_graphic \forgetall \edef\p_extensions{\MPinstanceparameter\s!extensions}% diff --git a/tex/context/base/mkiv/mlib-pps.lua b/tex/context/base/mkiv/mlib-pps.lua index e34bfe5f9..140acd185 100644 --- a/tex/context/base/mkiv/mlib-pps.lua +++ b/tex/context/base/mkiv/mlib-pps.lua @@ -25,7 +25,7 @@ local setmacro = interfaces.setmacro local texsetbox = tex.setbox local textakebox = tex.takebox -- or: nodes.takebox -local texruntoks = tex.runtoks +local texrunlocal = tex.runlocal local copy_list = node.copy_list local flush_list = node.flush_list local setmetatableindex = table.setmetatableindex @@ -858,7 +858,7 @@ local tx_reset, tx_process do mp_t = nil top.texstrings[mp_index] = str top.texregimes[mp_index] = regime or -1 - texruntoks("mptexttoks") + texrunlocal("mptexttoks") local box = textakebox("mptextbox") top.textexts[mp_target] = box mp.triplet(bp*box.width,bp*box.height,bp*box.depth) @@ -922,7 +922,7 @@ local tx_reset, tx_process do if overload then top.texstrings[mp_index] = map.template or map.label or "error" top.texregimes[mp_index] = regime or -1 - texruntoks("mptexttoks") + texrunlocal("mptexttoks") local box = textakebox("mptextbox") or new_hlist() width = bp * box.width where = overload.where @@ -930,7 +930,7 @@ local tx_reset, tx_process do -- the real text top.texstrings[mp_index] = overload and overload.text or text or "error" top.texregimes[mp_index] = regime or -1 - texruntoks("mptexttoks") + texrunlocal("mptexttoks") local box = textakebox("mptextbox") or new_hlist() local twd = bp * box.width local tht = bp * box.height @@ -1047,7 +1047,7 @@ local tx_reset, tx_process do local mp_hash = prescript.tx_cache local box if mp_hash == "no" then - texruntoks("mptexttoks") + texrunlocal("mptexttoks") box = textakebox("mptextbox") else local cache = data.texhash @@ -1080,7 +1080,7 @@ local tx_reset, tx_process do if box then box = copy_list(box) else - texruntoks("mptexttoks") + texrunlocal("mptexttoks") box = textakebox("mptextbox") cache[mp_hash] = box end @@ -1163,7 +1163,7 @@ local gt_reset, gt_process do if not graphics[index] then mp_index = index mp_str = str - texruntoks("mpgraphictexttoks") + texrunlocal("mpgraphictexttoks") end end @@ -1584,7 +1584,7 @@ local ot_reset, ot_process do mp_index = index mp_kind = kind mp_str = str - texruntoks("mpoutlinetoks") + texrunlocal("mpoutlinetoks") end end diff --git a/tex/context/base/mkiv/mult-aux.mkxl b/tex/context/base/mkiv/mult-aux.mkxl index 1df5bcf24..c1c99edbd 100644 --- a/tex/context/base/mkiv/mult-aux.mkxl +++ b/tex/context/base/mkiv/mult-aux.mkxl @@ -21,7 +21,7 @@ \unprotect -\edef\??empty{\Uchar25} \letvalue{\Uchar25}\empty % hex 19 +\immutable\edef\??empty{\Uchar25} \immutable\letvalue{\Uchar25}\empty % hex 19 % \edef\s!parent{\Uchar29} % inlining is ugly, a tiny bit faster, but neglectable on a run @@ -174,26 +174,17 @@ \let\m_mult_interfaces_namespace\empty -\def\mult_interfaces_get_parameters#1[#2% - {\if\noexpand#2]% - \expandafter\gobbleoneargument - \else - \def\m_mult_interfaces_namespace{#1}% - \expandafter\mult_interfaces_get_parameters_indeed - \fi#2} +\def\mult_interfaces_get_parameters#1[% + {\def\m_mult_interfaces_namespace{#1}% + \futureexpandis]\gobbleoneargument\mult_interfaces_get_parameters_indeed} -\def\mult_interfaces_get_parameters_indeed#1]% namespace already set +\def\mult_interfaces_get_parameters_indeed#1]% {\mult_interfaces_get_parameters_item#1\ignorearguments\ignorearguments} -\def\mult_interfaces_get_parameters_item_next - {\expandafterspaces\mult_interfaces_get_parameters_item} - -\def\mult_interfaces_get_parameters_item#1,% - {\ifarguments - % done - \else +\def\mult_interfaces_get_parameters_item#*#1,% + {\ifarguments \else \mult_interfaces_get_parameters_item_okay#1,\ignorearguments - \expandafter\mult_interfaces_get_parameters_item_next + \expandafter\mult_interfaces_get_parameters_item \fi} \def\mult_interfaces_get_parameters_item_okay#1=#2,% @@ -219,25 +210,16 @@ \or \mult_interfaces_get_parameters_item_error \else - \expandafter\def\csname\m_mult_interfaces_namespace#1\endcsname{#2}% + \defcsname\m_mult_interfaces_namespace#1\endcsname{#2}% \fi} -% \def\mult_interfaces_get_parameters_item_error#0\csname#2#3\endcsname#0% -% {\if,#3\else\mult_interfaces_get_parameters_error_indeed{#2}{#3}\fi} - - \def\mult_interfaces_get_parameters_item_error#-\csname#1#2\endcsname#-% + \def\mult_interfaces_get_parameters_item_error#-\defcsname#1#2\endcsname#-% {\if,#2\else\mult_interfaces_get_parameters_error_indeed{#1}{#2}\fi} \stopinterface %D Used? -% \def\mult_check_for_assignment_indeed#0=#2#0^^^^0004% -% {\if#2^^^^0003\assignmentfalse\else\assignmenttrue\fi} -% -% \def\mult_check_for_assignment_indeed_begin_#0=#2#0^^^^0004% -% {\if#2^^^^0003} - \def\mult_check_for_assignment_indeed#-=#1#-^^^^0004% {\if#1^^^^0003\assignmentfalse\else\assignmenttrue\fi} @@ -258,20 +240,13 @@ %D and that only the high level setup commands are used with language specific %D interfaces. -% \protected\def\mult_interfaces_let #1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} -% \protected\def\mult_interfaces_lete#1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty} -% \protected\def\mult_interfaces_def #1#2{\expandafter\def \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} -% \protected\def\mult_interfaces_edef#1#2{\expandafter\edef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} -% \protected\def\mult_interfaces_gdef#1#2{\expandafter\gdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} -% \protected\def\mult_interfaces_xdef#1#2{\expandafter\xdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} - % \startinterface english - \protected\def\mult_interfaces_let #1#2{\expandafter \let\csname#1#2\endcsname} - \protected\def\mult_interfaces_lete#1#2{\expandafter \let\csname#1#2\endcsname\empty} - \protected\def\mult_interfaces_def #1#2{\expandafter \def\csname#1#2\endcsname} - \protected\def\mult_interfaces_edef#1#2{\expandafter\edef\csname#1#2\endcsname} - \protected\def\mult_interfaces_gdef#1#2{\expandafter\gdef\csname#1#2\endcsname} - \protected\def\mult_interfaces_xdef#1#2{\expandafter\xdef\csname#1#2\endcsname} + \protected\def\mult_interfaces_let #1#2{\letcsname#1#2\endcsname} + \protected\def\mult_interfaces_lete#1#2{\letcsname#1#2\endcsname\empty} + \protected\def\mult_interfaces_def #1#2{\defcsname#1#2\endcsname} + \protected\def\mult_interfaces_edef#1#2{\edefcsname#1#2\endcsname} + \protected\def\mult_interfaces_gdef#1#2{\globaldef\csname#1#2\endcsname} + \protected\def\mult_interfaces_xdef#1#2{\globaledef\csname#1#2\endcsname} % \stopinterface %D Do, we only interface the assignment definition: @@ -279,7 +254,7 @@ \protected\def\mult_interfaces_adef#1#2{\expandafter\def \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} \startinterface english - \protected\def\mult_interfaces_adef#1#2{\expandafter \def\csname#1#2\endcsname} + \protected\def\mult_interfaces_adef#1#2{\defcsname#1#2\endcsname} \stopinterface % the commented detokenized variant that backtracks ... needs testing usage first @@ -299,19 +274,17 @@ \def\mult_interfaces_detokenize{\expandafter\expandafter\expandafter\detokenize\expandafter\expandafter\expandafter} \protected\def\mult_interfaces_install_parameter_handler#1#2#3#4#5#6#7#8#9% inlining \csname*\endcsname is more efficient (#3 and #6 only) - {\ifx#2\relax\let#2\empty\fi % it is hardly faster but produces less expansion tracing - \def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}% - \def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}% - %\def#5##1##2{\ifx##1\relax\??empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ? - %\def#5##1##2{\ifx##1\relax\??empty\else#4##1{##2}\fi}% is {} needed around ##1 ? - %\def#5##1##2{\ifx##1\relax^^^^0019\else#4##1{##2}\fi}% is {} needed around ##1 ? - \edef#5##1##2{\noexpand\ifx##1\relax\??empty\noexpand\else\noexpand#4##1{##2}\noexpand\fi}% is {} needed around ##1 ? - \def#6##1##2{\csname\ifcsname#1##1:##2\endcsname#1##1:##2\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}% - \def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack - \def#8##1{\begincsname#1#2:##1\endcsname} - \def#9##1##2{\expandafter\let\expandafter##1\csname\ifcsname#1#2:##2\endcsname#1#2:##2\else\expandafter#5\csname#1#2:\s!parent\endcsname{##2}\fi\endcsname}} - -\protected\def\installparameterhandler#1#2% + {\ifx#2\relax\let#2\empty\fi % it is hardly faster but produces less expansion tracing + \frozen\def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}% + \frozen\def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}% + \frozen\edef#5##1##2{\noexpand\ifx##1\relax\??empty\noexpand\else\noexpand#4##1{##2}\noexpand\fi}% is {} needed around ##1 ? + \frozen\def#6##1##2{\csname\ifcsname#1##1:##2\endcsname#1##1:##2\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}% + \frozen\def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack + \frozen\def#8##1{\begincsname#1#2:##1\endcsname}% + % TODO + \frozen\def#9##1##2{\expandafter\let\expandafter##1\csname\ifcsname#1#2:##2\endcsname#1#2:##2\else\expandafter#5\csname#1#2:\s!parent\endcsname{##2}\fi\endcsname}} + +\permanent\protected\def\installparameterhandler#1#2% {\normalexpanded {\mult_interfaces_install_parameter_handler {\noexpand#1}% \??aa @@ -325,10 +298,10 @@ \expandafter\noexpand\csname letfrom#2parameter\endcsname}} % strict#2parameter is gone \protected\def\mult_interfaces_install_root_parameter_handler#1#2#3% - {\def#2##1{\detokenize\expandafter\expandafter\expandafter{\csname#1:##1\endcsname}}% always root - \def#3##1{\begincsname#1:##1\endcsname}} + {\frozen\def#2##1{\detokenize\expandafter\expandafter\expandafter{\csname#1:##1\endcsname}}% always root + \frozen\def#3##1{\begincsname#1:##1\endcsname}} -\protected\def\installrootparameterhandler#1#2% +\permanent\protected\def\installrootparameterhandler#1#2% {\normalexpanded {\mult_interfaces_install_root_parameter_handler {\noexpand#1}% \??aa @@ -337,18 +310,17 @@ \protected\def\mult_interfaces_install_parameter_hash_handler#1#2#3#4#5#6#7#8#9% {\ifx#2\relax\let#2\empty\fi - \def#3##1{#1#4{#1#2}{##1}:}% leading #1 was missing .. is this one used? - \def#4##1##2{\ifcsname##1:##2\endcsname##1\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}% - %\def#5##1##2{\ifx##1\relax\else#4{##1}{##2}\fi}% - \def#5##1##2{\ifx##1\relax\else#4##1{##2}\fi}% - \def#6{#1#2:}% - \def#7##1{#1##1:}% - %\def#8{\ifx#2\empty\orelse\ifcsname#1#2:\s!parent\endcsname\else\expandafter\let\csname#1#2:\s!parent\endcsname#1\fi}% - \def#8{\ifempty#2\orelse\ifcsname#1#2:\s!parent\endcsname\else\expandafter\let\csname#1#2:\s!parent\endcsname#1\fi}% - \protected\def#9##1{\expandafter\edef\csname#1##1:\s!parent\endcsname{#1#2}}} - -\protected\def\installparameterhashhandler#1#2% - {\expandafter\let\csname#2namespace\endcsname#1% + \frozen\def#3##1{#1#4{#1#2}{##1}:}% leading #1 was missing .. is this one used? + \frozen\def#4##1##2{\ifcsname##1:##2\endcsname##1\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}% + \frozen\def#5##1##2{\ifx##1\relax\else#4##1{##2}\fi}% + \frozen\def#6{#1#2:}% + \frozen\def#7##1{#1##1:}% + \frozen\def#8{\ifempty#2\orelse\ifcsname#1#2:\s!parent\endcsname\else\letcsname#1#2:\s!parent\endcsname#1\fi}% + \frozen\protected\def#9##1{\edefcsname#1##1:\s!parent\endcsname{#1#2}}} + +\permanent\protected\def\installparameterhashhandler#1#2% +% {\expandafter\let\csname#2namespace\endcsname#1% + {\letcsname#2namespace\endcsname#1% \normalexpanded {\mult_interfaces_install_parameter_hash_handler {\noexpand#1}% \??aa @@ -365,23 +337,16 @@ % todo: inline the def/let -% \protected\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6% -% {\ifx#2\relax\let#2\empty\fi -% \protected\def#3{\mult_interfaces_def {#1#2:}}% ##1 {##2} (braces are mandate) -% \protected\def#4{\mult_interfaces_edef{#1#2:}}% ##1 {##2} (braces are mandate) -% \protected\def#5{\mult_interfaces_let {#1#2:}}% ##1 ##2 -% \protected\def#6{\mult_interfaces_lete{#1#2:}}}% ##1 -% % \startinterface english \protected\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6% {\ifx#2\relax\let#2\empty\fi - \protected\def#3##1{\expandafter \def\csname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate) - \protected\def#4##1{\expandafter\edef\csname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate) - \protected\def#5##1{\expandafter \let\csname#1#2:##1\endcsname}% ##1 ##2 - \protected\def#6##1{\expandafter \let\csname#1#2:##1\endcsname\empty}}% ##1 + \frozen\protected\def#3##1{\defcsname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate) + \frozen\protected\def#4##1{\edefcsname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate) + \frozen\protected\def#5##1{\letcsname#1#2:##1\endcsname}% ##1 ##2 + \frozen\protected\def#6##1{\letcsname#1#2:##1\endcsname\empty}}% ##1 % \stopinterface -\protected\def\installparametersethandler#1#2% +\permanent\protected\def\installparametersethandler#1#2% {\normalexpanded {\mult_interfaces_install_parameter_set_handler {\noexpand#1}% \??aa @@ -398,23 +363,19 @@ \let\currentcolorparameter\empty \protected\def\mult_interfaces_install_style_and_color_handler#1#2#3#4% - {\protected\def#2##1##2% style color + {\frozen\protected\def#2##1##2% style color {\edef\currentstyleparameter{#1{##1}}% this name is public (can also set color e.g. in underline) - %\ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi \ifempty\currentstyleparameter\else\dousecurrentstyleparameter\fi \edef\currentcolorparameter{#1{##2}}% this name is public (so we do this after the style switch) - %\ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}% \ifempty\currentcolorparameter\else\dousecurrentcolorparameter\fi}% - \protected\def#3##1% style + \frozen\protected\def#3##1% style {\edef\currentstyleparameter{#1{##1}}% this name is public - %\ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi}% \ifempty\currentstyleparameter\else\dousecurrentstyleparameter\fi}% - \protected\def#4##1% color + \frozen\protected\def#4##1% color {\edef\currentcolorparameter{#1{##1}}% this name is public - %\ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}}% \ifempty\currentcolorparameter\else\dousecurrentcolorparameter\fi}} -\protected\def\installstyleandcolorhandler#1#2% +\permanent\protected\def\installstyleandcolorhandler#1#2% {\normalexpanded {\mult_interfaces_install_style_and_color_handler \expandafter\noexpand\csname #2parameter\endcsname @@ -424,123 +385,107 @@ \let\definehandlerparent\empty -% \def\mult_check_for_parent#1#2#3#4% -% {\ifcsname#1#4:\s!parent\endcsname \else \ifx#4\empty \else -% \writestatus\m!system{error: invalid parent #4 for #3, #4 defined too (best check it)}% -% \expandafter\edef\csname#1#4:\s!parent\endcsname{#2}% -% \fi \fi} - \def\mult_check_for_parent#1#2#3#4% {\ifcsname#1#4:\s!parent\endcsname\orelse\ifx#4\empty\else \writestatus\m!system{error: invalid parent #4 for #3, #4 defined too (best check it)}% - \expandafter\edef\csname#1#4:\s!parent\endcsname{#2}% +% \expandafter\edef\csname#1#4:\s!parent\endcsname{#2}% + \edefcsname#1#4:\s!parent\endcsname{#2}% \fi} -%def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\space\fi} -%def\getparentchain #1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi} -%def\getcurrentparentchain#1#2{\ifcsname#1#2:\s!chain\endcsname\csname#1#2:\s!chain\endcsname\fi} - \def\mult_interfaces_chain#1#2{\ifcsname#1#2:\s!chain\endcsname\lastnamedcs\space\fi} \def\getparentchain #1#2{\begincsname#1#2:\s!chain\endcsname} \def\getcurrentparentchain#1#2{\begincsname#1#2:\s!chain\endcsname} -\protected\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8#9% why is \expanded still needed in clones - {\ifx#4\relax\let#4\empty\fi % see \defineregister - \protected\def#2{\dotripleempty#5}% +\protected\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8% why is \expanded still needed in clones + {\ifx#4\relax\let#4\empty\fi % see \defineregister + \newtoks#5% \newtoks#6% - \newtoks#7% - \protected\def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child] - {\let#9#4% - \edef#4{##1}% - \ifthirdargument - \the#6% predefine - \edef#8{##2}% - \mult_check_for_parent{#1}{#3}#4#8% - \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% - \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}% - \mult_interfaces_get_parameters{#1#4:}[##3]% - \orelse\ifsecondargument - \the#6% predefine + \frozen\tolerant\protected\def#2[##1]##*[##2]##*[##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child] + {\let#8#4% + % watch out: no \edef#4{##1} before the ifarguments because #1 can have macros + \ifarguments + \let#4\empty + \the#5% predefine + \let#7\empty + \letcsname#1#4:\s!chain\endcsname\empty + \edefcsname#1#4:\s!parent\endcsname{#3}% + \or + \edef#4{##1}% + \the#5% predefine + \let#7\empty + \edefcsname#1#4:\s!chain\endcsname{##1}% + \edefcsname#1#4:\s!parent\endcsname{#3}% + \or + \edef#4{##1}% + \the#5% predefine \relax - %\ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##2}=^^^^0003^^^^0003^^^^0004% -% \ifcondition\mult_aux_no_assignment_indeed##2\ignorearguments -% \edef#8{##2}% -% \mult_check_for_parent{#1}{#3}#4#8% -% \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% -% \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}% -% \else -% \let#8\empty -% \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}% -% \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}% -% \mult_interfaces_get_parameters{#1#4:}[##2]% -% \fi \ifhastok={##2}% - \let#8\empty - \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}% - \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}% + \let#7\empty + \edefcsname#1#4:\s!chain\endcsname{##1}% + \edefcsname#1#4:\s!parent\endcsname{#3}% \mult_interfaces_get_parameters{#1#4:}[##2]% \else - \edef#8{##2}% - \ifempty#8% - \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}% - \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}% + \edef#7{##2}% + \ifempty#7% + \edefcsname#1#4:\s!chain\endcsname{##1}% + \edefcsname#1#4:\s!parent\endcsname{#3}% \else - \mult_check_for_parent{#1}{#3}#4#8% - \expandafter\edef\csname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% - \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}% + \mult_check_for_parent{#1}{#3}#4#7% + \edefcsname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% + \edefcsname#1#4:\s!parent\endcsname{#1##2}% \fi \fi - \else - \the#6% predefine - \let#8\empty - \expandafter\edef\csname#1#4:\s!chain\endcsname{##1}% - \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}% + \or + \edef#4{##1}% + \the#5% predefine + \edef#7{##2}% + \mult_check_for_parent{#1}{#3}#4#7% + \edefcsname#1#4:\s!chain\endcsname{\mult_interfaces_chain#1{##2}##1}% + \edefcsname#1#4:\s!parent\endcsname{#1##2}% + \mult_interfaces_get_parameters{#1#4:}[##3]% \fi - \the#7% - \let#4#9}} + \the#6% + \let#4#8}} -\protected\def\installdefinehandler#1#2#3% +\permanent\protected\def\installdefinehandler#1#2#3% {\normalexpanded {\mult_interfaces_install_define_handler {\noexpand#1}% \??aa \expandafter\noexpand\csname define#2\endcsname {\noexpand#3}% root \expandafter\noexpand\csname current#2\endcsname - \expandafter\noexpand\csname define_#2\endcsname % semi-public \expandafter\noexpand\csname everypreset#2\endcsname \expandafter\noexpand\csname everydefine#2\endcsname \expandafter\noexpand\csname current#2parent\endcsname \expandafter\noexpand\csname saved_defined_#2\endcsname}} -\protected\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8#9% +\protected\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8% {\ifx#3\relax\let#3\empty\fi - \protected\def#2{\dodoubleempty#4}% - \protected\def#6{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it - \newtoks#5% - \newtoks#8% - \protected\def#4[##1][##2]% maybe helper - {\let#7#3% - \ifsecondargument - \def#9####1% we will have a simple one as well + \protected\def#5{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it + \newtoks#4% + \newtoks#7% + \frozen\tolerant\protected\def#2[##1]##*[##2]% maybe helper + {\let#6#3% + \ifnum\lastarguments=\plustwo + \def#8####1% we will have a simple one as well {\edef#3{####1}% \mult_interfaces_get_parameters{#1#3:}[##2]% - \the#5}% - \processcommalist[##1]#9% + \the#4}% + \processcommalist[##1]#8% \else \let#3\empty \mult_interfaces_get_parameters{#1:}[##1]% - \the#5% + \the#4% \fi - \let#3#7% - \the#8}} + \let#3#6% + \the#7}} -\protected\def\installsetuphandler#1#2% +\permanent\protected\def\installsetuphandler#1#2% {\normalexpanded {\mult_interfaces_install_setup_handler {\noexpand#1}% \??aa \expandafter\noexpand\csname setup#2\endcsname \expandafter\noexpand\csname current#2\endcsname - \expandafter\noexpand\csname setup_#2\endcsname % semi-public \expandafter\noexpand\csname everysetup#2\endcsname \expandafter\noexpand\csname setupcurrent#2\endcsname \expandafter\noexpand\csname saved_setup_current#2\endcsname @@ -552,10 +497,9 @@ \let\doingrootsetnamed \plusthree % \setuplayout[name] \let\doingrootsetroot \plusfour % \setuplayout -\protected\def\mult_interfaces_install_switch_setup_handler_a#1#2#3#4#5% - {\ifx#3\relax\let#3\empty\fi - \protected\def#2{\dodoubleempty#4}% - \protected\def#5{\mult_interfaces_get_parameters{#1#3:}}} +\protected\def\mult_interfaces_install_switch_setup_handler_a#1#2#3% + {\ifx#2\relax\let#2\empty\fi + \frozen\protected\def#3{\mult_interfaces_get_parameters{#1#2:}}} \protected\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9% {\newtoks#5% @@ -563,37 +507,15 @@ \newtoks#8% \newtoks#9% \ifx#6\relax\let#6\empty\fi - \protected\def#4[##1][##2]% maybe helper - {\ifsecondargument % no commalist here - % \setuplayout[whatever][key=value] - \let#7#3% - \let#6#3% - \edef#3{##1}% - #2\doingrootsetupnamed - \mult_interfaces_get_parameters{#1#3:}[##2]% + \frozen\tolerant\protected\def#4[##1]##*[##2]% maybe helper + {\ifarguments + % \setuplayout + \let#6#3% % previous becomes current + \let#3\empty % current becomes empty + #2\doingrootsetroot \the#5% - \ifx#3#6\the#8\fi % only switchsetups if previous == current - \let#3#7% - \orelse\iffirstargument - %\ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##1}=^^^^0003^^^^0003^^^^0004% -% \ifcondition\mult_aux_no_assignment_indeed##1\ignorearguments -% % \setuplayout[whatever] -% \let#6#3% % previous becomes current -% \edef#3{##1}% this will catch reset so one needs to test for it -% #2\doingrootsetnamed -% \the#5% % we can check for previous vs current -% \the#8% switchsetups -% \else -% % \setuplayout[key=value] -% \let#7#3% -% \let#6#3% -% \let#3\empty -% #2\doingrootsetuproot -% \mult_interfaces_get_parameters{#1:}[##1]% -% \the#5% -% \the#8% switchsetups -% \let#3#7% -% \fi + \the#8% switchsetups + \or \ifhastok={##1}% % \setuplayout[key=value] \let#7#3% @@ -620,111 +542,113 @@ \the#8% switchsetups \fi \fi - \else - % \setuplayout - \let#6#3% % previous becomes current - \let#3\empty % current becomes empty - #2\doingrootsetroot + \or + % \setuplayout[whatever][key=value] + \let#7#3% + \let#6#3% + \edef#3{##1}% + #2\doingrootsetupnamed + \mult_interfaces_get_parameters{#1#3:}[##2]% \the#5% - \the#8% switchsetups + \ifx#3#6\the#8\fi % only switchsetups if previous == current + \let#3#7% \fi #2\zerocount % mode is always zero at the end \the#9}} -\protected\def\installswitchsetuphandler#1#2% +\permanent\protected\def\installswitchsetuphandler#1#2% {\normalexpanded {\mult_interfaces_install_switch_setup_handler_a {\noexpand#1}% \??aa - \expandafter\noexpand\csname setup#2\endcsname \expandafter\noexpand\csname current#2\endcsname - \expandafter\noexpand\csname setup_#2\endcsname % semi-public \expandafter\noexpand\csname setupcurrent#2\endcsname \mult_interfaces_install_switch_setup_handler_b {\noexpand#1}% \??aa \expandafter\noexpand\csname #2setupmode\endcsname \expandafter\noexpand\csname current#2\endcsname - \expandafter\noexpand\csname setup_#2\endcsname % semi-public + \expandafter\noexpand\csname setup#2\endcsname \expandafter\noexpand\csname everysetup#2\endcsname \expandafter\noexpand\csname previous#2\endcsname \expandafter\noexpand\csname saved_setup_current#2\endcsname \expandafter\noexpand\csname everyswitch#2\endcsname \expandafter\noexpand\csname everysetup#2root\endcsname}} -\protected\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8#9% +\protected\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8% {\ifx#3\relax\let#3\empty\fi - \protected\def#2{\dotripleempty#4}% - \protected\def#6{\mult_interfaces_get_parameters{#1#3:}}% - \newtoks#5% - \def#4[##1][##2][##3]% - {\let#8#3% - \ifthirdargument - \def#9####1% - {\edef#3{####1}% - \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}% - \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent - \the#5}% - \processcommalist[##1]#9% - \orelse\ifsecondargument - \def#9####1% - {\edef#3{####1}% - #7% checks parent and sets if needed - \mult_interfaces_get_parameters{#1#3:}[##2]% - \the#5}% - \processcommalist[##1]#9% - \else + \frozen\protected\def#5{\mult_interfaces_get_parameters{#1#3:}}% + \newtoks#4% + \frozen\tolerant\protected\def#2[##1]##*[##2]##*[##3]% + {\let#7#3% + \ifarguments \let#3\empty - \mult_interfaces_get_parameters{#1:}[##1]% \the#5% + \or + \let#3\empty + \mult_interfaces_get_parameters{#1:}[##1]% + \the#4% + \or + \def#8####1% + {\edef#3{####1}% + #6% checks parent and sets if needed + \mult_interfaces_get_parameters{#1#3:}[##2]% + \the#4}% + \processcommalist[##1]#8% + \or + \def#8####1% + {\edef#3{####1}% + \defcsname#1#3:\s!parent\endcsname{#1##2}% + \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent + \the#4}% + \processcommalist[##1]#8% \fi - \let#3#8}} + \let#3#7}} -\protected\def\installautosetuphandler#1#2% +\permanent\protected\def\installautosetuphandler#1#2% {\normalexpanded {\mult_interfaces_install_auto_setup_handler {\noexpand#1}% \??aa \expandafter\noexpand\csname setup#2\endcsname \expandafter\noexpand\csname current#2\endcsname - \expandafter\noexpand\csname setup_#2\endcsname % semi-public \expandafter\noexpand\csname everysetup#2\endcsname \expandafter\noexpand\csname setupcurrent#2\endcsname \expandafter\noexpand\csname check#2parent\endcsname \expandafter\noexpand\csname saved_setup_current#2\endcsname \expandafter\noexpand\csname nested_setup_current#2\endcsname}} -\protected\def\installbasicparameterhandler#1#2% +\permanent\protected\def\installbasicparameterhandler#1#2% {\installparameterhandler {#1}{#2}% \installparameterhashhandler{#1}{#2}% \installparametersethandler {#1}{#2}% \installrootparameterhandler{#1}{#2}} -\protected\def\installbasicautosetuphandler#1#2#3% \??self name \??parent (can be \??self) +\permanent\protected\def\installbasicautosetuphandler#1#2#3% \??self name \??parent (can be \??self) {\installbasicparameterhandler{#1}{#2}% \installautosetuphandler {#1}{#2}} -\protected\def\installstylisticautosetuphandler#1#2#3% \??self name \??parent (can be \??self) +\permanent\protected\def\installstylisticautosetuphandler#1#2#3% \??self name \??parent (can be \??self) {\installbasicparameterhandler{#1}{#2}% \installautosetuphandler {#1}{#2}% \installstyleandcolorhandler {#1}{#2}} -\protected\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self) +\permanent\protected\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self) {\installbasicparameterhandler{#1}{#2}% \installdefinehandler {#1}{#2}{#3}% \installsetuphandler {#1}{#2}% \installstyleandcolorhandler {#1}{#2}} -\protected\def\installswitchcommandhandler#1#2#3% \??self name \??parent (can be \??self) +\permanent\protected\def\installswitchcommandhandler#1#2#3% \??self name \??parent (can be \??self) {\installbasicparameterhandler{#1}{#2}% \installdefinehandler {#1}{#2}{#3}% \installswitchsetuphandler {#1}{#2}% \installstyleandcolorhandler {#1}{#2}} -\protected\def\installautocommandhandler#1#2#3% automatically defined cloned setups +\permanent\protected\def\installautocommandhandler#1#2#3% automatically defined cloned setups {\installbasicparameterhandler{#1}{#2}% \installdefinehandler {#1}{#2}{#3}% \installautosetuphandler {#1}{#2}% \installstyleandcolorhandler {#1}{#2}} -\protected\def\installsimplecommandhandler#1#2#3% no define (experiment) - use \check*parent when defining +\permanent\protected\def\installsimplecommandhandler#1#2#3% no define (experiment) - use \check*parent when defining {\installbasicparameterhandler{#1}{#2}% \installsetuphandler {#1}{#2}% \installstyleandcolorhandler {#1}{#2}} @@ -741,13 +665,11 @@ %D We don't need colons for such simple cases. \protected\def\mult_interfaces_install_direct_parameter_handler#1#2#3#4#5% -%%{\def#3##1{\csname\ifcsname#1##1\endcsname#1##1\else\s!empty\fi\endcsname}% - {\def#3##1{\begincsname#1##1\endcsname}% - \def#4##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}% - % \def#4##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}% - \def#5##1{\begincsname#1##1\endcsname}} + {\frozen\def#3##1{\begincsname#1##1\endcsname}% + \frozen\def#4##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}% + \frozen\def#5##1{\begincsname#1##1\endcsname}} -\protected\def\installdirectparameterhandler#1#2% +\permanent\protected\def\installdirectparameterhandler#1#2% {\normalexpanded {\mult_interfaces_install_direct_parameter_handler {\noexpand#1}% @@ -756,36 +678,28 @@ \expandafter\noexpand\csname detokenized#2parameter\endcsname \expandafter\noexpand\csname direct#2parameter\endcsname}} -\protected\def\mult_interfaces_install_direct_setup_handler#1#2#3#4#5% - {\protected\def#2{\dosingleempty#3}% - \newtoks#5% - \def#3[##1]{\mult_interfaces_get_parameters#1[##1]\the#5}% - \def#4{\mult_interfaces_get_parameters#1}} +\protected\def\mult_interfaces_install_direct_setup_handler#1#2#3#4% + {\newtoks#4% + \frozen\protected\def#2[##1]{\ifarguments\or\mult_interfaces_get_parameters#1[##1]\fi\the#4}% + \frozen\def#3{\mult_interfaces_get_parameters#1}} -\protected\def\installdirectsetuphandler#1#2% +\permanent\protected\def\installdirectsetuphandler#1#2% {\normalexpanded {\mult_interfaces_install_direct_setup_handler {\noexpand#1}% \??aa \expandafter\noexpand\csname setup#2\endcsname - \expandafter\noexpand\csname setup_#2\endcsname % semi-public \expandafter\noexpand\csname setupcurrent#2\endcsname % no \every (we use 'current' for consistency) \expandafter\noexpand\csname everysetup#2\endcsname}} -% \protected\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5% -% {\protected\def#2{\mult_interfaces_def #1}% -% \protected\def#3{\mult_interfaces_edef#1}% -% \protected\def#4{\mult_interfaces_let #1}% -% \protected\def#5{\mult_interfaces_let #1\empty}}% - % \startinterface english \protected\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5% - {\protected\def#2##1{\expandafter \def\csname#1##1\endcsname}% - \protected\def#3##1{\expandafter\edef\csname#1##1\endcsname}% - \protected\def#4##1{\expandafter \let\csname#1##1\endcsname}% - \protected\def#5##1{\expandafter \let\csname#1##1\endcsname\empty}}% + {\frozen\protected\def#2##1{\defcsname#1##1\endcsname}% + \frozen\protected\def#3##1{\edefcsname#1##1\endcsname}% + \frozen\protected\def#4##1{\letcsname#1##1\endcsname}% + \frozen\protected\def#5##1{\letcsname#1##1\endcsname\empty}}% % \stopinterface -\protected\def\installdirectparametersethandler#1#2% +\permanent\protected\def\installdirectparametersethandler#1#2% {\normalexpanded {\mult_interfaces_install_direct_parameter_set_handler {\noexpand#1}% \??aa @@ -794,15 +708,15 @@ \expandafter\noexpand\csname let#2parameter\endcsname \expandafter\noexpand\csname reset#2parameter\endcsname}} -\let\installdirectstyleandcolorhandler\installstyleandcolorhandler +\aliased\let\installdirectstyleandcolorhandler\installstyleandcolorhandler -\protected\def\installdirectcommandhandler#1#2% +\permanent\protected\def\installdirectcommandhandler#1#2% {\installdirectparameterhandler {#1}{#2}% \installdirectsetuphandler {#1}{#2}% \installdirectparametersethandler {#1}{#2}% \installdirectstyleandcolorhandler{#1}{#2}} -\protected\def\installsetuponlycommandhandler#1#2% +\permanent\protected\def\installsetuponlycommandhandler#1#2% {\installdirectparameterhandler{#1}{#2}% \installdirectsetuphandler {#1}{#2}% }% maybe \installdirectparametersethandler {#1}{#2}% @@ -830,67 +744,48 @@ % yes:\twoparameter{alpha}\par % yes:\twoparameter{beta}\par -\protected\def\relateparameterhandlers#1#2#3#4% {from} {instance} {to} {instance} - {\expandafter\edef\csname\csname#1namespace\endcsname#2:\s!parent\endcsname{\csname#3namespace\endcsname#4}} +\permanent\protected\def\relateparameterhandlers#1#2#3#4% {from} {instance} {to} {instance} + {\edefcsname\csname#1namespace\endcsname#2:\s!parent\endcsname{\csname#3namespace\endcsname#4}} -\protected\def\relateparameterhandlersbyns#1#2#3#4% {from} {instance} {to} {instance} - {\expandafter\edef\csname#1#2:\s!parent\endcsname{#3#4}} +\permanent\protected\def\relateparameterhandlersbyns#1#2#3#4% {from} {instance} {to} {instance} + {\edefcsname#1#2:\s!parent\endcsname{#3#4}} %D Here is another experiment: -\protected\def\installactionhandler#1% - {\normalexpanded - {\mult_interfaces_install_action_handler - {#1}% - \expandafter\noexpand\csname current#1\endcsname - \expandafter\noexpand\csname setupcurrent#1\endcsname - \expandafter\noexpand\csname #1_action\endcsname}} - -% \protected\def\mult_interfaces_install_action_handler#1#2#3#4% -% {\protected\expandafter\def\csname#1\endcsname{\dodoubleempty#4}% -% \protected\def#4[##1][##2]% -% {\begingroup -% \ifsecondargument -% \edef#2{##1}% -% #3[##2]% -% \orelse\iffirstargument -% \doifelseassignment{##1} -% {\let#2\empty -% #3[##1]}% -% {\edef#2{##1}}% -% \else -% \let#2\empty -% \fi -% \directsetup{handler:action:#1}% -% \endgroup}} - -\protected\def\mult_interfaces_install_action_handler#1#2#3#4% - {\protected\expandafter\def\csname#1\endcsname{\dodoubleempty#4}% - \protected\def#4[##1][##2]% +\protected\def\mult_interfaces_install_action_handler#1#2#3% +% {\frozen\tolerant\protected\expandafter\def\csname#1\endcsname[##1]##*[##2]% + {\frozen\tolerant\protected\defcsname#1\endcsname[##1]##*[##2]% {\begingroup - \ifsecondargument - \edef#2{##1}% - #3[##2]% - \orelse\iffirstargument + \ifarguments + \let#2\empty + \or %\ifcondition\expandafter\mult_check_for_assignment_indeed_begin_\detokenize{##1}=^^^^0003^^^^0003^^^^0004% -% \ifcondition\mult_aux_no_assignment_indeed##1\ignorearguments -% \edef#2{##1}% -% \else -% \let#2\empty -% #3[##1]% -% \fi + % \ifcondition\mult_aux_no_assignment_indeed##1\ignorearguments + % \edef#2{##1}% + % \else + % \let#2\empty + % #3[##1]% + % \fi \ifhastok={##1}% \let#2\empty #3[##1]% \else \edef#2{##1}% \fi - \else - \let#2\empty + \or + \edef#2{##1}% + #3[##2]% \fi \directsetup{handler:action:#1}% \endgroup}} +\permanent\protected\def\installactionhandler#1% + {\normalexpanded + {\mult_interfaces_install_action_handler + {#1}% + \expandafter\noexpand\csname current#1\endcsname + \expandafter\noexpand\csname setupcurrent#1\endcsname}} + % First we had, in tune with the regular system variables: % % \starttyping @@ -918,30 +813,23 @@ \newcount\c_mult_interfaces_n_of_namespaces -%def\v_interfaces_prefix_template{\number \c_mult_interfaces_n_of_namespaces>} -%def\v_interfaces_prefix_template{\characters\c_mult_interfaces_n_of_namespaces>} - -%def\v_interfaces_prefix_template % consistently %03i> -% {\ifnum\c_mult_interfaces_n_of_namespaces<\plusten00\orelse\ifnum\c_mult_interfaces_n_of_namespaces<\plushundred0\fi -% \number\c_mult_interfaces_n_of_namespaces>} - \def\v_interfaces_prefix_template {\number\c_mult_interfaces_n_of_namespaces>} -\protected\def\installnamespace#1% for modules and users +\permanent\protected\def\installnamespace#1% for modules and users {\ifcsname ????#1\endcsname \writestatus\m!system{duplicate user namespace '#1'}\wait \else \global\advance\c_mult_interfaces_n_of_namespaces\plusone - \expandafter\edef\csname ????#1\endcsname{\v_interfaces_prefix_template}% + \immutable\edefcsname ????#1\endcsname{\v_interfaces_prefix_template}% \fi} -\protected\def\installcorenamespace#1% +\permanent\protected\def\installcorenamespace#1% {\ifcsname ??#1\endcsname \writestatus\m!system{duplicate core namespace '#1'}\wait \else \global\advance\c_mult_interfaces_n_of_namespaces\plusone - \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template}% + \immutable\edefcsname ??#1\endcsname{\v_interfaces_prefix_template}% \clf_registernamespace\c_mult_interfaces_n_of_namespaces{#1}% \fi} @@ -961,20 +849,19 @@ \letvalue\??dummy\empty - \def\dummyparameter #1{\begincsname\??dummy#1\endcsname} - \def\directdummyparameter #1{\begincsname\??dummy#1\endcsname} -\protected\def\setdummyparameter #1{\expandafter\def\csname\??dummy#1\endcsname} -\protected\def\setexpandeddummyparameter#1{\expandafter\edef\csname\??dummy#1\endcsname} -\protected\def\letdummyparameter #1{\expandafter\let\csname\??dummy#1\endcsname} +\permanent \def\dummyparameter #1{\begincsname\??dummy#1\endcsname} +\permanent \def\directdummyparameter #1{\begincsname\??dummy#1\endcsname} +\permanent\protected\def\setdummyparameter #1{\defcsname\??dummy#1\endcsname} +\permanent\protected\def\setexpandeddummyparameter#1{\edefcsname\??dummy#1\endcsname} +\permanent\protected\def\letdummyparameter #1{\letcsname\??dummy#1\endcsname} -% \protected\def\getdummyparameters -% {\mult_interfaces_get_parameters\??dummy} +\edef\mult_interfaces_dummy{\??dummy} % nor immutable -\protected\def\getdummyparameters[#1% +\permanent\protected\def\getdummyparameters[#1% {\if\noexpand#1]% \expandafter\gobbleoneargument \else - \let\m_mult_interfaces_namespace\??dummy + \let\m_mult_interfaces_namespace\mult_interfaces_dummy \expandafter\mult_interfaces_get_parameters_indeed \fi#1} @@ -1025,13 +912,10 @@ % % This is a user (module) command: -\protected\def\definenamespace - {\dodoubleargument\mult_interfaces_define_name_space} - -\def\mult_interfaces_define_name_space[#1][#2]% namespace settings +\permanent\tolerant\protected\def\definenamespace[#1]#*[#2]% namespace settings {\clf_definenamespace{#1}{#2}} -\def\listnamespaces +\permanent\protected\def\listnamespaces {\clf_listnamespaces} %D Helper: @@ -1040,61 +924,52 @@ %D \showparentchain{@@am}{left} %D \stoptyping -\protected\def\showparentchain#1#2% +\permanent\protected\def\showparentchain#1#2% {\writestatus\m!system{chain: [ \mult_interfaces_show_parent_chain{#1#2}]}} -% \def\mult_interfaces_show_parent_chain#1% -% {#1 => % -% \ifcsname#1:\s!parent\endcsname -% \expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname -% \fi} - \def\mult_interfaces_show_parent_chain#1% {#1 => % \ifcsname#1:\s!parent\endcsname - %\expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname \expandafter\mult_interfaces_show_parent_chain\lastnamedcs \fi} %D Another helper (needs to be applied): -\protected\def\doifelsecommandhandler#1#2% namespace name +\permanent\protected\def\doifelsecommandhandler#1#2% namespace name {\ifcsname#1#2:\s!parent\endcsname \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} -\let\doifcommandhandlerelse\doifelsecommandhandler +\aliased\let\doifcommandhandlerelse\doifelsecommandhandler -\protected\def\doifcommandhandler#1#2% namespace name +\permanent\protected\def\doifcommandhandler#1#2% namespace name {\ifcsname#1#2:\s!parent\endcsname \expandafter\firstofoneargument \else \expandafter\gobbleoneargument \fi} -\protected\def\doifnotcommandhandler#1#2% namespace name +\permanent\protected\def\doifnotcommandhandler#1#2% namespace name {\ifcsname#1#2:\s!parent\endcsname \expandafter\gobbleoneargument \else \expandafter\firstofoneargument \fi} -\let\doifcommandhandlerelse\doifelsecommandhandler - % another set of (fast) helpers (grep for usage): -\def\expandnamespaceparameter#1#2#3% \??xx \getp \c!xx \v!yy +\permanent\def\expandnamespaceparameter#1#2#3% \??xx \getp \c!xx \v!yy {\csname#1\ifcsname#1\expandafter\expandafter\expandafter\mult_aux_expand_namespace_parameter#2#3} \def\mult_aux_expand_namespace_parameter#1#2% \cs \v!yy {#1\endcsname#1\else#2\fi\endcsname} -\def\expandnamespacemacro#1#2#3% \??xx \some_edefed_cs \c!yy +\permanent\def\expandnamespacemacro#1#2#3% \??xx \some_edefed_cs \c!yy {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname} -\def\expandnamespacevalue#1#2% \??xx {...} \c!yy == optimized \expandcheckedcsname +\permanent\def\expandnamespacevalue#1#2% \??xx {...} \c!yy == optimized \expandcheckedcsname {\csname#1\ifcsname#1\normalexpanded{\noexpand\syst_helpers_expand_checked_value{#2}}} \def\syst_helpers_expand_checked_value#1#2% @@ -1120,11 +995,6 @@ % many assignments and mechanism that do are also slow; the advantage is mostly nicer % in tracing -\def\s!simple{simple} -\def\s!single{single} -\def\s!double{double} -\def\s!triple{triple} - \let\c_mult_set\relax \protected\def\mult_interfaces_install_definition_set#1#2#3#4#5#6#7% @@ -1134,23 +1004,23 @@ {\expandafter\let\expandafter\c_mult_set\csname #1_t_#6\endcsname \ifx\c_mult_set\relax \expandafter\newtoks\c_mult_set - \expandafter\let\csname #1_t_#6\endcsname\c_mult_set + \letcsname#1_t_#6\endcsname\c_mult_set \fi} - \protected\def#4##1% + \frozen\protected\def#4##1% {\pushmacro#6% \advance#3\plusone \edef#6{##1}% \unprotect}% - \protected\def#5% + \frozen\protected\def#5% {\protect \advance#3\minusone \popmacro#6}% - \protected\def#7##1% + \frozen\protected\def#7##1% {\edef#6{##1}% #2% \the\c_mult_set\relax}} -\protected\def\installdefinitionset#1#2% +\permanent\protected\def\installdefinitionset#1#2% {\normalexpanded {\mult_interfaces_install_definition_set {\noexpand#1}% \??aa @@ -1163,20 +1033,16 @@ \protected\def\mult_interfaces_install_definition_set_member#1#2#3#4#5#6#7#8#9% no everysetups etc {\let#5#2% - \protected\def#2% + \frozen\protected\def#2% {\ifcase#4\relax\expandafter#5\else\expandafter#6\fi}% - \protected\def#6% - {\dodoubleempty#7}% - \protected\def#7[##1][##2]% - {\ifsecondargument - %#3\c_mult_set\expandafter{\the\c_mult_set#9[##1][##2]}% - #3\toksapp\c_mult_set{#9[##1][##2]}% - \orelse\iffirstargument - %#3\c_mult_set\expandafter{\the\c_mult_set#8[##1]}% - #3\toksapp\c_mult_set{#8[##1]}% + \tolerant\protected\def#6[##1]##*[##2]% + {\ifarguments\or + #3\toksapp\c_mult_set{#7[##1]}% + \or + #3\toksapp\c_mult_set{#8[##1][##2]}% \fi}} -\protected\def\installdefinitionsetmember#1#2#3#4% +\permanent\protected\def\installdefinitionsetmember#1#2#3#4% {\normalexpanded {\mult_interfaces_install_definition_set_member {\noexpand#3}% \??aa @@ -1185,58 +1051,33 @@ \expandafter\noexpand\csname #2_nesting_depth\endcsname \expandafter\noexpand\csname normal_setup_#4\endcsname \expandafter\noexpand\csname delayed_setup_#4\endcsname - \expandafter\noexpand\csname do_delayed_setup_#4\endcsname \expandafter\noexpand\csname setup#4_\s!single\endcsname \expandafter\noexpand\csname setup#4_\s!double\endcsname}} %D Another experiment: \protected\def\mult_interfaces_install_parent_injector#1#2#3#4% - {\protected\def#4##1% - %{\ifx#3\empty + {\frozen\protected\def#4##1% {\ifempty#3% - \expandafter\def\csname#1#2:\s!parent\endcsname{#1##1}% + \defcsname#1#2:\s!parent\endcsname{#1##1}% \fi}} -\protected\def\installparentinjector#1#2% +\permanent\protected\def\installparentinjector#1#2% {\normalexpanded{\mult_interfaces_install_parent_injector {\noexpand#1}% \expandafter\noexpand\csname current#2\endcsname \expandafter\noexpand\csname current#2parent\endcsname \expandafter\noexpand\csname inject#2parent\endcsname}} -% Faster but not used that much to make a dent in performance. But, because it's -% cleaner anyway and also gives less tracing, we apply it a few times. - -% \protected\def\syst_helpers_install_macro_stack#1#2#3% -% {\xdef\m_syst_helpers_push_macro{\csstring#1}% -% \ifcsname#3\m_syst_helpers_push_macro\endcsname\else -% \expandafter\newcount\csname#3\m_syst_helpers_push_macro\endcsname -% \expandafter\edef\csname push_macro_\m_syst_helpers_push_macro\endcsname -% {\noexpand\expandafter\glet -% \noexpand\csname\m_syst_helpers_push_macro\noexpand\the\csname#3\m_syst_helpers_push_macro\endcsname\endcsname -% \noexpand#1% -% \global\advance\csname#3\m_syst_helpers_push_macro\endcsname\plusone}% -% \expandafter\edef\csname pop_macro_\m_syst_helpers_push_macro\endcsname -% {\global\advance\csname#3\m_syst_helpers_push_macro\endcsname\minusone -% \noexpand\expandafter#2% -% \noexpand\expandafter\noexpand#1% -% \noexpand\csname\m_syst_helpers_push_macro\noexpand\the\csname#3\m_syst_helpers_push_macro\endcsname\endcsname}% -% \fi} -% -% \protected\def\installmacrostack #1{\syst_helpers_install_macro_stack#1\let \??localpushedmacro } -% \protected\def\installglobalmacrostack#1{\syst_helpers_install_macro_stack#1\glet\??globalpushedmacro} - % The \LUA\ based variant is twice as fast as the above but as said, we don't use % this one that often. It's more about less tracing than speed here. -\protected\def\installmacrostack#1% +\permanent\protected\def\installmacrostack#1% {\ifdefined#1\else\let#1\empty\fi \protected\expandafter\gdef\csname push_macro_\csstring#1\endcsname{\localpushmacro#1}% \protected\expandafter\gdef\csname pop_macro_\csstring#1\endcsname{\localpopmacro #1}} - -\protected\def\installglobalmacrostack#1% +\permanent\protected\def\installglobalmacrostack#1% {\ifdefined#1\else\glet#1\empty\fi \protected\expandafter\gdef\csname push_macro_\csstring#1\endcsname{\globalpushmacro#1}% \protected\expandafter\gdef\csname pop_macro_\csstring#1\endcsname{\globalpopmacro #1}} @@ -1307,30 +1148,26 @@ \installcorenamespace{commalistprocessornext} \installcorenamespace{commalistprocessoraction} -\protected\def\installcommalistprocessor#1#2% 5 macro names overhead - {\protected\expandafter\edef\csname\??commalistprocessor#1\endcsname[% - % {\noexpand\futureexpandis]% - % \noexpand\gobbleoneargument - % \csname\??commalistprocessorpickup#1\endcsname} - %\protected\expandafter\edef\csname\??commalistprocessorpickup#1\endcsname +\permanent\protected\def\installcommalistprocessor#1#2% 5 macro names overhead + {\protected\edefcsname\??commalistprocessor#1\endcsname[% {\csname\??commalistprocessorwrap#1\endcsname\relax}% \relax preserves {} - \protected\expandafter\edef\csname\??commalistprocessorwrap#1\endcsname##1]% + \protected\edefcsname\??commalistprocessorwrap#1\endcsname##1]% {\csname\??commalistprocessorfirst#1\endcsname##1,]} - \protected\expandafter\edef\csname\??commalistprocessorfirst#1\endcsname\relax + \protected\edefcsname\??commalistprocessorfirst#1\endcsname\relax {\csname\??commalistprocessornext#1\endcsname}% - \protected\expandafter\edef\csname\??commalistprocessornext#1\endcsname + \protected\edefcsname\??commalistprocessornext#1\endcsname {\noexpand\futureexpandis]% \noexpand\gobbleoneargument \csname\??commalistprocessoraction#1\endcsname} - \protected\expandafter\edef\csname\??commalistprocessoraction#1\endcsname##1,% + \protected\edefcsname\??commalistprocessoraction#1\endcsname##1,% {\noexpand#2{##1}% \csname\??commalistprocessornext#1\endcsname}} -\protected\def\installcommalistprocessorcommand#1#2% \processor \action +\permanent\protected\def\installcommalistprocessorcommand#1#2% \processor \action {\edef\p_name{\csstring#2}% \installcommalistprocessor\p_name{#2}% \expandafter\let\expandafter#1\csname\??commalistprocessor\p_name\endcsname} -\protected\def\commalistprocessor#1{\csname\??commalistprocessor#1\endcsname} +\permanent\protected\def\commalistprocessor#1{\csname\??commalistprocessor#1\endcsname} \protect \endinput diff --git a/tex/context/base/mkiv/mult-def.lua b/tex/context/base/mkiv/mult-def.lua index ab26b7192..08baaf437 100644 --- a/tex/context/base/mkiv/mult-def.lua +++ b/tex/context/base/mkiv/mult-def.lua @@ -3770,7 +3770,7 @@ return { ["en"]="resetsystemmode", ["fr"]="razmodesysteme", }, - ["resettext"]={ + ["resettextcontent"]={ ["cs"]="resettextcontent", ["de"]="resettextcontent", ["en"]="resettextcontent", @@ -16239,6 +16239,9 @@ return { ["pe"]="پیشگفتار", ["ro"]="intro", }, + ["invertedshort"]={ + ["en"]="invertedshort", + }, ["italic"]={ ["cs"]="kurziva", ["de"]="italic", @@ -17168,6 +17171,9 @@ return { ["pe"]="نرمال", ["ro"]="normal", }, + ["normalshort"]={ + ["en"]="normalshort", + }, ["nospacing"]={ ["cs"]="nospacing", ["de"]="nospacing", @@ -17789,6 +17795,11 @@ return { ["pe"]="مراجعه", ["ro"]="referinta", }, + ["region"]={ + ["en"]="region", + ["fr"]="region", + ["nl"]="gebied", + }, ["register"]={ ["cs"]="rejstrik", ["de"]="register", diff --git a/tex/context/base/mkiv/mult-def.mkiv b/tex/context/base/mkiv/mult-def.mkiv index 78fcdf667..0a450e8b0 100644 --- a/tex/context/base/mkiv/mult-def.mkiv +++ b/tex/context/base/mkiv/mult-def.mkiv @@ -37,9 +37,9 @@ % some left-overs -\def\c!HL{HL} -\def\c!VL{VL} -\def\c!NL{NL} +\defineinterfaceconstant {HL} {HL} +\defineinterfaceconstant {VL} {VL} +\defineinterfaceconstant {NL} {NL} % stop todo diff --git a/tex/context/base/mkiv/mult-fmt.lua b/tex/context/base/mkiv/mult-fmt.lua index a91999afd..8d116c44f 100644 --- a/tex/context/base/mkiv/mult-fmt.lua +++ b/tex/context/base/mkiv/mult-fmt.lua @@ -38,6 +38,8 @@ local function limit(str,n) return str end +-- todo: use setmacro + function interfaces.setuserinterface(interface,response) local variables = interfaces.variables local constants = interfaces.constants diff --git a/tex/context/base/mkiv/mult-ini.lua b/tex/context/base/mkiv/mult-ini.lua index ef04fb622..9664342ab 100644 --- a/tex/context/base/mkiv/mult-ini.lua +++ b/tex/context/base/mkiv/mult-ini.lua @@ -233,92 +233,6 @@ end logs.setmessenger(context.verbatim.ctxreport) --- function interfaces.setuserinterface(interface,response) --- sharedstorage.currentinterface, currentinterface = interface, interface --- sharedstorage.currentresponse, currentresponse = response, response --- if environment.initex then --- local nofconstants = 0 --- local nofvariables = 0 --- local nofelements = 0 --- local nofcommands = 0 --- local nofformats = 0 --- local noftranslations = 0 --- local nofsetupstrings = 0 --- -- --- local t, f, s = { }, formatters["\\ui_c{%s}{%s}"], formatters["\\ui_s{%s}"] --- for given, constant in next, complete.constants do --- constant = constant[interface] or constant.en or given --- constants[constant] = given -- breedte -> width --- nofconstants = nofconstants + 1 --- if given == constant then --- t[nofconstants] = s(given) --- else --- t[nofconstants] = f(given,constant) --- end --- end --- contextsprint(prtcatcodes,concat(t)) --- -- --- local t, f = { }, formatters["\\ui_v{%s}{%s}"] --- for given, variable in next, complete.variables do --- variable = variable[interface] or variable.en or given --- variables[given] = variable -- ja -> yes --- nofvariables = nofvariables + 1 --- t[nofvariables] = f(given,variable) --- end --- contextsprint(prtcatcodes,concat(t)) --- -- --- local t, f = { }, formatters["\\ui_e{%s}{%s}"] --- for given, element in next, complete.elements do --- element = element[interface] or element.en or given --- elements[element] = given --- nofelements = nofelements + 1 --- t[nofelements] = f(given,element) --- end --- contextsprint(prtcatcodes,concat(t)) --- -- --- -- local t, n, f = { }, 0, formatters["\\ui_m{%s}{%s}"] --- local t, n, f = { }, 0, formatters["\\ui_a\\%s\\%s"] --- for given, command in next, complete.commands do --- command = command[interface] or command.en or given --- if command ~= given then --- n = n + 1 --- t[n] = f(given,command) --- end --- nofcommands = nofcommands + 1 --- end --- contextsprint(prtcatcodes,"\\toksapp\\everydump{"..concat(t).."}") --- -- --- for given, format in next, complete.messages.formats do --- formats[given] = format[interface] or format.en or given --- nofformats = nofformats + 1 --- end --- -- --- for given, translation in next, complete.messages.translations do --- translations[given] = translation[interface] or translation.en or given --- noftranslations = noftranslations + 1 --- end --- -- --- for given, setupstring in next, complete.setupstrings do --- setupstring = setupstring[interface] or setupstring.en or given --- setupstrings[given] = setupstring --- nofsetupstrings = nofsetupstrings + 1 --- end --- -- --- report_interface("definitions: %a constants, %a variables, %a elements, %a commands, %a formats, %a translations, %a setupstrings", --- nofconstants,nofvariables,nofelements,nofcommands,nofformats,noftranslations,nofsetupstrings) --- else --- report_interface("the language(s) can only be set when making the format") --- end --- interfaces.currentinterface = currentinterface --- interfaces.currentresponse = currentresponse --- end - --- interfaces.implement { --- name = "setuserinterface", --- actions = interfaces.setuserinterface, --- arguments = "2 strings", --- } - interfaces.cachedsetups = interfaces.cachedsetups or { } interfaces.hashedsetups = interfaces.hashedsetups or { } diff --git a/tex/context/base/mkiv/mult-ini.mkxl b/tex/context/base/mkiv/mult-ini.mkxl new file mode 100644 index 000000000..19c76d0cf --- /dev/null +++ b/tex/context/base/mkiv/mult-ini.mkxl @@ -0,0 +1,801 @@ +%D \module +%D [ file=mult-ini, +%D version=2008.10.22, % 1996.06.01, +%D title=\CONTEXT\ Multilingual Macros, +%D subtitle=Initialization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This module is a stripped down version of \type {mult-ini.tex}, which we keep +%D around as \type {mult-kep.tex} for sentimental reasons. There you will find some +%D more historic information. + +\writestatus{loading}{ConTeXt Multilingual Macros / Initialization} + +\unprotect + +\registerctxluafile{mult-ini}{} +\registerctxluafile{mult-fmt}{initexonly} + +%D \macros +%D [constanten,variabelen,commands] +%D {v!,c!,k!,s!,e!,m!,l!,r!,f!,p!,x!,y!} +%D +%D In the system modules we introduced some prefixed constants, variables (both +%D macros) and registers. Apart from a tremendous saving in terms of memory and a +%D gain in speed we use from now on prefixes when possible for just another reason: +%D consistency and multi||linguality. Systematically using prefixed macros enables +%D us to implement a multi||lingual user interface. Redefining these next set of +%D prefixes therefore can have desastrous results. +%D +%D \startlinecorrection +%D \starttable[|c|c|c|] +%D \HL +%D \NC \bf prefix \NC \bf meaning \NC \bf application \NC\SR +%D \HL +%D \NC \type{\c!prefix!} \NC c! \NC constant (direct) \NC\FR +%D \NC \type{\k!prefix!} \NC k! \NC constant (indirect) \NC\FR +%D \NC \type{\e!prefix!} \NC e! \NC element \NC\MR +%D \NC \type{\f!prefix!} \NC f! \NC file \NC\MR +%D \NC \type{\m!prefix!} \NC m! \NC age \NC\MR +%D \NC \type{\s!prefix!} \NC s! \NC system \NC\MR +%D \NC \type{\v!prefix!} \NC v! \NC variable \NC\MR +%D \HL +%D \stoptable +%D \stoplinecorrection +%D +%D In the single||lingual version we used \type {!}, \type {!!}, \type {!!!} and +%D \type {!!!!}. In the meantime some of these are obsolete (we had some 12 +%D originally). + +\immutable\def\c!prefix!{c!} +\immutable\def\k!prefix!{k!} +\immutable\def\e!prefix!{e!} +\immutable\def\f!prefix!{f!} % for the moment we keep this one +\immutable\def\m!prefix!{m!} +\immutable\def\s!prefix!{s!} +\immutable\def\v!prefix!{v!} + +%D \macros +%D [constants,variables,commands] +%D {@@,??} +%D +%D Variables generated by the system can be recognized on their prefix \type {@@}. +%D They are composed of a command (class) specific tag, which can be recognized on +%D \type {??}, and a system constant, which has the prefix \type {c!}. We'll se some +%D more of this. + +\immutable\def\??prefix {??} +\immutable\def\@@prefix {@@} + +%D Just to be complete we repeat some of the already defined system constants here. +%D Maybe their prefix \type {\s!} now falls into place. + +\def\s!next {next} \def\s!default {default} +\def\s!dummy {dummy} \def\s!unknown {unknown} + +\def\s!do {do} \def\s!dodo {dodo} + +\def\s!complex {complex} \def\s!start {start} +\def\s!simple {simple} \def\s!stop {stop} + +\def\s!true {true} +\def\s!false {false} + +%D The word \type {height} takes 6~token memory cells. The control sequence \type +%D {\height} on the other hand uses only one. Knowing this, we can improve the +%D performance of \TEX, both is terms of speed and memory usage, by using control +%D sequences instead of the words written in full. +%D +%D Where in the \ASCII\ file the second lines takes nine extra characters, \TEX\ +%D saves us 13~tokens. +%D +%D \starttyping +%D \hrule width 10pt height 2pt depth 1pt +%D \hrule \s!width 10pt \s!height 2pt \s!depth 1pt +%D \stoptyping +%D +%D One condition is that we have defined \type {\s!height}, \type {\s!width} and +%D \type {\s!depth} as respectively \type {height}, \type {width} and \type {depth}. +%D Using this scheme therefore only makes sense when a token sequence is used more +%D than once. Savings like this should of course be implemented in english, just +%D because \TEX\ is english. + +\def\s!width {width} +\def\s!height {height} +\def\s!depth {depth} +\def\s!spread {spread} +\def\s!plus {plus} +\def\s!minus {minus} +\def\s!to {to} + +\def\s!fil {fil} +\def\s!fill {fill} +\def\s!filll {filll} + +\def\s!attr {attr} +\def\s!axis {axis} +\def\s!both {both} +\def\s!bottom {bottom} +\def\s!left {left} +\def\s!options {options} +\def\s!orientation{orientation} +\def\s!reverse {reverse} +\def\s!right {right} +\def\s!top {top} +\def\s!xmove {xmove} +\def\s!xoffset {xoffset} +\def\s!ymove {ymove} +\def\s!yoffset {yoffset} + +%D \macros + +%D {defineinterfaceconstant, +%D defineinterfacevariable, +%D defineinterfaceelement, +%D definesystemvariable, +%D definesystemconstant, +%D definemessageconstant, +%D definefileconstant} +%D +%D The first part of this module is dedicated to dealing with multi||lingual +%D constants and variables. When \CONTEXT\ grew bigger and bigger in terms of bytes +%D and used string space, we switched to predefined constants. At the cost of more +%D hash table entries, the macros not only becase more compact, they became much +%D faster too. Maybe an even bigger advantage was that mispelling could no longer +%D lead to problems. Even a multi||lingual interface became possible. +%D +%D Constants |<|we'll introduce the concept of variables later on|>| are preceded by +%D a type specific prefix, followed by a \type {!}. To force consistency, we provide +%D a few commands for defining such constants. +%D +%D \starttyping +%D \defineinterfaceconstant {name} {meaning} +%D \defineinterfacevariable {name} {meaning} +%D \defineinterfaceelement {name} {meaning} +%D \stoptyping +%D +%D Which is the same as: +%D +%D \starttyping +%D \def\c!name{meaning} +%D \def\v!name{meaning} +%D \def\e!name{meaning} +%D \stoptyping + +%permanent\protected\def\defineinterfaceconstant #1#2{\immutable\expandafter\def\csname\c!prefix!#1\endcsname{#2}} +\permanent\protected\def\defineinterfacevariable #1#2{\immutable\expandafter\def\csname\v!prefix!#1\endcsname{#2}} +\permanent\protected\def\defineinterfaceelement #1#2{\immutable\expandafter\def\csname\e!prefix!#1\endcsname{#2}} + +%D Next come some interface independant constants: +%D +%D \starttyping +%D \definefileconstant {name} {meaning} +%D \stoptyping + +\permanent\protected\def\definefileconstant #1#2{\immutable\expandafter\def\csname\f!prefix!#1\endcsname{#2}} + +%D And finaly we have the one argument, space saving constants +%D +%D \starttyping +%D \definesystemconstant {name} +%D \definemessageconstant {name} +%D \stoptyping + +% for now we check if a system variable has been defined, till we fixed all duplicate definitions + +\permanent\protected\def\definesystemconstant #1{\immutable\expandafter\def\csname\s!prefix!#1\endcsname{#1}} +\permanent\protected\def\definemessageconstant #1{\immutable\expandafter\def\csname\m!prefix!#1\endcsname{#1}} + +%D In a parameter driven system, some parameters are shared by more system +%D components. In \CONTEXT\ we can distinguish parameters by a unique prefix. Such a +%D prefix is defined with: +%D +%D \starttyping +%D \definesystemvariable {name} +%D \stoptyping + +\permanent\protected\def\definesystemvariable#1{\immutable\expandafter\edef\csname\??prefix#1\endcsname{\@@prefix#1}} + +\definesystemvariable{ms} + +%D \macros +%D {selectinterface, +%D defaultinterface, currentinterface, currentresponses} +%D +%D With \type {\selectinterface} we specify the language we are going to use. The +%D system asks for the language wanted, and defaults to \type {\currentinterface} +%D when we just give \type {enter}. By default the message system uses the current +%D interface language, but \type {\currentresponses} can specify another language +%D too. +%D +%D Because we want to generate formats directly too, we do not ask for interface +%D specifications when these are already defined (like in cont-nl.tex and alike). + +\ifdefined\defaultinterface + + \permanent\protected\def\selectinterface + {\writestatus{interface}{defining \currentinterface\space interface}% + %writeline + \writestatus{interface}{using \currentresponses\space messages}% + %\writeline + \enforced\permanent\let\selectinterface\relax} + +\else + + \def\defaultinterface{english} + + \permanent\overloaded\protected\def\selectinterface + {\enforced\permanent\protected\def\selectinterface##1##2% + {\bgroup + \endlinechar\minusone + \global\read16 to ##1 + \egroup + \doifnothing\currentinterface{\let##1=##2}% + \doifundefined{\s!prefix!##1}{\let##1=##2}}% + \selectinterface\currentinterface\defaultinterface + \writestatus{interface}{defining \currentinterface\space interface}% + %\writeline + \selectinterface\currentresponses\currentinterface + \writestatus{interface}{using \currentresponses\space messages}% + %\writeline + \enforced\permanent\let\selectinterface\relax} + +\fi + +\ifdefined\currentinterface \else \let\currentinterface\defaultinterface \fi +\ifdefined\currentresponses \else \let\currentresponses\defaultinterface \fi + +%D \macros +%D {startinterface} +%D +%D Sometimes we want to define things only for specific interface languages. This +%D can be done by means of the selector: +%D +%D \starttyping +%D \startinterface language +%D +%D language specific definitions & commands +%D +%D \stopinterface +%D \stoptyping + +\permanent\protected\def\startinterface #1 + {\doifnot{#1}{all}{\doifnotinset\currentinterface{#1}{\gobbleuntil\stopinterface}}} + +\aliased\let\stopinterface\relax + +%D \macros +%D {startmessages, +%D getmessage, +%D showmessage, +%D makemessage} +%D +%D A package as large as \CONTEXT\ can hardly function without a decent message +%D mechanism. Due to its multi||lingual interface, the message subsystem has to be +%D multi||lingual too. A major drawback of this feature is that we have to code +%D messages. As a result, the source becomes less self documented. On the other +%D hand, consistency will improve. +%D +%D Because the overhead in terms of entries in the (already exhausted) hash table +%D has to be minimal, messages are packed in libraries. We can extract a message +%D from such a library in three ways: +%D +%D \starttyping +%D \getmessage {library} {tag} +%D \showmessage {library} {tag} {data} +%D \makemessage {library} {tag} {data} +%D \stoptyping +%D +%D The first command gets the message \type {tag} from the \type {library} +%D specified. The other commands take an extra argument: a list of items to be +%D inserted in the message text. While \type {\showmessage} shows the message at the +%D terminal, the other commands generate the message as text. Before we explain the +%D \type {data} argument, we give an example of a library. +%D +%D \starttyping +%D \startmessages english library: alfa +%D title: something +%D 1: first message +%D 2: second (--) message -- +%D \stopmessages +%D \stoptyping +%D +%D The first message is a simple one and can be shown with: +%D +%D \starttyping +%D \showmessage {alfa} {1} {} +%D \stoptyping +%D +%D The second message on the other hand needs some extra data: +%D +%D \starttyping +%D \showmessage {alfa} {2} {and last,to you} +%D \stoptyping +%D +%D This message is shown as: +%D +%D \starttyping +%D something : second (and last) message to you +%D \stoptyping +%D +%D As we can see, the title entry is shown with the message. The data fields are +%D comma separated and are specified in the message text by \type {--}. +%D +%D It is not required to define all messages in a library at once. We can add +%D messages to a library in the following way: +%D +%D \starttyping +%D \startmessages english library: alfa +%D 10: tenth message +%D \stopmessages +%D \stoptyping +%D +%D Because such definitions can take place in different modules, the system gives a +%D warning when a tag occurs more than once. The first occurrence takes preference +%D over later ones, so we had better use a save offset, as shown in the example. As +%D we can see, the title field is specified only the first time! +%D +%D Because we want to check for duplicate tags, the macros are a bit more +%D complicated than neccessary. The \NEWLINE\ token is used as message separator. +%D +%D For internal purposes one can use \type {\setmessagetext}, which puts the message +%D text asked for in \type {\currentmessagetext}. +%D +%D These will become obsolete: + +\permanent\protected\def\startmessages #1 library: #2 % + {\begingroup + \ifcsname\m!prefix!#2\endcsname\else\immutable\setgvalue{\m!prefix!#2}{#2}\fi + \catcode\endoflineasciicode\othercatcode + \doifelseinset{#1}{\currentresponses,all}\mult_messages_start_yes\mult_messages_start_nop{#2}} + +\def\mult_messages_start_yes#1#2\stopmessages + {\clf_setinterfacemessages{#1}{#2}% + \endgroup} + +\def\mult_messages_start_nop#1#2\stopmessages + {\endgroup} + +\let\stopmessages\relax + +\permanent\protected\def\setinterfacemessage#1#2#3% + {\ifcsname\m!prefix!#1\endcsname\else\immutable\setgvalue{\m!prefix!#1}{#1}\fi + \clf_setinterfacemessage{#1}{#2}{#3}} + +\pushoverloadmode + +\permanent\protected\def\setmessagetext #1#2{\relax\edef\currentmessagetext{\clf_getmessage{#1}{#2}}} +\permanent\protected\def\getmessage #1#2{\relax\clf_getmessage{#1}{#2}} +\permanent\protected\def\doifelsemessage #1#2{\relax\clf_doifelsemessage{#1}{#2}} +\permanent\protected\def\showmessage #1#2#3{\relax\clf_showmessage{#1}{#2}{#3}} +\permanent\protected\def\writestatus #1#2{\relax\clf_writestatus{#1}{#2}} +\permanent\protected\def\message {\relax\clf_message} + +\popoverloadmode + +\aliased\let\doifmessageelse\doifelsemessage + +\permanent\protected\def\inlinemessage #1{\dontleavehmode{\tttf#1}} +\permanent\protected\def\displaymessage#1{\blank\inlinemessage{#1}\blank} + +\permanent\let\getsetupstring\clf_getsetupstring +\permanent\let\rawsetupstring\clf_rawsetupstring + +%D For old times sake: + +\let\showwarning\showmessage + +%D \macros +%D {dosetvalue,dosetevalue,dosetgvalue,dosetxvalue,docopyvalue,doresetvalue} % dogetvalue +%D +%D We already defined these auxiliary macros in the system modules. Starting with +%D this module however, we have to take multi||linguality a bit more serious. +%D +%D In due time, when we exclusively use the parameter handler code, we can drop the +%D backmapping (\type{\c!k...}) and make \type {\c!c...} similar to \type {\v!...}. +%D In that case we can simply the following setters. + +\pushoverloadmode + +\permanent\protected\def\doletvalue #1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +\permanent\protected\def\dosetvalue #1#2{\expandafter\def \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +\permanent\protected\def\dosetevalue #1#2{\expandafter\edef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +\permanent\protected\def\dosetgvalue #1#2{\expandafter\gdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +\permanent\protected\def\dosetxvalue #1#2{\expandafter\xdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname} +\permanent\protected\def\doresetvalue #1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty} +\permanent\protected\def\doignorevalue#1#2#3{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty} + +\permanent\protected\def\docopyvalue#1#2#3% + {\ifcsname\k!prefix!#3\endcsname + \expandafter\def\csname#1\csname\k!prefix!#3\endcsname\expandafter\endcsname\expandafter + {\csname#2\csname\k!prefix!#3\endcsname\endcsname}% + \else + \expandafter\def\csname#1#3\expandafter\endcsname\expandafter + {\csname#2#3\endcsname}% + \fi} + +\startinterface english + + \permanent\protected\def\doletvalue #1#2{\expandafter \let\csname#1#2\endcsname} + \permanent\protected\def\dosetvalue #1#2{\expandafter \def\csname#1#2\endcsname} + \permanent\protected\def\dosetevalue #1#2{\expandafter\edef\csname#1#2\endcsname} + \permanent\protected\def\dosetgvalue #1#2{\expandafter\gdef\csname#1#2\endcsname} + \permanent\protected\def\dosetxvalue #1#2{\expandafter\xdef\csname#1#2\endcsname} + \permanent\protected\def\doresetvalue #1#2{\expandafter \let\csname#1#2\endcsname\empty} + \permanent\protected\def\doignorevalue#1#2#3{\expandafter \let\csname#1#2\endcsname\empty} + + \permanent\protected\def\docopyvalue#1#2#3% + {\expandafter\def\csname#1#3\expandafter\endcsname\expandafter + {\csname#2#3\endcsname}} + +\stopinterface + +\popoverloadmode + +%D We can now redefine some messages that will be introduced in the multi||lingual +%D system module. + +\permanent\protected\def\showassignerror #1#2{\showmessage\m!check1{#1,#2}} +\permanent\protected\def\showargumenterror#1#2{\showmessage\m!check2{#1,#2}} +\permanent\protected\def\showdefinederror #1#2{\showmessage\m!check3{#1,#2}} + +%D \CONTEXT\ is a parameter driven package. This means that users instruct the +%D system by means of variables, values and keywords. These instructions take the +%D form: +%D +%D \starttyping +%D \setupsomething[some variable=some value, another one=a keyword] +%D \stoptyping +%D +%D or by keyword only: +%D +%D \starttyping +%D \dosomething[this way,that way,no way] +%D \stoptyping +%D +%D Because the same variables can occur in more than one setup command, we have to +%D be able to distinguish them. This is achieved by assigning them a unique prefix. +%D +%D Imagine a setup command for boxed text, that enables us to specify the height and +%D width of the box. Behide the scenes the command +%D +%D \starttyping +%D \setupbox [width=12cm, height=3cm] +%D \stoptyping +%D +%D results in something like +%D +%D \starttyping +%D \<box><width> {12cm} +%D \<box><height> {3cm} +%D \stoptyping +%D +%D while a similar command for specifying the page dimensions +%D of an \cap {A4} page results in: +%D +%D \starttyping +%D \<page><width> {21.0cm} +%D \<page><height> {27.9cm} +%D \stoptyping +%D +%D The prefixes \type {<box>} and \type {<page>} are hidden from users and can +%D therefore be language independant. Variables on the other hand, differ for each +%D language: +%D +%D \starttyping +%D \<box><color> {<blue>} +%D \<box><kleur> {<blauw>} +%D \<box><couleur> {<blue>} +%D \stoptyping +%D +%D In this example we can see that the assigned values or keywords are language +%D dependant too. This will be a complication when defining multi||lingual setup +%D files. +%D +%D A third phenomena is that variables and values can have a similar meaning. +%D +%D \starttyping +%D \<pagenumber><location> {<left>} +%D \<skip><left> {12cm} +%D \stoptyping +%D +%D A (minor) complication is that where in english we use \type {<left>}, in dutch +%D we find both \type {<links>} and \type {<linker>}. This means that when we use +%D some sort of translation table, we have to distinguish between the variables at +%D the left side and the fixed values at the right. +%D +%D The same goes for commands that are composed of different user supplied and/or +%D language specific elements. In english we can use: +%D +%D \starttyping +%D \<empty><figure> +%D \<empty><intermezzo> +%D \stoptyping +%D +%D But in dutch we have the following: +%D +%D \starttyping +%D \<lege><figuur> +%D \<leeg><intermezzo> +%D \stoptyping +%D +%D These subtle differences automatically lead to a solution where variables, +%D values, elements and other components have a similar logical name (used in +%D macro's) but a different meaning (supplied by the user). +%D +%D Our solution is one in which the whole system is programmed in terms of +%D identifiers with language specific meanings. In such an implementation, each +%D fixed variable is available as: +%D +%D \starttyping +%D \<prefix><variable> +%D \stoptyping +%D +%D This means that for instance: +%D +%D \starttyping +%D \setupbox[width=12cm] +%D \stoptyping +%D +%D expands to something like: +%D +%D \starttyping +%D \def\boxwidth{12cm} +%D \stoptyping +%D +%D because we don't want to recode the source, a setup command in another language +%D has to expand to this variable, so: +%D +%D \starttyping +%D \setupblock[width=12cm] +%D \stoptyping +%D +%D has to result in the definition of \type {\boxwidth} too. This method enables us +%D to build compact, fast and readable code. +%D +%D An alternative method, which we considered using, uses a more indirect way. In +%D this case, both calls generate a different variable: +%D +%D \starttyping +%D \def\boxwidth {12cm} +%D \def\boxbreedte {12cm} +%D \stoptyping +%D +%D And because we don't want to recode those megabytes of already developed code, +%D this variable has to be called with something like: +%D +%D \starttyping +%D \valueof\box\width +%D \stoptyping +%D +%D where \type {\valueof} takes care of the translation of \type {width} or \type +%D {breedte} to \type {width} and combining this with \type {box} to \type +%D {\boxwidth}. +%D +%D One advantage of this other scheme is that, within certain limits, we can +%D implement an interface that can be switched to another language at will, while +%D the current approach fixes the interface at startup. There are, by the way, other +%D reasons too for not choosing this scheme. Switching user generated commands is +%D for instance impossible and a dual interface would therefore give a strange mix +%D of languages. +%D +%D Now let's work out the first scheme. Although the left hand of the assignment is +%D a variable from the users point of view, it is a constant in terms of the system. +%D Both \type {width} and \type {breedte} expand to \type {width} because in the +%D source we only encounter \type {width}. Such system constants are presented as +%D +%D \starttyping +%D \c!width +%D \stoptyping +%D +%D This constant is always equivalent to \type {width}. As we can see, we use \type +%D {c!} to mark this one as constant. Its dutch counterpart is: +%D +%D \starttyping +%D breedte +%D \stoptyping +%D +%D When we interpret a setup command each variable is translated to it's \type{c!} +%D counterpart. This means that \type {breedte} and \type{width} expand to \type +%D {breedte} and \type {\c!width} which both expand to \type {width}. That way user +%D variables become system constants. +%D +%D The interpretation is done by means of a general setup command \type +%D {\getparameters} that we introduced in the system module. Let us define some +%D simple setup command: +%D +%D \starttyping +%D \protected\def\setupbox[#1]% +%D {\getparameters[\??bx][#1]} +%D \stoptyping +%D +%D This command can be used as: +%D +%D \starttyping +%D \setupbox [width=3cm, height=1cm] +%D \stoptyping +%D +%D Afterwards we have two variables \type {\@@bxwidth} and \type {\@@bxheight} which +%D have the values \type {3cm} and \type {1cm} assigned. These variables are a +%D combinatiom of the setup prefix \type {\??bx}, which expands to \type {@@bx} and +%D the translated user supplied variables \type {width} and \type {height} or \type +%D {breedte} and \type {hoogte}, depending on the actual language. In dutch we just +%D say: +%D +%D \starttyping +%D \stelblokin [breedte=3cm,hoogte=1cm] +%D \stoptyping +%D +%D and get ourselves \type {\@@bxwidth} and \type {\@@bxheight} too. In the source +%D of \CONTEXT, we can recognize constants and variables on their leading \type +%D {c!}, \type {v!} etc., prefixes on \type {??} and composed variables on \type +%D {@@}. +%D +%D We already saw that user supplied keywords need some special treatment too. This +%D time we don't translate the keyword, but instead use in the source a variable +%D which meaning depends on the interface language. +%D +%D \starttyping +%D \v!left +%D \stoptyping +%D +%D Which can be used in macro's like: +%D +%D \starttyping +%D \processaction +%D [\@@bxlocation] +%D [ \v!left=>\dosomethingontheleft, +%D \v!middle=>\dosomthinginthemiddle, +%D \v!right=>\dosomethingontheright] +%D \stoptyping +%D +%D Because variables like \type {\@@bxlocation} can have a lot of meanings, +%D including tricky expandable tokens, we cannot translate this meaning when we +%D compare. This means that \type {\@@bxlocation} can be \type {left} of \type +%D {links} of whatever meaning suits the language. But because \type {\v!left} also +%D has a meaning that suits the language, we are able to compare. +%D +%D Although we know it sounds confusing we want to state two important +%D characteristics of the interface as described: +%D +%D \startnarrower \em +%D user variables become system constants +%D \stopnarrower +%D +%D and +%D +%D \startnarrower \em +%D user constants (keywords) become system variables +%D \stopnarrower +%D +%D The \type {\c!internal} is a left over from the time that the user interface +%D documents were not using a specification alongside a keyword specification but +%D used a shared file in which case we need to go in both directions. + +% temporary mkiv hack (we can best just store the whole table in memory) + +\permanent\overloaded\protected\def\setinterfaceconstant#1#2% + {\clf_setinterfaceconstant{#1}{#2}% + \immutable\expandafter\def\csname\c!prefix!#1\endcsname{#1}} + +\permanent\overloaded\protected\def\setinterfacevariable#1#2% + {\clf_setinterfacevariable{#1}{#2}% + \immutable\expandafter\def\csname\v!prefix!#1\endcsname{#2}} + +%D \macros +%D {defineinterfaceconstant} +%D +%D Next we redefine a previously defined macro to take care of interface translation +%D too. It's a bit redundant, because in these situations we could use the +%D c||version, but for documentation purposes the x||alternative comes in handy. + +\permanent\overloaded\protected\def\defineinterfaceconstant#1#2% + {\immutable\expandafter\def\csname\c!prefix!#1\endcsname{#2}} + +%D \macros +%D {startelements} +%D +%D Due to the object oriented nature of \CONTEXT, we also need to define the +%D elements that are used to build commands. +%D +%D Such elements sometimes are the same in different languages, but mostly they +%D differ. Things can get even confusing when we look at for instance the setup +%D commands. In english we say \type{\setup<something>}, but in dutch we have: \type +%D {\stel<iets>in}. Such split elements are no problem, because we just define two +%D elements. When no second part is needed, we use a \type {-}: + +\permanent\overloaded\protected\def\setinterfaceelement#1#2% + {\clf_setinterfaceelement{#1}{#2}% + \ifcsname\e!prefix!#1\endcsname + \doifnotvalue{\e!prefix!#1}{#2}{\enforced\immutable\setvalue{\e!prefix!#1}{#2}}% + \else + \enforced\immutable\setvalue{\e!prefix!#1}{#2}% + \fi} + +\permanent\protected\def\setinterfacecommand#1#2% \frozen ? \permanent ? + {\doifnot{#1}{#2}% todo: let when already defined + {\expandafter\def\csname#2\expandafter\endcsname\expandafter{\csname#1\endcsname}}} + +%D We just ignore these: + +\permanent\protected\def\startvariables{\gobbleuntil\stopvariables} \let\stopvariables\relax +\permanent\protected\def\startconstants{\gobbleuntil\stopconstants} \let\stopconstants\relax +\permanent\protected\def\startelements {\gobbleuntil\stopelements } \let\stopelements \relax +\permanent\protected\def\startcommands {\gobbleuntil\stopcommands } \let\stopcommands \relax + +%D For at the \LUA\ end (experiment): + +\def\ui_c#1#2{\immutable\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}% + \immutable\expandafter\gdef\csname\k!prefix!#2\endcsname{#1}} % backmapping from non english +\def\ui_s #1{\immutable\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}% + \immutable\expandafter\gdef\csname\k!prefix!#1\endcsname{#1}} % backmapping from non english +\def\ui_v#1#2{\immutable\expandafter\gdef\csname\v!prefix!#1\endcsname{#2}} +\def\ui_e#1#2{\immutable\expandafter\gdef\csname\e!prefix!#1\endcsname{#2}} +\def\ui_a#1#2{\frozen\protected\def#2{#1}} % will go away + +\startinterface english + + \def\ui_c#1#2{\immutable\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}} + \def\ui_s #1{\immutable\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}} + +\stopinterface + +%D So much for the basic multi||lingual interface commands. The macro's can be +%D enhanced with more testing facilities, but for the moment they suffice. + +\ifdefined\zwnj \else \immutable\edef\zwnj{\directlua{utf.char(\number"200C)}} \fi % needed for cont-pe % maybe to char-utf.mkiv +\ifdefined\zwj \else \immutable\edef\zwj {\directlua{utf.char(\number"200D)}} \fi % needed for cont-pe % maybe to char-utf.mkiv + +%D \macros +%D {contextversion, contextversionnumber, contextversionno, +%D contextbanner, showcontextbanner, formatversion} +%D +%D Out of convenience we define the banners here. This might move to the \LUA\ end. + +\pushoverloadmode + +\permanent\overloaded\def\contextbanner + {ConTeXt \space + ver: \contextversion \space \contextmark \space \space + fmt: \formatversion \space \space + int: \currentinterface/\currentresponses} + +\permanent\overloaded\protected\def\showcontextbanner + {\writestatus\m!system\empty + \writestatus\m!system\contextbanner + \writestatus\m!system\empty} + +\immutable\overloaded\edef\formatversion + {\the\normalyear.\the\normalmonth.\the\normalday} + +\newcount\contextversionno + +\ifx\contextversion\undefined + \immutable\edef\contextversion{\the\normalyear.\the\normalmonth.\the\normalday\space 00:00} +\fi + +\permanent\overloaded\protected\def \contextversionnumber #1.#2.#3 #4:#5\relax{#1#2#3} + \contextversionno \expandafter\contextversionnumber\contextversion\relax +\immutable\overloaded \edef\contextversionnumber {\the\contextversionno\space\contextmark} + +\popoverloadmode + +%D \macros +%D {everydump} +%D +%D This one is only used when we generate the format. + +% \ifx\undefined\everydump +% \newtoks\everydump +% \def\dump{\the\everydump\global\everydump\emptytoks\glet\dump\relax\normaldump} +% \fi + +% \appendtoks \showcontextbanner \to \everydump + +\protect \endinput diff --git a/tex/context/base/mkiv/mult-low.lua b/tex/context/base/mkiv/mult-low.lua index 6ca7a7a40..8cf89c40a 100644 --- a/tex/context/base/mkiv/mult-low.lua +++ b/tex/context/base/mkiv/mult-low.lua @@ -12,7 +12,7 @@ return { ["constants"] = { -- "zerocount", "minusone", "minustwo", "plusone", "plustwo", "plusthree", "plusfour", "plusfive", - "plussix", "plusseven", "pluseight", "plusnine", "plusten", "plussixteen", + "plussix", "plusseven", "pluseight", "plusnine", "plusten", "pluseleven", "plustwelve", "plussixteen", "plusfifty", "plushundred", "plusonehundred", "plustwohundred", "plusfivehundred", "plusthousand", "plustenthousand", "plustwentythousand", "medcard", "maxcard", "maxcardminusone", "zeropoint", "onepoint", "halfapoint", "onebasepoint", "maxcount", "maxdimen", "scaledpoint", "thousandpoint", @@ -67,15 +67,11 @@ return { "doublequoteasciicode", "singlequoteasciicode", "forwardslashasciicode", "primeasciicode", "hyphenasciicode", -- - "frozenhsizecode", "frozenleftskipcode", "frozenrightskipcode", "frozenhangindentcode", - "frozenhangaftercode", "frozenparindentcode", "frozenparfillskipcode", "frozenparfillleftskipcode", - "frozenadjustspacingcode", "frozenprotrudecharscode", "frozenpretolerancecode", "frozentolerancecode", - "frozenemergencystretchcode", "frozenloosenesscode", "frozenlastlinefitcode", "frozenlinepenaltycode", - "frozeninterlinepenaltycode", "frozenclubpenaltycode", "frozenwidowpenaltycode", - "frozendisplaywidowpenaltycode", "frozenbrokenpenaltycode", "frozenadjdemeritscode", - "frozendoublehyphendemeritscode", "frozenfinalhyphendemeritscode", "frozenparshapecode", - "frozeninterlinepenaltiescode", "frozenclubpenaltiescode", "frozenwidowpenaltiescode", - "frozendisplaywidowpenaltiescode", + "frozenhsizecode", "frozenskipcode", "frozenhangcode", "frozenindentcode", "frozenparfillcode", + "frozenadjustcode", "frozenprotrudecode", "frozentolerancecode", "frozenstretchcode", + "frozenloosenesscode", "frozenlastlinecode", "frozenlinepenaltycode", "frozenclubpenaltycode", + "frozenwidowpenaltycode", "frozendisplaypenaltycode", "frozenbrokenpenaltycode", + "frozendemeritscode", "frozenshapecode", "frozenlinecode", "frozenallcode", -- "activemathcharcode", -- @@ -85,7 +81,7 @@ return { -- "bottomlevelgroupcode", "simplegroupcode", "hboxgroupcode", "adjustedhboxgroupcode", "vboxgroupcode", "vtopgroupcode", "aligngroupcode", "noaligngroupcode", "outputgroupcode", "mathgroupcode", - "discgroupcode", "insertgroupcode", "vadjustgroupcode", "vcentergroupcode", "mathabovegroupcode", + "discretionarygroupcode", "insertgroupcode", "vadjustgroupcode", "vcentergroupcode", "mathabovegroupcode", "mathchoicegroupcode", "semisimplegroupcode", "mathshiftgroupcode", "mathleftgroupcode", "localboxgroupcode", "splitoffgroupcode", "splitkeepgroupcode", "preamblegroupcode", "alignsetgroupcode", "finrowgroupcode", "discretionarygroupcode", @@ -166,6 +162,14 @@ return { "permitgluehyphenationmodecode", "permitallhyphenationmodecode", "permitmathreplacehyphenationmodecode", -- "normalizelinemodecode", "indentskipmodecode", "swaphangindentmodecode", "swapparskipmodecode", "breakafterdirmodecode", + -- + "noligaturingcode", "nokerningcode", "noleftligaturecode", "noleftkerncode", "norightligaturecode", "norightkerncode", + "noexpansioncode", "noprotrusioncode", + -- + "frozenflagcode", "tolerantflagcode", "protectedflagcode", "primitiveflagcode", "permanentflagcode", "noalignedflagcode", "immutableflagcode", "mutableflagcode", + "globalflagcode", "overloadedflagcode", "immediateflagcode", "conditionalflagcode", "valueflagcode", "instanceflagcode", + -- + "continuewhenlmtxmode" }, ["helpers"] = { -- @@ -200,6 +204,7 @@ return { -- "strippedcsname","checkedstrippedcsname", -- + "nofarguments", "firstargumentfalse", "firstargumenttrue", "secondargumentfalse", "secondargumenttrue", "thirdargumentfalse", "thirdargumenttrue", @@ -477,7 +482,7 @@ return { "carryoverpar", "freezeparagraphproperties", "defrostparagraphproperties", "setparagraphfreezing", "forgetparagraphfreezing", - "updateparagraphproperties", "updateparagraphpenalties", "updateparagraphdemerits", "updateparagraphshapes", + "updateparagraphproperties", "updateparagraphpenalties", "updateparagraphdemerits", "updateparagraphshapes", "updateparagraphlines", -- "lastlinewidth", -- @@ -526,5 +531,13 @@ return { "ifbitwiseand", "bitwise", "bitwiseshift", "bitwiseflip", -- old ... very low level "textdir", "linedir", "pardir", "boxdir", + -- + "prelistbox", "postlistbox", "prelistcopy", "postlistcopy", "setprelistbox", "setpostlistbox", + -- + "noligaturing", "nokerning", "noexpansion", "noprotrusion", + -- + "futureletnexttoken", "defbackslashbreak", "letbackslashbreak", + -- + "pushoverloadmode", "popoverloadmode", } } diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua index 3f9b2e15a..1a2b9bfaa 100644 --- a/tex/context/base/mkiv/mult-prm.lua +++ b/tex/context/base/mkiv/mult-prm.lua @@ -54,6 +54,7 @@ return { "splitdiscards", "splitfirstmarks", "topmarks", + "tracingalignments", "tracingassigns", "tracinggroups", "tracingifs", @@ -234,6 +235,7 @@ return { "adjustspacingstretch", "afterassigned", "aftergrouped", + "aliased", "alignmark", "aligntab", "atendofgroup", @@ -246,7 +248,7 @@ return { "begincsname", "beginlocalcontrol", "boundary", - "boxattr", + "boxattribute", "boxdirection", "boxorientation", "boxtotal", @@ -261,9 +263,14 @@ return { "crampedscriptstyle", "crampedtextstyle", "csstring", + "defaliased", + "defcsname", "directlua", + "edefaliased", + "edefcsname", "efcode", "endlocalcontrol", + "enforced", "etoksapp", "etokspre", "everytab", @@ -278,6 +285,7 @@ return { "explicithyphenpenalty", "firstvalidlanguage", "fontid", + "fontspecifiedsize", "formatname", "frozen", "futuredef", @@ -288,6 +296,7 @@ return { "glet", "glyphdatafield", "glyphdimensionsmode", + "glyphoptions", "glyphscriptfield", "glyphstatefield", "gtoksapp", @@ -308,7 +317,7 @@ return { "ifcstok", "ifdimval", "ifempty", - "iffrozen", + "ifflags", "ifhastok", "ifhastoks", "ifhasxtoks", @@ -316,27 +325,29 @@ return { "ifmathparameter", "ifmathstyle", "ifnumval", - "ifprotected", + "ifparameter", "iftok", - "ifusercmd", "ignorearguments", "ignorepars", "immediate", - "immediateassigned", - "immediateassignment", + "immutable", "initcatcodetable", "insertht", + "instance", + "integerdef", "lastarguments", "lastnamedcs", "lastnodesubtype", "leftmarginkern", + "letaliased", "letcharcode", - "letdatacode", + "letcsname", "letfrozen", "letprotected", "linedirection", "linepar", "localbrokenpenalty", + "localcontrol", "localcontrolled", "localinterlinepenalty", "localleftbox", @@ -370,18 +381,21 @@ return { "mathstyle", "mathsurroundmode", "mathsurroundskip", + "mutable", + "noaligned", "noboundary", "nohrule", - "nokerns", - "noligs", "normalizelinemode", "nospaces", "novrule", "orelse", "orunless", "outputbox", + "overloaded", + "overloadmode", "parattr", "pardirection", + "permanent", "postexhyphenchar", "posthyphenchar", "prebinoppenalty", @@ -400,11 +414,13 @@ return { "setfontid", "snapshotpar", "supmarkmode", + "swapcsvalues", "textdirection", "thewithoutunit", "tokenized", "toksapp", "tokspre", + "tolerant", "tpack", "tracingfonts", "tracingmath", @@ -625,6 +641,7 @@ return { "font", "fontdimen", "fontname", + "fontspecifiedname", "futurelet", "gdef", "global", @@ -638,7 +655,6 @@ return { "hfill", "hfilneg", "hfuzz", - "hoffset", "holdinginserts", "hrule", "hsize", @@ -693,7 +709,6 @@ return { "looseness", "lower", "lowercase", - "mag", "mark", "mathaccent", "mathbin", @@ -712,6 +727,8 @@ return { "maxdeadcycles", "maxdepth", "meaning", + "meaningfull", + "meaningless", "medmuskip", "message", "middle", @@ -810,11 +827,14 @@ return { "thickmuskip", "thinmuskip", "time", + "todimension", + "tointeger", "toks", "toksdef", "tolerance", "topmark", "topskip", + "toscaled", "tracingcommands", "tracinglostchars", "tracingmacros", @@ -846,7 +866,6 @@ return { "vfill", "vfilneg", "vfuzz", - "voffset", "vrule", "vsize", "vskip", diff --git a/tex/context/base/mkiv/mult-sys.mkiv b/tex/context/base/mkiv/mult-sys.mkiv index f04f986fe..b4c006234 100644 --- a/tex/context/base/mkiv/mult-sys.mkiv +++ b/tex/context/base/mkiv/mult-sys.mkiv @@ -49,13 +49,13 @@ \definesystemconstant {bokmal} \definesystemconstant {nb} \definesystemconstant {catalan} \definesystemconstant {ca} \definesystemconstant {chinese} \definesystemconstant {cn} -\definesystemconstant {chinese} \definesystemconstant {cn} \definesystemconstant {croatian} \definesystemconstant {hr} \definesystemconstant {czech} \definesystemconstant {cs} \definesystemconstant {danish} \definesystemconstant {da} \definesystemconstant {dutch} \definesystemconstant {nl} \definesystemconstant {english} \definesystemconstant {en} \definesystemconstant {estonian} \definesystemconstant {et} +\definesystemconstant {esperanto} % \definesystemconstant {eo} \definesystemconstant {farsi} \definesystemconstant {fa} % just persian \definesystemconstant {finnish} \definesystemconstant {fi} \definesystemconstant {french} \definesystemconstant {fr} @@ -275,6 +275,7 @@ \definesystemconstant {start} \definesystemconstant {stop} \definesystemconstant {unknown} +\definesystemconstant {unexpanded} % translating setups is asking for a mess so we keep them as-is: @@ -408,8 +409,11 @@ \definesystemconstant {text} \definesystemconstant {paragraph} \definesystemconstant {margintext} +\definesystemconstant {themaintextcolor} \definesystemconstant {line} +\definesystemconstant {itemgroupcolumns} +\definesystemconstant {vfrac} \definesystemconstant {number} \definesystemconstant {symbol} \definesystemconstant {format} @@ -574,19 +578,19 @@ \defineinterfaceconstant {e} {e} % can go \defineinterfaceconstant {f} {f} % can go -\defineinterfaceconstant {s} {s} +%defineinterfaceconstant {s} {s} \defineinterfaceconstant {r} {r} \defineinterfaceconstant {g} {g} -\defineinterfaceconstant {b} {b} -\defineinterfaceconstant {c} {c} +%defineinterfaceconstant {b} {b} +%defineinterfaceconstant {c} {c} \defineinterfaceconstant {m} {m} -\defineinterfaceconstant {y} {y} +%defineinterfaceconstant {y} {y} \defineinterfaceconstant {k} {k} -\defineinterfaceconstant {a} {a} % alternative -\defineinterfaceconstant {t} {t} % transparency +%defineinterfaceconstant {a} {a} % alternative +%defineinterfaceconstant {t} {t} % transparency \defineinterfaceconstant {p} {p} % percentage -\defineinterfaceconstant {h} {h} -\defineinterfaceconstant {s} {s} +%defineinterfaceconstant {h} {h} +%defineinterfaceconstant {s} {s} \defineinterfaceconstant {v} {v} \defineinterfaceconstant {rgb} {rgb} @@ -673,7 +677,7 @@ \selectinterface -%D Ok, here are some more, because we've got ouselves some extensions to \CONTEXT. +%D Ok, here are some more, because we've got ourselves some extensions to \CONTEXT. \definemessageconstant {addresses} \definemessageconstant {documents} diff --git a/tex/context/base/mkiv/mult-sys.mkxl b/tex/context/base/mkiv/mult-sys.mkxl new file mode 100644 index 000000000..40fcb9c35 --- /dev/null +++ b/tex/context/base/mkiv/mult-sys.mkxl @@ -0,0 +1,596 @@ +%D \module +%D [ file=mult-sys, +%D version=1996.06.01, +%D title=\CONTEXT\ Multilingual Macros, +%D subtitle=System, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D In boring module we define a lot of obscure but useful system constants. +%D By doing so we save lots of memory while at the same time we prevent +%D ourself making typing errors. + +\writestatus{loading}{ConTeXt Multilingual Macros / System} + +\unprotect + +%D This file is mostly the same as the \MKII\ variant but we keep extending +%D \MKIV, so it was bout time to have a dedicated variant. +%D +%D The constants are grouped in such a way that there is a minimal change of +%D conflicts. +%D +%D \starttyping +%D \definesystemconstants {word} +%D \definemessageconstant {word} +%D \stoptyping +%D +%D This commands generate \type{\s!word} and \type{\m!word}. + +\definesystemconstant {hans} +\definesystemconstant {taco} +\definesystemconstant {wolfgang} + +%D First we define some system constants used for both the multi||lingual +%D interface and multi||linguag typesetting. + +% definesystemconstant {slovene} +% definesystemconstant {cz} +% definesystemconstant {vn} + +\definesystemconstant {afrikaans} \definesystemconstant {af} +\definesystemconstant {ancientgreek} \definesystemconstant {agr} +\definesystemconstant {ancientlatin} \definesystemconstant {ala} +\definesystemconstant {arabic} \definesystemconstant {ar} +\definesystemconstant {bokmal} \definesystemconstant {nb} +\definesystemconstant {catalan} \definesystemconstant {ca} +\definesystemconstant {chinese} \definesystemconstant {cn} +\definesystemconstant {croatian} \definesystemconstant {hr} +\definesystemconstant {czech} \definesystemconstant {cs} +\definesystemconstant {danish} \definesystemconstant {da} +\definesystemconstant {dutch} \definesystemconstant {nl} +\definesystemconstant {english} \definesystemconstant {en} +\definesystemconstant {estonian} \definesystemconstant {et} +\definesystemconstant {esperanto} % \definesystemconstant {eo} +\definesystemconstant {farsi} \definesystemconstant {fa} % just persian +\definesystemconstant {finnish} \definesystemconstant {fi} +\definesystemconstant {french} \definesystemconstant {fr} +\definesystemconstant {gbenglish} \definesystemconstant {gb} +\definesystemconstant {german} \definesystemconstant {de} +\definesystemconstant {greek} \definesystemconstant {gr} +\definesystemconstant {hebrew} \definesystemconstant {he} +\definesystemconstant {yiddish} \definesystemconstant {yi} +\definesystemconstant {hungarian} \definesystemconstant {hu} +\definesystemconstant {italian} \definesystemconstant {it} +\definesystemconstant {japanese} \definesystemconstant {ja} +\definesystemconstant {korean} \definesystemconstant {kr} +\definesystemconstant {latin} \definesystemconstant {la} +\definesystemconstant {lithuanian} \definesystemconstant {lt} +\definesystemconstant {malayalam} \definesystemconstant {ml} +\definesystemconstant {norwegian} \definesystemconstant {no} +\definesystemconstant {nynorsk} \definesystemconstant {nn} +\definesystemconstant {persian} \definesystemconstant {pe} +\definesystemconstant {polish} \definesystemconstant {pl} +\definesystemconstant {portuguese} \definesystemconstant {pt} +\definesystemconstant {romanian} \definesystemconstant {ro} +\definesystemconstant {russian} \definesystemconstant {ru} +\definesystemconstant {slovak} \definesystemconstant {sk} +\definesystemconstant {slovenian} \definesystemconstant {sl} +\definesystemconstant {spanish} \definesystemconstant {es} +\definesystemconstant {swedish} \definesystemconstant {sv} +\definesystemconstant {thai} \definesystemconstant {th} % mojca mentioned it at BT2013 but we need more info +\definesystemconstant {turkish} \definesystemconstant {tr} +\definesystemconstant {turkmen} \definesystemconstant {tk} +\definesystemconstant {ukenglish} \definesystemconstant {uk} +\definesystemconstant {ukrainian} \definesystemconstant {ua} +\definesystemconstant {usenglish} \definesystemconstant {us} +\definesystemconstant {vietnamese} \definesystemconstant {vi} + +%D For proper \UNICODE\ support we need a few font related constants. + +\definesystemconstant {action} +\definesystemconstant {all} +\definesystemconstant {ampersand} +\definesystemconstant {ascii} +\definesystemconstant {attribute} +\definesystemconstant {attr} +\definesystemconstant {author} +\definesystemconstant {auto} +\definesystemconstant {axis} +\definesystemconstant {a} +\definesystemconstant {bf} +\definesystemconstant {big} +\definesystemconstant {binary} +\definesystemconstant {bi} +\definesystemconstant {blackboard} +\definesystemconstant {black} +\definesystemconstant {BoldItalic} +\definesystemconstant {BoldSlanted} +\definesystemconstant {Bold} +\definesystemconstant {bold} +\definesystemconstant {both} +\definesystemconstant {bottomfloat} +\definesystemconstant {bottom} +\definesystemconstant {box} +\definesystemconstant {bp} +\definesystemconstant {bs} +\definesystemconstant {b} +\definesystemconstant {calligraphy} +\definesystemconstant {Calligraphy} +\definesystemconstant {Caps} +\definesystemconstant {casual} +\definesystemconstant {Casual} +\definesystemconstant {catcodes} +\definesystemconstant {catcodetable} +\definesystemconstant {cc} +\definesystemconstant {cg} +\definesystemconstant {chain} +\definesystemconstant {check} +\definesystemconstant {child} +\definesystemconstant {cite} +\definesystemconstant {class} +\definesystemconstant {clone} +\definesystemconstant {cmyk} +\definesystemconstant {cm} +\definesystemconstant {code} +\definesystemconstant {collapsing} +\definesystemconstant {command} +\definesystemconstant {compare} +\definesystemconstant {complex} +\definesystemconstant {counter} +\definesystemconstant {cramped} +\definesystemconstant {current} +\definesystemconstant {c} +\definesystemconstant {data} +\definesystemconstant {dd} +\definesystemconstant {decimal} +\definesystemconstant {DefaultFont} +\definesystemconstant {default} +\definesystemconstant {depth} +\definesystemconstant {designsize} +\definesystemconstant {direction} +\definesystemconstant {display} +\definesystemconstant {document} +\definesystemconstant {dodo} +\definesystemconstant {done} +\definesystemconstant {double} +\definesystemconstant {do} +\definesystemconstant {dtp} +\definesystemconstant {dummy} +\definesystemconstant {d} +\definesystemconstant {edge} +\definesystemconstant {effect} +\definesystemconstant {empty} +\definesystemconstant {em} +\definesystemconstant {environment} +\definesystemconstant {extensions} +\definesystemconstant {external} +\definesystemconstant {ex} +\definesystemconstant {e} +\definesystemconstant {fallbacks} +\definesystemconstant {fallback} +\definesystemconstant {false} +\definesystemconstant {fax} +\definesystemconstant {features} +\definesystemconstant {file} +\definesystemconstant {filll} +\definesystemconstant {fill} +\definesystemconstant {fil} +\definesystemconstant {first} +\definesystemconstant {float} +\definesystemconstant {font} +\definesystemconstant {forget} +\definesystemconstant {format} +\definesystemconstant {fraktur} +\definesystemconstant {full} +\definesystemconstant {f} +\definesystemconstant {global} +\definesystemconstant {goodies} +\definesystemconstant {gray} +\definesystemconstant {handler} +\definesystemconstant {handwriting} +\definesystemconstant {Handwriting} +\definesystemconstant {hascaption} +\definesystemconstant {haslevel} +\definesystemconstant {hasnumber} +\definesystemconstant {hasparent} +\definesystemconstant {hassuffix} +\definesystemconstant {hastitle} +\definesystemconstant {head} +\definesystemconstant {height} +\definesystemconstant {hw} +\definesystemconstant {hyphenmin} +\definesystemconstant {indeed} +\definesystemconstant {initializations} +\definesystemconstant {insert} % maybe insertclass +\definesystemconstant {integral} +\definesystemconstant {internal} +\definesystemconstant {in} +\definesystemconstant {italics} +\definesystemconstant {Italic} +\definesystemconstant {italic} +%definesystemconstant {it} +\definesystemconstant {itemgroupcolumns} +\definesystemconstant {kernpairs} +\definesystemconstant {language} +\definesystemconstant {lcgreek} +\definesystemconstant {lefthyphenchar} +\definesystemconstant {lefthyphenmin} +\definesystemconstant {leftpage} +\definesystemconstant {left} +\definesystemconstant {level} +\definesystemconstant {ligatures} +\definesystemconstant {line} +\definesystemconstant {link} +\definesystemconstant {list} +\definesystemconstant {local} +\definesystemconstant {lua} +\definesystemconstant {mapping} +\definesystemconstant {map} +\definesystemconstant {margintext} +\definesystemconstant {margin} +\definesystemconstant {marker} +\definesystemconstant {MathBold} % not used +\definesystemconstant {MathRomanBold} +\definesystemconstant {MathRoman} +\definesystemconstant {math} +\definesystemconstant {Math} % not used +\definesystemconstant {mblr} +\definesystemconstant {mbrl} +\definesystemconstant {mb} +\definesystemconstant {middle} +\definesystemconstant {minus} +\definesystemconstant {mixedcolumn} +\definesystemconstant {mi} % maybe some day a special default vector +\definesystemconstant {mkii} +\definesystemconstant {mkiv} +\definesystemconstant {mm} +\definesystemconstant {mnem} % kind of generic short tag +\definesystemconstant {mode} +\definesystemconstant {MonoBoldItalic} +\definesystemconstant {MonoBoldSlanted} +\definesystemconstant {MonoBold} +\definesystemconstant {MonoCaps} +\definesystemconstant {MonoItalic} +\definesystemconstant {MonoSlanted} +\definesystemconstant {Mono} +\definesystemconstant {mono} +\definesystemconstant {mrlr} +\definesystemconstant {mrrl} +\definesystemconstant {mr} +\definesystemconstant {multi} +\definesystemconstant {name} +\definesystemconstant {next} +\definesystemconstant {nocite} +\definesystemconstant {nodepth} +\definesystemconstant {noheight} +\definesystemconstant {nomath} +\definesystemconstant {none} +\definesystemconstant {normal} +\definesystemconstant {Normal} +\definesystemconstant {nowidth} +\definesystemconstant {numbering} +\definesystemconstant {number} +\definesystemconstant {options} +\definesystemconstant {ord} +\definesystemconstant {orientation} +\definesystemconstant {otr} +\definesystemconstant {pagefloat} +\definesystemconstant {page} +\definesystemconstant {paragraph} +\definesystemconstant {parent} +\definesystemconstant {patterns} +\definesystemconstant {pc} +\definesystemconstant {pickup} +\definesystemconstant {plural} +\definesystemconstant {plus} +%definesystemconstant {pt} +\definesystemconstant {realpage} +\definesystemconstant {register} +\definesystemconstant {Regular} +\definesystemconstant {regular} +\definesystemconstant {rel} +\definesystemconstant {reset} +\definesystemconstant {reverse} +\definesystemconstant {rgb} +\definesystemconstant {righthyphenchar} +\definesystemconstant {righthyphenmin} +\definesystemconstant {rightpage} +\definesystemconstant {right} +\definesystemconstant {rm} +\definesystemconstant {rname} +\definesystemconstant {rscale} +\definesystemconstant {SansBoldItalic} +\definesystemconstant {SansBoldSlanted} +\definesystemconstant {SansBold} +\definesystemconstant {SansCaps} +\definesystemconstant {SansItalic} +\definesystemconstant {SansSlanted} +\definesystemconstant {Sans} +\definesystemconstant {sans} +\definesystemconstant {scriptscript} +\definesystemconstant {script} +\definesystemconstant {sc} +\definesystemconstant {second} +\definesystemconstant {section} +\definesystemconstant {SerifBoldItalic} +\definesystemconstant {SerifBoldSlanted} +\definesystemconstant {SerifBold} +\definesystemconstant {SerifCaps} +\definesystemconstant {SerifItalic} +\definesystemconstant {SerifSlanted} +\definesystemconstant {Serif} +\definesystemconstant {serif} +\definesystemconstant {setups} +\definesystemconstant {setup} +\definesystemconstant {set} +\definesystemconstant {themaintextcolor} +\definesystemconstant {simple} +\definesystemconstant {Simple} +\definesystemconstant {single} +\definesystemconstant {singular} +\definesystemconstant {size} +\definesystemconstant {slanted} +\definesystemconstant {Slanted} +%definesystemconstant {sl} +\definesystemconstant {smallcaps} +\definesystemconstant {small} +\definesystemconstant {somewhere} +\definesystemconstant {special} +\definesystemconstant {spec} +\definesystemconstant {spot} +\definesystemconstant {spread} +\definesystemconstant {sp} +\definesystemconstant {ss} +\definesystemconstant {start} +\definesystemconstant {stop} +\definesystemconstant {subpage} +\definesystemconstant {subtype} +\definesystemconstant {sub} +\definesystemconstant {Support} +\definesystemconstant {sygreek} +\definesystemconstant {symbol} +\definesystemconstant {system} % not yet interfaces messages +\definesystemconstant {text} +\definesystemconstant {tex} +\definesystemconstant {tf} +\definesystemconstant {third} +\definesystemconstant {topfloat} +\definesystemconstant {top} +\definesystemconstant {to} +\definesystemconstant {traditional} +\definesystemconstant {triple} +\definesystemconstant {true} +\definesystemconstant {tt} +\definesystemconstant {Type} +\definesystemconstant {ucgreek} +\definesystemconstant {uncramped} +\definesystemconstant {unexpanded} +\definesystemconstant {Unicode} +\definesystemconstant {unknown} +\definesystemconstant {userdata} +\definesystemconstant {userpage} +\definesystemconstant {user} +\definesystemconstant {vfrac} +\definesystemconstant {white} +\definesystemconstant {width} +\definesystemconstant {xml} +\definesystemconstant {xmove} +\definesystemconstant {xoffset} +\definesystemconstant {xx} +\definesystemconstant {x} +\definesystemconstant {ymove} +\definesystemconstant {yoffset} + +%D As the name of their define command states, the next set of constants is used in +%D the message macro's. + +\definemessageconstant {backend} +\definemessageconstant {check} +\definemessageconstant {chemicals} +\definemessageconstant {colors} +\definemessageconstant {columns} +\definemessageconstant {fields} +\definemessageconstant {figures} +\definemessageconstant {files} +\definemessageconstant {floatblocks} +\definemessageconstant {fonts} +\definemessageconstant {handlings} +\definemessageconstant {interactions} +\definemessageconstant {javascripts} +\definemessageconstant {languages} +\definemessageconstant {layouts} +\definemessageconstant {lua} +\definemessageconstant {metapost} +\definemessageconstant {publications} +\definemessageconstant {references} +\definemessageconstant {regimes} +\definemessageconstant {structures} +\definemessageconstant {symbols} +\definemessageconstant {system} +\definemessageconstant {textblocks} +\definemessageconstant {verbatims} +\definemessageconstant {versions} + +%D When we use numbers and dimensions the same applies as with the keywords like +%D \type {width} and \type {plus} mentioned earlier. + +\immutable\def\!!ten {10} +\immutable\def\!!twelve {12} +\immutable\def\!!hundred {100} +\immutable\def\!!thousand {1000} +\immutable\def\!!tenthousand {10000} +\immutable\def\!!maxcard {65536} +\immutable\def\!!medcard {32768} + +\immutable\def\!!zeropoint {0pt} +\immutable\def\!!onepoint {1pt} +\immutable\def\!!twopoint {2pt} +\immutable\def\!!threepoint {3pt} +\immutable\def\!!fourpoint {4pt} +\immutable\def\!!fivepoint {5pt} +\immutable\def\!!sixpoint {6pt} +\immutable\def\!!sevenpoint {7pt} +\immutable\def\!!eightpoint {8pt} +\immutable\def\!!ninepoint {9pt} +\immutable\def\!!tenpoint {10pt} +\immutable\def\!!elevenpoint {11pt} +\immutable\def\!!twelvepoint {12pt} +\immutable\def\!!fourteenpointfour {14.4pt} + +\immutable\def\!!plustoken {+} % todo: \??plustoken +\immutable\def\!!minustoken {-} % todo: \??minustoken + +\immutable\def\__unknown__ {\string\\//} % unlikely value + +%D Variables are composed of a command specific tag and a user supplied variable +%D (system constant). The tag \type {du} for instance is available as \type {\??du} +%D and expands to \type {@@du} in composed variables. + +\definesystemvariable {du} % dummy, will stay + +% bibl: + +\definesystemvariable {pv} % PublicationVariable +\definesystemvariable {pb} % PuBlication + +% needs checking (namespaces now) + +\definesystemvariable {fw} % simpleFonts by Wolfgang + +% old pragma + +\definesystemvariable {kt} % KonTakten +\definesystemvariable {kw} % KontaktWaarde +\definesystemvariable {st} % STickers +\definesystemvariable {km} % KenMerk + +% mkii + +\definesystemvariable {xf} % XML File (xtag) +\definesystemvariable {xp} % XML Processing (xtag, so still needed) +\definesystemvariable {fo} % xml FO (xtag) +\definesystemvariable {fx} % FoXet + +% mkiv + +%D Next we define some language independant one letter variables and keywords. We can +%D actually make these system variables. + +\defineinterfaceconstant {x} {x} +\defineinterfaceconstant {y} {y} +\defineinterfaceconstant {w} {w} +\defineinterfaceconstant {h} {h} +\defineinterfaceconstant {s} {s} +\defineinterfaceconstant {t} {t} + +\defineinterfaceconstant {a} {a} % can go +\defineinterfaceconstant {b} {b} % can go +\defineinterfaceconstant {c} {c} % can go +\defineinterfaceconstant {d} {d} % can go +\defineinterfaceconstant {e} {e} % can go +\defineinterfaceconstant {f} {f} % can go + +%defineinterfaceconstant {s} {s} +\defineinterfaceconstant {r} {r} +\defineinterfaceconstant {g} {g} +%defineinterfaceconstant {b} {b} +%defineinterfaceconstant {c} {c} +\defineinterfaceconstant {m} {m} +%defineinterfaceconstant {y} {y} +\defineinterfaceconstant {k} {k} +%defineinterfaceconstant {a} {a} % alternative +%defineinterfaceconstant {t} {t} % transparency +\defineinterfaceconstant {p} {p} % percentage +%defineinterfaceconstant {h} {h} +%defineinterfaceconstant {s} {s} +\defineinterfaceconstant {v} {v} + +\defineinterfaceconstant {rgb} {rgb} +\defineinterfaceconstant {cmyk} {cmyk} +\defineinterfaceconstant {mp} {mp} + +\defineinterfacevariable {rgb} {rgb} +\defineinterfacevariable {cmyk} {cmyk} +\defineinterfacevariable {mp} {mp} + +\defineinterfacevariable {s} {s} + +\defineinterfacevariable {a} {a} +\defineinterfacevariable {b} {b} +\defineinterfacevariable {c} {c} +\defineinterfacevariable {d} {d} + +%D Special purpose variables: + +\immutable\def\v!oddeven#1{\ifodd#1\v!odd\else\v!even\fi} + +%D The names of files and their extensions are fixed. \CONTEXT\ uses as less +%D files as possible. Utility files can be recognized by the first two +%D characters of the extension: \type {tu}. + +%definefileconstant {utilityfilename} {texutil} +%definefileconstant {blockextension} {tub} +%definefileconstant {figureextension} {tuf} +%definefileconstant {inputextension} {tui} +%definefileconstant {outputextension} {tuo} % tup for previous run +%definefileconstant {optionextension} {top} +%definefileconstant {temporaryextension} {tmp} +%definefileconstant {patternsextension} {pat} +%definefileconstant {hyphensextension} {hyp} +%definefileconstant {fontmapextension} {map} +\definefileconstant {bibextension} {bbl} + +%D These files are loaded at start||up. They may contain system specific setups (or +%D calls to other files), old macro's, to garantee compatibility and new macro's noy +%D yet present in the format. + +\definefileconstant {sysfilename} {cont-sys.mkiv} +\definefileconstant {newfilename} {cont-new.mkiv} +\definefileconstant {locfilename} {cont-loc.mkiv} +\definefileconstant {expfilename} {cont-exp.mkiv} +\definefileconstant {fntfilename} {cont-fnt.mkiv} % not yet used +\definefileconstant {gdsfilename} {cont-fnt.lfg} % not yet used + +%D The setup files for the language, font, color and special subsystems have a common +%D prefix. This means that we have at most three characters for unique filenames. + +\definefileconstant {colo_run} {colo-run} +\definefileconstant {font_run} {font-run} +\definefileconstant {page_run} {page-run} +\definefileconstant {symb_run} {symb-run} +\definefileconstant {publ_tra} {publ-tra} + +%D For figure inclusion we need(ed): + +%defineinterfaceconstant {tif} {tif} +%defineinterfaceconstant {eps} {eps} +%defineinterfaceconstant {mps} {mps} +%defineinterfaceconstant {jpg} {jpg} +%defineinterfaceconstant {pdf} {pdf} +%defineinterfaceconstant {png} {png} +%defineinterfaceconstant {avi} {avi} +%defineinterfaceconstant {mov} {mov} +%defineinterfaceconstant {svg} {svg} +\defineinterfaceconstant {tex} {tex} % Also gone? +%defineinterfaceconstant {tmp} {tmp} +%defineinterfaceconstant {cld} {cld} + +%D A careful reader will have noticed that in the module \type {mult-ini} we defined +%D \type {\selectinterface}. We were not yet able to actually select an interface, +%D because we still had to define the constants and variables. Now we've done so, +%D selection is permitted. + +\selectinterface + +%D Ok, here are some more, because we've got ourselves some extensions to \CONTEXT. + +\definemessageconstant {addresses} +\definemessageconstant {documents} + +\protect \endinput diff --git a/tex/context/base/mkiv/node-aux.lmt b/tex/context/base/mkiv/node-aux.lmt index ada376556..d952ec41b 100644 --- a/tex/context/base/mkiv/node-aux.lmt +++ b/tex/context/base/mkiv/node-aux.lmt @@ -21,7 +21,7 @@ local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local attributelist_code = nodecodes.attributelist -- temporary -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local nuts = nodes.nuts local tonut = nuts.tonut @@ -364,9 +364,9 @@ end do - local localparcodes = nodes.localparcodes - local hmodepar_code = localparcodes.hmode_par - local vmodepar_code = localparcodes.vmode_par + local parcodes = nodes.parcodes + local hmodepar_code = parcodes.hmode_par + local vmodepar_code = parcodes.vmode_par local getnest = tex.getnest local getsubtype = nuts.getsubtype @@ -374,7 +374,7 @@ do function nuts.setparproperty(action,...) local tail = tonut(getnest().tail) while tail do - if getid(tail) == localpar_code then + if getid(tail) == par_code then local s = getsubtype(tail) if s == hmodepar_code or s == vmodepar_code then return action(tail,...) diff --git a/tex/context/base/mkiv/node-aux.lua b/tex/context/base/mkiv/node-aux.lua index aa7dc0292..d3c537a3b 100644 --- a/tex/context/base/mkiv/node-aux.lua +++ b/tex/context/base/mkiv/node-aux.lua @@ -21,7 +21,7 @@ local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local attributelist_code = nodecodes.attributelist -- temporary -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local nuts = nodes.nuts local tonut = nuts.tonut @@ -382,9 +382,9 @@ end do - local localparcodes = nodes.localparcodes - local hmodepar_code = localparcodes.vmode_par - local vmodepar_code = localparcodes.hmode_par + local parcodes = nodes.parcodes + local hmodepar_code = parcodes.vmode_par + local vmodepar_code = parcodes.hmode_par local getnest = tex.getnest local getsubtype = nuts.getsubtype @@ -392,7 +392,7 @@ do function nuts.setparproperty(action,...) local tail = tonut(getnest().tail) while tail do - if getid(tail) == localpar_code then + if getid(tail) == par_code then local s = getsubtype(tail) if s == hmodepar_code or s == vmodepar_code then return action(tail,...) diff --git a/tex/context/base/mkiv/node-cmp.lmt b/tex/context/base/mkiv/node-cmp.lmt index e9e7e266d..21fd700f0 100644 --- a/tex/context/base/mkiv/node-cmp.lmt +++ b/tex/context/base/mkiv/node-cmp.lmt @@ -192,7 +192,6 @@ end local uses_font = direct.uses_font local has_glyph = direct.has_glyph local protrusion_skippable = direct.protrusion_skippable -local prepend_prevdepth = direct.prepend_prevdepth local make_extensible = direct.make_extensible function node.uses_font(n,f) @@ -207,11 +206,6 @@ function node.protrusion_skippable(n) return protrusion_skippable(todirect(n)) end -function node.prepend_prevdepth(n) - local n, d = prepend_prevdepth(todirect(n)) - return tonode(n), d -end - function node.make_extensible(...) local n = make_extensible(...) return n and tonode(n) or nil diff --git a/tex/context/base/mkiv/node-fin.lua b/tex/context/base/mkiv/node-fin.lua index ddcdcd9d0..373cce3ce 100644 --- a/tex/context/base/mkiv/node-fin.lua +++ b/tex/context/base/mkiv/node-fin.lua @@ -636,100 +636,3 @@ end statistics.register("attribute processing time", function() return statistics.elapsedseconds(attributes,"front- and backend") end) - --- -- -- - --- do --- --- local cleaners = { } --- local trace = true -- false --- --- function attributes.cleanup() --- if next(cleaners) then --- local values = setmetatableindex("table") --- --- if trace then --- starttiming(values) --- end --- --- local function check(l) --- for n, id in nextnode, l do --- if id == hlist_code or id == vlist_code or id == glue_code then --- local l = getlist(n) --- if l then --- check(l) --- end --- end --- for a in next, cleaners do --- local v = getattr(n,a) --- if v then --- -- values[a] = values[a] + 1 --- values[a][v] = true --- end --- end --- end --- end --- --- local top = texgetnest("ptr") --- for i=1,top do --- local l = texgetnest(i) --- if l then --- check(tonut(l.head)) --- end --- end --- --- do local l --- l = tonut(texlists.page_ins_head) if l then check(l) end --- l = tonut(texlists.contrib_head) if l then check(l) end --- l = tonut(texlists.page_discards_head) if l then check(l) end --- l = tonut(texlists.split_discards_head) if l then check(l) end --- l = tonut(texlists.page_head) if l then check(l) end --- end --- --- -- todo: traverseboxes --- --- for i=0,65535 do --- local b = getbox(i) --- if b then --- local l = getlist(b) --- if l then --- check(l) --- end --- end --- end --- --- for a, t in next, values do --- cleaners[a](a,t) --- end --- --- if trace then --- stoptiming(values) --- local a = table.sortedkeys(values) --- local t = statistics.elapsedtime(values) --- local r = tex.getcount("realpageno") --- if #a == 0 then --- logs.report("attributes","cleaning up at page %i took %s seconds, no attributes",r,t) --- else --- logs.report("attributes","cleaning up at page %i took %s seconds, attributes: % t",r,t,a) --- end --- end --- end --- end --- --- -- not yet used but when we do ... delay a call till we enable it (attr-ini.mkiv) --- --- -- local function show(a,t) for k, v in next, t do print(a,k) end end --- -- --- -- attributes.registercleaner(1, show) --- -- attributes.registercleaner(2, show) --- --- function attributes.registercleaner(a,f) --- cleaners[a] = f --- end --- --- implement { --- name = "cleanupattributes", --- actions = attributes.cleanup, --- } --- --- end diff --git a/tex/context/base/mkiv/node-fin.mkiv b/tex/context/base/mkiv/node-fin.mkiv index 81a8fec51..2bf0e0806 100644 --- a/tex/context/base/mkiv/node-fin.mkiv +++ b/tex/context/base/mkiv/node-fin.mkiv @@ -19,6 +19,7 @@ \unprotect \registerctxluafile{node-shp}{optimize} +% \registerctxluafile{node-fin}{autosuffix,optimize} % we might generalize this one \registerctxluafile{node-fin}{optimize} % we might generalize this one % we might have two variants at some point (efficiency) diff --git a/tex/context/base/mkiv/node-ini.lmt b/tex/context/base/mkiv/node-ini.lmt index f43896d79..5cce9030d 100644 --- a/tex/context/base/mkiv/node-ini.lmt +++ b/tex/context/base/mkiv/node-ini.lmt @@ -43,8 +43,6 @@ local dircodes = mark(getsubtypes("dir")) local glyphcodes = mark(getsubtypes("glyph")) local disccodes = mark(getsubtypes("disc")) local gluecodes = mark(getsubtypes("glue")) -local leadercodes = mark(getsubtypes("leader")) -local fillcodes = mark(getsubtypes("fill")) local boundarycodes = mark(getsubtypes("boundary")) local penaltycodes = mark(getsubtypes("penalty")) local kerncodes = mark(getsubtypes("kern")) @@ -54,7 +52,10 @@ local radicalcodes = mark(getsubtypes("radical")) local accentcodes = mark(getsubtypes("accent")) local fencecodes = mark(getsubtypes("fence")) ----- fractioncodes = mark(getsubtypes("fraction")) -local localparcodes = mark(getsubtypes("localpar")) +local parcodes = mark(getsubtypes("par")) + +local fillvalues = mark(getvalues("fill")) +local dirvalues = mark(getvalues("dir")) local function simplified(t) local r = { } @@ -65,12 +66,8 @@ local function simplified(t) end local nodecodes = simplified(node.types()) -local whatcodes = simplified(node.whatsits and node.whatsits() or { }) - -local dirvalues = mark(getvalues("dir")) -local gluevalues = mark(getvalues("glue")) -local whatcodes = { +local whatcodes = allocate { literal = 0x1, [0x1] = "literal", latelua = 0x2, [0x2] = "latelua", userdefined = 0x3, [0x3] = "userdefined", @@ -127,70 +124,112 @@ glyphcodes = allocate(swapped(glyphcodes,glyphcodes)) kerncodes = allocate(swapped(kerncodes,kerncodes)) penaltycodes = allocate(swapped(penaltycodes,penaltycodes)) mathcodes = allocate(swapped(mathcodes,mathcodes)) -fillcodes = allocate(swapped(fillcodes,fillcodes)) disccodes = allocate(swapped(disccodes,disccodes)) accentcodes = allocate(swapped(accentcodes,accentcodes)) fencecodes = allocate(swapped(fencecodes,fencecodes)) -localparcodes = allocate(swapped(localparcodes,localparcodes)) +parcodes = allocate(swapped(parcodes,parcodes)) rulecodes = allocate(swapped(rulecodes,rulecodes)) -leadercodes = allocate(swapped(leadercodes,leadercodes)) usercodes = allocate(swapped(usercodes,usercodes)) noadoptions = allocate(swapped(noadoptions,noadoptions)) + dirvalues = allocate(swapped(dirvalues,dirvalues)) -gluevalues = allocate(swapped(gluevalues,gluevalues)) literalvalues = allocate(swapped(literalvalues,literalvalues)) +fillvalues = allocate(swapped(fillvalues,fillvalues)) nodes.gluecodes = gluecodes nodes.dircodes = dircodes nodes.boundarycodes = boundarycodes nodes.noadcodes = noadcodes -nodes.nodecodes = nodecodes nodes.whatcodes = whatcodes nodes.listcodes = listcodes nodes.glyphcodes = glyphcodes nodes.kerncodes = kerncodes nodes.penaltycodes = penaltycodes nodes.mathcodes = mathcodes -nodes.fillcodes = fillcodes nodes.disccodes = disccodes nodes.accentcodes = accentcodes nodes.radicalcodes = radicalcodes nodes.fencecodes = fencecodes -nodes.localparcodes = localparcodes +nodes.parcodes = parcodes nodes.rulecodes = rulecodes -nodes.leadercodes = leadercodes nodes.usercodes = usercodes + nodes.noadoptions = noadoptions +nodes.fillvalues = fillvalues +nodes.fillcodes = fillvalues -- for now nodes.dirvalues = dirvalues -nodes.gluevalues = gluevalues nodes.literalvalues = literalvalues -nodes.subtypes = allocate { - [nodecodes.accent] = accentcodes, - [nodecodes.boundary] = boundarycodes, - [nodecodes.dir] = dircodes, - [nodecodes.disc] = disccodes, - [nodecodes.fence] = fencecodes, - [nodecodes.glue] = gluecodes, - [nodecodes.glyph] = glyphcodes, - [nodecodes.hlist] = listcodes, - [nodecodes.kern] = kerncodes, - [nodecodes.localpar] = localparcodes, - [nodecodes.math] = mathcodes, - [nodecodes.noad] = noadcodes, - [nodecodes.penalty] = penaltycodes, - [nodecodes.radical] = radicalcodes, - [nodecodes.rule] = rulecodes, - -- [nodecodes.user] = usercodes, - [nodecodes.vlist] = listcodes, - [nodecodes.whatsit] = whatcodes, +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, + boundary = boundarycodes, + noad = noadcodes, + whatsit = whatcodes, + glyph = glyphcodes, + kern = kerncodes, + penalty = penaltycodes, + math = mathcodes, + disc = disccodes, + accent = accentcodes, + radical = radicalcodes, + fence = fencecodes, + par = parcodes, + rule = rulecodes, + + vlist = listcodes, + hlist = listcodes, + + -- list = listcodes, + + -- parameter = parametercodes, + -- user = usercodes, } -table.setmetatableindex(nodes.subtypes,function(t,k) - local v = { } - t[k] = v - return v -end) +for k, v in table.sortedhash(subtypes) do + local i = nodecodes[k] + if i and not subtypes[i] then + subtypes[i] = v + end +end + +nodes.subtypes = subtypes -- a few more friendly aliases: @@ -198,12 +237,15 @@ nodes.skipcodes = gluecodes nodes.directioncodes = dircodes nodes.whatsitcodes = whatcodes nodes.discretionarycodes = disccodes + nodes.directionvalues = dirvalues -nodes.skipvalues = gluevalues nodes.literalvalues = literalvalues glyphcodes.glyph = glyphcodes.character +gluecodes.parfillrightskip = gluecodes.parfillrightskip or gluecodes.parfillskip +gluecodes.parfillskip = gluecodes.parfillskip or gluecodes.parfillrightskip + listcodes.row = listcodes.alignment listcodes.column = listcodes.alignment @@ -212,28 +254,6 @@ kerncodes.italiccorrection = kerncodes.italiccorrection or 1 -- new literalvalues.direct = literalvalues.always -nodes.codes = allocate { -- mostly for listing - glue = skipcodes, - boundary = boundarycodes, - noad = noadcodes, - node = nodecodes, - hlist = listcodes, - vlist = listcodes, - glyph = glyphcodes, - kern = kerncodes, - penalty = penaltycodes, - math = mathnodes, - fill = fillcodes, - disc = disccodes, - whatsit = whatcodes, - accent = accentcodes, - fence = fencecodes, - rule = rulecodes, - leader = leadercodes, - user = usercodes, - noadoptions = noadoptions, -} - nodes.noadoptions = { set = 0x08, unused_1 = 0x00 + 0x08, @@ -246,36 +266,15 @@ nodes.noadoptions = { right = 0x14 + 0x08, } -local report_codes = logs.reporter("nodes","codes") - -function nodes.showcodes() - local t = { } - for name, codes in sortedhash(nodes.codes) do - local sorted = sortedkeys(codes) - for i=1,#sorted do - local s = sorted[i] - if type(s) ~= "number" then - t[#t+1] = { name, s, codes[s] } - end - end - end - formatcolumns(t) - for k=1,#t do - report_codes (t[k]) - end -end - -trackers.register("system.showcodes", nodes.showcodes) - -- We use the real node code numbers. -local texchardef = tex.chardef +local texsetintegervalue = tex.setintegervalue for i=0,nodecodes.glyph do - texchardef(nodecodes[i] .. "nodecode",i) + texsetintegervalue(nodecodes[i] .. "nodecode",i,"immutable") end for i=0,#gluecodes do - texchardef(gluecodes[i] .. "subtypecode",i) + texsetintegervalue(gluecodes[i] .. "subtypecode",i,"immutable") end -- tex.set("internalcodesmode",1) -- obsolete diff --git a/tex/context/base/mkiv/node-ini.lua b/tex/context/base/mkiv/node-ini.lua index ccbd726d9..3d49d01bd 100644 --- a/tex/context/base/mkiv/node-ini.lua +++ b/tex/context/base/mkiv/node-ini.lua @@ -78,7 +78,6 @@ local dircodes = mark(getsubtypes("dir")) local glyphcodes = mark(getsubtypes("glyph")) local disccodes = mark(getsubtypes("disc")) local gluecodes = mark(getsubtypes("glue")) -local leadercodes = mark(getsubtypes("leader")) local fillcodes = mark(getsubtypes("fill")) local boundarycodes = mark(getsubtypes("boundary")) local penaltycodes = mark(getsubtypes("penalty")) @@ -90,7 +89,7 @@ local radicalcodes = mark(getsubtypes("radical")) local accentcodes = mark(getsubtypes("accent")) local fencecodes = mark(getsubtypes("fence")) ----- fractioncodes = mark(getsubtypes("fraction")) -local localparcodes = allocate { [0] = "vmode_par", "local_box", "hmode_par", "penalty", "math" } +local parcodes = allocate { [0] = "vmode_par", "local_box", "hmode_par", "penalty", "math" } local function simplified(t) local r = { } @@ -160,15 +159,28 @@ margincodes = allocate(swapped(margincodes,margincodes)) disccodes = allocate(swapped(disccodes,disccodes)) accentcodes = allocate(swapped(accentcodes,accentcodes)) fencecodes = allocate(swapped(fencecodes,fencecodes)) -localparcodes = allocate(swapped(localparcodes,localparcodes)) +parcodes = allocate(swapped(parcodes,parcodes)) rulecodes = allocate(swapped(rulecodes,rulecodes)) -leadercodes = allocate(swapped(leadercodes,leadercodes)) usercodes = allocate(swapped(usercodes,usercodes)) noadoptions = allocate(swapped(noadoptions,noadoptions)) dirvalues = allocate(swapped(dirvalues,dirvalues)) gluevalues = allocate(swapped(gluevalues,gluevalues)) literalvalues = allocate(swapped(literalvalues,literalvalues)) +if not nodecodes.delimiter then + -- as in luametatex / lmtx + nodecodes.delimiter = nodecodes.delim + nodecodes[nodecodes.delimiter] = "delimiter" + nodecodes.delim = nil +end + +if not nodecodes.par then + -- as in luametatex / lmtx + local p = nodecodes.localpar + nodecodes.par = p + nodecodes[p] = "par" +end + if not gluecodes.indentskip then gluecodes.indentskip = gluecodes.userskip gluecodes.lefthangskip = gluecodes.userskip @@ -179,18 +191,7 @@ if not gluecodes.indentskip then gluecodes.parfillrightskip = gluecodes.parfillskip end -if CONTEXTLMTXMODE > 0 then - whatcodes.literal = 0x1 whatcodes[0x1] = "literal" - whatcodes.latelua = 0x2 whatcodes[0x2] = "latelua" - whatcodes.userdefined = 0x3 whatcodes[0x3] = "userdefined" - whatcodes.savepos = 0x4 whatcodes[0x4] = "savepos" - whatcodes.save = 0x5 whatcodes[0x5] = "save" - whatcodes.restore = 0x6 whatcodes[0x6] = "restore" - whatcodes.setmatrix = 0x7 whatcodes[0x7] = "setmatrix" - whatcodes.open = 0x8 whatcodes[0x8] = "open" - whatcodes.close = 0x9 whatcodes[0x9] = "close" - whatcodes.write = 0xA whatcodes[0xA] = "write" -elseif not whatcodes.literal then +if not whatcodes.literal then whatcodes.literal = whatcodes.pdfliteral whatcodes.save = whatcodes.pdfsave whatcodes.restore = whatcodes.pdfrestore @@ -214,9 +215,8 @@ nodes.disccodes = disccodes nodes.accentcodes = accentcodes nodes.radicalcodes = radicalcodes nodes.fencecodes = fencecodes -nodes.localparcodes = localparcodes +nodes.parcodes = parcodes nodes.rulecodes = rulecodes -nodes.leadercodes = leadercodes nodes.usercodes = usercodes nodes.noadoptions = noadoptions nodes.dirvalues = dirvalues @@ -233,7 +233,7 @@ nodes.subtypes = allocate { [nodecodes.glyph] = glyphcodes, [nodecodes.hlist] = listcodes, [nodecodes.kern] = kerncodes, - [nodecodes.localpar] = localparcodes, + [nodecodes.par] = parcodes, -- [nodecodes.marginkern] = margincodes, [nodecodes.math] = mathcodes, [nodecodes.noad] = noadcodes, @@ -295,7 +295,6 @@ nodes.codes = allocate { -- mostly for listing accent = accentcodes, fence = fencecodes, rule = rulecodes, - leader = leadercodes, user = usercodes, noadoptions = noadoptions, } diff --git a/tex/context/base/mkiv/node-ini.mkiv b/tex/context/base/mkiv/node-ini.mkiv index 8a3aa65df..b52695ef6 100644 --- a/tex/context/base/mkiv/node-ini.mkiv +++ b/tex/context/base/mkiv/node-ini.mkiv @@ -32,16 +32,16 @@ \registerctxluafile{node-tra}{} % we might split it off (module) \registerctxluafile{node-snp}{autosuffix} \registerctxluafile{node-tsk}{} -\registerctxluafile{node-tex}{} +\registerctxluafile{node-tex}{autosuffix} \registerctxluafile{node-dir}{} % experimental, not yet (and maybe never) used \registerctxluafile{node-pro}{} -\registerctxluafile{node-ser}{} +\registerctxluafile{node-ser}{autosuffix} \registerctxluafile{node-ext}{} \registerctxluafile{node-acc}{} % experimental %registerctxluafile{node-prp}{} % makes no sense (yet) \registerctxluafile{node-scn}{} \registerctxluafile{node-syn}{} -\registerctxluafile{node-par}{} +\registerctxluafile{node-par}{autosuffix} \newcount\c_node_tracers_show_box % box number diff --git a/tex/context/base/mkiv/node-ltp.lua b/tex/context/base/mkiv/node-ltp.lua index 6a36adf68..cf1d662a3 100644 --- a/tex/context/base/mkiv/node-ltp.lua +++ b/tex/context/base/mkiv/node-ltp.lua @@ -281,10 +281,10 @@ local unset_code = nodecodes.unset local marginkern_code = nodecodes.marginkern local dir_code = nodecodes.dir local boundary_code = nodecodes.boundary -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local protrusionboundary_code = nodes.boundarycodes.protrusion -local leaders_code = nodes.leadercodes.leaders +local leaders_code = nodes.gluecodes.leaders local indentlist_code = nodes.listcodes.indent local ligatureglyph_code = nodes.glyphcodes.ligature local cancel_code = nodes.dircodes.cancel @@ -1323,7 +1323,7 @@ do while current_break do - -- hm, here we have head == localpar and in the engine it's a temp node + -- hm, here we have head == par and in the engine it's a temp node head = inject_dirs_at_begin_of_line(dirstack,head) @@ -1463,7 +1463,7 @@ do p = nil end break - elseif id == localpar_code then + elseif id == par_code then break elseif id == temp_code then -- Go on. @@ -1560,29 +1560,29 @@ do start = insert_node_before(start,start,ls) end if normalize > 0 then - local localpar = nil - local localdir = nil + local par = nil + local dir = nil local indent = nil - local localpars = nil + local pars = nil local notflocal = 0 for n, id, subtype in nextnode, start do if id == hlist_code then if normalize > 1 and subtype == indentlist_code then indent = n end - elseif id == localpar_code then + elseif id == par_code then if start_of_par(n) then --- maybe subtype check instead - localpar = n + par = n elseif noflocals then noflocals = noflocals + 1 - localpars[noflocals] = n + pars[noflocals] = n else noflocals = 1 - localpars = { n } + pars = { n } end elseif id == dir_code then - if localpar and not localdir and subtype(n) == cancel_code then - localdir = n + if par and not dir and subtype(n) == cancel_code then + dir = n end end end @@ -1591,14 +1591,14 @@ do setattributelist(i,start) replace_node(indent,i) end - if localdir then - local d = new_direction((getdirection(localpar))) + if dir then + local d = new_direction((getdirection(par))) setattributelist(d,start) - replace_node(localpar,d) + replace_node(par,d) end - if localpars then + if pars then for i=1,noflocals do - start = remove_node(start,localpars[i],true) + start = remove_node(start,pars[i],true) end end end @@ -1719,7 +1719,7 @@ do local id = getid(next) if id == glyph_code then break - elseif id == localpar_code then + elseif id == par_code then -- nothing elseif id < math_code then -- messy criterium @@ -1756,7 +1756,7 @@ par.head = head if getnext(h) then report_parbuilders("something is left over") end - if getid(h) ~= localpar_code then + if getid(h) ~= par_code then report_parbuilders("no local par node") end end @@ -2454,7 +2454,7 @@ par.head = head if current then local id = getid(current) - if id == localpar_code then + if id == par_code then par.init_internal_left_box = getfield(current,"box_left") par.init_internal_left_box_width = getfield(current,"box_left_width") par.internal_pen_inter = getfield(current,"pen_inter") @@ -2617,7 +2617,7 @@ par.head = head p_active, n_active = try_break(getpenalty(current), unhyphenated_code, par, first_p, current, checked_expansion) elseif id == dir_code then par.line_break_dir = checked_line_dir(dirstack,current) or par.line_break_dir - elseif id == localpar_code then + elseif id == par_code then par.internal_pen_inter = getfield(current,"pen_inter") par.internal_pen_broken = getfield(current,"pen_broken") par.internal_left_box = getfield(current,"box_left") diff --git a/tex/context/base/mkiv/node-nut.lmt b/tex/context/base/mkiv/node-nut.lmt index d9edf2114..6b9dd803e 100644 --- a/tex/context/base/mkiv/node-nut.lmt +++ b/tex/context/base/mkiv/node-nut.lmt @@ -66,6 +66,7 @@ local nuts = { free = direct.free, getsynctexfields = direct.get_synctex_fields, getattr = direct.get_attribute, + getattrs = direct.get_attributes, getattributelist = direct.getattributelist, getattrlist = direct.getattributelist, getboth = d_getboth, @@ -88,8 +89,8 @@ local nuts = { getheight = direct.getheight, getid = d_getid, getkern = direct.getkern, - getlang = direct.getlang, - getlanguage = direct.getlang, + getlang = direct.getlanguage,-- will become obsolete + getlanguage = direct.getlanguage, getleader = direct.getleader, getlist = d_getlist, getnext = d_getnext, @@ -97,6 +98,7 @@ local nuts = { getnucleus = direct.getnucleus, getoffsets = direct.getoffsets, getorientation = direct.getorientation, + getoptions = direct.getoptions, getpenalty = direct.getpenalty, getpost = direct.getpost, getpre = direct.getpre, @@ -141,11 +143,13 @@ local nuts = { protect_glyphs = direct.protect_glyphs, protrusion_skippable = direct.protrusion_skippable, rangedimensions = direct.rangedimensions, + getglyphdimensions = direct.getglyphdimensions, + getkerndimension = direct.getkerndimension, remove = d_remove_node, reverse = direct.reverse, set_attribute = direct.set_attribute, - setsynctexfields = direct.set_synctex_fields, setattr = direct.set_attribute, + setattrs = direct.set_attributes, setattributelist = direct.setattributelist, setattrlist = direct.setattributelist, setboth = direct.setboth, @@ -167,8 +171,8 @@ local nuts = { setglyphdata = direct.setglyphdata, setheight = direct.setheight, setkern = direct.setkern, - setlang = direct.setlang, - setlanguage = direct.setlang, + setlang = direct.setlanguage, + setlanguage = direct.setlanguage, setleader = direct.setleader, setlink = d_setlink, setlist = direct.setlist, @@ -176,6 +180,7 @@ local nuts = { setnucleus = direct.setnucleus, setoffsets = direct.setoffsets, setorientation = direct.setorientation, + setoptions = direct.setoptions, setpenalty = direct.setpenalty, setpost = direct.setpost, setpre = direct.setpre, @@ -192,6 +197,7 @@ local nuts = { setsup = direct.setsup, setsuppre = direct.setsuppre, setsurround = direct.setkern, + setsynctexfields = direct.set_synctex_fields, setvalue = direct.setdata, -- obsolete setwhd = direct.setwhd, setwidth = direct.setwidth, @@ -207,6 +213,7 @@ local nuts = { traverse_glyph = direct.traverse_glyph, traverse_id = direct.traverse_id, traverse_list = direct.traverse_list, + traverse_content = direct.traverse_content, unprotect_glyph = direct.unprotect_glyph, unprotect_glyphs = direct.unprotect_glyphs, unset_attribute = direct.unset_attribute, @@ -215,9 +222,9 @@ local nuts = { vpack = direct.vpack, writable_spec = direct.writable_spec, write = direct.write, + append = direct.append, } - nodes.nuts = nuts nodes.is_node = is_node diff --git a/tex/context/base/mkiv/node-nut.lua b/tex/context/base/mkiv/node-nut.lua index 68d238b1a..c73397305 100644 --- a/tex/context/base/mkiv/node-nut.lua +++ b/tex/context/base/mkiv/node-nut.lua @@ -309,6 +309,11 @@ nuts.setglyphdata = direct.setglyphdata or function(n,d) set_attribute(n,0,d nuts.getruledata = direct.getglyphdata and getdata or function(n) return getfield(n,"transform") end nuts.setruledata = direct.setglyphdata and setdata or function(n,d) return setfield(n,"transform",d) end +-- maybe some day: [g|s]etglyphoptions and then use attribute for mkiv / generic but not now + +nuts.getoptions = direct.getoptions or function() return 0 end +nuts.setoptions = direct.setoptions or function() end + -- so far nuts.getnucleus = direct.getnucleus @@ -414,9 +419,9 @@ end if not nuts.start_of_par then - local localparcodes = nodes.localparcodes - local hmodepar_code = localparcodes.vmode_par - local vmodepar_code = localparcodes.hmode_par + local parcodes = nodes.parcodes + local hmodepar_code = parcodes.vmode_par + local vmodepar_code = parcodes.hmode_par local getsubtype = nuts.getsubtype diff --git a/tex/context/base/mkiv/node-par.lmt b/tex/context/base/mkiv/node-par.lmt new file mode 100644 index 000000000..af3125d23 --- /dev/null +++ b/tex/context/base/mkiv/node-par.lmt @@ -0,0 +1,48 @@ +if not modules then modules = { } end modules ['node-par'] = { + version = 1.001, + comment = "companion to node-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming + +local sequencers = utilities.sequencers + +-- This are called a lot! + +local actions = nodes.tasks.actions("everypar") + +local function everypar(head) + starttiming(builders) + head = actions(head) + stoptiming(builders) + return head +end + +callbacks.register("insert_par",everypar,"after paragraph start") + +local actions = sequencers.new { + name = "paragraph", + arguments = "mode,indented", + returnvalues = "indented", + results = "indented", +} + +sequencers.appendgroup(actions,"before") -- user +sequencers.appendgroup(actions,"system") -- private +sequencers.appendgroup(actions,"after" ) -- user + +local function paragraph(mode,indented) + local runner = actions.runner + if runner then + starttiming(builders) + indented = runner(mode,indented) + stoptiming(builders) + end + return indented +end + +callbacks.register("begin_paragraph",paragraph,"before paragraph start") diff --git a/tex/context/base/mkiv/node-par.lua b/tex/context/base/mkiv/node-par.lua index d89edf6f4..5a0f0d2e9 100644 --- a/tex/context/base/mkiv/node-par.lua +++ b/tex/context/base/mkiv/node-par.lua @@ -25,7 +25,7 @@ end callbacks.register("insert_local_par",everypar,"after paragraph start") local actions = sequencers.new { - name = "newgraf", + name = "paragraph", arguments = "mode,indented", returnvalues = "indented", results = "indented", @@ -35,7 +35,7 @@ sequencers.appendgroup(actions,"before") -- user sequencers.appendgroup(actions,"system") -- private sequencers.appendgroup(actions,"after" ) -- user -local function newgraf(mode,indented) +local function paragraph(mode,indented) local runner = actions.runner if runner then starttiming(builders) @@ -45,4 +45,4 @@ local function newgraf(mode,indented) return indented end -callbacks.register("new_graf",newgraf,"before paragraph start") +callbacks.register("new_graf",paragraph,"before paragraph start") diff --git a/tex/context/base/mkiv/node-ref.lua b/tex/context/base/mkiv/node-ref.lua index 2e035b2e0..2094fc2c7 100644 --- a/tex/context/base/mkiv/node-ref.lua +++ b/tex/context/base/mkiv/node-ref.lua @@ -94,7 +94,7 @@ local glue_code = nodecodes.glue local glyph_code = nodecodes.glyph local rule_code = nodecodes.rule local dir_code = nodecodes.dir -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local leftskip_code = gluecodes.leftskip local rightskip_code = gluecodes.rightskip @@ -420,7 +420,7 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx elseif id == dir_code then local direction, pop = getdirection(current) txtdir = not pop and direction -- we might need a stack - elseif id == localpar_code then + elseif id == par_code then if start_of_par(current) then pardir = getdirection(current) end diff --git a/tex/context/base/mkiv/node-res.lua b/tex/context/base/mkiv/node-res.lua index c27059003..03de8f843 100644 --- a/tex/context/base/mkiv/node-res.lua +++ b/tex/context/base/mkiv/node-res.lua @@ -26,7 +26,6 @@ local gluecodes = nodes.gluecodes local kerncodes = nodes.kerncodes local rulecodes = nodes.rulecodes local nodecodes = nodes.nodecodes -local leadercodes = nodes.leadercodes local boundarycodes = nodes.boundarycodes local usercodes = nodes.usercodes @@ -200,7 +199,7 @@ local correctionskip = register_nut(new_nut(glue_code,gluecodes.correctionski local temp = register_nut(new_nut(nodecodes.temp,0)) local noad = register_nut(new_nut(nodecodes.noad)) -local delimiter = register_nut(new_nut(nodecodes.delim)) +local delimiter = register_nut(new_nut(nodecodes.delimiter)) local fence = register_nut(new_nut(nodecodes.fence)) local submlist = register_nut(new_nut(nodecodes.submlist)) local accent = register_nut(new_nut(nodecodes.accent)) @@ -214,7 +213,7 @@ local choice = register_nut(new_nut(nodecodes.choice)) local boundary = register_nut(new_nut(nodecodes.boundary,boundarycodes.user)) local wordboundary = register_nut(new_nut(nodecodes.boundary,boundarycodes.word)) -local cleader = register_nut(copy_nut(glue)) setsubtype(cleader,leadercodes.cleaders) setglue(cleader,0,65536,0,2,0) +local cleader = register_nut(copy_nut(glue)) setsubtype(cleader,gluecodes.cleaders) setglue(cleader,0,65536,0,2,0) -- the dir field needs to be set otherwise crash: @@ -627,10 +626,10 @@ do return v end) - traversers.node = nodes.traverse (glyph) - traversers.char = nodes.traverse_char (glyph) - if nuts.traverse_glyph then traversers.glyph = nodes.traverse_glyph(glyph) end - if nuts.traverse_list then traversers.list = nodes.traverse_list (glyph) end + traversers.node = nodes.traverse (glyph) + traversers.char = nodes.traverse_char (glyph) + if nuts.traverse_glyph then traversers.glyph = nodes.traverse_glyph (glyph) end + if nuts.traverse_list then traversers.list = nodes.traverse_list (glyph) end nodes.traversers = traversers @@ -647,10 +646,11 @@ do return v end) - traversers.node = nuts.traverse (glyph) - traversers.char = nuts.traverse_char (glyph) - if nuts.traverse_glyph then traversers.glyph = nuts.traverse_glyph(glyph) end - if nuts.traverse_list then traversers.list = nuts.traverse_list (glyph) end + traversers.node = nuts.traverse (glyph) + traversers.char = nuts.traverse_char (glyph) + if nuts.traverse_glyph then traversers.glyph = nuts.traverse_glyph (glyph) end + if nuts.traverse_list then traversers.list = nuts.traverse_list (glyph) end + if nuts.traverse_content then traversers.content = nuts.traverse_content(glyph) end nuts.traversers = traversers diff --git a/tex/context/base/mkiv/node-rul.lua b/tex/context/base/mkiv/node-rul.lua index 830d97ff6..f60fb2406 100644 --- a/tex/context/base/mkiv/node-rul.lua +++ b/tex/context/base/mkiv/node-rul.lua @@ -75,7 +75,7 @@ local gluecodes = nodes.gluecodes local listcodes = nodes.listcodes local glyph_code = nodecodes.glyph -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local dir_code = nodecodes.dir local glue_code = nodecodes.glue local hlist_code = nodecodes.hlist @@ -588,7 +588,7 @@ function linefillers.handler(head) else break end - elseif id == localpar_code or id == dir_code then + elseif id == par_code or id == dir_code then -- go on elseif id == hlist_code then if getsubtype(head) == indentlist_code then diff --git a/tex/context/base/mkiv/node-scn.lua b/tex/context/base/mkiv/node-scn.lua index 055f5e20d..0ec1ba387 100644 --- a/tex/context/base/mkiv/node-scn.lua +++ b/tex/context/base/mkiv/node-scn.lua @@ -24,7 +24,6 @@ local setlist = nuts.setlist local end_of_math = nuts.end_of_math local nodecodes = nodes.nodecodes -local leadercodes = nodes.leadercodes local gluecodes = nodes.gluecodes local kerncodes = nodes.kerncodes @@ -43,8 +42,7 @@ local vlist_code = nodecodes.vlist local userskip_code = gluecodes.userskip local spaceskip_code = gluecodes.spaceskip local xspaceskip_code = gluecodes.xspaceskip - -local leaders_code = leadercodes.leaders +local leaders_code = gluecodes.leaders local fontkern_code = kerncodes.fontkern diff --git a/tex/context/base/mkiv/node-ser.lmt b/tex/context/base/mkiv/node-ser.lmt new file mode 100644 index 000000000..0d7f3ccad --- /dev/null +++ b/tex/context/base/mkiv/node-ser.lmt @@ -0,0 +1,285 @@ +if not modules then modules = { } end modules ['node-ser'] = { + version = 1.001, + comment = "companion to node-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type, tostring = type, tostring +local concat, tohash, sortedkeys, sortedhash, printtable, serialize = table.concat, table.tohash, table.sortedkeys, table.sortedhash, table.print, table.serialize +local formatters, format, rep = string.formatters, string.format, string.rep + +local allocate = utilities.storage.allocate + +local context = context +local nodes = nodes +local node = node + +local getfields = node.fields + +local traverse = nodes.traverse +local is_node = nodes.is_node + +local nodecodes = nodes.nodecodes +local subtypes = nodes.subtypes + +local tonode = nodes.tonode +local tonut = nodes.tonut + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist + +local f_char = formatters["%U"] +local f_attr = formatters["<attribute : %i>"] +local f_recurse = formatters["<recursive : %i>"] + +-- flat : don't use next, but indexes +-- verbose : also add type + +local canbezero = { + integer = true, + dimension = true, + number = true, +} + +local canbelist = { + attribute = "<attribute>", + node = "<node>", + token = "<token>", + attribute_list = "<attributes>", + node_list = "<nodes>", + token_list = "<tokens>", +} + +local canbeignored = { + prev = "<node>" +} + +local canbechar = { + char = true, + small_char = true, + large_char = true, +} + +local fieldtypes = table.setmetatableindex(function(t,k) + local v = getfields(k,true) or false + t[k] = v + return v +end) + +nodes.fieldtypes = fieldtypes + +local function astable(n) + n = tonode(n) + if n then + local fields = fieldtypes[n.id] + if fields then + local result = { } + for field, fieldtype in sortedhash(fields) do + local value = n[field] + if value then + if canbeignored[field] then + value = nil + elseif canbezero[fieldtype] and value == 0 then + value = nil + elseif canbelist[fieldtype] then + value = canbelist[fieldtype] + end + if value then + result[field] = value + end + end + end + local id = n.id + if id then + id = nodecodes[id] + result.id = id + local subtype = n.subtype + if subtype then + local subtypes = subtypes[id] + if subtypes then + result.subtype = subtypes[subtype] + end + end + end + return result + end + end +end + +nodes.astable = astable + +setinspector("node",function(v) if is_node(v) then printtable(astable(v),tostring(v)) return true end end) + +local function to_table(n,flat,verbose,noattributes,done) + local d = tonut(n) + if done[d] then + return f_recurse(d) + else + done[d] = true + local fields = fieldtypes[n.id] + if fields then + local result = { } + for field, fieldtype in sortedhash(fields) do + local value = n[field] + if value then + if fieldtype == "attribute_list" or fieldtype == "attribute" then + if noattributes then + result[value] = canbeignored[value] + else + result[value] = to_table(value,flat,verbose,noattributes,done) + end + elseif canbeignored[field] then + result[value] = canbeignored[value] + elseif not verbose and canbezero[fieldtype] and value == 0 then + value = nil + elseif canbelist[fieldtype] then + if flat then + result[value] = canbelist[value] + else + result[value] = to_table(value,flat,verbose,noattributes,done) + end + end + if value then + result[field] = value + end + end + end + if verbose then + local id = result.id + if id then + id = nodecodes[id] + result.id = id + local subtype = result.subtype + if subtype then + local subtypes = subtypes[id] + if subtypes then + result.subtype = subtypes[subtype] + end + end + end + for k, v in next, canbechar do + local v = result[k] + if v then + result[k] = f_char(v) + end + end + end + return result + end + end +end + +local function totable(n,flat,verbose,noattributes) -- nicest: n,true,true,true + if n then + local d = { } + if flat then + local t, tn = { }, 0 + while n do + tn = tn + 1 + local nt = to_table(n,flat,verbose,noattributes,d) + t[tn] = nt + nt.next = nil + nt.prev = nil + n = n.next + end + done = nil + return t + else + local t = to_table(n,flat,verbose,noattributes,d) + local n = n.next + if n then + t.next = totable(n,flat,verbose,noattributes,d) + end + return t + end + else + return { } + end +end + +nodes.totable = function(n,...) return totable(tonode(n),...) end +nodes.totree = function(n) return totable(tonode(n),true,true,true) end -- no attributes, todo: attributes in k,v list + +local function key(k) + return ((type(k) == "number") and "["..k.."]") or k +end + +function nodes.serialize(root,flat,verbose,noattributes,name) + return serialize(totable(tonode(root),flat,verbose,noattributes),name) +end + +function nodes.serializebox(n,flat,verbose,noattributes,name) + return serialize(totable(tex.box[n],flat,verbose,noattributes),name) +end + +function nodes.visualizebox(n,flat,verbose,noattributes,name) + context.tocontext(totable(tex.box[n],flat,verbose,noattributes),name) +end + +function nodes.list(head,n) -- name might change to nodes.type -- to be checked .. will move to module anyway + head = tonode(head) + if not n then + context.starttyping(true) + end + while head do + local id = head.id + context(rep(" ",n or 0) .. tostring(head) .. "\n") + if id == hlist_code or id == vlist_code then + nodes.list(head.list,(n or 0)+1) + end + head = head.next + end + if not n then + context.stoptyping(true) + end +end + +function nodes.print(head,n) + head = tonode(head) + while head do + local id = head.id + logs.writer(string.formatters["%w%S"],n or 0,head) + if id == hlist_code or id == vlist_code then + nodes.print(head.list,(n or 0)+1) + end + head = head.next + end +end + +-- quick hack, nicer is to have a proper expand per node type already prepared + +local function apply(n,action) + while n do + action(n) + local id = n.id + if id == hlist_code or id == vlist_code then + apply(n.list,action) + end + n = n.next + end +end + +nodes.apply = apply + +local nuts = nodes.nuts +local getid = nuts.getid +local getlist = nuts.getlist +local getnext = nuts.getnext + +local function apply(n,action) + while n do + action(n) + local id = getid(n) + if id == hlist_code or id == vlist_code then + local list = getlist(n,action) + if list then + apply(list,action) + end + end + n = getnext(n) + end +end + +nuts.apply = apply diff --git a/tex/context/base/mkiv/node-tex.lmt b/tex/context/base/mkiv/node-tex.lmt new file mode 100644 index 000000000..aae084740 --- /dev/null +++ b/tex/context/base/mkiv/node-tex.lmt @@ -0,0 +1,39 @@ +if not modules then modules = { } end modules ['node-tex'] = { + version = 1.001, + comment = "companion to node-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +builders = builders or { } +local kernel = builders.kernel or { } +builders.kernel = kernel + +local nuts = nodes.nuts + +local hyphenate = language.hyphenate + +local hyphenating = nuts.hyphenating +local ligaturing = nuts.ligaturing +local kerning = nuts.kerning + +function kernel.hyphenation(head) + return (hyphenate(head)) -- nodes ! +end + +function kernel.hyphenating(head) + return (hyphenating(head)) +end + +function kernel.ligaturing(head) + return (ligaturing(head)) +end + +function kernel.kerning(head) + return (kerning(head)) +end + +callbacks.register('hyphenate' , false, "normal hyphenation routine, called elsewhere") +callbacks.register('ligaturing', false, "normal ligaturing routine, called elsewhere") +callbacks.register('kerning' , false, "normal kerning routine, called elsewhere") diff --git a/tex/context/base/mkiv/node-tex.lua b/tex/context/base/mkiv/node-tex.lua index 5857fd2e6..cda6ff132 100644 --- a/tex/context/base/mkiv/node-tex.lua +++ b/tex/context/base/mkiv/node-tex.lua @@ -16,7 +16,6 @@ local hyphenate = lang.hyphenate local hyphenating = nuts.hyphenating local ligaturing = nuts.ligaturing local kerning = nuts.kerning -local cleanup = nuts.flush_components function kernel.hyphenation(head) return (hyphenate(head)) -- nodes ! @@ -34,14 +33,6 @@ function kernel.kerning(head) return (kerning(head)) end -if cleanup then - - function kernel.cleanup(head) - return (cleanup(head)) - end - -end - callbacks.register('hyphenate' , false, "normal hyphenation routine, called elsewhere") callbacks.register('ligaturing', false, "normal ligaturing routine, called elsewhere") callbacks.register('kerning' , false, "normal kerning routine, called elsewhere") diff --git a/tex/context/base/mkiv/node-tra.lua b/tex/context/base/mkiv/node-tra.lua index 2ebfaff12..a86dfb620 100644 --- a/tex/context/base/mkiv/node-tra.lua +++ b/tex/context/base/mkiv/node-tra.lua @@ -77,7 +77,7 @@ local glue_code = nodecodes.glue local kern_code = nodecodes.kern local rule_code = nodecodes.rule local dir_code = nodecodes.dir -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local whatsit_code = nodecodes.whatsit local dimenfactors = number.dimenfactors @@ -115,19 +115,6 @@ function nodes.handlers.checkglyphs(head,message) return false end -function nodes.handlers.checkforleaks(sparse) - local l = { } - local q = used_nodes() - for p, id in nextnode, q do - local s = table.serialize(nodes.astable(p,sparse),nodecodes[id]) - l[s] = (l[s] or 0) + 1 - end - flush_list(q) - for k, v in next, l do - report_nodes("%s * %s",v,k) - end -end - local fontcharacters -- = fonts.hashes.descriptions local function tosequence(start,stop,compact) @@ -167,7 +154,7 @@ local function tosequence(start,stop,compact) elseif id == dir_code then local d, p = getdirection(start) n = n + 1 ; t[n] = "[<" .. (p and "-" or "+") .. d .. ">]" -- todo l2r etc - elseif id == localpar_code and start_of_par(current) then + elseif id == par_code and start_of_par(current) then n = n + 1 ; t[n] = "[<" .. getdirection(start) .. ">]" -- todo l2r etc elseif compact then n = n + 1 ; t[n] = "[]" @@ -325,14 +312,6 @@ local function showsimplelist(h,depth,n) end end --- \startluacode --- callbacks.register('buildpage_filter',function() nodes.show_simple_list(tex.lists.contrib_head) end) --- \stopluacode --- \vbox{b\footnote{n}a} --- \startluacode --- callbacks.register('buildpage_filter',nil) --- \stopluacode - nodes.showsimplelist = function(h,depth) showsimplelist(h,depth,0) end local function listtoutf(h,joiner,textonly,last,nodisc) diff --git a/tex/context/base/mkiv/pack-box.mkxl b/tex/context/base/mkiv/pack-box.mkxl new file mode 100644 index 000000000..2f52939ce --- /dev/null +++ b/tex/context/base/mkiv/pack-box.mkxl @@ -0,0 +1,1114 @@ +%D \module +%D [ file=pack-box, +%D version=2002.04.12, +%D title=\CONTEXT\ Packaging Macros, +%D subtitle=Boxes, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Packaging Macros / Boxes} + +%D This module contains all kind of macros for moving content around. Many +%D macros here come from other modules, but depencies made it more clear +%D to isolate them. We invite users to document the macros. They can be +%D handy shortcuts for otherwise complex tasks. + +\unprotect + +%D We need to set the size, else we get dimensions depending on the content, +%D which in itself is ok, but can lead to loops due to rounding errors (happened +%D in demo-obv). + +% \definelayer[\v!text-2][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height] +% \definelayer[\v!text-1][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height] +% \definelayer[\v!text+1][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height] +% \definelayer[\v!text+2][\c!position=\v!yes,\c!region=,\c!width=\d_overlay_width,\c!height=\d_overlay_height] + +\definelayer[\v!text-2][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight] +\definelayer[\v!text-1][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight] +\definelayer[\v!text+1][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight] +\definelayer[\v!text+2][\c!position=\v!yes,\c!region=,\c!width=\textwidth,\c!height=\textheight] + +\permanent\protected\def\internaltextoverlay#1% will become more generic and installable + {\startoverlay % i.e. probably an overlay by itself + {\positionregionoverlay\textanchor{\v!text#1}}% see later + {\composedlayer {\v!text#1}}% + \stopoverlay} + +\defineoverlay[\v!text-2][\internaltextoverlay{-2}] +\defineoverlay[\v!text-1][\internaltextoverlay{-1}] +\defineoverlay[\v!text+1][\internaltextoverlay{+1}] +\defineoverlay[\v!text+2][\internaltextoverlay{+2}] + +\installcorenamespace {anchor} + +% produces a box too +% +% \anchor[text-1][preset=lefttop][framed settings]{HELLO WORLD} + +\permanent\tolerant\protected\def\defineanchor[#1]#*[#2]#*[#3]#*[#4]% name targetlayer layersetting framedsetting + {\setvalue{\??anchor#1}{\pack_anchors_process_defined{#2}{#3}{#4}}} + +\def\pack_anchors_process_defined#1#2#3% + {\tolerant\def\pack_anchors_process_defined_indeed[##1]##*[##2]% + {\ifarguments + \def\next{\pack_anchors_process_indeed{#1}{#2}{#3}}% + \or + \def\next{\pack_anchors_process_indeed{#1}{#2,##1}{#2,##1}}% + \or + \def\next{\pack_anchors_process_indeed{#1}{#2,##1}{#3,##2}}% + \fi + \next}% picks up a box + \pack_anchors_process_defined_indeed} + +\protected\def\anchor[#1]% + {\begingroup + \edef\currentanchor{#1}% + \ifcsname\??anchor\currentanchor\endcsname + \expandafter\lastnamedcs + \else + \expandafter\pack_anchor_notdefined + \fi} + +\tolerant\def\pack_anchor_notdefined[#1]#*[#2]% + {\ifarguments + \expandafter\gobbletwoarguments + \or + \expandafter\pack_anchor_notdefined_one + \else + \expandafter\pack_anchor_notdefined_two + \fi{#1}{#2}} + +\def\pack_anchor_notdefined_one #1#2{\dowithnextbox{\pack_anchors_process_finish\currentanchor{#1}{#1}}\vbox} +\def\pack_anchor_notdefined_two #1#2{\dowithnextbox{\pack_anchors_process_finish\currentanchor{#1}{#2}}\vbox} +\def\pack_anchors_process_indeed#1#2#3{\dowithnextbox{\pack_anchors_process_finish {#1}{#2}{#3}}\vbox} + +\newbox \b_pack_anchors +\newdimen\d_pack_anchors_width +\newdimen\d_pack_anchors_height +\newdimen\d_pack_anchors_depth + +% \definelayer[anchor] + +\newcount\c_pack_anchors_n +\newtoks \t_pack_anchors_flush + +\protected\def\pack_anchors_register#1#2% + {\global\advance\c_pack_anchors_n\plusone + \pagereference[\v!layer:\v!anchor:\number\c_pack_anchors_n]% + \putboxincache\v!anchor{\number\c_pack_anchors_n}\b_pack_anchors +% \xtoksapp\t_pack_anchors_flush{\pack_anchors_flush{\number\c_pack_anchors_n}{#1}{#2}}% + \doglobal\appendetoks + \pack_anchors_flush{\number\c_pack_anchors_n}{#1}{#2}% + \to \t_pack_anchors_flush + \glet\pack_anchors_flush_all\pack_anchors_flush_all_indeed} + +\protected\def\pack_anchors_flush#1#2#3% + {\doifelseboxincache\v!anchor{#1} + {\doifelsereferencefound{\v!layer:\v!anchor:#1} + {\ifnum\currentreferencerealpage=\realpageno\relax + \setlayer[#2][#3,\c!position=\v!no]{\directboxfromcache\v!anchor{#1}}% + \else + \donetrue + \fi + }\donetrue}% + \donetrue}% + +\protected\def\pack_anchors_flush_all_indeed + {\donefalse + \the\t_pack_anchors_flush + \ifdone\else + \global\t_pack_anchors_flush\emptytoks + \glet\pack_anchors_flush_all\relax + \fi} + +\let\pack_anchors_flush_all\relax + +\appendtoks + \pack_anchors_flush_all +\to \everybeforepagebody + +\def\pack_anchors_process_finish#1#2#3% brrr: we need to apply offset only once .. a bit messy + {\checkpositionoverlays + \setbox\b_pack_anchors\box\nextbox + \framed % could be a predefined framed but used seldom + [\c!offset=\v!overlay,\c!frame=\v!off,#3] + {\pack_anchors_register{#1}{#2}% + \novrule % hm, not needed as we frame the size (but kind of default) + \s!width \wd\b_pack_anchors + \s!height\ht\b_pack_anchors + \s!depth \dp\b_pack_anchors}% + \endgroup} + +% \setlayeranchored[text-1][preset=lefttop]{HELLO WORLD} produces a simple (empty) hbox +% synchronizes per page + +\permanent\tolerant\protected\def\setlayeranchored[#1]#*[#2]% + {\begingroup + \ifarguments + \dowithnextbox + {\endgroup}% + \or + \dowithnextbox + {\checkpositionoverlays + \setbox\b_pack_anchors\box\nextbox + \dontleavehmode\hpack{\pack_anchors_register{#1}{#2}}% + \endgroup}% + \fi + \hbox} + +% collectors + +\installcorenamespace{collectorbox} +\installcorenamespace{collector} + +\installcommandhandler \??collector {collector} \??collector + +\setupcollector + [\c!state=\v!start, + \c!x=\zeropoint, + \c!y=\zeropoint, + \c!offset=\zeropoint, + \c!rotation=, % geen 0 ! + \c!hoffset=\zeropoint, + \c!voffset=\zeropoint, + \c!location=rb, + \c!corner=] + +\appendtoks + \ifcsname\??collectorbox\currentcollector\endcsname \else + \expandafter\newbox\csname\??collectorbox\currentcollector\endcsname + \fi +\to \everydefinecollector + +\permanent\protected\def\resetcollector[#1]% + {\ifcsname\??collectorbox#1\endcsname + \global\setbox\lastnamedcs\emptybox + \fi} + +\newconditional\c_pack_boxes_collector_valid_box + +\let\b_pack_boxes_collector\scratchbox + +\def\pack_boxes_collector_check_box#1% + {\edef\currentcollector{#1}% + \ifcsname\??collectorbox\currentcollector\endcsname + \settrue\c_pack_boxes_collector_valid_box + \expandafter\let\expandafter\b_pack_boxes_collector\lastnamedcs + \else + \setfalse\c_pack_boxes_collector_valid_box + \writestatus{collector}{unknown collector \currentcollector}% + \fi} + +\permanent\tolerant\protected\def\setcollector[#1]#*[#2]% todo: keep reference point + {\bgroup + \pack_boxes_collector_check_box{#1}% + \ifconditional\c_pack_boxes_collector_valid_box + \setupcurrentcollector[#2]% + \expandafter\pack_boxes_collector_yes + \else + \expandafter\pack_boxes_collector_nop + \fi} + +\def\pack_boxes_collector_yes + {\forgetall + \dontcomplain + \dowithnextboxcs\pack_boxes_collector_finish\hbox} + +\let\pack_boxes_collector_nop\egroup + +\installcorenamespace{collectorcorners} + +\setvalue{\??collectorcorners\v!middle}% + {\ifdim\d_pack_layers_x_size>\zeropoint + \advance\d_pack_layers_x_position.5\d_pack_layers_x_size + \fi + \ifdim\d_pack_layers_y_size>\zeropoint + \advance\d_pack_layers_y_position.5\d_pack_layers_y_size + \fi} + +\setvalue{\??collectorcorners\v!bottom}% + {\ifdim\d_pack_layers_y_size>\zeropoint + \advance\d_pack_layers_y_position-\d_pack_layers_y_size + \d_pack_layers_y_position-\d_pack_layers_y_position + \fi} + +\setvalue{\??collectorcorners\v!right}% + {\ifdim\d_pack_layers_x_size>\zeropoint + \advance\d_pack_layers_x_position-\d_pack_layers_x_size + \d_pack_layers_x_position-\d_pack_layers_x_position + \fi} + +\def\pack_boxes_collector_check_corner#1% + {\ifcsname\??collectorcorners#1\endcsname + \lastnamedcs + \fi} + +\def\pack_boxes_collector_finish + {\edef\p_collector_rotation{\collectorparameter\c!rotation}% + \edef\p_collector_corner {\collectorparameter\c!corner}% + \ifx\p_collector_rotation\empty \else + \setbox\nextbox\hpack + {\rotate + [\c!location=\v!high, + \c!rotation=\p_collector_rotation] + {\box\nextbox}}% + \fi + \d_pack_layers_x_size\wd\b_pack_boxes_collector + \d_pack_layers_y_size\htdp\b_pack_boxes_collector + \d_pack_layers_x_position\dimexpr\collectorparameter\c!x+\collectorparameter\c!hoffset\relax + \d_pack_layers_y_position\dimexpr\collectorparameter\c!y+\collectorparameter\c!voffset\relax + \rawprocesscommacommand[\p_collector_corner]\pack_boxes_collector_check_corner + \setbox\nextbox\hpack + {\alignedbox[\collectorparameter\c!location]\vpack{\box\nextbox}}% + \boxmaxdepth\zeropoint % really needed, nice example + \global\advance\boxhdisplacement\d_pack_layers_x_position + \ifdim\boxhdisplacement<\zeropoint + \global\setbox\b_pack_boxes_collector\hpack + {\kern-\boxhdisplacement + \box\b_pack_boxes_collector}% + \fi + \global\advance\boxvdisplacement\d_pack_layers_y_position + \ifdim\boxvdisplacement<\zeropoint + \global\setbox\b_pack_boxes_collector\hpack + {\lower-\boxvdisplacement + \box\b_pack_boxes_collector}% + \fi + \d_pack_layers_x_size\wd\b_pack_boxes_collector + \d_pack_layers_y_size\htdp\b_pack_boxes_collector + \global\setbox\b_pack_boxes_collector\hpack + {\box\b_pack_boxes_collector + \kern\dimexpr + -\d_pack_layers_x_size + +\d_pack_layers_x_position + \ifdim\boxhdisplacement<\zeropoint + -\boxhdisplacement + \fi + \relax + \lower\d_pack_layers_y_position\hpack + {\ifdim\boxvdisplacement<\zeropoint + \lower-\boxvdisplacement + \fi + \box\nextbox}}% + % combine height and depth into depth only (later flushed as height) + \global\setbox\b_pack_boxes_collector\hpack + {\lower\ht\b_pack_boxes_collector\box\b_pack_boxes_collector}% + % just to be sure + \ifdim\wd\b_pack_boxes_collector<\d_pack_layers_x_size + \wd\b_pack_boxes_collector\d_pack_layers_x_size + \fi + \egroup} + +\permanent\protected\def\flushcollector[#1]% + {\bgroup + \pack_boxes_collector_check_box{#1}% + \ifconditional\c_pack_boxes_collector_valid_box + \edef\p_collector_state{\collectorparameter\c!state}% + \ifx\p_collector_state\v!stop \else + \vpack{\hpack{\raise + \dp\b_pack_boxes_collector + \ifx\p_collector_state\v!repeat\copy\else\box\fi\b_pack_boxes_collector}}% + \fi + \fi + \egroup} + +\permanent\protected\def\composedcollector#1% no [], handy as argument + {\flushcollector[#1]} + +\permanent\tolerant\protected\def\adaptcollector[#1]#*[#2]% % a typical case where \global\wd looks better in the code + {\begingroup + \pack_boxes_collector_check_box{#1}% + \ifconditional\c_pack_boxes_collector_valid_box + \letcollectorparameter\c!voffset\zeropoint + \letcollectorparameter\h!voffset\zeropoint + \setupcurrentcollector[#2]% + \global\wd\b_pack_boxes_collector\dimexpr\wd\b_pack_boxes_collector+\collectorparameter\c!hoffset\relax + \global\ht\b_pack_boxes_collector\dimexpr\ht\b_pack_boxes_collector+\collectorparameter\c!voffset\relax + \fi + \endgroup} + +%\definecollector[test] +%\setcollector[test] +% [location=rb] +% {\externalfigure[koe][frame=on,width=3cm]} +%\setcollector[test] +% [corner={right,bottom},location={left,top}] +% {\framed{gans}} +%\composedcollector{test} + +\definecollector + [caption] + +\permanent\tolerant\protected\def\collectedtext[#1]#*[#2]% for captions + {\pack_boxes_collector_text[#1][#2]} + +\def\pack_boxes_collector_text[#1][#2]#3% #3 is mandate so no tolerant here, so still two step + {\bgroup + \dowithnextbox + {\setcollector + [caption] + {\box\nextbox}% + \setcollector + [caption][#1]% + {\letdummyparameter\c!style\empty + \letdummyparameter\c!color\empty + \getdummyparameters[#2]% + \dousestyleparameter{\directdummyparameter\c!style}% + \setupinterlinespace + \normalexpanded{\framed[\c!foregroundcolor=\directdummyparameter\c!color,\c!foregroundstyle=\directdummyparameter\c!style},\c!frame=\v!overlay,#2]{#3}}% + \composedcollector{caption}% + \egroup}% + \hbox} + +% \collectedtext +% [corner={right,bottom},location={left,top}] +% [background=color,backgroundcolor=white,offset=0pt] +% {gans} +% {\externalfigure[koe][width=3cm]} +% +% \collectedtext +% [rotation=90,corner={right,bottom},location={right,top}] +% [frame=on,offset=0pt] +% {gans} +% {\externalfigure[koe][width=3cm]} +% +% \collectedtext +% [rotation=90,corner={left,bottom},location={left,top}] +% [frame=on,offset=0pt] +% {gans} +% {\externalfigure[koe][width=3cm]} + +\installcorenamespace {layeredtext} +\installcorenamespace {layeredtextlayer} +\installcorenamespace {layeredtextframed} + +\installsimpleframedcommandhandler \??layeredtext {layeredtext} \??layeredtext + +\newdimen\d_pack_layeredtexts_width +\newdimen\d_pack_layeredtexts_height + +\definelayer % private + [\??layeredtextlayer] + +\setuplayer % private + [\??layeredtextlayer] + [\c!width=\d_pack_layeredtexts_width, + \c!height=\d_pack_layeredtexts_height] + +\defineframed % private + [\??layeredtextframed] + [\c!offset=\v!overlay, + \c!frame=\v!off, + \c!background={\v!foreground,\??layeredtextlayer}, + \c!width=\d_pack_layeredtexts_width, + \c!height=\d_pack_layeredtexts_height] + +\setuplayeredtext % public (the attached data, usually small stuff, not the main thing) + [\c!frame=\v!overlay, + \c!color=, + \c!style=, + \c!foregroundcolor=\layeredtextparameter\c!color, + \c!foregroundstyle=\layeredtextparameter\c!style] + +\permanent\tolerant\protected\def\placelayeredtext[#1]#*[#2]#*[#3]#4% tag layersettings content(framed)settings content + {\bgroup + \edef\currentlayeredtext{#1}% + \checklayeredtextparent % bonus + \setupcurrentlayeredtext[#3]% + \dowithnextbox + {\d_pack_layeredtexts_width \wd\nextbox + \d_pack_layeredtexts_height\ht\nextbox + \begingroup % preserve \nextbox + \setlayer + [\??layeredtextlayer]% + [#2]% + {\setfalse\fontattributeisset + \uselayeredtextstyleparameter\c!style + \ifconditional\fontattributeisset + \setupinterlinespace + \fi + \inheritedlayeredtextframed{#4}}% + \endgroup + \placeframed[\??layeredtextframed]{\flushnextbox}% + \egroup}% + \hbox} + +\permanent\protected\def\layeredtext + {\placelayeredtext[]} + +% \layeredtext +% [corner={right,bottom},location={left,top}] +% [background=color,backgroundcolor=white,offset=0pt] +% {gans} +% {\externalfigure[koe][width=3cm]} +% +% \layeredtext +% [rotation=90,corner={right,bottom},location={right,top}] +% [frame=on,offset=0pt] +% {gans} +% {\externalfigure[koe][width=3cm]} +% +% \layeredtext +% [rotation=90,corner={left,bottom},location={left,top}] +% [frame=on,offset=0pt] +% {gans} +% {\externalfigure[koe][width=3cm]} + +\permanent\tolerant\protected\def\ornamenttext[#1]#*[#2]% takes another argument + {\bgroup + \doifelseassignment{#1} + {\letdummyparameter\c!alternative\v!a + \getdummyparameters[#1]% + \doifelse{\directdummyparameter\c!alternative}\v!a + {\egroup\collectedtext}% + {\egroup\layeredtext }% + [#1][#2]}% + {\egroup\getvalue{#1}}} + +\permanent\tolerant\protected\def\defineornament[#1]#*[#2]#*[#3]% + {\setuvalue{#1}{\pack_ornament_text[#2][#3]}} + +% \defineornament +% [affiliation] +% [rotation=90,corner={right,bottom},location={right,top}, +% hoffset=-.25ex] +% [frame=on,background=color,backgroundcolor=red,offset=0pt] +% +% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}} +% +% \defineornament +% [affiliation] +% [rotation=90,corner={right,bottom},location={right,top}, +% hoffset=-.25ex,alternative=b] +% [frame=on,background=color,backgroundcolor=red,offset=0pt] +% +% \ruledhbox{\affiliation{gans}{\externalfigure[koe][width=3cm]}} +% +% \defineornament +% [affiliation] +% [rotation=90,corner={right,bottom},location={left,top}, +% hoffset=.25ex,voffset=.25ex,alternative=a] +% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt] +% +% \affiliation{photo}{\externalfigure[molen][width=3cm]} +% +% \defineornament +% [affiliation] +% [rotation=90,corner={right,bottom},location={left,top}, +% hoffset=.25ex,voffset=.25ex,alternative=b] +% [background=color,style=\ss\tfxx,backgroundcolor=white,offset=0pt] +% +% \affiliation{drawing}{\externalfigure[hakker][width=3cm]} + +\newcount\c_pack_boxes_bleeds + +\installcorenamespace {bleeding} + +\installdirectcommandhandler \??bleeding {bleeding} % \??bleeding + +\setupbleeding + [\c!location=l, + \c!stretch=\v!yes, + \c!width=3cm, + \c!height=3cm, + \c!offset=2mm, + \c!page=\v!no, + \c!voffset=\scratchoffset, % is set to \bleedingparameter\c!offset + \c!hoffset=\scratchoffset] % which often saves one resolve + +\def\bleedwidth {\the\hsize} % these are global ! +\def\bleedheight{\the\vsize} % these are global ! + +\newconditional\c_pack_boxes_l +\newconditional\c_pack_boxes_r +\newconditional\c_pack_boxes_t +\newconditional\c_pack_boxes_b + +\installcorenamespace{bleedinglocation} + +\setvalue{\??bleedinglocation t}{\settrue\c_pack_boxes_t\scratchhoffset\zeropoint} +\setvalue{\??bleedinglocation b}{\settrue\c_pack_boxes_b\scratchhoffset\zeropoint} +\setvalue{\??bleedinglocation l}{\settrue\c_pack_boxes_l\scratchvoffset\zeropoint} +\setvalue{\??bleedinglocation r}{\settrue\c_pack_boxes_r\scratchvoffset\zeropoint} +\setvalue{\??bleedinglocation bl}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_b} +\setvalue{\??bleedinglocation lb}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_b} +\setvalue{\??bleedinglocation br}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_b} +\setvalue{\??bleedinglocation rb}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_b} +\setvalue{\??bleedinglocation tl}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_t} +\setvalue{\??bleedinglocation lt}{\settrue\c_pack_boxes_l\settrue\c_pack_boxes_t} +\setvalue{\??bleedinglocation tr}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_t} +\setvalue{\??bleedinglocation rt}{\settrue\c_pack_boxes_r\settrue\c_pack_boxes_t} + +\permanent\tolerant\protected\def\bleed[#1]% + {\hbox\bgroup + \global\advance\c_pack_boxes_bleeds\plusone + % + \xdef\bleedwidth {\the\hsize}% + \xdef\bleedheight{\the\vsize}% + % + \edef\currentbgposition {bleed:\number\c_pack_boxes_bleeds}% + \edef\currentpageposition{page:0}% todo: per page + % + \setupcurrentbleeding[#1]% + % + \scratchwidth \bleedingparameter\c!width + \scratchheight \bleedingparameter\c!height + \scratchoffset \bleedingparameter\c!offset + \scratchhoffset\bleedingparameter\c!hoffset + \scratchvoffset\bleedingparameter\c!voffset + % + \setfalse\c_pack_boxes_l % left + \setfalse\c_pack_boxes_r % right + \setfalse\c_pack_boxes_t % top + \setfalse\c_pack_boxes_b % bottom + % + \csname\??bleedinglocation\bleedingparameter\c!location\endcsname + % + \doifelse{\bleedingparameter\c!stretch}\v!yes\donetrue\donefalse + % + \xdef\bleedwidth{\the\dimexpr + \ifdone + \ifconditional\c_pack_boxes_l + \scratchwidth+\MPx\currentbgposition-\MPx\currentpageposition + \else\ifconditional\c_pack_boxes_r + \paperwidth -\MPx\currentbgposition+\MPx\currentpageposition % not checked + \else + \scratchwidth + \fi\fi + \else + \scratchwidth + \fi+\scratchhoffset + \relax}% + \xdef\bleedheight{\the\dimexpr + \ifdone + \ifconditional\c_pack_boxes_t + \paperheight -\MPy\currentbgposition+\MPy\currentpageposition % not checked + \else\ifconditional\c_pack_boxes_b + \scratchheight+\MPy\currentbgposition-\MPy\currentpageposition + \MPh\currentbgposition % not checked (\MPh added) + \else + \scratchheight + \fi\fi + \else + \scratchheight + \fi+\scratchvoffset + \relax}% + \dowithnextboxcontentcs\pack_boxes_bleed_settings\pack_boxes_bleed_finish\hbox} + +\def\pack_boxes_bleed_settings + {\hsize\bleedwidth + \vsize\bleedheight} + +\def\pack_boxes_bleed_finish + {\doif{\bleedingparameter\c!page}\v!yes + {\setbox\nextbox\topskippedbox{\box\nextbox}}% + \setbox\nextbox\hpack to \scratchwidth + {\ifconditional\c_pack_boxes_l\hss\fi + \box\nextbox + \ifconditional\c_pack_boxes_r\hss\fi}% + \ifconditional\c_pack_boxes_b + \setbox\nextbox\hpack + {\lower\bleedheight\hpack{\raise\scratchheight\box\nextbox}}% + \fi + \wd\nextbox\scratchwidth + \ht\nextbox\scratchheight + \dp\nextbox\zeropoint + \ifdone + \hpos\currentbgposition{\box\nextbox}% + \else + \box\nextbox + \fi + \egroup} + +\defineexternalfigure + [bleed] % should be \v!bleed + [\c!width=\bleedwidth, + \c!height=\bleedheight] + +% \placefigure[left]{none} +% {\bleed[width=5cm,height=3cm,location=lt]{\externalfigure[koe][bleed]}} +% +% \input tufte +% +% \placefigure[left]{none} +% {\bleed[width=5cm,height=3cm,location=l]{\externalfigure[koe][bleed]}} +% +% \input tufte +% +% \placefigure[right]{none} +% {\bleed[width=5cm,height=3cm,location=r]{\externalfigure[koe][bleed]}} +% +% \input tufte +% +% \placefigure +% [top,none] +% {} % no caption +% {\bleed +% [hoffset=-\backspace, +% voffset=3mm, +% width=0cm, +% height=6\lineheight, +% page=yes, % correct for topskip +% location=lt] +% {\externalfigure[koe][bleed][frame=on]}} + +% \setlayerframed[layer id][layer settings][framed setting]{data} +% \setlayerframed[layer id][combined settings]{data} + +% tricky: offsets apply to both the layer and the framed; it makes sense to +% only apply the offset to ... + +\permanent\tolerant\protected\def\setlayerframed[#1]#*[#2]#*[#3] + {\ifarguments + % error + \or + \expandafter\pack_layers_set_framed_s + \or + \expandafter\pack_layers_set_framed_d + \or + \expandafter\pack_layers_set_framed_t + \fi[#1][#2][#3]} + +\def\pack_layers_set_framed_s[#1][#2][#3]% + {\setlayer[#1][\c!width=\wd\nextbox,\c!height=\ht\nextbox,\c!offset=\zeropoint]% + \normalframedwithsettings[\c!location=\v!normal]} % different kind of location + +\def\pack_layers_set_framed_d[#1][#2][#3]% + {\setlayer[#1][\c!width=\wd\nextbox,\c!height=\ht\nextbox,#2,\c!offset=\zeropoint]% + \normalframedwithsettings[\c!location=\v!normal,#2]} % different kind of location + +\def\pack_layers_set_framed_t[#1][#2][#3]% + {\setlayer[#1][#2]% + \normalframedwithsettings[#3]} + +\permanent\tolerant\protected\def\setlayertext[#1]#*[#2]#*[#3]% + {\bgroup + \letdummyparameter\c!align\empty + \letdummyparameter\c!width\hsize + \letdummyparameter\c!color\empty + \letdummyparameter\c!style\empty + \getdummyparameters[#3]% + \dowithnextboxcontent + {\forgetall + \hsize\directdummyparameter\c!width + \usealignparameter\directdummyparameter + \dousestyleparameter{\directdummyparameter\c!style}} + {\setlayer[#1][#2]{\strut\dousecolorparameter{\directdummyparameter\c!color}\flushnextbox}% maybe expand the color + \egroup}% + \vtop} + +% \setupbackgrounds +% [page] +% [background=pagefigures] +% +% \definelayer +% [pagefigures] +% [x=-2mm, +% y=-2mm, +% width=\paperwidth, +% height=\paperheight] +% +% \definelayerpreset [lefttop] [corner={left,top},location={right,bottom}] +% \definelayerpreset [righttop] [corner={right,top},location={left,bottom}] +% \definelayerpreset [leftbottom] [corner={left,bottom},location={right,top}] +% \definelayerpreset [rightbottom] [corner={right,bottom},location={left,top}] +% \definelayerpreset [middle] [corner=middle,location=middle] +% +% \setlayer[pagefigures][preset=lefttop] +% \setlayer[pagefigures][preset=righttop] +% \setlayer[pagefigures][preset=leftbottom] +% \setlayer[pagefigures][preset=rightbottom] + +\definelayerpreset + [\v!left\v!top] + [\c!corner={\v!left,\v!top},\c!location={\v!right,\v!bottom}] + +\definelayerpreset + [\v!right\v!top] + [\c!corner={\v!right,\v!top},\c!location={\v!left,\v!bottom}] + +\definelayerpreset + [\v!left\v!bottom] + [\c!corner={\v!left,\v!bottom},\c!location={\v!right,\v!top}] + +\definelayerpreset + [\v!right\v!bottom] + [\c!corner={\v!right,\v!bottom},\c!location={\v!left,\v!top}] + +\definelayerpreset + [\v!middle] + [\c!corner=\v!middle,\c!location=\v!middle] + +\definelayerpreset + [\v!middle\v!top] + [\c!location=\v!bottom,\c!corner=\v!top,\c!dx=.5\layerwidth] + +\definelayerpreset + [\v!middle\v!bottom] + [\c!location=\v!top,\c!corner=\v!bottom,\c!dx=.5\layerwidth] + +\definelayerpreset + [\v!middle\v!left] + [\c!location=\v!right,\c!corner=\v!left,\c!dy=.5\layerheight] + +\definelayerpreset + [\v!middle\v!right] + [\c!location=\v!left,\c!corner=\v!right,\c!dy=.5\layerheight] + +% left and right hanging: + +\definelayerpreset + [\v!left\v!top\v!left] + [\c!location={\v!left,\v!bottom},\c!corner={\v!left,\v!top}] + +\definelayerpreset + [\v!right\v!top\v!right] + [\c!location={\v!right,\v!bottom},\c!corner={\v!right,\v!top}] + +\installcorenamespace{alignedboxes} + +\permanent\tolerant\protected\def\alignedbox[#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish} +\permanent\tolerant\protected\def\aligned [#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish\hbox} + +\def\pack_boxes_aligned_finish + {\ifcsname\??alignedboxes\serializedcommalist\endcsname + \expandafter\lastnamedcs + \else + \expandafter\middlebox + \fi{\flushnextbox}% + \egroup} + +\letvalue{\??alignedboxes }\middlebox +\letvalue{\??alignedboxes\v!middle }\middlebox +\letvalue{\??alignedboxes\v!middle\v!middle}\middlebox +\letvalue{\??alignedboxes\v!left }\leftbox +\letvalue{\??alignedboxes\v!left \v!top }\lefttopbox +\letvalue{\??alignedboxes\v!left \v!bottom}\leftbottombox +\letvalue{\??alignedboxes\v!right }\rightbox +\letvalue{\??alignedboxes\v!right \v!top }\righttopbox +\letvalue{\??alignedboxes\v!right \v!bottom}\rightbottombox +\letvalue{\??alignedboxes\v!bottom }\bottombox +\letvalue{\??alignedboxes\v!bottom\v!left }\bottomleftbox +\letvalue{\??alignedboxes\v!bottom\v!right }\bottomrightbox +\letvalue{\??alignedboxes\v!top }\topbox +\letvalue{\??alignedboxes\v!top \v!left }\topleftbox +\letvalue{\??alignedboxes\v!top \v!right }\toprightbox +\letvalue{\??alignedboxes\v!line }\baselinemiddlebox % \v!grid is taken +\letvalue{\??alignedboxes\v!line \v!left }\baselineleftbox +\letvalue{\??alignedboxes\v!line \v!middle}\baselinemiddlebox +\letvalue{\??alignedboxes\v!line \v!right }\baselinerightbox +\letvalue{\??alignedboxes c}\middlebox +\letvalue{\??alignedboxes l}\leftbox +\letvalue{\??alignedboxes r}\rightbox +\letvalue{\??alignedboxes b}\bottombox +\letvalue{\??alignedboxes t}\topbox +\letvalue{\??alignedboxes lt}\lefttopbox +\letvalue{\??alignedboxes lb}\leftbottombox +\letvalue{\??alignedboxes rt}\righttopbox +\letvalue{\??alignedboxes rb}\rightbottombox +\letvalue{\??alignedboxes tl}\topleftbox +\letvalue{\??alignedboxes bl}\bottomleftbox +\letvalue{\??alignedboxes tr}\toprightbox +\letvalue{\??alignedboxes br}\bottomrightbox +\letvalue{\??alignedboxes m}\middlebox +\letvalue{\??alignedboxes g}\baselinemiddlebox +\letvalue{\??alignedboxes gl}\baselineleftbox +\letvalue{\??alignedboxes gc}\baselinemiddlebox +\letvalue{\??alignedboxes gr}\baselinerightbox + +% left/right/top/bottomoffset -> dimensions change +% x/y | method=fixed -> dimensions don't change + +\installcorenamespace{offsetbox} + +\installautocommandhandler \??offsetbox {offsetbox} \??offsetbox + +\setupoffsetbox + [\c!x=\zeropoint, + \c!y=\zeropoint, + \c!width=\wd\nextbox, + \c!height=\ht\nextbox, + \c!depth=\dp\nextbox, + \c!location=, + \c!leftoffset=\zeropoint, + \c!rightoffset=\zeropoint, + \c!topoffset=\zeropoint, + \c!bottomoffset=\zeropoint, + \c!method=] + +\aliased\let\setupoffset\setupoffsetbox + +\permanent\tolerant\protected\def\offsetbox[#1]% + {\bgroup + \pack_boxes_offset_check[#1]% + \dowithnextboxcs\pack_boxes_offsetfinish} + +\permanent\tolerant\protected\def\offset[#1]% + {\bgroup + \pack_boxes_offset_check[#1]% + \dowithnextboxcs\pack_boxes_offsetfinish\hbox} + +\newcount\c_pack_boxes_offset_level + +\def\pack_boxes_offset_check + {\advance\c_pack_boxes_offset_level\plusone + \edef\currentoffsetbox{\the\c_pack_boxes_offset_level}% + \checkoffsetboxparent + \setupcurrentoffsetbox} + +\def\pack_boxes_offsetfinish + {\donefalse + \scratchxposition \offsetboxparameter\c!x + \scratchyposition \offsetboxparameter\c!y + \scratchleftoffset \offsetboxparameter\c!leftoffset + \scratchrightoffset \offsetboxparameter\c!rightoffset + \scratchtopoffset \offsetboxparameter\c!topoffset + \scratchbottomoffset\offsetboxparameter\c!bottomoffset + \relax % really needed + \ifzeropt\scratchleftoffset \else\donetrue\fi + \ifzeropt\scratchrightoffset \else\donetrue\fi + \ifzeropt\scratchtopoffset \else\donetrue\fi + \ifzeropt\scratchbottomoffset\else\donetrue\fi + \ifdone + \edef\p_method{\offsetboxparameter\c!method}% + \ifx\p_method\v!fixed % new + \ifzeropt\scratchleftoffset + \ifzeropt\scratchrightoffset \else + \scratchxposition-\scratchrightoffset + \scratchrightoffset\zeropoint + \fi + \else + \scratchxposition\scratchleftoffset + \scratchleftoffset\zeropoint + \fi + \ifzeropt\scratchtopoffset + \ifzeropt\scratchbottomoffset \else + \scratchyposition-\scratchbottomoffset + \scratchbottomoffset\zeropoint + \fi + \else + \scratchyposition\scratchtopoffset + \scratchtopoffset\zeropoint + \fi + \donefalse + \fi + \fi + \ifdone + \setbox\nextbox\vpack + {\forgetall % already done + \offinterlineskip + \kern\scratchtopoffset + \hpack + {\kern\scratchleftoffset + \box\nextbox + \kern\scratchrightoffset}% + \kern\scratchbottomoffset}% + \ht\nextbox\htdp\nextbox + \dp\nextbox\zeropoint + \fi + \scratchwidth \offsetboxparameter\c!width + \scratchheight\offsetboxparameter\c!height + \scratchdepth \offsetboxparameter\c!depth + \edef\p_location{\offsetboxparameter\c!location}% + \setbox\nextbox\hpack + {\kern\scratchxposition + \lower\scratchyposition\hpack + {\ifx\p_location\empty + \box\nextbox + \else + \alignedbox[\p_location]\hpack{\box\nextbox}% + \fi}}% + \wd\nextbox\scratchwidth + \ht\nextbox\scratchheight + \dp\nextbox\scratchdepth + \box\nextbox + \egroup} + +%D \starttyping +%D \framed[offset=overlay]{\offset[leftoffset=1cm] +%D {\framed[offset=overlay]{\offset[rightoffset=1cm] +%D {\externalfigure[koe][width=1cm]}}}} +%D +%D \blank +%D +%D \framed[offset=overlay]{\offset[leftoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank +%D \framed[offset=overlay]{\offset[rightoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank +%D \framed[offset=overlay]{\offset[topoffset=1cm] {\externalfigure[koe][width=5cm]}} \blank +%D \framed[offset=overlay]{\offset[bottomoffset=1cm]{\externalfigure[koe][width=5cm]}} \blank +%D \stoptyping + +% \useMPlibrary[pre] \setupbackgrounds[page][background=pagegrid] +% +% \placefigure[left,none]{}{\offset[leftoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte +% \placefigure[left,none]{}{\offset[rightoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte +% \placefigure[left,none]{}{\offset[topoffset=1cm] {\externalfigure[cow][width=3cm]}} \input tufte +% \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[cow][width=3cm]}} \input tufte + +% Some old code: +% +% \ltabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf +% \ltabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf +% \ltabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf +% +% \rtabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf +% \rtabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf +% \rtabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf +% +% \ctabbed{\romannumerals{3}}{\romannumerals{1}} test \endgraf +% \ctabbed{\romannumerals{3}}{\romannumerals{2}} test \endgraf +% \ctabbed{\romannumerals{3}}{\romannumerals{3}} test \endgraf + +\def\pack_boxes_tabbed#1#2#3#4% + {\dontleavehmode + \begingroup + \setbox\scratchbox\hpack{#3}% + \hpack to \wd\scratchbox{#1#4#2}% + \endgroup} + +\permanent\protected\def\ltabbed{\pack_boxes_tabbed\relax\hss} +\permanent\protected\def\rtabbed{\pack_boxes_tabbed\hss \relax} +\permanent\protected\def\ctabbed{\pack_boxes_tabbed\hss \hss} + +\let\mtabbed\ctabbed + +% to be documented + +\permanent\protected\def\phantombox[#1]% == \framed[\c!empty=\v!yes,\c!offset=\v!overlay,#1]{} + {\hpack\bgroup + \letdummyparameter\c!width \zeropoint + \letdummyparameter\c!height\zeropoint + \letdummyparameter\c!depth \zeropoint + \getdummyparameters[#1]% + \setbox\scratchbox\emptyhbox + \wd\scratchbox\directdummyparameter\c!width + \ht\scratchbox\directdummyparameter\c!height + \dp\scratchbox\directdummyparameter\c!depth + \box\scratchbox + \egroup} + +% \backgroundimage{1}{\hsize}{\vsize}{\externalfigure[cow][\c!width=3cm]} + +% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% \framed[offset=overlay,width=6cm,height=3cm]{\backgroundimage {3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} + +% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[cow][width=1cm]}} +% +% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[mill]}} +% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[mill]}} +% \framed[offset=overlay,width=4cm,height=2cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[mill]}} +% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{1}{\hsize}{\vsize}{\externalfigure[mill]}} +% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{2}{\hsize}{\vsize}{\externalfigure[mill]}} +% \framed[offset=overlay,width=2cm,height=4cm]{\backgroundimagefill{3}{\hsize}{\vsize}{\externalfigure[mill]}} + +\permanent\protected\def\backgroundimage#1#2#3% repeat hsize vsize + {\bgroup + \forgetall + \scratchcounter#1\relax + \scratchwidth #2\relax + \scratchheight #3\relax + \dowithnextboxcs\pack_boxes_background_image\hbox} + +\def\pack_boxes_background_image + {\offinterlineskip + \ifcase\scratchcounter + % just one + \else + \scratchdimen\scratchwidth \divide\scratchdimen\wd\nextbox\scratchnx\scratchdimen\advance\scratchnx\plusone\relax + \scratchdimen\scratchheight\divide\scratchdimen\ht\nextbox\scratchny\scratchdimen\advance\scratchny\plusone\relax + % to be considered: methods + \ifcase\scratchcounter + \or % x and y + \setbox\nextbox\hpack{\dorecurse\scratchnx{\copy\nextbox}}% + \setbox\nextbox\vpack{\dorecurse\scratchny{\copy\nextbox\endgraf}}% + \or % x + \setbox\nextbox\hpack{\dorecurse\scratchnx{\copy\nextbox}}% + \or % y + \setbox\nextbox\vpack{\dorecurse\scratchny{\copy\nextbox\endgraf}}% + \fi + \fi + \ifdim\wd\nextbox>\scratchwidth + \setbox\nextbox\hpack to \scratchwidth{\hss\box\nextbox\hss}% + \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}% + \fi + \ifdim\ht\nextbox>\scratchheight + \setbox\nextbox\vpack to \scratchheight{\vss\box\nextbox\vss}% + \setbox\nextbox\hpack{\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}% + \fi + \box\nextbox + \egroup} + +\permanent\protected\def\backgroundimagefill#1#2#3% repeat hsize vsize + {\bgroup + \forgetall + \scratchcounter#1\relax + \scratchwidth #2\relax + \scratchheight #3\relax + \dowithnextboxcs\pack_boxes_background_image_fill\hbox} + +\def\pack_boxes_background_image_fill + {\offinterlineskip + \setbox\nextbox\hpack\bgroup + \ifdim\scratchwidth>\scratchheight + \scale[\c!width=\the\scratchwidth]{\box\nextbox}% + \else + \scale[\c!height=\the\scratchheight]{\box\nextbox}% + \fi + \egroup + \ifdim\wd\nextbox>\scratchwidth + \setbox\nextbox\hpack to \scratchwidth + {\ifcase\scratchcounter + \hss\box\nextbox\hss + \or + \box\nextbox\hss + \or + \hss\box\nextbox + \else + \hss\box\nextbox\hss + \fi}% + \setbox\nextbox\hpack + {\normalexpanded{\clip[\c!width=\the\scratchwidth,\c!height=\the\ht\nextbox]{\box\nextbox}}}% + \fi + \ifdim\ht\nextbox>\scratchheight + \setbox\nextbox\vpack to \scratchheight + {\ifcase\scratchcounter + \vss\box\nextbox\vss + \or + \box\nextbox\vss + \or + \vss\box\nextbox + \else + \vss\box\nextbox\vss + \fi}% + \setbox\nextbox\hpack + {\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=\the\scratchheight]{\box\nextbox}}}% + \fi + \box\nextbox + \egroup} + +\permanent\protected\def\overlayimage#1% + {\vpack to \overlayheight\bgroup + \vss + \hpack to \overlaywidth\bgroup + \hss + \externalfigure[#1][\c!factor=\v!min,\c!equalwidth=\overlaywidth,\c!equalheight=\overlayheight]% + \hss + \egroup + \vss + \egroup} + +\permanent\protected\def\clippedoverlayimage#1% + {\clip + [\c!width=\overlaywidth,\c!height=\overlayheight] + {\overlayimage{#1}}} + +\protect \endinput diff --git a/tex/context/base/mkiv/pack-com.mkxl b/tex/context/base/mkiv/pack-com.mkxl new file mode 100644 index 000000000..5b7a16359 --- /dev/null +++ b/tex/context/base/mkiv/pack-com.mkxl @@ -0,0 +1,949 @@ +%D \module +%D [ file=pack-com, % used to be in core-mis, +%D version=20120111, +%D title=\CONTEXT\ Packing Macros, +%D subtitle=Combinations, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Packaging Macros / Combinations} + +\unprotect + +% \startfloatcombination will be redone ... we can decouple the floatcontent +% and caption and pass them to combinations so that we get better fit when the +% caption is wider than the float, testcase: +% +% \startfloatcombination [2*2] +% \placefigure[local]{alpha}{\externalfigure[cow.pdf][width=1cm]}% +% \placefigure[local]{beta} {\externalfigure[cow.pdf][width=2cm]}% +% \placefigure[local]{gamma}{\externalfigure[cow.pdf][width=3cm]} +% \placefigure[local]{delta}{\externalfigure[cow.pdf][width=4cm]} +% \stopfloatcombination + +%D We could of course map combinations onto one of the table mechanisms but as it +%D has served us well for ages we keep this one. The code has been cleaned up a bit +%D and mkiv'd. +%D +%D Okay ... I might luafy this one eventually. + +% \startcombination {alpha} {a} {beta} {b} \stopcombination +% \startcombination[2*1] {alpha} {a} {beta} {b} \stopcombination +% \startcombination[1*2] {alpha} {a} {beta} {b} \stopcombination +% \startcombination[2] {alpha} {a} {beta} {b} \stopcombination +% \startcombination[2] \combination {alpha} {a} \combination{beta} {b} \stopcombination + +%D We do support some structure but the order matters and currently it's only window +%D dressing: + +%D \starttyping +%D \let\startcontent\bgroup +%D \let\stopcontent \egroup +%D \let\startcaption\bgroup +%D \let\stopcaption \egroup +%D \stoptyping +%D +%D Of course we should have started with more structure as it would simply the code. +%D +%D \starttyping +%D \startcombination +%D \startcontent +%D \externalfigure[cow] +%D \stopcontent +%D \startcaption +%D Some cow. +%D \stopcaption +%D \startcontent +%D \externalfigure[cow] +%D \stopcontent +%D \startcaption +%D The same cow. +%D \stopcaption +%D \stopcombination +%D \stoptyping + +\ifdefined\dotagcombination \else \let\dotagcombination\relax \fi + +\newsystemmode{combination} + +\appendtoks + \globalresetsystemmode{combination}% +\to \everyinsidefloat + +\newcount\c_pack_combinations_nesting % local + +\newcount\c_pack_combinations_x % global +\newcount\c_pack_combinations_y % global +\newcount\c_pack_combinations_max % global + +\newdimen\d_pack_combinations_ht % global + +\newbox \b_pack_combinations_captions % global % can go +\newbox \b_pack_combinations_temp % global % can go +\newbox \b_pack_combinations_content % local +\newbox \b_pack_combinations_caption % local + +\installcorenamespace{combination} + +\installcommandhandler \??combination {combination} \??combination + +\initializeboxstack{\??combination captions} +\initializeboxstack{\??combination temp} + +\newcount\c_pack_combinations_x_saved +\newcount\c_pack_combinations_y_saved +\newcount\c_pack_combinations_max_saved + +\newdimen\d_pack_combinations_ht_saved + +\newbox \b_pack_combinations_captions_saved +\newbox \b_pack_combinations_temp_saved +\newbox \b_pack_combinations_content_saved +\newbox \b_pack_combinations_caption_saved + +\setfalse\c_strc_constructions_define_commands + +\def\pack_combinations_push + {\advance\c_pack_combinations_nesting\plusone + \ifnum\c_pack_combinations_nesting>\plusone + \c_pack_combinations_x_saved \c_pack_combinations_x + \c_pack_combinations_y_saved \c_pack_combinations_y + \c_pack_combinations_max_saved\c_pack_combinations_max + \d_pack_combinations_ht_saved \d_pack_combinations_ht + \setbox\b_pack_combinations_captions_saved\box\b_pack_combinations_captions + \setbox\b_pack_combinations_temp_saved \box\b_pack_combinations_temp + \setbox\b_pack_combinations_content_saved \box\b_pack_combinations_content + \setbox\b_pack_combinations_caption_saved \box\b_pack_combinations_caption + \else + \globalsetsystemmode{combination}% why global + \fi} + +\def\pack_combinations_pop + {\ifnum\c_pack_combinations_nesting>\plusone + \global\c_pack_combinations_x \c_pack_combinations_x_saved + \global\c_pack_combinations_y \c_pack_combinations_y_saved + \global\c_pack_combinations_max\c_pack_combinations_max_saved + \global\d_pack_combinations_ht \d_pack_combinations_ht_saved + \global\setbox\b_pack_combinations_captions\box\b_pack_combinations_captions_saved + \global\setbox\b_pack_combinations_temp \box\b_pack_combinations_temp_saved + \setbox\b_pack_combinations_content \box\b_pack_combinations_content_saved + \setbox\b_pack_combinations_caption \box\b_pack_combinations_caption_saved + \else + \globalresetsystemmode{combination}% why global + \fi + \advance\c_pack_combinations_nesting\minusone} + +\definelabel + [\v!combination] % handy for configuring + [\c!numberconversion=\v!character, + \c!text=] + +\settrue\c_strc_constructions_define_commands + +\setupcombination + [\c!width=\v!fit, + \c!height=\v!fit, + \c!distance=\emwidth, + \c!location=\v!bottom, % can be something {top,left} + \c!before=\blank, + \c!after=, + \c!inbetween={\blank[\v!medium]}, + %\c!style=, + %\c!color=, + \c!nx=2, % new + \c!ny=1, % new + \c!align=\v!middle] + +\let\setupcombinations\setupcombination % for the moment (we might distinguish) + +\installcorenamespace{combinationlocation} +\installcorenamespace{combinationalternative} + +\appendtoks + \setfalse\c_strc_constructions_define_commands + \normalexpanded + {\definelabel + [\v!combination:\currentcombination]% + [\v!combination\ifx\currentcombinationparent\empty\else:\currentcombinationparent\fi]}% + [\s!counter=\currentcombination,\c!levels=1]% + \settrue\c_strc_constructions_define_commands +\to \everydefinecombination + +\setvalue{\??combinationlocation\v!left }{\let\m_pack_combinations_leftfiller\relax} +\setvalue{\??combinationlocation\v!right }{\let\m_pack_combinations_rightfiller\relax} +\setvalue{\??combinationlocation\v!top }{\let\m_pack_combinations_valigner\depthonlybox} +\setvalue{\??combinationlocation\v!middle}{\let\m_pack_combinations_valigner\halfwaybox} + +\def\pack_combinations_location_reset + {\let\m_pack_combinations_rightfiller\hfil + \let\m_pack_combinations_leftfiller \hfil + \let\m_pack_combinations_valigner \firstofoneargument} + +\pack_combinations_location_reset + +\def\pack_combinations_location_step#1% + {\csname\??combinationlocation#1\endcsname} + +% formally ok: +% +% \protected\def\stopcombination +% {\egroup +% \egroup} +% +% more robust: +% +% \protected\def\stopcombination +% {{}{}{}{}{}{}{}{}% catches (at most 4) missing entries +% \egroup +% \egroup} +% +% even better: +% +% \protected\def\stopcombination +% {\bgroup +% \scratchtoks{{}}% +% \dorecurse\c_pack_combinations_y +% {\toksapp{{}{}}}% +% \expandafter\egroup\the\scratchtoks +% \egroup +% \dostoptagged +% \egroup} +% +% faster + +\protected\def\pack_common_content_start{\bgroup\ignorespaces} +\protected\def\pack_common_content_stop {\removeunwantedspaces\egroup} +\protected\def\pack_common_caption_start{\bgroup\ignorespaces} +\protected\def\pack_common_caption_stop {\removeunwantedspaces\egroup} + +\newtoks\everycombination + +\protected\def\stopcombination + {\bgroup\normalexpanded{\egroup{}\ntimes{{}{}}\c_pack_combinations_y}% brr + \dostoptagged + \egroup + \pack_combinations_pop + \egroup} + +\permanent\tolerant\protected\def\startcombination[#1]#*[#2]% can be simplified + {\bgroup % so we can grab a group + \pack_combinations_push + \edef\currentcombination{#1}% + \edef\currentcombinationspec{#2}% + \ifx\currentcombinationspec\empty + \ifcondition\validassignment{#1}% + \let\currentcombination\empty + \setupcurrentcombination[#1]% + \edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}% + \else + \doifelseinstring{*}\currentcombination + {\edef\currentcombinationspec{\currentcombination*\plusone*}% + \let\currentcombination\empty} + {\doifelsenumber\currentcombination + {\edef\currentcombinationspec{\currentcombination*\plusone*}% + \let\currentcombination\empty} + {\edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}}}% + \fi + \else + \ifcondition\validassignment{#2}% + \setupcurrentcombination[#2]% + \edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}% + \else + \edef\currentcombinationspec{\currentcombinationspec*\plusone*}% + \fi + \fi + % + \forgetall + % + \the\everycombination + % + \let\startcontent\pack_common_content_start + \let\stopcontent \pack_common_content_stop + \let\startcaption\pack_common_caption_start + \let\stopcaption \pack_common_caption_stop + % + \edef\p_height {\combinationparameter\c!height}% + \edef\p_width {\combinationparameter\c!width}% + \edef\p_location{\combinationparameter\c!location}% + \edef\p_distance{\combinationparameter\c!distance}% + % + \pack_combinations_location_reset + \rawprocesscommacommand[\p_location]\pack_combinations_location_step + % + \dostarttaggedchained\t!combination\currentcombination\??combination + \vbox \ifx\p_height\v!fit\else to \p_height \fi \bgroup + \let\combination\empty % permits \combination{}{} handy for cld + \normalexpanded{\pack_combinations_start_indeed[\currentcombinationspec]}} + +\let\pack_combinations_check_x_y\relax + +\protected\def\pack_combinations_start_indeed[#1*#2*#3]% + {\global\c_pack_combinations_x#1\relax + \global\c_pack_combinations_y#2\relax + \setexpandedcombinationparameter\c!nx{\the\c_pack_combinations_x}% in case we access it + \setexpandedcombinationparameter\c!ny{\the\c_pack_combinations_y}% in case we access it + \pack_combinations_check_x_y + \dotagcombination + \global\setbox\b_pack_combinations_captions\emptybox + \global\c_pack_combinations_max\c_pack_combinations_x + \multiply\c_pack_combinations_y\c_pack_combinations_x + \tabskip\zeropoint + \halign \ifx\p_width\v!fit\else to \p_width \fi \bgroup % repetitive preamble + \aligntab + \m_pack_combinations_leftfiller + \alignmark\alignmark + \m_pack_combinations_rightfiller + \aligntab + \tabskip\zeropoint \s!plus 1fill % \fillskip + \alignmark\alignmark + \cr + \pack_combinations_pickup} + +%D I've first considered using a constructor directly but it's more overhead and +%D some settings conflict with already used combination settings so instead we plug +%D in labels. This also permits extensions later on. + +\appendtoks + \edef\p_pack_combinations_alternative{\combinationparameter\c!alternative}% +\to \everydefinecombination + +\def\pack_combinations_pickup + {\dostarttagged\t!combinationpair\empty % better make this text + \dostarttagged\t!combinationcontent\empty + \assumelongusagecs\pack_combinations_pickup_content_indeed} + +\def\pack_combinations_pickup_content_indeed + {\dowithnextboxcs\pack_combinations_pickup_content\hbox} + +\def\pack_combinations_pickup_content % we want to add struts but still ignore an empty box + {\dostoptagged + \setbox\b_pack_combinations_content\box\nextbox + \dostarttagged\t!combinationcaption\empty + \expandnamespacemacro\??combinationalternative\p_pack_combinations_alternative\v!text} + +\setvalue{\??combinationalternative\v!text}% + {\assumelongusagecs\pack_combinations_alternative_text_indeed} + +\setvalue{\??combinationalternative\v!label}% + {\assumelongusagecs\pack_combinations_alternative_label_indeed} + +\def\pack_combinations_alternative_text_indeed + {\dowithnextboxcs\pack_combinations_pickup_caption\vtop\bgroup + \afterassignment\pack_combinations_caption_first + \let\nexttoken=} + +\def\pack_combinations_alternative_label_indeed + {\dowithnextboxcs\pack_combinations_pickup_caption\vtop\bgroup + \hsize\wd\b_pack_combinations_content + \usealignparameter\combinationparameter + \usecombinationstyleandcolor\c!style\c!color + \begstrut + \normalexpanded{\strc_labels_command[\v!combination\ifx\currentcombination\empty\else:\currentcombination\fi]}% + \endstrut + \egroup} + +\appendtoks + \edef\p_pack_combinations_alternative{\combinationparameter\c!alternative}% + \ifx\p_pack_combinations_alternative\v!label + \edef\p_continue{\combinationparameter\c!continue}% + \ifx\p_continue\v!yes \else + \normalexpanded{\strc_labels_reset{\v!combination\ifx\currentcombination\empty\else:\currentcombination\fi}{1}}% + \fi + \fi +\to \everycombination + +\def\pack_combinations_pickup_caption + {\dostoptagged + \dostoptagged + \setbox\b_pack_combinations_caption\box\nextbox + \pack_combinations_pickup_package_pair} + +\def\pack_combinations_caption_first + {\futurelet\nexttoken\pack_combinations_caption_second} + +\def\pack_combinations_caption_second + {\ifx\nexttoken\egroup + % the caption is empty + \orelse\ifx\nexttoken\stopcaption + % the caption is empty (new per 2014-05-24) + \else + % todo: \p_pack_combinations_alternative\v!none: no style, strut etc + \hsize\wd\b_pack_combinations_content + \usealignparameter\combinationparameter + \usecombinationstyleandcolor\c!style\c!color + \bgroup + \aftergroup\endstrut + \aftergroup\egroup + \begstrut + \fi} + +\def\pack_combinations_pickup_package_pair % we need to store the caption row + {\vbox + {\forgetall + \m_pack_combinations_valigner{\box\b_pack_combinations_content}% + % we need to save the caption for a next alignment line + \pack_combinations_save_caption}% + \ifnum\c_pack_combinations_y>\plusone + \global\advance\c_pack_combinations_y\minusone + \global\advance\c_pack_combinations_x\minusone + \ifcase\c_pack_combinations_x + \doubleexpandafter\pack_combinations_pickup_package_pair_a + \else + \doubleexpandafter\pack_combinations_pickup_package_pair_b + \fi + \else + \singleexpandafter\pack_combinations_pickup_package_pair_c + \fi} + +\def\pack_combinations_pickup_package_pair_a + {\cr + \pack_combinations_flush_captions + \noalign + {\forgetall + \global\setbox\b_pack_combinations_captions\emptybox + \nointerlineskip + \combinationparameter\c!after + \combinationparameter\c!before + \vss + \nointerlineskip}% + \global\c_pack_combinations_x\c_pack_combinations_max + \pack_combinations_pickup} + +\def\pack_combinations_pickup_package_pair_b + {\aligntab + \aligntab + \aligntab + \kern\p_distance + \aligntab + \pack_combinations_pickup} + +\def\pack_combinations_pickup_package_pair_c + {\cr + \pack_combinations_flush_captions + \egroup} + +\installcorenamespace{combinationcaption} + +\def\pack_combinations_save_caption + {\ifdim\htdp\b_pack_combinations_caption>\d_pack_combinations_ht + \global\d_pack_combinations_ht\htdp\b_pack_combinations_caption + \fi + \savebox{\??combinationcaption:\number\c_pack_combinations_nesting}{\number\c_pack_combinations_x}{\box\b_pack_combinations_caption}} + +\def\pack_combinations_flush_captions + {\noalign + {\ifdim\d_pack_combinations_ht>\zeropoint + \nointerlineskip % indeed + \combinationparameter\c!inbetween + \global\c_pack_combinations_x\c_pack_combinations_max + \glet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_yes + \else + \glet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_nop + \fi}% + \pack_combinations_flush_captions_indeed + \crcr} + +\def\pack_combinations_flush_captions_yes + {\vpack to \d_pack_combinations_ht\bgroup + \foundbox{\??combinationcaption:\number\c_pack_combinations_nesting}{\number\c_pack_combinations_x}% + \vss + \egroup + \global\advance\c_pack_combinations_x\minusone + \ifnum\c_pack_combinations_x>\zerocount % \c_pack_combinations_max + \expandafter\pack_combinations_flush_captions_yes_followup + \else + \global\d_pack_combinations_ht\zeropoint + \initializeboxstack{\??combinationcaption:\number-\c_pack_combinations_nesting}% + \fi} + +\let\pack_combinations_flush_captions_nop\donothing + +\def\pack_combinations_flush_captions_yes_followup + {\aligntab + \aligntab + \aligntab + \aligntab + \pack_combinations_flush_captions_indeed} + +%D \macros +%D {startfloatcombination} +%D +%D \setupexternalfigures[directory={../sample}] +%D \startbuffer +%D \placefigure +%D [left,none] +%D {} +%D {\startfloatcombination[2*2] +%D \placefigure{alpha}{\externalfigure[cow.pdf][width=1cm]} +%D \placefigure{beta} {\externalfigure[cow.pdf][width=2cm]} +%D \placefigure{gamma}{\externalfigure[cow.pdf][width=3cm]} +%D \placefigure{delta}{\externalfigure[cow.pdf][width=4cm]} +%D \stopfloatcombination} +%D +%D \input tufte +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\protected\def\pack_combinations_float_hack_a#1% + {\strc_floats_build_box_separate_split{#1}% + \box\b_strc_floats_separate_content} + +\protected\def\pack_combinations_float_hack_b#1% + {\box\b_strc_floats_separate_caption} + +\permanent\tolerant\protected\def\startfloatcombination[#1]#*[#2]% + {\ifinsidefloat\else\dontleavehmode\fi % tricky, floatcombinations fail to align well otherwise + \vbox\bgroup + \strc_floats_build_box_separate_set + %\insidecolumnstrue % trick, forces no centering, todo: proper switch/feature + \postcenterfloatmethod\zerocount + \forcelocalfloats + \protected\def\stopfloatcombination{\pack_combinations_stop_float{#1}}} + +\let\stopfloatcombination\relax + +\def\pack_combinations_float_check_x_y + {\ifnum\numexpr\c_pack_combinations_x*\c_pack_combinations_y\relax<\noflocalfloats\relax + \global\c_pack_combinations_x\noflocalfloats + \global\c_pack_combinations_y\plusone + \fi + \let\pack_combinations_check_x_y\relax}% + +\def\pack_combinations_stop_float#1% + {\scratchtoks\emptytoks + \dorecurse\noflocalfloats + {\appendetoks + {\pack_combinations_float_hack_a{\recurselevel}}% + {\pack_combinations_float_hack_b{\recurselevel}}% + \to\scratchtoks}% brrr + \let\pack_combinations_check_x_y\pack_combinations_float_check_x_y + \expanded{\startcombination[#1]\the\scratchtoks}\stopcombination + \resetlocalfloats + \egroup} + +%D \macros +%D {definepairedbox, setuppairedbox, placepairedbox} +%D +%D Paired boxes, formally called legends, but from now on a legend is just an +%D instance, are primarily meant for typesetting some text alongside an +%D illustration. Although there is quite some variation possible, the functionality +%D is kept simple, if only because in most cases such pairs are typeset sober. +%D +%D The location specification accepts a pair, where the first keyword specifies the +%D arrangement, and the second one the alignment. The first key of the location pair +%D is one of \type {left}, \type {right}, \type {top} or \type {bottom}, while the +%D second key can also be \type {middle}. +%D +%D The first box is just collected in an horizontal box, but the second one is a +%D vertical box that gets passed the bodyfont and alignment settings. +%D +%D In many cases the table builders can be used instead, but as this mechanism is a +%D traditional \CONTEXT\ one we keep it around. + +%D \macros +%D {setuplegend, placelegend} +%D +%D It makes sense to typeset a legend to a figure in \TEX\ and not in a drawing +%D package. The macro \type {\placelegend} combines a figure (or something else) and +%D its legend. This command is just a paired box. +%D +%D The legend is placed according to \type {location}, being \type {bottom} or \type +%D {right}. The macro macro is used as follows. +%D +%D \starttyping +%D \placefigure +%D {whow} +%D {\placelegend +%D {\externalfigure[cow]} +%D {\starttabulate +%D \NC 1 \NC head \NC \NR +%D \NC 2 \NC legs \NC \NR +%D \NC 3 \NC tail \NC \NR +%D \stoptabulate}} +%D +%D \placefigure +%D {whow} +%D {\placelegend +%D {\externalfigure[cow]} +%D {\starttabulate[|l|l|l|l|] +%D \NC 1 \NC head \NC 3 \NC tail \NC \NR +%D \NC 2 \NC legs \NC \NC \NC \NR +%D \stoptabulate}} +%D +%D \placefigure +%D {whow} +%D {\placelegend[n=2] +%D {\externalfigure[cow]} +%D {\starttabulate +%D \NC 1 \NC head \NC \NR +%D \NC 2 \NC legs \NC \NR +%D \NC 3 \NC tail \NC \NR +%D \stoptabulate}} +%D +%D \placefigure +%D {whow} +%D {\placelegend[n=2] +%D {\externalfigure[cow]} +%D {head \par legs \par tail}} +%D +%D \placefigure +%D {whow} +%D {\placelegend[n=2] +%D {\externalfigure[cow]} +%D {\startitemize[packed] +%D \item head \item legs \item tail \item belly \item horns +%D \stopitemize}} +%D +%D \placefigure +%D {whow} +%D {\placelegend[n=2,width=.8\hsize] +%D {\externalfigure[cow]} +%D {\startitemize[packed] +%D \item head \item legs \item tail \item belly \item horns +%D \stopitemize}} +%D +%D \def\MytTestTwo#1#2% +%D {\placefigure +%D {whow} +%D {\placelegend[location={#1,#2}] +%D {\externalfigure[cow]} +%D {\starttabulate +%D \NC 1 \NC head \NC \NR +%D \NC 2 \NC legs \NC \NR +%D \NC 3 \NC tail \NC \NR +%D \stoptabulate}}} +%D +%D \def\MytTestOne#1{\processcommalist[left,right,top,bottom]{\MytTestTwo{#1}}} +%D +%D \processcommalist[left,right,top,bottom,middle]\MytTestOne +%D \stoptyping +%D +%D More structure is also possible (the order matters!): +%D +%D \starttyping +%D \startplacefigure[title=whow] +%D \startplacelegend[location={bottom,middle},color=red] +%D \startcontent +%D \externalfigure[cow] +%D \stopcontent +%D \startcaption +%D \starttabulate[|l|l|] +%D \NC 1 \NC head \NC \NR +%D \NC 2 \NC legs \NC \NR +%D \NC 3 \NC tail \NC \NR +%D \stoptabulate +%D \stopcaption +%D \stopplacelegend +%D \stopplacefigure +%D \stoptyping + +% todo: natural size + +\newsystemmode{pairedbox} + +\appendtoks + \globalresetsystemmode{pairedbox}% +\to \everyinsidefloat + +\installcorenamespace {pairedbox} + +\installcommandhandler \??pairedbox {pairedbox} \??pairedbox + +\setuppairedbox + [\c!n=1, + \c!distance=\bodyfontsize, + %\c!before=, + %\c!after=, + %\c!color=, + %\c!style=, + \c!inbetween={\blank[\v!medium]}, + \c!width=\hsize, + \c!height=\vsize, + \c!maxwidth=\textwidth, % \makeupwidth, + \c!maxheight=\textheight, % \makeupheight, + %\c!bodyfont=, + %\c!align=, + \c!location=\v!bottom] + +% watch the hsize/vsize tricks + +\newbox \b_pack_pairedboxes_first +\newbox \b_pack_pairedboxes_second +\newdimen\s_pack_pairedboxes_size + +\appendtoks + \setuevalue{\e!setup\currentpairedbox\e!endsetup}{\setuppairedbox [\currentpairedbox]}% + \setuevalue{\e!place\currentpairedbox }{\placepairedbox [\currentpairedbox]}% one argument is mandate anyway + \setuevalue{\e!start\e!place\currentpairedbox }{\startplacepairedbox[\currentpairedbox]}% one argument is mandate anyway + \setuevalue{\e!stop\e!place \currentpairedbox }{\stopplacepairedbox }% +\to \everydefinepairedbox + +\permanent\tolerant\protected\def\startplacepairedbox[#1]#*[#2]% + {\bgroup + \edef\currentpairedbox{#1}% + \setupcurrentpairedbox[#2]% + \pairedboxparameter\c!before + \bgroup + \edef\p_location{\pairedboxparameter\c!location}% + \edef\p_n {\pairedboxparameter\c!n}% + % + \let\startcontent\pack_common_content_start + \let\stopcontent \pack_common_content_stop + \let\startcaption\pack_common_caption_start + \let\stopcaption \pack_common_caption_stop + % + \globalsetsystemmode{pairedbox}% + \pack_pairedboxes_before + \assumelongusagecs\pack_pairedboxes_first_pickup} + +\permanent\protected\def\stopplacepairedbox{} % we just pick up two boxes + +\let\placepairedbox\startplacepairedbox % we just pick up two boxes + +\def\pack_pairedboxes_first_pickup + {\dowithnextboxcs\pack_pairedboxes_first\hbox + \bgroup + \let\next=} + +\def\pack_pairedboxes_first + {\pack_pairedboxes_between + \assumelongusagecs\pack_pairedboxes_second_pickup} + +\def\pack_pairedboxes_second_pickup + {\dowithnextboxcs\pack_pairedboxes_second\vbox + \bgroup + \pack_pairedboxes_inside_second + \let\next=} + +\def\pack_pairedboxes_second + {\pack_pairedboxes_after + \egroup + \pairedboxparameter\c!after + \egroup} + +\newconditional\c_pack_pairedboxes_horizontal \settrue\c_pack_pairedboxes_horizontal + +\installcorenamespace{pairedboxnature} +\installcorenamespace{pairedboxalign} + +\let\pack_pairedboxes_fill_top \relax +\let\pack_pairedboxes_fill_bottom\relax + +\setvalue{\??pairedboxnature\v!left}% + {\settrue\c_pack_pairedboxes_horizontal + \let\pack_pairedboxes_flush\pack_pairedboxes_flush_left} + +\setvalue{\??pairedboxnature\v!right}% + {\settrue\c_pack_pairedboxes_horizontal + \let\pack_pairedboxes_flush\pack_pairedboxes_flush_right} + +\setvalue{\??pairedboxnature\v!top}% + {\setfalse\c_pack_pairedboxes_horizontal + \let\pack_pairedboxes_fill_top\relax + \let\pack_pairedboxes_fill_bottom\vss + \let\pack_pairedboxes_flush\pack_pairedboxes_flush_top} + +\setvalue{\??pairedboxnature\v!bottom}% + {\setfalse\c_pack_pairedboxes_horizontal + \let\pack_pairedboxes_fill_top\vss + \let\pack_pairedboxes_fill_bottom\relax + \let\pack_pairedboxes_flush\pack_pairedboxes_flush_bottom} + +\def\pack_pairedboxes_flush_left + {\box\b_pack_pairedboxes_second + \kern\pairedboxparameter\c!distance + \box\b_pack_pairedboxes_first} + +\def\pack_pairedboxes_flush_right + {\box\b_pack_pairedboxes_first + \kern\pairedboxparameter\c!distance + \box\b_pack_pairedboxes_second} + +\def\pack_pairedboxes_flush_top + {\box\b_pack_pairedboxes_second + \endgraf + \nointerlineskip + \pairedboxparameter\c!inbetween + \box\b_pack_pairedboxes_first} + +\def\pack_pairedboxes_flush_bottom + {\box\b_pack_pairedboxes_first + \endgraf + \nointerlineskip + \pairedboxparameter\c!inbetween + \box\b_pack_pairedboxes_second} + +\setvalue{\??pairedboxalign\v!left}% 0 + {\let\pack_pairedboxes_align_l\relax + \let\pack_pairedboxes_align_r\hss + \let\pack_pairedboxes_align_t\relax + \let\pack_pairedboxes_align_b\relax} + +\setvalue{\??pairedboxalign\v!right}% 1 + {\let\pack_pairedboxes_align_l\hss + \let\pack_pairedboxes_align_r\relax + \let\pack_pairedboxes_align_t\relax + \let\pack_pairedboxes_align_b\relax} + +\setvalue{\??pairedboxalign\v!high}% 2 + {\let\pack_pairedboxes_align_l\relax + \let\pack_pairedboxes_align_r\relax + \let\pack_pairedboxes_align_t\relax + \let\pack_pairedboxes_align_b\vss} + +\setvalue{\??pairedboxalign\v!low}% 3 + {\let\pack_pairedboxes_align_l\relax + \let\pack_pairedboxes_align_r\relax + \let\pack_pairedboxes_align_t\vss + \let\pack_pairedboxes_align_b\relax} + +\setvalue{\??pairedboxalign\v!middle}% 4 + {\let\pack_pairedboxes_align_l\hss + \let\pack_pairedboxes_align_r\hss + \let\pack_pairedboxes_align_t\vss + \let\pack_pairedboxes_align_b\vss} + +\setvalue{\??pairedboxalign\v!bottom}{\getvalue{\??pairedboxalign\v!low }} +\setvalue{\??pairedboxalign \v!top}{\getvalue{\??pairedboxalign\v!high}} + +\def\pack_pairedbox_valign#1{\setbox#1\vpack to \s_pack_pairedboxes_size{\pack_pairedboxes_align_t\box#1\pack_pairedboxes_align_b}} +\def\pack_pairedbox_halign#1{\setbox#1\hpack to \s_pack_pairedboxes_size{\pack_pairedboxes_align_l\box#1\pack_pairedboxes_align_r}} + +\def\pack_pairedboxes_before + {\ifx\p_location\empty + \csname\??pairedboxnature\v!left \endcsname + \csname\??pairedboxalign \v!middle\endcsname + \else + \getfromcommacommand[\p_location][1]% + \csname\??pairedboxnature + \ifcsname\??pairedboxnature\commalistelement\endcsname\commalistelement\else\v!left\fi + \endcsname + \getfromcommacommand[\p_location][2]% + \csname\??pairedboxalign + \ifcsname\??pairedboxalign\commalistelement\endcsname\commalistelement\else\v!middle\fi + \endcsname + \fi} + +\def\pack_pairedboxes_between + {\usebodyfontparameter\pairedboxparameter + \setbox\b_pack_pairedboxes_first\box\nextbox + \ifconditional\c_pack_pairedboxes_horizontal + \pack_pairedboxes_between_horizontal + \else + \pack_pairedboxes_between_vertical + \fi + \ifnum\p_n>\plusone + \setrigidcolumnhsize\hsize{\pairedboxparameter\c!distance}\p_n + \fi} + +\def\pack_pairedboxes_between_horizontal + {\scratchdistance\pairedboxparameter\c!distance + \scratchwidth\pairedboxparameter\c!maxwidth\relax + \setlocalhsize + \hsize\dimexpr\availablehsize-\wd\b_pack_pairedboxes_first-\scratchdistance\relax + \hsize\pairedboxparameter\c!width\relax % can be \hsize + \scratchdimen\dimexpr\wd\b_pack_pairedboxes_first+\scratchdistance\relax + \ifdim\dimexpr\hsize+\scratchdimen\relax>\scratchwidth + \hsize\dimexpr\scratchwidth-\scratchdimen\relax + \fi} + +\def\pack_pairedboxes_between_vertical + {\scratchwidth\pairedboxparameter\c!maxwidth\relax + \hsize\wd\b_pack_pairedboxes_first + \hsize\pairedboxparameter\c!width\relax % can be \hsize + \ifdim\hsize>\scratchwidth\relax + \hsize\scratchwidth + \fi} + +\def\pack_pairedboxes_after + {\setbox\b_pack_pairedboxes_second\vpack + {\ifnum\p_n>\plusone + \rigidcolumnbalance\nextbox + \else + \box\nextbox + \fi}% + \ifconditional\c_pack_pairedboxes_horizontal + \pack_pairedboxes_pack_horizontal + \else + \pack_pairedboxes_pack_vertical + \fi} + +\def\pack_pairedboxes_pack_horizontal + {\dontleavehmode\hbox\bgroup + \forgetall + \s_pack_pairedboxes_size\ht + \ifdim\ht\b_pack_pairedboxes_first>\ht\b_pack_pairedboxes_second + \b_pack_pairedboxes_first + \else + \b_pack_pairedboxes_second + \fi + \vsize\s_pack_pairedboxes_size + \ifdim\s_pack_pairedboxes_size<\pairedboxparameter\c!height\relax % can be \vsize + \s_pack_pairedboxes_size\pairedboxparameter\c!height + \fi + \ifdim\s_pack_pairedboxes_size>\pairedboxparameter\c!maxheight\relax + \s_pack_pairedboxes_size\pairedboxparameter\c!maxheight + \fi + \pack_pairedbox_valign\b_pack_pairedboxes_first + \pack_pairedbox_valign\b_pack_pairedboxes_second + \pack_pairedboxes_flush + \egroup} + +\def\pack_pairedboxes_pack_vertical + {\dontleavehmode\vpack\bgroup + \forgetall + \s_pack_pairedboxes_size\wd + \ifdim\wd\b_pack_pairedboxes_first>\wd\b_pack_pairedboxes_second + \b_pack_pairedboxes_first + \else + \b_pack_pairedboxes_second + \fi + \pack_pairedbox_halign\b_pack_pairedboxes_first + \pack_pairedbox_halign\b_pack_pairedboxes_second + \s_pack_pairedboxes_size\ht\b_pack_pairedboxes_second + \vsize\s_pack_pairedboxes_size + \ifdim\ht\b_pack_pairedboxes_second<\pairedboxparameter\c!height\relax % can be \vsize + \s_pack_pairedboxes_size\pairedboxparameter\c!height\relax % \relax needed + \fi + \ifdim\s_pack_pairedboxes_size>\pairedboxparameter\c!maxheight\relax % todo: totale hoogte + \s_pack_pairedboxes_size\pairedboxparameter\c!maxheight\relax % \relax needed + \fi + \ifdim\s_pack_pairedboxes_size>\ht\b_pack_pairedboxes_second + \setbox\b_pack_pairedboxes_second\vpack to \s_pack_pairedboxes_size + {\pack_pairedboxes_fill_top + \box\b_pack_pairedboxes_second + \pack_pairedboxes_fill_bottom}% \kern\zeropoint + \fi + \pack_pairedboxes_flush + \egroup} + +\def\pack_pairedboxes_inside_second + {\forgetall + \setupalign[\pairedboxparameter\c!align]% + \usepairedboxstyleandcolor\c!style\c!color + \tolerantTABLEbreaktrue % hm. + \blank[\v!disable]% use fast one + \everypar{\begstrut}} % also flushers here (see bTABLE) + +\definepairedbox[\v!legend] + +\permanent\protected\def\placeontopofeachother{\bgroup\dowithnextboxcs\pack_topofeachother_one\hbox} +\permanent\protected\def\placesidebyside {\bgroup\dowithnextboxcs\pack_sidebyside_one \hbox} + +\def\pack_topofeachother_one{\bgroup\setbox\scratchboxone\box\nextbox\dowithnextboxcs\pack_topofeachother_two\hbox} +\def\pack_sidebyside_one {\bgroup\setbox\scratchboxone\box\nextbox\dowithnextboxcs\pack_sidebyside_two \hbox} + +\def\pack_topofeachother_two{\setbox\scratchboxtwo\box\nextbox + \halign{\hss\alignmark\alignmark\hss\cr\box\scratchboxone\cr\box\scratchboxtwo\cr}% + \egroup\egroup} +\def\pack_sidebyside_two {\setbox\scratchboxtwo\box\nextbox + \valign{\vss\alignmark\alignmark\vss\cr\box\scratchboxone\cr\box\scratchboxtwo\cr}% + \egroup\egroup} + +\protect \endinput diff --git a/tex/context/base/mkiv/pack-lyr.mkxl b/tex/context/base/mkiv/pack-lyr.mkxl index 419c9f279..366eeff75 100644 --- a/tex/context/base/mkiv/pack-lyr.mkxl +++ b/tex/context/base/mkiv/pack-lyr.mkxl @@ -32,11 +32,10 @@ \ifdefined\defineoverlay \else \message{loaded to early} \wait \fi -\unexpanded\def\defineoverlay - {\dotripleempty\pack_framed_define_overlay} +\pushoverloadmode -\def\pack_framed_define_overlay[#1][#2][#3]% overlay [layer] content - {\ifthirdargument +\permanent\overloaded\tolerant\protected\def\defineoverlay[#1]#*[#2]#*[#3]% overlay [layer] content + {\ifnum\lastarguments=\plusthree %\writestatus{BEWARE}{This (overlay definition) has changed!}% temp \def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\setlayer[#2]{\executedefinedoverlay{##1}{#3}}}}% \else @@ -44,6 +43,8 @@ \fi \processcommalist[#1]\pack_framed_define_overlay_indeed} +\popoverloadmode + %D We use the command handler code. The previous, more direct parameter handling was %D 25\% faster when no parameters were passed when adding content to a layer. %D However, when we pass for instance a preset, the new methos is some 10\% faster @@ -130,7 +131,7 @@ \newconditional\c_pack_layers_trace \newcount \c_pack_layers_current_data -\newbox\b_layers +\newbox\b_layers \pushoverloadmode \mutable\let\b_layers\b_layers \popoverloadmode \newdimen\d_pack_layers_x_size \newdimen\d_pack_layers_y_size @@ -178,7 +179,7 @@ \global\setbox\lastnamedcs\emptybox \fi} -\def\resetlayer[#1]% +\permanent\protected\def\resetlayer[#1]% {\pack_layers_reset_box{#1}% \pack_layers_reset_box{\v!left #1}% \pack_layers_reset_box{\v!right#1}% @@ -195,37 +196,33 @@ %D \setlayer [identifier] [optional parameters] {data} %D \stoptyping -\def\setcurrentlayerdimensions - {\dodoubleempty\pack_layers_set_current_dimensions} - -\def\pack_layers_set_current_dimensions[#1][#2]% name left|right +\permanent\tolerant\protected\def\setcurrentlayerdimensions[#1]#*[#2]% name left|right {\edef\currentlayerwidth {\thelayerwidth {#2#1}}% \edef\currentlayerheight{\thelayerheight{#2#1}}} -\def\thelayerwidth #1{\the\ifcsname\??layerbox#1\endcsname\wd\lastnamedcs\else\zeropoint\fi} -\def\thelayerheight#1{\the\ifcsname\??layerbox#1\endcsname\ht\lastnamedcs\else\zeropoint\fi} +\permanent\def\thelayerwidth #1{\the\ifcsname\??layerbox#1\endcsname\wd\lastnamedcs\else\zeropoint\fi} +\permanent\def\thelayerheight#1{\the\ifcsname\??layerbox#1\endcsname\ht\lastnamedcs\else\zeropoint\fi} -\unexpanded\def\setlayer - {\dotripleempty\pack_layers_set} - -\def\pack_layers_set[#1][#2][#3]% #4 == box do \fi is ok +\permanent\tolerant\protected\def\setlayer[#1]#*[#2]#*[#3]% #4 == box do \fi is ok {\bgroup + \nofarguments\lastarguments \checkpositionoverlays % otherwise funny regions \edef\currentlayer{#1}% \edef\p_pack_layers_state{\layerparameter\c!state}% \ifx\p_pack_layers_state\v!stop \dowithnextboxcs\egroup\hbox % no pack ? - \orelse\ifthirdargument - \pack_layers_set_indeed[#1][#2][#3]% + \orelse\ifnum\nofarguments=\plusthree + \edef\m_pack_layers_target{#2}% + \pack_layers_set_indeed{#3}% + \orelse\ifhastok={#2}% + \let\m_pack_layers_target\empty + \pack_layers_set_indeed{#2}% \else - \ifcondition\validassignment{#2}% - \pack_layers_set_indeed[#1][][#2]% - \else - \pack_layers_set_indeed[#1][#2][]% - \fi + \edef\m_pack_layers_target{#2}% + \pack_layers_set_indeed\empty \fi} -\def\pack_layers_set_indeed[#1][#2][#3]% #2 = links/rechts +\def\pack_layers_set_indeed#1% {\page_backgrounds_recalculate % brrr \global\advance\c_pack_layers_current_data\plusone \forgetall @@ -235,8 +232,7 @@ \settrue\c_pack_layers_trace \traceboxplacementtrue \fi - \edef\m_pack_layers_target{#2}% - \dowithnextbox{\pack_layers_set_finish{#3}}\hbox} + \dowithnextbox{\pack_layers_set_finish{#1}}\hbox} \def\pack_layers_set_finish#1% {\ifcsname\??layerbox\currentlayer\endcsname % can move up @@ -295,13 +291,15 @@ \doifinset\v!middle\p_pack_layers_corner\pack_layers_set_middle_positions \edef\m_pack_layers_page{\layerparameter\c!page}} -\unexpanded\def\definelayerpreset - {\dodoubleargument\pack_layers_define_preset} - -\def\pack_layers_define_preset[#1][#2]% - {\doifelseassignment{#2} - {\setvalue{\??layerpreset#1}{\setupcurrentlayer[#2]}} - {\setvalue{\??layerpreset#1}{\csname\??layerpreset#2\endcsname}}} +\permanent\tolerant\protected\def\definelayerpreset[#1]#*[#2]% + {\ifarguments + \or + \letvalue{\??layerpreset#1}\empty + \orelse\ifhastok={#2}% + \setvalue{\??layerpreset#1}{\setupcurrentlayer[#2]}% + \else + \setvalue{\??layerpreset#1}{\csname\??layerpreset#2\endcsname}% + \fi} \def\pack_layers_set_content#1% {\layerwidth \layerparameter\c!width % global (local later) @@ -477,7 +475,7 @@ %D \macros %D {doifelselayerdata} -\def\doifelselayerdata#1% +\permanent\def\doifelselayerdata#1% {\ifcsname\??layerbox#1\endcsname %\ifvoid\csname\??layerbox#1\endcsname \ifvoid\lastnamedcs @@ -500,7 +498,7 @@ % todo: setups before flush, handy hook -\unexpanded\def\flushlayer[#1]% quite core, so optimized (todo: check for void) +\permanent\protected\def\flushlayer[#1]% quite core, so optimized (todo: check for void) {\begingroup \forgetall \edef\currentlayer{#1}% @@ -529,21 +527,7 @@ \fi \endgroup} -% \def\pack_layers_flush_single -% {\startoverlay -% {\ifcsname\??layerbox \currentlayer \endcsname\pack_layers_flush_indeed\plusone \currentlayer \fi}% -% {\ifcsname\??layerbox \currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{\currentlayer:\the\realpageno}\fi}% -% \stopoverlay} -% -% \def\pack_layers_flush_double#1% -% {\startoverlay -% {\ifcsname\??layerbox \currentlayer \endcsname\pack_layers_flush_indeed\plusone \currentlayer \fi}% -% {\ifcsname\??layerbox \currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount {\currentlayer:\the\realpageno}\fi}% -% {\ifcsname\??layerbox#1\currentlayer \endcsname\pack_layers_flush_indeed\plusone {#1\currentlayer }\fi}% -% {\ifcsname\??layerbox#1\currentlayer:\the\realpageno\endcsname\pack_layers_flush_indeed\zerocount{#1\currentlayer:\the\realpageno}\fi}% -% \stopoverlay} - -% optimized: +% optimized \def\pack_layers_flush_single {\ifcsname\??layerbox\currentlayer\endcsname @@ -606,7 +590,6 @@ \let\pack_layers_top_fill \relax \let\pack_layers_bottom_fill\vss -%def\pack_layers_flush_indeed#1#2% \def\pack_layers_flush_indeed#1#2#3% {\begingroup % already grouped \offinterlineskip @@ -705,9 +688,9 @@ %D This is a handy shortcut, which saves a couple of braces when we use it as %D parameter. This name also suits better to other layering commands. -\unexpanded\def\composedlayer#1{\flushlayer[#1]} +\permanent\protected\def\composedlayer#1{\flushlayer[#1]} -\unexpanded\def\tightlayer[#1]% +\permanent\protected\def\tightlayer[#1]% {\hpack {\def\currentlayer{#1}% todo: left/right \setbox\nextbox\emptybox @@ -747,21 +730,15 @@ %D {\useMPgraphic{oeps}} %D \stoptyping -\unexpanded\def\setMPlayer - {\dotripleempty\pack_layers_set_MP} - \def\MPlayerwidth {\hsize} \def\MPlayerheight{\vsize} -\def\pack_layers_set_MP[#1][#2][#3]% +\permanent\tolerant\protected\def\setMPlayer[#1]#*[#2]#*[#3]% {\edef\MPlayerwidth {\MPw{#2}}% \edef\MPlayerheight{\MPh{#2}}% \setlayer[#1][\c!x=\MPx{#2},\c!y=\MPy{#2},\c!position=\v!no,#3]} -\unexpanded\def\getMPlayer - {\dodoubleempty\pack_layers_get_MP} - -\def\pack_layers_get_MP[#1][#2]% +\permanent\tolerant\protected\def\getMPlayer[#1]#*[#2]% {\framed[\c!background={\v!foreground,#1},\c!frame=\v!off,\c!offset=\v!overlay,#2]} % takes argument %D Watch out, a redefinition: @@ -778,9 +755,11 @@ [\c!width=\innermakeupwidth, \c!height=\textheight] -\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr +\aliased\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr + +\overloaded\aliased\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr -\unexpanded\def\settextpagecontent#1#2#3% #2 and #3 will disappear +\permanent\overloaded\protected\def\settextpagecontent#1#2#3% #2 and #3 will disappear {\doifelselayerdata{OTRTEXT} {\setbox#1\hpack to \makeupwidth {\startoverlay diff --git a/tex/context/base/mkiv/pack-mrl.mkxl b/tex/context/base/mkiv/pack-mrl.mkxl index 7b09b2406..fd4153a6b 100644 --- a/tex/context/base/mkiv/pack-mrl.mkxl +++ b/tex/context/base/mkiv/pack-mrl.mkxl @@ -38,7 +38,7 @@ \installsimplecommandhandler \??blackrules {blackrules} \??blackrules -\unexpanded\def\blackrule +\permanent\protected\def\blackrule {\hpack\bgroup \doifelsenextoptionalcs\pack_black_rule_pickup\pack_black_rule_indeed} @@ -98,16 +98,10 @@ %D We could of course have implemented this macro using \type {\leaders}, but this %D would probably have taken more tokens. -\unexpanded\def\blackrules % probably never used +\permanent\tolerant\protected\def\blackrules[#1]% probably never used {\hpack\bgroup - \doifelsenextoptionalcs\pack_black_rules_pickup\pack_black_rules_indeed} - -\def\pack_black_rules_pickup[#1]% - {\setupcurrentblackrules[#1]% - \pack_black_rules_indeed} - -\def\pack_black_rules_indeed % no max handling here - {\scratchwidth \directblackrulesparameter\c!width + \ifarguments\or\setupcurrentblackrules[#1]\fi + \scratchwidth \directblackrulesparameter\c!width \scratchheight \directblackrulesparameter\c!height \scratchdepth \directblackrulesparameter\c!depth \scratchdistance\directblackrulesparameter\c!distance @@ -171,7 +165,7 @@ %D \showsetup{vl} %D \showsetup{hl} -\unexpanded\def\pack_rule_vl_indeed#1#2#3% +\protected\def\pack_rule_vl_indeed#1#2#3% {\dontleavehmode \begingroup \setbox\scratchbox\hbox @@ -184,10 +178,10 @@ \box\scratchbox \endgroup} -\def\pack_rule_vl[#1]% +\permanent\tolerant\protected\def\vl[#1]% {\pack_rule_vl_indeed{#1}{#1}{#1}} -\def\pack_rule_hl[#1]% +\permanent\tolerant\protected\def\hl[#1]% {\dontleavehmode \hbox {\vrule @@ -195,9 +189,6 @@ \s!height\linewidth \s!depth \zeropoint}} -\unexpanded\def\vl{\dosingleempty\pack_rule_vl} -\unexpanded\def\hl{\dosingleempty\pack_rule_hl} - \let\dovlwdhtdp\pack_rule_vl_indeed % used elsewhere %D \macros @@ -273,7 +264,7 @@ \newconstant\c_pack_thinrules_type -\unexpanded\def\thinrule +\permanent\protected\def\thinrule {\strut \bgroup \edef\p_height {\directthinrulesparameter\c!height}% @@ -362,15 +353,12 @@ \strut \carryoverpar\egroup} -\unexpanded\def\hairline +\permanent\protected\def\hairline % can be overloaded {\endgraf \thinrule \endgraf} -\unexpanded\def\thinrules - {\dosingleempty\pack_thinrules} - -\def\pack_thinrules[#1]% +\permanent\tolerant\protected\def\thinrules[#1]% {\bgroup \setupcurrentthinrules[#1]% \scratchcounter\directthinrulesparameter\c!n\relax @@ -533,7 +521,9 @@ \c!rulethickness=\linewidth, \c!distance=.5\emwidth] -\unexpanded\def\textrule +% can be done nicer with futureexpandis + +\permanent\protected\def\textrule {\dosingleempty\pack_textrule} \def\pack_textrule @@ -679,14 +669,14 @@ %D The grouped commands also supports bodyfont switching: -\unexpanded\def\starttextrule#1% +\permanent\protected\def\starttextrule#1% {\bgroup \def\pack_textrule_nop_indeed{\csname\??textrulealternatives\v!middle\endcsname}% \csname\??textrulealternatives\v!top\endcsname{#1}% \bgroup \usebodyfontparameter\directtextrulesparameter} -\unexpanded\def\stoptextrule +\permanent\protected\def\stoptextrule {\par \egroup \csname\??textrulealternatives\v!bottom\endcsname\empty @@ -713,7 +703,6 @@ %D \showsetup{fillinrules} %D \showsetup{setupfillinrules} - \installcorenamespace{fillinrules} \installdirectcommandhandler \??fillinrules {fillinrules} @@ -729,28 +718,20 @@ \c!style=, \c!color=] -\unexpanded\def\fillinrules - {\dosingleempty\pack_fillinrules} - -\def\pack_fillinrules[#1]% +\permanent\tolerant\protected\def\fillinrules[#1]#:#=#*#=% {\endgraf \begingroup \setupcurrentfillinrules[#1]% \let\pack_fillinrules_rule\thinrules - \dodoublegroupempty\pack_fillinrules_indeed} - -\def\pack_fillinrules_indeed#1#2% - {\directfillinrulesparameter\c!before + \directfillinrulesparameter\c!before \setupcurrentthinrules [\c!n=\directfillinrulesparameter\c!n, \c!interlinespace=\directfillinrulesparameter\c!interlinespace, \c!before=, \c!after=]% \scratchdistance\directfillinrulesparameter\c!distance\relax - \edef\m_fillinrules_one{#1}% - \edef\m_fillinrules_two{#2}% \noindent - \ifx\m_fillinrules_one\empty \else + \iftok{#2}\emptytoks\else \edef\p_width{\directfillinrulesparameter\c!width}% \ifx\p_width\v!fit \scratchdistance\zeropoint @@ -763,7 +744,7 @@ \bgroup \usefillinrulesstyleandcolor\c!style\c!color \strut - \m_fillinrules_one + #2% \hfill\directfillinrulesparameter\c!separator \hskip\scratchdistance \egroup @@ -771,10 +752,10 @@ \setupwhitespace[\v!big]% \ignorespaces \pack_fillinrules_rule - \ifx\m_fillinrules_two\empty \else + \iftok{#3}\emptytoks\else \kern\scratchdistance \usefillinrulesstyleandcolor\c!style\c!color - \m_fillinrules_two + #3% \strut \fi \endgraf @@ -789,18 +770,12 @@ %D %D \showsetup{fillintext} -\unexpanded\def\fillintext - {\dosingleempty\pack_fillintext} - -\def\pack_fillintext[#1]% ugly +\permanent\tolerant\protected\def\fillintext[#1]#:#=#*#=% {\endgraf \begingroup \setupcurrentfillinrules[#1]% - \dodoublegroupempty\pack_fillintext_indeed} - -\def\pack_fillintext_indeed#1#2% - {\def\pack_fillinrules_rule{\unhbox\nextbox\unskip}% - \dowithnextbox{\pack_fillinrules_indeed{#1}{\hfill#2}}% + \def\pack_fillinrules_rule{\unhbox\nextbox\unskip}% + \dowithnextbox{\pack_fillinrules_indeed{#2}{\hfill#3}}% \hbox\bgroup\let\par\egroup\ignorespaces} %D \macros @@ -842,10 +817,10 @@ \c!before=\blank, \c!after=\blank] -\unexpanded\def\pack_fillinline_before#1% +\protected\def\pack_fillinline_before#1% {} -\unexpanded\def\pack_fillinline_after#1% +\protected\def\pack_fillinline_after#1% {\begingroup \setupcurrentfillinlines[#1]% \ifhmode\unskip\hfill\fi @@ -865,10 +840,7 @@ \frozen\parfillskip\zeropoint\relax \endgroup} -\unexpanded\def\fillinline - {\dosingleempty\pack_fillinline} - -\def\pack_fillinline[#1]% +\permanent\tolerant\protected\def\fillinline[#1]% {\registerparwrapper {fillinline}% {\pack_fillinline_before{#1}}% diff --git a/tex/context/base/mkiv/pack-ori.mkxl b/tex/context/base/mkiv/pack-ori.mkxl index 2091adea4..4365db3ac 100644 --- a/tex/context/base/mkiv/pack-ori.mkxl +++ b/tex/context/base/mkiv/pack-ori.mkxl @@ -54,7 +54,7 @@ %D There will be some more helpers here. -\def\theorientation#1% +\permanent\def\theorientation#1% {\numexpr \ifcsname\??orientations#1\endcsname \lastnamedcs @@ -63,7 +63,7 @@ \fi \relax} -\def\autoorientation#1% +\permanent\def\autoorientation#1% {\numexpr \ifcsname\??orientations#1\endcsname \lastnamedcs @@ -85,7 +85,7 @@ %{\localcontrolled{\global\expandafter\chardef\csname\??orientations#1\endcsname\stringtoorientation{#1}}% % a bit slower \csname\??orientations#1\endcsname} -\unexpanded\def\doifelseorientation#1% +\permanent\protected\def\doifelseorientation#1% {\ifcsname\??orientations#1\endcsname \expandafter\firstoftwoarguments \else diff --git a/tex/context/base/mkiv/pack-rul.mkiv b/tex/context/base/mkiv/pack-rul.mkiv index 393668c60..e06949ed8 100644 --- a/tex/context/base/mkiv/pack-rul.mkiv +++ b/tex/context/base/mkiv/pack-rul.mkiv @@ -2693,7 +2693,7 @@ % \edef\p_framed_text_strut{\letframedtextparameter\c!strut}% to be used \letframedtextparameter\c!strut\v!no \inheritedframedtextframed\bgroup - \let\\=\endgraf + \let\\\endgraf \edef\p_framed_text_depthcorrection{\framedtextparameter\c!depthcorrection}% \ifx\p_framed_text_depthcorrection\v!on \pack_framed_text_start_depth_correction @@ -2814,7 +2814,7 @@ \letframedtextparameter\c!strut\v!no \inheritedframedtextframed\bgroup \blank[\v!disable]% - \let\\=\endgraf + \let\\\endgraf \useframedtextstyleandcolor\c!style\c!color \vskip-\strutdp % brrr why is this needed ... needs to be sorted out, see testcase 1 \framedtextparameter\c!inner @@ -3007,8 +3007,6 @@ %D A Goodie: -\def\v!unframed{unframed} - \defineframed [\v!unframed] [\c!frame=\v!off, diff --git a/tex/context/base/mkiv/pack-rul.mkxl b/tex/context/base/mkiv/pack-rul.mkxl index 69050d1fa..07aae0c92 100644 --- a/tex/context/base/mkiv/pack-rul.mkxl +++ b/tex/context/base/mkiv/pack-rul.mkxl @@ -37,10 +37,7 @@ \newdimen\linewidth -\unexpanded\def\setuplinewidth - {\dosingleargument\pack_framed_setup_line_width} - -\def\pack_framed_setup_line_width[#1]% +\permanent\tolerant\protected\def\setuplinewidth[#1]% {\assigndimension{#1}\linewidth{.2\points}{.4\points}{.6\points}} %D The parameter handler: @@ -61,9 +58,9 @@ \let\pack_framed_setupcurrentframed \setupcurrentframed \def\pack_framed_initialize - {\let\framedparameter \pack_framed_framedparameter - \let\framedparameterhash\pack_framed_framedparameterhash - \let\setupcurrentframed \pack_framed_setupcurrentframed + {\enforced\let\framedparameter \pack_framed_framedparameter + \enforced\let\framedparameterhash\pack_framed_framedparameterhash + \enforced\let\setupcurrentframed \pack_framed_setupcurrentframed \inframedtrue} %D A helper: @@ -72,7 +69,7 @@ %D Inheritance: -\def\installinheritedframed#1% +\permanent\protected\def\installinheritedframed#1% {\normalexpanded{\doinstallinheritedframed \expandafter\noexpand\csname current#1\endcsname \expandafter\noexpand\csname #1parameter\endcsname @@ -84,37 +81,36 @@ \expandafter\noexpand\csname inherited#1framed\endcsname \expandafter\noexpand\csname inherited#1framedbox\endcsname}} % new -\unexpanded\def\doinstallinheritedframed#1#2#3#4#5#6#7#8#9% - {\def#5##1##2{\ifx##1\relax#6{##2}\else#4{##1}{##2}\fi}% - %\def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\s!empty\fi}% root - \def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\??empty\fi}% root - \unexpanded\def#8% +\protected\def\doinstallinheritedframed#1#2#3#4#5#6#7#8#9% + {\enforced\def#5##1##2{\ifx##1\relax#6{##2}\else#4{##1}{##2}\fi}% + \enforced\def#6##1{\ifcsname\??framed:##1\endcsname\??framed:##1\else\??empty\fi}% root + \protected\def#8% {\bgroup \bgroup \inframedtrue - \let\currentframed #1% - \let\framedparameter #2% - \let\framedparameterhash#3% - \let\setupcurrentframed #7% + \enforced\let\currentframed #1% + \enforced\let\framedparameter #2% + \enforced\let\framedparameterhash#3% + \enforced\let\setupcurrentframed #7% \pack_framed_process_indeed}% - \unexpanded\def#9% + \protected\def#9% {\bgroup \inframedtrue - \let\currentframed #1% - \let\framedparameter #2% - \let\framedparameterhash#3% - \let\setupcurrentframed #7% + \enforced\let\currentframed #1% + \enforced\let\framedparameter #2% + \enforced\let\framedparameterhash#3% + \enforced\let\setupcurrentframed #7% \pack_framed_process_box_indeed}} -\unexpanded\def\installframedcommandhandler#1#2#3% +\permanent\protected\def\installframedcommandhandler#1#2#3% {\installcommandhandler{#1}{#2}{#3}% \installinheritedframed{#2}} -\unexpanded\def\installframedautocommandhandler#1#2#3% +\permanent\protected\def\installframedautocommandhandler#1#2#3% {\installautocommandhandler{#1}{#2}{#3}% \installinheritedframed{#2}} -\unexpanded\def\installsimpleframedcommandhandler#1#2#3% +\permanent\protected\def\installsimpleframedcommandhandler#1#2#3% {\installsimplecommandhandler{#1}{#2}{#3}% \installinheritedframed{#2}} @@ -192,11 +188,11 @@ \c!toffset=\zeropoint, \c!boffset=\zeropoint] -\unexpanded\def\definesimplifiedframed[#1]% no settings +\permanent\protected\def\definesimplifiedframed[#1]% no settings {\defineframed[#1][\??simplifiedframed]% - \expandafter\let\csname#1\endcsname\undefined} + \letcsname#1\endcsname\undefined} -\expandafter\let\csname\??simplifiedframed\endcsname\undefined +\letcsname\??simplifiedframed\endcsname\undefined %D We will communicate through module specific variables, current framed %D parameters and some reserved dimension registers. @@ -416,7 +412,7 @@ \let\overlaycolor \empty \let\overlaylinecolor \empty -\def\overlayradius{\framedparameter\c!frameradius} +\permanent\def\overlayradius{\framedparameter\c!frameradius} \newdimen\d_overlay_width \newdimen\d_overlay_height @@ -428,20 +424,20 @@ % expandable ... in a future version the space will go (in mp one can use Overlay*) -\def\overlaywidth {\the\d_overlay_width \space} % We preset the variables -\def\overlayheight {\the\d_overlay_height \space} % to some reasonable default -\def\overlaydepth {\the\d_overlay_depth \space} % values. -\def\overlayoffset {\the\d_overlay_offset \space} % of the frame can be (are) -\def\overlaylinewidth {\the\d_overlay_linewidth\space} % set somewhere else. -\def\overlayregion {\m_overlay_region} +\permanent\def\overlaywidth {\the\d_overlay_width \space} % We preset the variables +\permanent\def\overlayheight {\the\d_overlay_height \space} % to some reasonable default +\permanent\def\overlaydepth {\the\d_overlay_depth \space} % values. +\permanent\def\overlayoffset {\the\d_overlay_offset \space} % of the frame can be (are) +\permanent\def\overlaylinewidth {\the\d_overlay_linewidth\space} % set somewhere else. +\permanent\def\overlayregion {\m_overlay_region} % public but kind of protected -\def\usedoverlaywidth {\dimexpr\d_overlay_width \relax} -\def\usedoverlayheight {\dimexpr\d_overlay_height \relax} -\def\usedoverlaydepth {\dimexpr\d_overlay_depth \relax} -\def\usedoverlayoffset {\dimexpr\d_overlay_offset \relax} -\def\usedoverlaylinewidth{\dimexpr\d_overlay_linewidth\relax} +\permanent\def\usedoverlaywidth {\dimexpr\d_overlay_width \relax} +\permanent\def\usedoverlayheight {\dimexpr\d_overlay_height \relax} +\permanent\def\usedoverlaydepth {\dimexpr\d_overlay_depth \relax} +\permanent\def\usedoverlayoffset {\dimexpr\d_overlay_offset \relax} +\permanent\def\usedoverlaylinewidth{\dimexpr\d_overlay_linewidth\relax} %D The next register is used to initialize overlays. @@ -462,14 +458,11 @@ \vsize\d_overlay_height \to \everyoverlay -\unexpanded\def\defineoverlay - {\dodoubleargument\pack_framed_define_overlay} - -\def\pack_framed_define_overlay[#1][#2]% +\permanent\tolerant\protected\def\defineoverlay[#1]#*[#2]% wil be overloaded {\def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}% \processcommalist[#1]\pack_framed_define_overlay_indeed} -\unexpanded\def\executedefinedoverlay#1#2% we can share the definitions +\permanent\protected\def\executedefinedoverlay#1#2% we can share the definitions {\bgroup % redundant grouping \setlayoutcomponentattribute{\v!overlay:#1}% \setbox\scratchbox\hbox \layoutcomponentboxattribute{\the\everyoverlay#2}% @@ -484,7 +477,7 @@ %D \macros %D {overlayfakebox} -\unexpanded\def\overlayfakebox +\permanent\protected\def\overlayfakebox {\hpack % redundant but needs testing {\novrule \s!width \d_overlay_width @@ -493,7 +486,7 @@ %D For testing we provide: -\def\doifelseoverlay#1% only tests external overlays +\permanent\def\doifelseoverlay#1% only tests external overlays {\ifcsname\??overlay#1\endcsname \expandafter\firstoftwoarguments \else @@ -776,62 +769,49 @@ \installcorenamespace{regularframedlevel} -\unexpanded\def\installregularframed#1% +\permanent\protected\def\installregularframed#1% {\defineframed[#1]} -\unexpanded\def\presetlocalframed[#1]% +\permanent\protected\def\presetlocalframed[#1]% {\defineframed[#1]} % \presetlocalframed[\??framed] \newcount\c_pack_framed_nesting -\unexpanded\def\pack_framed_process_framed[#1]% - {\bgroup - \iffirstargument % faster - \setupcurrentframed[#1]% here ! - \fi - \pack_framed_process_indeed} - -\unexpanded\def\framed +\permanent\tolerant\protected\def\framed[#1]% {\bgroup \advance\c_pack_framed_nesting\plusone - \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed - \edef\currentframed{>\the\c_pack_framed_nesting}% - \pack_framed_initialize - \dosingleempty\pack_framed_process_framed} - -\unexpanded\def\startframed - {\dosingleempty\pack_framed_start_framed} - -\def\pack_framed_start_framed[#1]% - {\bgroup - \doifelseassignment{#1}\pack_framed_start_framed_yes\pack_framed_start_framed_nop{#1}} - -\def\pack_framed_start_framed_yes#1% - {\advance\c_pack_framed_nesting\plusone - \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed - \iffirstargument\secondargumenttrue\fi % dirty trick + \letcsname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed \edef\currentframed{>\the\c_pack_framed_nesting}% \pack_framed_initialize \bgroup - \iffirstargument - \secondargumenttrue % dirty trick - \setupcurrentframed[#1]% here ! - \fi - \pack_framed_process_indeed - \bgroup - \ignorespaces} - -\def\pack_framed_start_framed_nop#1% - {\edef\currentframed{#1}% - \dosingleempty\pack_framed_start_framed_nop_indeed} + \setupcurrentframed[#1]% here !, seldom no argument so no need to optimize + \pack_framed_process_indeed} -\def\pack_framed_start_framed_nop_indeed[#1]% - {\pack_framed_initialize - \bgroup - \iffirstargument - \setupcurrentframed[#1]% here ! +\permanent\tolerant\protected\def\startframed[#1]#*[#2]% + {\bgroup + \ifarguments + \pack_framed_initialize + \bgroup + \or + \ifhastok={#1}% + \advance\c_pack_framed_nesting\plusone + \letcsname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed + \edef\currentframed{>\the\c_pack_framed_nesting}% + \pack_framed_initialize + \bgroup + \setupcurrentframed[#1]% here ! + \else + \edef\currentframed{#1}% + \pack_framed_initialize + \bgroup + \fi + \else + \edef\currentframed{#1}% + \pack_framed_initialize + \bgroup + \setupcurrentframed[#2]% here ! \fi \pack_framed_process_indeed \bgroup @@ -839,14 +819,14 @@ % till here -\unexpanded\def\stopframed +\permanent\protected\def\stopframed {\removeunwantedspaces \egroup} -\unexpanded\def\normalframedwithsettings[#1]% +\protected\def\normalframedwithsettings[#1]% {\bgroup \advance\c_pack_framed_nesting\plusone - \expandafter\let\csname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed + \letcsname\??framed>\the\c_pack_framed_nesting:\s!parent\endcsname\??framed \bgroup \edef\currentframed{>\the\c_pack_framed_nesting}% \pack_framed_initialize @@ -880,21 +860,23 @@ \newif\ifinframed -%D The next one is faster on multiple backgrounds per page. No -%D dimensions can be set, only frames and backgrounds. +%D The next one is faster on multiple backgrounds per page. No dimensions can be +%D set, only frames and backgrounds. -\unexpanded\def\fastlocalframed[#1]#2[#3]#4% 3-4 +%% \protected\def\fastlocalframed[#1]#2[#3]#4% 3-4 + +\permanent\protected\def\fastlocalframed[#1]#*[#2]#3% {\bgroup \edef\currentframed{#1}% \pack_framed_initialize - \setbox\b_framed_normal\hbox{#4}% + \setbox\b_framed_normal\hbox{#3}% \iftrialtypesetting \else \edef\m_overlay_region{\framedparameter\c!region}% \ifempty\m_overlay_region\else \pack_framed_set_region \fi \fi - \setupcurrentframed[#3]% + \setupcurrentframed[#2]% \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}% also used in backgrounds \d_framed_frameoffset\framedparameter\c!frameoffset\relax % also used in backgrounds \edef\p_framed_frame{\framedparameter\c!frame}% @@ -928,7 +910,7 @@ %D The next macro uses a box and takes its natural width and height so these %D can better be correct. -\unexpanded\def\pack_framed_process_box_indeed#1#2% component box (assumes parameters set and grouped usage) +\protected\def\pack_framed_process_box_indeed#1#2% component box (assumes parameters set and grouped usage) {\setbox\b_framed_normal\box#2% could actually be \let\b_framed_normal#2 \edef\m_overlay_region{\framedparameter\c!region}% \ifempty\m_overlay_region\else @@ -961,7 +943,7 @@ \box\b_framed_normal \egroup} -\unexpanded\def\localbackgroundframed#1% namespace component box +\protected\def\localbackgroundframed#1% namespace component box {\bgroup \edef\currentframed{#1}% \pack_framed_initialize @@ -988,37 +970,26 @@ % todo: protect local \framednames -\unexpanded\def\localframed - {\bgroup - \dodoubleempty\pack_framed_local} - -\unexpanded\def\pack_framed_local[#1][#2]% - {\bgroup - \edef\currentframed{#1}% - \pack_framed_initialize - \ifsecondargument % faster - \setupcurrentframed[#2]% here ! - \fi - \pack_framed_process_indeed} - -\unexpanded\def\directlocalframed[#1]% no optional +\permanent\tolerant\protected\def\localframed[#1]#*[#2]% {\bgroup \bgroup \edef\currentframed{#1}% \pack_framed_initialize + \setupcurrentframed[#2]% here ! \pack_framed_process_indeed} -\unexpanded\def\localframedwithsettings[#1][#2]% no checking (so no spaces between) +\permanent\protected\def\directlocalframed[#1]% no optional {\bgroup \bgroup \edef\currentframed{#1}% \pack_framed_initialize - \setupcurrentframed[#2]% here ! \pack_framed_process_indeed} +\aliased\let\localframedwithsettings\localframed + % done -\def\c!fr!analyze{fr:analyze} % private option +\defineinterfaceconstant {fr!analyze} {fr:analyze} % private option \let\delayedbegstrut\relax \let\delayedendstrut\relax @@ -1030,7 +1001,7 @@ \let\localformat\empty \let\localstrut \empty -\unexpanded\def\pack_framed_process_indeed +\protected\def\pack_framed_process_indeed {\d_framed_frameoffset\framedparameter\c!frameoffset \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}% \d_framed_backgroundoffset @@ -1052,7 +1023,8 @@ \edef\localwidth {\framedparameter\c!width}% \edef\localheight{\framedparameter\c!height}% \edef\localformat{\framedparameter\c!align}% - \edef\localstrut {\framedparameter\c!strut}% + % + \edef\p_strut {\framedparameter\c!strut}% % these are not \edef\p_framed_autostrut {\framedparameter\c!autostrut}% \edef\p_framed_frame {\framedparameter\c!frame}% @@ -1131,48 +1103,48 @@ % i.e. disable (colsetbackgroundproblemintechniek) \advance\d_framed_width -2\d_framed_local_offset \advance\d_framed_height -2\d_framed_local_offset - \ifcsname\??framedstrutalternative\localstrut\endcsname + \ifcsname\??framedstrutalternative\p_strut\endcsname \lastnamedcs \else \framed_offset_alternative_unknown \fi % the next check could move to strutalternative \ifcase\c_framed_has_strut % none (not even noindent) - \let\localbegstrut\relax - \let\localendstrut\relax - \let\localstrut \relax + \enforced\let\localbegstrut\relax + \enforced\let\localendstrut\relax + \enforced\let\localstrut \relax \or % no / overlay - \let\localbegstrut\pseudobegstrut - \let\localendstrut\pseudoendstrut - \let\localstrut \pseudostrut + \enforced\let\localbegstrut\pseudobegstrut + \enforced\let\localendstrut\pseudoendstrut + \enforced\let\localstrut \pseudostrut \else - \let\localbegstrut\begstrut - \let\localendstrut\endstrut - \let\localstrut \strut + \enforced\let\localbegstrut\begstrut + \enforced\let\localendstrut\endstrut + \enforced\let\localstrut \strut \fi \ifx\p_framed_autostrut\v!yes - \let\delayedbegstrut\relax - \let\delayedendstrut\relax - \let\delayedstrut \relax + \enforced\let\delayedbegstrut\relax + \enforced\let\delayedendstrut\relax + \enforced\let\delayedstrut \relax \else - \let\delayedbegstrut\localbegstrut - \let\delayedendstrut\localendstrut - \let\delayedstrut \localstrut - \let\localbegstrut \relax - \let\localendstrut \relax - \let\localstrut \relax + \enforced\let\delayedbegstrut\localbegstrut + \enforced\let\delayedendstrut\localendstrut + \enforced\let\delayedstrut \localstrut + \enforced\let\localbegstrut \relax + \enforced\let\localendstrut \relax + \enforced\let\localstrut \relax \fi \ifconditional\c_framed_has_height - \let\\\pack_framed_vboxed_newline + \enforced\let\\\pack_framed_vboxed_newline \ifconditional\c_framed_has_width - \let\hairline\pack_framed_vboxed_hairline + \enforced\let\hairline\pack_framed_vboxed_hairline \ifconditional\c_framed_has_format \let\next\pack_framed_format_format_yes \else \let\next\pack_framed_format_format_nop \fi \else - \let\hairline\pack_framed_hboxed_hairline + \enforced\let\hairline\pack_framed_hboxed_hairline \ifconditional\c_framed_has_format \let\next\pack_framed_format_format_height \else @@ -1181,17 +1153,17 @@ \fi \orelse\ifconditional\c_framed_has_width \ifconditional\c_framed_has_format - \let\hairline\pack_framed_vboxed_hairline - \let\\\pack_framed_vboxed_newline + \enforced\let\\\pack_framed_vboxed_newline + \enforced\let\hairline\pack_framed_vboxed_hairline \let\next\pack_framed_format_format_width \else - \let\hairline\pack_framed_hboxed_hairline - \let\\\pack_framed_hboxed_newline + \enforced\let\\\pack_framed_hboxed_newline + \enforced\let\hairline\pack_framed_hboxed_hairline \let\next\pack_framed_format_format_hsize \fi \else - \let\hairline\pack_framed_hboxed_hairline - \let\\\pack_framed_hboxed_newline + \enforced\let\\\pack_framed_hboxed_newline + \enforced\let\hairline\pack_framed_hboxed_hairline \let\next\pack_framed_format_format_no_size \fi \pack_framed_check_extra_offsets @@ -1466,7 +1438,7 @@ \fi \fi} -\unexpanded\def\pack_framed_finish +\protected\def\pack_framed_finish {%\pack_framed_stop_orientation % hm, wrong place ! should rotate the result (after reshape) .. moved down \pack_framed_locator_before\p_framed_location \ifconditional\c_framed_has_format @@ -1845,16 +1817,7 @@ %D [height=3cm] {framed} boxes. Such boxes have to be \inframed {aligned} with the %D running text. -\unexpanded\def\inframed - {\dosingleempty\pack_framed_inline} - -% \def\pack_framed_inline[#1]% -% {\framed[\c!location=\v!low,#1]} -% -% or: - -\def\pack_framed_inline[% - {\framed[\c!location=\v!low,} +\permanent\tolerant\protected\def\inframed[#1]{\framed[\c!location=\v!low,#1]} %D When we set \type{empty} to \type{yes}, we get ourselves a frame and/or background, %D but no content, so actually we have a sort of phantom framed box. @@ -1900,7 +1863,7 @@ \newcount\c_framed_mstyle -\unexpanded\def\pack_framed_math_strut +\protected\def\pack_framed_math_strut {\Ustartmath \triggermathstyle\c_framed_mstyle \vphantom{(}% @@ -1910,18 +1873,18 @@ \installframedcommandhandler \??mathframed {mathframed} \??mathframed +\newcount\c_pack_framed_mathframed +\newtoks \t_pack_framed_mathframed + \appendtoks \setuevalue{\currentmathframed}{\pack_framed_mathframed{\currentmathframed}}% \to \everydefinemathframed -\unexpanded\def\pack_framed_mathframed#1% +\protected\def\pack_framed_mathframed#1% {\begingroup \edef\currentmathframed{#1}% \dosingleempty\pack_framed_mathframed_indeed} -\newcount\c_pack_framed_mathframed -\newtoks \t_pack_framed_mathframed - \def\pack_framed_math_pos {\global\advance\c_pack_framed_mathframed\plusone \xdef\pack_framed_mc_one{mcf:1:\number\c_pack_framed_mathframed}% @@ -1935,9 +1898,9 @@ \c_framed_mstyle\normalmathstyle \edef\m_framed_location{\mathframedparameter\c!location}% \ifx\m_framed_location\v!mathematics - \let\normalstrut\pack_framed_math_pos + \enforced\let\normalstrut\pack_framed_math_pos \orelse\ifx\m_framed_location\v!low\else - \let\normalstrut\pack_framed_math_strut + \enforced\let\normalstrut\pack_framed_math_strut \fi \inheritedmathframedframed\bgroup \Ustartmath @@ -2112,29 +2075,29 @@ \ifdefined\raggedonelinerstate \else \newconditional\raggedonelinerstate \fi -\def\doformatonelinerbox % beware: assumes explicit preceding bgroup +\permanent\protected\def\doformatonelinerbox % beware: assumes explicit preceding bgroup {\ifconditional\raggedonelinerstate \expandafter\dodoformatonelinerbox \else \expandafter\nodoformatonelinerbox \fi} -\def\dodoformatonelinerbox +\permanent\protected\def\dodoformatonelinerbox {\afterassignment\redoformatonelinerbox \setbox\nextbox\hbox} % maybe \hpack -\def\redoformatonelinerbox +\permanent\protected\def\redoformatonelinerbox {\aftergroup\dododoformatonelinerbox \ignorespaces} -\def\dododoformatonelinerbox +\permanent\protected\def\dododoformatonelinerbox {\hpack to \hsize % was \hbox {\ifcase\raggedstatus\or\hss\or\hss \fi \unhbox\nextbox \removeunwantedspaces \ifcase\raggedstatus\or \or\hss\or\hss\fi}% \egroup} -\def\nodoformatonelinerbox % grabs { +\permanent\protected\def\nodoformatonelinerbox % grabs { {\let\next=} %D The handlers: @@ -2177,13 +2140,10 @@ \pack_framed_do_setups \raggedcommand \pack_framed_do_top - \bgroup \synchronizeinlinedirection \localbegstrut - %\aftergrouped{\localendstrut\pack_framed_do_bottom\egroup}% - \aftergroup\localendstrut - \aftergroup\pack_framed_do_bottom - \aftergroup\egroup + \atendofgroup\localendstrut + \atendofgroup\pack_framed_do_bottom \doformatonelinerbox} \def\pack_framed_format_format_nop @@ -2200,12 +2160,10 @@ \pack_framed_do_setups \raggedcenter \vss - \bgroup \synchronizeinlinedirection \localbegstrut - \aftergroup\localendstrut - \aftergroup\vss - \aftergroup\egroup + \atendofgroup\localendstrut + \atendofgroup\vss \doformatonelinerbox} \def\pack_framed_format_format_height @@ -2220,12 +2178,10 @@ \pack_framed_do_setups \raggedcommand \vss - \bgroup - \aftergroup\localendstrut - \aftergroup\vss - \aftergroup\egroup \synchronizeinlinedirection \localbegstrut + \atendofgroup\localendstrut + \atendofgroup\vss \doformatonelinerbox} \def\pack_framed_format_format_width @@ -2241,12 +2197,10 @@ \pack_framed_do_setups \raggedcommand \pack_framed_do_top - \bgroup \synchronizeinlinedirection \localbegstrut - \aftergroup\localendstrut - \aftergroup\pack_framed_do_bottom - \aftergroup\egroup + \atendofgroup\localendstrut + \atendofgroup\pack_framed_do_bottom \doformatonelinerbox} \def\pack_framed_format_format_vsize @@ -2260,9 +2214,7 @@ \vsize\d_framed_height \pack_framed_do_setups \vss - \bgroup - \aftergroup\vss - \aftergroup\egroup + \atendofgroup\vss \hbox \bgroup \aftergroup\egroup @@ -2282,9 +2234,7 @@ \hss \synchronizeinlinedirection \localstrut - \bgroup - \aftergroup\hss - \aftergroup\egroup + \atendofgroup\hss \doformatonelinerbox} \def\pack_framed_format_format_no_size @@ -2465,7 +2415,7 @@ %D These macros try to adapt their behaviour as good as possible to the circumstances %D and act as natural as possible. -\unexpanded\def\pack_framed_vboxed_hairline % nasty overlay mess .. needed for autowidth +\protected\def\pack_framed_vboxed_hairline % nasty overlay mess .. needed for autowidth {\begingroup \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi \scratchwidth \dimexpr\scratchoffset+\d_framed_linewidth\relax @@ -2489,7 +2439,7 @@ \localbegstrut \endgroup} -\unexpanded\def\pack_framed_hboxed_hairline % use framed dimen +\protected\def\pack_framed_hboxed_hairline % use framed dimen {\bgroup \scratchoffset\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi \ifconditional\c_framed_has_height @@ -2513,10 +2463,10 @@ %D The argument of the frame command accepts \type{\\} as a sort of newline signal. In %D horizontal boxes it expands to a space. -\unexpanded\def\pack_framed_vboxed_newline +\protected\def\pack_framed_vboxed_newline {\endgraf\ignorespaces} -\unexpanded\def\pack_framed_hboxed_newline +\protected\def\pack_framed_hboxed_newline {\unskip\normalspace\ignorespaces} %D We can set each rule on or off. The default setting is inherited from @@ -2699,7 +2649,7 @@ \letframedtextparameter\c!right\relax \settrue\c_framed_text_location_none} -\unexpanded\def\pack_framed_text_start#1% +\protected\def\pack_framed_text_start#1% {\bgroup \edef\currentframedtext{#1}% \dodoubleempty\pack_framed_text_start_indeed} @@ -2726,7 +2676,7 @@ % \edef\p_framed_text_strut{\letframedtextparameter\c!strut}% to be used \letframedtextparameter\c!strut\v!no \inheritedframedtextframed\bgroup - \let\\=\endgraf + \enforced\let\\\endgraf \edef\p_framed_text_depthcorrection{\framedtextparameter\c!depthcorrection}% \ifx\p_framed_text_depthcorrection\v!on \pack_framed_text_start_depth_correction @@ -2753,7 +2703,7 @@ \defineplacement[\??framedtext][\s!parent=\??framedtext\currentframedtext] -\unexpanded\def\pack_framed_text_stop % no \baselinecorrection, see faq docs +\protected\def\pack_framed_text_stop % no \baselinecorrection, see faq docs {\endgraf \removelastskip \ifx\p_framed_text_depthcorrection\v!on @@ -2833,7 +2783,7 @@ %D The simple brace (or group) delimited case is typeset slightly different %D and is not aligned. -\unexpanded\def\pack_framed_text_direct#1% +\protected\def\pack_framed_text_direct#1% {\bgroup \edef\currentframedtext{#1}% \dosingleempty\pack_framed_text_start_direct} @@ -2847,7 +2797,7 @@ \letframedtextparameter\c!strut\v!no \inheritedframedtextframed\bgroup \blank[\v!disable]% - \let\\=\endgraf + \enforced\let\\\endgraf \useframedtextstyleandcolor\c!style\c!color \vskip-\strutdp % brrr why is this needed ... needs to be sorted out, see testcase 1 \framedtextparameter\c!inner @@ -2896,7 +2846,7 @@ \newcount\c_temp_framed_crap -\unexpanded\def\pack_framed_defined_process[#1]% official (not much checking, todo: parent) +\permanent\tolerant\protected\def\pack_framed_defined_process[#1]#*[#2]% official (not much checking, todo: parent) {\bgroup \ifcsname\??regularframedlevel#1\endcsname %\expandafter\let\expandafter\c_pack_framed_temp\csname\??regularframedlevel#1\endcsname @@ -2905,16 +2855,11 @@ \let\c_pack_framed_temp\c_temp_framed_crap \fi \advance\c_pack_framed_temp\plusone - \expandafter\def\csname\??framed#1>\the\c_pack_framed_temp:\s!parent\endcsname{\??framed#1}% \inheritlocalframed + \defcsname\??framed#1>\the\c_pack_framed_temp:\s!parent\endcsname{\??framed#1}% \inheritlocalframed \bgroup \edef\currentframed{#1>\the\c_pack_framed_temp}% \pack_framed_initialize - \dosingleempty\pack_framed_defined_process_indeed} - -\def\pack_framed_defined_process_indeed[#1]% - {\iffirstargument % faster - \setupcurrentframed[#1]% here ! - \fi + \setupcurrentframed[#2]% here ! \pack_framed_process_indeed} \let\placeframed\pack_framed_defined_process % new per 2012/04/23 @@ -2980,17 +2925,16 @@ %\c!width=\v!fit, \c!offset=\v!overlay] -\unexpanded\def\startframedcontent - {\dosingleempty\pack_framed_start_content} +\permanent\let\stopframedcontent\relax -\def\pack_framed_start_content[#1]% +\permanent\tolerant\protected\def\startframedcontent[#1]% {\bgroup \edef\currentframedcontent{#1}% \ifx\currentframedcontent\v!off - \let\stopframedcontent\egroup + \enforced\let\stopframedcontent\egroup \else \checkframedcontentparent - \let\stopframedcontent\pack_framed_stop_content_indeed + \enforced\let\stopframedcontent\pack_framed_stop_content_indeed \expandafter\pack_framed_start_content_indeed \fi} @@ -3011,7 +2955,7 @@ \forgetall \blank[\v!disable]} -\def\pack_framed_stop_content_indeed +\protected\def\pack_framed_stop_content_indeed {\removelastskip \egroup \vskip\scratchbottomoffset @@ -3040,8 +2984,6 @@ %D A Goodie: -\def\v!unframed{unframed} - \defineframed [\v!unframed] [\c!frame=\v!off, @@ -3058,9 +3000,9 @@ \let\themaxboxwidth\clf_themaxboxwidth -%D Fast enough for most cases: +%D Fast enough for most cases (we could do a massive \type {\ifhastok} instead): -\unexpanded\def\doifelseframed#1% +\protected\def\doifelseframed#1% {\iftok{#1\c!frame }{\v!on}\expandafter\firstoftwoarguments \orelse\iftok{#1\c!topframe }{\v!on}\expandafter\firstoftwoarguments \orelse\iftok{#1\c!bottomframe}{\v!on}\expandafter\firstoftwoarguments diff --git a/tex/context/base/mkiv/page-bck.mkxl b/tex/context/base/mkiv/page-bck.mkxl new file mode 100644 index 000000000..9f9c5ee03 --- /dev/null +++ b/tex/context/base/mkiv/page-bck.mkxl @@ -0,0 +1,715 @@ +%D \module +%D [ file=page-bck, % copied from main-001 +%D version=1997.03.31, +%D title=\CONTEXT\ Page Macros, +%D subtitle=Backgrounds, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +% Currently the text cells are fakes and no (foreground) frames which makes sense +% as order might matter e.g. is text sticks in other cells. The page, text etc +% areas do support foreground order change. + +\writestatus{loading}{ConTeXt Page Macros / Backgrounds} + +\unprotect + +% maybe use \currentframedhash here + +%D For special purposes, users can question the \type {*background} mode. This mode +%D is only available when typesetting the pagebody. +%D +%D \starttyping +%D \startmode[*background] ... +%D \stoptyping + +\newconditional\c_page_backgrounds_new +\newconditional\c_page_backgrounds_new_right +\newconditional\c_page_backgrounds_new_left +\newconditional\c_page_backgrounds_some + +\appendtoks + \ifconditional\c_page_backgrounds_some + \ifconditional\c_page_backgrounds_new + \setsystemmode\v!background + \fi + \fi +\to \everybeforepagebody + +\protected\def\initializepagebackgrounds + {\setfalse\c_page_backgrounds_new + \setfalse\c_page_backgrounds_new_right + \setfalse\c_page_backgrounds_new_left + \setfalse\c_page_backgrounds_some} + +%D We keep calculations and checks to a minimum and also try to minimize +%D the amount of tracing due to expansion. + +\let\currentotrbackground\empty + +%D This is the only spot where we have a low level dependency on the way +%D parent chains are defined but we want the speed. + +\protected\def\page_backgrounds_check_background + {\ifcsname\??framed\currentotrbackground:\c!background\endcsname + %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!background\endcsname}% + \edef\page_background_temp{\lastnamedcs}% + \ifx\page_background_temp\empty + \expandafter\expandafter\expandafter\page_backgrounds_check_frame + \else + \page_backgrounds_set_yes + \fi + \else + \expandafter\page_backgrounds_check_frame + \fi} + +\def\page_backgrounds_check_frame + {\ifcsname\??framed\currentotrbackground:\c!frame\endcsname + %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!frame\endcsname}% + \edef\page_background_temp{\lastnamedcs}% + \ifx\page_background_temp\v!on + \page_backgrounds_set_yes + \else + \expandafter\expandafter\expandafter\page_backgrounds_check_leftframe + \fi + \else + \expandafter\page_backgrounds_check_leftframe + \fi} + +\def\page_backgrounds_check_leftframe + {\ifcsname\??framed\currentotrbackground:\c!leftframe\endcsname + %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!leftframe\endcsname}% + \edef\page_background_temp{\lastnamedcs}% + \ifx\page_background_temp\v!on + \page_backgrounds_set_yes + \else + \expandafter\expandafter\expandafter\page_backgrounds_check_rightframe + \fi + \else + \expandafter\page_backgrounds_check_rightframe + \fi} + +\def\page_backgrounds_check_rightframe + {\ifcsname\??framed\currentotrbackground:\c!rightframe\endcsname + %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!rightframe\endcsname}% + \edef\page_background_temp{\lastnamedcs}% + \ifx\page_background_temp\v!on + \page_backgrounds_set_yes + \else + \expandafter\expandafter\expandafter\page_backgrounds_check_topframe + \fi + \else + \expandafter\page_backgrounds_check_topframe + \fi} + +\def\page_backgrounds_check_topframe + {\ifcsname\??framed\currentotrbackground:\c!topframe\endcsname + %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!topframe\endcsname}% + \edef\page_background_temp{\lastnamedcs}% + \ifx\page_background_temp\v!on + \page_backgrounds_set_yes + \else + \expandafter\expandafter\expandafter\page_backgrounds_check_bottomframe + \fi + \else + \expandafter\page_backgrounds_check_bottomframe + \fi} + +\def\page_backgrounds_check_bottomframe + {\ifcsname\??framed\currentotrbackground:\c!bottomframe\endcsname + %\edef\page_background_temp{\csname\??framed\currentotrbackground:\c!bottomframe\endcsname}% + \edef\page_background_temp{\lastnamedcs}% + \ifx\page_background_temp\v!on + \page_backgrounds_set_yes + \else + \page_backgrounds_set_nop + \fi + \else + \page_backgrounds_set_nop + \fi} + +%D We don't use the commandhandler code as we want these multitude of backgrounds to be +%D as fast as possible. + +\installcorenamespace{layoutbackgrounds} +\installcorenamespace{layoutbackgroundcheck} % we need another hash as \??layoutbackgrounds<...> gets defined + +\def\page_backgrounds_set_yes{\expandafter\let\csname\currentotrbackground\endcsname\relax } +\def\page_backgrounds_set_nop{\expandafter\let\csname\currentotrbackground\endcsname\undefined} + +\protected\def\page_backgrounds_check#1% + {\edef\currentotrbackground{\??layoutbackgrounds#1}% + \page_backgrounds_check_background} + +\permanent\def\doifelsesomebackground#1% + {\ifcsname\??layoutbackgrounds#1\endcsname + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doifsomebackgroundelse\doifelsesomebackground + +\permanent\def\doifsomebackground#1% + {\ifcsname\??layoutbackgrounds#1\endcsname + \expandafter\firstofoneargument + \else + \expandafter\gobbleoneargument + \fi} + +%D The background mechanism falls back on the \type {\framed} macro. This means +%D that all normal frame and overlay features can be used. + +\def\page_backgrounds_add_to_box#1% area + {\ifcsname\??layoutbackgrounds#1\endcsname + \expandafter\page_backgrounds_add_to_box_indeed + \else + \expandafter\gobblefourarguments + \fi#1} + +%D We don't need the dimensions here as this is a real framed but the question is: +%D do we indeed need a real framed or can we use a fake (i.e. no foreground, only +%D for hidden). + +\def\page_backgrounds_add_to_box_indeed#1#2#3#4% area box width height / always non zero + {\edef\p_page_backgrounds_setups{\namedframedparameter{\??layoutbackgrounds#1}\c!setups}% + \ifx\p_page_backgrounds_setups\empty \else + \doprocesslocalsetups\p_page_backgrounds_setups % should not produce funny spaces ! + \fi + % #2 has the right dimensions already + \setbox#2\hpack{\localbackgroundframed{\??layoutbackgrounds#1}#1#2}}% a real framed (including foreground) + + +%D There are quite some backgrounds. At the bottom layer, there is the {\em paper} +%D background. This one is only used for special purposes, like annotations to +%D documents. + +\def\page_backgrounds_add_to_print#1% + {\page_backgrounds_add_to_box\v!paper#1\printpaperwidth\printpaperheight} + +%D The page backgrounds can be put behind the {\em left page}, the {\em right page} +%D or {\em each page}. As with the paper background, these are calculated on each +%D page. + +\def\page_backgrounds_add_to_paper#1% + {\doifbothsidesoverruled + {\page_backgrounds_add_to_box\v!rightpage#1\paperwidth\paperheight}% + {\page_backgrounds_add_to_box\v!rightpage#1\paperwidth\paperheight}% + {\page_backgrounds_add_to_box\v!leftpage #1\paperwidth\paperheight}% + \page_backgrounds_add_to_box\v!page#1\paperwidth\paperheight} + +%D Then there are the 25 areas that make up the layout: {\em top, header, text, +%D footer, bottom} times {\em left edge, left margin, text, right margin, right +%D edge}. These are only recalculated when they change or when the \type {status} +%D is set to \type {repeat}. + +\newbox\leftbackground % todo: rename +\newbox\rightbackground % todo: rename + +%D Finaly there is an aditional {\em text} background, again useful for special +%D purposes only. This one is calculated each time. The hidden backgrounds are not +%D meant for users! + +\newconditional\c_page_backgrounds_hidden_enabled + +\def\page_backgrounds_add_to_text#1% + {\ifconditional\c_page_backgrounds_hidden_enabled + \page_backgrounds_add_to_box\v!hidden#1\makeupwidth\textheight % mine ! + \fi + \page_backgrounds_add_to_box\v!text#1\makeupwidth\textheight} + +%D The next couple of macros implement the area backgrounds. As said, these are +%D cached in dedicated boxes. The offsets and depth of the page are used for +%D alignment purposes. + +%newdimen\pageoffset % bleed +%newdimen\pagedepth % built-in + +%D We need a bit more clever mechanism in order to handle layers well. This means +%D that we cannot calculate both background at the same time since something may +%D have changed halfway a page. + +%D Margin swapping has been simplified: see mkii code in case of regression. +%D Calculation is delayed till the page anyway so the state is known. + +\def\page_backgrounds_recalculate + {\global\settrue\c_page_backgrounds_new} + +\def\page_backgrounds_set_boxes + {\ifconditional\c_page_backgrounds_new + \page_backgrounds_set_boxes_r + \fi + \doifbothsides + \page_backgrounds_set_boxes_a + \page_backgrounds_set_boxes_b + \page_backgrounds_set_boxes_c + \ifx\p_page_backgrounds_state\v!repeat\else + \global\setfalse\c_page_backgrounds_new + \fi} + +\def\page_backgrounds_set_boxes_r + {\global\settrue\c_page_backgrounds_new_right + \global\settrue\c_page_backgrounds_new_left + \global\setbox\leftbackground\emptybox + \global\setbox\rightbackground\emptybox} + +\def\page_backgrounds_set_boxes_a + {\ifconditional\c_page_backgrounds_new_left + % \showmessage\m!layouts8\empty + \page_backgrounds_set_box\leftbackground % \conditionalfalse + \global\setfalse\c_page_backgrounds_new_left + \global\setfalse\c_page_backgrounds_new_right + \fi} + +\def\page_backgrounds_set_boxes_b + {\ifconditional\c_page_backgrounds_new_left + % \showmessage\m!layouts8\empty + \page_backgrounds_set_box\leftbackground + \global\setfalse\c_page_backgrounds_new_left + \fi} + +\def\page_backgrounds_set_boxes_c + {\ifconditional\c_page_backgrounds_new_right + % \showmessage\m!layouts8\empty + \page_backgrounds_set_box\rightbackground + \global\setfalse\c_page_backgrounds_new_right + \fi} + +\def\page_backgrounds_add_to_main#1% todo: dimension spec + {\ifconditional\c_page_backgrounds_some + \page_backgrounds_set_boxes + \setbox#1\vpack + {\offinterlineskip + \doifelsemarginswap{\copy\leftbackground}{\copy\rightbackground}% + \box#1}% + \fi} + +\newdimen\pagebackgroundhoffset % THESE WILL BECOME OBSOLETE +\newdimen\pagebackgroundvoffset +\newdimen\pagebackgroundoffset % used elsewhere +\newdimen\pagebackgrounddepth +\newdimen\pagebackgroundcompensation + +\def\page_backgrounds_set_offsets % used in menus (we can use ifcsname's here) + {\ifconditional\c_page_backgrounds_some \ifconditional\c_page_backgrounds_new + \page_backgrounds_set_offsets_indeed % indirect, less tracing + \fi \fi} + +\def\page_backgrounds_set_offsets_indeed + {\ifcsname\??layoutbackgrounds\v!text\v!text\endcsname + \page_backgrounds_set_offsets_yes + \orelse\ifcsname\??layoutbackgrounds\v!text\endcsname + \page_backgrounds_set_offsets_yes + \else + \page_backgrounds_set_offsets_nop + \fi} + +\def\page_backgrounds_set_offsets_nop + {\global\pagebackgroundhoffset \zeropoint + \global\pagebackgroundvoffset \zeropoint + \global\pagebackgrounddepth \zeropoint + \global\pagebackgroundcompensation\zeropoint} + +\def\page_backgrounds_set_offsets_yes + {\global\pagebackgroundoffset \d_page_backgrounds_depth + \global\pagebackgroundcompensation\d_page_backgrounds_offset\relax + \ifzeropt\pagebackgroundcompensation + \page_backgrounds_set_offsets_nop + \else + \ifcsname\??layoutbackgrounds\v!top\v!text\endcsname + \global\pagebackgroundhoffset\zeropoint + \orelse\ifcsname\??layoutbackgrounds\v!bottom\v!text\endcsname + \global\pagebackgroundhoffset\zeropoint + \else + \global\pagebackgroundhoffset\pagebackgroundcompensation + \fi + \ifcsname\??layoutbackgrounds\v!text\v!rightedge\endcsname + \global\pagebackgroundvoffset\zeropoint + \global\pagebackgrounddepth \zeropoint + \orelse\ifcsname\??layoutbackgrounds\v!text\v!leftedge\endcsname + \global\pagebackgroundvoffset\zeropoint + \global\pagebackgrounddepth \zeropoint + \else + \global\pagebackgroundvoffset\pagebackgroundcompensation + \global\pagebackgrounddepth \d_page_backgrounds_depth + \fi + \fi} + +\appendtoks + \page_backgrounds_set_offsets +\to \everybeforepagebody + +\newconditional\swapbackgroundmargins \settrue\swapbackgroundmargins + +%D The swapping here is pretty nasty! Maybe we should find another way some day but +%D for now we tweak. + +\def\page_backgrounds_set_box#1% #2% + {\global\setbox#1\vpack + {\dontcomplain + \swapmargins + \ifconditional\swapbackgroundmargins + \doifelsemarginswap \donothing + {\enforced\swapcsvalues\v!rightmargin\v!leftmargin + \enforced\swapcsvalues\v!rightedge \v!leftedge}% + \fi + \calculatereducedvsizes + \offinterlineskip + % \ifconditional#2\relax + % \doswapmargins % hm, this one gets nilled in \swapmargins anyway + % \fi + \ifdim\topheight>\zeropoint + \kern\dimexpr-\topheight-\topdistance\relax + \page_backgrounds_set_box_row\v!top\topheight + \kern\topdistance + \fi + \ifdim\headerheight>\zeropoint + \page_backgrounds_set_box_row\v!header\headerheight + \kern\headerdistance + \fi + \ifdim\textheight>\zeropoint + \page_backgrounds_set_box_row\v!text\textheight + \fi + \ifdim\footerheight>\zeropoint + \kern\footerdistance + \page_backgrounds_set_box_row\v!footer\footerheight + \fi + \ifdim\bottomheight>\zeropoint + \kern\bottomdistance + \page_backgrounds_set_box_row\v!bottom\bottomheight + \fi + \vfilll}% + \smashbox#1} + +\def\page_backgrounds_set_box_row#1#2% maybe helper + {\setbox\scratchbox\vpack to #2 + \bgroup\hpack\bgroup + \goleftonpage + \ifdim\leftedgewidth>\zeropoint + \ifcsname\??layoutbackgrounds#1\v!leftedge\endcsname + \page_backgrounds_set_box_cell#1\v!leftedge\leftedgewidth#2% + \else + \kern\leftedgewidth + \fi + \kern\leftedgedistance + \fi + \ifdim\leftmarginwidth>\zeropoint + \ifcsname\??layoutbackgrounds#1\v!leftmargin\endcsname + \page_backgrounds_set_box_cell#1\v!leftmargin\leftmarginwidth#2% + \else + \kern\leftmarginwidth + \fi + \kern\leftmargindistance + \fi + \ifcsname\??layoutbackgrounds#1\v!text\endcsname + \page_backgrounds_set_box_cell#1\v!text\makeupwidth#2% + \else + \kern\makeupwidth + \fi + \ifdim\rightmarginwidth>\zeropoint + \kern\rightmargindistance + \ifcsname\??layoutbackgrounds#1\v!rightmargin\endcsname + \page_backgrounds_set_box_cell#1\v!rightmargin\rightmarginwidth#2% + \else + \kern\rightmarginwidth + \fi + \fi + \ifdim\rightedgewidth>\zeropoint + \kern\rightedgedistance + \ifcsname\??layoutbackgrounds#1\v!rightedge\endcsname + \page_backgrounds_set_box_cell#1\v!rightedge\rightedgewidth#2% + \else + \kern\rightedgewidth + \fi + \fi + \egroup\egroup + \wd\scratchbox\zeropoint + \box\scratchbox\relax} + +% these are fake framed .. maybe it's nicer to honor foreground here as well +% but it's probably a slow downer + +\def\page_backgrounds_set_box_cell#1#2#3#4% pos pos width height + {\begingroup + \edef\p_page_backgrounds_setups{\namedframedparameter{\??layoutbackgrounds#1#2}\c!setups}% + \ifx\p_page_backgrounds_setups\empty \else + \doprocesslocalsetups\p_page_backgrounds_setups % should not produce funny spaces ! + \fi + \edef\p_page_backgrounds_command{\namedframedparameter{\??layoutbackgrounds#1#2}\c!command}% + \ifx\p_page_backgrounds_command\empty + \expandafter\page_backgrounds_set_box_cell_nop + \else + \expandafter\page_backgrounds_set_box_cell_yes + \fi#3#4% + \localbackgroundframed{\??layoutbackgrounds#1#2}{#1:#2}\scratchbox + \endgroup} + +\def\page_backgrounds_set_box_cell_nop#1#2% + {\setbox\scratchbox\emptyvbox + \wd\scratchbox#1% + \ht\scratchbox#2} + +\def\page_backgrounds_set_box_cell_yes#1#2% + {\setbox\scratchbox\vpack to #2{\vss\hpack to#1{\hss\p_page_backgrounds_command\hss}\vss}% + \dp\scratchbox\zeropoint} + +%D The background mechanism is quite demanding in terms or resources. We used to +%D delay these definitions till runtime usage, but since today's \TEX's are large, +%D we now do the work on forehand. +%D +%D \starttyping +%D \setupbackgrounds [settings] +%D \setupbackgrounds [paper,page,text,..] [settings] +%D \setupbackgrounds [top,...] [leftedge,...] [settings] +%D \stoptyping +%D +%D \showsetup{setupbackgrounds} +%D +%D Because the number of arguments runs from one to three, we need to check +%D for it. + +\newtoks\everybackgroundssetup + +% \permanent\protected\def\setupbackgrounds +% {\dotripleempty\page_backgrounds_setup} +% +% \def\page_backgrounds_setup +% {\ifthirdargument +% \expandafter\page_backgrounds_setup_double +% \orelse\ifsecondargument +% \expandafter\page_backgrounds_setup_single +% \orelse\iffirstargument +% \expandafter\page_backgrounds_setup_basics +% \fi} + +\permanent\tolerant\protected\def\setupbackgrounds[#1]#*[#2]#*[#3]% + {\ifarguments + \expandafter\gobblethreeoptionals + \or + \expandafter\page_backgrounds_setup_basics + \or + \expandafter\page_backgrounds_setup_single + \or + \expandafter\page_backgrounds_setup_double + \fi[#1][#2][#3]} + +\newdimen\d_page_backgrounds_offset +\newdimen\d_page_backgrounds_depth + +\appendtoks + \edef\p_page_backgrounds_offset{\namedframedparameter{\??layoutbackgrounds\v!page}\c!offset}% + \edef\p_page_backgrounds_depth {\namedframedparameter{\??layoutbackgrounds\v!page}\c!depth }% + \edef\p_page_backgrounds_state {\namedframedparameter{\??layoutbackgrounds }\c!state }% + \global\d_page_backgrounds_offset\ifx\p_offset\empty\zeropoint\else\p_page_backgrounds_offset\fi + \global\d_page_backgrounds_depth \ifx\p_depth \empty\zeropoint\else\p_page_backgrounds_depth \fi + \global\pagebackgroundoffset\d_page_backgrounds_offset\relax + \global\pagebackgrounddepth \d_page_backgrounds_depth \relax + \ifx\p_page_backgrounds_state\v!stop + \global\setfalse\c_page_backgrounds_new + \else + \global\settrue \c_page_backgrounds_new + \fi +\to \everybackgroundssetup + +\def\v_page_backgrounds_double_set{\v!paper,\v!page,\v!leftpage,\v!rightpage} +\def\v_page_backgrounds_single_set{\v!text,\v!hidden,\v!paper,\v!page,\v!leftpage,\v!rightpage} +\def\v_page_backgrounds_common_set{\v!leftedge,\v!leftmargin,\v!text,\v!rightmargin,\v!rightedge} + +\protected\def\page_backgrounds_setup_double[#1][#2][#3]% if needed we can speed this up + {\global\settrue\c_page_backgrounds_some + \def\page_backgrounds_setup_step##1% + {\doifelseinset{##1}\v_page_backgrounds_double_set + {\page_backgrounds_setup_and_check{##1}{#3}} + {\def\page_backgrounds_setup_step_nested####1{\page_backgrounds_setup_and_check{##1####1}{#3}}% + \processcommacommand[#2]\page_backgrounds_setup_step_nested}}% + \processcommacommand[#1]\page_backgrounds_setup_step + \the\everybackgroundssetup} + +\protected\def\page_backgrounds_setup_single[#1][#2][#3]% + {\global\settrue\c_page_backgrounds_some + \doifelsecommon{#1}\v_page_backgrounds_single_set + {\def\page_backgrounds_setup_step##1{\page_backgrounds_setup_and_check{##1}{#2}}% + \processcommacommand[#1]\page_backgrounds_setup_step + \the\everybackgroundssetup}% + {\page_backgrounds_setup_double[#1][\v_page_backgrounds_common_set][#2]}} + +\protected\def\page_backgrounds_setup_basics[#1][#2][#3]% + {\setupframed[\??layoutbackgrounds][#1]% + \the\everybackgroundssetup} + +\protected\def\page_backgrounds_setup_and_check#1#2% tag settings + {\edef\currentotrbackground{\??layoutbackgrounds#1}% + \setupframed[\currentotrbackground][#2]% + \page_backgrounds_check_background} + +%D Each areas (currently there are $1+3+25+1=30$ of them) has its own low level +%D framed object associated. + +\definesimplifiedframed[\??layoutbackgrounds\v!paper] +\definesimplifiedframed[\??layoutbackgrounds\v!page] +\definesimplifiedframed[\??layoutbackgrounds\v!leftpage] +\definesimplifiedframed[\??layoutbackgrounds\v!rightpage] + +\definesimplifiedframed[\??layoutbackgrounds\v!text] +\definesimplifiedframed[\??layoutbackgrounds\v!hidden] + +\definesimplifiedframed[\??layoutbackgrounds\v!top\v!leftedge] +\definesimplifiedframed[\??layoutbackgrounds\v!top\v!leftmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!top\v!text] +\definesimplifiedframed[\??layoutbackgrounds\v!top\v!rightmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!top\v!rightedge] + +\definesimplifiedframed[\??layoutbackgrounds\v!header\v!leftedge] +\definesimplifiedframed[\??layoutbackgrounds\v!header\v!leftmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!header\v!text] +\definesimplifiedframed[\??layoutbackgrounds\v!header\v!rightmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!header\v!rightedge] + +\definesimplifiedframed[\??layoutbackgrounds\v!text\v!leftedge] +\definesimplifiedframed[\??layoutbackgrounds\v!text\v!leftmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!text\v!text] +\definesimplifiedframed[\??layoutbackgrounds\v!text\v!rightmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!text\v!rightedge] + +\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!leftedge] +\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!leftmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!text] +\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!rightmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!footer\v!rightedge] + +\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!leftedge] +\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!leftmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!text] +\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!rightmargin] +\definesimplifiedframed[\??layoutbackgrounds\v!bottom\v!rightedge] + +\setupbackgrounds + [\v!page] + [\c!offset=\zeropoint, % hm, so we need to force overlay elsewhere + \c!depth=\zeropoint] + +%D General setup: + +\setupbackgrounds + [\c!state=\c!start] + +%D The hidden layer can be populated by extending the following comma separated +%D list. This only happens in core modules. + +% todo page-2 .. page+2 achter pagina -> bleed +% spread-2 .. spread+2 achter spread -> spread (repeat 2 times) + +\permanent\protected\def\enablehiddenbackground + {\global\settrue\c_page_backgrounds_hidden_enabled + \global\settrue\c_page_backgrounds_some + \page_backgrounds_recalculate} + +\permanent\protected\def\disablehiddenbackground + {\global\setfalse\c_page_backgrounds_hidden_enabled} + +\def\hiddenbackgroundlist + {\v!text-2,\v!text-1,\v!foreground,\v!text+1,\v!text+2} + +\defineoverlay[\v!text-2][\positionregionoverlay\textanchor{\v!text-2}] % no new anchor, we share text +\defineoverlay[\v!text-1][\positionregionoverlay\textanchor{\v!text-1}] +\defineoverlay[\v!text+1][\positionregionoverlay\textanchor{\v!text+1}] +\defineoverlay[\v!text+2][\positionregionoverlay\textanchor{\v!text+2}] + +\setupbackgrounds + [\v!hidden] + [\c!background=\hiddenbackgroundlist] + +%D Because we haven't really set up backgrounds yet, we set the main efficiency +%D switch to false. + +\setfalse\c_page_backgrounds_some + +%D Sometimes you have a document wide (page) background but need to overload it +%D locally. In such case (at least in my experience) the only values that get set +%D are the background and backgroundcolor (if set at all). A full inheritance chain +%D would complicate things because then we need to use named backgrounds which in +%D turn will make this mechanism slower. I considered independent local backgrounds +%D but that also complicates the code (not that much) but isolation means that we +%D need to set more parameters each time. The following simple approach proabbly +%D suits most usage. +%D +%D \starttyping +%D \starttext +%D \setupbackgrounds[page][background=color,backgroundcolor=red] +%D \input tufte \page +%D \setupbackgrounds[page][background=,backgroundcolor=] +%D \input tufte \page +%D \setupbackgrounds[page][background=color,backgroundcolor=red] +%D \input tufte \page +%D \pushbackground[page] +%D \setupbackgrounds[page][background=color,backgroundcolor=green] +%D \input tufte \page +%D \popbackground +%D \input tufte \page +%D \stoptext +%D \stoptyping + +\permanent\protected\def\pushbackground[#1]% + {\pushmacro\popbackground + \edef\currentotrbackground{\??layoutbackgrounds#1}% + \overloaded\permanent\protected\edef\popbackground + {\setupframed + [\currentotrbackground] + [\c!background=\namedframedparameter{\currentotrbackground}\c!background, + \c!backgroundcolor=\namedframedparameter{\currentotrbackground}\c!backgroundcolor]% + \page_backgrounds_check_background + \popmacro\popbackground}% + \setupframed + [\currentotrbackground] + [\c!background=,\c!backgroundcolor=]% + \page_backgrounds_check_background} + +\permanent\let\popbackground\relax + +\protect \endinput + +% %D The next series is used in local (for instance floating) backgrounds. +% +% \installsimplifiedframed{\??layoutbackgrounds\v!local} +% +% \getparameters +% [\??layoutbackgrounds\v!local] +% [\c!component=local, +% \c!background=\localbackgroundlist] +% +% \def\localbackgroundlist +% {\v!local-2,\v!local-1,\v!foreground,\v!local+1,\v!local+2} +% +% \defineoverlay[\v!local-2][\positionoverlay{\v!local-2}] % todo share +% \defineoverlay[\v!local-1][\positionoverlay{\v!local-1}] +% \defineoverlay[\v!local+1][\positionoverlay{\v!local+1}] +% \defineoverlay[\v!local+2][\positionoverlay{\v!local+2}] +% +% \def\page_backgrounds_add_local_to_box +% {\ifconditional\c_page_backgrounds_hidden_enabled +% \expandafter\page_backgrounds_add_local_to_box_indeed +% \else +% \expandafter\gobbleoneargument +% \fi} +% +% \def\page_backgrounds_add_local_to_box_indeed#1% +% {\setbox#1\hbox{\localbackgroundframed{\??layoutbackgrounds\v!local}\v!local#1}% +% \global\advance\localpositionnumber\plusone} % afterwards ! +% +% \let\page_backgrounds_add_local_to_box\gobbleoneargument + +% Test how previous macro behaves with depth: +% +% \startcolumnset +% \input tufte +% \placefigure{none}{\framed[lines=5]{xxx}} +% \input tufte +% \placefigure{none}{\starttabulate\NC test\nc test\NC\NR\stoptabulate} +% \input tufte +% \stopcolumnset + diff --git a/tex/context/base/mkiv/page-ini.mkxl b/tex/context/base/mkiv/page-ini.mkxl new file mode 100644 index 000000000..6a9b75d22 --- /dev/null +++ b/tex/context/base/mkiv/page-ini.mkxl @@ -0,0 +1,376 @@ +%D \module +%D [ file=page-ini, +%D version=2000.10.20, +%D title=\CONTEXT\ Page Macros, +%D subtitle=Initializations, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Page Macros / Initializations} + +\registerctxluafile{page-ini}{} + +%D The \type {\processpage} command has become obsolete. It's original +%D purpose was to flush only parts of a document but nowadays we have +%D project structure and modes. This is just one of those very early +%D features that no longer makes sense. + +%D The \type {\couplepage} command has become obsolete. It's original +%D purpose was to provide hooks for printer directives (like choosing +%D different paper trays). + +\unprotect + +%D Shipout control. + +\newcount\nofshipouts + +\appendtoks + \global\advance\nofshipouts\plusone +\to \everyaftershipout + +\newconditional\c_otr_shipout_enabled \settrue\c_otr_shipout_enabled + +\protected\def\page_otr_shipout % not used at all + {\ifconditional\c_otr_shipout_enabled + \expandafter\page_otr_shipout_yes + \else + \expandafter\page_otr_shipout_nop + \fi} + +\aliased\let\page_otr_shipout_yes\normalshipout + +\protected\def\page_otr_shipout_nop + {\writestatus\m!system{ignoring shipout of real page \the\realpageno}% + \global\advance\realpageno\minusone % else no flush of resources + \dowithnextbox{\deadcycles\zerocount}} + +% We don't support direct user \shipouts (weird: this does not work, bug?) +% +% \let\shipout\page_otr_shipout_nop + +%D Building pages. + +\newbox\pagebox + +% \ifdefined\page_postprocessors_column \else \let\page_postprocessors_column\gobbleoneargument \fi +% \ifdefined\page_postprocessors_page \else \let\page_postprocessors_page \gobbleoneargument \fi +% \ifdefined\page_postprocessors_box \else \let\page_postprocessors_box \gobbleoneargument \fi + +\newtoks\t_page_postprocessors_box +\newtoks\t_page_postprocessors_page +\newtoks\t_page_postprocessors_column + +\newconstant\b_page_postprocessor + +\def\page_apply_postprocessors_box#1% + {\b_page_postprocessor#1\relax + \the\t_page_postprocessors_box} + +\def\page_apply_postprocessors_page#1% + {\b_page_postprocessor#1\relax + \the\t_page_postprocessors_page} + +\def\page_apply_postprocessors_column#1% + {\b_page_postprocessor#1\relax + \the\t_page_postprocessors_column} + +%D Floats. + +\def\page_otr_flush_all_floats + {%\flushnotes already done + \ifconditional\c_page_floats_some_waiting + \page_otr_command_flush_all_floats + \fi} + +\def\page_otr_insert_dummy_page + {\par + \ifvmode + \page_otr_flush_all_floats + \fixedspace + \vfill + \page_otr_command_next_page + \fi} + +\def\page_otr_flush_pending_content + {\vkern\zeropoint\relax + \ifvoid\normalpagebox \else + \unvbox\normalpagebox + \penalty\outputpenalty + \fi} + +\newconstant\c_page_postponed_mode % \c_page_postponed_mode\plusone +\newbox \b_page_otr_saved + +\installoutputroutine\savepagecontent + {\global\setbox\b_page_otr_saved\box\normalpagebox} + +\permanent\protected\def\flushpagecontent + {\ifvoid\b_page_otr_saved\else\unvbox\b_page_otr_saved\fi} + +% Test case: assumes one group level for output routine, todo: +% a toks. +% +% \starttext +% +% \startbuffer[makeup] +% \startpagemakeup[pagestate=start,page=no] +% \color[red]{ +% \vfill +% \dorecurse{3}{ +% \samplefile{klein} +% \vfill +% } +% } +% \stoppagemakeup +% \stopbuffer +% +% \startcolor[green] +% \dorecurse{10}{ +% \dontleavehmode{\bf 1:#1:} \samplefile{sapolsky}\par +% } +% \stopcolor +% +% \startpostponing % [+3] +% \getbuffer[makeup] +% \stoppostponing +% +% \startcolor[blue] +% \dorecurse{25}{ +% \dontleavehmode{\bf 2:#1:} \samplefile{sapolsky}\par +% } +% \stopcolor +% +% \stoptext + +\def\page_otr_construct_and_shipout#1#2#3% + {\forgetall + \page_boxes_shipout{\page_boxes_constructed_page#1#2}% \hbox removed + \page_otr_flush_pending_content + % not really needed, replaced by \flushsavedfloats + \page_otr_check_for_pending_inserts + % but does not hurt either (we're still in the otr!) + \inpagebodytrue % needed for enabling \blank ! brrr + \pagebodymode\plusone % todo: \plustwo when spread + \page_otr_command_flush_saved_floats + \page_otr_command_set_vsize % this is needed for interacting components, like floats and multicolumns + \strc_pagenumbers_increment_counters % should hook into an every + \page_adapts_synchronize + \page_otr_check_for_pending_inserts + \page_otr_command_flush_facing_floats + \page_floats_flush_page_floats % before postponed blocks + \page_spread_flush % defined later + \ifnum#3=\plusone + % this is tricky! we need to make sure we are in the output group + \ifnum\c_page_postponed_mode=\plusone + \aftergroup\page_postponed_blocks_flush + \else + \page_postponed_blocks_flush + \fi + \else + \page_postponed_blocks_flush + \fi} + +% Can't we get rid of this hackery? It's used in some widgets +% stuff so probably not. + +\newbox\b_page_otr_special + +\def\page_otr_flush_special_content + {\ifvoid\b_page_otr_special \else + \box\b_page_otr_special + \fi} + +\def\page_otr_add_special_content + {\dowithnextboxcs\page_otr_add_special_content_indeed\hbox} + +\def\page_otr_add_special_content_indeed + {\wd\nextbox\zeropoint + \ht\nextbox\zeropoint + \dp\nextbox\zeropoint + \global\setbox\b_page_otr_special\hbox + {%\hskip-\maxdimen % not here, fails in acrobat (clips) + \box\b_page_otr_special\box\nextbox}}% was \unhbox, is now box again + +\let\flushatshipout\page_otr_add_special_content + +\maxdeadcycles=1000 + +\newtoks\afterpage \newtoks\aftereverypage +\newtoks\beforepage \newtoks\beforeeverypage + +\newif\ifarrangingpages \arrangingpagesfalse + +\newconstant\pageornamentstate % 0=on 1=one-off 2=always-off + +% \appendtoks +% \ifcase\pageornamentstate \or +% \pageornamentstate\zerocount +% \fi +% \to \everyaftershipout + +\appendtoks + \ifcase\pageornamentstate \or + \global\pageornamentstate\zerocount + \fi +\to \everyaftershipout + +% Mark synchronization + +\newconditional\c_page_marks_building_successive_pages \settrue\c_page_marks_building_successive_pages + +\def\page_marks_synchronize_page#1% box + {\strc_markings_synchronize[\v!page][#1][\ifconditional\c_page_marks_building_successive_pages\v!keep\fi]} + +\def\page_marks_synchronize_column#1#2#3#4% first last column box + {\ifnum#3=#1\relax + \strc_markings_synchronize[\number#3,\v!column:\number#3,\v!first,\v!column:\v!first][#4][]% + \orelse\ifnum#3=#2\relax + \strc_markings_synchronize[\number#3,\v!column:\number#3,\v!last, \v!column:\v!last ][#4][]% + \else + \strc_markings_synchronize[\number#3,\v!column:\number#3 ][#4][]% + \fi} + +% Page body building + +\newconditional\c_page_boxes_save_page_body +\newbox \b_page_boxes_saved_page_body + +\def\page_boxes_constructed_page_body#1#2% + {\ifconditional\c_page_boxes_save_page_body \global\setbox\b_page_boxes_saved_page_body \fi \vpack \bgroup + \boxmaxdepth\maxdimen % new + \dontcomplain + \page_marks_synchronize_page {#2}% we could consider doing this for \pagebox (needs testing) + \page_boxes_construct_content \pagebox{#1}{#2}% + \page_backgrounds_add_to_main \pagebox + \page_boxes_apply_offsets \pagebox + \page_info_add_to_box \pagebox + \ifcase\pageornamentstate + \page_backgrounds_add_to_paper \pagebox + \fi + \anch_positions_register_page \pagebox + \ifarrangingpages + \page_boxes_apply_shift_paper \pagebox % \v!paper + \else + \page_boxes_apply_clip_paper \pagebox + \page_marks_add_page \pagebox + \page_boxes_apply_replicate \pagebox + \page_boxes_apply_scale \pagebox + \page_boxes_apply_mirror_paper \pagebox + \page_boxes_apply_orientate_paper \pagebox + \page_marks_add_more \pagebox + \page_boxes_apply_center \pagebox + \page_backgrounds_add_to_print \pagebox + \page_boxes_apply_mirror_print \pagebox + \page_boxes_apply_orientate_print \pagebox + \page_boxes_apply_shift_print \pagebox % \v!page + \page_boxes_apply_offset \pagebox + \page_boxes_apply_negate_print \pagebox + \fi + \box\pagebox + \egroup \ifconditional\c_page_boxes_save_page_body \copy\b_page_boxes_saved_page_body \fi} + +\appendtoks + \restoreglobalbodyfont + \pickupattributes +\to \everybeforepagebody + +% if we really need this ... we need to bypass \permanent + +% \ifdefined\nestednewbox \else \newbox\nestednextbox \fi % hm, still needed? +% +% \prependtoks +% \let\nextbox\nestednextbox +% \to \everybeforepagebody + +\def\page_boxes_constructed_page#1#2% + {\vpack\bgroup % intercept spurious spaces + \the\everybeforepagebody + \starttextproperties + \checkmarginblocks + \the\beforeeverypage + \normalexpanded{\global\beforepage\emptytoks\the\beforepage}% + \inpagebodytrue + \pagebodymode\plusone % todo: \plustwo when spread + \page_boxes_constructed_page_body#1#2% + \normalexpanded{\global\afterpage \emptytoks\the\afterpage }% + \the\aftereverypage + \resetpagebreak + \resetlayouttextlines % will go to \aftereverypage + \stoptextproperties + \the\everyafterpagebody + \egroup} + +\permanent\def\doifelsetopofpage + {\ifdim\pagegoal=\maxdimen + \expandafter\firstoftwoarguments + \orelse\ifdim\pagegoal=\vsize + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doiftopofpageelse\doifelsetopofpage + +% %D Idea: +% +% \newinsert\thispageinsert % <- installinsertion +% +% \def\flushatthispage +% {\bgroup +% \dowithnextbox{\insert\thispageinsert{\box\nextbox}\egroup}% +% \hbox} +% +% \appendtoks +% \ifvoid\thispageinsert\else\hbox{\smashedbox\thispageinsert}\fi +% \to \everyshipout + +% not yet in i-* file + +\installcorenamespace{markedpage} + +% todo: just define at the lua end ... less hassle + +\permanent\tolerant\protected\def\markpage [#1]#*[#2]{\clf_markpage {#1}{#2}} +\permanent \def\markedpages [#1]{\clf_markedpages {#1}} % expandable +\permanent\protected \def\doifelsemarkedpage#1{\clf_doifelsemarkedpage{#1}} +\permanent\protected \def\startmarkpages [#1]{\clf_startmarkpages {#1}} +\permanent\protected \def\stopmarkpages {\clf_stopmarkpages } + +%D Experimental: + +\newconstant\c_page_force_strut_depth_trace_mode + +\installtextracker + {otr.forcestrutdepth} + {\c_page_force_strut_depth_trace_mode\plusone} + {\c_page_force_strut_depth_trace_mode\zerocount} + +\installoutputroutine\forcestrutdepth + {\clf_forcestrutdepth\normalpagebox\strutdp\c_page_force_strut_depth_trace_mode + \unvbox\normalpagebox} + +\installoutputroutine\forcestrutdepthplus % experimental + {\clf_forcestrutdepthplus\normalpagebox\strutdp\c_page_force_strut_depth_trace_mode + \unvbox\normalpagebox} + +% maybe better: +% +% \installoutputroutine\doforcestrutdepth +% {\clf_forcestrutdepth\normalpagebox\strutdp\c_page_force_strut_depth_trace_mode +% \unvbox\normalpagebox} +% +% \protected\def\forcestrutdepth +% {\par\ifvmode\ifinner\else\doforcestrutdepth\fi\fi} + +% Also experimental: + +\permanent\protected\def\doifelsependingpagecontent{\clf_doifelsependingpagecontent} +% \permanent\protected\let\doifelsependingpagecontent\clf_doifelsependingpagecontent + +\protect \endinput diff --git a/tex/context/base/mkiv/page-inj.mkvi b/tex/context/base/mkiv/page-inj.mkvi index b1a2913cf..f1b520f5e 100644 --- a/tex/context/base/mkiv/page-inj.mkvi +++ b/tex/context/base/mkiv/page-inj.mkvi @@ -149,7 +149,7 @@ \stopsetups \startsetups[\??pageinjectionrenderings:\s!setup] - \setups[\dummyparameter\c!setup]% kind of redundant but fits in + \setups[\dummyparameter\c!setups]% kind of redundant but fits in \stopsetups \startsetups[\??pageinjectionrenderings:\v!buffer] diff --git a/tex/context/base/mkiv/page-lay.mkxl b/tex/context/base/mkiv/page-lay.mkxl new file mode 100644 index 000000000..d24621e60 --- /dev/null +++ b/tex/context/base/mkiv/page-lay.mkxl @@ -0,0 +1,1625 @@ +%D \module +%D [ file=page-lay, +%D version=2000.10.20, % copied from main-001 +%D title=\CONTEXT\ Page Macros, +%D subtitle=Layout Specification, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Page Macros / Layout Specification} + +%D Before you start wondering why some of the page related modules skip upward or +%D left in order to place elements, you must realize that the reference point is the +%D top left corner of the main typesetting area. One reason for this choice is that +%D it suited some viewers that displayed page areas. Another reason is that margins, +%D edges and top and bottom areas are kind of virtual, while the header, text and +%D footer areas normally determine the text flow. + +\unprotect + +%D The dimensions related to layout areas are represented by real dimensions. + +\newdimen\paperheight \paperheight = 297mm +\newdimen\paperwidth \paperwidth = 210mm +\newdimen\paperoffset \paperoffset = \zeropoint +\newdimen\paperbleed \paperbleed = \zeropoint +\newdimen\spinewidth \spinewidth = \zeropoint + +\newdimen\printpaperheight \printpaperheight = \paperheight +\newdimen\printpaperwidth \printpaperwidth = \paperwidth + +\newdimen\makeupheight % calculated +\newdimen\makeupwidth % calculated + +\newdimen\textheight % calculated +\newdimen\textwidth % calculated + +\newdimen\topspace \topspace = 2cm +\newdimen\backspace \backspace = \topspace +\newdimen\cutspace \cutspace = \zeropoint +\newdimen\bottomspace \bottomspace = \zeropoint + +\newdimen\headerheight \headerheight = 2cm +\newdimen\footerheight \footerheight = \headerheight + +\newdimen\topoffset \topoffset = \zeropoint +\newdimen\backoffset \backoffset = \topoffset + +\newdimen\leftmarginwidth \leftmarginwidth = 3cm +\newdimen\rightmarginwidth \rightmarginwidth = \leftmarginwidth + +\newdimen\leftedgewidth \leftedgewidth = 3cm +\newdimen\rightedgewidth \rightedgewidth = \leftedgewidth + +\newdimen\topheight \topheight = \zeropoint +\newdimen\bottomheight \bottomheight = \topheight + +\newcount\layoutlines \layoutlines = \zerocount +\newcount\layoutcolumns \layoutcolumns = \zerocount +\newdimen\layoutcolumndistance \layoutcolumndistance = \zeropoint +\newdimen\layoutcolumnwidth \layoutcolumnwidth = \zeropoint + +\newdimen\totaltextwidth + +%D The next series of dimensions are complemented by left and rights ones. + +\newdimen\margindistance +\newdimen\edgedistance +\newdimen\marginwidth +\newdimen\edgewidth + +%D Because a distance does not really makes sense when there is no area, we use a +%D zero distance in case there is no area. + +%D The horizontal distances are: + +\newdimen\leftedgedistance +\newdimen\rightedgedistance +\newdimen\leftmargindistance +\newdimen\rightmargindistance + +%D The vertical distances are: + +\newdimen\topdistance +\newdimen\headerdistance +\newdimen\textdistance +\newdimen\footerdistance +\newdimen\bottomdistance + +\newdimen\textovershoot % available in pagebuilder + +%D We need to calculate the extra distances: + +\newdimen\naturalmarginwidth +\newdimen\naturaledgewidth +\newdimen\naturalmargindistance +\newdimen\naturaledgedistance +\newdimen\naturalleftedgedistance +\newdimen\naturalrightedgedistance +\newdimen\naturalleftmargindistance +\newdimen\naturalrightmargindistance +\newdimen\naturaltopdistance +\newdimen\naturalheaderdistance +\newdimen\naturaltextdistance +\newdimen\naturalfooterdistance +\newdimen\naturalbottomdistance + +%D Now we've come to the setup and definition commands. + +\installcorenamespace{layout} +\installcorenamespace{layoutlocation} +\installcorenamespace{layoutalternative} +\installcorenamespace{layoutcolumn} +\installcorenamespace{layoutmethod} + +\installswitchcommandhandler \??layout {layout} \??layout + +\appendtoks + \doifnothing{\directlayoutparameter\c!state}{\letlayoutparameter\c!state\v!start}% +\to \everydefinelayout + +\appendtoks + \ifcase\layoutsetupmode + % can't happen + \or % \setuplayout[name][key=value] + \ifx\previouslayout\currentlayout + \letlayoutparameter\c!state\v!normal % global ? still needed ? + \let\currentlayout\currentlayout + \page_layouts_synchronize + \page_layouts_check_next + \fi + \or % \setuplayout[key=value] + % we can inherit so we always synchronize + \letlayoutparameter\c!state\v!normal % global ? still needed ? + \let\currentlayout\previouslayout + \page_layouts_synchronize + \page_layouts_check_next + \or % \setuplayout[name] + \ifx\currentlayout\v!reset + \let\currentlayout\empty + \fi + \letlayoutparameter\c!state\v!normal % global ? still needed ? + \glet\currentlayout\currentlayout % global + \page_layouts_synchronize + \page_layouts_check_next + \or % \setuplayout (reverts to main layout) + \letlayoutparameter\c!state\v!normal % global ? still needed ? + \glet\currentlayout\empty % global + \page_layouts_synchronize + \page_layouts_check_next + \fi +\to \everysetuplayout + +\permanent\def\doifelselayoutdefined#1% + {\ifcsname\namedlayouthash{#1}\c!state\endcsname % maybe a helper + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\aliased\let\doiflayoutdefinedelse\doifelselayoutdefined + +\permanent\def\layoutdistance#1#2{\ifdim\zeropoint<#1#2\else\zeropoint\fi} + +% \newconditional\reverselayout + +\def\page_layouts_set_dimensions + {\global\naturalmarginwidth \layoutparameter\c!margin + \global\naturaledgewidth \layoutparameter\c!edge + \global\naturalmargindistance \layoutparameter\c!margindistance + \global\naturaledgedistance \layoutparameter\c!edgedistance + \global\naturalleftedgedistance \layoutparameter\c!leftedgedistance + \global\naturalrightedgedistance \layoutparameter\c!rightedgedistance + \global\naturalleftmargindistance \layoutparameter\c!leftmargindistance + \global\naturalrightmargindistance\layoutparameter\c!rightmargindistance + \global\naturaltopdistance \layoutparameter\c!topdistance + \global\naturalheaderdistance \layoutparameter\c!headerdistance + \global\naturaltextdistance \layoutparameter\c!textdistance + \global\naturalfooterdistance \layoutparameter\c!footerdistance + \global\naturalbottomdistance \layoutparameter\c!bottomdistance + % + \global\marginwidth \naturalmarginwidth + \global\edgewidth \naturaledgewidth + \global\margindistance \naturalmargindistance + \global\edgedistance \naturaledgedistance + % + \global\leftedgedistance \layoutdistance\leftedgewidth \naturalleftedgedistance + \global\rightedgedistance \layoutdistance\rightedgewidth \naturalrightedgedistance + \global\leftmargindistance \layoutdistance\leftmarginwidth \naturalleftmargindistance + \global\rightmargindistance \layoutdistance\rightmarginwidth\naturalrightmargindistance + \global\topdistance \layoutdistance\topheight \naturaltopdistance + \global\headerdistance \layoutdistance\headerheight \naturalheaderdistance + \global\textdistance \naturaltextdistance + \global\footerdistance \layoutdistance\footerheight \naturalfooterdistance + \global\bottomdistance \layoutdistance\bottomheight \naturalbottomdistance} + +\def\page_layouts_set_distances % local in \setreducedvsize + {\headerdistance\layoutdistance\headerheight\naturalheaderdistance + \footerdistance\layoutdistance\footerheight\naturalfooterdistance} + +% these are wrong in the running text, assumes some swapping, needs a cleanup + +\newtoks\extralayoutcalculations + +\def\page_layouts_calculate_extras + {\the\extralayoutcalculations} + +\newtoks\everyswapmargins % watch the order ! + +\appendtoks + \enforced\swapcsvalues\leftmargindistance\rightmargindistance + \enforced\swapcsvalues\leftedgedistance \rightedgedistance + \enforced\swapcsvalues\leftmarginwidth \rightmarginwidth + \enforced\swapcsvalues\leftedgewidth \rightedgewidth + % + \enforced\swapcsvalues\leftmargintotal \rightmargintotal + \enforced\swapcsvalues\leftedgetotal \rightedgetotal + \enforced\swapcsvalues\leftsidetotal \rightsidetotal + \enforced\swapcsvalues\leftcombitotal \rightcombitotal + \enforced\swapcsvalues\innermargintotal \outermargintotal + \enforced\swapcsvalues\inneredgetotal \outeredgetotal + \enforced\swapcsvalues\innercombitotal \outercombitotal + \enforced\swapcsvalues\innersidetotal \outersidetotal +\to \everyswapmargins + +%D The papersize macros have a long history and we don't want to change the commands +%D so they keep looking a bit complex. + +%D \macros +%D {definepapersize} +%D +%D Before we start calculating layout dimensions, we will first take care of paper +%D sizes. The first argument can be either an assignment (for defaults) or an +%D identifier, in which case the second argument is an assignment. +%D +%D \showsetup{definepapersize} +%D +%D Yet undocumented, let's see if it gets noticed. +%D +%D \starttyping +%D \definepapersize[main] [A4] [A4] +%D \definepapersize[extra][A4,landscape][A4,landscape] +%D +%D \starttext +%D \setuppapersize[main] +%D Page 1. \page +%D Page 2. \page +%D \setuppapersize[extra] +%D Page 2 \page +%D \setuppapersize[main] +%D Page 3. \page +%D Page 4. \page +%D \adaptpapersize[extra] +%D Page 5. \page +%D Page 6. \page +%D \stoptext +%D \stoptyping +%D +%D \macros +%D {setuppaper,setuppapersize} +%D +%D When setting up the papersize on which to typeset and print, we can also +%D determine some more characteristics. +%D +%D \showsetup{setuppapersize} +%D +%D We keep track of these features with the following +%D variables. + +\installcorenamespace{layouttarget} +\installcorenamespace{layoutpaper} +\installcorenamespace{layoutprint} +\installcorenamespace{layoutcurrent} + +\installcommandhandler \??layouttarget {layouttarget} \??layouttarget % so this is a sort of mix, not really a user command / maybe switch handler + +\newconditional\c_page_target_paper_mirror +\newconstant \c_page_target_paper_orientation +\newconstant \c_page_target_paper_reverse +\newconditional\c_page_target_paper_landscape +\newconditional\c_page_target_paper_negate + +\newconditional\c_page_target_print_mirror +\newconstant \c_page_target_print_orientation +\newconstant \c_page_target_print_reverse +\newconditional\c_page_target_print_landscape +\newconditional\c_page_target_print_negate +\newconditional\c_page_target_print_doublesided + +\let\v_page_target_left_fill \relax +\let\v_page_target_right_fill \relax +\let\v_page_target_top_fill \relax +\let\v_page_target_bottom_fill\relax + +\let\papersize \empty +\let\printpapersize\empty + +\def\v_page_target_top {\namedlayouttargetparameter\papersize\c!top } +\def\v_page_target_bottom {\namedlayouttargetparameter\papersize\c!bottom} +\def\v_page_target_left {\namedlayouttargetparameter\papersize\c!left } +\def\v_page_target_right {\namedlayouttargetparameter\papersize\c!right } +\def\v_page_target_method {\rootlayouttargetparameter \c!method} +\def\v_page_target_scale {\rootlayouttargetparameter \c!scale } +\def\v_page_target_nx {\numexpr\rootlayouttargetparameter \c!nx \relax} +\def\v_page_target_ny {\numexpr\rootlayouttargetparameter \c!ny \relax} +\def\v_page_target_dx {\dimexpr\rootlayouttargetparameter \c!dx \relax} +\def\v_page_target_dy {\dimexpr\rootlayouttargetparameter \c!dy \relax} +\def\v_page_target_width {\dimexpr\rootlayouttargetparameter \c!width \relax} +\def\v_page_target_height {\dimexpr\rootlayouttargetparameter \c!height \relax} +\def\v_page_target_topspace {\dimexpr\rootlayouttargetparameter \c!topspace \relax} +\def\v_page_target_backspace{\dimexpr\rootlayouttargetparameter \c!backspace\relax} +\def\v_page_target_offset {\dimexpr\rootlayouttargetparameter \c!offset \relax} + +\def\v_page_target_xy {\numexpr\v_page_target_nx*\v_page_target_ny\relax} + +%D Normally we will not use this command directly but for now it works out okay. In +%D the future we might use more of the related commands. + +\setuplayouttarget + [% these are rather special + \c!nx=1, + \c!ny=1, + \c!dx=\zeropoint, + \c!dy=\zeropoint, + \c!topspace=\zeropoint, + \c!backspace=\zeropoint, + \c!width=\zeropoint, + \c!height=\zeropoint, + % + \c!method=\v!normal, + \c!option=\v!max, + \c!alternative=\v!normal, + % + \c!scale=1, + \c!offset=\zeropoint, + % + \c!top=, + \c!bottom=, + \c!left=, + \c!right=, + % + \c!location=] + +% \definepapersize[name][A4][A3] +% \definepapersize[name][settings] + +\permanent\tolerant\protected\def\definepapersize[#1]#*[#2]#*[#3]% + {\edef\currentlayouttarget{#1}% + \ifx\currentlayouttarget\empty + % invalid target + \orelse\ifhastok={#2}% + \definelayouttarget[#1][#2]% + \else + \setevalue{\??layoutpaper#1}{#2}% + \ifparameter#3\or + \setevalue{\??layoutprint#1}{#3}% + \else + \setevalue{\??layoutprint#1}{#2}% + \fi + \fi} + +\appendtoks + \letvalue{\??layoutcurrent\currentlayouttarget}\relax +\to \everydefinelayouttarget + +%def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\else#1\fi} +%def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\else#1\fi} + +\def\page_paper_the_paper_size#1{\ifcsname\??layoutpaper#1\endcsname\lastnamedcs\else#1\fi} +\def\page_paper_the_print_size#1{\ifcsname\??layoutprint#1\endcsname\lastnamedcs\else#1\fi} + +% \setuppaper [page=A4,paper=A3] % the k/v variant, changes the current page mapping +% \setuppapersize[A4][a=b,c=d] % the k/v variant, changes nothing, just settings +% \setuppapersize[A4][A3] % changes the current page mapping + +\let\page_paper_reinstate\relax +\let\page_paper_restore \relax + +\permanent\tolerant\protected\def\setuppapersize[#1]#*[#2]% + {\ifarguments + \page_paper_restore + \or + \ifhastok={#1}% + \page_paper_setup_size_settings[#1]% + \orelse\ifhastok={#2}% + \page_paper_setup_size_settings_by_name[#1][#2]% + \else + \page_paper_setup_size_change_size[#1][#2]% + \fi + \fi} + +\protected\def\page_paper_setup_size_settings[#1]% sometimes used to set paper/print size + {\let\currentlayouttarget\empty + \edef\m_layouttarget_paper_saved{\page_paper_the_paper_size{\layouttargetparameter\c!page }}% + \edef\m_layouttarget_print_saved{\page_paper_the_print_size{\layouttargetparameter\c!paper}}% + \setupcurrentlayouttarget[#1]% + \edef\m_layouttarget_paper{\page_paper_the_paper_size{\layouttargetparameter\c!page }}% + \edef\m_layouttarget_print{\page_paper_the_print_size{\layouttargetparameter\c!paper}}% + \ifx\m_layouttarget_paper_saved\m_layouttarget_paper + \ifx\m_layouttarget_print_saved\m_layouttarget_print + % we didn't change the size, maybe only sx or sy or so + \else + \page_paper_setup_size_settings_recalibrate + \fi + \else + \page_paper_setup_size_settings_recalibrate + \fi} + +\def\page_paper_setup_size_settings_recalibrate + {\ifx\m_layouttarget_paper\empty + % forget about it + \else + \ifx\m_layouttarget_print\empty + \let\m_layouttarget_print\m_layouttarget_paper + \fi + \page_paper_set_current[\m_layouttarget_paper][\m_layouttarget_print]% + \fi + \letlayouttargetparameter\c!page \papersize + \letlayouttargetparameter\c!paper\printpapersize} + +\protected\def\page_paper_setup_size_settings_by_name[#1][#2]% + {\def\currentlayouttarget{\page_paper_the_paper_size{#1}}% + \setuplayouttarget[#2]} + +\protected\def\page_paper_setup_size_change_size[#1][#2]% + {\doifelsenothing{#2} + {\page_paper_set_current[#1][#1]} + {\page_paper_set_current[#1][#2]}} + +\permanent\let\setuppaper\page_paper_setup_size_settings + +\permanent\protected\def\adaptpapersize + {\glet\page_paper_reinstate\page_paper_restore + \setuppapersize} + +\appendtoks + \page_paper_reinstate + \glet\page_paper_reinstate\relax +\to \everyaftershipout + +\protected\def\page_paper_set_restore#1#2% + {\xdef\page_paper_restore{\page_paper_set_current_indeed[#1][#2]}} + +\protected\def\page_paper_set_current[#1][#2]% + {\normalexpanded{\page_paper_set_current_indeed + [\page_paper_the_paper_size{#1}]% + [\page_paper_the_print_size{#2}]}} + +\protected\def\page_paper_reset_paper + {\global\setfalse\c_page_target_paper_landscape + \global\setfalse\c_page_target_paper_mirror + \global\setfalse\c_page_target_paper_negate + \global\c_page_target_paper_orientation\uprotationangle + \global\c_page_target_paper_reverse \uprotationangle} + +\protected\def\page_paper_reset_print + {\global\setfalse\c_page_target_print_landscape + \global\setfalse\c_page_target_print_mirror + \global\setfalse\c_page_target_print_negate + \global\c_page_target_print_orientation\uprotationangle + \global\c_page_target_print_reverse \uprotationangle} + +\letvalue{\??layoutpaper\v!reset}\page_paper_reset_paper +\letvalue{\??layoutprint\v!reset}\page_paper_reset_print + +\setvalue{\??layoutpaper\v!landscape }{\global\settrue\c_page_target_paper_landscape} +\setvalue{\??layoutpaper\v!mirrored }{\global\settrue\c_page_target_paper_mirror} +\setvalue{\??layoutpaper\v!negative }{\global\settrue\c_page_target_paper_negate} +\setvalue{\??layoutpaper\v!rotated }{\global\c_page_target_paper_orientation\rightrotationangle + \global\c_page_target_paper_reverse \leftrotationangle} +\setvalue{\??layoutpaper\number\rightrotationangle}{\global\c_page_target_paper_orientation\rightrotationangle + \global\c_page_target_paper_reverse \leftrotationangle} +\setvalue{\??layoutpaper\number\downrotationangle }{\global\c_page_target_paper_orientation\downrotationangle + \global\c_page_target_paper_reverse \zerocount} +\setvalue{\??layoutpaper\number\leftrotationangle }{\global\c_page_target_paper_orientation\leftrotationangle + \global\c_page_target_paper_reverse \rightrotationangle} + +\setvalue{\??layoutprint\v!landscape }{\global\settrue\c_page_target_print_landscape} +\setvalue{\??layoutprint\v!mirrored }{\global\settrue\c_page_target_print_mirror} +\setvalue{\??layoutprint\v!negative }{\global\settrue\c_page_target_print_negate} +\setvalue{\??layoutprint\v!rotated }{\global\c_page_target_print_orientation\rightrotationangle + \global\c_page_target_print_reverse \leftrotationangle} +\setvalue{\??layoutprint\number\rightrotationangle}{\global\c_page_target_print_orientation\rightrotationangle + \global\c_page_target_print_reverse \leftrotationangle} +\setvalue{\??layoutprint\number\downrotationangle }{\global\c_page_target_print_orientation\downrotationangle + \global\c_page_target_print_reverse \zerocount} +\setvalue{\??layoutprint\number\leftrotationangle }{\global\c_page_target_print_orientation\leftrotationangle + \global\c_page_target_print_reverse \rightrotationangle} + +%def\page_paper_handle_page_option #1{\ifcsname\??layoutpaper#1\endcsname\csname\??layoutpaper#1\endcsname\fi} +%def\page_paper_handle_print_option#1{\ifcsname\??layoutprint#1\endcsname\csname\??layoutprint#1\endcsname\fi} + +\def\page_paper_handle_page_option #1{\begincsname\??layoutpaper#1\endcsname} +\def\page_paper_handle_print_option#1{\begincsname\??layoutprint#1\endcsname} + +\protected\def\page_paper_identify_target#1% + {\ifcsname\??layoutcurrent#1\endcsname + \edef\currentlayouttarget{#1}% + \fi} + +\newdimen\d_page_minimum_paper_size \d_page_minimum_paper_size\luaexpr{math.pi}\onebasepoint + +\protected\def\page_paper_set_current_indeed[#1][#2]% + {\edef\m_page_asked_paper{#1}% can be the restores + \edef\m_page_asked_print{#2}% + % + \page_paper_set_restore\m_page_asked_paper\m_page_asked_print + % + % locate page target + \let\currentlayouttarget\empty + \page_paper_reset_paper + \processcommacommand[\m_page_asked_paper]\page_paper_identify_target + \ifx\currentlayouttarget\empty + \let\currentlayouttarget\currentpage + \fi + \glet\papersize\currentlayouttarget + \page_paper_reset_paper + \processcommacommand[\m_page_asked_paper]\page_paper_handle_page_option + \global\paperwidth \layouttargetparameter\c!width \relax + \global\paperheight\layouttargetparameter\c!height\relax + \ifdim\paperwidth<\d_page_minimum_paper_size + \global\paperwidth\d_page_minimum_paper_size + \fi + \ifdim\paperheight<\d_page_minimum_paper_size + \global\paperheight\d_page_minimum_paper_size + \fi + \ifconditional\c_page_target_paper_landscape + \enforced\global\swapcsvalues\paperwidth\paperheight + \fi + \ifinpagebody % local freeze + \normalexpanded{\setlayouttargetparemeter\c!height{\the\paperheight}}% + \normalexpanded{\setlayouttargetparemeter\c!width {\the\paperwidth }}% + \fi + % + \page_paper_set_offsets + % locate paper target + \page_paper_reset_print + \processcommacommand[\m_page_asked_print]\page_paper_identify_target + \glet\printpapersize\currentlayouttarget + \page_paper_reset_print + \processcommacommand[\m_page_asked_print]\page_paper_handle_print_option + \global\printpaperwidth \layouttargetparameter\c!width \relax + \global\printpaperheight\layouttargetparameter\c!height\relax + \ifdim\printpaperwidth<\onepoint + \global\printpaperwidth\paperwidth + \fi + \ifdim\printpaperheight<\onepoint + \global\printpaperheight\paperheight + \fi + \ifconditional\c_page_target_print_landscape + \enforced\global\swapcsvalues\printpaperwidth\printpaperheight + \fi + % this check can be confusing, so we've added the possibility + % to bypass this test: \setuppapersize[option=fit] + \edef\m_page_asked_option{\rootlayouttargetparameter\c!option}% + \ifx\m_page_asked_option\v!max % \v!fit is + \begingroup + % we need to pre-swap else we get the wrong paper size + \ifnum\c_page_target_paper_orientation=\rightrotationangle + \enforced\swapcsvalues\paperwidth\paperheight + \orelse\ifnum\c_page_target_paper_orientation=\leftrotationangle + \enforced\swapcsvalues\paperwidth\paperheight + \fi + \ifnum\c_page_target_print_orientation=\rightrotationangle + \enforced\swapcsvalues\printpaperwidth\printpaperheight + \orelse\ifnum\c_page_target_print_orientation=\leftrotationangle + \enforced\swapcsvalues\printpaperwidth\printpaperheight + \fi + \ifdim\paperheight>\printpaperheight + \global\printpaperheight\paperheight + \writestatus\m!system{print height forced to paper height}% + \fi + \ifdim\paperwidth>\printpaperwidth + \global\printpaperwidth\paperwidth + \writestatus\m!system{print width forced to paper width}% + \fi + \endgroup + \fi + %\writestatus{layout target}{(\the\paperwidth,\the\paperheight) -> (\the\printpaperwidth,\the\printpaperheight)}% + \page_layouts_synchronize + % new but we assume \setuplayout + \scrn_canvas_synchronize_only} + +\ifdefined\scrn_canvas_synchronize_only \else + \let\scrn_canvas_synchronize_only\relax +\fi + +\ifdefined\page_paper_set_offsets \else + + \def\page_paper_set_offsets % will move + {\global\paperoffset\v_page_target_offset + \global\advance\paperwidth -2\paperoffset + \global\advance\paperheight-2\paperoffset} + +\fi + +\ifdefined\synchronizegridsnapping \else + \let\synchronizegridsnapping\relax +\fi + +\let\p_page_layouts_width \empty +\let\p_page_layouts_height\empty + +\def\page_layouts_synchronize + {\setups[\layoutparameter\c!preset]\relax + \global\leftmarginwidth \layoutparameter\c!leftmargin + \global\rightmarginwidth\layoutparameter\c!rightmargin + \global\leftedgewidth \layoutparameter\c!leftedge + \global\rightedgewidth \layoutparameter\c!rightedge + \global\headerheight \layoutparameter\c!header + \global\footerheight \layoutparameter\c!footer + \global\bottomheight \layoutparameter\c!bottom + \global\topheight \layoutparameter\c!top + \global\backspace \layoutparameter\c!backspace + \global\topspace \layoutparameter\c!topspace + \page_layouts_set_dimensions + \synchronizegridsnapping + \usesetupsparameter\layoutparameter % depends on gridsnapping ! + \synchronizewhitespace + \synchronizeblank + \setupinterlinespace[\v!reset]% \synchronizegloballinespecs + \global\cutspace\layoutparameter\c!cutspace\relax + \edef\p_page_layouts_width{\layoutparameter\c!width}% + \ifx\p_page_layouts_width\v!middle + \ifzeropt\cutspace + \global\cutspace\backspace + \fi + \global\makeupwidth\dimexpr\paperwidth-\backspace-\cutspace\relax + \orelse\ifx\p_page_layouts_width\v!fit + \ifzeropt\cutspace + \global\cutspace\backspace + \fi + \global\makeupwidth\dimexpr\paperwidth-\cutspace\relax + \scratchdimen\dimexpr\backspace + -\leftedgewidth -\leftedgedistance + -\leftmarginwidth-\leftmargindistance\relax + \ifdim\scratchdimen<\zeropoint + \scratchdimen\zeropoint + \fi + \global\advance\makeupwidth\dimexpr + -\rightmargindistance-\rightmarginwidth + -\rightedgedistance -\rightedgewidth + -\scratchdimen\relax + \else + \global\makeupwidth\p_page_layouts_width\relax + \ifzeropt\cutspace + \global\cutspace\dimexpr\paperwidth-\makeupwidth-\backspace\relax + % \else + % A kind of inconsistent specification, but used + % in for instance s-pre-19.tex; the cutspace is + % used only for determining some kind of right + % margin; don't use this in doublesided mode + \fi + \fi + \scratchdimen\layoutparameter\c!bottomspace\relax + %\ifzeropt\scratchdimen + % \scratchdimen\topspace + %\fi + \global\bottomspace\layoutparameter\c!bottomspace\relax + \global\layoutlines0\number\layoutparameter\c!lines\relax % may be empty + \ifcase\layoutlines + \edef\p_page_layouts_height{\layoutparameter\c!height}% + \ifx\p_page_layouts_height\v!middle + \ifzeropt\bottomspace + \global\bottomspace\topspace + \fi + \global\makeupheight\dimexpr\paperheight-\topspace-\bottomspace\relax + \orelse\ifx\p_page_layouts_height\v!fit + \ifzeropt\bottomspace + \global\bottomspace\topspace + \fi + \global\makeupheight\dimexpr\paperheight-\bottomspace\relax + \scratchdimen\dimexpr\topspace-\topheight-\topdistance\relax + \ifdim\scratchdimen<\zeropoint + \scratchdimen\zeropoint + \fi + \global\advance\makeupheight\dimexpr-\bottomdistance-\bottomheight-\scratchdimen\relax + \else + \global\makeupheight\layoutparameter\c!height\relax + \ifzeropt\bottomspace + \global\bottomspace\dimexpr\paperheight-\makeupheight-\topspace\relax + % \else + % inconsistent specification + \fi + \fi + \else + % beware, when the bodyfont changes (switched) this will change as well; implementing + % a global lineheight is tricky: should we take the bodyfont interlinespace or the one set + % independent of the bodyfont (before or after a layout spec); way too fuzzy, so we + % stick to the current method (after a night of experimenting ...2003/10/13) + \global\makeupheight\dimexpr + \layoutparameter\c!lines\lineheight-\strutheight+\topskip+ + \headerdistance+\headerheight+\footerdistance+\footerheight\relax + \fi + \backoffset\layoutparameter\c!horoffset\relax + \topoffset \layoutparameter\c!veroffset\relax + \ifdim\makeupwidth<\onepoint + \global\makeupwidth\onepoint + \fi + \ifdim\makeupheight<\onepoint + \global\makeupheight\onepoint + \fi + % handy in page builder + \global\totaltextwidth\dimexpr + \leftedgetotal + +\leftmargintotal + +\makeupwidth + +\rightmargintotal + +\rightedgetotal + \relax + % \page_layouts_check_next % here ? + \page_layouts_check_direction + \page_layouts_calculate_extras + \page_target_check_centering + \calculatehsizes + \calculatevsizes + \page_layouts_check_pseudo_columns + \page_backgrounds_recalculate} + +\def\page_layouts_check_direction + {\edef\p_direction{\layoutparameter\c!direction}% + \ifx\p_direction\v!reverse + \enforced\global\swapcsvalues\naturalleftedgedistance \naturalrightedgedistance + \enforced\global\swapcsvalues\naturalleftmargindistance\naturalrightmargindistance + \enforced\global\swapcsvalues\leftedgedistance \rightedgedistance + \enforced\global\swapcsvalues\leftmargindistance \rightmargindistance + \enforced\global\swapcsvalues\leftmarginwidth \rightmarginwidth + \enforced\global\swapcsvalues\leftedgewidth \rightedgewidth + \enforced\global\swapcsvalues\backspace \cutspace + \expandafter\setsystemmode + \else + \expandafter\resetsystemmode + \fi{reverselayout}} + +\def\page_layouts_check_pseudo_columns + {\global\layoutcolumns\layoutparameter\c!columns + \global\layoutcolumndistance\layoutparameter\c!columndistance + \global\layoutcolumnwidth\dimexpr\makeupwidth-\layoutcolumns\layoutcolumndistance+\layoutcolumndistance\relax + \ifnum\layoutcolumns>\plusone + \global\divide\layoutcolumnwidth\layoutcolumns + \dorecurse\layoutcolumns\page_layouts_check_pseudo_column + \fi} + +\def\page_layouts_check_pseudo_column + {\setxvalue{\??layoutcolumn\recurselevel}% + {\the\numexpr\recurselevel-\plusone\relax\dimexpr\layoutcolumnwidth+\layoutcolumndistance\relax}} + +\letvalue{\??layoutcolumn0}\zeropoint + +\def\layoutcolumnoffset#1% can travel around so we can't use \lastnamedcs + {\csname\??layoutcolumn\ifcsname\??layoutcolumn#1\endcsname#1\else0\fi\endcsname} + +\def\page_layouts_synchronize_at_start + {\ifdim\makeupheight=\layoutlines\lineheight \else % weird check + \page_layouts_synchronize + \fi} + +\appendtoks + \page_layouts_synchronize_at_start % still needed? +\to \everystarttext + +% document: +% +% \setuplayout[odd][state=stop] \setuplayout[even][state=stop] \setuplayout[page] +% +% \startstandardmakeup[page=blank] ... \stopstandardmakeup + +\ifdefined\lastpage \else \let\lastpage\!!plusone \fi + +\def\page_layouts_change#1% + {%\writestatus\m!layouts{changing to layout #1}% + \xdef\currentlayout{#1}% + \page_layouts_synchronize} + +\let\changetolayout\page_layouts_change % also public + +\def\v_real_page_normal {\the\realpageno} +\def\v_real_page_reverse{-\the\numexpr\lastpage-\realpageno\relax} + +\def\v_real_page_odd_or_even + {\ifodd\pagenoshift + \ifodd\realpageno\v!even\else\v!odd \fi + \else + \ifodd\realpageno\v!odd \else\v!even\fi + \fi} + +\let\v_real_page_current\v!current + +\def\v_real_page_named + {\ifnum\lastpage=\realpageno + \v!last + \orelse\ifnum\plusone=\realpageno + \v!first + \else + \__unknown__ + \fi} + +\let\v_page_layouts_pre_check\relax + +\def\page_layouts_check_default_indeed#1% + {\edef\m_page_check{#1} + \edef\m_page_state{\namedlayoutparameter\m_page_check\c!state}% + \ifx\m_page_state\v!start + \glet\v_page_layouts_pre_check\currentlayout + \glet\currentlayout\m_page_check + \page_layouts_synchronize + \orelse\ifx\m_page_state\v!repeat + \glet\v_page_layouts_pre_check\relax + \glet\currentlayout\m_page_check + \page_layouts_synchronize + \fi} + +\def\page_layouts_check_revert + {\glet\currentlayout\v_page_layouts_pre_check + \glet\v_page_layouts_pre_check\relax + \page_layouts_synchronize} + +\def\page_layouts_check_default + {\ifcsname\namedlayouthash\v_real_page_normal\c!state\endcsname + \page_layouts_check_default_indeed\v_real_page_normal + \orelse\ifcsname\namedlayouthash\v_real_page_reverse\c!state\endcsname + \page_layouts_check_default_indeed\v_real_page_reverse + \orelse\ifcsname\namedlayouthash\v_real_page_named\c!state\endcsname + \page_layouts_check_default_indeed\v_real_page_named + \orelse\ifcsname\namedlayouthash\v_real_page_current\c!state\endcsname + \page_layouts_check_default_indeed\v_real_page_current + \orelse\ifcsname\namedlayouthash\v_real_page_odd_or_even\c!state\endcsname + \page_layouts_check_default_indeed\v_real_page_odd_or_even + \orelse\ifx\v_page_layouts_pre_check\relax + % okay + \else + \page_layouts_check_revert + \fi} + +\permanent\protected\def\installlayoutmethod#1#2% + {\setgvalue{\??layoutmethod#1}{#2}} + +\installlayoutmethod\v!default{\page_layouts_check_default} +\installlayoutmethod\v!normal {\page_layouts_check_default} + +% \def\page_layouts_check_next +% {\csname\??layoutmethod\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname +% \layoutparameter\c!method +% \else +% \v!normal +% \fi\endcsname} + +\def\page_layouts_check_next + {\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname + \lastnamedcs + \else + \page_layouts_check_default + \fi} + +\let\checkcurrentlayout\page_layouts_check_next % public and used in naw, so this synonym will stay + +% inheritance +% +% \definelayout +% [test] +% [width=12cm, +% height=10cm] +% +% \definelayout +% [more] +% [test] +% [height=12cm] +% +% testcase +% +% \setuppagenumbering[alternative=doublesided] +% +% \setuplayout [width=11cm] +% \definelayout [odd] [backspace=1cm] +% \definelayout [even] [backspace=4cm] +% \definelayout [5] [backspace=5cm] +% \definelayout [6] [backspace=5cm] +% \definelayout [-2] [backspace=0cm,cutspace=0cm] +% \definelayout [last] [backspace=0cm,cutspace=0cm] +% +% \checkcurrentlayout \showframe +% +% \starttext +% \dorecurse{20} {\input knuth \endgraf \input tufte \endgraf} +% \stoptext + +% Because we want to keep the set parameters as they are we use some +% helpers to communicate between the several page building related +% mechanism. + +\appendtoks \page_layouts_check_next \to \everystarttext +\appendtoks \page_layouts_check_next \to \everyaftershipout + +\newconditional\c_page_layouts_location_is_set +\newconditional\c_page_layouts_location_is_middle + +\def\page_layouts_location_reset % we start in the left top and mirror right pages + {\setfalse\c_page_layouts_location_is_set + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_left_fill \relax + \let\v_page_target_right_fill \hss % ? \relax + \let\v_page_target_top_fill \relax + \let\v_page_target_bottom_fill\vss} % \relax} + +\setvalue{\??layoutlocation\v!right }{\settrue\c_page_layouts_location_is_set + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_left_fill \hss + \let\v_page_target_right_fill \relax} +\setvalue{\??layoutlocation\v!left }{\settrue\c_page_layouts_location_is_set + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_left_fill \relax + \let\v_page_target_right_fill \hss} +\setvalue{\??layoutlocation\v!bottom }{\settrue\c_page_layouts_location_is_set + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_top_fill \vss + \let\v_page_target_bottom_fill\relax} +\setvalue{\??layoutlocation\v!top }{\settrue\c_page_layouts_location_is_set + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_top_fill \relax + \let\v_page_target_bottom_fill\vss} +\setvalue{\??layoutlocation\v!middle }{\settrue\c_page_layouts_location_is_set + \settrue\c_page_layouts_location_is_middle + \let\v_page_target_left_fill \hss + \let\v_page_target_right_fill \hss + \let\v_page_target_top_fill \vss + \let\v_page_target_bottom_fill\vss} +\setvalue{\??layoutlocation\empty }{\setfalse\c_page_layouts_location_is_set % default also signal to scrn_ + \setfalse\c_page_layouts_location_is_middle + \let\v_page_target_right_fill \hss + \let\v_page_target_bottom_fill\hss} +\setvalue{\??layoutlocation\v!doublesided}{\settrue \c_page_target_print_doublesided} +\setvalue{\??layoutlocation\v!singlesided}{\setfalse\c_page_target_print_doublesided} + +\def\page_target_check_centering_indeed#1% + % {\ifcsname\??layoutlocation#1\endcsname\csname\??layoutlocation#1\endcsname\fi} + {\begincsname\??layoutlocation#1\endcsname} + +\protected\def\page_target_check_centering + {\setfalse\c_page_target_print_doublesided + \page_layouts_location_reset + \processcommacommand[\layoutparameter\c!location]\page_target_check_centering_indeed} + +% installers + +\permanent\protected\def\installlayoutalternative#1#2% + {\setgvalue{\??layoutalternative#1}{#2}} + +\def\page_boxes_construct_content_default#1#2#3% targetbox flusher box + {\setbox#1\vpack % was \vbox + {\offinterlineskip + \begingroup % needed ? + \uselayoutstyleandcolor\c!style\c!color + \offinterlineskip + \page_layouts_insert_elements % zero size + \endgroup + \page_insert_body#2#3}}% including footnotes + +\installlayoutalternative\v!default{\page_boxes_construct_content_default} +\installlayoutalternative\v!normal {\page_boxes_construct_content_default} + +% \def\page_boxes_construct_content % targetbox flusher box +% {\csname\??layoutalternative\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname +% \layoutparameter\c!alternative +% \else +% \v!normal +% \fi\endcsname} + +\def\page_boxes_construct_content % targetbox flusher box + {\ifcsname\??layoutalternative\layoutparameter\c!alternative\endcsname + \expandafter\lastnamedcs + \else + \expandafter\page_boxes_construct_content_default + \fi} + +%D \macros +%D {adaptlayout} + +\installcorenamespace{adaptlayout} +\installcorenamespace{pageadaptations} + +\installsetuponlycommandhandler \??adaptlayout {adaptlayout} + +\newdimen\d_page_adepts_pushed_text_height +\newdimen\d_page_adepts_pushed_footer_height +\newdimen\d_page_adepts_height +\newdimen\d_page_adapts_delta + +\permanent\protected\tolerant\def\adaptlayout[#1]#*[#2]% + {\ifparameter#2\or + \processcommalist[#1]{\page_adapts_layout_register{#2}}% + \page_adapts_check + \else + \page_adapts_layout_indeed{#1}% + \fi} + +\def\page_adapts_layout_register#1#2% + {\setgvalue{\??pageadaptations#2}{\page_adapts_layout_indeed{#1}}} + +\let\p_adapts_height\zeropoint +\let\p_adapts_lines \zerocount + +\def\page_adapts_layout_indeed#1% + {\setupcurrentadaptlayout[\c!height=\zeropoint,\c!lines=\zerocount,#1]% + \page_adepts_push + \edef\p_adapts_height{\adaptlayoutparameter\c!height}% + \edef\p_adapts_lines {\adaptlayoutparameter\c!lines}% + \ifx\p_adapts_height\v!max + \global\d_page_adepts_height\footerheight + \else + \global\d_page_adepts_height\dimexpr + \ifnum\p_adapts_lines=\zerocount + \p_adapts_height + \else + \p_adapts_lines\openlineheight + \fi + \relax + \ifdim\d_page_adepts_height>\footerheight + \global\d_page_adepts_height\footerheight + \fi + \fi + \global\advance\textheight \d_page_adepts_height + \global\advance\footerheight-\d_page_adepts_height + \showmessage\m!layouts1{\the\d_page_adepts_height,\the\realpageno}% + % this will become a better one (do we need insert correction?) + \page_otr_command_set_vsize + % + \page_backgrounds_recalculate + \glet\page_adepts_push\relax + \glet\page_adepts_pop\page_adepts_pop_indeed} + +% \def\page_adapts_check +% {\csname\??pageadaptations\the\ifcsname\??pageadaptations\the\realpageno\endcsname\realpageno\else\zerocount\fi\endcsname} +% +% \def\page_adapts_reset +% {\ifcsname\??pageadaptations\the\realpageno\endcsname +% \global\undefinevalue{\??pageadaptations\the\realpageno}% +% \fi} + +\def\page_adapts_check + {\begincsname\??pageadaptations\the\realpageno\endcsname} + +\def\page_adapts_reset + {\ifcsname\??pageadaptations\the\realpageno\endcsname + \expandafter\glet\csname\??pageadaptations\the\realpageno\endcsname\relax + \fi} + +\def\page_adepts_push_indeed + {\global\d_page_adepts_pushed_text_height \textheight + \global\d_page_adepts_pushed_footer_height\footerheight} + +\def\page_adepts_pop_indeed + {\global\textheight \d_page_adepts_pushed_text_height + \global\footerheight\d_page_adepts_pushed_footer_height + \page_layouts_synchronize + \glet\page_adepts_push\page_adepts_push_indeed + \glet\page_adepts_pop\relax} + +\appendtoks \page_adapts_check \to \everystarttext +\appendtoks \page_adapts_reset \to \everyshipout + +\let\page_adepts_pop \relax +\let\page_adepts_push\page_adepts_push_indeed + +\protected\def\page_adapts_synchronize % used elsewhere + {\page_adepts_pop + \page_adapts_check} + +\def\page_adapts_status_info % used elsewhere + {\ifx\page_adepts_pop\relax \else + \space(adept: \the\d_page_adepts_height)\space + \fi + \the\realpageno} + +%D \macros +%D {startlayout,stoplayout} + +\permanent\protected\def\startlayout[#1]% + {\page + \globalpushmacro\currentlayout + \doifelselayoutdefined{#1}{\setuplayout[#1]}\donothing} % {\setuplayout[\currentlayout]}} + +\permanent\protected\def\stoplayout + {\page + \globalpopmacro\currentlayout + \setuplayout[\currentlayout]} + +% NOG EENS NAGAAN WANNEER NU GLOBAL EN WANNEER NIET + +\ifx\doifelselayoutsomeline\undefined % eventually defined in page-txt + \let\doifelselayoutsomeline\secondofthreearguments +\fi + +\permanent\def\compensatevsizeheader {\advance\textheight-\dimexpr\headerheight+\headerdistance\relax} +\permanent\def\compensatevsizefooter {\advance\textheight-\dimexpr\footerheight+\footerdistance\relax} +\permanent\def\globalcompensatevsizeheader{\global\advance\textheight-\dimexpr\headerheight+\headerdistance\relax} +\permanent\def\globalcompensatevsizefooter{\global\advance\textheight-\dimexpr\footerheight+\footerdistance\relax} + +\permanent\def\compensatevsizeheaderzero{\headerheight\zeropoint\page_layouts_set_distances} +\permanent\def\compensatevsizefooterzero{\footerheight\zeropoint\page_layouts_set_distances} + +\def\page_layouts_set_modes + {\ifzeropt\headerheight + \resetsystemmode\v!header + \else + \setsystemmode\v!header + \fi + \ifzeropt\footerheight + \resetsystemmode\v!footer + \else + \setsystemmode\v!footer + \fi} + +\permanent\protected\def\calculatevsizes % name will change + {\textheight\makeupheight + \doifelselayoutsomeline\v!header\compensatevsizeheader\donothing + \doifelselayoutsomeline\v!footer\compensatevsizefooter\donothing + \page_layouts_set_modes + \resetglobal + \page_otr_command_set_vsize} + +\permanent\protected\def\calculateglobalvsizes % name will change + {\global\textheight\makeupheight + \doifelselayoutsomeline\v!header\globalcompensatevsizeheader\donothing + \doifelselayoutsomeline\v!footer\globalcompensatevsizefooter\donothing + \page_layouts_set_modes + \page_otr_command_set_vsize} + +\permanent\protected\def\calculatereducedvsizes % name will change + {\textheight\makeupheight + \doifelselayoutsomeline\v!header\compensatevsizeheader\compensatevsizeheaderzero + \doifelselayoutsomeline\v!footer\compensatevsizefooter\compensatevsizefooterzero} + +\newdimen\innermakeupwidth % special purpose +\newdimen\innermakeupmargin % special purpose + +\newconditional\innermakeupcompensation \settrue\innermakeupcompensation + +\permanent\def\compensatedinnermakeupmargin + {\dimexpr\ifconditional\innermakeupcompensation+\innermakeupmargin\else\zeropoint\fi\relax} + +\permanent\protected\def\freezetextwidth % name will change % \makeupwidth may be set to \textwidth + {\textwidth\makeupwidth % which is a tricky but valid value + \edef\m_currentlayout_text_width {\layoutparameter\c!textwidth }% + \edef\m_currentlayout_text_margin{\layoutparameter\c!textmargin}% + \ifx\m_currentlayout_text_width\empty \else + \textwidth\m_currentlayout_text_width % local + \fi + \global\innermakeupwidth\textwidth + \ifx\m_currentlayout_text_margin\empty + \global\innermakeupmargin\zeropoint + \else + \global\innermakeupmargin\m_currentlayout_text_margin\relax + \fi + \scratchdimen\dimexpr\innermakeupmargin+\innermakeupmargin\relax + \global\advance\innermakeupwidth-\scratchdimen + \advance\textwidth-\scratchdimen} % local + +\permanent\protected\def\calculatehsizes % name will change + {\freezetextwidth + \page_otr_command_set_hsize} + +%D When we start at an even page, we need to swap the layout differently. We cannot +%D adapt the real page number, since it is used in cross referencing. The next +%D switch is set when we start at an even page. + +% #single #left #right + +\permanent\def\doifelseoddpage + {\ifodd\pagenoshift + \expandafter\page_layouts_if_odd_else_yes + \else + \expandafter\page_layouts_if_odd_else_nop + \fi} + +\aliased\let\doifoddpageelse\doifelseoddpage + +\def\page_layouts_if_odd_else_yes + {\ifodd\realpageno + \expandafter\secondoftwoarguments + \else + \expandafter\firstoftwoarguments + \fi} + +\def\page_layouts_if_odd_else_nop + {\ifodd\realpageno + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\def\page_layouts_if_odd_else_again#1{\doifelseoddpage} + +\def\doifbothsidesoverruled + {\ifdoublesided + \expandafter\page_layouts_if_odd_else_again + \else + \expandafter\firstofthreearguments + \fi} + +\def\doifbothsides% #1 #2 #3 + {\ifdoublesided + \expandafter\page_layouts_if_both_sides + \else + \expandafter\firstofthreearguments + \fi} + +\def\page_layouts_if_both_sides + {\ifsinglesided + \expandafter\firstofthreearguments + \else + \expandafter\page_layouts_if_odd_else_again + \fi} + +\newdimen\texthoffset + +\permanent\protected\def\settexthoffset % name will change + {\texthoffset\doifbothsides\backspace\backspace{\dimexpr\paperwidth-\backspace-\makeupwidth\relax}} + +\permanent\protected\def\goleftonpage % name will change (we could cache) + {\hkern-\dimexpr\leftmargindistance+\leftmarginwidth+\leftedgedistance+\leftedgewidth\relax} + +\permanent\def\doifelsemarginswap#1#2% protected? + {\doifbothsides{#1}{#1}{#2}} + +\aliased\let\doifmarginswapelse\doifelsemarginswap + +\def\swapmargins % name will change, frozen? + {\doifelsemarginswap\relax\doswapmargins} + +\def\doswapmargins % name will change, frozen? + {\let\swapmargins \relax % to prevent local swapping + \let\doswapmargins\relax % to prevent local swapping + \the\everyswapmargins} + +\permanent\def\rightorleftpageaction + {\ifdoublesided + \expandafter\page_layouts_right_or_left_page_action + \else + \expandafter\firstoftwoarguments + \fi} + +\def\page_layouts_right_or_left_page_action + {\ifsinglesided + \expandafter\firstoftwoarguments + \else + \expandafter\doifelseoddpage + \fi} + +% swapping needs frozen + +\permanent\def\outermarginwidth {\rightorleftpageaction\rightmarginwidth \leftmarginwidth } +\permanent\def\innermarginwidth {\rightorleftpageaction\leftmarginwidth \rightmarginwidth} +\permanent\def\outermargindistance{\rightorleftpageaction\rightmargindistance\leftmargindistance } +\permanent\def\innermargindistance{\rightorleftpageaction\leftmargindistance \rightmargindistance} + +\permanent\def\outeredgewidth {\rightorleftpageaction\rightedgewidth \leftedgewidth } +\permanent\def\inneredgewidth {\rightorleftpageaction\leftedgewidth \rightedgewidth} +\permanent\def\outeredgedistance {\rightorleftpageaction\rightedgedistance\leftedgedistance } +\permanent\def\inneredgedistance {\rightorleftpageaction\leftedgedistance \rightedgedistance} + +\permanent\def\outerspacewidth {\rightorleftpageaction\cutspace \backspace} +\permanent\def\innerspacewidth {\rightorleftpageaction\backspace\cutspace } + +\permanent\def\leftmargintotal {\dimexpr\leftmarginwidth +\leftmargindistance \relax} +\permanent\def\rightmargintotal {\dimexpr\rightmarginwidth+\rightmargindistance\relax} +\permanent\def\leftedgetotal {\dimexpr\leftedgewidth +\leftedgedistance \relax} +\permanent\def\rightedgetotal {\dimexpr\rightedgewidth +\rightedgedistance \relax} + +\permanent\def\leftsidetotal {\dimexpr\leftmarginwidth +\leftedgetotal \relax} +\permanent\def\rightsidetotal {\dimexpr\rightmarginwidth+\rightedgetotal\relax} +\permanent\def\leftcombitotal {\dimexpr\leftmargintotal +\leftedgetotal \relax} +\permanent\def\rightcombitotal {\dimexpr\rightmargintotal+\rightedgetotal\relax} + +\permanent\def\innermargintotal {\dimexpr\innermarginwidth+\innermargindistance\relax} +\permanent\def\outermargintotal {\dimexpr\outermarginwidth+\outermargindistance\relax} +\permanent\def\inneredgetotal {\dimexpr\inneredgewidth +\inneredgedistance \relax} +\permanent\def\outeredgetotal {\dimexpr\outeredgewidth +\outeredgedistance \relax} + +\permanent\def\innercombitotal {\dimexpr\innermargintotal+\inneredgetotal\relax} +\permanent\def\outercombitotal {\dimexpr\outermargintotal+\outeredgetotal\relax} +\permanent\def\innersidetotal {\dimexpr\innermarginwidth+\inneredgetotal\relax} +\permanent\def\outersidetotal {\dimexpr\outermarginwidth+\outeredgetotal\relax} + +%D \macros +%D {startlocallayout} +%D +%D These macros should be used with care. They permit local layouts (as used in +%D fitting pages, see \type {page-app.tex}). This is kind of obsolete now that we +%D have \type {\definelayout}, so this hack will disappear in future versions. + +\permanent\protected\def\startlocallayout + {\globalpushmacro\page_paper_restore + \globalpushmacro\currentlayout} + +\permanent\protected\def\stoplocallayout + {\globalpopmacro\currentlayout + \globalpopmacro\page_paper_restore + \page_paper_restore + \setuplayout[\currentlayout]\relax} % explicit ! + +%D \macros +%D {showprint, showframe, showlayout, showsetups} +%D +%D We predefine a couple of tracing macros. +%D +%D \showsetup{showprint} +%D \showsetup{showframe} +%D \showsetup{showlayout} +%D \showsetup{showsetups} +%D %showsetup{showmargins} +%D %showsetup{showgrid} +%D %showsetup{showusage} + +\fetchruntimecommand \showprint \f!page_run +\fetchruntimecommand \showframe \f!page_run +\fetchruntimecommand \showlayout \f!page_run +\fetchruntimecommand \showsetups \f!page_run +\fetchruntimecommand \showmargins \f!page_run +\fetchruntimecommand \showgrid \f!page_run + +\glet\page_grids_add_to_box\gobbleoneargument +\glet\page_grids_add_to_one\gobbleoneargument +\glet\page_grids_add_to_mix\gobbleoneargument + +%D The default dimensions are quite old and will not change. The funny fractions +%D were introduced when we went from fixed dimensions to relative ones. Since +%D \CONTEXT\ is a dutch package, the dimensions are based on the metric system. The +%D asymmetrical layout is kind of handy for short quick||and||dirty stapled +%D documents. +%D +%D Although valid, it is not a real good idea to use dimensions based on the \type +%D {em} unit. First of all, since there are no fonts loaded yet, this dimension +%D makes no sense, and second, you would loose track of values, since they could +%D change while going to a new page, depending on the current font setting. + +\setuplayout + [ \c!topspace=.08417508418\paperheight, % 2.5cm + \c!top=\zeropoint, + \c!topdistance=\zeropoint, + \c!header=.06734006734\paperheight, % 2.0cm + \c!headerdistance=\zeropoint, + \c!height=.84175084175\paperheight, % 25.0cm + \c!footerdistance=\layoutparameter\c!headerdistance, + \c!footer=.06734006734\paperheight, % 2.0cm + \c!bottomdistance=\layoutparameter\c!topdistance, + \c!bottom=\zeropoint, + \c!backspace=.11904761905\paperwidth, % 2.5cm + \c!edge=\zeropoint, + \c!edgedistance=\layoutparameter\c!margindistance, + \c!margin=.12649983170\paperwidth, % snijwit-2*afstand + \c!margindistance=.02008341748\paperwidth, % 12.0pt + \c!leftedge=\layoutparameter\c!edge, + \c!leftedgedistance=\layoutparameter\c!edgedistance, + \c!leftmargin=\layoutparameter\c!margin, + \c!leftmargindistance=\layoutparameter\c!margindistance, + \c!width=.71428571429\paperwidth, % 15.0cm \dimexpr\ + \c!rightmargindistance=\layoutparameter\c!margindistance, + \c!rightmargin=\layoutparameter\c!margin, + \c!rightedgedistance=\layoutparameter\c!edgedistance, + \c!rightedge=\layoutparameter\c!edge, + \c!veroffset=\zeropoint, + \c!bottomspace=\zeropoint, + \c!horoffset=\zeropoint, + \c!cutspace=\zeropoint, + \c!textwidth=, % dangerous option -> centered / local + \c!textmargin=, % dangerous option -> both sides + \c!textdistance=\zeropoint, % shift down on grid + \c!style=, + \c!color=, + \c!marking=\v!off, + \c!location=,% \v!singlesided, but unset is signal (no other default, spoils arrange) + \c!state=\v!start, + \c!scale=1, + \c!sx=1, + \c!sy=1, + \c!nx=1, + \c!ny=1, + \c!dx=\zeropoint, + \c!dy=\zeropoint, + \c!grid=\v!no, + \c!direction=\v!normal, + \c!preset=, + \c!setups=\systemsetupsprefix\s!default, + \c!clipoffset=\zeropoint, + \c!lines=0, + \c!paper=, % for foxet + \c!page=, % for foxet + \c!columns=\plusone, + \c!columndistance=\zeropoint] + +%D First we define a whole range of (DIN) papersizes, of which the A-series makes +%D most sense. We enable checking. + +\definepapersize [A0] [\c!width=841mm,\c!height=1189mm] +\definepapersize [A1] [\c!width=594mm,\c!height=841mm] +\definepapersize [A2] [\c!width=420mm,\c!height=594mm] +\definepapersize [A3] [\c!width=297mm,\c!height=420mm] +\definepapersize [A4] [\c!width=210mm,\c!height=297mm] +\definepapersize [A5] [\c!width=148mm,\c!height=210mm] +\definepapersize [A6] [\c!width=105mm,\c!height=148mm] +\definepapersize [A7] [\c!width=74mm,\c!height=105mm] +\definepapersize [A8] [\c!width=52mm,\c!height=74mm] +\definepapersize [A9] [\c!width=37mm,\c!height=52mm] +\definepapersize [A10] [\c!width=26mm,\c!height=37mm] + +\definepapersize [A4/2][\c!width=\dimexpr297mm/2\relax,\c!height=210mm] % 148.5mm +%definepapersize [2A5] [\c!width=296mm,\c!height=210mm] % doublewide + +\definepapersize [B0] [\c!width=1000mm,\c!height=1414mm] +\definepapersize [B1] [\c!width=707mm,\c!height=1000mm] +\definepapersize [B2] [\c!width=500mm,\c!height=707mm] +\definepapersize [B3] [\c!width=353mm,\c!height=500mm] % [\c!width=354mm,\c!height=500mm] +\definepapersize [B4] [\c!width=250mm,\c!height=353mm] % [\c!width=250mm,\c!height=354mm] +\definepapersize [B5] [\c!width=176mm,\c!height=250mm] % [\c!width=177mm,\c!height=250mm] +\definepapersize [B6] [\c!width=125mm,\c!height=176mm] % [\c!width=125mm,\c!height=177mm] +\definepapersize [B7] [\c!width=88mm,\c!height=125mm] +\definepapersize [B8] [\c!width=62mm,\c!height=88mm] % [\c!width=63mm,\c!height=88mm] +\definepapersize [B9] [\c!width=44mm,\c!height=62mm] % [\c!width=44mm,\c!height=63mm] +\definepapersize [B10] [\c!width=31mm,\c!height=44mm] + +\definepapersize [C0] [\c!width=917mm,\c!height=1297mm] +\definepapersize [C1] [\c!width=648mm,\c!height=917mm] % [\c!width=649mm,\c!height=917mm] +\definepapersize [C2] [\c!width=458mm,\c!height=648mm] % [\c!width=459mm,\c!height=649mm] +\definepapersize [C3] [\c!width=324mm,\c!height=458mm] % [\c!width=324mm,\c!height=459mm] +\definepapersize [C4] [\c!width=229mm,\c!height=324mm] +\definepapersize [C5] [\c!width=162mm,\c!height=229mm] +\definepapersize [C6] [\c!width=114mm,\c!height=162mm] % [\c!width=115mm,\c!height=162mm] +\definepapersize [C7] [\c!width=81mm,\c!height=114mm] % [\c!width=81mm,\c!height=115mm] +\definepapersize [C8] [\c!width=57mm,\c!height=81mm] +\definepapersize [C9] [\c!width=40mm,\c!height=57mm] +\definepapersize [C10] [\c!width=28mm,\c!height=40mm] + +%D Per August 2004 the rounding of some (seldom used) sizes were corrected top the +%D latest DIN specifications. Peter Rolf came up with these and a few more missing +%D sizes. Watch out: spaces and slashes! + +\definepapersize [4 A0] [\c!width=1682mm,\c!height=2378mm] +\definepapersize [2 A0] [\c!width=1189mm,\c!height=1682mm] +\definepapersize [C6/C5] [\c!width=114mm,\c!height=229mm] + +%D Because there are no standardized screen sizes, we define a bunch of sizes with +%D $4:3$ ratios. The \type {S6} size is nearly as wide as a sheet of \type {A4} +%D paper. + +\definepapersize [S3] [\c!width=300pt,\c!height=225pt] +\definepapersize [S4] [\c!width=400pt,\c!height=300pt] +\definepapersize [S5] [\c!width=500pt,\c!height=375pt] +\definepapersize [S6] [\c!width=600pt,\c!height=450pt] +\definepapersize [S8] [\c!width=800pt,\c!height=600pt] +\definepapersize [SL] [\c!width=640pt,\c!height=400pt] % low +\definepapersize [SM] [\c!width=720pt,\c!height=450pt] % medium +\definepapersize [SW] [\c!width=800pt,\c!height=450pt] % wide +\definepapersize [HD] [\c!width=1920pt,\c!height=1080pt] +\definepapersize [HD+] [\c!width=1920pt,\c!height=1200pt] +\definepapersize [HD-] [\c!width=960pt,\c!height=540pt] + +%D These are handy too: + +\definepapersize [S33] [\c!width=300pt,\c!height=300pt] +\definepapersize [S44] [\c!width=400pt,\c!height=400pt] +\definepapersize [S55] [\c!width=500pt,\c!height=500pt] +\definepapersize [S66] [\c!width=600pt,\c!height=600pt] + +%D One may wonder if \TEX\ should be used for typesetting \CDROM\ covers, but it +%D does not hurt to have the paper size ready. + +\definepapersize [CD] [\c!width=120mm,\c!height=120mm] + +%D The next series is for our English speaking friends who decided to stick to non +%D metric values. Thanks to Nelson Beebe for completing the inch based list. + +\definepapersize [letter] [\c!width=8.5in,\c!height=11in] +\definepapersize [ledger] [\c!width=11in,\c!height=17in] +\definepapersize [tabloid] [\c!width=17in,\c!height=11in] + +\definepapersize [legal] [\c!width=8.5in,\c!height=14in] +\definepapersize [folio] [\c!width=8.5in,\c!height=13in] +\definepapersize [executive] [\c!width=7.25in,\c!height=10.5in] + +\definepapersize [A] [\c!width=8.5in,\c!height=11in] % 1 sheet +\definepapersize [B] [\c!width=11in,\c!height=17in] % 2 sheets +\definepapersize [C] [\c!width=17in,\c!height=22in] % 4 sheets + +%D The next set is for Tobias Burnus, who gave me the sizes. + +\definepapersize [envelope 9] [\c!width=8.88in,\c!height=3.88in] +\definepapersize [envelope 10] [\c!width=9.5in,\c!height=4.13in] +\definepapersize [envelope 11] [\c!width=10.38in,\c!height=4.5in] +\definepapersize [envelope 12] [\c!width=11.0in,\c!height=4.75in] +\definepapersize [envelope 14] [\c!width=11.5in,\c!height=5.0in] +\definepapersize [monarch] [\c!width=7.5in,\c!height=3.88in] +\definepapersize [check] [\c!width=8.58in,\c!height=3.88in] +\definepapersize [DL] [\c!width=110mm,\c!height=220mm] % [\c!width=220mm,\c!height=110mm] +\definepapersize [E4] [\c!width=280mm,\c!height=400mm] + +%D The next three sets are supplied by Taco: + +\definepapersize [RA0] [\c!width=860mm,\c!height=1220mm] +\definepapersize [RA1] [\c!width=610mm,\c!height=860mm] +\definepapersize [RA2] [\c!width=430mm,\c!height=610mm] +\definepapersize [RA3] [\c!width=305mm,\c!height=430mm] +\definepapersize [RA4] [\c!width=215mm,\c!height=305mm] + +%D ISO SRA (supplementary raw A) sizes: + +\definepapersize [SRA0] [\c!width=900mm,\c!height=1280mm] +\definepapersize [SRA1] [\c!width=640mm,\c!height=900mm] +\definepapersize [SRA2] [\c!width=450mm,\c!height=640mm] +\definepapersize [SRA3] [\c!width=320mm,\c!height=450mm] +\definepapersize [SRA4] [\c!width=225mm,\c!height=320mm] + +%D Swedish thesis formats: + +\definepapersize [G5] [\c!width=169mm,\c!height=239mm] +\definepapersize [E5] [\c!width=155mm,\c!height=220mm] + +%D Industry invention: + +\definepapersize [A3plus] [\c!width=329mm,\c!height=483mm] + +%D For Alan: + +\definepapersize [business] [\c!width=85mm,\c!height=55mm] +\definepapersize [businessUS] [\c!width=3.5in,\c!height=2in] + +%D We can now default to a reasonable size. We match the print paper size with the +%D typeset paper size. This setting should come after the first layout specification +%D (already done). + +% \definepapersize +% [\v!default] +% [ \c!width=\paperwidth, +% \c!height=\paperheight] + +% \definepapersize +% [samesized] +% [ \c!width=\paperwidth, +% \c!height=\paperheight] + +\setuppapersize + [\c!distance=1.5cm] % offset is already taken + +\definepapersize + [oversized] + [ \c!width=\dimexpr\paperwidth +\layouttargetparameter\c!distance\relax, + \c!height=\dimexpr\paperheight+\layouttargetparameter\c!distance\relax] + +\definepapersize + [undersized] + [ \c!width=\dimexpr\paperwidth -\layouttargetparameter\c!distance\relax, + \c!height=\dimexpr\paperheight-\layouttargetparameter\c!distance\relax] + +\definepapersize + [doublesized] + [ \c!width=\dimexpr \paperwidth \relax, + \c!height=\dimexpr2\paperheight\relax] + +\definepapersize + [doubleoversized] + [ \c!width=\dimexpr \paperwidth +\layouttargetparameter\c!distance\relax, + \c!height=\dimexpr2\paperheight+\layouttargetparameter\c!distance\relax] + +\definepapersize + [doublewide] + [ \c!width=\dimexpr2\paperwidth \relax, + \c!height=\dimexpr \paperheight\relax] + +% \setuppapersize +% [A4][A4] + +\setuppapersize + [A4] % [samesized] + +%D A few goodies, first a full page layout: + +\definelayout + [\v!page] + +\setuplayout + [\v!page] + [\c!backspace=\zeropoint, + \c!cutspace=\zeropoint, + \c!topspace=\zeropoint, + \c!bottomspace=\zeropoint, + \c!margin=\zeropoint, + \c!edge=\zeropoint, + \c!header=\zeropoint, + \c!footer=\zeropoint, + \c!top=\zeropoint, + \c!bottom=\zeropoint, + \c!leftmargin=\zeropoint, + \c!rightmargin=\zeropoint, + \c!leftedge=\zeropoint, + \c!rightedge=\zeropoint, + \c!textdistance=\zeropoint, + \c!width=\v!middle, + \c!height=\v!middle, + \c!lines=0, + \c!grid=\v!no] + +%D A quick and dirty one: + +\definelayout + [\v!middle] + [\c!width=\v!middle, + \c!height=\v!middle] + +%D One for testing examples (5mm is often the non printable area): + +\definelayout + [\v!tight] + +\definelayout + [\v!tight] + [\v!page] + [\c!backspace=5mm, + \c!cutspace=5mm, + \c!topspace=5mm, + \c!bottomspace=5mm] + +\protect \endinput diff --git a/tex/context/base/mkiv/page-lin.mkvi b/tex/context/base/mkiv/page-lin.mkvi index ba3acef78..e355e3e60 100644 --- a/tex/context/base/mkiv/page-lin.mkvi +++ b/tex/context/base/mkiv/page-lin.mkvi @@ -53,7 +53,8 @@ \c_attr_linenumber\attributeunsetvalue \to \everyinsidefloat -\newcount \linenumber % not used +\mutable\let\linenumber\!!zerocount + \newbox \b_page_lines_scratch \newcount \c_page_lines_reference \newconstant\c_page_lines_nesting diff --git a/tex/context/base/mkiv/page-mcl.mkxl b/tex/context/base/mkiv/page-mcl.mkxl index f90576cf6..6874e4fb2 100644 --- a/tex/context/base/mkiv/page-mcl.mkxl +++ b/tex/context/base/mkiv/page-mcl.mkxl @@ -98,7 +98,7 @@ \fi -\unexpanded\def\page_mcl_command_set_hsize +\protected\def\page_mcl_command_set_hsize {\d_page_mcl_available_width\dimexpr \makeupwidth -\d_page_mcl_leftskip @@ -112,7 +112,7 @@ \textwidth\d_page_mcl_used_width \hsize\d_page_mcl_used_width} -\unexpanded\def\page_mcl_set_n_of_lines#1% +\protected\def\page_mcl_set_n_of_lines#1% {\d_page_mcl_temp\dimexpr +\textheight \ifdim\d_page_mcl_preceding_height>\zeropoint -\d_page_mcl_preceding_height \fi @@ -125,7 +125,7 @@ \fi \fi \c_page_mcl_n_of_lines\noflines} -\unexpanded\def\page_mcl_command_set_vsize +\protected\def\page_mcl_command_set_vsize {%%\page_one_command_set_vsize % indeed? \page_mcl_set_n_of_lines\zeropoint \d_page_mcl_temp\nofcolumns\dimexpr @@ -135,7 +135,7 @@ \global\vsize \d_page_mcl_temp \global\pagegoal\d_page_mcl_temp} % let's do it only here, reports maxdimen anyway -\unexpanded\def\page_mcl_command_routine +\protected\def\page_mcl_command_routine {\ifcase\c_page_mcl_routine \page_one_command_routine \or @@ -159,7 +159,7 @@ {\showmessage\m!columns3\empty \page_otr_construct_and_shipout\unvbox\normalpagebox\zerocount} % three arguments -\unexpanded\def\page_mcl_initialize_variables +\protected\def\page_mcl_initialize_variables {\reseteverypar % maybe still freeze .... \dontcomplain \settopskip @@ -370,17 +370,12 @@ {%\global\setbox\currentcolumnbox\box\currentcolumnbox \ht\currentcolumnbox\ht\firstcolumnbox} -\unexpanded\def\startmulticolumns - {\dosingleempty\page_mcl_start} - -\def\page_mcl_start[#1]% +\tolerant\protected\def\startmulticolumns[#1]% {\bgroup \ifinsidecolumns \page_mcl_start_nop \else - \iffirstargument - \setupmulticolumns[#1]% - \fi + \setupmulticolumns[#1]% \nofcolumns\multicolumnsparameter\c!n\relax \ifnum\nofcolumns>\plusone \page_mcl_start_yes @@ -390,16 +385,16 @@ \fi \fi} -\unexpanded\def\page_mcl_start_nop - {\let\stopmulticolumns\page_mcl_stop_nop} +\def\page_mcl_start_nop + {\enforced\let\stopmulticolumns\page_mcl_stop_nop} -\unexpanded\def\page_mcl_stop_nop +\permanent\protected\def\page_mcl_stop_nop {\egroup} -\unexpanded\def\page_mcl_start_yes +\protected\def\page_mcl_start_yes {\whitespace \begingroup - \let\stopmulticolumns\page_mcl_stop_indeed + \enforced\let\stopmulticolumns\page_mcl_stop_indeed \global\insidecolumnstrue \global\insidemulticolumnstrue % @@ -471,7 +466,7 @@ \page_otr_command_set_hsize \page_otr_command_set_vsize} -\unexpanded\def\page_mcl_stop_indeed +\permanent\protected\def\page_mcl_stop_indeed {\relax \synchronizeoutput \par diff --git a/tex/context/base/mkiv/page-one.mkiv b/tex/context/base/mkiv/page-one.mkiv index ada90eccf..f362a2fab 100644 --- a/tex/context/base/mkiv/page-one.mkiv +++ b/tex/context/base/mkiv/page-one.mkiv @@ -82,7 +82,12 @@ % 1 = partial page, 2 = whole page, 3 = partial page -\setnewconstant\kindofpagetextareas\plustwo % \plusone can become default some day +% We really need a setting! Todo, what key to use? + +\pushoverloadmode + \setnewconstant\kindofpagetextareas\plustwo % \plusone can become default some day + \overloaded\let\kindofpagetextareas\kindofpagetextareas +\popoverloadmode \def\page_one_registered_text_area_a % two arguments: (un)vbox n {\ifconditional\c_page_areas_enabled diff --git a/tex/context/base/mkiv/page-spr.mkxl b/tex/context/base/mkiv/page-spr.mkxl new file mode 100644 index 000000000..877509e41 --- /dev/null +++ b/tex/context/base/mkiv/page-spr.mkxl @@ -0,0 +1,131 @@ +%D \module +%D [ file=page-spr, +%D version=2002.11.11, +%D title=\CONTEXT\ Page Macros, +%D subtitle=Spreading, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Page Macros / Spreading} + +% This module is experimental and not yet official! + +\unprotect + +\newbox \b_page_spread_content +\newconditional\c_page_spread_busy +\newconditional\c_page_spread_once % when true only one flush (writes etc) + +\permanent\overloaded\protected\def\normalsettextpagecontent#1#2#3% #2 and #3 will disappear + {\setbox#1\hpack + {\setlayoutcomponentattribute{\v!page:\v!text}% + \vpack \layoutcomponentboxattribute to \textheight + {\offinterlineskip + \freezetextwidth + \hsize\textwidth % local variant of \sethsize + \boxmaxdepth\maxdepth + \noindent % content can be < \hsize + \page_otr_command_package_contents#2#3}}% + \dp#1\zeropoint + \ifconditional\c_page_spread_busy + \normalsettextpagecontent_spread{#1}% + \else + \normalsettextpagecontent_normal{#1}% + \fi} + +\def\normalsettextpagecontent_normal#1% + {\ifdim\wd#1=\makeupwidth\else + \setbox#1\hpack to \makeupwidth + {\hss\box#1\hss}% never change the \hss's + \fi} + +\def\normalsettextpagecontent_spread#1% + {\setbox#1\hpack to \makeupwidth + {\ifvoid\b_page_spread_content + \ifconditional\c_page_spread_once + \box#1% + \else + \global\setbox\b_page_spread_content\box#1% + \copy\b_page_spread_content + \fi + \hss % left page + \else + \hss % right page + \ifarrangingpages + % writes don't matter anyway + \else\ifconditional\c_page_spread_once + \global\setbox\b_page_spread_content\emptyhbox + \wd\b_page_spread_content\makeupwidth + \ht\b_page_spread_content\textheight + \else + % writes can interfere (todo: write stripper, but how about hyperlinks) + \fi \fi + \box\b_page_spread_content + \fi}} + +\protected\def\page_spread_flush + {\ifconditional\c_page_spread_busy \ifvoid\b_page_spread_content\else + % this page will be discarded later + \emptyhbox \page + \fi \fi } + +\permanent\protected\def\startspread + {\ifdoublesided + \ifconditional\c_page_spread_busy + \doubleexpandafter\page_spread_start_nop + \else + \doubleexpandafter\page_spread_start_yes + \fi + \else + \expandafter\page_spread_start_nop + \fi} + +\let\stopspread\relax + +\protected\def\page_spread_start_yes + {\bgroup + \page[\v!left]% + %\setsystemmode{spread}% + \settrue\c_page_spread_busy + \expanded{\setuplayout[\c!textwidth=\the\dimexpr2\textwidth+2\backspace\relax]}% + \let\stopspread\page_spread_stop_yes} + +\protected\def\page_spread_stop_yes + {\kern\zeropoint + \page + \setuplayout[\c!textwidth=\textwidth]% + \page[\v!left]% + \egroup} + +\protected\def\page_spread_start_nop + {\bgroup + \let\stopspread\page_spread_stop_nop} + +\protected\def\page_spread_stop_nop + {\egroup} + +\protect \endinput + +% texexec --arr --pdf test +% +% \setuplayout[width=middle] +% \setuppapersize[A4][A3,landscape] +% \setuppagenumbering[alternative=doublesided] +% \setuparranging[2UP] +% +% \starttext +% +% \dorecurse{3}{\input tufte } +% +% \startspread +% \dorecurse{10}{\input tufte } +% \stopspread +% +% \dorecurse{3}{\input tufte } +% +% \stoptext diff --git a/tex/context/base/mkiv/page-txt.mklx b/tex/context/base/mkiv/page-txt.mklx index ff582e561..6d9af76b0 100644 --- a/tex/context/base/mkiv/page-txt.mklx +++ b/tex/context/base/mkiv/page-txt.mklx @@ -77,11 +77,8 @@ \definelayoutelement[\v!footer:\v!edge] [\v!footer][\c!lefttext=,\c!middletext=,\c!righttext=] \definelayoutelement[\v!bottom:\v!edge] [\v!bottom][\c!lefttext=,\c!middletext=,\c!righttext=] -\unexpanded\def\setuplayouttext - {\dotripleempty\page_layouts_setup_text} - -\def\page_layouts_setup_text[#vertical][#horizontal][#settings]% - {\ifthirdargument +\permanent\tolerant\protected\def\setuplayouttext[#vertical]#spacer[#horizontal]#spacer[#settings]% + {\ifnum\lastarguments>\plustwo \setuplayoutelement[#vertical:#horizontal][#settings]% \else \setuplayoutelement[#vertical][#horizontal]% @@ -116,11 +113,11 @@ \ifx\previoustextstate\v!none \calculatevsizes\page_backgrounds_recalculate \fi \letgvalue{\??layouttextssynchronize#vertical}\currenttextstate} -\unexpanded\def\setuptop {\dotripleempty\page_layouts_setup_text[\v!top ]} -\unexpanded\def\setupheader{\dotripleempty\page_layouts_setup_text[\v!header]} -\unexpanded\def\setuptext {\dotripleempty\page_layouts_setup_text[\v!text ]} -\unexpanded\def\setupfooter{\dotripleempty\page_layouts_setup_text[\v!footer]} -\unexpanded\def\setupbottom{\dotripleempty\page_layouts_setup_text[\v!bottom]} +\permanent\protected\def\setuptop {\setuplayouttext[\v!top ]} +\permanent\protected\def\setupheader{\setuplayouttext[\v!header]} +\permanent\protected\def\setuptext {\setuplayouttext[\v!text ]} +\permanent\protected\def\setupfooter{\setuplayouttext[\v!footer]} +\permanent\protected\def\setupbottom{\setuplayouttext[\v!bottom]} %D We inherit some settings: @@ -143,11 +140,11 @@ %D \showsetup{noheaderandfooterlines} %D \showsetup{notopandbottomlines} -\unexpanded\def\noheaderandfooterlines +\permanent\protected\def\noheaderandfooterlines {\setuplayoutelement[\v!header][\c!state=\v!empty]% \setuplayoutelement[\v!footer][\c!state=\v!empty]} -\unexpanded\def\notopandbottomlines +\permanent\protected\def\notopandbottomlines {\setuplayoutelement[\v!top ][\c!state=\v!empty]% \setuplayoutelement[\v!bottom][\c!state=\v!empty]} @@ -169,59 +166,50 @@ %D someone uses the key|/|value interface these things have to be set explicitly as %D part of the text. -\unexpanded\def\setuptoptexts {\dosixtupleempty\page_layouts_setup_texts[\v!top ]} -\unexpanded\def\setupheadertexts{\dosixtupleempty\page_layouts_setup_texts[\v!header]} -\unexpanded\def\setuptexttexts {\dosixtupleempty\page_layouts_setup_texts[\v!text ]} -\unexpanded\def\setupfootertexts{\dosixtupleempty\page_layouts_setup_texts[\v!footer]} -\unexpanded\def\setupbottomtexts{\dosixtupleempty\page_layouts_setup_texts[\v!bottom]} - -\unexpanded\def\page_layouts_setup_text_six[#vertical][#horizontal][#a][#b][#c][#d]% - {\edef\currentlayoutelement{#vertical:#horizontal}% - \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_double{#a}{#d}}% - \setlayoutelementparameter\c!righttext{\page_layouts_process_element_double{#b}{#c}}} - -\unexpanded\def\page_layouts_setup_text_five[#vertical][#horizontal][#a][#b][#c][#d]% - {\edef\currentlayoutelement{#vertical:\v!text}% - \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_double{#horizontal}{#c}}% - \setlayoutelementparameter\c!righttext{\page_layouts_process_element_double{#a}{#b}}} - -\unexpanded\def\page_layouts_setup_text_four[#vertical][#horizontal][#a][#b][#c][#d]% - {\edef\currentlayoutelement{#vertical:#horizontal}% - \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_single{#a}}% - \setlayoutelementparameter\c!righttext{\page_layouts_process_element_single{#b}}} - -\unexpanded\def\page_layouts_setup_text_three[#vertical][#horizontal][#a][#b][#c][#d]% - {\edef\currentlayoutelement{#vertical:\v!text}% - \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_single{#horizontal}}% - \setlayoutelementparameter\c!righttext{\page_layouts_process_element_single{#a}}} - -\unexpanded\def\page_layouts_setup_text_two[#vertical][#horizontal][#a][#b][#c][#d]% - {\edef\currentlayoutelement{#vertical:\v!text}% - \resetlayoutelementparameter\c!lefttext - \resetlayoutelementparameter\c!righttext - \setlayoutelementparameter \c!middletext{\page_layouts_process_element_single{#horizontal}}} - -\unexpanded\def\page_layouts_setup_text_one[#vertical][#horizontal][#a][#b][#c][#d]% - {\edef\currentlayoutelement{#vertical:\v!text}% - \resetlayoutelementparameter\c!lefttext - \resetlayoutelementparameter\c!righttext - \resetlayoutelementparameter\c!middletext - \edef\currentlayoutelement{#vertical:\v!margin}% - \resetlayoutelementparameter\c!lefttext - \resetlayoutelementparameter\c!righttext - \resetlayoutelementparameter\c!middletext - \edef\currentlayoutelement{#vertical:\v!edge}% - \resetlayoutelementparameter\c!lefttext - \resetlayoutelementparameter\c!righttext - \resetlayoutelementparameter\c!middletext} - -\unexpanded\def\page_layouts_setup_texts - {\ifsixthargument \expandafter\page_layouts_setup_text_six \orelse - \iffifthargument \expandafter\page_layouts_setup_text_five \orelse - \iffourthargument\expandafter\page_layouts_setup_text_four \orelse - \ifthirdargument \expandafter\page_layouts_setup_text_three\orelse - \ifsecondargument\expandafter\page_layouts_setup_text_two \else - \expandafter\page_layouts_setup_text_one \fi} +\permanent\protected\def\setuptoptexts {\setuptexts[\v!top ]} +\permanent\protected\def\setupheadertexts{\setuptexts[\v!header]} +\permanent\protected\def\setuptexttexts {\setuptexts[\v!text ]} +\permanent\protected\def\setupfootertexts{\setuptexts[\v!footer]} +\permanent\protected\def\setupbottomtexts{\setuptexts[\v!bottom]} + +\permanent\tolerant\protected\def\setuptexts[#vertical]#spacer[#horizontal]#spacer[#a]#spacer[#b]#spacer[#c]#spacer[#d]% + {\ifarguments + % there is always one + \or + \edef\currentlayoutelement{#vertical:\v!text}% + \resetlayoutelementparameter\c!lefttext + \resetlayoutelementparameter\c!righttext + \resetlayoutelementparameter\c!middletext + \edef\currentlayoutelement{#vertical:\v!margin}% + \resetlayoutelementparameter\c!lefttext + \resetlayoutelementparameter\c!righttext + \resetlayoutelementparameter\c!middletext + \edef\currentlayoutelement{#vertical:\v!edge}% + \resetlayoutelementparameter\c!lefttext + \resetlayoutelementparameter\c!righttext + \resetlayoutelementparameter\c!middletext + \or + \edef\currentlayoutelement{#vertical:\v!text}% + \resetlayoutelementparameter\c!lefttext + \resetlayoutelementparameter\c!righttext + \setlayoutelementparameter \c!middletext{\page_layouts_process_element_single{#horizontal}}% + \or + \edef\currentlayoutelement{#vertical:\v!text}% + \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_single{#horizontal}}% + \setlayoutelementparameter\c!righttext{\page_layouts_process_element_single{#a}}% + \or + \edef\currentlayoutelement{#vertical:#horizontal}% + \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_single{#a}}% + \setlayoutelementparameter\c!righttext{\page_layouts_process_element_single{#b}}% + \or + \edef\currentlayoutelement{#vertical:\v!text}% + \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_double{#horizontal}{#c}}% + \setlayoutelementparameter\c!righttext{\page_layouts_process_element_double{#a}{#b}}% + \or + \edef\currentlayoutelement{#vertical:#horizontal}% + \setlayoutelementparameter\c!lefttext {\page_layouts_process_element_double{#a}{#d}}% + \setlayoutelementparameter\c!righttext{\page_layouts_process_element_double{#b}{#c}}% + \fi} %D Left and right texts are swapped on odd and even pages, but only when double %D sided typesetting is enabled. @@ -230,7 +218,7 @@ \let\m_page_layouts_element_content\empty -\unexpanded\def\page_layouts_process_element_single#content% +\protected\def\page_layouts_process_element_single#content% {\edef\m_page_layouts_element_content{\detokenize{#content}}% so no \v!xxx \ifcsname\??layouttextspecial\m_page_layouts_element_content\endcsname \lastnamedcs @@ -240,12 +228,12 @@ {#content}% \fi} -\unexpanded\def\page_layouts_process_element_double#first#second% +\protected\def\page_layouts_process_element_double#first#second% {\doifelseoddpage {\page_layouts_process_element_single{#first}} {\page_layouts_process_element_single{#second}}} -\unexpanded\def\page_layouts_process_element_indeed#style#color#width% +\protected\def\page_layouts_process_element_indeed#style#color#width% {\begingroup \uselayoutelementstyleandcolor#style#color% \begincsname\??layouttextstrut\layoutelementparameter\c!strut\endcsname @@ -257,7 +245,6 @@ \endgroup} \def\page_layouts_process_element_limited#content% are the {}{}{} still needed? -% {\limitatetext{#content{}{}{}}\currentlayoutelementwidth\unknown} {\limitated left \currentlayoutelementwidth text {#content} @@ -294,7 +281,7 @@ \doifinset\v!footer\floatspecification{\setxvalue{\namedlayoutelementhash\v!footer\c!n}{1}}% \to \everybeforeflushedpagefloat -\unexpanded\def\page_layouts_place_text_line#vertical% +\protected\def\page_layouts_place_text_line#vertical% {\page_layouts_set_element_status#vertical\relax \ifcsname\??layouttextsline\textlinestatus\endcsname \expandafter\lastnamedcs @@ -302,7 +289,7 @@ \expandafter\page_layouts_place_text_line_unknown \fi#vertical} -\unexpanded\def\doifelselayouttextline#vertical% shown or not +\permanent\protected\def\doifelselayouttextline#vertical% shown or not {\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}% \ifx\currentlayoutelementstate\v!normal \expandafter\firstoftwoarguments @@ -312,7 +299,7 @@ \expandafter\secondoftwoarguments \fi} -\unexpanded\def\doifelselayoutsomeline#vertical% present or not +\permanent\protected\def\doifelselayoutsomeline#vertical% present or not {\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}% \ifx\currentlayoutelementstate\v!none \expandafter\secondoftwoarguments @@ -377,7 +364,7 @@ %D The following macro has to be called after a page is flushed. -\unexpanded\def\resetlayouttextlines % public +\permanent\protected\def\resetlayouttextlines % public {\begincsname\??layouttextsreset\v!top \endcsname \begincsname\??layouttextsreset\v!header\endcsname \begincsname\??layouttextsreset\v!text \endcsname @@ -389,39 +376,36 @@ \global\setfalse\resyncaftertextline \fi} -\def\getspecificlayouttext#vertical#horizontal#what% +\permanent\def\getspecificlayouttext#vertical#horizontal#what% {\begincsname\namedlayoutelementhash{#vertical:#horizontal}#what\endcsname} % \settext[header][text][middle][xxx][yyy] -\unexpanded\def\settextcontent - {\doquintupleempty\page_layouts_set_text_content} - -\def\page_layouts_set_text_content[#vertical][#horizontal][#one][#two][#three]% header text middle text/text - {\iffifthargument - \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#one\endcsname\c!middletext}% - {\page_layouts_process_element_double{#two}{#three}}% - \orelse\iffourthargument - \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#one\endcsname\c!middletext}% - {\page_layouts_process_element_double{#two}{#two}}% - \orelse\ifthirdargument +\permanent\tolerant\protected\def\settextcontent[#vertical]#spacer[#horizontal]#spacer[#one]#spacer[#two]#spacer[#three]% header text middle text/text + {\ifarguments\or\or\or % 3 \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\c!middletext}% {\page_layouts_process_element_double{#one}{#one}}% + \or % 4 + \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#one\endcsname\c!middletext}% + {\page_layouts_process_element_double{#two}{#two}}% + \or % 5 + \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\begincsname\??layouttextcontent\v!text:#one\endcsname\c!middletext}% + {\page_layouts_process_element_double{#two}{#three}}% \fi} \let\currentlayoutelement\relax -\unexpanded\def\resettextcontent - {\dotripleempty\page_layouts_reset_text_content} +%D This will be redefined, so no \type {\frozen} here! -\def\page_layouts_reset_text_content[#vertical][#horizontal][#tag]% header text middle - {\edef\currentlayoutelement{#vertical:#horizontal}% - \ifthirdargument - \letvalueempty{\layoutelementhash\begincsname\??layouttextcontent\v!text:#tag\endcsname\c!middletext}% - \orelse\ifsecondargument +\permanent\tolerant\protected\def\resettextcontent[#vertical]#spacer[#horizontal]#spacer[#tag]% header text middle + {\ifarguments\or\or % 2 + \edef\currentlayoutelement{#vertical:#horizontal}% \resetlayoutelementparameter\c!lefttext \resetlayoutelementparameter\c!middletext \resetlayoutelementparameter\c!righttext + \or % 3 + \edef\currentlayoutelement{#vertical:#horizontal}% + \letvalueempty{\layoutelementhash\begincsname\??layouttextcontent\v!text:#tag\endcsname\c!middletext}% \fi} \letvalue{\??layouttextcontent\v!text:\c!middle}\c!middletext @@ -718,20 +702,17 @@ %D \chapter{tweede} \dorecurse{20}{\input tufte \relax} %D \stoptyping -\unexpanded\def\definetext - {\doseventupleempty\page_layouts_define_text} - -\def\page_layouts_define_text[#tag][#vertical][#horizontal][#a][#b][#c][#d]% - {\ifseventhargument - \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}{\page_layouts_setup_text_six [#vertical][#horizontal][#a][#b][#c][#d]}% - \orelse\ifsixthargument - \setvalue{\namedlayoutelementhash {#vertical}#tag}{\page_layouts_setup_text_five [#vertical][#horizontal][#a][#b][#c][]}% - \orelse\iffifthargument - \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}{\page_layouts_setup_text_four [#vertical][#horizontal][#a][#b][][]}% - \orelse\iffourthargument - \setvalue{\namedlayoutelementhash {#vertical}#tag}{\page_layouts_setup_text_three[#vertical][#horizontal][#a][][][]}% - \else - \setvalue{\namedlayoutelementhash {#vertical}#tag}{\page_layouts_setup_text_two [#vertical][#horizontal][][][][]}% +\permanent\tolerant\protected\def\definetext[#tag]#spacer[#vertical]#spacer[#horizontal]#spacer[#a]#spacer[#b]#spacer[#c]#spacer[#d]% + {\ifnum\lastarguments<\plusfour + \setvalue{\namedlayoutelementhash {#vertical}#tag}{\setuptexts[#vertical][#horizontal]\relax}% 1, 2, 3 + \orelse\ifarguments\or\or\or\or + \setvalue{\namedlayoutelementhash {#vertical}#tag}{\setuptexts[#vertical][#horizontal][#a]\relax}% 4 + \or + \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}{\setuptexts[#vertical][#horizontal][#a][#b]\relax}% 5 + \or + \setvalue{\namedlayoutelementhash {#vertical}#tag}{\setuptexts[#vertical][#horizontal][#a][#b][#c]\relax}% 6 + \or + \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}{\setuptexts[#vertical][#horizontal][#a][#b][#c][#d]\relax}% 7 \fi} %D A few more page breakers: @@ -769,7 +750,7 @@ \let\m_page_layouts_page_number_location_h\relax \let\m_page_layouts_page_number_location_x\relax -\def\page_layouts_place_page_number % also elsewhere .. beware, not \unexpanded else +\def\page_layouts_place_page_number % also elsewhere .. beware, not \protected else {\strc_pagenumbers_place_location} % test below fails \def\page_layouts_reset_page_number_location @@ -817,7 +798,7 @@ \v!marginedge=>\let\m_page_layouts_page_number_location_h\v!text \let\m_page_layouts_page_number_location_x\c!marginedgetext]} -\unexpanded\def\strc_pagenumbers_set_location +\protected\def\strc_pagenumbers_set_location {\edef\p_strc_pagenumbers_location{\directpagenumberingparameter\c!location}% \ifx\p_strc_pagenumbers_location\m_page_layouts_page_number_location % unchanged @@ -949,10 +930,10 @@ %D The main text area has to be combined with some additional (tracing) information. %D %D This will be stored as normal and overloaded in page-lyr and later in page-spr we -%D overload the the stored version .. evenatually i will clear up the experimental +%D overload the the stored version .. eventually i will clear up the experimental %D mess. -\def\settextpagecontent#1#2#3% #2 and #3 will disappear / is overloaded +\protected\def\settextpagecontent#1#2#3% #2 and #3 will disappear / is overloaded {\setbox#1\hpack to \makeupwidth {\hss % so don't change this \setlayoutcomponentattribute{\v!page:\v!text}% diff --git a/tex/context/base/mkiv/phys-dim.mkiv b/tex/context/base/mkiv/phys-dim.mkiv index f17861405..decc19bd3 100644 --- a/tex/context/base/mkiv/phys-dim.mkiv +++ b/tex/context/base/mkiv/phys-dim.mkiv @@ -175,8 +175,6 @@ %def\digitstimessymbol{\ifmmode\cdot\else\digitstextbinop\cdot\fi} \def\digitstimessymbol{\digitstextbinop\times} -\unexpanded\def\mathplusminus{±} % will be in math-ini - \unexpanded\def\digitszeropadding {\hphantom{0}} \unexpanded\def\digitsnegative {\phys_digits_normalized{0}{\phys_digits_raised{\textminus}}} \unexpanded\def\digitspositive {\phys_digits_normalized{0}{\phys_digits_raised{\textplus}}} diff --git a/tex/context/base/mkiv/publ-ini.lua b/tex/context/base/mkiv/publ-ini.lua index da6c74b2e..ec36be89a 100644 --- a/tex/context/base/mkiv/publ-ini.lua +++ b/tex/context/base/mkiv/publ-ini.lua @@ -3500,7 +3500,7 @@ do function publications.prerollcmdstring(str) btxstring = str or "" - tex.runtoks("t_btx_cmd") + tex.runlocal("t_btx_cmd") return nodes.toutf(tex.getbox("b_btx_cmd").list) or str end diff --git a/tex/context/base/mkiv/publ-ini.mkiv b/tex/context/base/mkiv/publ-ini.mkiv index 996b6d3ca..12864aa6c 100644 --- a/tex/context/base/mkiv/publ-ini.mkiv +++ b/tex/context/base/mkiv/publ-ini.mkiv @@ -59,22 +59,24 @@ \startcontextdefinitioncode -\def\s!btx {btx} - -\def\v!btxcite {btxcite} -\def\v!btxlist {btxlist} -\def\v!btxrendering {btxrendering} - -\def\s!btxset {btxset} -\def\s!btxref {btxref} -\def\s!btxint {btxint} -\def\s!btxltx {btxltx} -\def\s!btxrtx {btxrtx} -\def\s!btxatx {btxatx} -\def\s!btxbtx {btxbtx} -\def\s!btxspc {btxspc} -\def\s!btxlst {btxlst} -\def\s!btxcom {btxcom} +%D These are currently not interfaced. + +\definesystemconstant {btx} + +\definesystemconstant {btxset} +\definesystemconstant {btxref} +\definesystemconstant {btxint} +\definesystemconstant {btxltx} +\definesystemconstant {btxrtx} +\definesystemconstant {btxatx} +\definesystemconstant {btxbtx} +\definesystemconstant {btxspc} +\definesystemconstant {btxlst} +\definesystemconstant {btxcom} + +\defineinterfacevariable {btxcite} {btxcite} +\defineinterfacevariable {btxlist} {btxlist} +\defineinterfacevariable {btxrendering} {btxrendering} \definelabelclass[btxlabel][2] diff --git a/tex/context/base/mkiv/scrn-but.mkvi b/tex/context/base/mkiv/scrn-but.mkvi index 977b02acd..6c279dfc4 100644 --- a/tex/context/base/mkiv/scrn-but.mkvi +++ b/tex/context/base/mkiv/scrn-but.mkvi @@ -337,7 +337,7 @@ \let\scrn_menu_define_original\defineinteractionmenu -\unexpanded\def\defineinteractionmenu +\unexpanded\overloaded\def\defineinteractionmenu {\dotripleempty\scrn_menu_define} \def\scrn_menu_define[#tag][#category][#settings]% category reflects location, settings can be parent diff --git a/tex/context/base/mkiv/scrn-wid.mkvi b/tex/context/base/mkiv/scrn-wid.mkvi index ea77a7da3..d0b0fb006 100644 --- a/tex/context/base/mkiv/scrn-wid.mkvi +++ b/tex/context/base/mkiv/scrn-wid.mkvi @@ -605,7 +605,7 @@ {\iflocation \clf_insertsoundclip tag {#tag}% - repeat {\directexternalsoundtrackparameter\c!option}% + repeat {\directexternalsoundtracksparameter\c!option}% \relax \fi} diff --git a/tex/context/base/mkiv/spac-ali.mkiv b/tex/context/base/mkiv/spac-ali.mkiv index ad1b118f8..7ed3416cc 100644 --- a/tex/context/base/mkiv/spac-ali.mkiv +++ b/tex/context/base/mkiv/spac-ali.mkiv @@ -797,7 +797,7 @@ \unexpanded\def\ibox {\vbox\bgroup \forgetall - \let\\=\endgraf + \let\\\endgraf \ifdoublesided\signalinnerrealign\fi \doifelserightpage\spac_align_set_horizontal_right\spac_align_set_horizontal_left \let\next} @@ -805,7 +805,7 @@ \unexpanded\def\obox {\vbox\bgroup \forgetall - \let\\=\endgraf + \let\\\endgraf \ifdoublesided\signalouterrealign\fi \doifelserightpage\c_spac_align_state_horizontal_left\spac_align_set_horizontal_right \let\next} @@ -956,7 +956,7 @@ \dontleavehmode % added in marrakesch at TUG 2006\begingroup \begingroup \setlocalhsize % new - \def\\{\egroup\par\doalignline{#1}{#2}\bgroup}% + \protected\def\\{\egroup\par\doalignline{#1}{#2}\bgroup}% \dowithnextbox {\hbox to \localhsize {\ifcase\alignstrutmode\or\strut\fi @@ -1036,7 +1036,7 @@ \dontleavehmode % added in marrakesch at TUG 2006\begingroup \begingroup \setlocalhsize - \def\\{\egroup\par\doxalignline#1#2#3#4#5#6\bgroup}% inefficient + \protected\def\\{\egroup\par\doxalignline#1#2#3#4#5#6\bgroup}% inefficient \dowithnextbox {\hbox to \localhsize {#1\hskip\ifdone#2\else#3\fi#4% diff --git a/tex/context/base/mkiv/spac-ali.mkxl b/tex/context/base/mkiv/spac-ali.mkxl index f4310dfc0..a41c99410 100644 --- a/tex/context/base/mkiv/spac-ali.mkxl +++ b/tex/context/base/mkiv/spac-ali.mkxl @@ -21,11 +21,11 @@ \registerctxluafile{spac-ali}{optimize} -\chardef\normalizelinemodecode = "01 -\chardef\indentskipmodecode = "02 -\chardef\swaphangindentmodecode = "04 -\chardef\swapparskipmodecode = "08 -\chardef\breakafterdirmodecode = "10 +\immutable\chardef\normalizelinemodecode = "01 +\immutable\chardef\indentskipmodecode = "02 +\immutable\chardef\swaphangindentmodecode = "04 +\immutable\chardef\swapparskipmodecode = "08 +\immutable\chardef\breakafterdirmodecode = "10 \definesystemattribute[realign] [public] % might be combined with the next one \definesystemattribute[alignstate][public] % will make a single attributes for several states @@ -35,16 +35,16 @@ \c_attr_alignstate\attributeunsetvalue \to \everyforgetall -\unexpanded\def\resetrealignsignal{\c_attr_realign\attributeunsetvalue} -\unexpanded\def\signalinnerrealign{\clf_setrealign\plustwo} -\unexpanded\def\signalouterrealign{\clf_setrealign\plusone} +\permanent\protected\def\resetrealignsignal{\c_attr_realign\attributeunsetvalue} +\permanent\protected\def\signalinnerrealign{\clf_setrealign\plustwo} +\permanent\protected\def\signalouterrealign{\clf_setrealign\plusone} \installcorenamespace{aligncommand} \installcorenamespace{alignhorizontal} \installcorenamespace{alignvertical} -\installcorenamespace{alignmentnormalcache} -\installcorenamespace{alignmentraggedcache} +% \installcorenamespace{alignmentnormalcache} +% \installcorenamespace{alignmentraggedcache} % nasty hack: @@ -54,8 +54,8 @@ \installcorenamespace{alignmentraggedcacheodd} \installcorenamespace{alignmentraggedcacheeven} -\def\??alignmentnormalcache{\ifodd\realpageno\??alignmentnormalcacheodd\else\??alignmentnormalcacheeven\fi} -\def\??alignmentraggedcache{\ifodd\realpageno\??alignmentraggedcacheodd\else\??alignmentraggedcacheeven\fi} +\immutable\def\??alignmentnormalcache{\ifodd\realpageno\??alignmentnormalcacheodd\else\??alignmentnormalcacheeven\fi} +\immutable\def\??alignmentraggedcache{\ifodd\realpageno\??alignmentraggedcacheodd\else\??alignmentraggedcacheeven\fi} \newtoks\everyresetalign % todo @@ -65,48 +65,48 @@ \newconditional\displaylefttoright \settrue\displaylefttoright \newconditional\inlinelefttoright \settrue\inlinelefttoright -\unexpanded\def\lefttoright +\permanent\protected\def\lefttoright {\ifvmode \spac_directions_lefttoright_vmode \else \spac_directions_lefttoright_hmode \fi} -\unexpanded\def\righttoleft +\permanent\protected\def\righttoleft {\ifvmode \spac_directions_righttoleft_vmode \else \spac_directions_righttoleft_hmode \fi} -\unexpanded\def\spac_directions_lefttoright_vmode +\protected\def\spac_directions_lefttoright_vmode {\settrue\displaylefttoright \settrue\inlinelefttoright \textdirection\directionlefttoright \pardirection \directionlefttoright} -\unexpanded\def\spac_directions_righttoleft_vmode +\protected\def\spac_directions_righttoleft_vmode {\setfalse\displaylefttoright \setfalse\inlinelefttoright \textdirection\directionrighttoleft \pardirection \directionrighttoleft} -\unexpanded\def\spac_directions_lefttoright_hmode +\protected\def\spac_directions_lefttoright_hmode {\linedirection\directionlefttoright % linedir keeps subtype of skip \settrue\inlinelefttoright} -\unexpanded\def\spac_directions_righttoleft_hmode +\protected\def\spac_directions_righttoleft_hmode {\linedirection\directionrighttoleft % linedir keeps subtype of skip \setfalse\inlinelefttoright} -\unexpanded\def\synchronizelayoutdirection +\permanent\protected\def\synchronizelayoutdirection {\ifconditional\layoutlefttoright \spac_directions_synchronize_lr \else \spac_directions_synchronize_rl \fi} -\unexpanded\def\synchronizedisplaydirection +\permanent\protected\def\synchronizedisplaydirection {\ifconditional\displaylefttoright \spac_directions_synchronize_lr \else @@ -123,30 +123,30 @@ \textdirection\directionrighttoleft \pardirection \directionrighttoleft} -\unexpanded\def\synchronizeinlinedirection +\permanent\protected\def\synchronizeinlinedirection {% why not \linedirection here \textdirection\ifconditional\inlinelefttoright\directionlefttoright\else\directionrighttoleft\fi} -\unexpanded\def\checkedlefttoright +\permanent\protected\def\checkedlefttoright {\ifvmode \spac_directions_lefttoright_vmode \else \spac_directions_lefttoright_hmode_checked \fi} -\unexpanded\def\checkedrighttoleft +\permanent\protected\def\checkedrighttoleft {\ifvmode \spac_directions_righttoleft_vmode \else \spac_directions_righttoleft_hmode_checked \fi} -\unexpanded\def\spac_directions_lefttoright_hmode_checked +\protected\def\spac_directions_lefttoright_hmode_checked {\ifconditional\inlinelefttoright\else \lefttoright \fi} -\unexpanded\def\spac_directions_righttoleft_hmode_checked +\protected\def\spac_directions_righttoleft_hmode_checked {\ifconditional\inlinelefttoright \righttoleft \fi} @@ -156,10 +156,10 @@ \letvalue{\??bidi\v!left }\checkedlefttoright \letvalue{\??bidi l2r}\checkedlefttoright \letvalue{\??bidi\v!right}\checkedrighttoleft \letvalue{\??bidi r2l}\checkedrighttoleft -\unexpanded\def\usebidiparameter#1% +\permanent\protected\def\usebidiparameter#1% {\begincsname\??bidi#1\c!bidi\endcsname} -\unexpanded\def\showdirections +\permanent\protected\def\showdirections {\dontleavehmode \begingroup\infofont\textdirection\directionlefttoright[\space layout: \ifconditional\layoutlefttoright l2r\else r2l\fi\space @@ -167,20 +167,20 @@ inline: \ifconditional\inlinelefttoright l2r\else r2l\fi\space ]\endgroup} -\unexpanded\def\righttolefthbox#1#{\reversehbox#1\bgroup\righttoleft\let\next} \let\rtlhbox\righttolefthbox -\unexpanded\def\lefttorighthbox#1#{\naturalhbox#1\bgroup\lefttoright\let\next} \let\ltrhbox\lefttorighthbox -\unexpanded\def\righttoleftvbox#1#{\reversevbox#1\bgroup\righttoleft\let\next} \let\rtlvbox\righttoleftvbox -\unexpanded\def\lefttorightvbox#1#{\naturalvbox#1\bgroup\lefttoright\let\next} \let\ltrvbox\lefttorightvbox -\unexpanded\def\righttoleftvtop#1#{\reversevtop#1\bgroup\righttoleft\let\next} \let\rtlvtop\righttoleftvtop -\unexpanded\def\lefttorightvtop#1#{\naturalvtop#1\bgroup\lefttoright\let\next} \let\ltrvtop\lefttorightvtop +\permanent\protected\def\righttolefthbox#1#{\reversehbox#1\bgroup\righttoleft\let\next} \let\rtlhbox\righttolefthbox +\permanent\protected\def\lefttorighthbox#1#{\naturalhbox#1\bgroup\lefttoright\let\next} \let\ltrhbox\lefttorighthbox +\permanent\protected\def\righttoleftvbox#1#{\reversevbox#1\bgroup\righttoleft\let\next} \let\rtlvbox\righttoleftvbox +\permanent\protected\def\lefttorightvbox#1#{\naturalvbox#1\bgroup\lefttoright\let\next} \let\ltrvbox\lefttorightvbox +\permanent\protected\def\righttoleftvtop#1#{\reversevtop#1\bgroup\righttoleft\let\next} \let\rtlvtop\righttoleftvtop +\permanent\protected\def\lefttorightvtop#1#{\naturalvtop#1\bgroup\lefttoright\let\next} \let\ltrvtop\lefttorightvtop -\unexpanded\def\autodirhbox#1#{\hbox#1\bgroup\synchronizeinlinedirection\let\next} -\unexpanded\def\autodirvbox#1#{\vbox#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vbox -\unexpanded\def\autodirvtop#1#{\vtop#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vtop +\permanent\protected\def\autodirhbox#1#{\hbox#1\bgroup\synchronizeinlinedirection\let\next} +\permanent\protected\def\autodirvbox#1#{\vbox#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vbox +\permanent\protected\def\autodirvtop#1#{\vtop#1\bgroup\synchronizeinlinedirection\let\next} % maybe also pardir or maybe just a \vtop -\unexpanded\def\leftorrighthbox{\ifconditional\displaylefttoright\expandafter\lefttorighthbox\else\expandafter\righttolefthbox\fi} -\unexpanded\def\leftorrightvbox{\ifconditional\displaylefttoright\expandafter\lefttorightvbox\else\expandafter\righttoleftvbox\fi} -\unexpanded\def\leftorrightvtop{\ifconditional\displaylefttoright\expandafter\lefttorightvtop\else\expandafter\righttoleftvtop\fi} +\permanent\protected\def\leftorrighthbox{\ifconditional\displaylefttoright\expandafter\lefttorighthbox\else\expandafter\righttolefthbox\fi} +\permanent\protected\def\leftorrightvbox{\ifconditional\displaylefttoright\expandafter\lefttorightvbox\else\expandafter\righttoleftvbox\fi} +\permanent\protected\def\leftorrightvtop{\ifconditional\displaylefttoright\expandafter\lefttorightvtop\else\expandafter\righttoleftvtop\fi} % Tolerance and hyphenation @@ -203,7 +203,7 @@ \def\spac_align_set_raggedness_middle{\ifzeropt\hsize\plussix\bodyfontsize\else.5\hsize\fi} -\unexpanded\def\setraggedness#1% tricky .. we keep the global tolerance otherwise ... to be reconsidered +\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 @@ -215,37 +215,37 @@ % no need to do something as we're in \nohyphens \fi} -\unexpanded\def\spac_align_set_tolerant +\protected\def\spac_align_set_tolerant {\tolerance\c_spac_tolerance_normal} -\unexpanded\def\spac_align_set_very_tolerant +\protected\def\spac_align_set_very_tolerant {\tolerance\c_spac_tolerance_extreme} -\unexpanded\def\spac_align_set_stretch +\protected\def\spac_align_set_stretch {\emergencystretch\bodyfontsize} -\unexpanded\def\spac_align_set_extreme_stretch +\protected\def\spac_align_set_extreme_stretch {\emergencystretch10\bodyfontsize} % Vertical \newconstant\c_spac_align_state_vertical -\unexpanded\def\spac_align_set_vertical_none - {\let\raggedtopcommand \relax - \let\raggedbottomcommand\relax} +\protected\def\spac_align_set_vertical_none + {\enforced\let\raggedtopcommand \relax + \enforced\let\raggedbottomcommand\relax} -\unexpanded\def\spac_align_set_vertical_lohi - {\let\raggedtopcommand \vfilll - \let\raggedbottomcommand\vfilll} +\protected\def\spac_align_set_vertical_lohi + {\enforced\let\raggedtopcommand \vfilll + \enforced\let\raggedbottomcommand\vfilll} -\unexpanded\def\spac_align_set_vertical_low - {\let\raggedtopcommand \vfilll - \let\raggedbottomcommand\relax} +\protected\def\spac_align_set_vertical_low + {\enforced\let\raggedtopcommand \vfilll + \enforced\let\raggedbottomcommand\relax} -\unexpanded\def\spac_align_set_vertical_high - {\let\raggedtopcommand \relax - \let\raggedbottomcommand\vfilll} +\protected\def\spac_align_set_vertical_high + {\enforced\let\raggedtopcommand \relax + \enforced\let\raggedbottomcommand\vfilll} \def\spac_align_flush_vertical {\ifcase\c_spac_align_state_vertical @@ -289,7 +289,7 @@ % \s!plus ... slower than inline -\unexpanded\def\spac_align_set_horizontal_none % should also relax \updateraggedskips +\permanent\protected\def\spac_align_set_horizontal_none % should also relax \updateraggedskips {\raggedstatus \zerocount \c_attr_alignstate\attributeunsetvalue \leftskip \plusone\leftskip @@ -301,7 +301,7 @@ \setfalse \raggedonelinerstate % now here \let\updateraggedskips\relax} % no need for adaption -\unexpanded\def\spac_align_set_horizontal_left +\permanent\protected\def\spac_align_set_horizontal_left {\setraggedness \spac_align_set_raggedness_left \raggedstatus \plusone \c_attr_alignstate\plusone @@ -314,7 +314,7 @@ \parindent \zeropoint \relax} -\unexpanded\def\spac_align_set_horizontal_center +\permanent\protected\def\spac_align_set_horizontal_center {\setraggedness \spac_align_set_raggedness_middle \raggedstatus \plustwo \c_attr_alignstate\plustwo @@ -327,7 +327,7 @@ \parindent \zeropoint \relax} -\unexpanded\def\spac_align_set_horizontal_right +\permanent\protected\def\spac_align_set_horizontal_right {\setraggedness \spac_align_set_raggedness_right \raggedstatus \plusthree \c_attr_alignstate\plusthree @@ -340,7 +340,7 @@ %\parindent \parindent \relax} -\unexpanded\def\spac_align_set_horizontal_very_left +\permanent\protected\def\spac_align_set_horizontal_very_left {\raggedstatus \plusone \c_attr_alignstate\plusone \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount @@ -352,7 +352,7 @@ \parindent \zeropoint \relax} -\unexpanded\def\spac_align_set_horizontal_very_center +\permanent\protected\def\spac_align_set_horizontal_very_center {\raggedstatus \plustwo \c_attr_alignstate\plustwo \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount @@ -364,7 +364,7 @@ \parindent \zeropoint \relax} -\unexpanded\def\spac_align_set_horizontal_very_right +\permanent\protected\def\spac_align_set_horizontal_very_right {\raggedstatus \plusthree \c_attr_alignstate\plusthree \leftskip \plusone\leftskip \s!plus\zeropoint @@ -376,7 +376,7 @@ %\parindent \parindent \relax} -\unexpanded\def\spac_align_set_horizontal_wide_center +\permanent\protected\def\spac_align_set_horizontal_wide_center {\setraggedness \spac_align_set_raggedness_middle \raggedstatus \plustwo \c_attr_alignstate\plustwo @@ -389,7 +389,7 @@ \parindent \zeropoint \relax} -\unexpanded\def\spac_align_set_horizontal_centered_last_line +\permanent\protected\def\spac_align_set_horizontal_centered_last_line {\raggedstatus \zerocount \c_attr_alignstate\attributeunsetvalue \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount\relax @@ -401,7 +401,7 @@ \parindent \zeropoint \relax} -\unexpanded\def\spac_align_set_horizontal_flushedright_last_line +\permanent\protected\def\spac_align_set_horizontal_flushedright_last_line {\raggedstatus \zerocount \c_attr_alignstate\attributeunsetvalue \leftskip \plusone\leftskip \s!plus\v_spac_align_fill_amount\relax @@ -413,7 +413,7 @@ \parindent \zeropoint \relax} -\unexpanded\def\spac_align_set_horizontal_right_tt % a plain command +\permanent\protected\def\spac_align_set_horizontal_right_tt % a plain command {\tttf % brrr \raggedstatus \plusthree \c_attr_alignstate\plusthree @@ -426,7 +426,7 @@ %\parindent \parindent \relax} -\unexpanded\def\spac_align_set_horizontal_extra +\permanent\protected\def\spac_align_set_horizontal_extra {\xspaceskip\zeropoint\s!plus\v_spac_align_fill_amount_space\relax} \def\spac_align_flush_horizontal @@ -496,21 +496,21 @@ \newconstant\bottomraggednessmode % 0=ragged 1=normal/align 2=baseline -\unexpanded\def\raggedbottom +\permanent\protected\def\raggedbottom {\bottomraggednessmode\zerocount \settopskip} -\unexpanded\def\alignbottom +\permanent\protected\def\alignbottom {\bottomraggednessmode\plusone \settopskip} -\unexpanded\def\baselinebottom +\permanent\protected\def\baselinebottom {\bottomraggednessmode\plustwo \settopskip} \let\normalbottom\alignbottom % downward compatible -\unexpanded\def\setbottomalignmode#1% +\permanent\protected\def\setbottomalignmode#1% {\bottomraggednessmode#1% \settopskip} @@ -548,7 +548,7 @@ \let\updateraggedskips\relax \def\spac_align_add_to_cache - {\let\raggedbox\relax % why + {\enforced\let\raggedbox\relax % why % we inherit hyphenation and tolerance \t_spac_align_collected \emptytoks \c_spac_align_state_broad \zerocount @@ -582,7 +582,7 @@ % The local (key driven) setter: -\unexpanded\def\spac_align_prepare#1% deferred +\permanent\protected\def\spac_align_prepare#1% deferred {\edef\m_spac_align_asked{#1}% \expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname \ifx\raggedcommand\relax @@ -595,10 +595,7 @@ % The regular align setter: -\unexpanded\def\setupalign - {\dosingleempty\spac_align_setup} - -\def\spac_align_setup[#1]% immediate +\permanent\tolerant\protected\def\setupalign[#1]% immediate {\edef\m_spac_align_asked{#1}% \expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname \ifx\raggedcommand\relax @@ -608,13 +605,13 @@ \fi \raggedcommand} -\unexpanded\def\usealignparameter#1% faster local variant +\permanent\protected\def\usealignparameter#1% faster local variant {\edef\m_spac_align_asked{#1\c!align}% \ifx\m_spac_align_asked\empty\else \spac_align_use_indeed \fi} -\unexpanded\def\dousealignparameter#1% faster local variant +\permanent\protected\def\dousealignparameter#1% faster local variant {\edef\m_spac_align_asked{#1}% \ifx\m_spac_align_asked\empty\else \spac_align_use_indeed @@ -631,7 +628,7 @@ % experiment -\unexpanded\def\spac_align_use_later#1% +\protected\def\spac_align_use_later#1% {\begingroup \edef\m_spac_align_asked{#1}% \expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align_asked\endcsname @@ -640,12 +637,12 @@ \fi \endgroup} -\unexpanded\def\spac_align_use_now#1% +\protected\def\spac_align_use_now#1% {\csname\??alignmentnormalcache#1\endcsname} % Maybe we need something different in columns. -\unexpanded\def\installalign#1#2% beware: commands must be unexpandable! +\protected\def\installalign#1#2% beware: commands must be unexpandable! {\ifcsname\??aligncommand#1\endcsname \else \setvalue{\??aligncommand#1}{\toksapp\t_spac_align_collected{#2}}% \fi} @@ -659,7 +656,7 @@ % % this one could deal with both % -% \unexpanded\def\installalignoption#1#2% +% \protected\def\installalignoption#1#2% % {\ifcsname\??aligncommand#1\endcsname \else % \setvalue{\??aligncommand#1}% % {\spac_align_set_horizontal_none @@ -759,7 +756,7 @@ \spac_align_flush_parfill_indeed{\number\c_spac_align_state_par_fill}% \fi} -\unexpanded\def\spac_align_flush_parfill_indeed#1% +\protected\def\spac_align_flush_parfill_indeed#1% {\parfillskip #1\directhspaceamount\v!final % plus \dimexpr\availablehsize-#1\directhspaceamount\v!final\relax @@ -775,7 +772,7 @@ \setvalue{\??aligncommand\v!left }{\c_spac_align_state_horizontal\plustwo }% \to \t_spac_every_swap_align -\unexpanded\def\enablereversealignment +\permanent\protected\def\enablereversealignment {\the\t_spac_every_swap_align \t_spac_every_swap_align\emptytoks} @@ -792,8 +789,7 @@ \let\centeredlastline \spac_align_set_horizontal_centered_last_line \let\flushedrightlastline\spac_align_set_horizontal_flushedright_last_line \let\ttraggedright \spac_align_set_horizontal_right_tt % a plain command - -\let\forgetragged \spac_align_set_horizontal_none +\let\forgetragged \spac_align_set_horizontal_none \appendtoks \spac_align_set_horizontal_none @@ -801,18 +797,18 @@ % Box commands. -\unexpanded\def\ibox +\permanent\protected\def\ibox {\vbox\bgroup \forgetall - \let\\=\endgraf + \enforced\let\\\endgraf \ifdoublesided\signalinnerrealign\fi \doifelserightpage\spac_align_set_horizontal_right\spac_align_set_horizontal_left \let\next} -\unexpanded\def\obox +\permanent\protected\def\obox {\vbox\bgroup \forgetall - \let\\=\endgraf + \enforced\let\\\endgraf \ifdoublesided\signalouterrealign\fi \doifelserightpage\c_spac_align_state_horizontal_left\spac_align_set_horizontal_right \let\next} @@ -820,11 +816,11 @@ \let\raggedbox\relax \def\dosetraggedvbox#1% can be more keys .. how about caching here (but seldom used) - {\let\raggedbox\vbox + {\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) - {\let\raggedbox\hbox + {\enforced\let\raggedbox\hbox \processcommacommand[#1]\spac_align_set_ragged_hbox} \def\spac_align_set_ragged_vbox#1% @@ -839,35 +835,52 @@ \quitcommalist \fi} -\setvalue{\??alignvertical \v!left }{\let\raggedbox\lbox} -\setvalue{\??alignvertical \v!right }{\let\raggedbox\rbox} -\setvalue{\??alignvertical \v!middle }{\let\raggedbox\cbox} -\setvalue{\??alignvertical \v!inner }{\let\raggedbox\ibox} -\setvalue{\??alignvertical \v!outer }{\let\raggedbox\obox} -\setvalue{\??alignvertical \v!flushleft }{\let\raggedbox\rbox} -\setvalue{\??alignvertical \v!flushright}{\let\raggedbox\lbox} -\setvalue{\??alignvertical \v!center }{\let\raggedbox\cbox} -\setvalue{\??alignvertical \v!no }{\def\raggedbox{\vbox\bgroup\spac_align_set_horizontal_right\let\next=}]} - -% maybe \let's - -\setvalue{\??alignhorizontal\v!left }{\def\raggedbox{\doalignedline\v!left }} -\setvalue{\??alignhorizontal\v!right }{\def\raggedbox{\doalignedline\v!right }} -\setvalue{\??alignhorizontal\v!middle }{\def\raggedbox{\doalignedline\v!middle}} -\setvalue{\??alignhorizontal\v!inner }{\def\raggedbox{\doalignedline\v!inner }} -\setvalue{\??alignhorizontal\v!outer }{\def\raggedbox{\doalignedline\v!outer }} -\setvalue{\??alignhorizontal\v!flushleft }{\def\raggedbox{\doalignedline\v!right }} -\setvalue{\??alignhorizontal\v!flushright}{\def\raggedbox{\doalignedline\v!left }} -\setvalue{\??alignhorizontal\v!center }{\def\raggedbox{\doalignedline\v!middle}} +\permanent\protected\def\spac_align_vertical_left {\lbox} +\permanent\protected\def\spac_align_vertical_right {\rbox} +\permanent\protected\def\spac_align_vertical_middle {\cbox} +\permanent\protected\def\spac_align_vertical_inner {\ibox} +\permanent\protected\def\spac_align_vertical_outer {\obox} +\permanent\protected\def\spac_align_vertical_flushleft {\rbox} +\permanent\protected\def\spac_align_vertical_flushright{\lbox} +\permanent\protected\def\spac_align_vertical_center {\cbox} +\permanent\protected\def\spac_align_vertical_no {\vbox\bgroup\spac_align_set_horizontal_right\let\next=} + +\permanent\protected\def\spac_align_horizontal_left {\doalignedline\v!left} +\permanent\protected\def\spac_align_horizontal_right {\doalignedline\v!right} +\permanent\protected\def\spac_align_horizontal_middle {\doalignedline\v!middle} +\permanent\protected\def\spac_align_horizontal_inner {\doalignedline\v!inner} +\permanent\protected\def\spac_align_horizontal_outer {\doalignedline\v!outer} +\permanent\protected\def\spac_align_horizontal_flushleft {\doalignedline\v!right} +\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} % The next one can be in use so we keep it around but oen should % be aware of possible interference. -\unexpanded\def\setraggedskips#1#2#3#4#5#6#7% never change this name (todo: inline this one .. less tracingall) - {\unexpanded\def\updateraggedskips{\dosetraggedskips{#1}{#2}{#3}{#4}{#5}{#6}{#7}}% +\permanent\protected\def\setraggedskips#1#2#3#4#5#6#7% never change this name (todo: inline this one .. less tracingall) + {\protected\def\updateraggedskips{\dosetraggedskips{#1}{#2}{#3}{#4}{#5}{#6}{#7}}% \updateraggedskips} -\def\dosetraggedskips#1#2#3#4#5#6#7% +\permanent\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 @@ -890,7 +903,7 @@ \expandafter\spac_show_par_data \fi} -\unexpanded\def\showpardata +\permanent\protected\def\showpardata {\edef\thepardata {\hbox{font: \fontname\font}\endgraf \spac_show_par_data @@ -909,24 +922,24 @@ \endgroup \let\showpardata\relax} -\unexpanded\def\startshowpardata +\permanent\protected\def\startshowpardata {\begingroup \showstruts \tracingparagraphs\maxdimen \appendtoksonce\showpardata\to\everypar} -\unexpanded\def\stopshowpardata +\permanent\protected\def\stopshowpardata {\endgraf \endgroup} % Structure: -\unexpanded\def\startalignment +\protected\def\startalignment {\par \begingroup \setupalign} -\unexpanded\def\stopalignment +\protected\def\stopalignment {\par \endgroup} @@ -937,19 +950,19 @@ \newtoks \everyleftofalignedline \newtoks \everyrightofalignedline -\unexpanded\def\shiftalignedline#1#2#3#4% left, right, inner, outer +\permanent\protected\def\shiftalignedline#1#2#3#4% left, right, inner, outer {\rightorleftpageaction {\everyleftofalignedline {\hskip\dimexpr#1+#3\relax}% \everyrightofalignedline{\hskip\dimexpr#2+#4\relax}} {\everyleftofalignedline {\hskip\dimexpr#1+#4\relax}% \everyrightofalignedline{\hskip\dimexpr#2+#3\relax}}} -\def\doalignline#1#2% \\ == newline +\permanent\def\doalignline#1#2% \\ == newline {\noindentation % was \noindent \dontleavehmode % added in marrakesch at TUG 2006\begingroup \begingroup \setlocalhsize % new - \def\\{\egroup\par\doalignline{#1}{#2}\bgroup}% + \enforced\permanent\protected\def\\{\egroup\par\doalignline{#1}{#2}\bgroup}% \dowithnextbox {\hbox to \localhsize {\ifcase\alignstrutmode\or\strut\fi @@ -961,10 +974,10 @@ % plain commands -\ifdefined\line \else \def\line {\hbox to\hsize} \fi -\ifdefined\leftline \else \def\leftline #1{\line{#1\hss}} \fi -\ifdefined\rightline \else \def\rightline #1{\line{\hss#1}} \fi -\ifdefined\centerline \else \def\centerline#1{\line{\hss#1\hss}} \fi +\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 % direct commands @@ -978,36 +991,32 @@ \def\spac_align_wrapper_middle {\doalignline\hss \hss} \def\spac_align_wrapper_handle#1% - %{\csname\??alignwrapper\ifcsname\??alignwrapper#1\endcsname#1\else\v!middle\fi\endcsname} {\ifcsname\??alignwrapper#1\endcsname\expandafter\lastnamedcs\else\expandafter\spac_align_wrapper_middle\fi} -\unexpanded\def\spac_align_wrapper_start[#1]% +\permanent\tolerant\protected\def\startlinealignment[#1]% {\spac_align_wrapper_handle{#1}% \bgroup\ignorespaces} -\unexpanded\def\spac_align_wrapper_stop +\protected\def\spac_align_wrapper_stop {\removeunwantedspaces\egroup} -\unexpanded\def\startlinealignment - {\dosingleempty\spac_align_wrapper_start} - -\let\stoplinealignment\spac_align_wrapper_stop +\permanent\let\stoplinealignment\spac_align_wrapper_stop -\unexpanded\def\startleftaligned {\spac_align_wrapper_start[\v!left ]} \let\stopleftaligned \spac_align_wrapper_stop -\unexpanded\def\startmiddlealigned{\spac_align_wrapper_start[\v!middle]} \let\stopmiddlealigned\spac_align_wrapper_stop -\unexpanded\def\startrightaligned {\spac_align_wrapper_start[\v!right ]} \let\stoprightaligned \spac_align_wrapper_stop -\unexpanded\def\startmaxaligned {\spac_align_wrapper_start[\v!max ]} \let\stopmaxaligned \spac_align_wrapper_stop +\permanent\protected\def\startleftaligned {\startlinealignment[\v!left ]} \permanent\let\stopleftaligned \spac_align_wrapper_stop +\permanent\protected\def\startmiddlealigned{\startlinealignment[\v!middle]} \permanent\let\stopmiddlealigned\spac_align_wrapper_stop +\permanent\protected\def\startrightaligned {\startlinealignment[\v!right ]} \permanent\let\stoprightaligned \spac_align_wrapper_stop +\permanent\protected\def\startmaxaligned {\startlinealignment[\v!max ]} \permanent\let\stopmaxaligned \spac_align_wrapper_stop -\let\startmidaligned \startmiddlealigned \let\stopmidaligned \stopmiddlealigned -\let\startcenteraligned\startmiddlealigned \let\stopcenteraligned\stopmiddlealigned +\aliased\let\startmidaligned \startmiddlealigned \aliased\let\stopmidaligned \stopmiddlealigned +\aliased\let\startcenteraligned\startmiddlealigned \aliased\let\stopcenteraligned\stopmiddlealigned -\unexpanded\def\leftaligned {\spac_align_wrapper_handle\v!left } -\unexpanded\def\middlealigned{\spac_align_wrapper_handle\v!middle} -\unexpanded\def\rightaligned {\spac_align_wrapper_handle\v!right } -\unexpanded\def\maxaligned {\spac_align_wrapper_handle\v!max } +\permanent\protected\def\leftaligned {\spac_align_wrapper_handle\v!left } +\permanent\protected\def\middlealigned{\spac_align_wrapper_handle\v!middle} +\permanent\protected\def\rightaligned {\spac_align_wrapper_handle\v!right } +\permanent\protected\def\maxaligned {\spac_align_wrapper_handle\v!max } -\let\midaligned \middlealigned -\let\centeraligned\middlealigned +\aliased\let\midaligned \middlealigned +\aliased\let\centeraligned\middlealigned \installcorenamespace{alignline} @@ -1019,17 +1028,17 @@ \letvalue{\??alignline\v!center }\midaligned \letvalue{\??alignline\v!max }\maxaligned -\def\doalignedline#1{\resetrealignsignal\csname\??alignline#1\endcsname} +% \permanent\protected\def\doalignedline#1{\resetrealignsignal\csname\??alignline#1\endcsname} %D Experimental (will be redone when floats are redone as it's real messy %D now). It can also be made faster (if needed). -\def\doxalignline#1#2#3#4#5#6% +\permanent\protected\def\doxalignline#1#2#3#4#5#6% {\noindentation % was \noindent \dontleavehmode % added in marrakesch at TUG 2006\begingroup \begingroup \setlocalhsize - \def\\{\egroup\par\doxalignline#1#2#3#4#5#6\bgroup}% inefficient + \enforced\permanent\protected\def\\{\egroup\par\doxalignline#1#2#3#4#5#6\bgroup}% inefficient \dowithnextbox {\hbox to \localhsize {#1\hskip\ifdone#2\else#3\fi#4% @@ -1042,7 +1051,7 @@ \endgroup} \hbox} -\def\doxcheckline % used for floats so multipass anyway +\permanent\protected\def\doxcheckline % used for floats so multipass anyway {\signalrightpage\doifelserightpage\donetrue\donefalse} \setvalue{\??alignline\v!inner }{\doxalignline\doxcheckline++\zeropoint \relax\hss } @@ -1059,11 +1068,9 @@ \setvalue{\??alignline\v!leftedge }{\doxalignline\donefalse --\leftedgetotal \hss \relax} \setvalue{\??alignline\v!rightedge }{\doxalignline\donefalse ++\rightedgetotal \relax\hss } -\def\doalignedline#1% unchecked - {\csname\??alignline#1\endcsname} % no \resetrealignsignal here ? +\permanent\protected\def\doalignedline#1{\csname\??alignline#1\endcsname} % no \resetrealignsignal here ? -\def\alignedline#1#2% setting default - % {\csname\??alignline\ifcsname\??alignline#1\endcsname#1\else#2\fi\endcsname} +\permanent\protected\def\alignedline#1#2% setting default {\ifcsname\??alignline#1\endcsname \expandafter\lastnamedcs \else @@ -1076,15 +1083,12 @@ %D We need to pick up a box (downward compatible in case \type {\bgroup} %D is used (test suite index example). -\unexpanded\def\wordright - {\dosingleempty\spac_word_right} - -\def\spac_word_right[#1]% +\permanent\tolerant\protected\def\wordright[#1]% {\dowithnextbox {\normalexpanded{\spac_word_right_indeed{#1}{\hpack{\thebox\nextbox}}}} \hbox} -\unexpanded\def\spac_word_right_indeed#1#2% +\protected\def\spac_word_right_indeed#1#2% {\registerparwrapper {\v!word:\v!right} {\begingroup @@ -1119,13 +1123,13 @@ % Trick posted by WS on mailing list, generalized a bit. The bottom text only shows % op when there is one line space available. We could add some extra space if needed. -% \unexpanded\def\bottomword +% v\protected\def\bottomword % {\par % \dowithnextbox % {\leaders\box\nextbox\vfil\page} % \vbox to \lineheight} % -% \unexpanded\def\bottomword +% \permanent\protected\def\bottomword % {\par % \groupedcommand % {\leaders @@ -1141,9 +1145,9 @@ % todo: also handle \bgroup ... \egroup -\unexpanded\def\spac_align_simple_left #1{{#1\hss}} -\unexpanded\def\spac_align_simple_right #1{{\hss#1}} -\unexpanded\def\spac_align_simple_middle#1{{\hss#1\hss}} +\protected\def\spac_align_simple_left #1{{#1\hss}} +\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 @@ -1161,7 +1165,7 @@ \letvalue{\??alignsimplereverse\v!flushright}\spac_align_simple_left \letvalue{\??alignsimplereverse\v!middle }\spac_align_simple_middle -\unexpanded\def\simplealignedbox#1#2% +\permanent\protected\def\simplealignedbox#1#2% {\hbox \ifdim#1>\zeropoint to #1 \ifcsname\??alignsimple#2\endcsname \doubleexpandafter\lastnamedcs @@ -1170,7 +1174,7 @@ \fi \fi} -\unexpanded\def\simplealignedspreadbox#1#2% +\permanent\protected\def\simplealignedspreadbox#1#2% {\hbox \ifdim#1>\zeropoint spread #1 \ifcsname\??alignsimple#2\endcsname \doubleexpandafter\lastnamedcs @@ -1179,7 +1183,7 @@ \fi \fi} -\unexpanded\def\simplealignedboxplus#1#2#3% +\permanent\protected\def\simplealignedboxplus#1#2#3% {\hbox #3 \ifdim#1>\zeropoint to #1 \ifcsname\??alignsimple#2\endcsname \doubleexpandafter\lastnamedcs @@ -1190,7 +1194,7 @@ \newconditional\alignsimplelefttoright \settrue\alignsimplelefttoright -\unexpanded\def\simplereversealignedbox#1#2% +\permanent\protected\def\simplereversealignedbox#1#2% {\hbox \ifdim#1>\zeropoint to #1 \ifcsname\??alignsimplereverse#2\endcsname \doubleexpandafter\lastnamedcs @@ -1199,7 +1203,7 @@ \fi \fi} -\unexpanded\def\simplereversealignedboxplus#1#2#3% +\permanent\protected\def\simplereversealignedboxplus#1#2#3% {\hbox #3 \ifdim#1>\zeropoint to #1 \ifcsname\??alignsimplereverse#2\endcsname \doubleexpandafter\lastnamedcs @@ -1220,16 +1224,13 @@ % \setvalue{\??alignsets\v!lohi }#1#2{\let#1\vss \let#2\vss } % \setvalue{\??alignsets\s!unknown }#1#2{\let#1\relax\let#2\relax} % -% \unexpanded\def\spac_align_set_ss#1% +% \protected\def\spac_align_set_ss#1% % {\csname\??alignsetss\ifcsname\??alignsetss#1\endcsname#1\else\s!unknown\fi\endcsname} % Some obsolete (old) helpers: -\unexpanded\def\definehbox - {\dodoubleargument\spac_align_definehbox} - -\def\spac_align_definehbox[#1][#2]% - {\setvalue{hbox#1}##1{\hbox to #2{\begstrut##1\endstrut\hss}}} +\permanent\tolerant\protected\def\definehbox[#1][#2]% + {\ifarguments\else\setvalue{hbox#1}##1{\hbox to #2{\begstrut##1\endstrut\hss}}\fi} %D Some direction related helpers: @@ -1238,6 +1239,6 @@ \setvalue{\??reverse\v!normal }{\ifconditional\inlinelefttoright\else\s!reverse\fi} \setvalue{\??reverse\v!reverse}{\ifconditional\inlinelefttoright \s!reverse\fi} -\def\usedirectionparameterreverse#1{\begincsname\??reverse#1\c!direction\endcsname} +\permanent\def\usedirectionparameterreverse#1{\begincsname\??reverse#1\c!direction\endcsname} \protect \endinput diff --git a/tex/context/base/mkiv/spac-chr.lua b/tex/context/base/mkiv/spac-chr.lua index ac04a4c8e..899d274b4 100644 --- a/tex/context/base/mkiv/spac-chr.lua +++ b/tex/context/base/mkiv/spac-chr.lua @@ -33,7 +33,7 @@ local getnext = nuts.getnext local getprev = nuts.getprev local getattr = nuts.getattr local setattr = nuts.setattr -local getlang = nuts.getlang +local getlanguage = nuts.getlanguage local setchar = nuts.setchar local setattrlist = nuts.setattrlist local getfont = nuts.getfont diff --git a/tex/context/base/mkiv/spac-chr.mkiv b/tex/context/base/mkiv/spac-chr.mkiv index 43a725ae6..9113dc6a1 100644 --- a/tex/context/base/mkiv/spac-chr.mkiv +++ b/tex/context/base/mkiv/spac-chr.mkiv @@ -54,6 +54,8 @@ % Making them active is also not an option unless we do that in every % catcode vector. +\pushoverloadmode + % \nobreakspace {\begingroup\setalignstateattribute\normalUchar"00A0\endgroup} % 1 = left \edef\nobreakspace {\normalUchar"00A0} % space \edef\softhyphen {\normalUchar"00AD} % softhyohen @@ -63,6 +65,9 @@ \let\ideographicspace \enquad \let\ideographichalffillspace \emquad +\unletfrozen\hairspace +\unletfrozen\sixperemspace + \edef\twoperemspace {\normalUchar"2002} % quad/2 % % "2003 % quad == \quad == \hskip\emwidth \edef\threeperemspace {\normalUchar"2004} % quad/3 @@ -88,6 +93,8 @@ \let\zwj \zerowidthjoiner \let\nbsp \nobreakspace +\popoverloadmode + \chardef\optionalspace"1F % will be space unless before punctuation % Shortcuts: diff --git a/tex/context/base/mkiv/spac-grd.mkxl b/tex/context/base/mkiv/spac-grd.mkxl index 3e5030043..fbb02f50c 100644 --- a/tex/context/base/mkiv/spac-grd.mkxl +++ b/tex/context/base/mkiv/spac-grd.mkxl @@ -22,9 +22,9 @@ \installcorenamespace{lastnodepusher} -\let\poplastnode\relax +\permanent\let\poplastnode\relax -\unexpanded\def\pushlastnode +\permanent\protected\def\pushlastnode {\csname\??lastnodepusher \ifcsname\??lastnodepusher\the\lastnodetype\endcsname \the\lastnodetype @@ -34,19 +34,19 @@ \endcsname} \setvalue{\??lastnodepusher\number\kernnodecode}% - {\unexpanded\edef\poplastnode{\kern\the\lastkern\relax}% + {\enforced\permanent\protected\edef\poplastnode{\kern\the\lastkern\relax}% \kern-\lastkern} \setvalue{\??lastnodepusher\number\gluenodecode}% - {\unexpanded\edef\poplastnode{\vskip\the\lastskip\relax}% + {\enforced\permanent\protected\edef\poplastnode{\vskip\the\lastskip\relax}% \vskip-\lastskip} \setvalue{\??lastnodepusher\number\penaltynodecode}% - {\unexpanded\edef\poplastnode{\penalty\the\lastpenalty\relax}% + {\enforced\permanent\protected\edef\poplastnode{\penalty\the\lastpenalty\relax}% \nobreak} \setvalue{\??lastnodepusher\s!unknown}% - {\let\poplastnode\relax} + {\enforced\permanent\let\poplastnode\relax} %D Moved from supp-box: @@ -115,9 +115,6 @@ \ifdim\d_spac_lines_correction_before<\zeropoint\d_spac_lines_correction_before\zeropoint\fi \ifdim\d_spac_lines_correction_after <\zeropoint\d_spac_lines_correction_after \zeropoint\fi} -%unexpanded\def\dotopbaselinecorrection{\kern\d_spac_lines_correction_before} -%unexpanded\def\dobotbaselinecorrection{\kern\d_spac_lines_correction_after } - % experiment, todo: proper mkiv mechanism % % \input ward \par @@ -136,11 +133,11 @@ % to be redone: -\unexpanded\def\dotopbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_before]} -\unexpanded\def\dobotbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_after ]} +\permanent\protected\def\dotopbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_before]} +\permanent\protected\def\dobotbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_after ]} -\def\showbaselinecorrection - {\def\dobaselinecorrection % visualization is not watertight! +\permanent\def\showbaselinecorrection + {\enforced\permanent\protected\def\dobaselinecorrection % visualization is not watertight! {\bgroup \ifdim\prevdepth>\zeropoint \kern-\prevdepth @@ -153,17 +150,15 @@ \ruledvpack{\box\scratchbox}% \egroup \prevdepth\strutdp}% - \def\dotopbaselinecorrection - {\hrule\s!height\d_spac_lines_correction_before}% - \def\dobotbaselinecorrection - {\hrule\s!height\d_spac_lines_correction_after}} + \enforced\permanent\protected\def\dotopbaselinecorrection{\hrule\s!height\d_spac_lines_correction_before}% + \enforced\permanent\protected\def\dobotbaselinecorrection{\hrule\s!height\d_spac_lines_correction_after }} % \def\dobaselinecorrection % beware, this one is redefined below % {\ifdim\prevdepth>\zeropoint\kern-\prevdepth\fi % \kern\strutdp % \prevdepth\strutdp} -\def\baselinecorrection +\permanent\protected\def\baselinecorrection {\endgraf \ifvmode \ifdim\prevdepth<\maxdimen @@ -177,7 +172,7 @@ \fi \fi} -\def\pagebaselinecorrection +\permanent\protected\def\pagebaselinecorrection {\ifdim\pagegoal<\maxdimen \ifdim\pagetotal>\lineheight % or \topskip \scratchdimen\pagetotal @@ -188,35 +183,35 @@ \fi \fi} -\unexpanded\def\startbaselinecorrection +\permanent\protected\def\startbaselinecorrection {\bgroup - \let\stopbaselinecorrection\egroup + \enforced\let\stopbaselinecorrection\egroup \ifcase\baselinecorrectionmode \or % normal \baselinecorrection \ifvmode \setbox\scratchbox\vbox\bgroup\ignorespaces - \let\stopbaselinecorrection\donormalstopbaselinecorrection + \enforced\let\stopbaselinecorrection\donormalstopbaselinecorrection \fi \or % off \or % force \baselinecorrection \ifvmode \setbox\scratchbox\vbox\bgroup\ignorespaces - \let\stopbaselinecorrection\doforcedstopbaselinecorrection + \enforced\let\stopbaselinecorrection\doforcedstopbaselinecorrection \fi \fi} -\let\stopbaselinecorrection\relax +\permanent\let\stopbaselinecorrection\relax -\def\donormalstopbaselinecorrection % I have to check columns yet. +\permanent\protected\def\donormalstopbaselinecorrection % I have to check columns yet. {\egroup \topbaselinecorrection \box\scratchbox \botbaselinecorrection \egroup} -\def\doforcedstopbaselinecorrection % I have to check columns yet. +\permanent\protected\def\doforcedstopbaselinecorrection % I have to check columns yet. {\egroup \forcedtopbaselinecorrection \box\scratchbox @@ -229,31 +224,31 @@ \setnewconstant\baselinecorrectionmode\plusone -\def\onbaselinecorrection {\baselinecorrectionmode\plusone } -\def\offbaselinecorrection {\baselinecorrectionmode\plustwo } -\def\forcebaselinecorrection{\baselinecorrectionmode\plusthree} +\permanent\protected\def\onbaselinecorrection {\baselinecorrectionmode\plusone } +\permanent\protected\def\offbaselinecorrection {\baselinecorrectionmode\plustwo } +\permanent\protected\def\forcebaselinecorrection{\baselinecorrectionmode\plusthree} %D \macros %D {topbaselinecorrection,botbaselinecorrection} %D %D The actual top and bottom corrections are implemented as: -\def\topbaselinecorrection +\permanent\protected\def\topbaselinecorrection {\ifvmode \ifdim\pagegoal<\maxdimen \forcedtopbaselinecorrection \fi \fi} -\def\forcedtopbaselinecorrection - {\ifvmode - \bgroup - \spac_lines_initialize_corrections - \whitespace % no longer ok - \nointerlineskip - \dotopbaselinecorrection - \egroup - \fi} +% \permanent\protected\def\forcedtopbaselinecorrection +% {\ifvmode +% \bgroup +% \spac_lines_initialize_corrections +% \whitespace % no longer ok +% \nointerlineskip +% \dotopbaselinecorrection +% \egroup +% \fi} -\def\botbaselinecorrection +\permanent\protected\def\botbaselinecorrection {\ifvmode \bgroup \spac_lines_initialize_corrections @@ -263,8 +258,6 @@ \egroup \fi} -\let\forcedbotbaselinecorrection\botbaselinecorrection - % nointerlineskip % % startpacked @@ -272,17 +265,17 @@ % \startlinecorrection \framed{test} \stoplinecorrection % \stoppacked -\def\forcedtopbaselinecorrection +\permanent\protected\def\forcedtopbaselinecorrection {\ifvmode \bgroup \spac_lines_initialize_corrections \vspacing[\v!white] -% \nointerlineskip % + %\nointerlineskip % \dotopbaselinecorrection \egroup -\fi} + \fi} -\def\dobaselinecorrection +\permanent\protected\def\dobaselinecorrection {\ifdim\prevdepth>\zeropoint \vspacing[\the\dimexpr-\prevdepth+\strutdp\relax]% \else @@ -290,17 +283,17 @@ \fi \prevdepth\strutdp} -% \def\dobaselinecorrection +% \permanent\protected\def\dobaselinecorrection % {\scratchdimen\dimexpr\ifdim\prevdepth>\zeropoint-\prevdepth+\fi\strutdp\relax % \vspacing[\the\scratchdimen]% % \prevdepth\strutdp} % % some day: % -% \def\dobaselinecorrection +% \permanent\protected\def\dobaselinecorrection % {\clf_checkstrutdepth\strutdp} % -% \def\baselinecorrection +% \permanent\protected\def\baselinecorrection % {\endgraf % \ifvmode % \ifdim\prevdepth<\maxdimen @@ -321,7 +314,7 @@ %D For the moment only with placefloats (should work in mvl and boxes): -\unexpanded\def\checkprevdepth +\permanent\protected\def\checkprevdepth {\endgraf \ifvmode \ifdim\prevdepth<\maxdimen @@ -335,18 +328,22 @@ \let\normalstartbaselinecorrection\startbaselinecorrection -\unexpanded\def\startbaselinecorrection +\pushoverloadmode + +\permanent\protected\def\startbaselinecorrection {\ifgridsnapping \snaptogrid[\v!normal]\vbox\bgroup - \let\stopbaselinecorrection\egroup + \enforced\let\stopbaselinecorrection\egroup \else \normalstartbaselinecorrection \fi} +\popoverloadmode + % This is new (and experimental) and might replace some of the above. beware it doesn't always work % out well, e.g. when used grouped and such (e.g. before display math doesn't work out well). -% \unexpanded\def\fakenextstrutline +% \permanent\protected\def\fakenextstrutline % {\par % \begingroup % \reseteverypar @@ -355,7 +352,7 @@ % \vskip-\struttotal % \endgroup} -% \unexpanded\def\fakenextstrutline +% \permanent\protected\def\fakenextstrutline % {\par % \begingroup % \reseteverypar @@ -366,7 +363,7 @@ % \fi % \endgroup} -% \unexpanded\def\fakenextstrutline +% \permanent\protected\def\fakenextstrutline % {\par % \begingroup % \reseteverypar diff --git a/tex/context/base/mkiv/spac-hor.mkxl b/tex/context/base/mkiv/spac-hor.mkxl index e0fb9e407..c394308f3 100644 --- a/tex/context/base/mkiv/spac-hor.mkxl +++ b/tex/context/base/mkiv/spac-hor.mkxl @@ -30,16 +30,13 @@ %D After a blank or comparable situation (left side floats) we %D need to check if the next paragraph has to be indented. -\unexpanded\def\presetindentation +\permanent\protected\def\presetindentation {\doifoutervmode{\ifconditional\c_spac_indentation_indent_first\else\spac_indentation_variant_no\fi}} -\unexpanded\def\setupindenting +\permanent\protected\def\setupindenting {\doifelsenextoptionalcs\spac_indentation_setup_options\spac_indentation_setup_size} -% \unexpanded\def\spac_indentation_setup_size -% {\assigndimension\v_spac_indentation_current\d_spac_indentation_par{1\emwidth}{1.5\emwidth}{2\emwidth}} - -\unexpanded\def\spac_indentation_setup_size +\protected\def\spac_indentation_setup_size {\assigndimension\v_spac_indentation_current\d_spac_indentation_par{1\emwidth}{1.5\emwidth}{2\emwidth}% \ifzeropt\parindent\else \parindent\d_spac_indentation_par\relax % new per 2019-04-12 : just in case it has been set beforehand @@ -74,7 +71,7 @@ \def\spac_indentation_set_everypar {\everypar{\checkindentation}} -\unexpanded\def\useindentingparameter#1% faster local variant +\permanent\protected\def\useindentingparameter#1% faster local variant {\edef\m_spac_indentation_options{#1\c!indenting}% \ifx\m_spac_indentation_options\empty \else \spac_indentation_setup_indeed @@ -105,37 +102,8 @@ \installcorenamespace {indentingpreset} -\unexpanded\def\defineindenting - {\dodoubleargument\spac_indenting_define} - -\def\spac_indenting_define[#1][#2]% todo: mixes - {\setevalue{\??indentingpreset#1}{#2}} - -% \def\spac_indentation_apply_step_one_nested#1% -% {\expandafter\processcommacommand\expandafter[\csname\??indentingpreset#1\endcsname]\spac_indentation_apply_step_one} -% -% \def\spac_indentation_apply_step_two_nested#1% -% {\expandafter\processcommacommand\expandafter[\csname\??indentingpreset#1\endcsname]\spac_indentation_apply_step_two} -% -% \def\spac_indentation_apply_step_one#1% -% {\ifcsname\??indentingpreset#1\endcsname -% \spac_indentation_apply_step_one_nested{#1}% -% \orelse\ifcsname\??indentingmethod#1\endcsname -% % case two -% \else -% \edef\v_spac_indentation_current{#1}% single entry in list -% \let\normalindentation\v_spac_indentation_current -% \spac_indentation_setup_size -% \fi} -% -% \def\spac_indentation_apply_step_two#1% -% {\ifcsname\??indentingpreset#1\endcsname -% \spac_indentation_apply_step_two_nested{#1}% -% \orelse\ifcsname\??indentingmethod#1\endcsname -% \lastnamedcs -% \else -% % case one -% \fi} +\permanent\tolerant\protected\def\defineindenting[#1]#*[#2]% todo: mixes + {\ifarguments\else\setevalue{\??indentingpreset#1}{#2}\fi} \def\spac_indentation_apply_step_one_nested {\expandafter\processcommacommand\expandafter[\lastnamedcs]\spac_indentation_apply_step_one} @@ -163,14 +131,14 @@ % case one \fi} -\unexpanded\def\indenting % kind of obsolete +\permanent\protected\def\indenting % kind of obsolete {\doifelsenextoptionalcs\spac_indentation_setup_options\relax} % use \noindentation to suppress next indentation \installcorenamespace{indentingmethod} -\unexpanded\def\installindentingmethod#1#2% +\permanent\protected\def\installindentingmethod#1#2% {\setvalue{\??indentingmethod#1}{#2}} \installindentingmethod \v!no {\parindent\zeropoint} @@ -203,8 +171,8 @@ \zeropoint \fi\relax} -\unexpanded\def\noindenting{\indenting[\v!no, \v!next ]} -\unexpanded\def\doindenting{\indenting[\v!yes,\v!first]} +\permanent\protected\def\noindenting{\indenting[\v!no, \v!next ]} +\permanent\protected\def\doindenting{\indenting[\v!yes,\v!first]} %D Here come the handlers (still rather messy ... we need states). @@ -260,19 +228,19 @@ {\spac_indentation_remove \glet\checkindentation\spac_indentation_do_indeed} -\def\spac_indentation_variant_no % made global +\permanent\protected\def\spac_indentation_variant_no % made global {\ifinpagebody \else %\global\indentationfalse \glet\checkindentation\spac_indentation_no_next_check \fi} -\def\nonoindentation % bv bij floats +\permanent\protected\def\nonoindentation % bv bij floats {\ifinpagebody \else %\global\indentationtrue \glet\checkindentation\spac_indentation_do_indeed \fi} -\def\spac_indentation_variant_force +\permanent\protected\def\spac_indentation_variant_force {\ifvmode \ifzeropt\parindent \else % was : \hskip\parindent % can be: \indent @@ -296,27 +264,27 @@ \let\noindentation\spac_indentation_variant_no % public \let\doindentation\spac_indentation_variant_yes % public -\def\dontrechecknextindentation % public (in macros) - {\glet\dorechecknextindentation\relax} +\permanent\protected\def\dontrechecknextindentation % public (in macros) + {\global\enforced\let\dorechecknextindentation\relax} -\let\dorechecknextindentation\relax % public (in macros) +\let\dorechecknextindentation\relax % public (in macros) -\unexpanded\def\spac_indentation_check_next_indentation - {\glet\dorechecknextindentation\relax +\permanent\protected\protected\def\spac_indentation_check_next_indentation + {\global\enforced\let\dorechecknextindentation\relax \doifelsenextchar\par\donothing\spac_indentation_variant_no} % messy check as next is seldom \par \def\spac_indentation_variant_auto - {\glet\dorechecknextindentation\spac_indentation_check_next_indentation} + {\global\enforced\let\dorechecknextindentation\spac_indentation_check_next_indentation} %D This one sets up the local indentation behaviour (i.e. either or not %D a next paragraph will be indented). \installcorenamespace{indentnext} -\unexpanded\def\checknextindentation[#1]% +\permanent\protected\def\checknextindentation[#1]% {\begincsname\??indentnext#1\endcsname} -\unexpanded\def\useindentnextparameter#1% new, the more efficient variant +\permanent\protected\def\useindentnextparameter#1% new, the more efficient variant {\edef\p_indentnext{#1\c!indentnext}% \ifx\p_indentnext\empty\else \begincsname\??indentnext\p_indentnext\endcsname @@ -366,7 +334,7 @@ % maybe an everyforgetparindent -\unexpanded\def\forgetparindent +\permanent\protected\def\forgetparindent {\settrue\c_spac_indentation_indent_first % recently added \d_spac_indentation_par\zeropoint \parindent\zeropoint @@ -376,7 +344,7 @@ \forgetparindent \to \everyforgetall -\unexpanded\def\forgethorizontalstretch +\permanent\protected\def\forgethorizontalstretch {\emergencystretch\zeropoint} \appendtoks @@ -385,7 +353,7 @@ %D Helper: -\unexpanded\def\softbreak +\permanent\protected\def\softbreak {\relax\ifhmode\hskip\parfillskip\break\fi} %D \macros @@ -413,27 +381,33 @@ \sfcode`\?3000 \sfcode`\!3000 \sfcode`\:2000 \sfcode`\;1500 } -\unexpanded\def\frenchspacing {\spac_spacecodes_set_fixed\plusthousand} -\unexpanded\def\newfrenchspacing{\spac_spacecodes_set_fixed{1050}} -\unexpanded\def\nonfrenchspacing{\spac_spacecodes_set_stretch} +\permanent\protected\def\frenchspacing {\spac_spacecodes_set_fixed\plusthousand} +\permanent\protected\def\newfrenchspacing{\spac_spacecodes_set_fixed{1050}} +\permanent\protected\def\nonfrenchspacing{\spac_spacecodes_set_stretch} -\unexpanded\def\installspacingmethod#1#2{\setvalue{\??spacecodemethod#1}{#2}} +\permanent\protected\def\installspacingmethod#1#2{\setvalue{\??spacecodemethod#1}{#2}} \installspacingmethod \empty {} % keep values \installspacingmethod \v!fixed {\frenchspacing } % equal spaces everywhere \installspacingmethod \v!packed {\newfrenchspacing} % slighly more after punctuation \installspacingmethod \v!broad {\nonfrenchspacing} % more depending on what punctuation -\unexpanded\def\setupspacing - {\doifelsenextoptionalcs\spac_spacecodes_setup_yes\spac_spacecodes_setup_nop} - -\def\spac_spacecodes_setup_yes[#1]% - {\begincsname\??spacecodemethod#1\endcsname +%% \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 + \fi \updateraggedskips} -\def\spac_spacecodes_setup_nop - {\updateraggedskips} - %D Here's a tweak .. if needed one can configure it in the configuration %D so that initialization happens more efficient. %D @@ -453,7 +427,7 @@ % This is not needed, as \updateraggedskips is taking care of it: -\let\synchronizespacecodes\spac_spacecodes_setup_nop % \relax +\permanent\protected\def\synchronizespacecodes{\updateraggedskips} % \dorecurse{100}{\recurselevel\spacefactor 800 \space} \par % \dorecurse{100}{\recurselevel\spacefactor1200 \space} \par @@ -476,16 +450,20 @@ %D from now on we treat it as a normal space and not as a space with \type %D {sfcode} 1000. -\unexpanded\def\specialspaceprimitive +\permanent\protected\def\specialspaceprimitive {\begingroup % so, no fancy extra spacing after: foo i.e.\ bar \nonfrenchspacing\normalspaceprimitive \endgroup} -\unexpanded\def\normalnotobeyedspace +\permanent\protected\def\normalnotobeyedspace {\mathortext\normalspaceprimitive\specialspaceprimitive} % no \dontleavehmode\space (else no frenchspacing) -\let\ =\normalnotobeyedspace +\pushoverloadmode + +\overloaded\let\ =\normalnotobeyedspace % so we redefine the primitive! + +\popoverloadmode % Because I strip spaces at the end of lines (in the editor) we need a bit of % a trick to define slash+newline, so \space and \<newline> are the same @@ -508,27 +486,27 @@ % \ruledhbox spread 10pt {\frenchspacing xx dr.~X} % \ruledhbox spread 10pt {\nonfrenchspacing xx dr.~X} -\unexpanded\def\nonbreakablespace{\penalty\plustenthousand\normalspaceprimitive} % no space in math +\permanent\protected\def\nonbreakablespace{\penalty\plustenthousand\normalspaceprimitive} % no space in math \letcatcodecommand \ctxcatcodes \tildeasciicode \nonbreakablespace % overloaded later - \def\space { } -\unexpanded\def\removelastspace{\ifhmode\unskip\fi} -\unexpanded\def\nospace {\removelastspace\ignorespaces} +% \def\space { } +\permanent\protected\def\removelastspace{\ifhmode\unskip\fi} +\permanent\protected\def\nospace {\removelastspace\ignorespaces} \ifdefined\nospaces - \unexpanded\def\nospacing{\normalnospaces\plusone} - \unexpanded\def\dospacing{\normalnospaces\zerocount} + \permanent\protected\def\nospacing{\normalnospaces\plusone} + \permanent\protected\def\dospacing{\normalnospaces\zerocount} \else - \unexpanded\def\nospacing{\spaceskip\scaledpoint \xspaceskip\zeropoint} - \unexpanded\def\dospacing{\spaceskip\currentspaceskip\xspaceskip\zeropoint} % what + \permanent\protected\def\nospacing{\spaceskip\scaledpoint \xspaceskip\zeropoint} + \permanent\protected\def\dospacing{\spaceskip\currentspaceskip\xspaceskip\zeropoint} % what \fi \ifdefined\softhyphen \else \let\softhyphen\explicitdiscretionary \fi -\cldcontext{"\string\\unexpanded\string\\def\string\\\string\n{\string\\space}"} +\cldcontext{"\string\\protected\string\\def\string\\\string\n{\string\\space}"} %cldcontext{"\string\\let\string\\\string\n=\string\\space"} % in tables we need: @@ -537,31 +515,31 @@ % % but, since not all fonts have .5em digits: -\unexpanded\def\fixedspace +\permanent\protected\def\fixedspace {\setbox\scratchbox\hpack{\mathortext{0}{0}}% was \hbox \hskip\wd\scratchbox\relax} -\unexpanded\def\fixedspaces +\permanent\protected\def\fixedspaces {\letcatcodecommand \ctxcatcodes \tildeasciicode\fixedspace - \let~\fixedspace} % we need to renew it + \enforced\let~\fixedspace} % we need to renew it \appendtoks - \let~\space - \let\ \space + \enforced\let~\space + \enforced\let\ \space \to \everysimplifycommands \newsignal\s_spac_keep_unwanted_space % \parindentmode\plusone -\unexpanded\def\keepunwantedspaces +\permanent\protected\def\keepunwantedspaces {\ifhmode \ifdim\lastskip=\s_spac_keep_unwanted_space\else \hskip\s_spac_keep_unwanted_space\relax \fi \fi} -\unexpanded\def\removeunwantedspaces +\permanent\protected\def\removeunwantedspaces {\ifhmode \expandafter \spac_helpers_remove_unwantedspace \fi} @@ -578,7 +556,7 @@ \fi \fi} -\unexpanded\def\onlynonbreakablespace +\permanent\protected\def\onlynonbreakablespace {\ifdim\lastskip=\interwordspace \unskip \nonbreakablespace @@ -609,34 +587,25 @@ %D A couple of plain macros: -\ifdefined\thinspace \else +\ifdefined\enspace \else \permanent\protected\def\enspace{\kern .5\emwidth} \fi +\ifdefined\quad \else \permanent\protected\def\quad {\hskip \emwidth\relax} \fi +\ifdefined\enskip \else \permanent\protected\def\enskip {\hskip.5\emwidth\relax} \fi +\ifdefined\qquad \else \permanent\protected\def\qquad {\hskip 2\emwidth\relax} \fi - \unexpanded\def\thinspace {\kern .16667\emwidth} - \unexpanded\def\negthinspace{\kern-.16667\emwidth} - \unexpanded\def\enspace {\kern .5\emwidth} - -\fi - -\ifdefined\quad \else - - \unexpanded\def\enskip{\hskip.5\emwidth\relax} - \unexpanded\def\quad {\hskip \emwidth\relax} - \unexpanded\def\qquad {\hskip 2\emwidth\relax} - -\fi - -\unexpanded\def\negenspace{\kern-.5\emwidth} -\unexpanded\def\negemspace{\kern- \emwidth} +\permanent\protected\def\negenspace{\kern-.5\emwidth} +\permanent\protected\def\negemspace{\kern- \emwidth} \let\emspace\quad -\unexpanded\def\charspace{ } % the unexpandable \space (as space can also be delimiter for numbers) - -\unexpanded\def\quads - {\dosingleempty\spac_quads} +\permanent\protected\def\charspace{ } % the unexpandable \space (as space can also be delimiter for numbers) -\def\spac_quads[#1]% - {\zwj\dorecurse{\iffirstargument#1\else\plusthree\fi}{\hskip\emwidth\zwj}} +\permanent\tolerant\protected\def\quads[#1]% we do robust checking + {\dontleavehmode + \begingroup + %\scratchcounter\ifparameter#1\or#1\else\plusthree\fi + \scratchcounter\ifchknum#1\or#1\else\plusthree\fi + \zwj\dorecurse\scratchcounter{\hskip\emwidth\zwj}% + \endgroup} % Suggested by GB (not the name -): @@ -652,16 +621,16 @@ \newskip\s_spac_neg_fill \s_spac_neg_fill = \zeropoint \s!plus-1\s!fill \relax \newskip\s_spac_neg_filll \s_spac_neg_filll = \zeropoint \s!plus-1\s!filll\relax -\unexpanded\def\hfilll {\hskip\s_spac_filll\relax} -\unexpanded\def\vfilll {\vskip\s_spac_filll\relax} +\permanent\protected\def\hfilll {\hskip\s_spac_filll\relax} +\permanent\protected\def\vfilll {\vskip\s_spac_filll\relax} -\unexpanded\def\hfillneg {\hskip\s_spac_neg_fill \relax} -\unexpanded\def\hfilllneg{\hskip\s_spac_neg_filll\relax} -\unexpanded\def\vfillneg {\vskip\s_spac_neg_fill \relax} -\unexpanded\def\vfilllneg{\vskip\s_spac_neg_filll\relax} +\permanent\protected\def\hfillneg {\hskip\s_spac_neg_fill \relax} +\permanent\protected\def\hfilllneg{\hskip\s_spac_neg_filll\relax} +\permanent\protected\def\vfillneg {\vskip\s_spac_neg_fill \relax} +\permanent\protected\def\vfilllneg{\vskip\s_spac_neg_filll\relax} -\unexpanded\def\tfskip {\begingroup\tf\hskip\emwidth\endgroup} -\unexpanded\def\dotfskip#1{\begingroup\tf\hskip #1\endgroup} % used elsewhere +\permanent\protected\def\tfskip {\begingroup\tf\hskip\emwidth\endgroup} +\permanent\protected\def\dotfskip#1{\begingroup\tf\hskip #1\endgroup} % used elsewhere % maybe we should hash the analysis @@ -683,14 +652,14 @@ \c!default=\v!middle] \appendtoks - \setuevalue{\e!start\currentnarrower}{\spac_narrower_start{\currentnarrower}}% + \setuevalue{\e!start\currentnarrower}{\spac_narrower_start[\currentnarrower]}% \setuevalue{\e!stop \currentnarrower}{\spac_narrower_stop}% \to \everydefinenarrower -\unexpanded\def\installnarrowermethod#1#2% +\permanent\protected\def\installnarrowermethod#1#2% {\setvalue{\??narrowermethod#1}{#2}} -\unexpanded\def\spac_narrower_method_analyze#1% +\protected\def\spac_narrower_method_analyze#1% {\ifcsname\??narrowermethod#1\endcsname \lastnamedcs \else @@ -712,20 +681,17 @@ \installnarrowermethod \v!none {} \installnarrowermethod \v!reverse {} % never seen -\unexpanded\def\spac_narrower_start#1% +\permanent\overloaded\tolerant\protected\def\spac_narrower_start[#1]#*[#2]% {\begingroup \edef\currentnarrower{#1}% - \dosingleempty\spac_narrower_start_indeed} - -\unexpanded\def\spac_narrower_start_indeed[#1]% - {\iffirstargument - \spac_narrower_start_apply{#1}% + \ifparameter#2\or + \spac_narrower_start_apply{#2}% \else \spac_narrower_start_apply{\narrowerparameter\v!default}% \fi} -\newskip\s_spac_narrower_left_last -\newskip\s_spac_narrower_right_last +\newskip \s_spac_narrower_left_last +\newskip \s_spac_narrower_right_last \newconditional\s_spac_narrower_last_swap \def\spac_narrower_start_apply#1% @@ -736,22 +702,22 @@ \edef\askednarrower{#1}% \ifx\askednarrower\v!reverse \ifconditional\s_spac_narrower_last_swap - \frozen\leftskip \s_spac_narrower_right_last - \frozen\rightskip\s_spac_narrower_left_last + \permanent\leftskip \s_spac_narrower_right_last + \permanent\rightskip\s_spac_narrower_left_last \setfalse\s_spac_narrower_last_swap \else - \frozen\leftskip \s_spac_narrower_left_last - \frozen\rightskip\s_spac_narrower_right_last + \permanent\leftskip \s_spac_narrower_left_last + \permanent\rightskip\s_spac_narrower_right_last \settrue\s_spac_narrower_last_swap \fi \else \normalexpanded{\processcommalistwithparameters[\askednarrower]}\spac_narrower_initialize - \frozen\advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_middle\relax - \frozen\advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_middle\relax + \permanent\advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_middle\relax + \permanent\advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_middle\relax \fi \seteffectivehsize} -\unexpanded\def\spac_narrower_stop +\permanent\protected\def\spac_narrower_stop {\narrowerparameter\c!after \normalexpanded{% \endgroup @@ -764,13 +730,15 @@ \fi }} -\unexpanded\def\startnarrower - {\dosingleempty\spac_narrower_start_basic} +%% \permanent\protected\def\startnarrower +%% {\dosingleempty\spac_narrower_start_basic} +%% +%% \protected\def\spac_narrower_start_basic[#1]% -\unexpanded\def\spac_narrower_start_basic[#1]% +\permanent\tolerant\protected\def\startnarrower[#1]% {\begingroup \let\currentnarrower\empty - \iffirstargument + \ifparameter#1\or \spac_narrower_start_apply{#1}% \else \spac_narrower_start_apply{\narrowerparameter\v!default}% @@ -778,24 +746,26 @@ \let\stopnarrower\spac_narrower_stop -\unexpanded\def\startnarrow % current how - {\begingroup - \dodoubleempty\spac_narrower_start_named} +%% \protected\def\startnarrow % current how +%% {\begingroup +%% \dodoubleempty\spac_narrower_start_named} +%% +%% \def\spac_narrower_start_named +%% {\ifsecondargument +%% \expandafter\spac_narrower_start_named_two +%% \else +%% \expandafter\spac_narrower_start_named_one +%% \fi} -% \def\spac_narrower_start_named[#1][#2]% -% {\edef\currentnarrower{#1}% -% \ifsecondargument -% \spac_narrower_start_apply{#2}% -% \else -% \spac_narrower_start_apply{\narrowerparameter\v!default}% -% \fi} +% can be cleaned up more ... todo -\def\spac_narrower_start_named - {\ifsecondargument +\permanent\tolerant\protected\def\startnarrow[#1]#*[#2]% current how + {\begingroup + \ifnum\lastarguments=\plustwo \expandafter\spac_narrower_start_named_two \else \expandafter\spac_narrower_start_named_one - \fi} + \fi[#1][#2]} \def\spac_narrower_start_named_one[#1]% {\doifelseassignment{#1}\spac_narrower_start_named_one_yes\spac_narrower_start_named_one_nop[#1]} @@ -833,7 +803,7 @@ \newdimen\d_spac_effective_leftskip \def\effectiveleftskip {\dimexpr\leftskip \relax} \newdimen\d_spac_effective_rightskip \def\effectiverightskip{\dimexpr\rightskip\relax} -\unexpanded\def\seteffectivehsize +\permanent\protected\def\seteffectivehsize {\setlocalhsize \d_spac_effective_hsize \localhsize \d_spac_effective_leftskip 1\leftskip @@ -861,16 +831,16 @@ \letcsnamecsname\csname\??skipadaptionleft \v!standard\endcsname\csname\??skipadaptionleft \v!yes\endcsname \letcsnamecsname\csname\??skipadaptionright\v!standard\endcsname\csname\??skipadaptionright\v!yes\endcsname -% \unexpanded\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\csname\??skipadaptionleft #1\endcsname\else#1\fi\relax} -% \unexpanded\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\csname\??skipadaptionright#1\endcsname\else#1\fi\relax} +% \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} -\unexpanded\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname\??skipadaptionleft #1\endcsname\lastnamedcs\else#1\fi\relax} -\unexpanded\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname\??skipadaptionright#1\endcsname\lastnamedcs\else#1\fi\relax} +\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} -\unexpanded\def\doadaptleftskip #1{\normalexpanded{\dosetleftskipadaption {#1}}\frozen\advance\leftskip \leftskipadaption } -\unexpanded\def\doadaptrightskip#1{\normalexpanded{\dosetrightskipadaption{#1}}\frozen\advance\rightskip\rightskipadaption} +\permanent\protected\def\doadaptleftskip #1{\normalexpanded{\dosetleftskipadaption {#1}}\permanent\advance\leftskip \leftskipadaption } +\permanent\protected\def\doadaptrightskip#1{\normalexpanded{\dosetrightskipadaption{#1}}\permanent\advance\rightskip\rightskipadaption} -\unexpanded\def\forgetbothskips +\permanent\protected\def\forgetbothskips {\leftskip\zeropoint \rightskip\zeropoint \relax} @@ -881,7 +851,7 @@ % in spac-ver.mkiv % -% \unexpanded\def\forgetparskip +% \protected\def\forgetparskip % {\s_spac_whitespace_parskip\zeropoint % \parskip\zeropoint % \let\v_spac_whitespace_current\v!none} @@ -894,7 +864,7 @@ \installcorenamespace{tolerancemethods} -\unexpanded\def\installtolerancemethod#1#2#3% +\permanent\protected\def\installtolerancemethod#1#2#3% {\setvalue{\??tolerancemethods#1:#2}{#3}} \installtolerancemethod \v!vertical \v!verystrict {\let\bottomtolerance\empty} @@ -917,13 +887,20 @@ \def\spac_tolerances_step_vertical #1{\csname\??tolerancemethods\v!vertical :#1\endcsname} \def\spac_tolerances_step_horizontal#1{\csname\??tolerancemethods\v!horizontal:#1\endcsname} -\unexpanded\def\setuptolerance - {\dosingleargument\spac_tolerances_setup} - -\def\spac_tolerances_setup[#1]% - {\doifelseinset\v!vertical{#1}% - {\processcommacommand[#1]\spac_tolerances_step_vertical } - {\processcommacommand[#1]\spac_tolerances_step_horizontal}} +%% \protected\def\setuptolerance +%% {\dosingleargument\spac_tolerances_setup} +%% +%% \def\spac_tolerances_setup[#1]% +%% {\doifelseinset\v!vertical{#1}% +%% {\processcommacommand[#1]\spac_tolerances_step_vertical } +%% {\processcommacommand[#1]\spac_tolerances_step_horizontal}} + +\permanent\tolerant\protected\def\setuptolerance[#1]% + {\ifarguments\or + \doifelseinset\v!vertical{#1}% + {\processcommacommand[#1]\spac_tolerances_step_vertical } + {\processcommacommand[#1]\spac_tolerances_step_horizontal}% + \fi} %D \macros %D {pushindentation,popindentation} @@ -933,7 +910,7 @@ \newbox\b_spac_indentations_a \newbox\b_spac_indentations_b -\unexpanded\def\pushindentation +\permanent\protected\def\pushindentation {\begingroup \ifhmode \unskip @@ -948,7 +925,7 @@ \setbox\b_spac_indentations_b\emptybox \fi} -\unexpanded\def\popindentation +\permanent\protected\def\popindentation {\box\b_spac_indentations_b \box\b_spac_indentations_a \endgroup} @@ -1017,16 +994,16 @@ %D \ruledvtop{\typebuffer}} %D \stoptyping -\unexpanded\def\justonespace{\removeunwantedspaces\space} -%unexpanded\def\justaperiod {\removeunwantedspaces.} -%unexpanded\def\justacomma {\removeunwantedspaces,} +\permanent\protected\def\justonespace{\removeunwantedspaces\space} +%frozen\protected\def\justaperiod {\removeunwantedspaces.} +%frozen\protected\def\justacomma {\removeunwantedspaces,} \installcorenamespace{hspace} -\unexpanded\def\ignorecrlf +\permanent\protected\def\ignorecrlf {\let\crlf\justonespace\let\\\crlf} -\unexpanded\def\definehspace +\permanent\protected\def\definehspace {\dotripleempty\spac_hspaces_define} \def\spac_hspaces_define[#1][#2][#3]% #1 = optional namespace @@ -1036,28 +1013,23 @@ \setvalue{\??hspace:#1}{#2}% \fi} -\unexpanded\def\hspace - {\dodoubleempty\spac_hspaces_insert} - -\def\spac_hspaces_insert[#1][#2]% +\permanent\tolerant\protected\def\hspace[#1]#*[#2]% {\ifhmode \removeunwantedspaces \hskip % always a skip even when 0pt - \ifsecondargument + \ifparameter#2\or \hspaceamount{#1}{#2}% - \orelse\iffirstargument + \orelse\ifparameter#1\or \hspaceamount\empty{#1}% \else \hspaceamount\empty\s!default \fi + \relax \expandafter\ignorespaces \fi} -\def\hspaceamount#1#2% - {\dimexpr\ifcsname\??hspace#1:#2\endcsname\lastnamedcs\else\zeropoint\fi\relax} - -\def\directhspaceamount#1% - {\dimexpr\ifcsname\??hspace :#1\endcsname\lastnamedcs\else\zeropoint\fi\relax} +\permanent\overloaded\def\hspaceamount #1#2{\dimexpr\ifcsname\??hspace#1:#2\endcsname\lastnamedcs\else\zeropoint\fi\relax} +\permanent\overloaded\def\directhspaceamount #1{\dimexpr\ifcsname\??hspace :#1\endcsname\lastnamedcs\else\zeropoint\fi\relax} % no installhspace here (this is already an old command) @@ -1071,56 +1043,55 @@ %D Taken from Taco's math module (cq. \AMS\ macros), but %D adapted to \type {\hspace}: -\unexpanded\def\textormathspace #1#2#3{\ifmmode\mskip#1#2\else\kern #1\hspaceamount\empty{#3}\fi\relax} -\unexpanded\def\textormathspacecommand #1#2#3{\ifmmode\mskip#1#2\else#3\fi\relax} -\unexpanded\def\breakabletextormathspace#1#2#3{\ifmmode\mskip#1#2\else\hskip#1\hspaceamount\empty{#3}\fi\relax} +\permanent\protected\def\textormathspace #1#2#3{\ifmmode\mskip#1#2\else\kern #1\hspaceamount\empty{#3}\fi\relax} +\permanent\protected\def\textormathspacecommand #1#2#3{\ifmmode\mskip#1#2\else#3\fi\relax} +\permanent\protected\def\breakabletextormathspace#1#2#3{\ifmmode\mskip#1#2\else\hskip#1\hspaceamount\empty{#3}\fi\relax} \newmuskip\hairmuskip \hairmuskip=.15mu -\unexpanded\def\hairspace {\textormathspace+\hairmuskip{.5}} -\unexpanded\def\thinspace {\textormathspace+\thinmuskip 1} -%unexpanded\def\medspace {\textormathspace+\medmuskip 2} % 4/18 em -\unexpanded\def\thickspace {\textormathspace+\thickmuskip3} -\unexpanded\def\neghairspace {\textormathspace-\thinmuskip{.5}} -\unexpanded\def\negthinspace {\textormathspace-\thinmuskip 1} -\unexpanded\def\negmedspace {\textormathspace-\medmuskip 2} -\unexpanded\def\negthickspace{\textormathspace-\thickmuskip3} - -\unexpanded\edef\medspace {\textormathspacecommand+\medmuskip{\Uchar"205F}} +\overloaded\permanent\protected \def\hairspace {\textormathspace+\hairmuskip{.5}} +\overloaded\permanent\protected \def\thinspace {\textormathspace+\thinmuskip 1} +%overloaded\permanent\protected \def\medspace {\textormathspace+\medmuskip 2} % 4/18 em +\overloaded\permanent\protected \def\thickspace {\textormathspace+\thickmuskip3} +\overloaded\permanent\protected \def\neghairspace {\textormathspace-\thinmuskip{.5}} +\overloaded\permanent\protected \def\negthinspace {\textormathspace-\thinmuskip 1} +\overloaded\permanent\protected \def\negmedspace {\textormathspace-\medmuskip 2} +\overloaded\permanent\protected \def\negthickspace{\textormathspace-\thickmuskip3} +\overloaded\permanent\protected\edef\medspace {\textormathspacecommand+\medmuskip{\Uchar"205F}} % needed for unicode: -%unexpanded\def\breakablethinspace {\breakabletextormathspace+\thinmuskip1} -%unexpanded\def\twoperemspace {\hskip\dimexpr\emwidth/2\relax} % == \enspace -%unexpanded\def\threeperemspace {\hskip\dimexpr\emwidth/3\relax} -%unexpanded\def\fourperemspace {\hskip\dimexpr\emwidth/4\relax} -%unexpanded\def\fiveperemspace {\hskip\dimexpr\emwidth/5\relax} % goodie -%unexpanded\def\sixperemspace {\hskip\dimexpr\emwidth/6\relax} -%unexpanded\def\figurespace {\begingroup\setbox\scratchbox\hbox{0}\hskip\wd\scratchbox\endgroup} % there is a command for this -%unexpanded\def\punctuationspace {\begingroup\setbox\scratchbox\hbox{.}\hskip\wd\scratchbox\endgroup} -%unexpanded\def\ideographicspace {\hskip\dimexpr\emwidth/1\relax} -%unexpanded\def\ideographichalffillspace{\hskip\dimexpr\emwidth/2\relax} -%unexpanded\def\nobreakspace {\penalty\plustenthousand\kern\interwordspace} -%unexpanded\def\narrownobreakspace {\penalty\plustenthousand\thinspace} -%unexpanded\def\zerowidthnobreakspace {\penalty\plustenthousand\kern\zeropoint} -%unexpanded\def\zerowidthspace {\hskip\zeropoint} +%protected\def\breakablethinspace {\breakabletextormathspace+\thinmuskip1} +%protected\def\twoperemspace {\hskip\dimexpr\emwidth/2\relax} % == \enspace +%protected\def\threeperemspace {\hskip\dimexpr\emwidth/3\relax} +%protected\def\fourperemspace {\hskip\dimexpr\emwidth/4\relax} +%protected\def\fiveperemspace {\hskip\dimexpr\emwidth/5\relax} % goodie +%protected\def\sixperemspace {\hskip\dimexpr\emwidth/6\relax} +%protected\def\figurespace {\begingroup\setbox\scratchbox\hbox{0}\hskip\wd\scratchbox\endgroup} % there is a command for this +%protected\def\punctuationspace {\begingroup\setbox\scratchbox\hbox{.}\hskip\wd\scratchbox\endgroup} +%protected\def\ideographicspace {\hskip\dimexpr\emwidth/1\relax} +%protected\def\ideographichalffillspace{\hskip\dimexpr\emwidth/2\relax} +%protected\def\nobreakspace {\penalty\plustenthousand\kern\interwordspace} +%protected\def\narrownobreakspace {\penalty\plustenthousand\thinspace} +%protected\def\zerowidthnobreakspace {\penalty\plustenthousand\kern\zeropoint} +%protected\def\zerowidthspace {\hskip\zeropoint} \definehspace[.5][.1250\emwidth] % hair \definehspace[1] [.1667\emwidth] % thin \definehspace[2] [.2222\emwidth] % med \definehspace[3] [.2777\emwidth] % thick -\let \, \thinspace -\let \: \medspace -\let \; \thickspace -\let \! \negthinspace +\aliased\let \, \thinspace +\aliased\let \: \medspace +\aliased\let \; \thickspace +\aliased\let \! \negthinspace % plain ... % -% \ifdefined\> \else \unexpanded\def\>{\mskip \medmuskip } \fi -% \ifdefined\* \else \unexpanded\def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}} \fi +% \ifdefined\> \else \protected\def\>{\mskip \medmuskip } \fi +% \ifdefined\* \else \protected\def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}} \fi -\def\flexiblespaceamount#1#2#3% +\permanent\def\flexiblespaceamount#1#2#3% {#1\interwordspace \s!plus#2\interwordstretch \s!minus#3\interwordshrink} @@ -1136,37 +1107,37 @@ \installcorenamespace{spacemethods} -\unexpanded\def\installspacemethod#1#2% needs to set \obeyedspace +\permanent\protected\def\installspacemethod#1#2% needs to set \obeyedspace {\setvalue{\??spacemethods#1}{#2}} -\def\activatespacehandler#1% +\permanent\def\activatespacehandler#1% {\csname\??spacemethods\ifcsname\??spacemethods#1\endcsname#1\else\v!off\fi\endcsname} -\unexpanded\def\spac_spaces_checked_control{\mathortext\normalspace{\dontleavehmode{\tt\controlspace}}}% -\unexpanded\def\spac_spaces_checked_normal {\mathortext\normalspace{\dontleavehmode\normalspace}}% -\unexpanded\def\spac_spaces_checked_fixed {\mathortext\normalspace{\dontleavehmode\fixedspace}}% +\permanent\protected\def\spac_spaces_checked_control{\mathortext\normalspace{\dontleavehmode{\tt\controlspace}}}% +\permanent\protected\def\spac_spaces_checked_normal {\mathortext\normalspace{\dontleavehmode\normalspace}}% +\permanent\protected\def\spac_spaces_checked_fixed {\mathortext\normalspace{\dontleavehmode\fixedspace}}% % hm, order matters when we \let in \obeyspaces \installspacemethod \v!on {\obeyspaces - \let\obeyedspace\spac_spaces_checked_control - \let\ =\obeyedspace} + \enforced\let\obeyedspace\spac_spaces_checked_control + \enforced\let\ =\obeyedspace} \installspacemethod \v!yes {\obeyspaces - \let\obeyedspace\spac_spaces_checked_normal - \let\ =\obeyedspace} + \enforced\let\obeyedspace\spac_spaces_checked_normal + \enforced\let\ =\obeyedspace} \installspacemethod \v!off % == default {\normalspaces - \let\obeyedspace\normalspace - \let\ =\normalspaceprimitive} % was \normalspace + \enforced\let\obeyedspace\normalspace + \enforced\let\ =\normalspaceprimitive} % was \normalspace \installspacemethod \v!fixed {\obeyspaces - \let\obeyedspace\spac_spaces_checked_fixed - \let\ =\obeyedspace} + \enforced\let\obeyedspace\spac_spaces_checked_fixed + \enforced\let\ =\obeyedspace} \appendtoks \normalspaces % to be sure @@ -1183,15 +1154,15 @@ %D %D \typebuffer \getbuffer -\unexpanded\def\autoinsertnextspace +\permanent\protected\def\autoinsertnextspace {\futurelet\nexttoken\spac_spaces_auto_insert_next} -\def\spac_spaces_auto_insert_next +\permanent\def\spac_spaces_auto_insert_next {\clf_autonextspace{\normalmeaning\nexttoken}} % todo, just consult nexttoken at the lua end %D Moved from bib module: -\unexpanded\def\outdented#1% +\permanent\protected\def\outdented#1% {\hskip-\hangindent#1\relax} %D Beware: due to char-def this becomes an active character but that @@ -1204,7 +1175,7 @@ % TODO (but used in languages): -\unexpanded\def\spac_glues_text_or_math#1#2% +\def\spac_glues_text_or_math#1#2% {\begingroup \ifmmode \mskip#1% @@ -1215,23 +1186,21 @@ \fi \endgroup} -\unexpanded\def\thinglue {\spac_glues_text_or_math\thinmuskip \v!small} -\unexpanded\def\medglue {\spac_glues_text_or_math\medmuskip \v!medium} -\unexpanded\def\thickglue{\spac_glues_text_or_math\thickmuskip\v!big} +\permanent\protected\def\thinglue {\spac_glues_text_or_math\thinmuskip \v!small} +\permanent\protected\def\medglue {\spac_glues_text_or_math\medmuskip \v!medium} +\permanent\protected\def\thickglue{\spac_glues_text_or_math\thickmuskip\v!big} %D A rather unknown one: -\unexpanded\def\widened % moved from cont-new +\permanent\protected\def\widened % moved from cont-new {\doifelsenextoptionalcs\spac_widened_yes\spac_widened_nop} \def\spac_widened_yes[#1]#2{\hbox \s!spread #1{\hss#2\hss}} \def\spac_widened_nop #1{\hbox \s!spread \emwidth{\hss#1\hss}} -\definecomplexorsimple\widened - %D For the moment here (used in page-txt): -\unexpanded\def\ignoredlinebreak{\unskip\space\ignorespaces} +\protected\def\ignoredlinebreak{\unskip\space\ignorespaces} %D \macros %D {startignorespaces} @@ -1253,14 +1222,14 @@ \newsignal\s_spac_ignore_spaces \newcount \c_spac_ignore_spaces -\unexpanded\def\startignorespaces +\protected\def\startignorespaces {\advance\c_spac_ignore_spaces\plusone \ifcase\c_spac_ignore_spaces\or \ifhmode \hskip\s_spac_ignore_spaces \fi \fi \ignorespaces} -\unexpanded\def\stopignorespaces +\protected\def\stopignorespaces {\ifcase\c_spac_ignore_spaces \or \ifhmode \doloop\spac_ignore_spaces_body @@ -1285,11 +1254,11 @@ %D Something new: -\unexpanded\def\interwordspacebefore{\wordboundary\zwnj\hskip\interwordspace\relax} -\unexpanded\def\interwordspaceafter {\hskip\interwordspace\relax\zwnj\wordboundary} +\protected\def\interwordspacebefore{\wordboundary\zwnj\hskip\interwordspace\relax} +\protected\def\interwordspaceafter {\hskip\interwordspace\relax\zwnj\wordboundary} -\unexpanded\def\interwordspacesbefore#1{\dofastloopcs{#1}\interwordspacebefore} -\unexpanded\def\interwordspacesafter #1{\dofastloopcs{#1}\interwordspaceafter} -\unexpanded\def\interwordspaces #1{\wordboundary\zwnj\dofastloopcs{\numexpr#1+\minusone}\interwordspaceafter} +\protected\def\interwordspacesbefore#1{\dofastloopcs{#1}\interwordspacebefore} +\protected\def\interwordspacesafter #1{\dofastloopcs{#1}\interwordspaceafter} +\protected\def\interwordspaces #1{\wordboundary\zwnj\dofastloopcs{\numexpr#1+\minusone}\interwordspaceafter} \protect \endinput diff --git a/tex/context/base/mkiv/spac-lin.mkiv b/tex/context/base/mkiv/spac-lin.mkiv index 640bcdaae..3d54b630a 100644 --- a/tex/context/base/mkiv/spac-lin.mkiv +++ b/tex/context/base/mkiv/spac-lin.mkiv @@ -171,7 +171,7 @@ \dostoptagged % can be a dummy one as we don't look ahead \par \dostarttagged\t!line\empty - \futurelet\next\spac_lines_between} + \futurelet\nexttoken\spac_lines_between} \unexpanded\def\spac_lines_stop {\dostoptagged @@ -182,10 +182,10 @@ \egroup} \def\spac_lines_between - {\ifx\next\spac_lines_stop + {\ifx\nexttoken\spac_lines_stop \donefalse \else - \doifelsemeaning\next\obeyedline % brrr + \doifelsemeaning\nexttoken\obeyedline % brrr {\donefalse\linesparameter\c!inbetween} {\donetrue\spac_after_first_obeyed_line}% \fi} diff --git a/tex/context/base/mkiv/spac-par.mkiv b/tex/context/base/mkiv/spac-par.mkiv index ee2d9c9cd..752d5c059 100644 --- a/tex/context/base/mkiv/spac-par.mkiv +++ b/tex/context/base/mkiv/spac-par.mkiv @@ -36,7 +36,8 @@ \hangafter \the\hangafter \parskip \the\parskip \leftskip \the\leftskip - \rightskip \the\rightskip}} + \rightskip \the\rightskip + \relax}} \unexpanded\def\pushparagraphproperties {\edef\currentparagraphproperties{\carryoverpar\relax}% diff --git a/tex/context/base/mkiv/spac-par.mkxl b/tex/context/base/mkiv/spac-par.mkxl index e0eef0c67..524e31bc5 100644 --- a/tex/context/base/mkiv/spac-par.mkxl +++ b/tex/context/base/mkiv/spac-par.mkxl @@ -23,93 +23,75 @@ % this might move to syst-ini.mkxl -\setnewconstant\frozenhsizecode "00000001 -\setnewconstant\frozenleftskipcode "00000002 -\setnewconstant\frozenrightskipcode "00000004 -\setnewconstant\frozenhangindentcode "00000008 -\setnewconstant\frozenhangaftercode "00000010 -\setnewconstant\frozenparindentcode "00000020 -\setnewconstant\frozenparfillskipcode "00000040 -\setnewconstant\frozenparfillleftskipcode "00000080 -\setnewconstant\frozenadjustspacingcode "00000100 -\setnewconstant\frozenprotrudecharscode "00000200 -\setnewconstant\frozenpretolerancecode "00000400 -\setnewconstant\frozentolerancecode "00000800 -\setnewconstant\frozenemergencystretchcode "00001000 -\setnewconstant\frozenloosenesscode "00002000 -\setnewconstant\frozenlastlinefitcode "00004000 -\setnewconstant\frozenlinepenaltycode "00008000 -\setnewconstant\frozeninterlinepenaltycode "00010000 -\setnewconstant\frozenclubpenaltycode "00020000 -\setnewconstant\frozenwidowpenaltycode "00040000 -\setnewconstant\frozendisplaywidowpenaltycode "00080000 -\setnewconstant\frozenbrokenpenaltycode "00100000 -\setnewconstant\frozenadjdemeritscode "00200000 -\setnewconstant\frozendoublehyphendemeritscode "00400000 -\setnewconstant\frozenfinalhyphendemeritscode "00800000 -\setnewconstant\frozenparshapecode "01000000 -\setnewconstant\frozeninterlinepenaltiescode "02000000 -\setnewconstant\frozenclubpenaltiescode "04000000 -\setnewconstant\frozenwidowpenaltiescode "08000000 -\setnewconstant\frozendisplaywidowpenaltiescode "10000000 - \setnewconstant\paragraphupdatecodes\numexpr \frozentolerancecode + \frozenloosenesscode + \frozenlinepenaltycode - + \frozeninterlinepenaltycode + \frozenwidowpenaltycode + \frozenclubpenaltycode + \frozenbrokenpenaltycode - + \frozenadjdemeritscode - + \frozendoublehyphendemeritscode - + \frozenfinalhyphendemeritscode - + \frozeninterlinepenaltiescode - + \frozenwidowpenaltiescode - + \frozenclubpenaltiescode + + \frozendemeritscode \relax \setnewconstant\paragraphpenaltycodes\numexpr - \frozeninterlinepenaltycode + \frozenlinepenaltycode + \frozenwidowpenaltycode + \frozenclubpenaltycode + \frozenbrokenpenaltycode - + \frozeninterlinepenaltiescode - + \frozenwidowpenaltiescode - + \frozenclubpenaltiescode \relax \setnewconstant\paragraphdemeritcodes\numexpr - \frozenadjdemeritscode - + \frozendoublehyphendemeritscode - + \frozenfinalhyphendemeritscode + \frozendemeritscode \relax -% + \frozenparskipcode - \setnewconstant\paragraphshapecodes\numexpr - \frozenhangindentcode - + \frozenhangaftercode - + \frozenleftskipcode - + \frozenrightskipcode - + \frozenparfillskipcode - + \frozenparshapecode + \frozenhangcode + + \frozenskipcode + + \frozenparfillcode + + \frozenshapecode \relax -\protected\def\freezeparagraphproperties {\snapshotpar\maxcount} -\protected\def\defrostparagraphproperties{\snapshotpar\zerocount} +\setnewconstant\frozenparagraphdefault\numexpr + \frozenhsizecode % \hsize + + \frozenskipcode % \leftskip \rightskip + + \frozenhangcode % \hangindent \hangafter + + \frozenindentcode % \parindent + + \frozenparfillcode % \parfillskip \parfillleftskip + + \frozenadjustcode % \adjustspacing + + \frozenprotrudecode % \protrudechars + + \frozentolerancecode % \tolerance \pretolerance + + \frozenstretchcode % \emergcystretch + + \frozenloosenesscode % \looseness + + \frozenlastlinecode % \lastlinefit + + \frozenlinepenaltycode % \linepenalty \interlinepenalty \interlinepenalties + + \frozenclubpenaltycode % \clubpenalty \clubpenalties + + \frozenwidowpenaltycode % \widowpenalty \widowpenalties + + \frozendisplaypenaltycode % \displaypenalty \displaypenalties + + \frozenbrokenpenaltycode % \brokenpenalty + + \frozendemeritscode % \doublehyphendemerits \finalhyphendemerits \adjdemerits + + \frozenshapecode % \parshape + % \frozenlinecode % \baselineskip \lineskip \lineskiplimit +\relax + +\setnewconstant\paragraphlinecodes\numexpr + \frozenlinecode +\relax -\protected\def\updateparagraphproperties {\ifhmode\snapshotpar\paragraphupdatecodes \fi} -\protected\def\updateparagraphpenalties {\ifhmode\snapshotpar\paragraphpenaltycodes\fi} -\protected\def\updateparagraphdemerits {\ifhmode\snapshotpar\paragraphdemeritcodes\fi} -\protected\def\updateparagraphshapes {\ifhmode\snapshotpar\paragraphshapecodes \fi} +\permanent\protected\def\freezeparagraphproperties {\snapshotpar\frozenparagraphdefault} +\permanent\protected\def\defrostparagraphproperties{\snapshotpar\zerocount} + +\permanent\protected\def\updateparagraphproperties{\ifhmode\snapshotpar\paragraphupdatecodes \fi} +\permanent\protected\def\updateparagraphpenalties {\ifhmode\snapshotpar\paragraphpenaltycodes\fi} +\permanent\protected\def\updateparagraphdemerits {\ifhmode\snapshotpar\paragraphdemeritcodes\fi} +\permanent\protected\def\updateparagraphshapes {\ifhmode\snapshotpar\paragraphshapecodes \fi} +\permanent\protected\def\updateparagraphlines {\ifhmode\snapshotpar\paragraphlinecodes \fi} % so far \let\spac_paragraph_freeze\relax -\protected\def\setparagraphfreezing {\let\spac_paragraph_freeze\freezeparagraphproperties} -\protected\def\forgetparagraphfreezing {\let\spac_paragraph_freeze\relax} +\permanent\protected\def\setparagraphfreezing {\enforced\let\spac_paragraph_freeze\freezeparagraphproperties} +\permanent\protected\def\forgetparagraphfreezing{\enforced\let\spac_paragraph_freeze\relax} \installcorenamespace {bparwrap} \installcorenamespace {eparwrap} @@ -130,8 +112,8 @@ \wrapuppar{\the\csname\??eparwrap\the\c_spac_paragraph_group_level\endcsname\relax}% \fi} -\protected\def\registerparwrapper {\spac_register_par_wrapper\toksapp\tokspre} -\protected\def\registerparwrapperreverse{\spac_register_par_wrapper\tokspre\toksapp} +\permanent\protected\def\registerparwrapper {\spac_register_par_wrapper\toksapp\tokspre} +\permanent\protected\def\registerparwrapperreverse{\spac_register_par_wrapper\tokspre\toksapp} \protected\def\spac_paragraph_install {\expandafter\newtoks\csname\??bparwrap\the\currentgrouplevel\endcsname @@ -143,10 +125,8 @@ \def\spac_paragraph_install_pair#1#2#3% {\expandafter\newtoks\csname\??parwrapbefore#3\endcsname \expandafter\newtoks\csname\??parwrapafter #3\endcsname - #1\csname\??bparwrap\the\currentgrouplevel\endcsname - {\the\csname\??parwrapbefore#3\endcsname}% - #2\csname\??eparwrap\the\currentgrouplevel\endcsname - {\the\csname\??parwrapafter #3\endcsname}} + #1\csname\??bparwrap\the\currentgrouplevel\endcsname{\the\csname\??parwrapbefore#3\endcsname}% + #2\csname\??eparwrap\the\currentgrouplevel\endcsname{\the\csname\??parwrapafter #3\endcsname}} \def\spac_register_par_wrapper_yes#1#2#3#4#5% {\ifcsname\??bparwrap\the\currentgrouplevel\endcsname \else @@ -162,7 +142,7 @@ \clf_setparwrapper{#3}#4}% #2\csname\??parwrapafter #3\endcsname{#5}% \clf_newparwrapper{#3}% - \let\spac_paragraph_wrap\spac_paragraph_update} + \enforced\let\spac_paragraph_wrap\spac_paragraph_update} \def\spac_register_par_wrapper_nop#1#2#3#4#5% {\ifcsname\??parwrapcount#3\endcsname \else @@ -178,34 +158,21 @@ \expandafter\spac_register_par_wrapper_yes \fi} -\protected\def\forgetparwrapper +\permanent\protected\def\forgetparwrapper {\csname\??bparwrap\the\currentgrouplevel\endcsname\emptytoks \csname\??eparwrap\the\currentgrouplevel\endcsname\emptytoks} -\protected\def\unregisterparwrapper#1% +\permanent\protected\def\unregisterparwrapper#1% {\csname\??parwrapcount#1\endcsname\zerocount \ifcsname\??parwrapbefore#1\endcsname \lastnamedcs\emptytoks \csname\??parwrapafter#1\endcsname\emptytoks \fi} -\def\directparwrapper#1#2% +\permanent\def\directparwrapper#1#2% {#1\wrapuppar{#2}} -% \protected\def\doifelseparwrapper#1% -% {\ifcsname\??parwrapbefore#1\endcsname -% \unless\iftok\lastnamedcs\emptytoks -% \doubleexpandafter\firstoftwoarguments -% \orelse\iftok\csname\??parwrapafter#1\endcsname\emptytoks -% \doubleexpandafter\secondoftwoarguments -% \else -% \doubleexpandafter\firstoftwoarguments -% \fi -% \else -% \expandafter\secondoftwoarguments -% \fi} - -\protected\def\doifelseparwrapper#1% +\permanent\protected\def\doifelseparwrapper#1% {\unless\ifcsname\??parwrapcount#1\endcsname \expandafter\secondoftwoarguments \orelse\ifcase\lastnamedcs @@ -217,7 +184,7 @@ % \getparwrapper % defined in lua % \lastparwrapper % defined in lua -\protected\def\showparwrapperstate#1% +\permanent\protected\def\showparwrapperstate#1% {\begingroup \infofont ¶#1\hilo {\smallinfofont\getparwrapper {#1}}% @@ -230,7 +197,7 @@ \setparagraphfreezing -\appendtoks\let\spac_paragraph_wrap\relax\to\everyforgetall +\appendtoks\enforced\let\spac_paragraph_wrap\relax\to\everyforgetall %D In due time, the code below will be upgraded using the above mechanisms. @@ -240,24 +207,25 @@ %D indentation as set (by the output routine) inside the group are forgotten %D afterwards. (I must not forget its existence). -\def\carryoverpar#1% #1 can be \endgroup or \egroup or ... expandable ! +\permanent\def\carryoverpar#1% #1 can be \endgroup or \egroup or ... expandable ! {\normalexpanded {\noexpand#1% \hangindent\the\hangindent \hangafter \the\hangafter \parskip \the\parskip \leftskip \the\leftskip - \rightskip \the\rightskip}} + \rightskip \the\rightskip + \relax}} -\unexpanded\def\pushparagraphproperties +\permanent\protected\def\pushparagraphproperties {\edef\currentparagraphproperties{\carryoverpar\relax}% \pushmacro\currentparagraphproperties} -\unexpanded\def\popparagraphproperties +\permanent\protected\def\popparagraphproperties {\popmacro\currentparagraphproperties \currentparagraphproperties} -\unexpanded\def\flushparagraphproperties +\permanent\protected\def\flushparagraphproperties {\popmacro\currentparagraphproperties} %D Beware, changing this will break some code (like pos/backgrounds) but it has been @@ -275,10 +243,7 @@ \newconditional\c_spac_paragraphs_intro_next \newconditional\c_spac_paragraphs_intro_each -\unexpanded\def\setupparagraphintro - {\dodoubleempty\spac_paragraphs_intro} - -\unexpanded\def\spac_paragraphs_intro[#1][#2]% +\permanent\protected\tolerant\def\setupparagraphintro[#1]#*[#2]% {\def\spac_paragraphs_intro_step##1% {\csname\??paragraphintro\ifcsname\??paragraphintro##1\endcsname##1\fi\endcsname{#2}}% \processcommacommand[#1]\spac_paragraphs_intro_step} @@ -345,7 +310,7 @@ %D some paragraph \par %D \stoptyping -\unexpanded\def\flushatparagraph#1% +\permanent\protected\def\flushatparagraph#1% {\global\c_spac_paragraphs_intro_first\plusone \gtoksapp\t_spac_paragraphs_intro_first{#1}% \glet\insertparagraphintro\spac_paragraphs_flush_intro} @@ -353,7 +318,7 @@ %D Here comes the flusher (we misuse the one level expansion of token registers to %D feed a nice stream into the paragraph.) -\unexpanded\def\spac_paragraphs_flush_intro % we make sure that the token lists expand directly +\protected\def\spac_paragraphs_flush_intro % we make sure that the token lists expand directly {\normalexpanded{% % after another so the first code is there twice \ifconditional\c_spac_paragraphs_intro_each \ifconditional\c_spac_paragraphs_intro_next @@ -378,7 +343,7 @@ \fi \fi}} -\unexpanded\def\spac_paragraphs_flush_intro_next +\protected\def\spac_paragraphs_flush_intro_next {\normalexpanded{% \global\setfalse\c_spac_paragraphs_intro_next \global\t_spac_paragraphs_intro_next\emptytoks @@ -391,7 +356,7 @@ \the\t_spac_paragraphs_intro_next \fi}} -\unexpanded\def\spac_paragraphs_flush_intro_each +\protected\def\spac_paragraphs_flush_intro_each {\the\t_spac_paragraphs_intro_each} %D \macros @@ -409,11 +374,11 @@ % % \initializeboxstack\??postponednodesstack % -% \unexpanded\def\pushpostponednodedata +% \protected\def\pushpostponednodedata % {\global\advance\c_spac_postponed_data\plusone % \savebox\??postponednodesstack{\the\c_spac_postponed_data}{\box\b_spac_postponed_data}} % -% \unexpanded\def\poppostponednodedata +% \protected\def\poppostponednodedata % {\global\setbox\b_spac_postponed_data\hbox{\foundbox\??postponednodesstack{\the\c_spac_postponed_data}}% % \global\advance\c_spac_postponed_data\minusone % \ifvoid\b_spac_postponed_data\else @@ -422,16 +387,16 @@ \newtoks\everyflushatnextpar -\unexpanded\def\pushpostponednodedata +\permanent\protected\def\pushpostponednodedata {\globalpushbox\b_spac_postponed_data} -\unexpanded\def\poppostponednodedata +\permanent\protected\def\poppostponednodedata {\globalpopbox\b_spac_postponed_data \ifvoid\b_spac_postponed_data\else \glet\flushpostponednodedata\spac_postponed_data_flush \fi} -\unexpanded\def\flushatnextpar +\permanent\protected\def\flushatnextpar {\begingroup \the\everyflushatnextpar \glet\flushpostponednodedata\spac_postponed_data_flush @@ -471,7 +436,7 @@ \glet\flushpostponednodedata\relax }%\fi} -\unexpanded\def\doflushatpar % might be renamed +\permanent\protected\def\doflushatpar % might be renamed {\ifvmode \expandafter\flushatnextpar \else diff --git a/tex/context/base/mkiv/spac-prf.lua b/tex/context/base/mkiv/spac-prf.lua index 7731b21f7..2223c7730 100644 --- a/tex/context/base/mkiv/spac-prf.lua +++ b/tex/context/base/mkiv/spac-prf.lua @@ -17,7 +17,6 @@ local formatters = string.formatters local nodecodes = nodes.nodecodes local gluecodes = nodes.gluecodes local listcodes = nodes.listcodes -local leadercodes = nodes.leadercodes local glyph_code = nodecodes.glyph local disc_code = nodecodes.disc @@ -31,8 +30,7 @@ local math_code = nodecodes.math local rule_code = nodecodes.rule local marginkern_code = nodecodes.marginkern -local leaders_code = leadercodes.leaders - +local leaders_code = gluecodes.leaders local lineskip_code = gluecodes.lineskip local baselineskip_code = gluecodes.baselineskip diff --git a/tex/context/base/mkiv/spac-ver.lmt b/tex/context/base/mkiv/spac-ver.lmt new file mode 100644 index 000000000..bfbcdf772 --- /dev/null +++ b/tex/context/base/mkiv/spac-ver.lmt @@ -0,0 +1,2623 @@ +if not modules then modules = { } end modules ['spac-ver'] = { + version = 1.001, + optimize = true, + comment = "companion to spac-ver.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- we also need to call the spacer for inserts! + +-- somehow lists still don't always have proper prev nodes so i need to +-- check all of the luatex code some day .. maybe i should replece the +-- whole mvl handler by lua code .. why not + +-- todo: use lua nodes with lua data (>0.79) +-- see ** can go when 0.79 + +-- needs to be redone, too many calls and tests now ... still within some +-- luatex limitations + +-- this code dates from the beginning and is kind of experimental; it +-- will be optimized and improved soon .. it's way too complex now but +-- dates from less possibilities +-- +-- the collapser will be redone with user nodes; also, we might get make +-- parskip into an attribute and appy it explicitly thereby getting rid +-- of automated injections; eventually i want to get rid of the currently +-- still needed tex -> lua -> tex > lua chain (needed because we can have +-- expandable settings at the tex end + +-- todo: strip baselineskip around display math + +local next, type, tonumber = next, type, tonumber +local gmatch, concat = string.gmatch, table.concat +local ceil, floor = math.ceil, math.floor +local lpegmatch = lpeg.match +local unpack = unpack or table.unpack +local allocate = utilities.storage.allocate +local todimen = string.todimen +local formatters = string.formatters +local abs = math.abs + +local nodes = nodes +local trackers = trackers +local attributes = attributes +local context = context +local tex = tex + +local texlists = tex.lists +local texget = tex.get +local texgetcount = tex.getcount +local texgetdimen = tex.getdimen +local texset = tex.set +local texsetdimen = tex.setdimen +local texsetcount = tex.setcount +local texnest = tex.nest +local texgetbox = tex.getbox + +local buildpage = tex.triggerbuildpage + +local variables = interfaces.variables +local implement = interfaces.implement + +local v_local = variables["local"] +local v_global = variables["global"] +local v_box = variables.box +----- v_page = variables.page -- reserved for future use +local v_split = variables.split +local v_min = variables.min +local v_max = variables.max +local v_none = variables.none +local v_line = variables.line +local v_noheight = variables.noheight +local v_nodepth = variables.nodepth +local v_line = variables.line +local v_halfline = variables.halfline +local v_line_m = "-" .. v_line +local v_halfline_m = "-" .. v_halfline +local v_first = variables.first +local v_last = variables.last +local v_top = variables.top +local v_bottom = variables.bottom +local v_minheight = variables.minheight +local v_maxheight = variables.maxheight +local v_mindepth = variables.mindepth +local v_maxdepth = variables.maxdepth +local v_offset = variables.offset +local v_strut = variables.strut + +local v_hfraction = variables.hfraction +local v_dfraction = variables.dfraction +local v_bfraction = variables.bfraction +local v_tlines = variables.tlines +local v_blines = variables.blines + +-- vertical space handler + +local trace_vbox_vspacing = false trackers.register("vspacing.vbox", function(v) trace_vbox_vspacing = v end) +local trace_page_vspacing = false trackers.register("vspacing.page", function(v) trace_page_vspacing = v end) +local trace_page_builder = false trackers.register("builders.page", function(v) trace_page_builder = v end) +local trace_collect_vspacing = false trackers.register("vspacing.collect", function(v) trace_collect_vspacing = v end) +local trace_vspacing = false trackers.register("vspacing.spacing", function(v) trace_vspacing = v end) +local trace_vsnapping = false trackers.register("vspacing.snapping", function(v) trace_vsnapping = v end) +local trace_specials = false trackers.register("vspacing.specials", function(v) trace_specials = v end) + +local remove_math_skips = true directives.register("vspacing.removemathskips", function(v) remnove_math_skips = v end) + +local report_vspacing = logs.reporter("vspacing","spacing") +local report_collapser = logs.reporter("vspacing","collapsing") +local report_snapper = logs.reporter("vspacing","snapping") +local report_specials = logs.reporter("vspacing","specials") + +local a_skipcategory = attributes.private('skipcategory') +local a_skippenalty = attributes.private('skippenalty') +local a_skiporder = attributes.private('skiporder') +local a_snapmethod = attributes.private('snapmethod') +local a_snapvbox = attributes.private('snapvbox') + +local nuts = nodes.nuts +local tonut = nuts.tonut +local tonode = nuts.tonode + +local getnext = nuts.getnext +local setlink = nuts.setlink +local getprev = nuts.getprev +local getid = nuts.getid +local getlist = nuts.getlist +local setlist = nuts.setlist +local getattr = nuts.getattr +local getattrs = nuts.getattrs +local setattr = nuts.setattr +local getsubtype = nuts.getsubtype +local getbox = nuts.getbox +local getwhd = nuts.getwhd +local setwhd = nuts.setwhd +local getprop = nuts.getprop +local setprop = nuts.setprop +local getglue = nuts.getglue +local setglue = nuts.setglue +local getkern = nuts.getkern +local getpenalty = nuts.getpenalty +local setshift = nuts.setshift +local setwidth = nuts.setwidth +local getwidth = nuts.getwidth +local setheight = nuts.setheight +local getheight = nuts.getheight +local setdepth = nuts.setdepth +local getdepth = nuts.getdepth +local setnext = nuts.setnext + +local find_node_tail = nuts.tail +local flush_node = nuts.flush_node +local remove_node = nuts.remove +local count_nodes = nuts.countall +local hpack_node = nuts.hpack +local vpack_node = nuts.vpack +local start_of_par = nuts.start_of_par + +local write_node = nuts.write + +local nextnode = nuts.traversers.node +local nexthlist = nuts.traversers.hlist + +local nodereference = nuts.reference + +local theprop = nuts.theprop + +local listtoutf = nodes.listtoutf +local nodeidstostring = nodes.idstostring + +local nodepool = nuts.pool + +local new_penalty = nodepool.penalty +local new_kern = nodepool.kern +local new_glue = nodepool.glue +local new_rule = nodepool.rule + +local nodecodes = nodes.nodecodes +local gluecodes = nodes.gluecodes +----- penaltycodes = nodes.penaltycodes +----- listcodes = nodes.listcodes + +local penalty_code = nodecodes.penalty +local kern_code = nodecodes.kern +local glue_code = nodecodes.glue +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local rule_code = nodecodes.rule +local par_code = nodecodes.par + +local userskip_code = gluecodes.userskip +local lineskip_code = gluecodes.lineskip +local baselineskip_code = gluecodes.baselineskip +local parskip_code = gluecodes.parskip +local topskip_code = gluecodes.topskip +local splittopskip_code = gluecodes.splittopskip + +local linelist_code = nodes.listcodes.line + +local properties = nodes.properties.data + +local vspacing = builders.vspacing or { } +builders.vspacing = vspacing + +local vspacingdata = vspacing.data or { } +vspacing.data = vspacingdata + +local snapmethods = vspacingdata.snapmethods or { } +vspacingdata.snapmethods = snapmethods + +storage.register("builders/vspacing/data/snapmethods", snapmethods, "builders.vspacing.data.snapmethods") + +do + + local default = { + [v_maxheight] = true, + [v_maxdepth] = true, + [v_strut] = true, + [v_hfraction] = 1, + [v_dfraction] = 1, + [v_bfraction] = 0.25, + } + + local fractions = { + [v_minheight] = v_hfraction, [v_maxheight] = v_hfraction, + [v_mindepth] = v_dfraction, [v_maxdepth] = v_dfraction, + [v_box] = v_bfraction, + [v_top] = v_tlines, [v_bottom] = v_blines, + } + + local values = { + offset = "offset" + } + + local colonsplitter = lpeg.splitat(":") + + local function listtohash(str) + local t = { } + for s in gmatch(str,"[^, ]+") do + local key, detail = lpegmatch(colonsplitter,s) + local v = variables[key] + if v then + t[v] = true + if detail then + local k = fractions[key] + if k then + detail = tonumber("0" .. detail) + if detail then + t[k] = detail + end + else + k = values[key] + if k then + detail = todimen(detail) + if detail then + t[k] = detail + end + end + end + end + else + detail = tonumber("0" .. key) + if detail then + t[v_hfraction] = detail + t[v_dfraction] = detail + end + end + end + if next(t) then + t[v_hfraction] = t[v_hfraction] or 1 + t[v_dfraction] = t[v_dfraction] or 1 + return t + else + return default + end + end + + function vspacing.definesnapmethod(name,method) + local n = #snapmethods + 1 + local t = listtohash(method) + snapmethods[n] = t + t.name = name -- not interfaced + t.specification = method -- not interfaced + context(n) + end + +end + +local function validvbox(parentid,list) + if parentid == hlist_code then + local id = getid(list) + if id == par_code and start_of_par(list) then + list = getnext(list) + if not next then + return nil + end + end + local done = nil + for n, id in nextnode, list do + if id == vlist_code or id == hlist_code then + if done then + return nil + else + done = n + end + elseif id == glue_code or id == penalty_code then + -- go on + else + return nil -- whatever + end + end + if done then + local id = getid(done) + if id == hlist_code then + return validvbox(id,getlist(done)) + end + end + return done -- only one vbox + end +end + +local function already_done(parentid,list,a_snapmethod) -- todo: done when only boxes and all snapped + -- problem: any snapped vbox ends up in a line + if list and parentid == hlist_code then + local id = getid(list) + if id == par_code and start_of_par(list) then + list = getnext(list) + if not list then + return false + end + end + for n, id in nextnode, list do + if id == hlist_code or id == vlist_code then + -- local a = getattr(n,a_snapmethod) + -- if not a then + -- -- return true -- not snapped at all + -- elseif a == 0 then + -- return true -- already snapped + -- end + local p = getprop(n,"snapper") + if p then + return p + end + elseif id == glue_code or id == penalty_code then -- or id == kern_code then + -- go on + else + return false -- whatever + end + end + end + return false +end + +-- quite tricky: ceil(-something) => -0 + +local function ceiled(n) + if n < 0 or n < 0.01 then + return 0 + else + return ceil(n) + end +end + +local function floored(n) + if n < 0 or n < 0.01 then + return 0 + else + return floor(n) + end +end + +-- check variables.none etc + +local function fixedprofile(current) + local profiling = builders.profiling + return profiling and profiling.fixedprofile(current) +end + +local function snap_hlist(where,current,method,height,depth) -- method[v_strut] is default + if fixedprofile(current) then + return + end + local list = getlist(current) + local t = trace_vsnapping and { } + if t then + t[#t+1] = formatters["list content: %s"](listtoutf(list)) + t[#t+1] = formatters["snap method: %s"](method.name) -- not interfaced + t[#t+1] = formatters["specification: %s"](method.specification) -- not interfaced + end + local snapht, snapdp + if method[v_local] then + -- snapping is done immediately here + snapht = texgetdimen("bodyfontstrutheight") + snapdp = texgetdimen("bodyfontstrutdepth") + if t then + t[#t+1] = formatters["local: snapht %p snapdp %p"](snapht,snapdp) + end + elseif method[v_global] then + snapht = texgetdimen("globalbodyfontstrutheight") + snapdp = texgetdimen("globalbodyfontstrutdepth") + if t then + t[#t+1] = formatters["global: snapht %p snapdp %p"](snapht,snapdp) + end + else + -- maybe autolocal + -- snapping might happen later in the otr + snapht = texgetdimen("globalbodyfontstrutheight") + snapdp = texgetdimen("globalbodyfontstrutdepth") + local lsnapht = texgetdimen("bodyfontstrutheight") + local lsnapdp = texgetdimen("bodyfontstrutdepth") + if snapht ~= lsnapht and snapdp ~= lsnapdp then + snapht, snapdp = lsnapht, lsnapdp + end + if t then + t[#t+1] = formatters["auto: snapht %p snapdp %p"](snapht,snapdp) + end + end + + local wd, ht, dp = getwhd(current) + + local h = (method[v_noheight] and 0) or height or ht + local d = (method[v_nodepth] and 0) or depth or dp + local hr = method[v_hfraction] or 1 + local dr = method[v_dfraction] or 1 + local br = method[v_bfraction] or 0 + local ch = h + local cd = d + local tlines = method[v_tlines] or 1 + local blines = method[v_blines] or 1 + local done = false + local plusht = snapht + local plusdp = snapdp + local snaphtdp = snapht + snapdp + local extra = 0 + + if t then + t[#t+1] = formatters["hlist: wd %p ht %p (used %p) dp %p (used %p)"](wd,ht,h,dp,d) + t[#t+1] = formatters["fractions: hfraction %s dfraction %s bfraction %s tlines %s blines %s"](hr,dr,br,tlines,blines) + end + + if method[v_box] then + local br = 1 - br + if br < 0 then + br = 0 + elseif br > 1 then + br = 1 + end + local n = ceiled((h+d-br*snapht-br*snapdp)/snaphtdp) + local x = n * snaphtdp - h - d + plusht = h + x / 2 + plusdp = d + x / 2 + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_box,plusht,plusdp) + end + elseif method[v_max] then + local n = ceiled((h+d)/snaphtdp) + local x = n * snaphtdp - h - d + plusht = h + x / 2 + plusdp = d + x / 2 + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_max,plusht,plusdp) + end + elseif method[v_min] then + -- we catch a lone min + if method.specification ~= v_min then + local n = floored((h+d)/snaphtdp) + local x = n * snaphtdp - h - d + plusht = h + x / 2 + plusdp = d + x / 2 + if plusht < 0 then + plusht = 0 + end + if plusdp < 0 then + plusdp = 0 + end + end + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_min,plusht,plusdp) + end + elseif method[v_none] then + plusht, plusdp = 0, 0 + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_none,0,0) + end + end + -- for now, we actually need to tag a box and then check at several points if something ended up + -- at the top of a page + if method[v_halfline] then -- extra halfline + extra = snaphtdp/2 + plusht = plusht + extra + plusdp = plusdp + extra + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_halfline,plusht,plusdp) + end + end + if method[v_line] then -- extra line + extra = snaphtdp + plusht = plusht + extra + plusdp = plusdp + extra + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_line,plusht,plusdp) + end + end + if method[v_halfline_m] then -- extra halfline + extra = - snaphtdp/2 + plusht = plusht + extra + plusdp = plusdp + extra + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_halfline_m,plusht,plusdp) + end + end + if method[v_line_m] then -- extra line + extra = - snaphtdp + plusht = plusht + extra + plusdp = plusdp + extra + if t then + t[#t+1] = formatters["%s: plusht %p plusdp %p"](v_line_m,plusht,plusdp) + end + end + if method[v_first] then + local thebox = current + local id = getid(thebox) + if id == hlist_code then + thebox = validvbox(id,getlist(thebox)) + id = thebox and getid(thebox) + end + if thebox and id == vlist_code then + local list = getlist(thebox) + local lw, lh, ld + for n in nexthlist, list do + lw, lh, ld = getwhd(n) + break + end + if lh then + local wd, ht, dp = getwhd(thebox) + if t then + t[#t+1] = formatters["first line: height %p depth %p"](lh,ld) + t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp) + end + local delta = h - lh + ch, cd = lh, delta + d + h, d = ch, cd + local shifted = hpack_node(getlist(current)) + setshift(shifted,delta) + setlist(current,shifted) + done = true + if t then + t[#t+1] = formatters["first: height %p depth %p shift %p"](ch,cd,delta) + end + elseif t then + t[#t+1] = "first: not done, no content" + end + elseif t then + t[#t+1] = "first: not done, no vbox" + end + elseif method[v_last] then + local thebox = current + local id = getid(thebox) + if id == hlist_code then + thebox = validvbox(id,getlist(thebox)) + id = thebox and getid(thebox) + end + if thebox and id == vlist_code then + local list = getlist(thebox) + local lw, lh, ld + for n in nexthlist, list do + lw, lh, ld = getwhd(n) + end + if lh then + local wd, ht, dp = getwhd(thebox) + if t then + t[#t+1] = formatters["last line: height %p depth %p" ](lh,ld) + t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp) + end + local delta = d - ld + cd, ch = ld, delta + h + h, d = ch, cd + local shifted = hpack_node(getlist(current)) + setshift(shifted,delta) + setlist(current,shifted) + done = true + if t then + t[#t+1] = formatters["last: height %p depth %p shift %p"](ch,cd,delta) + end + elseif t then + t[#t+1] = "last: not done, no content" + end + elseif t then + t[#t+1] = "last: not done, no vbox" + end + end + if method[v_minheight] then + ch = floored((h-hr*snapht)/snaphtdp)*snaphtdp + plusht + if t then + t[#t+1] = formatters["minheight: %p"](ch) + end + elseif method[v_maxheight] then + ch = ceiled((h-hr*snapht)/snaphtdp)*snaphtdp + plusht + if t then + t[#t+1] = formatters["maxheight: %p"](ch) + end + else + ch = plusht + if t then + t[#t+1] = formatters["set height: %p"](ch) + end + end + if method[v_mindepth] then + cd = floored((d-dr*snapdp)/snaphtdp)*snaphtdp + plusdp + if t then + t[#t+1] = formatters["mindepth: %p"](cd) + end + elseif method[v_maxdepth] then + cd = ceiled((d-dr*snapdp)/snaphtdp)*snaphtdp + plusdp + if t then + t[#t+1] = formatters["maxdepth: %p"](cd) + end + else + cd = plusdp + if t then + t[#t+1] = formatters["set depth: %p"](cd) + end + end + if method[v_top] then + ch = ch + tlines * snaphtdp + if t then + t[#t+1] = formatters["top height: %p"](ch) + end + end + if method[v_bottom] then + cd = cd + blines * snaphtdp + if t then + t[#t+1] = formatters["bottom depth: %p"](cd) + end + end + local offset = method[v_offset] + if offset then + -- we need to set the attr + if t then + local wd, ht, dp = getwhd(current) + t[#t+1] = formatters["before offset: %p (width %p height %p depth %p)"](offset,wd,ht,dp) + end + local shifted = hpack_node(getlist(current)) + setshift(shifted,offset) + setlist(current,shifted) + if t then + local wd, ht, dp = getwhd(current) + t[#t+1] = formatters["after offset: %p (width %p height %p depth %p)"](offset,wd,ht,dp) + end + setattr(shifted,a_snapmethod,0) + setattr(current,a_snapmethod,0) + end + if not height then + setheight(current,ch) + if t then + t[#t+1] = formatters["forced height: %p"](ch) + end + end + if not depth then + setdepth(current,cd) + if t then + t[#t+1] = formatters["forced depth: %p"](cd) + end + end + local lines = (ch+cd)/snaphtdp + if t then + local original = (h+d)/snaphtdp + local whatever = (ch+cd)/(texgetdimen("globalbodyfontstrutheight") + texgetdimen("globalbodyfontstrutdepth")) + t[#t+1] = formatters["final lines : %p -> %p (%p)"](original,lines,whatever) + t[#t+1] = formatters["final height: %p -> %p"](h,ch) + t[#t+1] = formatters["final depth : %p -> %p"](d,cd) + end +-- todo: +-- +-- if h < 0 or d < 0 then +-- h = 0 +-- d = 0 +-- end + if t then + report_snapper("trace: %s type %s\n\t%\n\tt",where,nodecodes[getid(current)],t) + end + if not method[v_split] then + -- so extra will not be compensated at the top of a page + extra = 0 + end + return h, d, ch, cd, lines, extra +end + +local categories = { + [0] = "discard", + [1] = "largest", + [2] = "force", + [3] = "penalty", + [4] = "add", + [5] = "disable", + [6] = "nowhite", + [7] = "goback", + [8] = "packed", + [9] = "overlay", + [10] = "enable", + [11] = "notopskip", +} + +categories = allocate(table.swapped(categories,categories)) +vspacing.categories = categories + +function vspacing.tocategories(str) + local t = { } + for s in gmatch(str,"[^, ]") do -- use lpeg instead + local n = tonumber(s) + if n then + t[categories[n]] = true + else + t[b] = true + end + end + return t +end + +function vspacing.tocategory(str) -- can be optimized + if type(str) == "string" then + return set.tonumber(vspacing.tocategories(str)) + else + return set.tonumber({ [categories[str]] = true }) + end +end + +vspacingdata.map = vspacingdata.map or { } -- allocate ? +vspacingdata.skip = vspacingdata.skip or { } -- allocate ? + +storage.register("builders/vspacing/data/map", vspacingdata.map, "builders.vspacing.data.map") +storage.register("builders/vspacing/data/skip", vspacingdata.skip, "builders.vspacing.data.skip") + +do + + local P, C, R, S, Cc, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Cs + + vspacing.fixed = false + + local map = vspacingdata.map + local skip = vspacingdata.skip + + local sign = S("+-")^0 + local multiplier = C(sign * R("09")^1) * P("*") + local singlefier = Cs(sign * Cc(1)) + local separator = S(", ") + local category = P(":") * C((1-separator)^1) + local keyword = C((1-category-separator)^1) + local splitter = (multiplier + Cc(1)) * keyword * (category + Cc(false)) + + local k_fixed = variables.fixed + local k_flexible = variables.flexible + local k_category = "category" + local k_penalty = "penalty" + local k_order = "order" + + function vspacing.setmap(from,to) + map[from] = to + end + + function vspacing.setskip(key,value,grid) + if value ~= "" then + if grid == "" then grid = value end + skip[key] = { value, grid } + end + end + + do -- old variant + + local ctx_fixedblankskip = context.fixedblankskip + local ctx_flexibleblankskip = context.flexibleblankskip + local ctx_setblankcategory = context.setblankcategory + local ctx_setblankorder = context.setblankorder + local ctx_setblankpenalty = context.setblankpenalty + ----- ctx_setblankhandling = context.setblankhandling + local ctx_flushblankhandling = context.flushblankhandling + local ctx_addpredefinedblankskip = context.addpredefinedblankskip + local ctx_addaskedblankskip = context.addaskedblankskip + local ctx_setblankpacked = context.setblankpacked + + local ctx_pushlogger = context.pushlogger + local ctx_startblankhandling = context.startblankhandling + local ctx_stopblankhandling = context.stopblankhandling + local ctx_poplogger = context.poplogger + + local pattern = nil + + local packed = categories.packed + + local function handler(amount, keyword, detail) + if not keyword then + report_vspacing("unknown directive %a",s) + else + local mk = map[keyword] + if mk then + lpegmatch(pattern,mk) + elseif keyword == k_fixed then + ctx_fixedblankskip() + elseif keyword == k_flexible then + ctx_flexibleblankskip() + elseif keyword == k_category then + local category = tonumber(detail) + if category == packed then + ctx_setblankpacked() + elseif category then + ctx_setblankcategory(category) + ctx_flushblankhandling() + end + elseif keyword == k_order and detail then + local order = tonumber(detail) + if order then + ctx_setblankorder(order) + end + elseif keyword == k_penalty and detail then + local penalty = tonumber(detail) + if penalty then + ctx_setblankpenalty(penalty) + end + else + amount = tonumber(amount) or 1 + local sk = skip[keyword] + if sk then + ctx_addpredefinedblankskip(amount,keyword) + else -- no check + ctx_addaskedblankskip(amount,keyword) + end + end + end + end + + local splitter = ((multiplier + singlefier) * keyword * (category + Cc(false))) / handler + pattern = (splitter + separator^1)^0 + + function vspacing.analyze(str) + if trace_vspacing then + ctx_pushlogger(report_vspacing) + ctx_startblankhandling() + lpegmatch(pattern,str) + ctx_stopblankhandling() + ctx_poplogger() + else + ctx_startblankhandling() + lpegmatch(pattern,str) + ctx_stopblankhandling() + end + end + + end + + do -- new variant + + local expandmacro = token.expand_macro + -- local runlocal = tex.runlocal + -- local setmacro = tokens.setters.macro + -- local settoks = tex.settoks + local toscaled = tex.toscaled + + local setattrs = nuts.setattrs + + local b_done = false + local b_packed = false + + local b_amount = 0 + local b_stretch = 0 + local b_shrink = 0 + local b_category = false + local b_penalty = false + local b_order = false + local b_fixed = false + local b_grid = false + + local pattern = nil + + local packed = categories.packed + + local gluefactor = .25 + + local ctx_ignoreparskip = context.core.ignoreparskip + + -- local ctx_vspacingfromtempstring = context.core.vspacingfromtempstring + -- local ctx_vspacingfromscratchtoks = context.core.vspacingfromscratchtoks + + -- local ctx_vspacingpredefinedvalue = context.core.vspacingpredefinedvalue + -- + -- local cache = table.setmetatableindex(function(t,k) + -- local v = function() ctx_vspacingpredefinedvalue(k) end + -- t[k] = v + -- return v + -- end) + + local function before() + b_amount = 0 + b_stretch = 0 + b_shrink = 0 + b_category = 1 + b_penalty = false + b_order = false + b_fixed = b_grid + end + + local function after() + if fixed then + b_stretch = 0 + b_shrink = 0 + else + b_stretch = gluefactor * b_amount + b_shrink = gluefactor * b_amount + end + end + + -- use a cache for predefined ones + + -- local function inject() + -- local n = new_glue(b_amount,b_stretch,b_shrink) + -- if b_category then + -- setattr(n,a_skipcategory,b_category) + -- end + -- if b_penalty then + -- setattr(n,a_skippenalty,b_penalty) + -- end + -- if b_order then + -- setattr(n,a_skiporder,b_order or 1) + -- end + -- write_node(n) + -- end + + local function inject() + local n = new_glue(b_amount,b_stretch,b_shrink) + setattrs(n,false,a_skipcategory,b_category,a_skippenalty,b_penalty,a_skiporder,b_order or 1) + write_node(n) + end + + local function flush() + after() + if b_done then + inject() + b_done = false + end + before() + end + + -- local cmd = token.create("vspacingfromtempstring") + local cmd = token.create("vspacingpredefinedvalue") + + local function handler(amount, keyword, detail) + if not keyword then + report_vspacing("unknown directive %a",s) + else + local mk = map[keyword] + if mk then + lpegmatch(pattern,mk) + elseif keyword == k_fixed then + b_fixed = true + elseif keyword == k_flexible then + b_flexible = false + elseif keyword == k_category then + local category = tonumber(detail) + if category == packed then + b_packed = true + elseif category then + b_category = category + b_done = true + flush() + end + elseif keyword == k_order and detail then + local order = tonumber(detail) + if order then + b_order = order + end + elseif keyword == k_penalty and detail then + local penalty = tonumber(detail) + if penalty then + flush() + b_done = true + b_category = 3 + b_penalty = penalty + flush() + end + else + amount = tonumber(amount) or 1 + local sk = skip[keyword] + if sk then + -- amount, keyword + b_done = true + -- best, for now, todo: runlocal with arguments + -- expandmacro("vspacingpredefinedvalue",true,keyword) + expandmacro(cmd,true,keyword) + -- setmacro("tempstring",keyword) + -- runlocal(cmd) + -- nicest + -- runlocal(cache[keyword]) + -- fast + -- settoks("scratchtoks",keyword) + -- runlocal("vspacingfromscratchtoks") + -- middleground + -- setmacro("tempstring",keyword) + -- runlocal(ctx_vspacingfromtempstring) + -- + b_amount = b_amount + amount * texgetdimen("scratchdimen") + else -- no check + b_done = true + b_amount = b_amount + amount * toscaled(keyword) + end + end + end + end + + -- alternatively we can make a table and have a keyword -> split cache but this is probably + -- not really a bottleneck + + local splitter = ((multiplier + singlefier) * keyword * (category + Cc(false))) / handler + pattern = (splitter + separator^1)^0 + + function vspacing.inject(grid,str) + if trace_vspacing then + -- ctx_pushlogger(report_vspacing) + end + b_done = false + b_packed = false + b_grid = gridsnapping + before() + lpegmatch(pattern,str) + after() + if b_done then + inject() + end + if b_packed then + ctx_ignoreparskip() + end + if trace_vspacing then + -- ctx_poplogger() + end + end + + function vspacing.injectpenalty(penalty) + local n = new_glue() + setattrs(n,false,a_skipcategory,categories.penalty,a_skippenalty,penalty,a_skiporder,1) + write_node(n) + end + + function vspacing.injectskip(amount) + local n = new_glue(amount) + setattrs(n,false,a_skipcategory,categories.largest,a_skippenalty,false,a_skiporder,1) + write_node(n) + end + + function vspacing.injectdisable(amount) + local n = new_glue() + setattrs(n,false,a_skipcategory,categories.disable,a_skippenalty,false,a_skiporder,1) + write_node(n) + end + + end + +end + +-- implementation + +-- alignment box begin_of_par vmode_par hmode_par insert penalty before_display after_display + +function vspacing.snapbox(n,how) + local sv = snapmethods[how] + if sv then + local box = getbox(n) + local list = getlist(box) + if list then + local s = getattr(list,a_snapmethod) + if s == 0 then + if trace_vsnapping then + -- report_snapper("box list not snapped, already done") + end + else + local wd, ht, dp = getwhd(box) + if false then -- todo: already_done + -- assume that the box is already snapped + if trace_vsnapping then + report_snapper("box list already snapped at (%p,%p): %s", + ht,dp,listtoutf(list)) + end + else + local h, d, ch, cd, lines, extra = snap_hlist("box",box,sv,ht,dp) + setprop(box,"snapper",{ + ht = h, + dp = d, + ch = ch, + cd = cd, + extra = extra, + current = current, + }) + setwhd(box,wd,ch,cd) + if trace_vsnapping then + report_snapper("box list snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s", + h,d,ch,cd,sv.name,sv.specification,"direct",lines,listtoutf(list)) + end + setattr(box,a_snapmethod,0) -- + setattr(list,a_snapmethod,0) -- yes or no + end + end + end + end +end + +-- I need to figure out how to deal with the prevdepth that crosses pages. In fact, +-- prevdepth is often quite interfering (even over a next paragraph) so I need to +-- figure out a trick. Maybe use something other than a rule. If we visualize we'll +-- see the baselineskip in action: +-- +-- \blank[force,5*big] { \baselineskip1cm xxxxxxxxx \par } \page +-- \blank[force,5*big] { \baselineskip1cm xxxxxxxxx \par } \page +-- \blank[force,5*big] { \baselineskip5cm xxxxxxxxx \par } \page + +-- We can register and copy the rule instead. + +do + + local insert_node_after = nuts.insert_after + local insert_node_before = nuts.insert_before + + local abovedisplayskip_code = gluecodes.abovedisplayskip + local belowdisplayskip_code = gluecodes.belowdisplayskip + local abovedisplayshortskip_code = gluecodes.abovedisplayshortskip + local belowdisplayshortskip_code = gluecodes.belowdisplayshortskip + + local w, h, d = 0, 0, 0 + ----- w, h, d = 100*65536, 65536, 65536 + + local trace_list = { } + local tracing_info = { } + local before = "" + local after = "" + + local function nodes_to_string(head) + local current = head + local t = { } + while current do + local id = getid(current) + local ty = nodecodes[id] + if id == penalty_code then + t[#t+1] = formatters["%s:%s"](ty,getpenalty(current)) + elseif id == glue_code then + t[#t+1] = formatters["%s:%s:%p"](ty,gluecodes[getsubtype(current)],getwidth(current)) + elseif id == kern_code then + t[#t+1] = formatters["%s:%p"](ty,getkern(current)) + else + t[#t+1] = ty + end + current = getnext(current) + end + return concat(t," + ") + end + + local function reset_tracing(head) + trace_list, tracing_info, before, after = { }, false, nodes_to_string(head), "" + end + + local function trace_skip(str,sc,so,sp,data) + trace_list[#trace_list+1] = { "skip", formatters["%s | %p | category %s | order %s | penalty %s"](str, getwidth(data), sc or "-", so or "-", sp or "-") } + tracing_info = true + end + + local function trace_natural(str,data) + trace_list[#trace_list+1] = { "skip", formatters["%s | %p"](str, getwidth(data)) } + tracing_info = true + end + + local function trace_info(message, where, what) + trace_list[#trace_list+1] = { "info", formatters["%s: %s/%s"](message,where,what) } + end + + local function trace_node(what) + local nt = nodecodes[getid(what)] + local tl = trace_list[#trace_list] + if tl and tl[1] == "node" then + trace_list[#trace_list] = { "node", formatters["%s + %s"](tl[2],nt) } + else + trace_list[#trace_list+1] = { "node", nt } + end + end + + local function show_tracing(head) + if tracing_info then + after = nodes_to_string(head) + for i=1,#trace_list do + local tag, text = unpack(trace_list[i]) + if tag == "info" then + report_collapser(text) + else + report_collapser(" %s: %s",tag,text) + end + end + report_collapser("before: %s",before) + report_collapser("after : %s",after) + end + end + + local function trace_done(str,data) + if getid(data) == penalty_code then + trace_list[#trace_list+1] = { "penalty", formatters["%s | %s"](str,getpenalty(data)) } + else + trace_list[#trace_list+1] = { "glue", formatters["%s | %p"](str,getwidth(data)) } + end + tracing_info = true + end + + local function forced_skip(head,current,width,where,trace) -- looks old ... we have other tricks now + if head == current then + if getsubtype(head) == baselineskip_code then + width = width - getwidth(head) + end + end + if width == 0 then + -- do nothing + elseif where == "after" then + head, current = insert_node_after(head,current,new_rule(w,h,d)) + head, current = insert_node_after(head,current,new_kern(width)) + head, current = insert_node_after(head,current,new_rule(w,h,d)) + else + local c = current + head, current = insert_node_before(head,current,new_rule(w,h,d)) + head, current = insert_node_before(head,current,new_kern(width)) + head, current = insert_node_before(head,current,new_rule(w,h,d)) + current = c + end + if trace then + report_vspacing("inserting forced skip of %p",width) + end + return head, current + end + + -- penalty only works well when before skip + + local discard = categories.discard + local largest = categories.largest + local force = categories.force + local penalty = categories.penalty + local add = categories.add + local disable = categories.disable + local nowhite = categories.nowhite + local goback = categories.goback + local packed = categories.packed + local overlay = categories.overlay + local enable = categories.enable + local notopskip = categories.notopskip + + -- [whatsits][hlist][glue][glue][penalty] + + local special_penalty_min = 32250 + local special_penalty_max = 35000 + local special_penalty_xxx = 0 + + -- this is rather messy and complex: we want to make sure that successive + -- header don't break but also make sure that we have at least a decent + -- break when we have succesive ones (often when testing) + + -- todo: mark headers as such so that we can recognize them + + local specialmethods = { } + local specialmethod = 1 + + specialmethods[1] = function(pagehead,pagetail,start,penalty) + -- + if not pagehead or penalty < special_penalty_min or penalty > special_penalty_max then + return + end + local current = pagetail + -- + -- nodes.showsimplelist(pagehead,0) + -- + if trace_specials then + report_specials("checking penalty %a",penalty) + end + while current do + local id = getid(current) + if id == penalty_code then + local p = properties[current] + if p then + local p = p.special_penalty + if not p then + if trace_specials then + report_specials(" regular penalty, continue") + end + elseif p == penalty then + if trace_specials then + report_specials(" context penalty %a, same level, overloading",p) + end + return special_penalty_xxx + elseif p > special_penalty_min and p < special_penalty_max then + if penalty < p then + if trace_specials then + report_specials(" context penalty %a, lower level, overloading",p) + end + return special_penalty_xxx + else + if trace_specials then + report_specials(" context penalty %a, higher level, quitting",p) + end + return + end + elseif trace_specials then + report_specials(" context penalty %a, higher level, continue",p) + end + else + local p = getpenalty(current) + if p < 10000 then + -- assume some other mechanism kicks in so we seem to have content + if trace_specials then + report_specials(" regular penalty %a, quitting",p) + end + break + else + if trace_specials then + report_specials(" regular penalty %a, continue",p) + end + end + end + end + current = getprev(current) + end + -- none found, so no reson to be special + if trace_specials then + if pagetail then + report_specials(" context penalty, discarding, nothing special") + else + report_specials(" context penalty, discarding, nothing preceding") + end + end + return special_penalty_xxx + end + + -- This will be replaced after 0.80+ when we have a more robust look-back and + -- can look at the bigger picture. + + -- todo: look back and when a special is there before a list is seen penalty keep ut + + -- we now look back a lot, way too often + + -- userskip + -- lineskip + -- baselineskip + -- parskip + -- abovedisplayskip + -- belowdisplayskip + -- abovedisplayshortskip + -- belowdisplayshortskip + -- topskip + -- splittopskip + + -- we could inject a vadjust to force a recalculation .. a mess + -- + -- So, the next is far from robust and okay but for the moment this overlaying + -- has to do. Always test this with the examples in spac-ver.mkvi! + + local function snap_topskip(current,method) + local w = getwidth(current) + setwidth(current,0) + return w, 0 + end + + local function check_experimental_overlay(head,current) + local p = nil + local c = current + local n = nil + local function overlay(p,n,mvl) + local p_wd, p_ht, p_dp = getwhd(p) + local n_wd, n_ht, n_dp = getwhd(n) + local skips = 0 + -- + -- We deal with this at the tex end .. we don't see spacing .. enabling this code + -- is probably harmless but then we need to test it. + -- + -- we could calculate this before we call + -- + -- problem: prev list and next list can be unconnected + -- + local c = getnext(p) + local l = c + while c and c ~= n do + local id = getid(c) + if id == glue_code then + skips = skips + getwidth(c) + elseif id == kern_code then + skips = skips + getkern(c) + end + l = c + c = getnext(c) + end + local c = getprev(n) + while c and c ~= n and c ~= l do + local id = getid(c) + if id == glue_code then + skips = skips + getwidth(c) + elseif id == kern_code then + skips = skips + getkern(c) + end + c = getprev(c) + end + -- + local delta = n_ht + skips + p_dp + texsetdimen("global","d_spac_overlay",-delta) -- for tracing + -- we should adapt pagetotal ! (need a hook for that) .. now we have the wrong pagebreak + local k = new_kern(-delta) + head = insert_node_before(head,n,k) + if n_ht > p_ht then + local k = new_kern(n_ht-p_ht) + head = insert_node_before(head,p,k) + end + if trace_vspacing then + report_vspacing("overlaying, prev height: %p, prev depth: %p, next height: %p, skips: %p, move up: %p",p_ht,p_dp,n_ht,skips,delta) + end + return remove_node(head,current,true) + end + + -- goto next line + while c do + local id = getid(c) + if id == glue_code or id == penalty_code or id == kern_code then + -- skip (actually, remove) + c = getnext(c) + elseif id == hlist_code then + n = c + break + else + break + end + end + if n then + -- we have a next line, goto prev line + c = current + while c do + local id = getid(c) + if id == glue_code or id == penalty_code then -- kern ? + c = getprev(c) + elseif id == hlist_code then + p = c + break + else + break + end + end + if not p then + if a_snapmethod == a_snapvbox then + -- quit, we're not on the mvl + else + -- inefficient when we're at the end of a page + local c = tonut(texlists.page_head) + while c and c ~= n do + local id = getid(c) + if id == hlist_code then + p = c + end + c = getnext(c) + end + if p and p ~= n then + return overlay(p,n,true) + end + end + elseif p ~= n then + return overlay(p,n,false) + end + end + -- in fact, we could try again later ... so then no remove (a few tries) + return remove_node(head,current,true) + end + + local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also pass tail + if trace then + reset_tracing(head) + end + local current = head + local oldhead = head + local glue_order = 0 + local glue_data + local force_glue = false + local penalty_order = 0 + local penalty_data + local natural_penalty + local special_penalty + local parskip + local ignore_parskip = false + local ignore_following = false + local ignore_whitespace = false + local keep_together = false + local lastsnap + local pagehead + local pagetail + -- + -- todo: keep_together: between headers + -- + local function getpagelist() + if not pagehead then + pagehead = texlists.page_head + if pagehead then + pagehead = tonut(pagehead) + pagetail = find_node_tail(pagehead) -- no texlists.page_tail yet-- no texlists.page_tail yet + end + end + end + -- + local function compensate(n) + local g = 0 + while n and getid(n) == glue_code do + g = g + getwidth(n) + n = getnext(n) + end + if n then + local p = getprop(n,"snapper") + if p then + local extra = p.extra + if extra and extra < 0 then -- hm, extra can be unset ... needs checking + local h = p.ch -- getheight(n) + -- maybe an extra check + -- if h - extra < g then + setheight(n,h-2*extra) + p.extra = 0 + if trace_vsnapping then + report_snapper("removed extra space at top: %p",extra) + end + -- end + end + end + return n + end + end + -- + local function removetopsnap() + getpagelist() + if pagehead then + local n = pagehead and compensate(pagehead) + if n and n ~= pagetail then + local p = getprop(pagetail,"snapper") + if p then + local e = p.extra + if e and e < 0 then + local t = texget("pagetotal") + if t > 0 then + local g = texget("pagegoal") -- 1073741823 is signal + local d = g - t + if d < -e then + local penalty = new_penalty(1000000) + setlink(penalty,head) + head = penalty + report_snapper("force pagebreak due to extra space at bottom: %p",e) + end + end + end + end + end + elseif head then + compensate(head) + end + end + -- + local function getavailable() + getpagelist() + if pagehead then + local t = texget("pagetotal") + if t > 0 then + local g = texget("pagegoal") + return g - t + end + end + return false + end + -- + local function flush(why) + if penalty_data then + local p = new_penalty(penalty_data) + if trace then + trace_done("flushed due to " .. why,p) + end + if penalty_data >= 10000 then -- or whatever threshold? + local prev = getprev(current) + if getid(prev) == glue_code then -- maybe go back more, or maybe even push back before any glue + -- tricky case: spacing/grid-007.tex: glue penalty glue + head = insert_node_before(head,prev,p) + else + head = insert_node_before(head,current,p) + end + else + head = insert_node_before(head,current,p) + end + -- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then + local props = properties[p] + if props then + props.special_penalty = special_penalty or penalty_data + else + properties[p] = { + special_penalty = special_penalty or penalty_data + } + end + -- end + end + if glue_data then + if force_glue then + if trace then + trace_done("flushed due to forced " .. why,glue_data) + end + head = forced_skip(head,current,getwidth(glue_data,width),"before",trace) + flush_node(glue_data) + else + local width, stretch, shrink = getglue(glue_data) + if width ~= 0 then + if trace then + trace_done("flushed due to non zero " .. why,glue_data) + end + head = insert_node_before(head,current,glue_data) + elseif stretch ~= 0 or shrink ~= 0 then + if trace then + trace_done("flushed due to stretch/shrink in" .. why,glue_data) + end + head = insert_node_before(head,current,glue_data) + else + -- report_vspacing("needs checking (%s): %p",gluecodes[getsubtype(glue_data)],w) + flush_node(glue_data) + end + end + end + + if trace then + trace_node(current) + end + glue_order, glue_data, force_glue = 0, nil, false + penalty_order, penalty_data, natural_penalty = 0, nil, nil + parskip, ignore_parskip, ignore_following, ignore_whitespace = nil, false, false, false + end + -- + if trace_vsnapping then + report_snapper("global ht/dp = %p/%p, local ht/dp = %p/%p", + texgetdimen("globalbodyfontstrutheight"), + texgetdimen("globalbodyfontstrutdepth"), + texgetdimen("bodyfontstrutheight"), + texgetdimen("bodyfontstrutdepth") + ) + end + if trace then + trace_info("start analyzing",where,what) + end + if snap and where == "page" then + removetopsnap() + end + while current do + local id = getid(current) + if id == hlist_code or id == vlist_code then + -- needs checking, why so many calls + if snap then + lastsnap = nil + local list = getlist(current) + local s = getattr(current,a_snapmethod) + if not s then + -- if trace_vsnapping then + -- report_snapper("mvl list not snapped") + -- end + elseif s == 0 then + if trace_vsnapping then + report_snapper("mvl %a not snapped, already done: %s",nodecodes[id],listtoutf(list)) + end + else + local sv = snapmethods[s] + if sv then + -- check if already snapped + local done = list and already_done(id,list,a_snapmethod) + if done then + -- assume that the box is already snapped + if trace_vsnapping then + local w, h, d = getwhd(current) + report_snapper("mvl list already snapped at (%p,%p): %s",h,d,listtoutf(list)) + end + else + local h, d, ch, cd, lines, extra = snap_hlist("mvl",current,sv,false,false) + lastsnap = { + ht = h, + dp = d, + ch = ch, + cd = cd, + extra = extra, + current = current, + } + setprop(current,"snapper",lastsnap) + if trace_vsnapping then + report_snapper("mvl %a snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s", + nodecodes[id],h,d,ch,cd,sv.name,sv.specification,where,lines,listtoutf(list)) + end + end + elseif trace_vsnapping then + report_snapper("mvl %a not snapped due to unknown snap specification: %s",nodecodes[id],listtoutf(list)) + end + setattr(current,a_snapmethod,0) + end + else + -- + end + -- tex.prevdepth = 0 + flush("list") + current = getnext(current) + elseif id == penalty_code then + -- natural_penalty = getpenalty(current) + -- if trace then + -- trace_done("removed penalty",current) + -- end + -- head, current = remove_node(head,current,true) + current = getnext(current) + elseif id == kern_code then + if snap and trace_vsnapping and getkern(current) ~= 0 then + report_snapper("kern of %p kept",getkern(current)) + end + flush("kern") + current = getnext(current) + elseif id == glue_code then + local subtype = getsubtype(current) + if subtype == userskip_code then + local sc, so, sp = getattrs(current,a_skipcategory,a_skiporder,a_skippenalty) + if not so then + so = 1 -- the others have no default value + end + if sp and sc == penalty then + if where == "page" then + getpagelist() + local p = specialmethods[specialmethod](pagehead,pagetail,current,sp) + if p then + -- todo: other tracer + -- + -- if trace then + -- trace_skip("previous special penalty %a is changed to %a using method %a",sp,p,specialmethod) + -- end + special_penalty = sp + sp = p + end + end + if not penalty_data then + penalty_data = sp + elseif penalty_order < so then + penalty_order, penalty_data = so, sp + elseif penalty_order == so and sp > penalty_data then + penalty_data = sp + end + if trace then + trace_skip("penalty in skip",sc,so,sp,current) + end + head, current = remove_node(head,current,true) + elseif not sc then -- if not sc then + if glue_data then + if trace then + trace_done("flush",glue_data) + end + head = insert_node_before(head,current,glue_data) + if trace then + trace_natural("natural",current) + end + current = getnext(current) + glue_data = nil + else + -- not look back across head + -- todo: prev can be whatsit (latelua) + local previous = getprev(current) + if previous and getid(previous) == glue_code and getsubtype(previous) == userskip_code then + local pwidth, pstretch, pshrink, pstretch_order, pshrink_order = getglue(previous) + local cwidth, cstretch, cshrink, cstretch_order, cshrink_order = getglue(current) + if pstretch_order == 0 and pshrink_order == 0 and cstretch_order == 0 and cshrink_order == 0 then + setglue(previous,pwidth + cwidth, pstretch + cstretch, pshrink + cshrink) + if trace then + trace_natural("removed",current) + end + head, current = remove_node(head,current,true) + if trace then + trace_natural("collapsed",previous) + end + else + if trace then + trace_natural("filler",current) + end + current = getnext(current) + end + else + if trace then + trace_natural("natural (no prev)",current) + end + current = getnext(current) + end + end + glue_order = 0 + elseif sc == disable or sc == enable then + local next = getnext(current) + if next then + ignore_following = sc == disable + if trace then + trace_skip(sc == disable and "disable" or "enable",sc,so,sp,current) + end + head, current = remove_node(head,current,true) + else + current = next + end + elseif sc == packed then + if trace then + trace_skip("packed",sc,so,sp,current) + end + -- can't happen ! + head, current = remove_node(head,current,true) + elseif sc == nowhite then + local next = getnext(current) + if next then + ignore_whitespace = true + head, current = remove_node(head,current,true) + else + current = next + end + elseif sc == discard then + if trace then + trace_skip("discard",sc,so,sp,current) + end + head, current = remove_node(head,current,true) + elseif sc == overlay then + -- todo (overlay following line over previous + if trace then + trace_skip("overlay",sc,so,sp,current) + end + -- beware: head can actually be after the affected nodes as + -- we look back ... some day head will the real head + head, current = check_experimental_overlay(head,current,a_snapmethod) + elseif ignore_following then + if trace then + trace_skip("disabled",sc,so,sp,current) + end + head, current = remove_node(head,current,true) + elseif not glue_data then + if trace then + trace_skip("assign",sc,so,sp,current) + end + glue_order = so + head, current, glue_data = remove_node(head,current) + elseif glue_order < so then + if trace then + trace_skip("force",sc,so,sp,current) + end + glue_order = so + flush_node(glue_data) + head, current, glue_data = remove_node(head,current) + elseif glue_order == so then + -- is now exclusive, maybe support goback as combi, else why a set + if sc == largest then + local cw = getwidth(current) + local gw = getwidth(glue_data) + if cw > gw then + if trace then + trace_skip("largest",sc,so,sp,current) + end + flush_node(glue_data) + head, current, glue_data = remove_node(head,current) + else + if trace then + trace_skip("remove smallest",sc,so,sp,current) + end + head, current = remove_node(head,current,true) + end + elseif sc == goback then + if trace then + trace_skip("goback",sc,so,sp,current) + end + flush_node(glue_data) + head, current, glue_data = remove_node(head,current) + elseif sc == force then + -- last one counts, some day we can provide an accumulator and largest etc + -- but not now + if trace then + trace_skip("force",sc,so,sp,current) + end + flush_node(glue_data) + head, current, glue_data = remove_node(head,current) + elseif sc == penalty then + if trace then + trace_skip("penalty",sc,so,sp,current) + end + flush_node(glue_data) + glue_data = nil + head, current = remove_node(head,current,true) + elseif sc == add then + if trace then + trace_skip("add",sc,so,sp,current) + end + local cwidth, cstretch, cshrink = getglue(current) + local gwidth, gstretch, gshrink = getglue(glue_data) + setglue(glue_data,gwidth + cwidth, gstretch + cstretch,gshrink + cshrink) + -- toto: order + head, current = remove_node(head,current,true) + else + if trace then + trace_skip("unknown",sc,so,sp,current) + end + head, current = remove_node(head,current,true) + end + else + if trace then + trace_skip("unknown",sc,so,sp,current) + end + head, current = remove_node(head,current,true) + end + if sc == force then + force_glue = true + end + elseif subtype == lineskip_code then + if snap then + local s = getattr(current,a_snapmethod) + if s and s ~= 0 then + setattr(current,a_snapmethod,0) + setwidth(current,0) + if trace_vsnapping then + report_snapper("lineskip set to zero") + end + else + if trace then + trace_skip("lineskip",sc,so,sp,current) + end + flush("lineskip") + end + else + if trace then + trace_skip("lineskip",sc,so,sp,current) + end + flush("lineskip") + end + current = getnext(current) + elseif subtype == baselineskip_code then + if snap then + local s = getattr(current,a_snapmethod) + if s and s ~= 0 then + setattr(current,a_snapmethod,0) + setwidth(current,0) + if trace_vsnapping then + report_snapper("baselineskip set to zero") + end + else + if trace then + trace_skip("baselineskip",sc,so,sp,current) + end + flush("baselineskip") + end + else + if trace then + trace_skip("baselineskip",sc,so,sp,current) + end + flush("baselineskip") + end + current = getnext(current) + elseif subtype == parskip_code then + -- parskip always comes later + if ignore_whitespace then + if trace then + trace_natural("ignored parskip",current) + end + head, current = remove_node(head,current,true) + elseif glue_data then + local w = getwidth(current) + if w ~= 0 and w > getwidth(glue_data) then +flush_node(glue_data) + glue_data = current + if trace then + trace_natural("taking parskip",current) + end + head, current = remove_node(head,current) + else + if trace then + trace_natural("removed parskip",current) + end + head, current = remove_node(head,current,true) + end + else + if trace then + trace_natural("honored parskip",current) + end + head, current, glue_data = remove_node(head,current) + end + elseif subtype == topskip_code or subtype == splittopskip_code then + local next = getnext(current) + if next and getattr(next,a_skipcategory) == notopskip then + nuts.setglue(current) -- zero + end + if snap then + local s = getattr(current,a_snapmethod) + if s and s ~= 0 then + setattr(current,a_snapmethod,0) + local sv = snapmethods[s] + local w, cw = snap_topskip(current,sv) + if trace_vsnapping then + report_snapper("topskip snapped from %p to %p for %a",w,cw,where) + end + else + if trace then + trace_skip("topskip",sc,so,sp,current) + end + flush("topskip") + end + else + if trace then + trace_skip("topskip",sc,so,sp,current) + end + flush("topskip") + end + current = getnext(current) + elseif subtype == abovedisplayskip_code and remove_math_skips then + -- + if trace then + trace_skip("above display skip (normal)",sc,so,sp,current) + end + flush("above display skip (normal)") + current = getnext(current) + -- + elseif subtype == belowdisplayskip_code and remove_math_skips then + -- + if trace then + trace_skip("below display skip (normal)",sc,so,sp,current) + end + flush("below display skip (normal)") + current = getnext(current) + -- + elseif subtype == abovedisplayshortskip_code and remove_math_skips then + -- + if trace then + trace_skip("above display skip (short)",sc,so,sp,current) + end + flush("above display skip (short)") + current = getnext(current) + -- + elseif subtype == belowdisplayshortskip_code and remove_math_skips then + -- + if trace then + trace_skip("below display skip (short)",sc,so,sp,current) + end + flush("below display skip (short)") + current = getnext(current) + -- + else -- other glue + if snap and trace_vsnapping then + local w = getwidth(current) + if w ~= 0 then + report_snapper("glue %p of type %a kept",w,gluecodes[subtype]) + end + end + if trace then + trace_skip(formatters["glue of type %a"](subtype),sc,so,sp,current) + end + flush("some glue") + current = getnext(current) + end + else + flush(trace and formatters["node with id %a"](id) or "other node") + current = getnext(current) + end + end + if trace then + trace_info("stop analyzing",where,what) + end + -- if natural_penalty and (not penalty_data or natural_penalty > penalty_data) then + -- penalty_data = natural_penalty + -- end + if trace and (glue_data or penalty_data) then + trace_info("start flushing",where,what) + end + local tail + if penalty_data then + tail = find_node_tail(head) + local p = new_penalty(penalty_data) + if trace then + trace_done("result",p) + end + setlink(tail,p) + -- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then + local props = properties[p] + if props then + props.special_penalty = special_penalty or penalty_data + else + properties[p] = { + special_penalty = special_penalty or penalty_data + } + end + -- end + end + if glue_data then + if not tail then tail = find_node_tail(head) end + if trace then + trace_done("result",glue_data) + end + if force_glue then + head, tail = forced_skip(head,tail,getwidth(glue_data),"after",trace) + flush_node(glue_data) + glue_data = nil + elseif tail then + setlink(tail,glue_data) +setnext(glue_data) + else + head = glue_data + end + texnest[texnest.ptr].prevdepth = 0 -- appending to the list bypasses tex's prevdepth handler + end + if trace then + if glue_data or penalty_data then + trace_info("stop flushing",where,what) + end + show_tracing(head) + if oldhead ~= head then + trace_info("head has been changed from %a to %a",nodecodes[getid(oldhead)],nodecodes[getid(head)]) + end + end + return head + end + + local stackhead, stacktail, stackhack = nil, nil, false + + local function report(message,where,lst) + if lst and where then + report_vspacing(message,where,count_nodes(lst,true),nodeidstostring(lst)) + else + report_vspacing(message,count_nodes(lst,true),nodeidstostring(lst)) + end + end + + -- ugly code: we get partial lists (check if this stack is still okay) ... and we run + -- into temp nodes (sigh) + + local forceflush = false + + function vspacing.pagehandler(newhead,where) + if newhead then + local newtail = find_node_tail(newhead) -- best pass that tail, known anyway + local flush = false + stackhack = true -- todo: only when grid snapping once enabled + -- todo: fast check if head = tail + for n, id, subtype in nextnode, newhead do -- we could just look for glue nodes + if id ~= glue_code then + flush = true + elseif subtype == userskip_code then + if getattr(n,a_skipcategory) then + stackhack = true + else + flush = true + end + elseif subtype == parskip_code then + -- if where == new_graf then ... end + if texgetcount("c_spac_vspacing_ignore_parskip") > 0 then + -- texsetcount("c_spac_vspacing_ignore_parskip",0) + setglue(n) + -- maybe removenode + end + end + end + texsetcount("c_spac_vspacing_ignore_parskip",0) + + if forceflush then + forceflush = false + flush = true + end + + if flush then + if stackhead then + if trace_collect_vspacing then report("%s > appending %s nodes to stack (final): %s",where,newhead) end + setlink(stacktail,newhead) + newhead = stackhead + stackhead = nil + stacktail = nil + end + if stackhack then + stackhack = false + if trace_collect_vspacing then report("%s > processing %s nodes: %s",where,newhead) end + newhead = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod) + else + if trace_collect_vspacing then report("%s > flushing %s nodes: %s",where,newhead) end + end + return newhead + else + if stackhead then + if trace_collect_vspacing then report("%s > appending %s nodes to stack (intermediate): %s",where,newhead) end + setlink(stacktail,newhead) + else + if trace_collect_vspacing then report("%s > storing %s nodes in stack (initial): %s",where,newhead) end + stackhead = newhead + end + stacktail = newtail + end + end + return nil + end + + function vspacing.pageoverflow() + local h = 0 + if stackhead then + for n, id in nextnode, stackhead do + if id == glue_code then + h = h + getwidth(n) + elseif id == kern_code then + h = h + getkern(n) + end + end + end + return h + end + + function vspacing.forcepageflush() + forceflush = true + end + + local ignore = table.tohash { + "split_keep", + "split_off", + -- "vbox", + } + + function vspacing.vboxhandler(head,where) + if head and not ignore[where] and getnext(head) then + if getnext(head) then -- what if a one liner and snapping? + head = collapser(head,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper + return head + end + end + return head + end + + function vspacing.collapsevbox(n,aslist) -- for boxes but using global a_snapmethod + local box = getbox(n) + if box then + local list = getlist(box) + if list then + list = collapser(list,"snapper","vbox",trace_vbox_vspacing,true,a_snapmethod) + if aslist then + setlist(box,list) -- beware, dimensions of box are wrong now + else + setlist(box,vpack_node(list)) + end + end + end + end + +end + +-- This one is needed to prevent bleeding of prevdepth to the next page +-- which doesn't work well with forced skips. I'm not that sure if the +-- following is a good way out. + +do + + local outer = texnest[0] + + local enabled = true + local trace = false + local report = logs.reporter("vspacing") + + trackers.register("vspacing.synchronizepage",function(v) + trace = v + end) + + directives.register("vspacing.synchronizepage",function(v) + enabled = v + end) + + local ignoredepth = -65536000 + + -- A previous version analyzed the number of lines moved to the next page in + -- synchronizepage because prevgraf is unreliable in that case. However, we cannot + -- tweak that parameter because it is also used in postlinebreak and hangafter, so + -- there is a danger for interference. Therefore we now do it dynamically. + + -- We can also support other lists but there prevgraf probably is ok. + + function vspacing.getnofpreviouslines(head) + if enabled then + if not thead then + head = texlists.page_head + end + local noflines = 0 + if head then + local tail = find_node_tail(tonut(head)) + while tail do + local id = getid(tail) + if id == hlist_code then + if getsubtype(tail) == linelist_code then + noflines = noflines + 1 + else + break + end + elseif id == vlist_code then + break + elseif id == glue_code then + local subtype = getsubtype(tail) + if subtype == baselineskip_code or subtype == lineskip_code then + -- we're ok + elseif subtype == parskip_code then + if getwidth(tail) > 0 then + break + else + -- we assume we're ok + end + end + elseif id == penalty_code then + -- we're probably ok + elseif id == rule_code or id == kern_code then + break + else + -- ins, mark, boundary, whatsit + end + tail = getprev(tail) + end + end + return noflines + end + end + + interfaces.implement { + name = "getnofpreviouslines", + public = true, + actions = vspacing.getnofpreviouslines, + } + + function vspacing.synchronizepage() + if enabled then + if trace then + local newdepth = outer.prevdepth + local olddepth = newdepth + if not texlists.page_head then + newdepth = ignoredepth + texset("prevdepth",ignoredepth) + outer.prevdepth = ignoredepth + end + report("page %i, prevdepth %p => %p",texgetcount("realpageno"),olddepth,newdepth) + -- report("list %s",nodes.idsandsubtypes(head)) + else + if not texlists.page_head then + texset("prevdepth",ignoredepth) + outer.prevdepth = ignoredepth + end + end + end + end + + local trace = false + local last = nil + local vmode_code = tex.modelevels.vertical + local temp_code = nodecodes.temp + local getnest = tex.getnest + local getlist = tex.getlist + + trackers.register("vspacing.forcestrutdepth",function(v) trace = v end) + + -- abs : negative is inner + + function vspacing.checkstrutdepth(depth) + local nest = getnest() + if abs(nest.mode) == vmode_code and nest.head then + local tail = nest.tail + local id = tail.id + if id == hlist_code then + if tail.depth < depth then + tail.depth = depth + end + nest.prevdepth = depth + elseif id == temp_code and getnest("ptr") == 0 then + local head = getlist("page_head") + if head then + tail = nodes.tail(head) + if tail and tail.id == hlist_code then + if tail.depth < depth then + tail.depth = depth + end + nest.prevdepth = depth + -- only works in lmtx + texset("pagedepth",depth) + end + end + end + end + end + + interfaces.implement { + name = "checkstrutdepth", + arguments = "dimension", + actions = vspacing.checkstrutdepth, + } + + function vspacing.forcestrutdepth(n,depth,trace_mode,plus) + local box = texgetbox(n) + if box then + box = tonut(box) + local head = getlist(box) + if head then + local tail = find_node_tail(head) + if tail then + if getid(tail) == hlist_code then + local dp = getdepth(tail) + if dp < depth then + setdepth(tail,depth) + outer.prevdepth = depth + if trace or trace_mode > 0 then + nuts.setvisual(tail,"depth") + end + end + end + last = nil + if plus then + -- penalty / skip ... + local height = 0 + local sofar = 0 + local same = false + local seen = false + local list = { } + last = nil + while tail do + local id = getid(tail) + if id == hlist_code or id == vlist_code then + local w, h, d = getwhd(tail) + height = height + h + d + sofar + sofar = 0 + last = tail + elseif id == kern_code then + sofar = sofar + getkern(tail) + elseif id == glue_code then + if seen then + sofar = sofar + getwidth(tail) + seen = false + else + break + end + elseif id == penalty_code then + local p = getpenalty(tail) + if p >= 10000 then + same = true + seen = true + else + break + end + else + break + end + tail = getprev(tail) + end + texsetdimen("global","d_spac_prevcontent",same and height or 0) + end + end + end + end + end + + function vspacing.pushatsame() + -- needs better checking ! + if last then -- setsplit + nuts.setnext(getprev(last)) + nuts.setprev(last) + end + end + + function vspacing.popatsame() + -- needs better checking ! + nuts.write(last) + end + +end + +-- interface + +do + + -- old variant + + implement { + name = "vspacing", + actions = vspacing.analyze, + scope = "private", + arguments = "string" + } + + -- new variant + + interfaces.implement { + name = "injectvspacing", + actions = vspacing.inject, + arguments = { "integer", "string" }, + } + + interfaces.implement { + name = "injectvpenalty", + actions = vspacing.injectpenalty, + arguments = "integer", + } + + interfaces.implement { + name = "injectvskip", + actions = vspacing.injectskip, + arguments = "dimension", + } + + interfaces.implement { + name = "injectdisable", + actions = vspacing.injectdisable, + } + + -- + + implement { + name = "synchronizepage", + actions = vspacing.synchronizepage, + scope = "private" + } + + implement { + name = "forcestrutdepth", + arguments = { "integer", "dimension", "integer" }, + actions = vspacing.forcestrutdepth, + scope = "private" + } + + implement { + name = "forcestrutdepthplus", + arguments = { "integer", "dimension", "integer", true }, + actions = vspacing.forcestrutdepth, + scope = "private" + } + + implement { + name = "pushatsame", + actions = vspacing.pushatsame, + scope = "private" + } + + implement { + name = "popatsame", + actions = vspacing.popatsame, + scope = "private" + } + + implement { + name = "vspacingsetamount", + actions = vspacing.setskip, + scope = "private", + arguments = "string", + } + + implement { + name = "vspacingdefine", + actions = vspacing.setmap, + scope = "private", + arguments = "2 strings", + } + + implement { + name = "vspacingcollapse", + actions = vspacing.collapsevbox, + scope = "private", + arguments = "integer" + } + + implement { + name = "vspacingcollapseonly", + actions = vspacing.collapsevbox, + scope = "private", + arguments = { "integer", true } + } + + implement { + name = "vspacingsnap", + actions = vspacing.snapbox, + scope = "private", + arguments = { "integer", "integer" } + } + + implement { + name = "definesnapmethod", + actions = vspacing.definesnapmethod, + scope = "private", + arguments = "2 strings", + } + + -- local remove_node = nodes.remove + -- local find_node_tail = nodes.tail + -- + -- interfaces.implement { + -- name = "fakenextstrutline", + -- actions = function() + -- local head = texlists.page_head + -- if head then + -- local head = remove_node(head,find_node_tail(head),true) + -- texlists.page_head = head + -- buildpage() + -- end + -- end + -- } + + implement { + name = "removelastline", + actions = function() + local head = texlists.page_head + if head then + local tail = find_node_tail(head) + if tail then + -- maybe check for hlist subtype 1 + local head = remove_node(head,tail,true) + texlists.page_head = head + buildpage() + end + end + end + } + + implement { + name = "showpagelist", -- will improve + actions = function() + local head = texlists.page_head + if head then + print("start") + while head do + print(" " .. tostring(head)) + head = head.next + end + end + end + } + + implement { + name = "pageoverflow", + actions = { vspacing.pageoverflow, context } + } + + implement { + name = "forcepageflush", + actions = vspacing.forcepageflush + } + +end diff --git a/tex/context/base/mkiv/spac-ver.lua b/tex/context/base/mkiv/spac-ver.lua index 2f0d54227..2fc926321 100644 --- a/tex/context/base/mkiv/spac-ver.lua +++ b/tex/context/base/mkiv/spac-ver.lua @@ -185,7 +185,7 @@ local glue_code = nodecodes.glue local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local rule_code = nodecodes.rule -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local userskip_code = gluecodes.userskip local lineskip_code = gluecodes.lineskip @@ -293,7 +293,7 @@ end local function validvbox(parentid,list) if parentid == hlist_code then local id = getid(list) - if id == localpar_code and start_of_par(list) then + if id == par_code and start_of_par(list) then list = getnext(list) if not next then return nil @@ -329,7 +329,7 @@ local function already_done(parentid,list,a_snapmethod) -- todo: done when only -- problem: any snapped vbox ends up in a line if list and parentid == hlist_code then local id = getid(list) - if id == localpar_code and start_of_par(list) then + if id == par_code and start_of_par(list) then list = getnext(list) if not list then return false @@ -1263,7 +1263,7 @@ do end end -- in fact, we could try again later ... so then no remove (a few tries) - return remove_node(head, current, true) + return remove_node(head,current,true) end local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also pass tail @@ -1501,7 +1501,7 @@ do -- if trace then -- trace_done("removed penalty",current) -- end - -- head, current = remove_node(head, current, true) + -- head, current = remove_node(head,current,true) current = getnext(current) elseif id == kern_code then if snap and trace_vsnapping and getkern(current) ~= 0 then @@ -1539,7 +1539,7 @@ do if trace then trace_skip("penalty in skip",sc,so,sp,current) end - head, current = remove_node(head, current, true) + head, current = remove_node(head,current,true) elseif not sc then -- if not sc then if glue_data then if trace then @@ -1562,7 +1562,7 @@ do if trace then trace_natural("removed",current) end - head, current = remove_node(head, current, true) + head, current = remove_node(head,current,true) if trace then trace_natural("collapsed",previous) end @@ -1587,7 +1587,7 @@ do if trace then trace_skip(sc == disable and "disable" or "enable",sc,so,sp,current) end - head, current = remove_node(head, current, true) + head, current = remove_node(head,current,true) else current = next end @@ -1596,12 +1596,12 @@ do trace_skip("packed",sc,so,sp,current) end -- can't happen ! - head, current = remove_node(head, current, true) + head, current = remove_node(head,current,true) elseif sc == nowhite then local next = getnext(current) if next then ignore_whitespace = true - head, current = remove_node(head, current, true) + head, current = remove_node(head,current,true) else current = next end @@ -1609,7 +1609,7 @@ do if trace then trace_skip("discard",sc,so,sp,current) end - head, current = remove_node(head, current, true) + head, current = remove_node(head,current,true) elseif sc == overlay then -- todo (overlay following line over previous if trace then @@ -1622,20 +1622,20 @@ do if trace then trace_skip("disabled",sc,so,sp,current) end - head, current = remove_node(head, current, true) + head, current = remove_node(head,current,true) elseif not glue_data then if trace then trace_skip("assign",sc,so,sp,current) end glue_order = so - head, current, glue_data = remove_node(head, current) + head, current, glue_data = remove_node(head,current) elseif glue_order < so then if trace then trace_skip("force",sc,so,sp,current) end glue_order = so flush_node(glue_data) - head, current, glue_data = remove_node(head, current) + head, current, glue_data = remove_node(head,current) elseif glue_order == so then -- is now exclusive, maybe support goback as combi, else why a set if sc == largest then @@ -1651,7 +1651,7 @@ do if trace then trace_skip("remove smallest",sc,so,sp,current) end - head, current = remove_node(head, current, true) + head, current = remove_node(head,current,true) end elseif sc == goback then if trace then @@ -1666,34 +1666,34 @@ do trace_skip("force",sc,so,sp,current) end flush_node(glue_data) - head, current, glue_data = remove_node(head, current) + head, current, glue_data = remove_node(head,current) elseif sc == penalty then if trace then trace_skip("penalty",sc,so,sp,current) end flush_node(glue_data) glue_data = nil - head, current = remove_node(head, current, true) + head, current = remove_node(head,current,true) elseif sc == add then if trace then trace_skip("add",sc,so,sp,current) end local cwidth, cstretch, cshrink = getglue(current) local gwidth, gstretch, gshrink = getglue(glue_data) - setglue(old,gwidth + cwidth, gstretch + cstretch, gshrink + cshrink) + setglue(glue_data,gwidth + cwidth, gstretch + cstretch,gshrink + cshrink) -- toto: order - head, current = remove_node(head, current, true) + head, current = remove_node(head,current,true) else if trace then trace_skip("unknown",sc,so,sp,current) end - head, current = remove_node(head, current, true) + head, current = remove_node(head,current,true) end else if trace then trace_skip("unknown",sc,so,sp,current) end - head, current = remove_node(head, current, true) + head, current = remove_node(head,current,true) end if sc == force then force_glue = true @@ -1748,7 +1748,7 @@ do if trace then trace_natural("ignored parskip",current) end - head, current = remove_node(head, current, true) + head, current = remove_node(head,current,true) elseif glue_data then local w = getwidth(current) if (w ~= 0) and (w > getwidth(glue_data)) then @@ -1756,18 +1756,18 @@ do if trace then trace_natural("taking parskip",current) end - head, current = remove_node(head, current) + head, current = remove_node(head,current) else if trace then trace_natural("removed parskip",current) end - head, current = remove_node(head, current, true) + head, current = remove_node(head,current,true) end else if trace then trace_natural("honored parskip",current) end - head, current, glue_data = remove_node(head, current) + head, current, glue_data = remove_node(head,current) end elseif subtype == topskip_code or subtype == splittopskip_code then local next = getnext(current) @@ -1902,18 +1902,6 @@ do return head end - -- alignment after_output end box new_graf vmode_par hmode_par insert penalty before_display after_display - -- \par -> vmode_par - -- - -- status.best_page_break - -- tex.lists.best_page_break - -- tex.lists.best_size (natural size to best_page_break) - -- tex.lists.least_page_cost (badness of best_page_break) - -- tex.lists.page_head - -- tex.lists.contrib_head - - -- do - local stackhead, stacktail, stackhack = nil, nil, false local function report(message,where,lst) @@ -1930,7 +1918,6 @@ do local forceflush = false function vspacing.pagehandler(newhead,where) - -- local newhead = texlists.contrib_head if newhead then local newtail = find_node_tail(newhead) -- best pass that tail, known anyway local flush = false @@ -1972,11 +1959,9 @@ do if stackhack then stackhack = false if trace_collect_vspacing then report("%s > processing %s nodes: %s",where,newhead) end - -- texlists.contrib_head = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod) newhead = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod) else if trace_collect_vspacing then report("%s > flushing %s nodes: %s",where,newhead) end - -- texlists.contrib_head = newhead end return newhead else @@ -1993,20 +1978,6 @@ do return nil end - -- function vspacing.flushpagestack() - -- if stackhead then - -- local head = texlists.contrib_head - -- if head then - -- local tail = find_node_tail(head) - -- setlink(tail,stackhead) - -- else - -- texlists.contrib_head = tonode(stackhead) - -- end - -- stackhead, stacktail = nil, nil - -- end - -- - -- end - function vspacing.pageoverflow() local h = 0 if stackhead then @@ -2187,6 +2158,8 @@ do tail.depth = depth end nest.prevdepth = depth + -- only works in lmtx + texset("pagedepth",depth) end end end diff --git a/tex/context/base/mkiv/spac-ver.mkiv b/tex/context/base/mkiv/spac-ver.mkiv index 2c8c30bec..680ba7a99 100644 --- a/tex/context/base/mkiv/spac-ver.mkiv +++ b/tex/context/base/mkiv/spac-ver.mkiv @@ -1940,7 +1940,7 @@ \clf_vspacingsetamount{#1}} \def\spac_vspacing_no_topskip % use grouped - {\c_attr_skipcategory\plusten} + {\c_attr_skipcategory\pluseleven} % \installcorenamespace{vspacingamountnormal} % \installcorenamespace{vspacingamountgrid} diff --git a/tex/context/base/mkiv/spac-ver.mkxl b/tex/context/base/mkiv/spac-ver.mkxl index c76c011e1..7a4688791 100644 --- a/tex/context/base/mkiv/spac-ver.mkxl +++ b/tex/context/base/mkiv/spac-ver.mkxl @@ -15,7 +15,7 @@ \unprotect -\registerctxluafile{spac-ver}{optimize} +\registerctxluafile{spac-ver}{autosuffix,optimize} % todo: use usernodes ? @@ -64,7 +64,7 @@ \def\skipfactor {.75} \def\skipgluefactor{.25} -\def\normalskipamount +\permanent\def\normalskipamount {\openlineheight \ifgridsnapping \orelse \ifconditional\c_spac_whitespace_flexible \s!plus \skipgluefactor\openlineheight @@ -76,7 +76,7 @@ \let\bodyfontinterlinespace\empty \fi -\unexpanded\def\presetnormallineheight % each bodyfont +\permanent\protected\def\presetnormallineheight % each bodyfont {\edef\normallineheight{\interlinespaceparameter\c!line}% \iflocalinterlinespace \else \edef\m_spac_normallineheight{\bodyfontinterlinespace}% @@ -85,7 +85,7 @@ \fi \fi} -\unexpanded\def\setupspecifiedinterlinespace[#1]% +\permanent\protected\def\setupspecifiedinterlinespace[#1]% {\setupcurrentinterlinespace[#1]% \spac_linespacing_setup_specified_interline_space} @@ -125,7 +125,7 @@ {\assignvalue{#1}\currentrelativeinterlinespace{1.00}{1.25}{1.50}% \spacing\currentrelativeinterlinespace}} -\unexpanded\def\setuprelativeinterlinespace[#1]% +\permanent\protected\def\setuprelativeinterlinespace[#1]% {\processcommalist[#1]\spac_linespacing_setup_relative_interlinespace} \def\spac_linespacing_setup_relative_interlinespace#1% @@ -140,7 +140,7 @@ \spacing\currentrelativeinterlinespace \fi} -\unexpanded\def\spac_linespacing_setup_use +\protected\def\spac_linespacing_setup_use {\ifcsname\namedinterlinespacehash\m_spac_interlinespace\s!parent\endcsname \let\currentinterlinespace\m_spac_interlinespace \spac_linespacing_setup_specified_interline_space @@ -148,7 +148,7 @@ % we only support named interlinespaces \fi} -\unexpanded\def\useinterlinespaceparameter#1% see footnotes +\permanent\protected\def\useinterlinespaceparameter#1% see footnotes {\edef\m_spac_interlinespace{#1\c!interlinespace}% \ifempty\m_spac_interlinespace \else \spac_linespacing_setup_use @@ -165,18 +165,12 @@ \installmacrostack\currentinterlinespace -\unexpanded\def\setupinterlinespace - {\dodoubleempty\spac_linespacing_setup} - -\ifdefined\setupinterlinespace_double \else - \let\setupinterlinespace_double\setup_interlinespace % for a while -\fi - -\def\spac_linespacing_setup[#1][#2]% - {\settrue\interlinespaceisset % reset has to be done when needed - \ifsecondargument - \setupinterlinespace_double[#1][#2]% - \orelse\iffirstargument +\permanent\overloaded\tolerant\protected\def\setupinterlinespace[#1]#*[#2]% + {\ifarguments + \settrue\interlinespaceisset + \spac_linespacing_synchronize_local + \or + \settrue\interlinespaceisset \ifcsname\namedinterlinespacehash{#1}\s!parent\endcsname \edef\currentinterlinespace{#1}% \spac_linespacing_setup_specified_interline_space @@ -184,9 +178,9 @@ \else \spac_linespacing_setup_specified_or_relative[#1]% \fi - \else - \let\currentinterlinespace\empty - \spac_linespacing_synchronize_local + \or + \settrue\interlinespaceisset + \setup_interlinespace[#1][#2]% \fi} \def\spac_linespacing_setup_specified_or_relative[#1]% @@ -200,7 +194,7 @@ \the\everysetuplocalinterlinespace \localinterlinespacefalse} -\unexpanded\def\dosetupcheckedinterlinespace#1% often a chain +\permanent\protected\def\dosetupcheckedinterlinespace#1% often a chain {\edef\p_spac_checked_interlinespace{#1}% \ifempty\p_spac_checked_interlinespace \spac_linespacing_synchronize_local @@ -228,7 +222,7 @@ \fi \fi} -\unexpanded\def\setuplocalinterlinespace[#1]% +\permanent\protected\def\setuplocalinterlinespace[#1]% {\localinterlinespacetrue \push_macro_currentinterlinespace \setupinterlinespace[#1]% @@ -244,8 +238,8 @@ \newcount\c_spac_spacefactor \newdimen\d_spac_prevcontent % set by lua -\unexpanded\def\removelastskip - {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi} +% \permanent\overloaded\protected\def\removelastskip +% {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi} \def\doifoutervmode {\ifvmode @@ -258,7 +252,7 @@ \expandafter\gobbleoneargument \fi} -\unexpanded\def\dosomebreak#1% +\protected\def\dosomebreak#1% {\doifoutervmode {\s_spac_lastskip\lastskip \removelastskip @@ -269,19 +263,19 @@ \vskip\s_spac_lastskip \fi}} -\unexpanded\def\packed +\permanent\protected\def\packed {\nointerlineskip} -\unexpanded\def\godown[#1]% +\permanent\protected\def\godown[#1]% {\relax \ifhmode\endgraf\fi \ifvmode\nointerlineskip\vskip#1\relax\fi} -\unexpanded\def\smallskip{\vskip\smallskipamount} -\unexpanded\def\medskip {\vskip\medskipamount} -\unexpanded\def\bigskip {\vskip\bigskipamount} +\permanent\protected\def\smallskip{\vskip\smallskipamount} +\permanent\protected\def\medskip {\vskip\medskipamount} +\permanent\protected\def\bigskip {\vskip\bigskipamount} -\unexpanded\def\smallbreak +\permanent\protected\def\smallbreak {\par \ifvmode\ifdim\lastskip<\smallskipamount \removelastskip @@ -289,7 +283,7 @@ \smallskip \fi\fi} -\unexpanded\def\medbreak +\permanent\protected\def\medbreak {\par \ifvmode\ifdim\lastskip<\medskipamount \removelastskip @@ -297,7 +291,7 @@ \medskip \fi\fi} -\unexpanded\def\bigbreak +\permanent\protected\def\bigbreak {\par \ifvmode\ifdim\lastskip<\bigskipamount \removelastskip @@ -305,18 +299,18 @@ \bigskip \fi\fi} -\unexpanded\def\break {\penalty-\plustenthousand} % can be hmode or vmode -\unexpanded\def\nobreak {\penalty \plustenthousand} % can be hmode or vmode -\unexpanded\def\allowbreak{\penalty \zerocount} % can be hmode or vmode +\permanent\protected\def\break {\penalty-\plustenthousand} % can be hmode or vmode +\permanent\protected\def\nobreak {\penalty \plustenthousand} % can be hmode or vmode +\permanent\protected\def\allowbreak{\penalty \zerocount} % can be hmode or vmode -\unexpanded\def\goodbreak {\par\ifvmode\penalty-\plusfivehundred\relax\fi} % forces vmode -\unexpanded\def\filbreak {\par\ifvmode\vfil\penalty-\plustwohundred\vfilneg\fi} % forces vmode +\permanent\protected\def\goodbreak {\par\ifvmode\penalty-\plusfivehundred\relax\fi} % forces vmode +\permanent\protected\def\filbreak {\par\ifvmode\vfil\penalty-\plustwohundred\vfilneg\fi} % forces vmode %D Made slightly more readable: -\unexpanded\def\vglue {\afterassignment\spac_helpers_vglue_indeed\s_spac_lastskip=} -\unexpanded\def\hglue {\afterassignment\spac_helpers_hglue_indeed\s_spac_lastskip=} -\unexpanded\def\topglue{\par\ifvmode\nointerlineskip\vglue-\topskip\vglue\fi} +\permanent\protected\def\vglue {\afterassignment\spac_helpers_vglue_indeed\s_spac_lastskip=} +\permanent\protected\def\hglue {\afterassignment\spac_helpers_hglue_indeed\s_spac_lastskip=} +\permanent\protected\def\topglue{\par\ifvmode\nointerlineskip\vglue-\topskip\vglue\fi} \def\spac_helpers_vglue_indeed {\par @@ -338,9 +332,13 @@ %D We adapt plain's \type {\removelastskip} a bit: -\unexpanded\def\removelastskip % also in supp-box +\pushoverloadmode + +\permanent\overloaded\protected\def\removelastskip % also in supp-box {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi} +\popoverloadmode + % The whitespace handler. We could cache settings but normally there are not % that many in a set. @@ -353,8 +351,31 @@ %def\v_spac_whitespace_current{\zeropoint} \let\v_spac_whitespace_current\v!none -\unexpanded\def\setupwhitespace - {\doifelsenextoptionalcs\spac_whitespace_setup_yes\spac_whitespace_setup_nop} +% \permanent\tolerant\protected\def\setupwhitespace[#1]% +% {\ifarguments +% \spac_whitespace_setup_nop +% \or +% \spac_whitespace_setup_yes{#1}% +% \fi} +% +% \def\spac_whitespace_setup_yes#1% +% {\edef\m_spac_whitespace_asked{#1}% +% \ifempty\m_spac_whitespace_asked +% \spac_whitespace_setup_nop +% \else +% \let\v_spac_whitespace_current\m_spac_whitespace_asked +% \spac_whitespace_setup +% \fi} + +\permanent\tolerant\protected\def\setupwhitespace[#1]% + {\ifarguments + \spac_whitespace_setup_nop + \orelse\iftok{#1}\emptytoks + \spac_whitespace_setup_nop + \else + \edef\v_spac_whitespace_current{#1}% + \spac_whitespace_setup + \fi} \def\spac_whitespace_setup_nop {\ifx\v_spac_whitespace_current\v!none\else @@ -363,15 +384,6 @@ \let\synchronizewhitespace\spac_whitespace_setup_nop -\def\spac_whitespace_setup_yes[#1]% - {\edef\m_spac_whitespace_asked{#1}% - \ifempty\m_spac_whitespace_asked - \spac_whitespace_setup_nop - \else - \let\v_spac_whitespace_current\m_spac_whitespace_asked - \spac_whitespace_setup - \fi} - \def\spac_whitespace_setup % quick test for no list {\ifcsname\??whitespacemethod\v_spac_whitespace_current\endcsname \lastnamedcs @@ -407,7 +419,7 @@ \fi \fi} -\unexpanded\def\installwhitespacemethod#1#2% +\permanent\protected\def\installwhitespacemethod#1#2% {\setvalue{\??whitespacemethod#1}{#2}} \installwhitespacemethod \v!fix {} @@ -431,7 +443,7 @@ \s_spac_whitespace_parskip#1\fi \relax} -\unexpanded\def\forgetparskip +\permanent\protected\def\forgetparskip {\s_spac_whitespace_parskip\zeropoint \parskip\zeropoint \let\v_spac_whitespace_current\v!none} @@ -445,8 +457,8 @@ % \def\spac_whitespace_setup_method#1% % {\csname\??whitespacemethod\ifcsname\??whitespacemethod#1\endcsname#1\else\s!unknown\endcsname\relax} -\unexpanded\def\nowhitespace{\directcheckedvspacing\v!nowhite} % {\vspacing[\v!nowhite]} -\unexpanded\def\whitespace {\directcheckedvspacing\v!white} % {\vspacing[\v!white]} +\permanent\protected\def\nowhitespace{\directcheckedvspacing\v!nowhite} % {\vspacing[\v!nowhite]} +\permanent\protected\def\whitespace {\directcheckedvspacing\v!white} % {\vspacing[\v!white]} \setupwhitespace [\v!none] @@ -458,10 +470,7 @@ \newconditional\c_spac_packed_blank \settrue\c_spac_packed_blank \newcount \c_spac_packed_level -\unexpanded\def\startpacked - {\dosingleempty\spac_packed_start} - -\def\spac_packed_start[#1]% nesting afvangen +\permanent\tolerant\protected\def\startpacked[#1]% {\global\advance\c_spac_packed_level\plusone \par \ifnum\c_spac_packed_level=\plusone \ifvmode @@ -472,18 +481,18 @@ \setupwhitespace[\v!none]% or \forgetparskip \fi \fi} -\unexpanded\def\stoppacked +\permanent\protected\def\stoppacked {\par \ifnum\c_spac_packed_level=\plusone \ifvmode \endgroup \fi \fi \global\advance\c_spac_packed_level\minusone} -\unexpanded\def\startunpacked +\permanent\protected\def\startunpacked {\directdefaultvspacing % \blank \begingroup} -\unexpanded\def\stopunpacked +\permanent\protected\def\stopunpacked {\endgroup \directdefaultvspacing}% \blank} @@ -500,8 +509,8 @@ \installtextracker {linecorrection.boxes} - {\let\spac_lines_vbox\ruledvbox} - {\let\spac_lines_vbox\vbox} + {\letfrozen\let\spac_lines_vbox\ruledvbox} + {\letfrozen\let\spac_lines_vbox\vbox} \let\v_spac_lines_around_action_set\relax \let\m_spac_lines_around \empty @@ -517,20 +526,14 @@ \ifcsname\??linesaround\m_spac_lines_around\endcsname\m_spac_lines_around\else\s!unknown\fi \endcsname} -\unexpanded\def\startlinecorrection - {\endgraf - \begingroup - \setconstant\c_spac_lines_correction_mode\plusone - \dosingleempty\spac_lines_start_correction} +\permanent\tolerant\protected\def\startlinecorrection [#1]{\spac_lines_start_correction\plusone{#1}} +\permanent\tolerant\protected\def\startlocallinecorrection[#1]{\spac_lines_start_correction\plustwo{#1}} -\unexpanded\def\startlocallinecorrection +\protected\def\spac_lines_start_correction#1#2% {\endgraf \begingroup - \setconstant\c_spac_lines_correction_mode\plustwo - \dosingleempty\spac_lines_start_correction} - -\unexpanded\def\spac_lines_start_correction[#1]% - {\edef\m_spac_lines_around{#1}% + \setconstant\c_spac_lines_correction_mode#1% + \edef\m_spac_lines_around{#2}% \spac_lines_action_around \d_spac_prevdepth\prevdepth \spac_lines_initialize_corrections @@ -548,7 +551,7 @@ \fi \ignorespaces} -\unexpanded\def\spac_lines_stop_correction +\protected\def\spac_lines_stop_correction {\removeunwantedspaces \egroup \ifgridsnapping @@ -558,14 +561,14 @@ \fi \endgroup} -\unexpanded\def\spac_lines_stop_correction_ongrid +\protected\def\spac_lines_stop_correction_ongrid {\directcheckedvspacing\v!white % \blank[\v!white]% \spac_lines_action_around \snaptogrid\hpack{\box\scratchbox}% \directcheckedvspacing\v!white \spac_lines_action_around} -\unexpanded\def\spac_lines_stop_correction_normal +\protected\def\spac_lines_stop_correction_normal {\directcheckedvspacing\v!nowhite % \blank[\v!nowhite]% \ifdim\parskip>\zeropoint % too fuzzy otherwise @@ -616,16 +619,16 @@ % todo: -\unexpanded\def\correctwhitespace +\permanent\protected\def\correctwhitespace {\dowithnextboxcs\correctwhitespacefinish\vbox} -\unexpanded\def\correctwhitespacefinish +\permanent\protected\def\correctwhitespacefinish {\startbaselinecorrection \flushnextbox \stopbaselinecorrection} -\unexpanded\def\verticalstrut {\vpack{\hsize\zeropoint\forgetall\strut}} -\unexpanded\def\horizontalstrut{\hpack {\strut}} +\permanent\protected\def\verticalstrut {\vpack{\hsize\zeropoint\forgetall\strut}} +\permanent\protected\def\horizontalstrut{\hpack {\strut}} %D Here follow some presets related to interline spacing and therefore also struts. %D The values 2.8, 0.07, 0.72 and 0.28 originate in \INRSTEX, a package that we used @@ -700,19 +703,19 @@ \def\normalizedbodyfontsize{12pt} \fi -\unexpanded\def\topskipcorrection +\permanent\protected\def\topskipcorrection {\simpletopskipcorrection \vskip-\struttotal \verticalstrut} -\unexpanded\def\simpletopskipcorrection +\permanent\protected\def\simpletopskipcorrection {\ifdim\topskip>\openstrutheight % == \vskip\topskipgap \vskip\topskip \vskip-\openstrutheight \fi} -\unexpanded\def\settopskip % the extra test is needed for the lbr family +\permanent\protected\def\settopskip % the extra test is needed for the lbr family {\topskip \ifgridsnapping \zeropoint @@ -735,24 +738,24 @@ \fi \fi} -\unexpanded\def\setmaxdepth +\protected\def\setmaxdepth {\maxdepth\systemmaxdepthfactor\globalbodyfontsize} \newskip \usedbaselineskip % These used to be \normal... but that isn't pretty \newskip \usedlineskip % in the token interface, so thes few now have new \newdimen\usedlineskiplimit % names. They are public but not really user commands. -\unexpanded\def\normalbaselines +\permanent\protected\def\normalbaselines {\baselineskip \usedbaselineskip \lineskip \usedlineskip \lineskiplimit\usedlineskiplimit} -\unexpanded\def\flexiblebaselines +\permanent\protected\def\flexiblebaselines {\baselineskip \usedbaselineskip \lineskip 1\usedlineskip \s!plus 1\s!fill \lineskiplimit\usedlineskiplimit} -\unexpanded\def\setnormalbaselines +\permanent\protected\def\setnormalbaselines % used in overload {\ifdim\normallineheight>\zeropoint \lineheight\normallineheight \fi @@ -779,7 +782,7 @@ \usedlineskiplimit\zeropoint\relax \normalbaselines} -\unexpanded\def\spacing#1% vertical +\permanent\protected\def\spacing#1% vertical {\ifgridsnapping \let\spacingfactor\plusone \else @@ -790,10 +793,10 @@ \setnormalbaselines \setstrut} -% \unexpanded\def\forgetverticalstretch % \forgetspacing +% \protected\def\forgetverticalstretch % \forgetspacing % {\spacing\plusone} -\unexpanded\def\forgetverticalstretch +\permanent\protected\def\forgetverticalstretch {\let\spacingfactor \plusone \let\systemtopskipfactor \topskipfactor \let\systemmaxdepthfactor\maxdepthfactor @@ -812,8 +815,8 @@ \let\restoreinterlinespace\relax -\unexpanded\def\saveinterlinespace - {\unexpanded\edef\restoreinterlinespace +\permanent\protected\def\saveinterlinespace + {\protected\edef\restoreinterlinespace {\lineheight \the\lineheight \openstrutheight \the\openstrutheight \openstrutdepth \the\openstrutdepth @@ -844,7 +847,7 @@ \def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox} -% \unexpanded\def\strut +% \protected\def\strut % {\relax % \ifmmode\copy\else\dontleavehmode\unhcopy\fi\strutbox} @@ -852,17 +855,17 @@ %D The double \type {\hbox} construction enables us to backtrack boxes. -\let\strutht\undefined \newdimen\strutht -\let\strutdp\undefined \newdimen\strutdp +\overloaded\let\strutht\undefined \newdimen\strutht +\overloaded\let\strutdp\undefined \newdimen\strutdp -\unexpanded\def\setstrut +\permanent\protected\def\setstrut {\ifgridsnapping \setstrutgridyes \else \setstrutgridnop \fi} -\unexpanded\def\setstrutgridyes +\permanent\protected\def\setstrutgridyes {\strutht\spacingfactor\dimexpr \ifdim\minimumstrutheight>\zeropoint \minimumstrutheight @@ -879,7 +882,7 @@ \relax \dosetstrut} -\unexpanded\def\setstrutgridnop +\permanent\protected\def\setstrutgridnop {\strutht\spacingfactor\dimexpr \ifdim\minimumstrutheight>\zeropoint \minimumstrutheight @@ -896,30 +899,30 @@ \relax \dosetstrut} -\unexpanded\def\setcharstrut#1% +\permanent\protected\def\setcharstrut#1% {\setbox\strutbox\hbox{#1}% no \hpack, in case we have smallcaps \strutht\ht\strutbox \strutdp\dp\strutbox \dosetstrut} -\unexpanded\def\settightstrut +\permanent\protected\def\settightstrut {\setcharstrut{(}} -\unexpanded\def\setfontstrut +\permanent\protected\def\setfontstrut {\setcharstrut{(gplQT}} -\unexpanded\def\setcapstrut% could be M, but Q has descender +\permanent\protected\def\setcapstrut% could be M, but Q has descender {\setcharstrut{Q}} %D Handy for math (used in mathml): -\unexpanded\def\charhtstrut +\permanent\protected\def\charhtstrut {\begingroup \setcharstrut{GJY}% \vrule\s!width\zeropoint\s!depth\zeropoint\s!height\strutht \endgroup} -\unexpanded\def\chardpstrut +\permanent\protected\def\chardpstrut {\begingroup \setcharstrut{gjy}% \vrule\s!width\zeropoint\s!depth\strutdp\s!height\zeropoint @@ -930,8 +933,8 @@ %D an attribute so far have shown that it's slower because testing the attribute %D takes time too. -\unexpanded\def\dosetstrut - {\let\strut\normalstrut +\permanent\protected\def\dosetstrut + {\enforced\let\strut\normalstrut \ifabsnum\dimexpr\strutht+\strutdp-\lineheight\relax<\plustwo % compensate rounding error /- 1sp to avoid too many % 1sp baselineskips in for instance verbatim @@ -1012,18 +1015,18 @@ \ht\strutbox\strutht \dp\strutbox\strutdp} -\unexpanded\def\strut % still callbacks for \hbox{\strut} +\permanent\protected\def\strut % still callbacks for \hbox{\strut} {\relax \dontleavehmode \copy\strutbox} -% \unexpanded\def\strut % slightly faster +% \protected\def\strut % slightly faster % {\relax % \ifmmode\copy\else\dontleavehmode\unhcopy\fi\strutbox} \let\normalstrut\strut -\unexpanded\def\halfstrut +\permanent\protected\def\halfstrut {\relax \dontleavehmode \begingroup @@ -1033,7 +1036,7 @@ \box\scratchbox \endgroup} -\unexpanded\def\quarterstrut +\permanent\protected\def\quarterstrut {\relax \dontleavehmode \begingroup @@ -1043,7 +1046,7 @@ \box\scratchbox \endgroup} -\unexpanded\def\depthstrut +\permanent\protected\def\depthstrut {\relax \dontleavehmode \begingroup @@ -1052,7 +1055,7 @@ \box\scratchbox \endgroup} -\unexpanded\def\halflinestrut +\permanent\protected\def\halflinestrut {\relax \dontleavehmode \begingroup @@ -1061,7 +1064,7 @@ \box\scratchbox \endgroup} -\unexpanded\def\noheightstrut +\permanent\protected\def\noheightstrut {\relax \dontleavehmode \begingroup @@ -1084,10 +1087,7 @@ \installcorenamespace{struts} -\unexpanded\def\setupstrut - {\dosingleempty\spac_struts_setup} - -\def\spac_struts_setup[#1]% +\permanent\tolerant\protected\def\setupstrut[#1]% {\edef\m_strut{#1}% \ifcsname\??struts\m_strut\endcsname \lastnamedcs @@ -1095,7 +1095,7 @@ \setcharstrut\m_strut \fi} -\unexpanded\def\synchronizestrut#1% no [] parsing, faster for internal +\permanent\protected\def\synchronizestrut#1% no [] parsing, faster for internal {\edef\m_strut{#1}% \ifcsname\??struts\m_strut\endcsname \lastnamedcs @@ -1103,38 +1103,38 @@ \setcharstrut\m_strut \fi} -\unexpanded\def\dosynchronizestrut#1% no [] parsing, faster for internal +\permanent\protected\def\dosynchronizestrut#1% no [] parsing, faster for internal {\ifcsname\??struts#1\endcsname \lastnamedcs \else \setcharstrut{#1}% \fi} -\unexpanded\def\showstruts % adapts .. is wrong +\permanent\protected\def\showstruts % adapts .. is wrong {\c_strut_visual_mode\zerocount \setteststrut \settestcrlf} -\unexpanded\def\showcolorstruts % adapts .. is wrong +\permanent\protected\def\showcolorstruts % adapts .. is wrong {\c_strut_visual_mode\plusone \setteststrut \settestcrlf} -\unexpanded\def\setteststrut +\permanent\protected\def\setteststrut {\def\strutwidth{.8pt}% \setstrut} -\unexpanded\def\dontshowstruts +\permanent\protected\def\dontshowstruts {\unsetteststrut \settestcrlf} -\unexpanded\def\unsetteststrut +\permanent\protected\def\unsetteststrut {\let\strutwidth\zeropoint \setstrut} \def\autostrutfactor{1.1} -\unexpanded\def\setautostrut +\permanent\protected\def\setautostrut {\begingroup \setbox\scratchbox\copy\strutbox \setstrut @@ -1150,26 +1150,26 @@ \newtoks\everysetnostrut -\unexpanded\def\setnostrut +\permanent\protected\def\setnostrut {\the\everysetnostrut} \appendtoks \setbox\strutbox\copy\nostrutbox - \let\strut\empty - \let\endstrut\empty - \let\begstrut\empty + \enforced\let\strut \empty + \enforced\let\endstrut\empty + \enforced\let\begstrut\empty \to \everysetnostrut %D When enabled, sigstruts will remove themselves if nothing goes inbetween. For %D practical reasons we define some boundary characters here. -\unexpanded\def\leftboundary {\protrusionboundary\plusone} -\unexpanded\def\rightboundary {\protrusionboundary\plustwo} -\unexpanded\def\signalcharacter{\boundary\plusone\char\zerocount\boundary\plustwo} % not the same as strut signals +\permanent\protected\def\leftboundary {\protrusionboundary\plusone} +\permanent\protected\def\rightboundary {\protrusionboundary\plustwo} +\permanent\protected\def\signalcharacter{\boundary\plusone\char\zerocount\boundary\plustwo} % not the same as strut signals \newsignal\strutsignal \setfalse\sigstruts -\unexpanded\def\begstrut +\permanent\protected\def\begstrut {\relax\ifcase\strutht % \ignorespaces % maybe \else @@ -1198,7 +1198,7 @@ %\boundary\plusone \hskip\zeropoint} -\unexpanded\def\endstrut +\permanent\protected\def\endstrut {\relax\ifhmode \ifcase\strutht % \removeunwantedspaces % maybe @@ -1251,13 +1251,13 @@ % % so: -\unexpanded\def\pseudostrut +\permanent\protected\def\pseudostrut {\noindent} % better: \dontleavehmode \let\pseudobegstrut\pseudostrut \let\pseudoendstrut\removeunwantedspaces -\unexpanded\def\resetteststrut +\permanent\protected\def\resetteststrut {\def\strutwidth{\zeropoint}% no let \setstrut} @@ -1284,17 +1284,21 @@ %D assignment, and |<|don't ask me why|>| this assignment gives troubles in for %D instance the visual debugger. -\unexpanded\def\offinterlineskip +\pushoverloadmode + +\overloaded\permanent\protected\def\offinterlineskip {\baselineskip-\thousandpoint \lineskip \zeropoint \lineskiplimit\maxdimen % We also need this here now; thanks to taco for figuring that out! \def\minimumlinedistance{\zeropoint}} -\unexpanded\def\nointerlineskip +\overloaded\permanent\protected\def\nointerlineskip {\prevdepth-\thousandpoint} -\let\normaloffinterlineskip\offinterlineskip % knuth's original +\aliased\let\normaloffinterlineskip\offinterlineskip % knuth's original + +\popoverloadmode %D This is tricky. The prevdepth value is still set to the last one even if there is %D nothing on the page. The same is true for prevgraf, which doesn't resemble the @@ -1312,19 +1316,19 @@ \let\getnofpreviouslines\!!zerocount \fi -\unexpanded\def\page_otr_synchronize_page_yes +\protected\def\page_otr_synchronize_page_yes {\aftergroup\page_otr_synchronize_page_indeed - \glet\page_otr_synchronize_page\relax} + \global\enforced\let\page_otr_synchronize_page\relax} -% \unexpanded\def\page_otr_synchronize_page_indeed +% \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 -\unexpanded\def\page_otr_synchronize_page_indeed +\protected\def\page_otr_synchronize_page_indeed {\ifx\currentoutputroutine\s!multicolumn\else\clf_synchronizepage\fi - \glet\page_otr_synchronize_page\page_otr_synchronize_page_yes} + \global\enforced\let\page_otr_synchronize_page\page_otr_synchronize_page_yes} \let\page_otr_synchronize_page\page_otr_synchronize_page_yes @@ -1334,18 +1338,20 @@ %D My own one: -\unexpanded\def\spac_helpers_push_interlineskip_yes - {\edef\oninterlineskip +\protected\def\spac_helpers_push_interlineskip_yes + {\enforced\edef\oninterlineskip {\baselineskip \the\baselineskip \lineskip \the\lineskip \lineskiplimit\the\lineskiplimit \noexpand\edef\noexpand\minimumlinedistance{\the\dimexpr\minimumlinedistance}% - \let\noexpand\offinterlineskip\noexpand\normaloffinterlineskip}} % \noexpand not needed + \enforced\let\noexpand\offinterlineskip\noexpand\normaloffinterlineskip}} % \noexpand not needed -\unexpanded\def\spac_helpers_push_interlineskip_nop - {\let\oninterlineskip\setnormalbaselines} +\protected\def\spac_helpers_push_interlineskip_nop + {\enforced\let\oninterlineskip\setnormalbaselines} -\unexpanded\def\offinterlineskip +\pushoverloadmode + +\overloaded\permanent\protected\def\offinterlineskip {\ifdim\baselineskip>\zeropoint \spac_helpers_push_interlineskip_yes \else @@ -1353,14 +1359,16 @@ \fi \normaloffinterlineskip} -\let\oninterlineskip\relax +\permanent\let\oninterlineskip\relax + +\popoverloadmode -\unexpanded\def\resetpenalties#1% +\permanent\protected\def\resetpenalties#1% {\ifdefined#1% \frozen#1\minusone \fi} -\unexpanded\def\setpenalties#1#2#3% +\permanent\protected\def\setpenalties#1#2#3% {\ifdefined#1% space before #3 prevents lookahead problems, needed when #3=text \frozen#1\numexpr#2+\plusone\relax\space\doexpandedrecurse{\the\numexpr#2\relax}{ #3}\zerocount\relax \fi} @@ -1376,16 +1384,16 @@ \newcount\c_spac_keep_lines_together \let\restoreinterlinepenalty\relax -\unexpanded\def\spac_penalties_restore - {\glet\restoreinterlinepenalty\relax - \global\resetpenalties\interlinepenalties +\protected\def\spac_penalties_restore + {\global\enforced\let\restoreinterlinepenalty\relax + \overloaded\global\resetpenalties\interlinepenalties \global\c_spac_keep_lines_together\zerocount} -\unexpanded\def\keeplinestogether#1% +\protected\def\keeplinestogether#1% {\ifnum#1>\c_spac_keep_lines_together \global\c_spac_keep_lines_together#1% - \global\setpenalties\interlinepenalties\c_spac_keep_lines_together\plustenthousand - \glet\restoreinterlinepenalty\spac_penalties_restore + \overloaded\global\setpenalties\interlinepenalties\c_spac_keep_lines_together\plustenthousand + \global\enforced\let\restoreinterlinepenalty\spac_penalties_restore \fi} \def\defaultdisplaywidowpenalty {50} @@ -1404,7 +1412,7 @@ \def\defaultgridfinalhyphendemerits {5000} % always was so \def\defaultgridadjdemerits {10000} % always was so -\unexpanded\def\nopenalties +\permanent\protected\def\nopenalties {\frozen\widowpenalty \zerocount \frozen\clubpenalty \zerocount \frozen\brokenpenalty \zerocount @@ -1412,7 +1420,7 @@ \frozen\finalhyphendemerits \zerocount \frozen\adjdemerits \zerocount} -\unexpanded\def\setdefaultpenalties +\permanent\protected\def\setdefaultpenalties {\directsetup{\systemsetupsprefix\s!default}} \startsetups [\systemsetupsprefix\s!reset] @@ -1472,8 +1480,8 @@ \newbox\b_spac_struts_saved -\unexpanded\def\savestrut {\setbox\b_spac_struts_saved\copy\strutbox} -\unexpanded\def\savedstrut{\copy \b_spac_struts_saved} +\permanent\protected\def\savestrut {\setbox\b_spac_struts_saved\copy\strutbox} +\permanent\protected\def\savedstrut{\copy \b_spac_struts_saved} %D Good old blank redone: @@ -1499,8 +1507,8 @@ \newdimen \globalbodyfontstrutheight \newdimen \globalbodyfontstrutdepth -\def\snappedvboxattribute{\ifgridsnapping attr\snapvboxattribute\c_attr_snapmethod\fi} -\def\setlocalgridsnapping{\ifgridsnapping \c_attr_snapvbox \c_attr_snapmethod\fi} +\permanent\def\snappedvboxattribute{\ifgridsnapping attr\snapvboxattribute\c_attr_snapmethod\fi} +\permanent\def\setlocalgridsnapping{\ifgridsnapping \c_attr_snapvbox \c_attr_snapmethod\fi} \def\spac_grids_set_local_snapping#1% {\ifgridsnapping @@ -1516,7 +1524,7 @@ \lastnamedcs\else#1% \fi}} -\unexpanded\def\installsnapvalues#1#2% +\permanent\protected\def\installsnapvalues#1#2% {\let\m_spac_snapper\empty \rawprocesscommacommand[#2]\spac_grids_expand_snapper \edef\currentsnapper{#1:\m_spac_snapper}% @@ -1529,9 +1537,9 @@ \setevalue{\??gridsnappers#1}{\c_attr_snapmethod\the\scratchcounter\relax}% \letvalue{\??gridsnappersets#1}\m_spac_snapper} -\def\theexpandedsnapperset#1{\begincsname\??gridsnappersets#1\endcsname} % only for manuals +\permanent\def\theexpandedsnapperset#1{\begincsname\??gridsnappersets#1\endcsname} % only for manuals -\unexpanded\def\usegridparameter#1% no checking here +\permanent\protected\def\usegridparameter#1% no checking here {\edef\m_spac_grid_asked{#1\c!grid}% \ifempty\m_spac_grid_asked \c_attr_snapvbox\attributeunsetvalue @@ -1540,10 +1548,7 @@ \c_attr_snapvbox\c_attr_snapmethod \fi} -\unexpanded\def\definegridsnapping - {\dodoubleargument\spac_grids_define} - -\def\spac_grids_define[#1][#2]% +\permanent\tolerant\protected\def\definegridsnapping[#1]#*[#2]% {\installsnapvalues{#1}{#2}} \edef\spac_grids_snap_value_reset @@ -1637,12 +1642,12 @@ \definegridsnapping[\v!math:-\v!line] [\v!math,-\v!line,\v!split] \definegridsnapping[\v!math:-\v!halfline][\v!math,-\v!halfline,\v!split] -\unexpanded\def\synchronizelocallinespecs +\permanent\protected\def\synchronizelocallinespecs {\bodyfontlineheight \normallineheight \bodyfontstrutheight\strutht \bodyfontstrutdepth \strutdp} -\unexpanded\def\synchronizegloballinespecs +\permanent\protected\def\synchronizegloballinespecs {\global\globalbodyfontlineheight \normallineheight \global\globalbodyfontstrutheight\strutht \global\globalbodyfontstrutdepth \strutdp} @@ -1658,7 +1663,7 @@ %D We still have to synchronize these: -\unexpanded\def\synchronizeskipamounts +\permanent\protected\def\synchronizeskipamounts {\bigskipamount \skipfactor\baselineskip \s!plus\skipgluefactor\baselineskip @@ -1669,30 +1674,20 @@ %D Snapping. -\newif\ifgridsnapping - -%unexpanded\def\moveongrid {\dosingleempty\spac_grids_move_on} -\unexpanded\def\snaptogrid {\dosingleempty\spac_grids_snap_to} -\unexpanded\def\placeongrid{\dosingleempty\spac_grids_place_on} +% \newif\ifgridsnapping % already defined -\unexpanded\def\startgridsnapping - {\dosingleempty\spac_grids_start_snapping} - -\unexpanded\def\spac_grids_start_snapping[#1]% +\permanent\tolerant\protected\def\startgridsnapping[#1]% {\snaptogrid[#1]\vbox\bgroup} -\unexpanded\def\stopgridsnapping +\permanent\protected\def\stopgridsnapping {\egroup} -% \def\spac_grids_move_on[#1]% -% {[obsolete]} % gone, unless we set an attribute - -\def\spac_grids_place_on[#1]% +\permanent\tolerant\protected\def\placeongrid[#1]% {\snaptogrid[#1]\vbox} % mark as done -\def\spac_grids_snap_to[#1]% list or predefined +\permanent\tolerant\protected\def\snaptogrid[#1]% list or predefined {\ifgridsnapping - \expandafter\spac_grids_snap_to_indeed + \expandafter\spac_grids_snap_to_indeed % todo: move inline \else \expandafter\gobbleoneargument \fi{#1}} @@ -1723,7 +1718,7 @@ \setsystemmode\v!grid \spac_grids_snap_value_set\askedgridmode} -\unexpanded\def\synchronizegridsnapping +\protected\def\synchronizegridsnapping {\edef\askedgridmode{\layoutparameter\c!grid}% \ifx\askedgridmode\v!no % official \spac_grids_check_nop @@ -1735,10 +1730,10 @@ \spac_grids_check_yes \fi} -\unexpanded\def\setupgridsnapping[#1]% less overhead than setuplayout (needs testing) +\permanent\protected\def\setupgridsnapping[#1]% less overhead than setuplayout (needs testing) {\setlayoutparameter\c!grid{#1}\synchronizegridsnapping} -\unexpanded\def\checkgridmethod#1% +\permanent\protected\def\checkgridmethod#1% {\edef\p_grid{#1}% \ifempty\p_grid \let\checkedgridmethod\empty @@ -1753,7 +1748,7 @@ \fi \fi} -\unexpanded\def\applygridmethod#1#2#3% content localsettings (used in head rendering) +\permanent\protected\def\applygridmethod#1#2#3% content localsettings (used in head rendering) {\checkgridmethod{#1}% \ifx\checkedgridscope\v!global \ifempty\checkedgridmethod \else @@ -1778,13 +1773,13 @@ \egroup \fi} -\unexpanded\gdef\page_layouts_calculate_overshoot +\protected\gdef\page_layouts_calculate_overshoot {\ifgridsnapping\ifcase\layoutlines \getnoflines\textheight \textovershoot\dimexpr\noflines\globalbodyfontlineheight-\textheight\relax \fi\fi} -\unexpanded\def\page_layouts_report_overshoot +\protected\def\page_layouts_report_overshoot {\page_layouts_calculate_overshoot \ifdim\textovershoot>\zeropoint \writestatus\m!layouts{gridmode,\space @@ -1809,7 +1804,7 @@ three=blue, four=gray] -\unexpanded\def\setgridtracebox#1[#2]% % maybe reverse the order +\permanent\protected\def\setgridtracebox#1[#2]% % maybe reverse the order {\setbox\nextbox#1% {\hbox {\hbox to \zeropoint @@ -1821,7 +1816,7 @@ \setnewconstant\gridboxlinenomode\plusone % 0:nothing 1:all 2:lines 3:frame 4:l/r \setnewconstant\gridboxlinemode \plusone -\unexpanded\def\gridboxvbox +\permanent\protected\def\gridboxvbox {\ifcase\gridboxlinemode \vpack \or @@ -1834,9 +1829,9 @@ \ruledvpack \fi} -\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\linewidth} +\permanent\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\linewidth} -\unexpanded\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level +\permanent\protected\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level {\setbox#1\gridboxvbox to #3 % given size {\forgetall \resetvisualizers @@ -1878,7 +1873,7 @@ %D Helper: -\unexpanded\def\spac_helpers_assign_skip#1#2% ook nog \v!halfline+fuzzysnap +\protected\def\spac_helpers_assign_skip#1#2% ook nog \v!halfline+fuzzysnap {\doifelse{#2}\v!line {#1\ifgridsnapping \bodyfontlineheight @@ -1921,21 +1916,20 @@ \installcorenamespace{vspacingamount} -\unexpanded\def\definevspacingamount - {\dotripleempty\spac_vspacing_define_amount} - -\def\spac_vspacing_define_amount[#1][#2][#3]% can be combined - {\ifthirdargument - \setvalue{\??vspacingamount#1}{\ifgridsnapping#3\else#2\fi}% - \orelse\ifsecondargument - \setvalue{\??vspacingamount#1}{\ifgridsnapping\lineheight\else#2\fi}% - \else +\permanent\tolerant\protected\def\definevspacingamount[#1]#*[#2]#*[#3]% can be combined + {\ifarguments + %setvalue{\??vspacingamount#1}{\lineheight}% + \or \setvalue{\??vspacingamount#1}{\lineheight}% + \or + \setvalue{\??vspacingamount#1}{\ifgridsnapping\lineheight\else#2\fi}% + \or + \setvalue{\??vspacingamount#1}{\ifgridsnapping#3\else#2\fi}% \fi \clf_vspacingsetamount{#1}} \def\spac_vspacing_no_topskip % use grouped - {\c_attr_skipcategory\plusten} + {\c_attr_skipcategory\pluseleven} % \installcorenamespace{vspacingamountnormal} % \installcorenamespace{vspacingamountgrid} @@ -1949,13 +1943,10 @@ % \csname g>#1\endcsname{#3}% % \clf_vspacingsetamount{#1}} -\unexpanded\def\definevspacing - {\dodoubleempty\spac_vspacing_define} - -\def\spac_vspacing_define[#1][#2]% +\permanent\tolerant\protected\def\definevspacing[#1]#*[#2]% {\clf_vspacingdefine{#1}{#2}} -%D The injector code (generated at the \LUA\ end): +%D The injector code (generated at the \LUA\ end). This will go away! \newtoks\everybeforeblankhandling \newtoks\everyafterblankhandling @@ -1985,34 +1976,34 @@ \relax \to \everyafterblankhandling -\unexpanded\def\setblankpacked +\permanent\protected\def\setblankpacked {\settrue\c_space_ignore_parskip} -\unexpanded\def\setblankcategory#1% +\permanent\protected\def\setblankcategory#1% {\settrue\c_space_vspacing_done \c_attr_skipcategory#1\relax} -\unexpanded\def\setblankorder#1% +\permanent\protected\def\setblankorder#1% {\c_attr_skiporder#1\relax} -\unexpanded\def\fixedblankskip +\permanent\protected\def\fixedblankskip {\settrue\c_space_vspacing_fixed} -\unexpanded\def\flexibleblankskip +\permanent\protected\def\flexibleblankskip {\setfalse\c_space_vspacing_fixed} -% \unexpanded\def\addblankskip#1#2#3% +% \protected\def\addblankskip#1#2#3% % {\settrue\c_space_vspacing_done % \advance\s_spac_vspacing_temp#1\dimexpr\ifgridsnapping#3\else#2\fi\relax\relax} -\unexpanded\def\setblankpenalty#1% +\permanent\protected\def\setblankpenalty#1% {\flushblankhandling \settrue\c_space_vspacing_done \c_attr_skipcategory\plusthree \c_attr_skippenalty #1\relax \flushblankhandling} -\unexpanded\def\startblankhandling % move this to \vspacing +\permanent\protected\def\startblankhandling % move this to \vspacing {\par \ifvmode \expandafter\dostartblankhandling @@ -2020,16 +2011,16 @@ \expandafter\nostartblankhandling \fi} -\unexpanded\def\nostartblankhandling#1\stopblankhandling +\permanent\protected\def\nostartblankhandling#1\stopblankhandling {} -\def\dostartblankhandling +\permanent\def\dostartblankhandling {\begingroup \setfalse\c_space_vspacing_done \setfalse\c_space_ignore_parskip \the\everybeforeblankhandling} -\unexpanded\def\stopblankhandling +\permanent\protected\def\stopblankhandling {\the\everyafterblankhandling \ifconditional\c_space_vspacing_done \vskip\s_spac_vspacing_temp @@ -2040,30 +2031,37 @@ \endgroup \fi} -\unexpanded\def\flushblankhandling +\permanent\protected\def\flushblankhandling {\the\everyafterblankhandling \ifconditional\c_space_vspacing_done \vskip\s_spac_vspacing_temp + \setfalse\c_space_vspacing_done \fi - \setfalse\c_space_vspacing_done \the\everybeforeblankhandling} -\unexpanded\def\addpredefinedblankskip#1#2% +\permanent\protected\def\addpredefinedblankskip#1#2% {\settrue\c_space_vspacing_done \advance\s_spac_vspacing_temp#1\dimexpr\csname\??vspacingamount#2\endcsname\relax} -% \unexpanded\def\addpredefinedblankskip#1#2% +% \protected\def\addpredefinedblankskip#1#2% % {\settrue\c_space_vspacing_done % \advance\s_spac_vspacing_temp#1\dimexpr\the\csname\ifgridsnapping g\else n\fi>#2\endcsname\relax} -\unexpanded\def\addaskedblankskip#1#2% +\permanent\protected\def\addaskedblankskip#1#2% {\settrue\c_space_vspacing_done \advance\s_spac_vspacing_temp#1\dimexpr#2\relax} % The main spacer: -\unexpanded\def\vspacing - {\doifelsenextoptionalcs\spac_vspacing_yes\spac_vspacing_nop} +% \protected\def\vspacing +% {\doifelsenextoptionalcs\spac_vspacing_yes\spac_vspacing_nop} + +\tolerant\protected\def\vspacing[#1]% + {\ifarguments + \spac_vspacing_yes[\currentvspacing]% in the new mechanism no [] needed + \else + \spac_vspacing_yes[#1]% in the new mechanism no [] needed + \fi} \def\spac_vspacing_yes {\ifinpagebody % somewhat weird @@ -2097,7 +2095,7 @@ \installcorenamespace{vspacing} -\unexpanded\def\directvspacing#1% +\protected\def\directvspacing#1% {\par \ifchkdim#1\or \spac_vspacing_dim_preset{\the\dimexpr#1}% @@ -2131,14 +2129,14 @@ \directvspacing\currentvspacing \fi} -\def\directdefaultvspacing +\permanent\protected\def\directdefaultvspacing {\ifinpagebody % somewhat weird \directvspacing\currentvspacing \orelse\ifconditional\c_spac_packed_blank \directvspacing\currentvspacing \fi} -\def\directcheckedvspacing +\permanent\protected\def\directcheckedvspacing {\ifinpagebody % somewhat weird \expandafter\directvspacing \orelse\ifconditional\c_spac_packed_blank @@ -2147,7 +2145,7 @@ \expandafter\gobbleoneargument \fi} -\unexpanded\def\useblankparameter#1% faster local variant +\permanent\protected\def\useblankparameter#1% faster local variant {\edef\m_spac_blank_asked{#1\c!blank}% \ifempty\m_spac_blank_asked\else \directvspacing\m_spac_blank_asked @@ -2155,7 +2153,7 @@ %D Handy (and faster): -\unexpanded\def\directvpenalty#1% +\permanent\protected\def\directvpenalty#1% {\begingroup \c_attr_skipcategory\plusthree \c_attr_skippenalty #1\relax @@ -2163,7 +2161,7 @@ \vskip\zeropoint \endgroup} -\unexpanded\def\directvskip#1% +\permanent\protected\def\directvskip#1% {\begingroup \c_attr_skipcategory\plusone \c_attr_skippenalty \attributeunsetvalue @@ -2173,27 +2171,23 @@ %D These depend on bigskipamount cum suis so we'd better sync them: -\unexpanded\def\setupvspacing - {\doifelsenextoptionalcs\setupvspacing_yes\setupvspacing_nop} - \let\currentvspacing\s!default % hm, default, standard ... -\def\setupvspacing_yes[#1]% - {\edef\currentvspacing{#1}% - \spac_whitespace_setup_nop % yes or no, was forgotten - } +\permanent\tolerant\protected\def\setupvspacing[#1]% + {\ifarguments\else + \edef\currentvspacing{#1}% + \fi + \synchronizevspacing} -\def\setupvspacing_nop +\permanent\protected\def\synchronizevspacing {\ifempty\currentvspacing % mistakenly had an \else \let\currentvspacing\s!default \fi \spac_whitespace_setup_nop} -\unexpanded\def\restorestandardblank % or default ? +\permanent\protected\def\restorestandardblank % or default ? {\let\currentvspacing\v!standard} -\let\synchronizevspacing\setupvspacing_nop - %D The \type {category:4} is default. \definevspacingamount[\v!none] [\zeropoint] [\zeropoint] @@ -2210,7 +2204,7 @@ \definevspacingamount[\v!standard] [.75\openlineheight] [.75\openlineheight] % mkii compatible -\def\bodyfontwhitespace +\permanent\def\bodyfontwhitespace {\dimexpr \ifzeropt\parskip \zeropoint @@ -2274,7 +2268,7 @@ % 2019-05-31 : upgraded a bit to more distinctive samepage-[level]-[0|1|2] names -\unexpanded\def\spac_vspacing_define_same_step#1#2% alternatively we could have samepage-n-m +\protected\def\spac_vspacing_define_same_step#1#2% alternatively we could have samepage-n-m {\begingroup \scratchcounterone\numexpr\plusthree*#1+#2\relax \scratchcountertwo\numexpr\c_spac_vspacing_special_base+\c_spac_vspacing_special_step*\scratchcounterone\relax @@ -2282,7 +2276,7 @@ \normalexpanded{\definevspacing[\v!samepage-\number#1-\number#2][penalty:\the\scratchcountertwo]}% \endgroup} -\unexpanded\def\spac_vspacing_define_same_page#1% +\protected\def\spac_vspacing_define_same_page#1% {\dostepwiserecurse\c_spac_vspacing_special_done{#1}\plusone {\spac_vspacing_define_same_step\recurselevel\zerocount % before \spac_vspacing_define_same_step\recurselevel\plusone % after @@ -2311,12 +2305,12 @@ % We keep this one as reference % -% \unexpanded\def\inhibitblank +% \protected\def\inhibitblank % {\vspacing[\v!disable]} % % but use the following more efficient variant instead: -\unexpanded\def\inhibitblank +\permanent\protected\def\inhibitblank {\ifvmode \begingroup \c_attr_skipcategory\plusfive @@ -2337,30 +2331,27 @@ \installcorenamespace{vspace} -\unexpanded\def\definevspace - {\dotripleempty\spac_vspace_define} - -\def\spac_vspace_define[#1][#2][#3]% - {\ifthirdargument - \setvalue{\??vspace#1:#2}{#3}% - \else +\permanent\tolerant\protected\def\definevspace[#1]#*[#2]#*[#3]% + {\ifarguments + \or + \letvalue{\??vspace:#1}\empty % or undefined? + \or \setvalue{\??vspace:#1}{#2}% + \or + \setvalue{\??vspace#1:#2}{#3}% \fi} \letvalue{\??vspace:\s!unknown}\zeropoint -\unexpanded\def\vspace - {\dodoubleempty\spac_vspace_inject} - \def\spac_vspace_unknown {\csname\??vspace:\s!unknown\endcsname} -\def\spac_vspace_inject[#1][#2]% use \lastnamedcs +\permanent\tolerant\protected\def\vspace[#1]#*[#2]% {\par \ifvmode \removelastskip \vskip - \ifsecondargument + \ifparameter#2\or \ifcsname\??vspace#1:#2\endcsname \lastnamedcs \orelse\ifcsname\??vspace:#2\endcsname @@ -2368,7 +2359,7 @@ \else \spac_vspace_unknown \fi - \orelse\iffirstargument + \orelse\ifparameter#1\or \ifcsname\??vspace:#1\endcsname \lastnamedcs \else @@ -2395,26 +2386,25 @@ \c!location=\v!left, \c!n=\zerocount] -\unexpanded\def\starthanging - {\dontleavehmode\bgroup - \dosingleempty\spac_hanging_start} - -\unexpanded\def\stophanging - {\endgraf - \egroup} - \let\m_spac_hanging_location\empty -\def\spac_hanging_start[#1]% - {\doifelseassignment{#1} - {\let\m_spac_hanging_location\empty - \setupcurrenthanging[#1]}% - {\edef\m_spac_hanging_location{#1}}% +\permanent\tolerant\protected\def\starthanging[#1]% + {\dontleavehmode\bgroup + \ifhastok={#1}% + \let\m_spac_hanging_location\empty + \setupcurrenthanging[#1]% + \else + \edef\m_spac_hanging_location{#1}% + \fi \ifempty\m_spac_hanging_location \edef\m_spac_hanging_location{\directhangingparameter\c!location}% \fi \dowithnextboxcs\spac_hanging_finish\hbox} +\permanent\protected\def\stophanging + {\endgraf + \egroup} + \def\spac_hanging_finish {\scratchdistance\directhangingparameter\c!distance\relax \ifdim\ht\nextbox>\strutht @@ -2440,7 +2430,6 @@ \fi \ignorespaces} - %D \macros %D {startfixed} %D @@ -2465,34 +2454,33 @@ \installcorenamespace{fixedalternatives} -\unexpanded\def\startfixed - {\bgroup - \dosingleempty\typo_fixed_start} +\let\stopfixed\relax -\def\typo_fixed_start - {\ifhmode +\permanent\protected\def\startfixed + {\bgroup + \ifhmode \expandafter\typo_fixed_start_h \else \expandafter\typo_fixed_start_v \fi} -\def\typo_fixed_start_h[#1]% - {\let\stopfixed\typo_fixed_stop_h +\tolerant\def\typo_fixed_start_h[#1]% + {\enforced\let\stopfixed\typo_fixed_stop_h \dowithnextbox{\typo_fixed_finish{#1}}% \vbox\bgroup %ignorespaces \setlocalhsize} -\unexpanded\def\typo_fixed_stop_h +\protected\def\typo_fixed_stop_h {%removeunwantedspaces \egroup \egroup} -\def\typo_fixed_start_v[#1]% - {\let\stopfixed\typo_fixed_stop_v +\tolerant\def\typo_fixed_start_v[#1]% + {\enforced\let\stopfixed\typo_fixed_stop_v \startbaselinecorrection} -\unexpanded\def\typo_fixed_stop_v +\protected\def\typo_fixed_stop_v {\stopbaselinecorrection \egroup} @@ -2503,7 +2491,7 @@ \letvalue{\??fixedalternatives\s!unknown}\tbox \letvalue{\??fixedalternatives\s!default}\tbox -\unexpanded\def\typo_fixed_finish#1% +\protected\def\typo_fixed_finish#1% {\expandnamespacevalue\??fixedalternatives{#1}\s!default{\box\nextbox}} % %D Forgotten already: @@ -2534,7 +2522,7 @@ %D Helper: -\unexpanded\def\checkedblank[#1]% +\permanent\protected\def\checkedblank[#1]% {\edef\p_blank{#1}% \ifempty\p_blank % ignore @@ -2550,7 +2538,7 @@ \newskip\prerolledblank -\unexpanded\def\prerollblank[#1]% +\permanent\protected\def\prerollblank[#1]% {\begingroup \edef\p_blank{#1}% \ifempty\p_blank @@ -2588,6 +2576,51 @@ % test \par % test \par -\unexpanded\def\ignoreparskip{\c_spac_vspacing_ignore_parskip\plusone} +\protected\def\ignoreparskip{\c_spac_vspacing_ignore_parskip\plusone} + +% experimental (for the moment only for hh and ws) + +%def\vspacingfromscratchtoks {\scratchdimen\dimexpr\csname\??vspacingamount\the\scratchtoks\endcsname\relax} +\def\vspacingpredefinedvalue#1{\scratchdimen\dimexpr\csname\??vspacingamount#1\endcsname\relax} +%def\vspacingfromtempstring {\scratchdimen\dimexpr\csname\??vspacingamount\tempstring\endcsname\relax} + +\let\spac_vspacing_yes_indeed_old\spac_vspacing_yes_indeed +\let\spac_vspacing_nop_indeed_old\spac_vspacing_nop_indeed +\let\directvspacing_old \directvspacing + +\def\spac_vspacing_yes_indeed_new[#1]% + {\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{#1}\fi\fi} + +\def\spac_vspacing_nop_indeed_new + {\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{\currentvspacing}\fi\fi} + +\protected\def\directvspacing_new#1% +%{\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{#1}\fi\fi} + {\ifmmode\else\par\ifvmode\clf_injectvspacing\ifgridsnapping\plusone\else\zerocount\fi{\iftok{#1}\emptytoks\currentvspacing\else#1\fi}\fi\fi} + +\let\directvpenalty_old\directvpenalty +\let\directvskip_old \directvskip +\let\inhibitblank_old \inhibitblank + +\protected\def\directvpenalty_new#1{\ifmmode\else\par\ifvmode\clf_injectvpenalty#1\relax\fi\fi} +\protected\def\directvskip_new #1{\ifmmode\else\par\ifvmode\clf_injectvskip #1\relax\fi\fi} +\protected\def\inhibitblank_new {\ifmmode\else\par\ifvmode\clf_injectdisable \fi\fi} + +\installtexdirective + {vspacing.experimental} + {\writestatus{vspacing}{enabling experimental handler}% + \let\spac_vspacing_yes_indeed\spac_vspacing_yes_indeed_new + \let\spac_vspacing_nop_indeed\spac_vspacing_nop_indeed_new + \enforced\let\directvspacing\directvspacing_new + \enforced\let\directvpenalty\directvpenalty_new + \enforced\let\directvskip\directvskip_new + \enforced\let\inhibitblank\inhibitblank_new} + {\writestatus{vspacing}{disabling experimental handler}% + \let\spac_vspacing_yes_indeed\spac_vspacing_yes_indeed_old + \let\spac_vspacing_nop_indeed\spac_vspacing_nop_indeed_old + \enforced\let\directvspacing\directvspacing_old + \enforced\let\directvpenalty\directvpenalty_old + \enforced\let\directvskip\directvskip_old + \enforced\let\inhibitblank\inhibitblank_old} \protect \endinput diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf Binary files differindex d3e36d330..4970622c9 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 e449f1238..ceb04ac24 100644 --- a/tex/context/base/mkiv/status-lua.pdf +++ b/tex/context/base/mkiv/status-lua.pdf diff --git a/tex/context/base/mkiv/strc-con.mklx b/tex/context/base/mkiv/strc-con.mklx new file mode 100644 index 000000000..ce7f60176 --- /dev/null +++ b/tex/context/base/mkiv/strc-con.mklx @@ -0,0 +1,1156 @@ +%D \module +%D [ file=strc-con, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Constructions, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Constructions} + +\registerctxluafile{strc-con}{} + +% todo: check why \copy .. probably mkii leftover +% +% todo: check if commands similar to lists +% todo: \strc_constructions_setup_counter\strc_constructions_setup_counter{#1} in setup ... synchronization +% +% ? : \def\showdnlisttext{\constructionparameter\c!listtext} % space in default +% +% maybe: pickup text and store in buffer ... +% +% \@@notemakeconstruction[##1]{}{##2}% +% \expandafter\endgroup\noteparameter\c!next}} +% +% todo: \currentconstructionattribute : can be a counter instead + +%D Constructions are just descriptions but a bit more abstract so that we can +%D conveniently build upon them. They are not really meant for users but module +%D writers might find them useful. We mention a couple of parameters but these are +%D only mentioned because in the shared code we map all resolvers to constructions. +%D +%D On top of constructions we build descriptions, enumerations, notes, labels and +%D maybe some day more. + +\unprotect + +%D Todo: + +\installcorenamespace{construction} + +\installcommandhandler \??construction {construction} \??construction + +\aliased\let\setupconstructions\setupconstruction + +\setupconstructions[% + %c!title=, + %c!text=, + % + %c!style=, + %c!color=, + %c!command=, + %c!align=, + % + %c!headstyle=, + %c!headcolor=, + %c!headalign=, + % + %c!titlestyle=, + %c!titlecolor=, + %c!titlecommand=, + %c!titleleft=, + %c!titleright=, + % + %c!closesymbol=, + %c!closecommand=, + % + \c!alternative=\v!left, + \c!display=\v!yes, + \c!width=7\emwidth, + \c!distance=\emwidth, + \c!stretch=.50, + \c!shrink=.25, + \c!titledistance=.5\emwidth, + %c!hang=, + %c!sample=, + \c!margin=\v!no, + \c!before=\blank, + \c!inbetween=\blank, + \c!after=\blank, + %c!indentnext=, + %c!indenting=, + % + \c!expansion=\v!no, + %c!xmlsetup=, + %s!catcodes=, +] + +%D Constructions and alike uses similar structures. In order to prevent issues +%D we freeze some states. There is some overhead in the intermediate define +%D step (as we could set them directly) but this is more flexible (and looks +%D nicer). Keep in mind that descriptions, enumeration and notations are all +%D independent and that we just remap the resolvers. + +% \defineconstruction[test][handler=description,level=1] +% \defineconstruction[test][parent][handler=description,level=3] + +\installcorenamespace{constructionmain} % frozen after definition +\installcorenamespace{constructionlevel} % frozen after definition +\installcorenamespace{constructionclass} % frozen after definition + +\let\currentconstructionmain \empty +\let\currentconstructionlevel \empty +\let\currentconstructionhandler\empty + +\settrue\c_strc_constructions_define_commands % use with care, might become a proper key + +\appendtoks + \ifx\currentconstructionparent\empty + \letvalue{\??constructionmain\currentconstruction}\currentconstruction + \definelist[\currentconstruction]% goodie + \else + \letvalue{\??constructionmain\currentconstruction}\currentconstructionparent + \definelist[\currentconstruction][\currentconstructionparent]% goodie + \fi + \instance\setevalue{\??constructionlevel\currentconstruction}{\number\constructionparameter\c!level}% + \instance\setevalue{\??constructionclass\currentconstruction}{\constructionparameter\s!handler}% +\to \everydefineconstruction + +\appendtoks + \ifconditional\c_strc_constructions_define_commands + %% \setuevalue{\e!start\currentconstruction}{\strc_constructions_start{\currentconstruction}}% + \instance\setuevalue{\e!start\currentconstruction}{\strc_constructions_start[\currentconstruction]}% + \instance\setuevalue{\e!stop \currentconstruction}{\strc_constructions_stop}% + \fi +\to \everydefineconstruction + +%D Just a basic environment (mostly for testing). We will provide a 'setup' based +%D plugin once the rest is sorted out. + +\tolerant\protected\def\strc_constructions_start[#1]#*[#2]#*[#3]% + {\begingroup + \strc_constructions_initialize{#1}% + \strc_constructions_register[#3][\c!label={\constructionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#2]% + \csname\??constructionstarthandler\currentconstructionhandler\endcsname} + +\protected\def\strc_constructions_stop + {\csname\??constructionstophandler\currentconstructionhandler\endcsname + \endgroup} + +%D As we will build on top of the generic construction mechanism we have handlers +%D as a sort of plug in mechanism. In order to have some consistency we share +%D some namespaces. + +\installcorenamespace{constructioninitializer} +\installcorenamespace{constructionfinalizer} + +\installcorenamespace{constructionmainhandler} +\installcorenamespace{constructioncommandhandler} +\installcorenamespace{constructionstarthandler} +\installcorenamespace{constructionstophandler} + +\installcorenamespace{constructiontexthandler} +\installcorenamespace{constructionnotehandler} + +\protected\def\strc_constructions_initialize#1% class instance + {\edef\currentconstruction{#1}% + \enforced\let\currentconstructionhash\??construction + \let\currentconstructionlistentry\!!zerocount + \enforced\expandafter\let\expandafter\currentconstructionmain \csname\??constructionmain \currentconstruction\endcsname + \enforced\expandafter\let\expandafter\currentconstructionlevel \csname\??constructionlevel\currentconstruction\endcsname + \enforced\expandafter\let\expandafter\currentconstructionhandler\csname\??constructionclass\currentconstruction\endcsname + \csname\??constructioninitializer\currentconstructionhandler\endcsname} + +\protected\def\strc_constructions_finalize + {\csname\??constructionfinalizer\currentconstructionhandler\endcsname + \strc_constructions_discard} + +\newconditional\c_strc_constructions_number_state +\newconditional\c_strc_constructions_title_state + +\protected\setvalue{\??constructioninitializer\v!construction}% + {\setfalse\c_strc_constructions_number_state + \setfalse\c_strc_constructions_title_state} + +\protected\setvalue{\??constructionfinalizer\v!construction}% + {} + +%D We keep the command variant around but rather would move to the start-stop one. +%D Also, passing the title as argument has some history so we need to keep that as +%D well. + +% \ifdefined\dotagsetconstruction \else \let\dotagsetconstruction\relax \fi + +% \startuseMPgraphic{MyFrame} +% picture p ; numeric o ; path a, b ; pair c ; +% p := textext.rt("\FunnyFramed{\currentconstructiontext}") ; +% % p := textext.rt("\wrappedconstruction{\FunnyFramed{\currentconstructiontext}}") ; +% % p := textext.rt("\FunnyFramed{\wrappedconstruction{\currentconstructiontext}}") ; +% % p := textext.rt("\FunnyFramed{\wrappedcurrentconstruction}") ; +% ... +% \stopuseMPgraphic +% +% \defineoverlay[MyFrame][\useMPgraphic{MyFrame}] +% +% \defineframedtext +% [MyText] +% [frame=off, +% background=MyFrame] +% +% \defineenumeration[Theorem] +% [alternative=empty, +% before=\startMyText, +% after=\stopMyText] + +\newtoks\everyconstruction + +\permanent\protected\def\currentconstructiontext + {\begstrut + \csname\??constructiontexthandler\currentconstructionhandler\endcsname + \endstrut} + +\permanent\protected\def\currentconstructionsample + {\begstrut + \constructionparameter\c!text + \p_strc_constructions_sample + \endstrut} + +\permanent\protected\def\wrappedconstruction#1% + {\begingroup + \iftrialtypesetting \else + \currentconstructionsynchronize + \c_attr_destination\currentconstructionattribute\relax + \fi + #1% + \endgroup} + +\permanent\protected\def\wrappedcurrentconstruction + {\begingroup + \iftrialtypesetting \else + \currentconstructionsynchronize + \c_attr_destination\currentconstructionattribute\relax + \fi + \currentconstructiontext + \endgroup} + +\protected\setvalue{\??constructionmainhandler\v!construction}#1% + {\iftrialtypesetting \else + \begingroup + \currentconstructionsynchronize % reinstated + \c_attr_destination\currentconstructionattribute\relax % todo, whole text + \signalcharacter + \endgroup + \fi#1} + +\protected\setvalue{\??constructiontexthandler\v!construction}% + {\begingroup + \useconstructionstyleandcolor\c!headstyle\c!headcolor % move to \currentconstructiontext + \the\everyconstruction + \constructionparameter\c!headcommand + {\strut + \constructionparameter\c!text + \clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax}% + \endgroup} + +\protected\def\strc_constructions_stored_start + {\begingroup % brrr \endgroup elsewhere ... will be sorted out + \csname\??constructionstarthandler\currentconstructionhandler\endcsname} + +\protected\def\strc_constructions_stored_stop + {\csname\??constructionstophandler\currentconstructionhandler\endcsname} + +\newconstant\c_strc_constructions_nested_state % to be redone + +\def\resetconstructions % to be used in e.g. footnotes + {\c_strc_constructions_nested_state\zerocount} + +\protected\setvalue{\??constructioncommandhandler\v!construction}% + {\endgroup} + +\let\p_strc_constructions_sample \empty +\let\p_strc_constructions_align \empty +\let\p_strc_constructions_indenting \empty +\let\p_strc_constructions_width \empty +\let\p_strc_constructions_aligntitle \empty +\let\p_strc_constructions_renderingsetup\empty +\let\p_strc_constructions_headalign \empty +\let\p_strc_constructions_hang \empty +\let\p_strc_constructions_inbetween \empty +\let\p_strc_constructions_closesymbol \empty +\let\p_strc_constructions_distance \empty + +\newconditional\c_strc_constructions_distance_none + +\def\strc_constructions_set_width_and_distance + {\assignwidth + \p_strc_constructions_width + \constructionsheadwidth + {\unhcopy\constructionheadbox} + \constructionsheaddistance} + +\def\strc_constructions_preroll_head#content% + {\setbox\constructionheadbox\hbox + {\forgetall + \dontcomplain + \settrialtypesetting + \csname\??constructionmainhandler\currentconstructionhandler\endcsname#content}} + +\def\strc_constructions_ignore_head + {\constructionsheaddistance\zeropoint + \constructionsheadwidth \zeropoint + % 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 + \constructionparameter\c!before + \begingroup + \edef\currentconstructionalternative{\constructionparameter\c!alternative}% + \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}% + % catch fuzzyness + \ifx\p_strc_constructions_renderingsetup\empty + \letconstructionparameter\c!alternative\v!left + \let\currentconstructionalternative\v!left + \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}% + \else + \doifnotsetups\p_strc_constructions_renderingsetup + {\letconstructionparameter\c!alternative\v!left + \let\currentconstructionalternative\v!left + \edef\p_strc_constructions_renderingsetup{\constructionalternativeparameter\c!renderingsetup}}% + \fi + % + \doadaptleftskip{\constructionparameter\c!margin}% + \setlocalhsize % so we can use \localhsize in width assignments + \edef\p_strc_constructions_distance{\constructionalternativeparameter\c!distance}% + \edef\p_strc_constructions_width{\constructionalternativeparameter\c!width}% + \ifx\p_strc_constructions_distance\v!none + \settrue\c_strc_constructions_distance_none + \constructionsheaddistance\zeropoint + \else + \setfalse\c_strc_constructions_distance_none + \constructionsheaddistance\p_strc_constructions_distance\relax + \ifdim\constructionsheaddistance=\zeropoint + \ifx\p_strc_constructions_width\v!broad + \constructionsheaddistance\emwidth + \orelse\ifx\p_strc_constructions_width\v!line + \constructionsheaddistance\emwidth + \fi + \fi + \fi + % inefficient and not always needed, for instance not with margins so we will make checkers + % per alternative some day (especially in labels this is unwanted overhead) + % + % maybe we should have an option as i cannot oversee the consequences now + % + % \edef\p_strc_constructions_sample{\constructionparameter\c!sample}% + % \ifx\p_strc_constructions_sample\empty + % \strc_constructions_preroll_head\currentconstructiontext + % \else + % \strc_constructions_preroll_head\currentconstructiontextsample + % \fi + % \strc_constructions_set_width_and_distance + % + \strc_constructions_preroll_head\currentconstructiontext + \ifzeropt\wd\constructionheadbox + \strc_constructions_ignore_head + \else + \edef\p_strc_constructions_sample{\constructionparameter\c!sample}% + \ifx\p_strc_constructions_sample\empty + \strc_constructions_set_width_and_distance + \else + \strc_constructions_preroll_head\currentconstructionsample + \ifzeropt\wd\constructionheadbox + \strc_constructions_ignore_head + \else + \strc_constructions_set_width_and_distance + \fi + \fi + \fi + % + \dostarttagged\t!constructiontag\empty % todo + \setbox\constructionheadbox\hbox + {\forgetall + \dontcomplain + \ifx\currentconstructionalternative\v!serried % brrr, hack, will change + \csname\??constructionmainhandler\currentconstructionhandler\endcsname\currentconstructiontext + \else + \csname\??constructionmainhandler\currentconstructionhandler\endcsname{\boxedconstructionhead\currentconstructiontext}% + \fi}% + \edef\p_strc_constructions_aligntitle{\constructionparameter\c!aligntitle}% + \ifx\p_strc_constructions_aligntitle\v!no + \leftconstructionskip \leftskip + \rightconstructionskip\rightskip + \else + \ifcase\c_strc_constructions_nested_state + \leftconstructionskip \leftskip + \rightconstructionskip\rightskip + \fi + \fi + \edef\p_strc_constructions_align{\constructionparameter\c!align}% + \ifx\p_strc_constructions_align\empty \else + \setupalign[\p_strc_constructions_align]% \use... + \fi + \ifcase\c_strc_constructions_nested_state + \c_strc_constructions_nested_state\plusone + \or + \c_strc_constructions_nested_state\plustwo + \fi + \strc_constructions_close_symbol_reset + % + \edef\p_strc_constructions_headalign{\constructionparameter\c!headalign}% + % + \directsetup\p_strc_constructions_renderingsetup\relax + % moved to here 2014-07-03 + \edef\p_strc_constructions_indenting{\constructionparameter\c!indenting}% + \ifx\p_strc_constructions_indenting\empty \else + \indenting[\p_strc_constructions_indenting]% \use... + \fi + % + \dostoptagged % tag + \dostarttagged\t!constructioncontent\empty + %\freezeparagraphproperties + \updateparagraphshapes + \ignorespaces} % args not needed + +\protected\setvalue{\??constructionstophandler\v!construction}% + {\strc_constructions_close_symbol_place + \doifnot{\constructionparameter\c!display}\v!no\par + \dostoptagged % content + \dostoptagged % construction + \endgroup + \constructionparameter\c!after + \useindentnextparameter\constructionparameter + \strc_constructions_finalize +% \endgroup + \dorechecknextindentation} + +\protected\def\boxedconstructionhead#1% + {\doifelse{\constructionalternativeparameter\c!alignbottom}{\v!yes}\vbox\vtop + {\hsize\constructionsheadwidth + \edef\p_strc_constructions_headalign{\constructionparameter\c!headalign}% + \ifx\p_strc_constructions_headalign\empty \else + \setupalign[\p_strc_constructions_headalign]% \use... + \fi + #1}} + +\installcorenamespace{constructionalternative} +\installcorenamespace{constructionrenderings} + +% see lists: alternativemethods ... todo +% +% there will be a proper interface to variables + +\installcommandhandler \??constructionalternative {constructionalternative} \??constructionalternative + +\setupconstructionalternative + [%c!left=, % no inheritance + %c!right=,% no inheritance + \c!width=\constructionparameter\c!width, + \c!distance=\constructionparameter\c!distance, + \c!stretch=\constructionparameter\c!stretch, + \c!shrink=\constructionparameter\c!shrink] + +\defineconstructionalternative + [\v!left] + [%\c!width=7em, + %\c!distance=1em, + \c!renderingsetup=\??constructionrenderings:\v!left] + +\defineconstructionalternative + [\v!right] + [%\c!width=7em, + %\c!distance=1em, + \c!renderingsetup=\??constructionrenderings:\v!right] + +\defineconstructionalternative + [\v!inmargin] + [\c!renderingsetup=\??constructionrenderings:\v!inmargin] + +\defineconstructionalternative + [\v!inleft] + [\c!renderingsetup=\??constructionrenderings:\v!inleft] + +\defineconstructionalternative + [\v!inright] + [\c!renderingsetup=\??constructionrenderings:\v!inright] + +\defineconstructionalternative + [\v!margin] + [\c!renderingsetup=\??constructionrenderings:\v!margin] + +\defineconstructionalternative + [\v!leftmargin] + [\c!renderingsetup=\??constructionrenderings:\v!leftmargin] + +\defineconstructionalternative + [\v!rightmargin] + [\c!renderingsetup=\??constructionrenderings:\v!rightmargin] + +\defineconstructionalternative + [\v!innermargin] + [\c!renderingsetup=\??constructionrenderings:\v!innermargin] + +\defineconstructionalternative + [\v!outermargin] + [\c!renderingsetup=\??constructionrenderings:\v!outermargin] + +\defineconstructionalternative + [\v!serried] + [\c!renderingsetup=\??constructionrenderings:\v!serried] + +\defineconstructionalternative + [\v!hanging] + [%\c!width=.75\emwidth + \c!renderingsetup=\??constructionrenderings:\v!hanging] + +\defineconstructionalternative + [\v!top] + [\c!renderingsetup=\??constructionrenderings:\v!top, + \c!width=\localhsize] + +\defineconstructionalternative + [\v!command] + [\c!renderingsetup=\??constructionrenderings:\v!command] + +\defineconstructionalternative + [\v!empty] + [\c!renderingsetup=\??constructionrenderings:\v!empty] + +\defineconstructionalternative + [\v!label] + [\c!renderingsetup=\??constructionrenderings:\v!label, + \c!width=] + +\newbox \constructionheadbox +\newskip \leftconstructionskip +\newskip \rightconstructionskip +\newdimen \constructionsheadwidth % replaces \!!widtha % TODO: proper namespace dimens +\newdimen \constructionsheaddistance % replaces \!!widthb % TODO: proper namespace dimens + +\def\strc_constructions_set_hang_box#1% messy left/rightskip + {\setbox\constructionheadbox\vtop % \vbox gaat fout in hang + {\forgetall + \dontcomplain + \hsize\constructionsheadwidth\relax + \ifx\p_strc_constructions_headalign\empty + \setupalign[#1]% use fast one + \else + \setupalign[\p_strc_constructions_headalign]% use fast one + \fi + \ifconditional\c_strc_constructions_distance_none \else + \advance\ifx#1\v!flushleft\rightskip\else\leftskip\fi\constructionsheaddistance % only difference and wrong anyway + \fi + \flushconstructionheadbox}% + \setbox\constructionheadbox\hpack{\box\constructionheadbox}% needed in case of e.g. a real big head font, see descriptions-006.tex + \ht\constructionheadbox\strutht + \dp\constructionheadbox\strutdp} + +\def\strc_constructions_set_pure_box#1% default ... better set up differently + {\setbox\constructionheadbox\vtop + {\forgetall + \dontcomplain + \hsize\constructionsheadwidth\relax + \ifx\p_strc_constructions_headalign\empty + \setupalign[#1]% use fast one + \else + \setupalign[\p_strc_constructions_headalign]% use fast one + \fi + \flushconstructionheadbox}% + \setbox\constructionheadbox\hpack{\box\constructionheadbox}% needed in case of e.g. a real big head font, see descriptions-006.tex + \ht\constructionheadbox\strutht + \dp\constructionheadbox\strutdp} + +\def\strc_constructions_set_hang#1% + {\ifx\p_strc_constructions_hang\empty + % nothing + \orelse\ifx\p_strc_constructions_hang\v!fit + \scratchdimen\htdp\constructionheadbox + \getnoflines\scratchdimen + \hangafter-\noflines + \orelse\ifx\p_strc_constructions_hang\v!broad + \scratchdimen\dimexpr\htdp\constructionheadbox+.5\strutht\relax + \getnoflines\scratchdimen + \hangafter-\noflines + \else + \hangafter-\p_strc_constructions_hang + \fi + \relax + \hangindent\ifx#1\v!right-\fi\constructionsheadwidth} + +\protected\def\flushconstructionheadbox + {\ifhbox\constructionheadbox\unhbox\else\box\fi\constructionheadbox} + +% The setups. These only deal with placement of the descriptor and initializing the +% environment. The wrapping happens elsewhere. + +% todo: optimize the setups with +% +% \ifconditional\c_strc_constructions_distance_none : no need for skip +% \ifzeropt\wd\constructionheadbox : no need for box and skips + +\startsetups[\??constructionrenderings:\v!left] + \edef\p_strc_constructions_hang{\constructionparameter\c!hang}% + \doifelsesetups{\??constructionrenderings:\v!left:\p_strc_constructions_hang} { + \directsetup{\??constructionrenderings:\v!left:\p_strc_constructions_hang} + } { + \directsetup{\??constructionrenderings:\v!left:\v!hanging} + } +\stopsetups + +\startsetups[\??constructionrenderings:\v!right] + \edef\p_strc_constructions_hang{\constructionparameter\c!hang} + \doifelsesetups{\??constructionrenderings:\v!right:\p_strc_constructions_hang} { + \directsetup{\??constructionrenderings:\v!right:\p_strc_constructions_hang} + } { + \directsetup{\??constructionrenderings:\v!right:\v!hanging} + } +\stopsetups + +\startsetups[\??constructionrenderings:\v!left:\v!none] + \enforced\let\\\crlf + \noindent + \strc_constructions_set_pure_box\v!flushleft + \leftskip\dimexpr\leftconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax + \rightskip\rightconstructionskip\relax + \llap { + \hpack to \leftskip { + \hskip\leftconstructionskip + \box\constructionheadbox % was copy + \hss + } + } + \nobreak + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!left:0] + \directsetup{\??constructionrenderings:\v!left:\v!none} +\stopsetups + +\startsetups[\??constructionrenderings:\v!left:] + \directsetup{\??constructionrenderings:\v!left:\v!none} +\stopsetups + +\startsetups[\??constructionrenderings:\v!right:\v!none] + \enforced\let\\\crlf + \noindent + \leftskip\leftconstructionskip + \rightskip\dimexpr\rightconstructionskip+\constructionsheadwidth\relax + %\strc_constructions_pure_hang_box\raggedleft + \strc_constructions_set_pure_box\v!flushright + \rlap { + \hskip\dimexpr\hsize-\leftskip-\rightskip\relax + \copy\constructionheadbox + \hskip\rightconstructionskip + } + \nobreak + \advance\rightskip \constructionsheaddistance + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!right:0] + \directsetup{\??constructionrenderings:\v!right:\v!none} +\stopsetups + +\startsetups[\??constructionrenderings:\v!right:] + \directsetup{\??constructionrenderings:\v!right:\v!none} +\stopsetups + +\startsetups[\??constructionrenderings:\v!left:\v!margin]% + \enforced\let\\\crlf + \noindent + \strc_constructions_set_pure_box\v!flushleft + \llap { + \hpack to \constructionsheadwidth { + \box\constructionheadbox % was copy + \hss + } + \hskip\constructionsheaddistance + } + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!right:\v!margin]% + \enforced\let\\\crlf + \noindent + \strc_constructions_set_pure_box\v!flushright + \rlap { + \hskip\constructionsheaddistance + \hpack to \constructionsheadwidth { + \box\constructionheadbox % was copy + \hss + } + } + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!left:\v!hanging]% + \enforced\let\\\crlf + \dontcomplain + \advance\constructionsheadwidth \constructionsheaddistance + \strc_constructions_set_hang_box\v!flushleft + \strc_constructions_set_hang\v!left + \noindent + \llap { + \tpack to \zeropoint { + \box\constructionheadbox + } + } + \nobreak + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!right:\v!hanging]% + \enforced\let\\\crlf + \dontcomplain + \advance\constructionsheadwidth \constructionsheaddistance + \strc_constructions_set_hang_box\v!flushright + \strc_constructions_set_hang\v!right + \noindent + \rlap { + \hpack to \dimexpr\hsize-\leftskip-\rightskip\relax { + \hss + \tpack to \zeropoint { + \box\constructionheadbox + } + } + } + \nobreak + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!top] + % \strc_sectioning_prevent_page_break % commented per 31/5/2019 + \enforced\let\\\space + \noindent + \copy\constructionheadbox % why copy ? + \par + \nobreak + \edef\p_strc_constructions_inbetween{\constructionparameter\c!inbetween}% + \ifx\p_strc_constructions_inbetween\empty \else + \p_strc_constructions_inbetween + % shouldn't this move to after the fi? + \directcheckedvspacing\v!samepage + \fi + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +% why copy? historic reason? + +\startsetups[\??constructionrenderings:\v!margin] + \enforced\let\\\crlf + \noindent + \inmargin[\c!scope=\v!local]{\flushconstructionheadbox}% + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!leftmargin] + \enforced\let\\\crlf + \noindent + \inleft[\c!scope=\v!local]{\flushconstructionheadbox}% + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!rightmargin] + \enforced\let\\\crlf + \noindent + \inright[\c!scope=\v!local]{\flushconstructionheadbox}% + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!innermargin] + \enforced\let\\\crlf + \noindent + \ininner[\c!scope=\v!local]{\flushconstructionheadbox}% + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!outermargin] + \enforced\let\\\crlf + \noindent + \inouter[\c!scope=\v!local]{\flushconstructionheadbox}% + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!inmargin] + \directsetup{\??constructionrenderings:\v!margin} +\stopsetups + +\startsetups[\??constructionrenderings:\v!inleft] + \directsetup{\??constructionrenderings:\v!leftmargin} +\stopsetups + +\startsetups[\??constructionrenderings:\v!inright] + \directsetup{\??constructionrenderings:\v!rightmargin} +\stopsetups + +\startsetups[\??constructionrenderings:\v!serried] + % already set? + \edef\p_strc_constructions_width{\constructionparameter\c!width}% CHECK ! ! ! wrong parameter namespace + \doifelsesetups{\??constructionrenderings:\v!serried:\p_strc_constructions_width} { + \directsetup{\??constructionrenderings:\v!serried:\p_strc_constructions_width} + } { + \directsetup{\??constructionrenderings:\v!serried:\v!wide} + } +\stopsetups + +\startsetups[\??constructionrenderings:\v!serried:\v!fit] + \enforced\let\\\crlf + \noindent + \flushconstructionheadbox + \nobreak + \hskip\constructionsheaddistance\relax + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!serried:\v!broad] + \enforced\let\\\crlf + \noindent + \flushconstructionheadbox + \ifconditional\c_strc_constructions_distance_none \else + \nobreak + \hskip\constructionsheaddistance + \s!plus \constructionalternativeparameter\c!stretch\constructionsheaddistance + \s!minus\constructionalternativeparameter\c!shrink \constructionsheaddistance + \relax + \fi + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!serried:] + \directsetup{\??constructionrenderings:\v!serried:\v!broad} +\stopsetups + +\startsetups[\??constructionrenderings:\v!serried:\v!wide] + \enforced\let\\\crlf + \noindent + \hbox to \constructionsheadwidth { + \flushconstructionheadbox + \hss + } + \nobreak + \hskip\constructionsheaddistance\relax + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!hanging] + % tricky: leftskipadaption is somewhat unpredictable + \enforced\let\\\crlf + \noindent + \advance\leftskip-\leftskipadaption\relax + \ifdim\leftskipadaption=\zeropoint + \leftskipadaption1.5\emwidth\relax % just some default + \ifnum\c_strc_constructions_nested_state=\plusone + \ifdim\leftskip>\zeropoint \relax + \leftskipadaption\leftskip + \fi + \fi + \fi + \ifnum\c_strc_constructions_nested_state>\zerocount % was \ifnum\c_strc_constructions_nested_state=\plusone + \advance\leftskip\leftskipadaption % but we're already further on + \fi + \hskip-\leftskipadaption\relax + \ifhbox\constructionheadbox \unhbox\else\box\fi\constructionheadbox + \ifconditional\c_strc_constructions_distance_none \else + % we used to have just a kern, but long lines look bad then + \scratchdistance\ifdim\constructionsheaddistance=\zeropoint .75\emwidth\else\constructionsheaddistance\fi + \hskip \scratchdistance + \s!plus \constructionalternativeparameter\c!stretch\scratchdistance + \s!minus\constructionalternativeparameter\c!shrink \scratchdistance + \fi + \ifhmode + \ifx\p_strc_constructions_width\v!line + \hfill\break + \else + \allowbreak + \fi + \fi + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +%D \starttyping +%D \setupfootnotation[location=command,headcommand=\llap] +%D \stoptyping + +\startsetups[\??constructionrenderings:\v!command] + \noindent + \constructionparameter\c!headcommand{\flushconstructionheadbox} + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!empty] + \noindent + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +\startsetups[\??constructionrenderings:\v!label] + \dontleavehmode + \begingroup + \constructionparameter\c!headcommand{\flushconstructionheadbox} + \endgroup +\stopsetups + +\ifcase\contextlmtxmode \else + % just an empty check so that we can grep for contextlmtxmode in mkiv files +\fi + +% \definedescription[whatever][alternative=right:bottom] +% +% \startwhatever{just a small\\example} +% \input ward +% \stopwhatever + +\defineconstructionalternative + [\v!right:\v!bottom] + [%\c!width=7em, + %\c!distance=1em, + \c!alignbottom=\v!yes, + \c!renderingsetup=\??constructionrenderings:\v!right:\v!bottom] + +\startsetups[\??constructionrenderings:\v!right:\v!bottom] + \enforced\let\\\crlf + \noindent + \leftskip\leftconstructionskip + \rightskip\dimexpr\rightconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax + \parfillskip\zeropoint + \strc_constructions_set_pure_box\v!flushright + \directparwrapper \relax {% + \hfilll + \rlap + {\kern\constructionsheaddistance + \copy\constructionheadbox}% + }% + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +%D This next feature will get an lmtx implementation (probably by using a new generic +%D close mechanism). + +% you can use \placeclosesymbol or \qed to place a symbol at the end of a +% construction + +\installcorenamespace{constructionclosesymbol} + +\let\placeclosesymbol\donothing +\let\qed \donothing + +\def\strc_constructions_close_symbol_reset % no need for global + {\global\expandafter\settrue\csname\??constructionclosesymbol\currentconstruction\endcsname + \let\placeclosesymbol\strc_constructions_close_symbol_place + \let\qed \strc_constructions_close_symbol_place} + +\protected\def\strc_constructions_close_symbol_place + {\ifconditional\csname\??constructionclosesymbol\currentconstruction\endcsname + \global\expandafter\setfalse\csname\??constructionclosesymbol\currentconstruction\endcsname + \edef\p_strc_constructions_closesymbol{\constructionparameter\c!closesymbol}% + \ifx\p_strc_constructions_closesymbol\empty \else + \constructionparameter\c!closecommand{\p_strc_constructions_closesymbol}% hm why {} maybe because box expected + \fi + \fi} + +\newif\ifnoconstructioncaption + +%D The storage macros: + +\let\currentconstructionlistentry\!!zerocount + +\protected\def\strc_constructions_register + {\clf_doifelselisthasentry\numexpr\currentconstructionlistentry\relax + \strc_constructions_register_nop + \strc_constructions_register_yes} + +% \def\strc_constructions_register{\strc_constructions_register_yes} + +\def\strc_constructions_register_nop[#1][#2]% #1=optional user data #2=interfaced-settings + %{\writestatus{constructions}{reusing \currentconstruction: \number\currentconstructionlistentry}} + {} + +\def\strc_constructions_discard + {\iftrialtypesetting + % \writestatus{constructions}{discarding \currentconstruction: \number\currentconstructionlistentry}% + \clf_discardfromlist\currentconstructionlistentry\relax + \fi} + +\let\currentconstructionlistnumber \!!zerocount +\let\currentconstructionsynchronize\relax +\let\currentconstructionattribute \attributeunsetvalue + +\def\strc_constructions_register_yes[#1][#2]% #1=optional user data #2=interfaced-settings + {\begingroup % similar to structure so we might generalize this + \setupcurrentconstruction[#2]% % xdef's will become edef's + \xdef\currentconstructionexpansion {\constructionparameter\c!expansion}% + \xdef\currentconstructionxmlsetup {\constructionparameter\c!xmlsetup}% + \xdef\currentconstructioncatcodes {\constructionparameter\s!catcodes}% + \xdef\currentconstructionlabel {\constructionparameter\c!label}% + \xdef\currentconstructionreference {\constructionparameter\c!reference}% + \xdef\currentconstructionreferenceprefix{\constructionparameter\c!referenceprefix}% + %xdef\currentconstructionshownumber {\constructionparameter\c!number}% + \xdef\currentconstructionincrementnumber{\constructionparameter\c!incrementnumber}% + % + \ifx\currentconstructionexpansion\empty + \glet\currentconstructionexpansion\v!no + \fi + % + \ifx\currentconstructionreferenceprefix\empty + \glet\currentconstructionreferenceprefix\referenceprefix + \fi + \ifx\currentconstructionexpansion\s!xml + \xmlstartraw + \xdef\currentconstructiontitle {\constructionparameter\c!title}% + \xdef\currentconstructionbookmark{\constructionparameter\c!bookmark}% + \xdef\currentconstructionmarking {\constructionparameter\c!marking}% + \xdef\currentconstructionlist {\constructionparameter\c!list}% + \xmlstopraw + \ifx\currentconstructionlist\empty + \glet\currentconstructionlist\currentconstructiontitle + \fi + \glet\currentconstructioncoding\s!xml + \else + \ifx\currentconstructionexpansion\v!yes + \xdef\currentconstructiontitle {\constructionparameter\c!title}% + \xdef\currentconstructionbookmark{\constructionparameter\c!bookmark}% + \xdef\currentconstructionmarking {\constructionparameter\c!marking}% + \xdef\currentconstructionlist {\constructionparameter\c!list}% + \else + \xdef\currentconstructiontitle {\detokenizedconstructionparameter\c!title}% + \xdef\currentconstructionbookmark{\detokenizedconstructionparameter\c!bookmark}% + \xdef\currentconstructionmarking {\detokenizedconstructionparameter\c!marking}% + \xdef\currentconstructionlist {\detokenizedconstructionparameter\c!list}% + \iflocation \ifx\currentconstructionbookmark\empty + \begingroup + \simplifycommands + \xdef\currentconstructionbookmark{\detokenize\expandafter{\normalexpanded{\constructionparameter\c!title}}}% + \endgroup + \fi \fi + \fi + \ifx\currentconstructionlist\empty + \glet\currentconstructionlist\currentconstructiontitle + \fi + \glet\currentconstructioncoding\s!tex + \fi + % + \ifx\currentconstructiontitle\v!none % will become obsolete + \global\noconstructioncaptiontrue\global\noconstructionnumbertrue + \fi + % + \ifnoconstructioncaption % then why analyze anyway? + \endgroup + \let\currentconstructionlistnumber \relax + \let\currentconstructionsynchronize\relax + \let\currentconstructionattribute \relax + \else + \setnextinternalreferences{construction}\currentconstructionmain % plural + \relax + \scratchcounter\clf_addtolist + metadata { + kind {construction} + name {\currentconstructionmain} + % level structures.sections.currentlevel() + catcodes \catcodetable + } + references { + internal \locationcount + order \locationorder + reference {\currentconstructionreference} + prefix {\currentconstructionreferenceprefix} + % block {\currentsectionblock} + % section structures.sections.currentid(), + } + titledata { + label {\detokenize\expandafter{\currentconstructionlabel}} + title {\detokenize\expandafter{\currentconstructiontitle}} + \ifx\currentconstructionbookmark\currentconstructiontitle \else + bookmark {\detokenize\expandafter{\currentconstructionbookmark}} + \fi + \ifx\currentconstructionlist\currentconstructiontitle \else + list {\detokenize\expandafter{\currentconstructionlist}} + \fi + } + \ifconditional\c_strc_constructions_number_state + prefixdata { + prefix {\constructionparameter\c!prefix} + separatorset {\constructionparameter\c!prefixseparatorset} + conversion {\constructionparameter\c!prefixconversion} + conversionset {\constructionparameter\c!prefixconversionset} + set {\constructionparameter\c!prefixset} + segments {\constructionparameter\c!prefixsegments} + connector {\constructionparameter\c!prefixconnector} + } + numberdata { + numbers {\currentconstructionnumber} + separatorset {\constructionparameter\c!numberseparatorset} + conversion {\constructionparameter\c!numberconversion} + conversionset {\constructionparameter\c!numberconversionset} + starter {\constructionparameter\c!numberstarter} + stopper {\constructionparameter\c!numberstopper} + segments {\constructionparameter\c!numbersegments} + } + \or + % symbol + \fi + userdata {\detokenize{#1}} + \relax + % \writestatus{constructions}{registering \currentconstruction: \number\scratchcounter}% + \clf_setinternalreference + prefix {\currentconstructionreferenceprefix}% + reference {\currentconstructionreference}% + internal \locationcount + view {\interactionparameter\c!focus}% + \relax + \normalexpanded {% + \endgroup + \edef\noexpand\currentconstructionlistentry {\the\scratchcounter}% + \edef\noexpand\currentconstructionattribute {\the\lastdestinationattribute}% + \edef\noexpand\currentconstructionsynchronize{\clf_deferredenhancelist\the\scratchcounter}% + }% + \fi} + +% This is not so nice, some day I'll just store the number with the entry +% and deal with all at the Lua end, but first we need to be able to set +% macros. + +\permanent\protected\def\reinstateconstructionnumberentry#1% was xdef + {\edef\currentconstructionattribute {\clf_getinternallistreference#1}% + \edef\currentconstructionsynchronize{\clf_deferredenhancelist\number#1}} + +\permanent\protected\def\reinstatecachedconstructionnumberentry#1% was xdef | #1 = cached index can be different from real + {\edef\currentconstructionattribute {\clf_getinternalcachedlistreference#1}% destination + \edef\currentconstructionsynchronize{\clf_deferredenhancelist\number#1}} + +\installstructurelistprocessor{construction}{\usestructurelistprocessor{number+title}} + +% Helpers: + +\def\currentconstructionnumber{\constructionparameter\s!counter} + +\protected\def\strc_constructions_next_indeed #get#tag#level{\strc_counters_increment_sub{#get{#tag}\s!counter}{#level}} +\protected\def\strc_constructions_reset_indeed#get#tag#level{\strc_counters_reset_sub {#get{#tag}\s!counter}{#level}} + +\protect \endinput diff --git a/tex/context/base/mkiv/strc-con.mkvi b/tex/context/base/mkiv/strc-con.mkvi index 681e813b7..81e28f67f 100644 --- a/tex/context/base/mkiv/strc-con.mkvi +++ b/tex/context/base/mkiv/strc-con.mkvi @@ -620,7 +620,7 @@ \stopsetups \startsetups[\??constructionrenderings:\v!left:\v!none] - \let\\=\crlf + \let\\\crlf \noindent \strc_constructions_set_pure_box\v!flushleft \leftskip\dimexpr\leftconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax @@ -646,7 +646,7 @@ \stopsetups \startsetups[\??constructionrenderings:\v!right:\v!none] - \let\\=\crlf + \let\\\crlf \noindent \leftskip\leftconstructionskip \rightskip\dimexpr\rightconstructionskip+\constructionsheadwidth\relax @@ -672,7 +672,7 @@ \stopsetups \startsetups[\??constructionrenderings:\v!left:\v!margin]% - \let\\=\crlf + \let\\\crlf \noindent \strc_constructions_set_pure_box\v!flushleft \llap { @@ -687,7 +687,7 @@ \stopsetups \startsetups[\??constructionrenderings:\v!right:\v!margin]% - \let\\=\crlf + \let\\\crlf \noindent \strc_constructions_set_pure_box\v!flushright \rlap { @@ -702,7 +702,7 @@ \stopsetups \startsetups[\??constructionrenderings:\v!left:\v!hanging]% - \let\\=\crlf + \let\\\crlf \dontcomplain \advance\constructionsheadwidth \constructionsheaddistance \strc_constructions_set_hang_box\v!flushleft @@ -719,7 +719,7 @@ \stopsetups \startsetups[\??constructionrenderings:\v!right:\v!hanging]% - \let\\=\crlf + \let\\\crlf \dontcomplain \advance\constructionsheadwidth \constructionsheaddistance \strc_constructions_set_hang_box\v!flushright @@ -740,7 +740,7 @@ \startsetups[\??constructionrenderings:\v!top] % \strc_sectioning_prevent_page_break % commented per 31/5/2019 - \let\\=\space + \let\\\space \noindent \copy\constructionheadbox % why copy ? \par @@ -758,7 +758,7 @@ % why copy? historic reason? \startsetups[\??constructionrenderings:\v!margin] - \let\\=\crlf + \let\\\crlf \noindent \inmargin[\c!scope=\v!local]{\flushconstructionheadbox}% \useconstructionstyleandcolor\c!style\c!color @@ -766,7 +766,7 @@ \stopsetups \startsetups[\??constructionrenderings:\v!leftmargin] - \let\\=\crlf + \let\\\crlf \noindent \inleft[\c!scope=\v!local]{\flushconstructionheadbox}% \useconstructionstyleandcolor\c!style\c!color @@ -774,7 +774,7 @@ \stopsetups \startsetups[\??constructionrenderings:\v!rightmargin] - \let\\=\crlf + \let\\\crlf \noindent \inright[\c!scope=\v!local]{\flushconstructionheadbox}% \useconstructionstyleandcolor\c!style\c!color @@ -782,7 +782,7 @@ \stopsetups \startsetups[\??constructionrenderings:\v!innermargin] - \let\\=\crlf + \let\\\crlf \noindent \ininner[\c!scope=\v!local]{\flushconstructionheadbox}% \useconstructionstyleandcolor\c!style\c!color @@ -790,7 +790,7 @@ \stopsetups \startsetups[\??constructionrenderings:\v!outermargin] - \let\\=\crlf + \let\\\crlf \noindent \inouter[\c!scope=\v!local]{\flushconstructionheadbox}% \useconstructionstyleandcolor\c!style\c!color @@ -820,7 +820,7 @@ \stopsetups \startsetups[\??constructionrenderings:\v!serried:\v!fit] - \let\\=\crlf + \let\\\crlf \noindent \flushconstructionheadbox \nobreak @@ -830,7 +830,7 @@ \stopsetups \startsetups[\??constructionrenderings:\v!serried:\v!broad] - \let\\=\crlf + \let\\\crlf \noindent \flushconstructionheadbox \ifconditional\c_strc_constructions_distance_none \else @@ -849,7 +849,7 @@ \stopsetups \startsetups[\??constructionrenderings:\v!serried:\v!wide] - \let\\=\crlf + \let\\\crlf \noindent \hbox to \constructionsheadwidth { \flushconstructionheadbox @@ -863,7 +863,7 @@ \startsetups[\??constructionrenderings:\v!hanging] % tricky: leftskipadaption is somewhat unpredictable - \let\\=\crlf + \let\\\crlf \noindent \advance\leftskip-\leftskipadaption\relax \ifdim\leftskipadaption=\zeropoint @@ -939,7 +939,7 @@ \c!renderingsetup=\??constructionrenderings:\v!right:\v!bottom] \startsetups[\??constructionrenderings:\v!right:\v!bottom] - \let\\=\crlf + \let\\\crlf \noindent \leftskip\leftconstructionskip \rightskip\dimexpr\rightconstructionskip+\constructionsheadwidth+\constructionsheaddistance\relax diff --git a/tex/context/base/mkiv/strc-des.mklx b/tex/context/base/mkiv/strc-des.mklx new file mode 100644 index 000000000..9bdb0e6ea --- /dev/null +++ b/tex/context/base/mkiv/strc-des.mklx @@ -0,0 +1,194 @@ +%D \module +%D [ file=strc-des, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Descriptions, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Descriptions} + +\unprotect + +\installcorenamespace{description} + +\installcommandhandler \??description {description} \??description + +\aliased\let\setupdescriptions\setupdescription + +% \setupdescription % check with old +% [\c!alternative=\descriptionparameter\c!location, +% \c!location=\v!left] + +\setupdescription % check with old + [\c!alternative=\v!left, + \c!headstyle=\v!bold, + \c!titlestyle=\v!bold, + %\c!style=, + %\c!color=, + %\c!headcolor=, + %\c!titlecolor=, + \c!width=7\emwidth, + \c!distance=\emwidth, + \c!titledistance=.5\emwidth, + %\c!hang=, + %\c!sample=, + %\c!align=, + %\c!headalign=, + \c!margin=\v!no, + \c!before=\blank, + \c!inbetween=\blank, + \c!after=\blank, + \c!indentnext=\v!yes, + \c!indenting=\v!never, + \c!titleleft=(, + \c!titleright=), + %\c!closesymbol=, + \c!closecommand=\wordright, + \c!display=\v!yes, + %\c!command=, + \c!titlecommand=, + \c!expansion=\v!no, + %\c!xmlsetup=, + %\s!catcodes=, + \c!title=\v!yes, + %\c!text=, + ] + +\appendtoks + \ifx\currentdescriptionparent\empty + \defineconstruction[\currentdescription][\currentdescriptionparent][\s!handler=\v!description,\c!level=1]% + \else + \defineconstruction[\currentdescription][\s!handler=\v!description,\c!level=1]% + \fi + % We can combine these but in tracing (or errors) using a different caller is nicer. + \instance\setuevalue {\currentdescription}{\strc_descriptions_command[\currentdescription]}% + \instance\setuevalue{\e!start\currentdescription}{\strc_descriptions_start [\currentdescription]}% + \instance\setuevalue{\e!stop \currentdescription}{\strc_descriptions_stop}% +\to \everydefinedescription + +\let\p_strc_constructions_title \empty + +\protected\setvalue{\??constructioninitializer\v!description}% + {\let \currentdescription \currentconstruction + \enforced\let\constructionparameter \descriptionparameter + \enforced\let\constructionnamespace \??description + \enforced\let\detokenizedconstructionparameter\detokenizeddescriptionparameter + \enforced\let\letconstructionparameter \letdescriptionparameter + \enforced\let\useconstructionstyleandcolor \usedescriptionstyleandcolor + \enforced\let\setupcurrentconstruction \setupcurrentdescription + \edef\p_strc_constructions_title{\constructionparameter\c!title}% + \ifx\p_strc_constructions_title\v!yes + \settrue\c_strc_constructions_title_state + \else + \setfalse\c_strc_constructions_title_state + \fi} + +% We keep the command variant around but rather would move to the +% start-stop one. Also, passing the title as argument has some +% history so we need to keep that as well. + +% \startdescription [reference] text \stopdescription +% \startdescription [reference]{title} text \stopdescription +% \startdescription [title=,title=,reference=] text \stopdescription + +% A bit over the top, the optional title but mkii has it too. + +\tolerant\protected\def\strc_descriptions_start[#1]#*[#2]% + {\begingroup + \strc_constructions_initialize{#1}% + \ifhastok={#2}% + \expandafter\strc_descriptions_start_setups + \orelse\ifconditional\c_strc_constructions_title_state + \expandafter\strc_descriptions_start_title + \else + \expandafter\strc_descriptions_start_reference + \fi[#2]} + +\protected\def\strc_descriptions_start_setups[#1]% + {\setfalse\c_strc_constructions_title_state + \strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1]% + \csname\??constructionstarthandler\currentconstructionhandler\endcsname} + +\protected\tolerant\def\strc_descriptions_start_title[#1]#*#=% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]% + \csname\??constructionstarthandler\currentconstructionhandler\endcsname} + +\protected\def\strc_descriptions_start_reference[#1]% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title=,\c!bookmark=,\c!list=]% + \csname\??constructionstarthandler\currentconstructionhandler\endcsname} + +\protected\def\strc_descriptions_stop + {\csname\??constructionstophandler\currentconstructionhandler\endcsname} + +% \description [reference] text \par +% \description [reference] {title} text \par + +\tolerant\protected\def\strc_descriptions_command[#1]#*[#2]#:#*#=% + {\begingroup + \strc_constructions_initialize{#1}% + \ifhastok={#2}% + \expandafter\strc_descriptions_command_setups + \orelse\ifconditional\c_strc_constructions_title_state + \expandafter\strc_descriptions_command_title + \else + \expandafter\strc_descriptions_command_reference + \fi[#2]} + +\protected\def\strc_descriptions_command_setups[#1]% + {\setfalse\c_strc_constructions_title_state + \strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1]% + \csname\??constructioncommandhandler\currentconstructionhandler\endcsname} + +\protected\tolerant\def\strc_descriptions_command_title[#1]#:#*#=% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]% + \csname\??constructioncommandhandler\currentconstructionhandler\endcsname} + +\protected\def\strc_descriptions_command_reference[#1]% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title=,\c!bookmark=,\c!list=]% + \csname\??constructioncommandhandler\currentconstructionhandler\endcsname} + +%D Handlers: + +\expandafter\let\csname\??constructionmainhandler \v!description\expandafter\endcsname\csname\??constructionmainhandler \v!construction\endcsname +\expandafter\let\csname\??constructioncommandhandler\v!description\expandafter\endcsname\csname\??constructioncommandhandler\v!construction\endcsname +\expandafter\let\csname\??constructiontexthandler \v!description\expandafter\endcsname\csname\??constructiontexthandler \v!construction\endcsname + +\protected\setvalue{\??constructioncommandhandler\v!description}% + {\dowithpar + {\csname\??constructionstarthandler\v!construction\endcsname}% + {\csname\??constructionstophandler \v!construction\endcsname\endgroup}} + +\protected\setvalue{\??constructionstarthandler\v!description}% + {\dogotopar + {\csname\??constructionstarthandler\v!construction\endcsname}} + +\protected\setvalue{\??constructionstophandler\v!description}% + {\csname\??constructionstophandler\v!construction\endcsname + \endgroup} + +%D For historic reasons we have (from now on undocumented): + +\definedescription + [tab] + [\c!alternative=\v!left, + \c!headstyle=\v!normal, + \c!headcolor=, + \c!style=\v!normal, + \c!color=, + \c!width=\v!broad, + \c!sample=\kern4\emwidth, % was \hskip but that no longer is okay + \c!before=, + \c!after=] + +\protected\def\setuptab + {\setupdescription[tab]} + +%D Maybe we should remove this definition. + +\protect \endinput diff --git a/tex/context/base/mkiv/strc-enu.mklx b/tex/context/base/mkiv/strc-enu.mklx new file mode 100644 index 000000000..6bc2f39d4 --- /dev/null +++ b/tex/context/base/mkiv/strc-enu.mklx @@ -0,0 +1,375 @@ +%D \module +%D [ file=strc-enu, % moved from strc-des +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Enumerations, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Enumerations} + +\unprotect + +% command -> headcommand + +%D Enumerations are just super descriptions. Therefore we implement +%D them as an extension. After all, the keys don't clash. In order +%D to be able to differentiate between specific settings we use +%D some flags. Unfortunately we have some historic differences +%D in default values. Therefore we push an extra step in the +%D parent chain (we might do the same for regular descriptions). + +%D In order to be more flexible with theorems Aditya Mahajan added +%D support for titles and endsymbols. At the same time we added more +%D flexible support for inheriting numbers. +%D +%D \startbuffer +%D \defineenumeration[one] +%D \defineenumeration[two] [one] % clone one +%D \defineenumeration[three] [counter=one,style=slanted] % only use counter of one +%D \defineenumeration[four] [three] % clone three +%D \defineenumeration[five] [three] [counter=five] % clone three and use own counter +%D \defineenumeration[six] [three] [counter=four] % clone tree and use counter four (undefined) +%D +%D \startone test test 6 \stopone +%D \starttwo test test 7 \stoptwo +%D \startthree test test 8 \stopthree +%D \startfour test test 9 \stopfour +%D \startfive test test 2 \stopfive +%D \startsix test test 10 \stopsix +%D \stopbuffer +%D +%D \typebuffer \start \getbuffer \stop +%D +%D \starttyping +%D \setupenumerations[one] [prefix=yes,prefixsegments=section] +%D \setupenumerations[two] [prefix=yes,prefixsegments=section] +%D \setupenumerations[three][prefix=yes,prefixsegments=section] +%D \setupenumerations[four] [prefix=yes,prefixsegments=chapter:section] +%D \setupenumerations[five] [prefix=yes,prefixsegments=chapter:section] +%D \setupenumerations[six] [prefix=yes,prefixsegments=chapter:section] +%D \stoptyping + +% list and titles are experimental +% +% \definedescription[test] [location=left,hang=4,headalign={right},distance=1em,list=test] +% \defineenumeration[lemma][title=yes,right=:,textdistance=1em, location=top, titlestyle=\bs,list=lemma] +% \defineenumeration[ammel][title=yes,right=:,textdistance=.5em,location=left,titlestyle=\it,width=9em] +% +% \placelist[enumeration:lemma] +% \placelist[description:test][width=0pt] +% +% \starttest {something something something} \input zapf \stoptest +% \startlemma {with a title of a certain length} \input tufte \stoplemma +% \startammel {with a title} \input zapf \stopammel +% +% \defineenumeration[lemma][...] +% \defineenumeration[titledlemma][lemma][title=yes,right=:,text=lemma,list=lemma] + +\installcorenamespace{enumeration} + +\installcommandhandler \??enumeration {enumeration} \??enumeration + +\installcounterassociation{enumeration} + +\let\setupenumerations\setupenumeration + +\setupenumeration % check with old + [\c!alternative=\v!top, + \c!headstyle=\v!bold, + \c!titlestyle=\v!bold, + %\c!style=, + %\c!color=, + %\c!headcolor=, + %\c!titlecolor=, + \c!width=8\emwidth, + %\c!distance=\zeropoint, + \c!distance=\emwidth, + \c!titledistance=.5\emwidth, + %\c!hang=, + %\c!sample=, + %\c!align=, + %\c!headalign=, + \c!margin=\v!no, + \c!before=\blank, + \c!inbetween=\blank, + \c!after=\blank, + \c!indentnext=\v!yes, + \c!indenting=\v!never, + \c!titleleft=(, + \c!titleright=), + %\c!closesymbol=, + \c!closecommand=\wordright, + \c!display=\v!yes, + %\c!command=, + \c!titlecommand=, + \c!expansion=\v!no, + %\c!xmlsetup=, + %\s!catcodes=, + \c!way=\v!by\v!text, + \c!prefix=\v!no, + \c!prefixconnector=., + %\c!starter=, + %\c!stopper=, + \c!text=\currentenumeration, + \c!number=\v!yes, % else description + \c!start=0, + \c!state=\v!start, + \c!levels=4] + +% to be considered: +% +% \let\??construction\??enumeration +% +% with push/pop (also at definition time) + +\protected\def\strc_define_commands_enumeration#tag#level#parent% + {\doifelsenothing{#parent} + {\normalexpanded{\defineconstruction[#tag][\s!handler=\v!enumeration,\c!level=#level]}% + \setevalue{\??enumeration#tag:\s!parent}{\??enumeration}}% + {\normalexpanded{\defineconstruction[#tag][#parent][\s!handler=\v!enumeration,\c!level=#level]}% + \setevalue{\??enumeration#tag:\s!parent}{\??enumeration#parent}}% + \instance\setuevalue{\e!next #tag}{\strc_enumerations_next {#tag}{\number#level}}% obsolete + \instance\setuevalue{\c!reset#tag}{\strc_enumerations_reset {#tag}{\number#level}}% obsolete + %instance\setuevalue{\c!set #tag}{\strc_enumerations_set {#tag}{\number#level}}% obsolete + \instance\setuevalue {#tag}{\strc_enumerations_command[#tag]}% we could pass level here as well (faster) + \instance\setuevalue{\e!start#tag}{\strc_enumerations_start [#tag]}% we could pass level here as well (faster) + \instance\setuevalue{\e!stop #tag}{\strc_enumerations_stop }} + +\appendtoks + \ifx\currentenumerationparent\empty + % clone => parent | subclone => clone | subsubclone => subclone + \let\currentenumerationsub\empty + \strc_define_commands_enumeration + {\currentenumerationsub\currentenumeration}% + \plusone + \empty + \edef\p_levels{\enumerationparameter\c!levels}% + \dostepwiserecurse\plustwo\p_levels\plusone + {\strc_define_commands_enumeration + {\v!sub\currentenumerationsub\currentenumeration}% + \recurselevel + {\currentenumerationsub\currentenumeration}% + \edef\currentenumerationsub{\v!sub\currentenumerationsub}}% + \else + % clone => parent | subclone => subparent | subsubclone => subsubparent + \let\currentenumerationsub\empty + \edef\p_levels{\enumerationparameter\c!levels}% + \dorecurse\p_levels + {\strc_define_commands_enumeration + {\currentenumerationsub\currentenumeration}% + \recurselevel + {\currentenumerationsub\currentenumerationparent}% + \edef\currentenumerationsub{\v!sub\currentenumerationsub}}% + \fi + \edef\p_counter{\enumerationparameter\s!counter}% can inherit from parent + \ifx\p_counter\empty % + \let\p_counter\currentenumeration + \fi + \doifelsecounter\p_counter\donothing{\strc_enumerations_define_counter\p_counter}% + \letenumerationparameter\s!counter\p_counter + %\strc_enumerations_setup_counter\currentenumeration +\to \everydefineenumeration + +\let\p_strc_constructions_title \empty +\let\p_strc_constructions_number\empty + +\protected\setvalue{\??constructioninitializer\v!enumeration}% + {\let \currentenumeration \currentconstruction + \enforced\let\constructionparameter \enumerationparameter + \enforced\let\constructionnamespace \??enumeration + \enforced\let\detokenizedconstructionparameter\detokenizedenumerationparameter + \enforced\let\letconstructionparameter \letenumerationparameter + \enforced\let\useconstructionstyleandcolor \useenumerationstyleandcolor + \enforced\let\setupcurrentconstruction \setupcurrentenumeration + \edef\p_strc_constructions_number{\constructionparameter\c!number}% + \ifx\p_strc_constructions_number\v!yes + \settrue\c_strc_constructions_number_state + \iftrialtypesetting + \strc_counters_save\currentconstructionnumber + \fi + \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel + \else + \setfalse\c_strc_constructions_number_state + \fi + \edef\p_strc_constructions_title{\constructionparameter\c!title}% + \ifx\p_strc_constructions_title\v!yes + \settrue\c_strc_constructions_title_state + \else + \setfalse\c_strc_constructions_title_state + \fi} + +\protected\setvalue{\??constructionfinalizer\v!enumeration}% + {\ifconditional\c_strc_constructions_number_state + \iftrialtypesetting + \strc_counters_restore\currentconstructionnumber + \fi + \fi} + +%D Interfaces: + +\let\strc_enumerations_command\strc_descriptions_command +\let\strc_enumerations_start \strc_descriptions_start +\let\strc_enumerations_stop \strc_descriptions_stop + +\protected\def\strc_enumerations_next {\strc_constructions_next_indeed \namedenumerationparameter} % #1#2 +\protected\def\strc_enumerations_reset{\strc_constructions_reset_indeed\namedenumerationparameter} % #1#2 +%unexpanded\def\strc_enumerations_set {\strc_constructions_set_indeed \namedenumerationparameter} % #1#2 + +%D Counters (maybe we can share this code): (not ok yet, messy with notes) + +% Maybe we should move counters to the construction level as more derived mechanisms +% use it \unknown\ so don't depend on names here! + +\def\strc_enumerations_define_counter#tag% todo: move inline + {\definecounter[#tag]% + \registerenumerationcounter{#tag}} + +\appendtoks + \synchronizeenumerationcounters +\to \everysetupenumeration + +\appendtoks + \synchronizeenumerationcounters +\to \everydefineenumeration + +%D Initializer: + +%D The handlers. + +\newtoks\everyenumeration + +\appendtoks + \disablepseudocaps % sorry, uppercase causes troubles +\to \everyenumeration + +\expandafter\let\csname\??constructionmainhandler \v!enumeration\expandafter\endcsname\csname\??constructionmainhandler \v!description\endcsname +\expandafter\let\csname\??constructioncommandhandler\v!enumeration\expandafter\endcsname\csname\??constructioncommandhandler\v!description\endcsname +\expandafter\let\csname\??constructionstarthandler \v!enumeration\expandafter\endcsname\csname\??constructionstarthandler \v!description\endcsname +\expandafter\let\csname\??constructionstophandler \v!enumeration\expandafter\endcsname\csname\??constructionstophandler \v!description\endcsname + +\protected\setvalue{\??constructiontexthandler\v!enumeration}% + {\begingroup + \useconstructionstyleandcolor\c!headstyle\c!headcolor + \strc_enumerations_text + \endgroup} + +\protected\def\strc_enumerations_text + {\the\everyenumeration % will become obsolete + \ifconditional\c_strc_constructions_number_state + \ifx\currentconstructionreference\!!plustoken + \strc_enumerations_full_number_symbol + \else\ifx\currentconstructionreference\!!minustoken + \strc_enumerations_full_number_nop + \else + \strc_enumerations_full_number_coupling + \fi\fi + \else + \strc_enumerations_full_number_nop + \fi} + +\protected\def\strc_enumerations_inject_text_with_space + {\edef\p_text{\constructionparameter\c!text}% + \ifx\p_text\empty \else + \p_text + \removeunwantedspaces + \nobreakspace + \fi} + +\protected\def\strc_enumerations_inject_extra_text + {\ifconditional\c_strc_constructions_title_state + \clf_doifelselisthastitle{\currentconstructionmain}\numexpr\currentconstructionlistentry\relax + \strc_enumerations_inject_extra_text_indeed + \donothing + \fi} + +\protected\def\strc_enumerations_inject_text + {\constructionparameter\c!numbercommand + {\constructionparameter\c!text}} + +% head ( number title ) + +\protected\def\strc_enumerations_inject_extra_text_indeed + {\begingroup + \hskip\constructionparameter\c!titledistance % we listen to the headstyle + \useconstructionstyleandcolor\c!titlestyle\c!titlecolor + \constructionparameter\c!titlecommand + {\constructionparameter\c!titleleft + \clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax + \constructionparameter\c!titleright}% + \endgroup} + +\protected\def\strc_enumerations_inject_symbol % todo check + {\constructionparameter\c!left + \constructionparameter\c!symbol + \constructionparameter\c!right} + +\protected\def\strc_enumerations_inject_number + {\constructionparameter\c!left + \constructionparameter\c!starter + \clf_savedlistprefixednumber{\currentconstructionmain}\currentconstructionlistentry\relax + \constructionparameter\c!stopper + \constructionparameter\c!right} + +\protected\def\strc_enumerations_inject_text_and_number + {\constructionparameter\c!numbercommand + {\strc_enumerations_inject_text_with_space + \strc_enumerations_inject_number}} + +\protected\def\strc_enumerations_inject_text_and_symbol + {\constructionparameter\c!numbercommand + {\strc_enumerations_inject_text_with_space + \strc_enumerations_inject_symbol}} + +\protected\def\strc_enumerations_full_number_yes + {\constructionparameter\c!headcommand + {\begstrut + \strc_enumerations_inject_text_and_number + \strc_enumerations_inject_extra_text + \endstrut}} + +\protected\def\strc_enumerations_full_number_nop + {\constructionparameter\c!headcommand + {\begstrut + \strc_enumerations_inject_text + \strc_enumerations_inject_extra_text + \endstrut}} + +\protected\def\strc_enumerations_full_number_symbol + {\constructionparameter\c!headcommand + {\begstrut + \strc_enumerations_inject_text_and_symbol + \strc_enumerations_inject_extra_text + \endstrut}} + +% to be used in for instance: +% +% coupling=questions .... coupling=answers +% +% we will provide some more control, like skipping etc or reference relates + +% to do / to be checked + +\protected\def\strc_enumerations_full_number_coupling + {\iflocation + \strc_enumerations_full_number_yes + \else + \iftrialtypesetting \else + % \doenumerationregistercoupling + \fi + \strc_enumerations_full_number_yes + \edef\p_coupling{\constructionparameter\c!coupling}% + \ifx\p_coupling\empty \else + \symbolreference[order(construction:\p_coupling:\the\locationorder)]% + \fi + \fi} + +\protected\def\strc_enumerations_skip_number_coupling[#tag]% e.g. for questions with no answer + {\clf_setnextreferenceorder{construction}{#tag}} + +\protect \endinput diff --git a/tex/context/base/mkiv/strc-flt.lua b/tex/context/base/mkiv/strc-flt.lua index e3a0ea30e..59c67efa1 100644 --- a/tex/context/base/mkiv/strc-flt.lua +++ b/tex/context/base/mkiv/strc-flt.lua @@ -31,13 +31,13 @@ function builders.checksidefloat(mode,indented) return indented end -appendaction ("newgraf","system","builders.checksidefloat") -disableaction("newgraf","builders.checksidefloat") +appendaction ("paragraph","system","builders.checksidefloat") +disableaction("paragraph","builders.checksidefloat") interfaces.implement { name = "enablesidefloatchecker", onlyonce = true, actions = function() - enableaction("newgraf","builders.checksidefloat") + enableaction("paragraph","builders.checksidefloat") end, } diff --git a/tex/context/base/mkiv/strc-flt.mkvi b/tex/context/base/mkiv/strc-flt.mkvi index 91cc3f666..d9fd359c6 100644 --- a/tex/context/base/mkiv/strc-flt.mkvi +++ b/tex/context/base/mkiv/strc-flt.mkvi @@ -211,7 +211,7 @@ \let\strc_floats_define_saved\definefloat -\unexpanded\def\definefloat +\unexpanded\overloaded\def\definefloat {\dotripleempty\strc_floats_define} \def\strc_floats_define[#1][#2][#3]% name+plural+parent | name+parent+settings @@ -1230,7 +1230,7 @@ \let\doifoddpagefloatelse \doifelseoddpagefloat \appendtoks - \let\rightorleftpageaction\doifelserightpagefloat + \overloaded\frozen\let\rightorleftpageaction\doifelserightpagefloat \to \everyinsidefloat % \let\movesidefloat\gobbleoneargument diff --git a/tex/context/base/mkiv/strc-itm.mklx b/tex/context/base/mkiv/strc-itm.mklx index 86d2275d7..aa105af33 100644 --- a/tex/context/base/mkiv/strc-itm.mklx +++ b/tex/context/base/mkiv/strc-itm.mklx @@ -328,7 +328,7 @@ \installcommandhandler \??itemgroup {itemgroup} \??itemgroup -\let\setupitemgroups\setupitemgroup +\aliased\let\setupitemgroups\setupitemgroup \appendtoks \setuevalue{\e!start\currentitemgroup}{\startitemgroup[\currentitemgroup]}% @@ -386,12 +386,12 @@ \vspacing[\v!item @500]% \fi} -\unexpanded\def\strc_itemgroups_process_options#options% +\protected\def\strc_itemgroups_process_options#options% {\processcommacommand[#options]\strc_itemgroups_process_option} % expansion of options is handy for xml % \installcommalistprocessorcommand \strc_itemgroups_process_option_list \strc_itemgroups_process_option % -% \unexpanded\def\strc_itemgroups_process_options#options% +% \protected\def\strc_itemgroups_process_options#options% % {\normalexpanded{\strc_itemgroups_process_option_list[#options]}} % expansion of options is handy for xml \def\strc_itemgroups_process_option#option% @@ -599,29 +599,31 @@ \let\strc_itemgroups_normal_setup\setupitemgroup -\unexpanded\def\setupitemgroup - {\doquadrupleempty\strc_itemgroups_setup} - -\def\strc_itemgroups_setup[#category][#levels][#options][#settings]% category level|each options|settings settings|options - {\edef\strc_itemgroups_setup_what{#levels}% - \iffourthargument +\permanent\overloaded\tolerant\protected\def\setupitemgroup[#category]#spacer[#levels]#spacer[#options]#spacer[#settings]% category level|each options|settings settings|options + {\ifarguments + % nothing to set up + \or + \edef\strc_itemgroups_setup_what{#levels}% + \strc_itemgroups_normal_setup[#category]% == settings + \or + \edef\strc_itemgroups_setup_what{#levels}% + \strc_itemgroups_setup_each{#category}{#levels}% + \or + \edef\strc_itemgroups_setup_what{#levels}% \ifx\strc_itemgroups_setup_what\v!each \strc_itemgroups_setup_each{#category}{#options}% - \strc_itemgroups_setup_each{#category}{#settings}% \else \strc_itemgroups_setup_list{#levels}{#category}{#options}% - \strc_itemgroups_setup_list{#levels}{#category}{#settings}% \fi - \orelse\ifthirdargument + \or + \edef\strc_itemgroups_setup_what{#levels}% \ifx\strc_itemgroups_setup_what\v!each \strc_itemgroups_setup_each{#category}{#options}% + \strc_itemgroups_setup_each{#category}{#settings}% \else \strc_itemgroups_setup_list{#levels}{#category}{#options}% + \strc_itemgroups_setup_list{#levels}{#category}{#settings}% \fi - \orelse\ifsecondargument - \strc_itemgroups_setup_each{#category}{#levels}% - \else - \strc_itemgroups_normal_setup[#category]% == settings \fi} % can be made a bit faster @@ -663,7 +665,7 @@ \fi \fi} -\unexpanded\def\strc_itemgroups_insert_item_counter +\protected\def\strc_itemgroups_insert_item_counter {\ifconditional\c_strc_itemgroups_repeat \ifcase\c_strc_itemgroups_nesting % skip @@ -792,11 +794,9 @@ \advance\d_strc_itemgroups_list_width\itemgroupparameter\c!distance\relax \let\currentitemgroup\savedcurrentitemgroup} -\unexpanded\def\startitemgroup - {\dotripleempty\strc_itemgroups_start} - -\def\strc_itemgroups_start[#category][#options][#settings]% +\permanent\tolerant\protected\def\startitemgroup[#category]#spacer[#options]#spacer[#settings]% {\begingroup % (1) + \nofarguments\lastarguments \def\currentitemgroup{#category}% no nested mixing of itemgroups \let\currentparentitemgroup\currentitemgroup \global\advance\c_strc_itemgroups_nesting\plusone @@ -804,22 +804,26 @@ \normalexpanded{\chaintocurrentitemgroup{\currentparentitemgroup:\currentitemlevel}}% \edef\currentitemgroup{\currentparentitemgroup:\currentitemlevel}% % - \ifthirdargument - \strc_itemgroups_start_indeed[#options][#settings]% - \orelse\ifsecondargument + \edef\itemgroupoptions{\itemgroupparameter\c!option}% + \let\itemgroupextraoptions\empty + \ifcase\nofarguments + \strc_itemgroups_start_indeed{}% + \or + \strc_itemgroups_start_indeed{}% + \or \ifcondition\validassignment{#options}% - \strc_itemgroups_start_indeed[][#options]% + \strc_itemgroups_start_indeed{#options}% \else - \strc_itemgroups_start_indeed[#options][]% + \edef\itemgroupextraoptions{#options}% + \strc_itemgroups_start_indeed{}% \fi - \else - \strc_itemgroups_start_indeed[][]% + \or + \edef\itemgroupextraoptions{#options}% + \strc_itemgroups_start_indeed{#settings}% \fi} -\def\strc_itemgroups_start_indeed[#options][#settings]% - {\edef\itemgroupoptions{\itemgroupparameter\c!option}% - \edef\itemgroupextraoptions{#options}% - \ifempty\itemgroupoptions +\def\strc_itemgroups_start_indeed#settings% + {\ifempty\itemgroupoptions \let\itemgroupoptions\itemgroupextraoptions \orelse\ifempty\itemgroupextraoptions % ok @@ -998,8 +1002,8 @@ % will be redefined in page-mix \ifdefined\startcolumns \else - \unexpanded\def\startcolumns[#settings]{} - \unexpanded\def\stopcolumns {} + \protected\def\startcolumns[#settings]{} + \protected\def\stopcolumns {} \fi \def\strc_itemgroups_start_columns @@ -1015,7 +1019,7 @@ \fi -\unexpanded\def\stopitemgroup +\permanent\protected\def\stopitemgroup {\stopcollectitems \ifconditional\c_strc_itemgroups_text \removeunwantedspaces @@ -1069,9 +1073,6 @@ % The items. -\unexpanded\def\startitemgroupitem - {\dosingleempty\strc_itemgroups_start_item} - \def\strc_itemgroups_start_item_first {\setfalse\c_strc_itemgroups_first % \begingroup % (3) @@ -1133,7 +1134,7 @@ % \stopitemize % \stopitemize -\unexpanded\def\strc_itemgroups_start_item[#reference]% we can reuse more +\tolerant\protected\def\startitemgroupitem[#reference]% we can reuse more {\def\currentitemreference{#reference}% \ifconditional\c_strc_itemgroups_text % begin of item @@ -1171,7 +1172,7 @@ \hskip\d_strc_itemgroups_signal % concat \itemgroupparameter\c!command} -\unexpanded\def\stopitemgroupitem +\protected\def\stopitemgroupitem {\ifhmode \endstrut % new per 2017-12-15 \fi @@ -1180,10 +1181,8 @@ \else \endgraf \fi} -\unexpanded\def\startitemgrouphead - {\dosingleempty\strc_itemgroups_start_head} -\unexpanded\def\strc_itemgroups_start_head[#reference]% +\tolerant\protected\def\startitemgrouphead[#reference]% {\ifconditional\c_strc_itemgroups_first \else \strc_itemgroups_insert_breakallow \fi @@ -1197,23 +1196,24 @@ \fi \fi \fi - \strc_itemgroups_start_item[#reference]% + %\strc_itemgroups_start_item[#reference]% + \startitemgroupitem[#reference]% \pickupgroupedcommand \strc_itemgroups_start_head_indeed \strc_itemgroups_stop_head_indeed \strc_itemgroups_head_body_indeed} -\unexpanded\def\stopitemgrouphead +\protected\def\stopitemgrouphead {\dostoptagged \stopitemgroupitem} -\unexpanded\def\strc_itemgroups_start_head_indeed +\protected\def\strc_itemgroups_start_head_indeed {\settrue\c_strc_itemgroups_head \dotagsetitem\s!head% % weird place \dostarttagged\t!itemhead\empty \useitemgroupstyleandcolor\c!headstyle\c!headcolor\ignorespaces} -\unexpanded\def\strc_itemgroups_stop_head_indeed +\protected\def\strc_itemgroups_stop_head_indeed {\removeunwantedspaces \dostoptagged \ifconditional\c_strc_itemgroups_inline_head @@ -1231,17 +1231,17 @@ \strc_itemgroups_insert_breakno \fi} -\unexpanded\def\strc_itemgroups_head_body_indeed +\protected\def\strc_itemgroups_head_body_indeed {\dostarttagged\t!itembody\empty \noindentation \ignorespaces} % Simple commands. -\unexpanded\def\strc_itemgroups_start_do_item +\protected\def\strc_itemgroups_start_do_item {\startitemgroupitem} -\unexpanded\def\strc_itemgroups_start_no_item +\protected\def\strc_itemgroups_start_no_item {\let\currentitemreference\empty \strc_itemgroups_increment_item_counter %\advance\c_strc_itemgroups_n_of_items\plusone @@ -1249,27 +1249,27 @@ \strc_itemgroups_check_for_repeated \ignorespaces} -\unexpanded\def\strc_itemgroups_start_button[#destination]% +\protected\def\strc_itemgroups_start_button[#destination]% {\edef\m_strc_itemgroups_destination{#destination}% \startitemgroupitem} -\unexpanded\def\strc_itemgroups_start_symbol#text% +\protected\def\strc_itemgroups_start_symbol#text% {\def\strc_itemgroups_extra_symbol{#text}% \settrue\c_strc_itemgroups_symbol \startitemgroupitem \dotagsetitem\s!symbol} -\unexpanded\def\strc_itemgroups_start_dummy +\protected\def\strc_itemgroups_start_dummy {\strc_itemgroups_start_symbol %\strut\strut} % two ? \begstrut} -\unexpanded\def\strc_itemgroups_start_subitem +\protected\def\strc_itemgroups_start_subitem {\settrue\c_strc_itemgroups_sub \startitemgroupitem \dotagsetitem\s!sub} -\unexpanded\def\strc_itemgroups_start_edge#text% +\protected\def\strc_itemgroups_start_edge#text% {\strc_itemgroups_start_symbol {\strc_itemgroups_calculate_list_width\c_strc_itemgroups_nesting \dostarttagged\t!ignore\empty % for the moment, maybe an attribute @@ -1277,7 +1277,7 @@ {#text\hskip\itemgroupparameter\c!distance}% \dostoptagged}} -\unexpanded\def\strc_itemgroups_start_margin#text% +\protected\def\strc_itemgroups_start_margin#text% {\def\strc_itemgroups_margin_symbol % brrr {\dostarttagged\t!ignore\empty % for the moment, maybe an attribute \llap @@ -1290,35 +1290,32 @@ \startitemgroupitem \dotagsetitem\s!margin} -\unexpanded\def\strc_itemgroups_start_text#text% +\protected\def\strc_itemgroups_start_text#text% {\def\strc_itemgroups_extra_symbol{#text}% \settrue\c_strc_itemgroups_symbol \settrue\c_strc_itemgroups_txt \startitemgroupitem} -% \unexpanded\def\strc_itemgroups_start_head +% \protected\def\strc_itemgroups_start_head % {\settrue\c_strc_itemgroups_head % \startitemgrouphead} -\unexpanded\def\strc_itemgroups_start_items +\protected\def\strc_itemgroups_start_items {\dosingleempty\strc_itemgroups_start_items_indeed} -\unexpanded\def\strc_itemgroups_start_items_indeed[#whatever]% something got lost +\protected\def\strc_itemgroups_start_items_indeed[#whatever]% something got lost {\strc_itemgroups_start_edge {\dorecurse{0\itemgroupparameter\c!items}{\strc_itemgroups_used_symbol\hss}% \unskip}} -% \unexpanded\def\startspecialitemgroupitem[#name]% -% {\csname\??itemgroupstart\ifcsname\??itemgroupstart#name\endcsname#name\else\v!item\fi\endcsname} - -\unexpanded\def\startspecialitemgroupitem[#name]% +\protected\def\startspecialitemgroupitem[#name]% todo: frozen {\ifcsname\??itemgroupstart#name\endcsname \expandafter\lastnamedcs \else \expandafter\strc_itemgroups_start_do_item \fi} -\unexpanded\def\stopspecialitemgroupitem +\protected\def\stopspecialitemgroupitem % todo: frozen {\stopitemgroupitem} \letvalue{\??itemgroupstart\v!item}\strc_itemgroups_start_do_item @@ -1329,7 +1326,7 @@ \letvalue{\??itemgroupstart\v!mar }\strc_itemgroups_start_margin \letvalue{\??itemgroupstart\v!txt }\strc_itemgroups_start_text -\def\optimizelistitemsbreak +\def\strc_itemgroups_optimize_breaks {\ifcase\c_strc_itemgroups_column_depth \ifconditional\c_strc_itemgroups_optimize \ifcase\c_strc_itemgroups_max_items @@ -1411,11 +1408,12 @@ \box\b_strc_itemgroups \hss}} % was: \hfill -\unexpanded\def\strc_itemgroups_start_head_sym#text% +\protected\def\strc_itemgroups_start_head_sym#text% {\def\strc_itemgroups_extra_symbol{#text}% \settrue\c_strc_itemgroups_symbol \settrue\c_strc_itemgroups_head - \strc_itemgroups_start_head} + %\strc_itemgroups_start_head} + \startitemgrouphead} \def\strc_itemgroups_make_symbol_box {\setbox\b_strc_itemgroups\autodirhbox @@ -1490,7 +1488,7 @@ \par % done twice? \fi \advance\c_strc_itemgroups_n_of_items\plusone - \optimizelistitemsbreak + \strc_itemgroups_optimize_breaks \strc_itemgroups_check_indenting \dontleavehmode \ifconditional\c_strc_itemgroups_indented_first @@ -1551,7 +1549,7 @@ \setvalue\??itemgroupdistance % catches empty value {\let\m_strc_itemgroups_text_distance\zeropoint} -\unexpanded\def\strc_itemgroups_set_text_item_distance +\protected\def\strc_itemgroups_set_text_item_distance {\edef\m_strc_itemgroups_text_distance{\itemgroupparameter\c!textdistance}% \ifempty\m_strc_itemgroups_text_distance % @@ -1569,45 +1567,45 @@ {\interwordspace \s!plus \emwidth}% {\emwidth \s!plus \interwordstretch\s!minus\interwordshrink}} -% \unexpanded\def\strc_itemgroups_default_command +% \protected\def\strc_itemgroups_default_command % {\EveryPar{\ignorespaces}% needed ? % \ignorespaces} -\unexpanded\def\strc_itemgroups_default_command +\protected\def\strc_itemgroups_default_command {\ignorespaces} %D Special case: -\unexpanded\def\strc_itemgroups_head#text\par +\protected\def\strc_itemgroups_head#text\par {\startitemgrouphead{#text}} %D The local commands: \appendtoks - \let\item \strc_itemgroups_start_do_item - \let\sub \strc_itemgroups_start_subitem - \let\sym \strc_itemgroups_start_symbol - \let\ran \strc_itemgroups_start_edge - \let\its \strc_itemgroups_start_items - \let\mar \strc_itemgroups_start_margin - \let\noitem \strc_itemgroups_start_no_item - \let\itm \strc_itemgroups_start_do_item - \let\but \strc_itemgroups_start_button - \let\nop \strc_itemgroups_start_dummy - \let\txt \strc_itemgroups_start_text - \let\head \strc_itemgroups_head - \let\headsym \strc_itemgroups_start_head_sym - \let\startitem \startitemgroupitem - \let\stopitem \stopitemgroupitem - \let\starthead \startitemgrouphead - \let\stophead \stopitemgrouphead - \let\startspecialitem\startspecialitemgroupitem - \let\stopspecialitem \stopspecialitemgroupitem + \enforced\let\item \strc_itemgroups_start_do_item + \enforced\let\sub \strc_itemgroups_start_subitem + \enforced\let\sym \strc_itemgroups_start_symbol + \enforced\let\ran \strc_itemgroups_start_edge + \enforced\let\its \strc_itemgroups_start_items + \enforced\let\mar \strc_itemgroups_start_margin + \enforced\let\noitem \strc_itemgroups_start_no_item + \enforced\let\itm \strc_itemgroups_start_do_item + \enforced\let\but \strc_itemgroups_start_button + \enforced\let\nop \strc_itemgroups_start_dummy + \enforced\let\txt \strc_itemgroups_start_text + \enforced\let\head \strc_itemgroups_head + \enforced\let\headsym \strc_itemgroups_start_head_sym + \enforced\let\startitem \startitemgroupitem + \enforced\let\stopitem \stopitemgroupitem + \enforced\let\starthead \startitemgrouphead + \enforced\let\stophead \stopitemgrouphead + \enforced\let\startspecialitem\startspecialitemgroupitem + \enforced\let\stopspecialitem \stopspecialitemgroupitem \to \itemgroupcommands \ifx\currentinterface \s!english \else - \def\next#1#2{\ifcsname#1\endcsname\else\let\csname#1\endcsname#2\fi} + \def\next#1#2{\ifcsname#1\endcsname\else\enforced\expandafter\let\csname#1\endcsname#2\fi} \etoksapp\itemgroupcommands{% \next{\v!item }\strc_itemgroups_start_do_item @@ -1666,10 +1664,6 @@ \newcount\c_strc_itemgroups_collected_done \newcount\c_strc_itemgroups_collected_current -% \expandafter\def\expandafter\strc_itemgroups_collected_store\expandafter#\expandafter1\csname\e!stop\v!item\endcsname % use grabuntil -% {\advance\c_strc_itemgroups_collected_stored\plusone -% \setvalue{\??itemgroupstack\number\c_strc_itemgroups_collected_stored}{\startitemgroupitem#1\stopitemgroupitem}} - \let\strc_itemgroups_collected_store\relax \normalexpanded{\def\strc_itemgroups_collected_store#1\csname\e!stop\v!item\endcsname}% @@ -1722,7 +1716,7 @@ \expandafter\strc_itemgroups_collected_flush \fi} -\unexpanded\def\stopcollectitems +\protected\def\stopcollectitems % todo: frozen {\ifconditional\c_strc_itemgroups_collecting \c_strc_itemgroups_collected_done \zerocount \c_strc_itemgroups_collected_current\zerocount @@ -1738,7 +1732,7 @@ \fi \fi} -\unexpanded\def\startcollectitems +\protected\def\startcollectitems % todo: frozen {\ifconditional\c_strc_itemgroups_collecting \c_strc_itemgroups_collected_stored\zerocount \letvalue{\e!start\v!item}\strc_itemgroups_collected_store @@ -1746,7 +1740,7 @@ %D Left-overs: -\unexpanded\def\item +\protected\def\item % todo: frozen {\strc_itemgroups_item_alone} \def\strc_itemgroups_item_alone[#category]#text\par @@ -1754,7 +1748,7 @@ \startitem#text\stopitem \stopitemgroup} -\unexpanded\def\head +\protected\def\head % todo: frozen {\strc_itemgroups_head_alone} \def\strc_itemgroups_head_alone[#category]#head\par#body\par @@ -1762,10 +1756,10 @@ \starthead{#head}#body\stophead \stopitemgroup} -\setuvalue{\e!start\v!item}% +\setuvalue{\e!start\v!item}% todo: frozen {\startitemgroup[\v!itemize]% \startitemgroupitem - \setuvalue{\e!stop\v!item}{\stopitemgroupitem\stopitemgroup}} + \setuvalue{\e!stop\v!item}{\stopitemgroupitem\stopitemgroup}} % todo: frozen % \def\sym#text% % {\noindent @@ -1779,11 +1773,9 @@ %D Something for tables: -\unexpanded\def\itemtag - {\dosingleempty\strc_itemgroups_item_tag} - -\unexpanded\def\strc_itemgroups_item_tag[#reference]% we can reuse more - {\def\currentitemreference{#reference}% +\permanent\tolerant\protected\def\itemtag[#reference]% we can reuse more + {% what if empty + \def\currentitemreference{#reference}% \iftrialtypesetting \strc_counters_save\v_strc_itemgroups_counter \strc_itemgroups_increment_item_counter @@ -1888,8 +1880,8 @@ \global\c_strc_itemgroups_column_depth\zerocount \global\c_strc_itemgroups_nesting \zerocount \glet\currentitemlevel\!!zerocount - \unexpanded\def\startitemize{\startitemgroup[\v!itemize:\v!note]}% - \unexpanded\def\stopitemize {\stopitemgroup}} + \enforced\permanent\protected\def\startitemize{\startitemgroup[\v!itemize:\v!note]}% + \enforced\permanent\protected\def\stopitemize {\stopitemgroup}} \let\strc_itemgroups_pop\relax diff --git a/tex/context/base/mkiv/strc-lab.mkxl b/tex/context/base/mkiv/strc-lab.mkxl new file mode 100644 index 000000000..2de2b1007 --- /dev/null +++ b/tex/context/base/mkiv/strc-lab.mkxl @@ -0,0 +1,198 @@ +%D \module +%D [ file=strc-lab, % was part of strc-des, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Labels, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Labels} + +\unprotect + +% todo: reset and increment will go + +%D Labels are implemented somewhat inefficient but have the advantage that they +%D can be controlled like other constructions. Who knows when that comes in +%D handy? + +\installcorenamespace{labels} + +\installcommandhandler \??labels {label} \??labels % plural hash, else clash with label (or rename that one) + +\installcounterassociation{label} + +\let\setuplabels\setuplabel + +\setuplabel + [\c!alternative=\v!intext, + \c!headstyle=\v!bold, + \c!titlestyle=\v!bold, + \c!distance=\zeropoint, + \c!width=\v!fit, + \c!titledistance=.5\emwidth, + \c!margin=\v!no, + \c!titleleft=(, + \c!titleright=), + \c!display=\v!no, + \c!titlecommand=, + \c!expansion=\v!no, + \c!way=\v!by\v!text, + \c!prefix=\v!no, + \c!prefixconnector=., + \c!text=\currentlabel, + \c!number=\v!yes, % else description + \c!start=0, + \c!state=\v!start, + \c!levels=3] + +\protected\def\strc_define_commands_label#1#2#3% current level parent + {\doifelsenothing{#3} + {\normalexpanded{\defineconstruction[#1][\s!handler=\v!label,\c!level=#2]}% + \setevalue{\??label#1:\s!parent}{\??label}}% + {\normalexpanded{\defineconstruction[#1][#3][\s!handler=\v!label,\c!level=#2]}% + \setevalue{\??label#1:\s!parent}{\??label#3}}% + \ifconditional\c_strc_constructions_define_commands + \setuevalue{\e!next #1}{\strc_labels_next {#1}{\number#2}}% obsolete + \setuevalue{\v!reset #1}{\strc_labels_reset {#1}{\number#2}}% obsolete % should be \e!reset anyway + %setuevalue{\c!set #1}{\strc_labels_set {#1}{\number#2}}% obsolete + \ifcsname\v!current#1\endcsname + % we play safe + \else + \setuevalue{\v!current#1}{\strc_labels_current{#1}}% % obsolete % should be \e!current anyway + \fi + \setuevalue{#1}{\strc_labels_command[#1]}% + \fi} + +% todo: \strc_labels_command for user + +\appendtoks + \ifx\currentlabelparent\empty + % clone => parent | subclone => clone | subsubclone => subclone + \let\currentlabelsub\empty + \strc_define_commands_label + {\currentlabelsub\currentlabel}% + \plusone + \empty + \edef\p_levels{\labelparameter\c!levels}% + \dostepwiserecurse\plustwo\p_levels\plusone + {\strc_define_commands_label + {\v!sub\currentlabelsub\currentlabel}% + \recurselevel + {\currentlabelsub\currentlabel}% + \edef\currentlabelsub{\v!sub\currentlabelsub}}% + \else + % clone => parent | subclone => subparent | subsubclone => subsubparent + \let\currentlabelsub\empty + \edef\p_levels{\labelparameter\c!levels}% + \dorecurse\p_levels + {\strc_define_commands_label + {\currentlabelsub\currentlabel}% + \recurselevel + {\currentlabelsub\currentlabelparent}% + \edef\currentlabelsub{\v!sub\currentlabelsub}}% + \fi + \edef\p_counter{\labelparameter\s!counter}% can inherit from parent + \ifx\p_counter\empty % + \let\p_counter\currentlabel + \fi + \doifelsecounter\p_counter\donothing{\strc_labels_define_counter\p_counter}% + \letlabelparameter\s!counter\p_counter +\to \everydefinelabel + +\let\p_strc_constructions_title \empty +\let\p_strc_constructions_number\empty + +\newconditional\c_strc_constructions_number_keep + +\setvalue{\??constructioninitializer\v!label}% + {\let \currentlabel \currentconstruction + \enforced\let\constructionparameter \labelparameter + \enforced\let\constructionnamespace \??label + \enforced\let\detokenizedconstructionparameter\detokenizedlabelparameter + \enforced\let\letconstructionparameter \letlabelparameter + \enforced\let\useconstructionstyleandcolor \uselabelstyleandcolor + \enforced\let\setupcurrentconstruction \setupcurrentlabel + % shared with enumerations + \edef\p_strc_constructions_number{\constructionparameter\c!number}% + \ifx\p_strc_constructions_number\v!yes + \settrue\c_strc_constructions_number_state + \iftrialtypesetting + \strc_counters_save\currentconstructionnumber + \fi + \ifconditional\c_strc_constructions_number_keep \else + \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel + \fi + \else + \setfalse\c_strc_constructions_number_state + \fi + \edef\p_strc_constructions_title{\constructionparameter\c!title}% + \ifx\p_strc_constructions_title\v!yes + \settrue\c_strc_constructions_title_state + \else + \setfalse\c_strc_constructions_title_state + \fi} + +\setvalue{\??constructionfinalizer\v!label}% + {\ifconditional\c_strc_constructions_number_state + \iftrialtypesetting + \strc_counters_restore\currentconstructionnumber + \fi + \fi} + +%D Interfaces: + +\protected\def\strc_labels_command{\setfalse\c_strc_constructions_number_keep\strc_descriptions_command} +\protected\def\strc_labels_current{\settrue \c_strc_constructions_number_keep\strc_descriptions_command} + +\protected\def\strc_labels_next {\strc_constructions_next_indeed \namedlabelparameter} % #1#2 +\protected\def\strc_labels_reset {\strc_constructions_reset_indeed\namedlabelparameter} % #1#2 +%protected\def\strc_labels_set {\strc_constructions_set_indeed \namedlabelparameter} % #1#2 + +% similar to enumerations + +\def\strc_labels_define_counter#1% + {\definecounter[#1]% + \registerlabelcounter{#1}} + +\appendtoks + \synchronizelabelcounters +\to \everysetuplabel + +\appendtoks + \synchronizelabelcounters +\to \everydefinelabel + +% no start stop here + +\expandafter\let\csname\??constructionmainhandler\v!label\expandafter\endcsname\csname\??constructionmainhandler\v!description\endcsname + +\protected\setevalue{\??constructioncommandhandler\v!label}% + {\csname\??constructionstarthandler\v!construction\endcsname + \csname\??constructionstophandler \v!construction\endcsname + \endgroup} + +\protected\setvalue{\??constructiontexthandler\v!label}% + {\begingroup + \useconstructionstyleandcolor\c!headstyle\c!headcolor + \strc_labels_text + \endgroup} + +\let\strc_labels_text\strc_enumerations_text + +% inline variant + +\defineconstructionalternative + [\v!intext] + [\c!renderingsetup=\??constructionrenderings:\v!intext] + +\startsetups[\??constructionrenderings:\v!intext] + \dontleavehmode\box\constructionheadbox +\stopsetups + +\protect \endinput diff --git a/tex/context/base/mkiv/strc-lst.mkvi b/tex/context/base/mkiv/strc-lst.mkvi index 678c02e15..7a593878c 100644 --- a/tex/context/base/mkiv/strc-lst.mkvi +++ b/tex/context/base/mkiv/strc-lst.mkvi @@ -892,7 +892,7 @@ \appendtoks % better is to use a special list entry but we keep this for compatibility - \let\\=\space + \enforced\let\\\space % so expanding this token register has to come *after* the font switch \dontconvertfont % (**) this has to become an option (see publ) \to \t_lists_every_renderingtext diff --git a/tex/context/base/mkiv/strc-mat.mkiv b/tex/context/base/mkiv/strc-mat.mkiv index fe25e236e..7f5a19154 100644 --- a/tex/context/base/mkiv/strc-mat.mkiv +++ b/tex/context/base/mkiv/strc-mat.mkiv @@ -499,6 +499,8 @@ %D %D Otherwise we get a missing \type {$$} error reported. +\pushoverloadmode + \let\reqno\eqno % no longer valid as we just nil it \let\math_native_leqno\leqno @@ -513,6 +515,8 @@ \let\reqno\normaleqno \let\eqno \normaleqno +\popoverloadmode + %D \macros %D {startsubformulas} diff --git a/tex/context/base/mkiv/strc-not.mklx b/tex/context/base/mkiv/strc-not.mklx new file mode 100644 index 000000000..6e82c9c4e --- /dev/null +++ b/tex/context/base/mkiv/strc-not.mklx @@ -0,0 +1,1972 @@ +%D \module +%D [ file=strc-not, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Note Handling, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Note Handling} + +\registerctxluafile{strc-not}{} + +\unprotect + +% todo: finish local rendering +% todo: more p_strc_notations_* (outside trial loop) +% todo: see if we can now use \insertpenalties (>0 == some left) + +\ifdefined\dotagsetnotesymbol \else \let\dotagsetnotesymbol\relax \fi +\ifdefined\dotagsetnotation \else \let\dotagsetnotation \relax \fi + +\protected\def\unvboxed {\ifvmode\unvbox \else\box \fi} % will change or used more often +\protected\def\unvcopied{\ifvmode\unvcopy\else\copy\fi} % will change or used more often + +%D \LMTX\ testcase: +%D +%D \starttyping +%D \hbox {\hbox{\footnote{HH1}\footnote{HH2}}} \par +%D \hbox {\hbox{x\footnote{XHH1}x\footnote{XHH2}}} \par +%D \vbox {\setbox0\hbox{\footnote{VH1}\footnote{VH2}}\box0} \par +%D \vbox {\hbox{\footnote{VH1}xxx\footnote{VH2}}} \par +%D \vbox {\hbox{\footnote{VH1}\footnote{VH2}} +%D \hbox{\footnote{VH1}\footnote{VH2}}} \par +%D \vbox {\hbox{x\footnote{XVH1}x\footnote{XVH2}}} \par +%D \vbox {\vbox{\footnote{VV1}\footnote{VV2}}} \par % two lines +%D \vbox {\vbox{x\footnote{XVV1}x\footnote{XVV2}}} \par +%D \stoptyping + +%D Notes have two handlers: notations and notes. Although notations can be defined +%D independently it makes not much sense. In principle we can treat notes as lists +%D but they are currently done as a variant on enumerations. I will provide a list +%D variant as well. One complication is that for page related notes inserts are used +%D and therefore notes are typeset immediately and descriptions are better suited +%D for that. For instance endnotes can as well be typeset using lists. + +% textcommand/textstyle/textcolor : set by note commandhandler and used for inline number + +%D \macros +%D {setupnote,setupnotation} +%D +%D We can influence footnote typesetting with the setup command: +%D +%D \showsetup{setupnotation} +%D \showsetup{setupnote} +%D +%D The definition command indicate that we can frame the footnote area. The +%D footnotes themselves are treated as descriptions. +%D +%D \showsetup{definenote} +%D +%D It's sort of a custom to precede footnotes by a horizontal rule and although +%D fancy rules like +%D +%D \starttyping +%D \hbox to 10em{\hskip-3em\dotfill} +%D \stoptyping +%D +%D Are quite ligitimate, we default to a simple one 20\% of the text width. + +% \c!headstyle=\noteparameter\c!style, +% \c!headcolor=\noteparameter\c!color, + +\installcorenamespace{notation} + +\installcommandhandler \??notation {notation} \??notation + +\installcounterassociation{notation} + +\aliased\let\setupnotations\setupnotation + +\definesymbol[\v!note:\v!previouspage][\llap{\low{\symbol[\v!previouspage]}}] +\definesymbol[\v!note:\v!nextpage ][\llap{\low{\symbol[\v!nextpage ]}}] + +\setupnotations % check with old + [\c!alternative=\v!note, + %\c!headstyle=, + %\c!titlestyle=, + %\c!style=, + %\c!color=, + %\c!headcolor=, + %\c!titlecolor=, + \c!numbercommand=\high, + %\c!symbolcommand=\lowllap, % experiment + %\c!indicator=\v!no, % was \v!yes in mkii for page notes + \c!width=\v!fit, + \c!titledistance=.5em, + \c!distance=.5em, + %\c!hang=, + %\c!sample=, + %\c!align=, + %\c!headalign=, + \c!margin=\v!no, + \c!before=, + \c!inbetween=, + \c!after=, + \c!indentnext=\v!yes, + \c!indenting=\v!never, + \c!titleleft=(, + \c!titleright=), + %\c!closesymbol=, + \c!closecommand=\wordright, + \c!display=\v!yes, + %\c!command=, + \c!titlecommand=, + \c!expansion=\v!no, + %\c!xmlsetup=, + %\s!catcodes=, + \c!way=\v!by\v!text, + \c!prefix=\v!no, + \c!prefixconnector=., + %\c!starter=, + %\c!stopper=, + \c!number=\v!yes, + \c!text=, + \c!start=0, + \c!state=\v!start, + \c!levels=3] + +%D The code here is mostly the same as enumerations but we want to keep them +%D isolated and at some point we might differentiate. + +% \installcorenamespace{noteclass} + +\protected\def\strc_define_commands_notation#tag#level#parent% + {\doifelsenothing{#parent} + {\normalexpanded{\defineconstruction[#tag][\s!handler=\v!notation,\c!level=#level]}% + \setevalue{\??notation#tag:\s!parent}{\??notation}}% + {\normalexpanded{\defineconstruction[#tag][#parent][\s!handler=\v!notation,\c!level=#level]}% + \setevalue{\??note #tag:\s!parent}{\??note#parent}% see later for \s!note + \setevalue{\??notation#tag:\s!parent}{\??notation#parent}}% + \instance\setuevalue{\e!next #tag}{\strc_notations_next {#tag}{\number#level}}% obsolete + \instance\setuevalue{\c!reset#tag}{\strc_notations_reset {#tag}{\number#level}}% obsolete + \instance\setuevalue {#tag}{\strc_notations_command[#tag]}% + \instance\setuevalue{\e!start#tag}{\strc_notations_start [#tag]}% + \instance\setuevalue{\e!stop #tag}{\strc_notations_stop }} + +\appendtoks + \ifx\currentnotationparent\empty + % clone => parent | subclone => clone | subsubclone => subclone + \let\currentnotationsub\empty + \strc_define_commands_notation + {\currentnotationsub\currentnotation}% + \plusone + \empty + \edef\p_levels{\notationparameter\c!levels}% + \dostepwiserecurse\plustwo\p_levels\plusone + {\strc_define_commands_notation + {\v!sub\currentnotationsub\currentnotation}% + \recurselevel + {\currentnotationsub\currentnotation}% + \edef\currentnotationsub{\v!sub\currentnotationsub}}% + \definelist[\currentnotation]% goodie + \else + % clone => parent | subclone => subparent | subsubclone => subsubparent + \let\currentnotationsub\empty + \edef\p_levels{\notationparameter\c!levels}% + \dorecurse\p_levels + {\strc_define_commands_notation + {\currentnotationsub\currentnotation}% + \recurselevel + {\currentnotationsub\currentnotationparent}% + \edef\currentnotationsub{\v!sub\currentnotationsub}}% + \definelist[\currentnotation][\currentnotationparent]% goodie + \fi + \edef\p_counter{\notationparameter\s!counter}% can inherit from parent + \ifx\p_counter\empty % + \let\p_counter\currentnotation + \fi + \doifelsecounter\p_counter\donothing{\strc_notes_define_counter\p_counter}% + \letnotationparameter\s!counter\p_counter + %\strc_notes_setup_counter\currentnotation +\to \everydefinenotation + +\let\p_strc_constructions_title \empty +\let\p_strc_constructions_number\empty + +\protected\setvalue{\??constructioninitializer\v!notation}% + {\let \currentnotation \currentconstruction + \enforced\let\constructionparameter \notationparameter + \enforced\let\constructionnamespace \??notation + \enforced\let\detokenizedconstructionparameter\detokenizednotationparameter + \enforced\let\letconstructionparameter \letnotationparameter + \enforced\let\useconstructionstyleandcolor \usenotationstyleandcolor + \enforced\let\setupcurrentconstruction \setupcurrentnotation + \edef\p_strc_constructions_number{\constructionparameter\c!number}% + \ifx\p_strc_constructions_number\v!yes + \settrue\c_strc_constructions_number_state + \iftrialtypesetting + \strc_counters_save\currentconstructionnumber + \fi + %\strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel + \else + \setfalse\c_strc_constructions_number_state + \fi + \edef\p_strc_constructions_title{\constructionparameter\c!title}% + \ifx\p_strc_constructions_title\v!yes + \settrue\c_strc_constructions_title_state + \else + \setfalse\c_strc_constructions_title_state + \fi} + +\protected\setvalue{\??constructionfinalizer\v!notation}% + {\ifconditional\c_strc_constructions_number_state + \iftrialtypesetting + \strc_counters_restore\currentconstructionnumber + \fi + \fi} + +%D Notations (we simply needed a word that relates to notes and is and sounds like +%D description and enumeration) are a special case in the sense that they are +%D stored, rendered elsewhere and referered to from where they are specified. For +%D that reason they have a different set op main commands. + +% \notation[ref]{title} +% \notation[reference=,title=] +% \startnotation[ref] title \stopnotation + +\protected\def\strc_notations_next {\strc_constructions_next_indeed \namednotationparameter} % #1#2 +\protected\def\strc_notations_reset{\strc_constructions_reset_indeed\namednotationparameter} % #1#2 +%protected\def\strc_notations_set {\strc_constructions_set_indeed \namednotationparameter} % #1#2 + +\newconditional\c_strc_notations_anchored_next + +\def\strc_notations_finalize + {\ifconditional\c_strc_notations_anchored_next + \expandafter\strc_notations_finalize_next + \else + \expandafter\strc_notations_finalize_previous + \fi} + +\def\strc_notations_finalize_previous + {\normalexpanded{\endgroup\noteparameter\c!next}} + +\def\strc_notations_finalize_next + {\endgroup\ignorespaces} + +\tolerant\protected\def\strc_notations_command[#1]#*[#2]% + {\begingroup + \edef\currentnote{#1}% + \strc_constructions_initialize{#1}% + \strc_notes_synchronize + \edef\p_next{\noteparameter\c!anchor}% + \ifx\p_next\v!next % for now only two states + \settrue \c_strc_notations_anchored_next + \else + \setfalse\c_strc_notations_anchored_next + \fi + \ifnotesenabled + \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel + \fi + \ifhastok={#2}% + \expandafter\strc_notations_command_setups + \else + \expandafter\strc_notations_command_reference + \fi[#2]} + +\def\strc_notations_command_setups[#1]% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1]% + \strc_notations_wrapup} + +\tolerant\def\strc_notations_command_reference[#1]#*#=% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]% + \strc_notations_wrapup} + +\def\strc_notations_wrapup + {\csname\??constructionnotehandler\currentconstructionhandler\endcsname + \strc_constructions_finalize + \strc_notations_finalize} + +\tolerant\protected\def\strc_notations_start[#1]#*[#2]% + {\begingroup + \edef\currentnote{#1}% + \strc_constructions_initialize{#1}% + \strc_notes_synchronize + \ifnotesenabled + \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel + \fi + \ifhastok={#2}% + \expandafter\strc_notations_start_setups + \else + \expandafter\strc_notations_start_reference + \fi[#2]} + +\protected\def\strc_notations_start_setups[#1]% + {\normalexpanded{\def\noexpand\strc_pickup_yes##/\csname\e!stop\currentconstruction\endcsname{\strc_notations_start_setups_indeed[#1]{##1}}}% + \strc_pickup_yes} + +\protected\def\strc_notations_start_setups_indeed[#1]#*#2% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#2},\c!bookmark=,\c!list=,#1]% + \strc_notations_wrapup} + +\protected\def\strc_notations_start_reference[#1]% + {\normalexpanded{\def\noexpand\strc_pickup_yes##/\csname\e!stop\currentconstruction\endcsname{\strc_notations_start_reference_indeed[#1]{##1}}}% + \strc_pickup_yes} + +\protected\def\strc_notations_start_reference_indeed[#1]#*#2% + {\strc_constructions_register[][\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=]% + \strc_notations_wrapup} + +\protected\def\strc_notations_stop + {} + +%D A complication is that we need to set up rather specific properties of e.g. +%D footnotes. It is for this reason that we introduce an extra level of +%D indirectness. This way notations don't bark on undefined macros when used in +%D combination. + +\protected\setvalue{\??constructionnotehandler\v!notation}% + {\csname\??constructionnotehandler\currentconstructionhandler:\constructionparameter\c!type\endcsname} + +\protected\setvalue{\??constructionnotehandler\v!notation:}% empty case + {[\currentconstructionhandler:\currentconstruction]} + +%D Here is a simple renderer for notes + +\defineconstructionalternative + [\v!note] + [\c!renderingsetup=\??constructionrenderings:\v!note] + +\startsetups[\??constructionrenderings:\v!note] + \noindent + \leftboundary % experiment, to be done in more places + \llap{\box\constructionheadbox\hskip\constructionparameter\c!distance}% + \useconstructionstyleandcolor\c!style\c!color + \ignorespaces +\stopsetups + +%D We now implement the note definer. + +\installcorenamespace{note} + +\installframedcommandhandler \??note {note} \??note + +\let\setupnotes\setupnote + +% These only concern the inline symbol/number and wrapping of the whole list. + +\setupnotes % not all make sense here + [\c!location=\v!page, + %\c!conversion=, + \c!rule=\v!on, + \c!before=\blank, + \c!bodyfont=\v!small, + \c!anchor=, % can also be v!next + %\c!style=, + %\c!color=, + %\c!after=, + %\c!rulecolor=, + %\c!rulecommand=, + \c!rulethickness=\linewidth, + \c!frame=\v!off, + \c!distance=.125em, % in the text between symbols + % \c!textseparator={,}, % optional separator + \c!columndistance=1em, + % \c!margindistance=.5em, + \c!align=, % also use instead of \c!tolerance + \c!split=\v!tolerant, + \c!width=\makeupwidth, % \ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi + \c!height=\textheight, + \c!command=, % \noteparameter\c!numbercommand, % (command in enumeration) too messy, called twice + \c!separator=,% + \c!textcommand=\high, + \c!textstyle=\tx, + %\c!textcolor=, + \c!interaction=\v!yes, + %\c!factor=, + %\c!scope=, % \v!text \v!page + \c!prefixconnector=., + %\c!next=\autoinsertnextspace, + \c!prefix=\v!no, + %\c!continue=\v!no, + \c!paragraph=\v!no, + \c!inbetween=\hskip\emwidth, + \c!symbol=\mathematics{*}, + \c!n=1] + +\setupnotes + [\c!expansion=\v!no, + \c!xmlsetup=, + \s!catcodes=] + +%D Insertions are part of notes. + +% \installcorenamespace{noteinsertion} + +\permanent\def\currentnoteinsertion {\noteparameter\s!insert} +\permanent\def\currentnoteinsertionnumber{\namedinsertionnumber{\noteparameter\s!insert}} + +\appendtoks + \ifx\currentnoteparent\empty + \doifelseinsertion\currentnote + \donothing + {\defineinsertion[\currentnote]% could be an option + \normalexpanded{\t_strc_notes{\the\t_strc_notes\noexpand\strc_notes_process_list{\currentnote}}}}% + \letnoteparameter\s!insert\currentnote + \definenotation[\currentnote][\c!type=\v!note]% + \else + \setexpandednoteparameter\s!insert{\namednoteparameter\currentnoteparent\s!insert}% + \definenotation[\currentnote][\currentnoteparent][\c!type=\v!note]% + \fi + \clf_definenote + {\currentnote}% + {insert}% + \currentnoteinsertionnumber + \relax +\to \everydefinenote + +% maybe we will share this at some point: + +\def\strc_notes_define_counter#tag% todo: move inline + {\definecounter[#tag]% + \registerenumerationcounter{#tag}} + +\appendtoks + \synchronizenotationcounters +\to \everysetupnotation + +\appendtoks + \synchronizenotationcounters +\to \everydefinenotation + +% so far + +%expandafter\let\csname\??constructionstarthandler \v!notation\expandafter\endcsname\csname\??constructionstarthandler \v!enumeration\endcsname +\expandafter\let\csname\??constructionstarthandler \v!notation\expandafter\endcsname\csname\??constructionstarthandler \v!construction\endcsname % no par mess +\expandafter\let\csname\??constructionstophandler \v!notation\expandafter\endcsname\csname\??constructionstophandler \v!enumeration \endcsname +\expandafter\let\csname\??constructioncommandhandler\v!notation\expandafter\endcsname\csname\??constructioncommandhandler\v!enumeration \endcsname +\expandafter\let\csname\??constructiontexthandler \v!notation\expandafter\endcsname\csname\??constructiontexthandler \v!enumeration \endcsname + +\protected\setvalue{\??constructionmainhandler\v!notation}#following% + {\iftrialtypesetting \else + \begingroup + \currentconstructionsynchronize + \c_attr_destination\currentconstructionattribute\relax % todo, whole text + \signalcharacter + \endgroup + \fi#following} + +\protected\setvalue{\??constructionnotehandler\v!notation:\v!note}% in the running text + {\ifnotesenabled + % do be done elsewhere + % + %let\currentnote\currentconstructionmain + \let\currentnote\currentconstruction % else wrong inheritance + % + \iftrialtypesetting + \strc_notes_inject_dummy + \else + \begingroup + \edef\currentnotenumber{\clf_storenote{\currentnote}\currentconstructionlistentry}% + \settrue\processingnote + \ifconditional\c_strc_notes_skip + \glet\lastnotesymbol\strc_notes_inject_symbol_nop + \else + \iftypesettinglines % otherwise problems with \type <crlf> {xxx} + \ignorelines % makes footnotes work in \startlines ... \stoplines + \fi + \ifconditional\c_strc_notes_symbol + \strc_notes_inject_symbol_yes + \else + \unskip\unskip + \glet\lastnotesymbol\strc_notes_inject_symbol_yes + \fi + \fi + \ifconditional\postponingnotes % todo: per note class + \global\settrue\postponednote + \orelse\ifconditional\inlocalnotes % todo: per note class + \global\settrue\postponednote + \orelse\ifconditional\c_strc_notes_delayed + % probably end notes + \else + \handlenoteinsert\currentnote\currentnotenumber % either an insert or just delayed + \fi + \endgroup + \fi + \fi + \ifconditional\c_strc_notes_skip + \global\setfalse\c_strc_notes_skip + \else + \kern\notesignal\relax % \relax is needed to honor spaces + \fi} + +%D Interaction in notes is somewhat complex due to the way notes get flushed. In +%D principle it is more or less the same as lists but where in lists we pack whole +%D entries, in notes this doesn't happen. Okay, in retrospect we could have made +%D descriptions lists but that will be a backward compatibility mess. At some point +%D a completely new mechanism might show up, but not now. Also, as notes are inserts +%D there is some extra mess to be kept in mind and it's easier to maintain two +%D mechanisms than to combine too much. +%D +%D Interaction is also complicated because we want to provide several variants. For +%D simple reference there is no need for anything special, as page references will +%D do and we store them in the list anyway. But if we want a destination with +%D dimensions we will use an additional destination because we can have only one +%D with the same name and we always have the number as one. + +% interaction: +% +% all : text and number +% number|yes: only number +% text : only text +% +% \dogetsimple : injects + +\installcorenamespace{noteinteractioninline} +\installcorenamespace{noteinteractiondisplay} + +\newconstant\a_strc_notes_symbol_reference +\newconstant\a_strc_notes_number_reference +\newconstant\a_strc_notes_text_reference +\newconstant\a_strc_notes_text_destination + +\let\strc_notes_get_reference_attribute_symbol \empty +\let\strc_notes_get_destination_attribute_symbol\empty + +\def\strc_notes_interaction_check_inline + {\edef\p_interaction{\noteparameter\c!interaction}% + \csname\??noteinteractioninline + \ifcsname\??noteinteractioninline\p_interaction\endcsname\p_interaction\else\v!no\fi + \endcsname} + +\def\strc_notes_interaction_check_display + {\edef\p_interaction{\noteparameter\c!interaction}% + \csname\??noteinteractiondisplay + \ifcsname\??noteinteractiondisplay\p_interaction\endcsname\p_interaction\else\v!no\fi + \endcsname} + +\def\currentnotenumber{0} + +\let\strc_notes_get_reference_attribute_symbol \empty +\let\strc_notes_get_destination_attribute_symbol\empty + +\let\strc_notes_set_reference_attribute_number\donothing +\let\strc_notes_set_reference_attribute_text \donothing +\let\strc_notes_set_destination_attribute_text\donothing + +% inline + +\def\strc_references_prepare_inline_references_nop + {\let\strc_notes_get_reference_attribute_symbol\empty + \let\strc_notes_get_destination_attribute_symbol\empty + \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_nop} + +% \def\strc_references_prepare_inline_references_yes +% {\strc_references_set_simple_reference{symb:\currentnote:\currentnotenumber}% destination +% \strc_references_get_simple_reference{internal(\clf_noteinternal{\currentnote}\currentnotenumber)}% reference +% \edef\strc_notes_get_destination_attribute_symbol{attr\destinationattribute\currentdestinationattribute}% +% \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}% +% \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_yes} + +\def\strc_references_prepare_inline_references_yes + {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}% + \strc_references_set_simple_reference{*\currentnoteinternal}% destination + \strc_references_get_simple_reference{internal(\currentnoteinternal)}% reference + \edef\strc_notes_get_destination_attribute_symbol{attr\destinationattribute\currentdestinationattribute}% + \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}% + \let\strc_notes_set_style_color_inline\strc_notes_set_style_color_inline_yes} + +\letvalue{\??noteinteractioninline\v!no }\strc_references_prepare_inline_references_nop +\letvalue{\??noteinteractioninline\v!all }\strc_references_prepare_inline_references_yes +\letvalue{\??noteinteractioninline\v!number}\strc_references_prepare_inline_references_yes +\letvalue{\??noteinteractioninline\v!text }\strc_references_prepare_inline_references_yes +\letvalue{\??noteinteractioninline\v!yes }\strc_references_prepare_inline_references_yes + +% display (for 'all' we need unique text and number attributes so we resolve twice +% as we otherwise don't get the number one which is lapped in the margin so we need +% to explicitly visit it) + +\def\strc_references_prepare_display_references_nop + {\let\strc_notes_set_reference_attribute_number\donothing + \let\strc_notes_set_reference_attribute_text\donothing + \let\strc_notes_set_destination_attribute_text\donothing + \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_nop} + +\def\strc_references_prepare_display_references_yes_number + {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}% + \ifcase\currentnoteinternal\relax + \strc_references_prepare_display_references_nop + \else + \let\strc_notes_set_reference_attribute_text\donothing + \strc_references_get_simple_reference{*\currentnoteinternal}% reference + \edef\strc_notes_set_reference_attribute_number{\c_attr_reference\currentreferenceattribute}% + \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes + \fi} + +\def\strc_references_prepare_display_references_yes_text + {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}% + \ifcase\currentnoteinternal\relax + \strc_references_prepare_display_references_nop + \else + \strc_references_get_simple_reference{*\currentnoteinternal}% reference + \edef\strc_notes_set_reference_attribute_text{\c_attr_reference\currentreferenceattribute}% + \let\strc_notes_set_reference_attribute_number\donothing + \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes + \fi} + +\def\strc_references_prepare_display_references_yes_all + {\edef\currentnoteinternal{\clf_noteinternal{\currentnote}\currentnotenumber}% + \ifcase\currentnoteinternal\relax + \strc_references_prepare_display_references_nop + \else + \strc_references_get_simple_reference{*\currentnoteinternal}% reference + \edef\strc_notes_set_reference_attribute_text{\c_attr_reference\currentreferenceattribute}% + \strc_references_get_simple_reference{*\currentnoteinternal}% reference + \edef\strc_notes_set_reference_attribute_number{\c_attr_reference\currentreferenceattribute}% + \let\strc_notes_set_style_color_display\strc_notes_set_style_color_display_yes + \fi} + +\letvalue{\??noteinteractiondisplay\v!no }\strc_references_prepare_display_references_nop +\letvalue{\??noteinteractiondisplay\v!all }\strc_references_prepare_display_references_yes_all +\letvalue{\??noteinteractiondisplay\v!number}\strc_references_prepare_display_references_yes_number +\letvalue{\??noteinteractiondisplay\v!text }\strc_references_prepare_display_references_yes_text +\letvalue{\??noteinteractiondisplay\v!yes }\strc_references_prepare_display_references_yes_number + +\let\strc_notes_set_style_color_inline_nop \usenotestyleandcolor +\let\strc_notes_set_style_color_display_nop\usenotationstyleandcolor + +\protected\def\strc_notes_set_style_color_inline_yes#style#color% + {\usenotestyleandcolor#style#color% + \iflocation\strc_notes_set_style_color_special\fi} + +\protected\def\strc_notes_set_style_color_display_yes#style#color% + {\usenotationstyleandcolor#style#color% + \iflocation\strc_notes_set_style_color_special\fi} + +\def\strc_notes_set_style_color_special + {\iftrialtypesetting + % keep + \orelse\ifx\currentcolorparameter\empty + \scratchcounter\clf_notedeltapage{\currentnote}\currentnotenumber\relax % todo calculate once + \setlocationcolorspecified\scratchcounter + \fi} + +\setvalue{\??constructiontexthandler\v!notation}% + {\begingroup + % we need to retrigger the reference as otherwise it gets lost because we don't do nested + % references with the same id ... maybe some day if we can figure out a nice heuristic ... + % the problem is that normally it's no issue but here we lap into the margin, so maybe that's + % a criterium + % \strc_notes_interaction_check_display + \strc_notes_set_reference_attribute_number + \dotagsetnotation + \strc_notes_set_style_color_display\c!headstyle\c!headcolor + \strc_enumerations_text + \endgroup} + +% in mkii the pointer only showed up in pagewise notes + +\protected\def\strc_notes_inject_pointer % todo calculate once + {\ifcase\clf_notedeltapage{\currentnote}\currentnotenumber\relax\relax + % unknown + \or + % same page + \or + \noteparameter\c!symbolcommand{\symbol[\v!note:\v!nextpage]}% + \or + \noteparameter\c!symbolcommand{\symbol[\v!note:\v!previouspage]}% + \fi} + +\protected\def\strc_notes_inject_symbol_yes + {\strc_notes_inject_symbol_indeed\conditionaltrue} + +\protected\def\strc_notes_inject_symbol_nop + {\strc_notes_inject_symbol_indeed\conditionalfalse} + +\definemargindata + [strc_notes_destination_margin] + [\v!left] + [\c!margin=\zeropoint, + \c!width=\zeropoint, + \c!style=, + \c!color=] + +\protected\def\strc_notes_inject_symbol_indeed#synchronize% + {\ifconditional\c_strc_notations_anchored_next\else + \removeunwantedspaces + \doifelseitalic\/\donothing % Charles IV \footnote{the fourth} + \fi + \ifdim\lastkern=\notesignal + % \kern\noteparameter\c!distance % yes or no note font? or main text + \strc_notes_inject_separator + \fi + \nobreak + \begingroup + \strc_notes_interaction_check_inline + \strc_notes_set_style_color_inline\c!textstyle\c!textcolor + \hbox \strc_notes_get_reference_attribute_symbol \strc_notes_get_destination_attribute_symbol \bgroup + % \hbox \strc_notes_get_reference_attribute_symbol \bgroup \strc_notes_destination_hack + \strc_references_flush_destination_nodes % a bit late but ok + \dostarttagged\t!descriptionsymbol\currentnote + \dotagsetnotesymbol + \noteparameter\c!textcommand{\clf_noteprefixednumber{\currentnote}\currentnotenumber\relax}% + % the next one can cycle so we need to make sure it has no advance width + \doif{\noteparameter\c!indicator}\v!yes\strc_notes_inject_pointer + \dostoptagged + \egroup + \endgroup + \glet\lastnotesymbol\relax} + +\protected\def\strc_notes_inject_dummy % temp hack + {\removeunwantedspaces + \doifelseitalic\/\donothing % Charles IV \footnote{the fourth} + \ifdim\lastkern=\notesignal + % \kern\noteparameter\c!distance % yes or no note font? or main text + \strc_notes_inject_separator + \fi + \nobreak + \hpack to .5\emwidth{}% + \glet\lastnotesymbol\relax} + +\protected\def\strc_notes_inject_separator % patch by WS due to request on list + {\edef\p_textseparator{\noteparameter\c!textseparator}% + \ifx\p_textseparator\empty + \kern\noteparameter\c!distance + \else + % skip or kern + \nobreak + \hbox\bgroup + \strc_notes_interaction_check_inline + \strc_notes_set_style_color_inline\c!textstyle\c!textcolor + \noteparameter\c!textcommand{\p_textseparator}% + \kern\noteparameter\c!distance + \egroup + \nobreak + \fi} + +% this needs a further cleanup ... soon as it's a slow mechanism +% +% -- set breakpoint in descriptions +% -- reset after trialtypesetting +% -- that way we can trick the symbol space + +% removed: +% +% \pushsomestates +% +% core-ins -> obsolete +% +% saveinsertiondata +% restoreinsertiondata +% saveinsertionbox +% eraseinsertionbackup +% restoreinsertionbackup + +\def\savenotedata {} % \writestatus{todo}{save note data}} +\def\restorenotedata {} % \writestatus{todo}{restore note data}} +\def\savenotecontent {} % \writestatus{todo}{save note content}} +\def\restorenotecontent{} % \writestatus{todo}{restore note content}} +\def\erasenotebackup {} % \writestatus{todo}{erase note backup}} + +% page-set: + +\def\enablenotes {\writestatus{todo}{enable notes}} +\def\disablenotes {\writestatus{todo}{disable notes}} +\def\savenotes {\writestatus{todo}{save notes}} +\def\flushsavednotes{\writestatus{todo}{flush notes}} + +% experiment: (compare scope=text and scope=page) +% +% \definenote[mynote][way=bytext,location=text,width=\leftmarginwidth,scope=page,rule=,before=,after=,factor=0] +% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][] + +%D Footnotes are can be characterized by three components: +%D +%D \startitemize[packed] +%D \item a small number \footnote {a footnote number} or symbol {\setupfootnotes +%D [conversion=set 2]\footnote {a footnote}} +%D \item and a similar mark at the bottom of the page +%D \item followed by some additional text +%D \stopitemize +%D +%D Because footnotes are declared at the location of their reference they can be +%D seen as a special kind of floating bodies. Their placement is postponed but has +%D to be taken into account in the pagebreak calculations. This kind of calculations +%D are forced by using \type{\insert}s and dealing with all cases is not trivial. + +%D \macros +%D {notesenabled} +%D +%D We need a couple of states because at some moments we don't want to mess around +%D with inserts at all. Take for instance a table of contents. And so we can +%D temporary disable footnotes by saying +%D +%D \starttyping +%D \notesenabledfalse +%D \stoptyping + +\newif\ifnotesenabled \notesenabledtrue + +% better mark a note .. once flushed no more flushing + +%appendtoks \notesenabledfalse \to \everymarking +\appendtoks \notesenabledfalse \to \everybeforepagebody +\appendtoks \notesenabledfalse \to \everystructurelist % quick hack +\appendtoks \notesenabledfalse \to \everysimplifycommands % quick hack +\appendtoks \notesenabledfalse \to \everypreroll % quick hack + +%D Often we need to process the whole set of notes and to make that fast, we use a +%D token register: + +% we have several synchronizers: +% +% - after a definition +% - after a specific setup +% - after a general setup (inheritance of dimensions) +% - just before a note is typeset + +\newtoks\t_strc_notes + +\let\strc_notes_process_list\gobbleoneargument + +\protected\def\strc_notes_process#action% argument is a \macro that uses \currentnote + {\def\strc_notes_process_list##1{\edef\currentnote{##1}\let\currentdescription\currentnote#action}% + \the\t_strc_notes} + +\newtoks\everychecknote % just before a note is typeset +\newtoks\everysynchronizenote % after a general setup has happened + +\appendtoks + \ifx\currentnote\empty \else + \setupnotations[\currentnote][]% also a synchronize + \fi +\to \everysynchronizenote + +\def\strc_notes_synchronize + {\the\everysynchronizenote} % we can speed this one up if needed by avoiding the commalist + +\appendtoks + \strc_notes_process\strc_notes_synchronize +\to \everysetupnoteroot + +\appendtoks + \the\everysynchronizenote +\to \everydefinenote + +% \starttext +% text \startfootnote Test.\stopfootnote +% test \footnote{xxxx} \subfootnote{xxxx} +% test \footnote{xxxx} \subfootnote{xxxx} +% \stoptext + +\installcorenamespace{notecommand} +\installcorenamespace{notealign} +\installcorenamespace{notepenalty} +\installcorenamespace{noterule} + +\permanent\protected\def\currentnoterulecommand{\begincsname\??notecommand\currentnote\endcsname} +\permanent\protected\def\currentnoterulealign {\begincsname\??notealign \currentnote\endcsname} + +\permanent\protected\def\currentnoterulecommandcommand{\noteparameter\c!rulecommand} +\permanent\protected\def\currentnoterulecommandnormal {\normalnoterule} % no let as it can be changed afterwards + +\permanent\protected\def\letcurrentnoterulecommand{\enforced\expandafter\let\csname\??notecommand\currentnote\endcsname} +\permanent\protected\def\letcurrentnoterulealign {\enforced\expandafter\let\csname\??notealign \currentnote\endcsname} + +\appendtoks + \enforced\expandafter\let\csname\??notecommand\currentnote\endcsname\currentnoterulecommandnormal + \enforced\expandafter\let\csname\??notealign \currentnote\endcsname\lefttoright +\to \everysynchronizenote + +\def\strc_notes_set_rule + {\letcurrentnoterulecommand\relax % so we default to nothing + \letcurrentnoterulealign \relax + \processcommacommand[\noteparameter\c!rule]\strc_notes_set_rule_step} + +\def\strc_notes_set_rule_step#alternative% + {\begincsname\??noterule#alternative\endcsname} + +\def\strc_notes_set_rule_autodir + {\doifelserighttoleftinbox\currentnoteinsertionnumber\righttoleft\lefttoright} + +\setvalue{\??noterule \v!command}{\letcurrentnoterulecommand\currentnoterulecommandcommand} +\setvalue{\??noterule \v!on}{\letcurrentnoterulecommand\currentnoterulecommandnormal} +\setvalue{\??noterule \v!normal}{\letcurrentnoterulecommand\currentnoterulecommandnormal} +\setvalue{\??noterule \v!left}{\letcurrentnoterulecommand\currentnoterulecommandnormal + \letcurrentnoterulealign \lefttoright} +\setvalue{\??noterule \v!right}{\letcurrentnoterulecommand\currentnoterulecommandnormal + \letcurrentnoterulealign \righttoleft} +\setvalue{\??noterule\v!paragraph}{\letcurrentnoterulecommand\currentnoterulecommandnormal + \letcurrentnoterulealign \strc_notes_set_rule_autodir} +\setvalue{\??noterule \v!off}{\letcurrentnoterulecommand\relax} + +\appendtoks + \strc_notes_set_rule +\to \everysynchronizenote + +\permanent\def\currentnotepenalty + {\ifcsname\??notepenalty\noteparameter\c!split\endcsname + \lastnamedcs + \else + \numexpr\noteparameter\c!split\relax + \fi} + +\setnewconstant\notepenaltytolerant \zerocount +\setnewconstant\notepenaltystrict 9999 +\setnewconstant\notepenaltyverystrict\maxdimen + +\letvalue{\??notepenalty\v!tolerant }\notepenaltytolerant +\letvalue{\??notepenalty\v!strict }\notepenaltystrict +\letvalue{\??notepenalty\v!verystrict}\notepenaltyverystrict +\letvalue{\??notepenalty }\notepenaltytolerant + +%D The following switch can be used to disable limiting the height of the footnote +%D area, something that is needed in multi column balancing. Use this switch with +%D care. + +\newif\ifnotelimit \notelimittrue % shared + +\def\strc_notes_set_factor + {\edef\p_factor{\noteparameter\c!factor}% + \ifx\p_factor\empty \else + \ifnum\p_factor<\zerocount \else +% \global + \count\currentnoteinsertionnumber\p_factor % new: global + \fi + \fi} + +\appendtoks + \strc_notes_set_factor +\to \everysynchronizenote + +% locations: + +\installcorenamespace{notelocationvariant} +\installcorenamespace{notepositionvariant} +\installcorenamespace{notedelayedvariant} +\installcorenamespace{notelocation} + +\newconditional\c_strc_notes_delayed + +\protected\def\strc_notes_set_delayed_yes{\settrue \c_strc_notes_delayed} +\protected\def\strc_notes_set_delayed_nop{\setfalse\c_strc_notes_delayed} + +\setvalue{\??notelocation\v!page }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop + \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_page} +\setvalue{\??notelocation\v!columns }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop + \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_columns} +\setvalue{\??notelocation\v!lastcolumn }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop + \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_lastcolumn} +\setvalue{\??notelocation\v!firstcolumn}{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_nop + \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_firstcolumn} +\setvalue{\??notelocation\v!none }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_yes + \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_none} +\setvalue{\??notelocation\v!text }{\letvalue{\??notedelayedvariant \currentnote}\strc_notes_set_delayed_yes + \letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_text} +\setvalue{\??notelocation\v!high }{\letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_high} +\setvalue{\??notelocation\v!bottom }{\letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_bottom} + +\setvalue{\??notedelayedvariant \??notedelayedvariant }{\strc_notes_set_delayed_nop} % not let +\setvalue{\??notepositionvariant\??notepositionvariant}{\strc_notes_set_position_bottom} % not let +\setvalue{\??notelocationvariant\??notelocationvariant}{\strc_notes_set_location_page} % not let + +\protected\def\strc_notes_set_delayed + {\csname\??notedelayedvariant + \ifcsname\??notedelayedvariant\currentnote\endcsname + \currentnote + \else + \??notedelayedvariant + \fi + \endcsname} + +\protected\def\strc_notes_set_position + {\csname\??notepositionvariant + \ifcsname\??notepositionvariant\currentnote\endcsname + \currentnote + \else + \??notepositionvariant + \fi + \endcsname} + +\protected\def\strc_notes_set_location + {\csname\??notelocationvariant + \ifcsname\??notelocationvariant\currentnote\endcsname + \currentnote + \else + \??notelocationvariant + \fi + \endcsname} + +\protected\def\strc_notes_set_variants + {\normalexpanded{\rawprocesscommalist[\noteparameter\c!location]\strc_notes_set_location_step}} + +\protected\def\strc_notes_set_location_step#alternative% the insert related one + {\begincsname\??notelocation#alternative\endcsname} + +\appendtoks + \strc_notes_set_variants + \strc_notes_set_delayed +\to \everysynchronizenote + +\newskip \s_strc_notes_distance % we need to implement stretch +\newcount\c_strc_notes_columns + +\newskip \s_strc_notes_before +\newskip \s_strc_notes_inbetween +\newconditional\c_strc_notes_first_flushed + +\appendtoks + \edef\p_spacebefore{\rootnoteparameter\c!spacebefore}% + \ifx\p_spacebefore\empty + \global\s_strc_notes_before\zeropoint + \else + \setbox\scratchbox\vbox{\blank[\p_spacebefore]\global\s_strc_notes_before\lastskip}% + \fi + \edef\p_spaceinbetween{\rootnoteparameter\c!spaceinbetween}% + \ifx\p_spaceinbetween\empty + \global\s_strc_notes_inbetween\zeropoint + \else + \setbox\scratchbox\vbox{\blank[\p_spaceinbetween]\global\s_strc_notes_inbetween\lastskip}% + \fi +\to \everysynchronizenote + +\def\strc_notes_set_distance + {\begingroup + \restoreglobalbodyfont + \setbox\scratchbox\vbox % no reuse as it can mirror + {\forgetall + \dontcomplain + \noteparameter\c!before + \placenoterule + \strut + \noteparameter\c!after}% + % also dp now + \scratchdimen\dimexpr\htdp\scratchbox-\lineheight\relax + \ifgridsnapping + \getnoflines\scratchdimen + \scratchdimen\noflines\lineheight + \fi + \expandafter\endgroup\expandafter + \s_strc_notes_distance\the\scratchdimen\relax} + +\def\strc_notes_set_columns + {\c_strc_notes_columns\noteparameter\c!n\relax + \ifcase\c_strc_notes_columns + \c_strc_notes_columns\plusone + \fi} + +\def\strc_notes_set_location_page + {\setfalse\c_strc_notes_delayed + \strc_notes_set_distance + \strc_notes_set_columns + \page_inserts_set_location\currentnoteinsertion\v!page % \setupinsertion[\currentnote][\c!location=\v!page]% + \global\count\currentnoteinsertionnumber\numexpr(\plusthousand/\c_strc_notes_columns)*\nofmulticolumns\relax + \global\dimen\currentnoteinsertionnumber\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi + \global\skip \currentnoteinsertionnumber\s_strc_notes_distance} + +\def\strc_notes_set_location_columns + {\setfalse\c_strc_notes_delayed + \strc_notes_set_distance + \strc_notes_set_columns + \ifnum\currentnofcolumns=\zerocount + \c_strc_notes_columns\plusone + \fi + \page_inserts_set_location\currentnoteinsertion\v!columns % \setupinsertion[\currentnote][\c!location=\v!columns]% + \global\count\currentnoteinsertionnumber\numexpr\plusthousand/\c_strc_notes_columns\relax + \global\dimen\currentnoteinsertionnumber\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi + \global\skip \currentnoteinsertionnumber\s_strc_notes_distance} + +\def\strc_notes_set_location_somecolumn#whatcolumn% + {\setfalse\c_strc_notes_delayed + \strc_notes_set_distance + \strc_notes_set_columns + \page_inserts_set_location\currentnoteinsertion#whatcolumn% \setupinsertion[\currentnote][\c!location=#whatcolumn]% + \global\count\currentnoteinsertionnumber\plusthousand + \global\dimen\currentnoteinsertionnumber\ifnotelimit\noteparameter\c!height\else\maxdimen\fi + \global\skip \currentnoteinsertionnumber\s_strc_notes_distance} + +\def\strc_notes_set_location_firstcolumn{\strc_notes_set_location_somecolumn\v!firstcolumn} +\def\strc_notes_set_location_lastcolumn {\strc_notes_set_location_somecolumn\v!lastcolumn } + +\def\strc_notes_set_location_text % we don't use inserts anyway (e.g. endnotes) + {\settrue\c_strc_notes_delayed + \clf_setnotestate{\currentnote}{store}% + \page_inserts_set_location\currentnoteinsertion\v!text % \setupinsertion[\currentnote][\c!location=\v!text]% + \global\count\currentnoteinsertionnumber\zerocount + \global\dimen\currentnoteinsertionnumber\maxdimen + \global\skip \currentnoteinsertionnumber\zeropoint} + +\let\strc_notes_set_location_none\strc_notes_set_location_text + +\def\strc_notes_set_properties + {\strc_notes_set_columns + \strc_notes_set_distance + \strc_notes_set_location + \strc_notes_set_delayed} + +\let\strc_notes_set_position_high\relax + +\def\strc_notes_set_position_bottom + {\settrue\c_notes_bottom_present} + +\appendtoks + \strc_notes_set_properties +\to \everysynchronizenote + +%D A fast checker for bottom notes being used: + +\newconditional\c_notes_bottom_present + +\def\strc_notes_check_if_bottom_present_indeed % in otr ! + {\ifvoid\currentnoteinsertionnumber\else + \strc_notes_set_position + \fi} + +\def\strc_notes_check_if_bottom_present_step + {\ifconditional\c_notes_bottom_present\else\strc_notes_check_if_bottom_present_indeed\fi} + +\def\strc_notes_check_if_bottom_present + {\setfalse\c_notes_bottom_present + \strc_notes_process\strc_notes_check_if_bottom_present_step} + +% Example of using factor: +% +% \definenote[mynote][way=bypage,location=text,width=\marginwidth,rule=,before=,factor=0] +% \setuplayout[backspace=5cm,margin=3cm,margindistance=.5cm,width=middle] +% \setuptexttexts[margin][\vbox to \textheight{\placenotes[mynote]\vfill}][] +% \starttext +% \dorecurse{10}{test \mynote{one one one one one one} \input zapf \mynote{one one one one one one} } +% \stoptext + +%D The noterule can be a graphic and therefore calling this setup macro at every +%D skipswitch is tricky (many many MP runs). Let's just reserve a few points, that +%D probably match those of the stretch component. A bit messy: + +\permanent\protected\def\placenoterule + {\begingroup + \currentnoterulealign + \currentnoterulecommand + \par + \endgroup} + +\permanent\protected\def\normalnoterule + {\ifvmode + \dontleavehmode \blackrule + [\c!color=\noteparameter\c!rulecolor, + \c!width=.2\hsize, + \c!height=\noteparameter\c!rulethickness, + \c!depth=\zeropoint]% + \endgraf + \kern\strutdepth + \fi} + +%D The formatting depends on the width of the table, so we have to set \type {n} to +%D zero. +%D +%D \starttyping +%D \startbuffer +%D \bTABLE +%D \bTR \bTD one \footnote{\dorecurse{10}{abcd }} \eTD \bTD two \eTD \eTR +%D \bTR \bTD three fout five six seven eight nine \eTD \bTD ten \eTD \eTR +%D \eTABLE +%D \stopbuffer +%D +%D \startlocalfootnotes[n=0,location={text,none}] +%D \placelegend[n=2]{\getbuffer}{\placelocalfootnotes} +%D \stoplocalfootnotes +%D \stoptyping + +%D \macros +%D {footnote} +%D +%D A footnote can have a reference as optional argument and therefore its formal +%D specification looks like: +%D +%D \showsetup{footnote} +%D +%D This command has one optional command: the reference. By saying \type{[-]} the +%D number is omitted. The footnote command is not that sensitive to spacing, so it's +%D quite legal to say: +%D +%D \startbuffer +%D Users of \CONTEXT\ must keep both feet \footnote {Given they have two.} on the +%D ground and not get confused \footnote {Or even crazy.} by all those obscure +%D \footnote {But fortunately readable.} parameters. +%D \stopbuffer +%D +%D \typebuffer +%D +%D When setting the \type{conversion} to \type{set 2} we get +%D something like: +%D +%D \bgroup +%D \startnarrower +%D \setupfootnotes[conversion=set 1] +%D \getbuffer +%D \stopnarrower +%D \egroup +%D +%D Typesetting footnotes is, at least for the moment, disabled when reshaping boxes. +%D The additional macro \type {\footnotetext} and the associated \type {\note} macro +%D were implemented at request of users on the mailing list and a suggestion by taco +%D to split of the symbol placement. I decided to merge this functionality with the +%D existing \type {\note} functionality. + +\newconditional\c_strc_notes_symbol \settrue\c_strc_notes_symbol % not used +\newconditional\c_strc_notes_skip + +\permanent\protected\def\setnote [#tag]{\csname#tag\endcsname} +\permanent\protected\def\setnotetext[#tag]{\global\settrue\c_strc_notes_skip\csname#tag\endcsname} + +\permanent\protected\def\handlenoteinsert#tag#id% + {\begingroup + \edef\currentnote{#tag}% + \strc_constructions_initialize{#tag}% + \strc_notes_synchronize + \the\everybeforenoteinsert + \insert\currentnoteinsertionnumber\bgroup + \the\everyinsidenoteinsert\relax + \usesetupsparameter\noteparameter % experimental + \useinterlinespaceparameter\noteparameter + \doifelse{\noteparameter\c!paragraph}\v!yes + {\nointerlineskip + \startvboxtohboxseparator + \noteparameter\c!inbetween + \stopvboxtohboxseparator + \startvboxtohbox + \handlenoteitself{#tag}{#id}% + \stopvboxtohbox} + {\handlenoteitself{#tag}{#id}}% + \egroup + \the\everyafternoteinsert + \endgroup} + +\permanent\protected\def\betweennoteitself#tag% used ? + {\edef\currentnote{#tag}% + \doif{\noteparameter\c!paragraph}\v!yes{\noteparameter\c!inbetween}} + +\permanent\protected\def\handlenoteitself#tag#id% + {\edef\currentnotenumber{#id}% + \edef\currentnote{#tag}% + \strc_constructions_initialize{#tag}% + \strc_notes_synchronize + \edef\currentconstructionlistentry{\clf_notelistindex{\currentnote}#id}% index in list cache + % as we can have collected notes (e.g. in tables) we need to recover + % \currentdescriptionattribute and \currentdescriptionsynchronize + % + \reinstatecachedconstructionnumberentry\currentconstructionlistentry % we could store the number in the entry (e.g. needed when local notes in table) + % + \dontcomplain + %begingroup + \strc_notes_interaction_check_display + \strc_notes_set_reference_attribute_text + \strc_constructions_stored_start + \begstrut + \strc_references_flush_destination_nodes + \strc_notes_set_destination_attribute_text + \strc_notes_inject_text\relax + \ifvmode\obeydepth\else\endstrut\fi % \obeydepth is new per 2015-01-10 + \strc_constructions_stored_stop + %endgroup + } + +\protected\def\strc_notes_inject_text % hm main? + {\clf_savedlisttitle{\currentconstructionmain}\currentconstructionlistentry\relax} + +\let\startpushnote\relax +\let\stoppushnote \relax + +\newsignal\notesignal + +\newconditional\processingnote +\newconditional\postponednote + +\newtoks\everybeforenoteinsert +\newtoks\everyinsidenoteinsert +\newtoks\everyafternoteinsert + +\permanent\protected\def\doifelseinnote + {\ifconditional\processingnote + \expandafter\firstoftwoarguments + \else + \expandafter\secondoftwoarguments + \fi} + +\appendtoks + \enforced\let\flushnotes \relax + \enforced\let\postponenotes\relax + \forgetall + \resetallattributes % new, we don't want color bleed into notes + \inheritmaintextcolor % but we do want to obey the textcolor +\to \everybeforenoteinsert + +\def\strc_notes_set_penalties + {% stored in insert node + \floatingpenalty \currentnotepenalty + % used when typesetting + \interlinepenalty\plushundred % plain value + % used when we need to split in columns + \ifnum\noteparameter\c!n>\plusone + \penalty\zerocount % otherwise no split in columns, maybe just always (tex just adds it to accumulated) + \fi} + +\appendtoks + \strc_notes_set_penalties + \forgetall % again + \strc_notes_set_bodyfont + \redoconvertfont % to undo \undo calls in in headings etc + \splittopskip\strutht % not actually needed here + \splitmaxdepth\strutdp % not actually needed here + % + % not: + % + % \leftmargindistance \noteparameter\c!margindistance + % \rightmargindistance\leftmargindistance + % \ifnum\noteparameter\c!n=\zerocount % no ifcase new 31-07-99 ; always ? + % \doifnotinset{\noteparameter\c!width}{\v!fit,\v!broad}\setnotehsize % ? + % \fi + % + \pickupattributes +\to \everyinsidenoteinsert + +%D Nasty, the might be more: + +\appendtoks \strc_itemgroups_push \to \everybeforenoteinsert +\appendtoks \strc_itemgroups_pop \to \everyafternoteinsert + +% maybe but better use [scope=local] here +% +% \appendtoks +% \setfalse\inhibitmargindata +% \to \everyinsidenoteinsert + +\setupnotes + [\c!width=\v!auto] + +\permanent\protected\def\setnotehsize + {\ifinsidemulticolumns + \setnoteparameter\c!width{\makeupwidth}% + \else + \edef\p_width{\noteparameter\c!width}% + \ifx\p_width\v!auto + % \ifinsidecolumns + \setnoteparameter\c!width{\ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi}% + % \else + % \setnoteparameter\c!width{\makeupwidth}% + % \fi + \orelse\ifx\p_width\empty + \setnoteparameter\c!width{\hsize}% + \fi + \fi + \hsize\noteparameter\c!width\relax} + +\appendtoks + % only needed when columns (could be three \set...) + \setnotehsize + \setsimplecolumnshsize[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]% +\to \everyinsidenoteinsert + +%D Normally footnotes are saved as inserts that are called upon as soon as the +%D pagebody is constructed. The footnote insertion routine looks just like the +%D \PLAIN\ \TEX\ one, except that we check for the end note state. + +% testcase for split bottom alignment see (a) below +% +% \dorecurse{6}{\input tufte\footnote{\input ward \input tufte \relax}} + +\newconditional\c_strc_notes_first_placed + +\permanent\protected\def\placenoteinserts + {\setfalse\c_strc_notes_first_placed + \strc_notes_process\strc_notes_place_inserts} + +\def\strc_notes_place_inserts + {\strc_notes_set_delayed % \strc_notes_synchronize % we need to know if it's delayed + \ifconditional\c_strc_notes_delayed \else + \ifdim\ht\currentnoteinsertionnumber>\zeropoint % or a faster delayed test + \strc_notes_place_inserts_indeed + \settrue\c_strc_notes_first_placed + \fi + \fi} + +\def\strc_notes_place_inserts_indeed + {\relax + \ifdim\ht\currentnoteinsertionnumber>\zeropoint + \endgraf + \ifvmode + \whitespace + \ifconditional\c_strc_notes_first_placed + \edef\p_spaceinbetween{\noteparameter\c!spaceinbetween}% + \ifx\p_spaceinbetween\empty\else + \blank[\p_spaceinbetween]% + \fi + \else + \edef\p_spacebefore{\noteparameter\c!spacebefore}% + \ifx\p_spacebefore\empty\else + \blank[\p_spacebefore]% + \fi + \fi + \noteparameter\c!before + \fi + \placenoterule + \bgroup + \strc_notes_set_bodyfont + \setbox\scratchbox\hbox + {\strc_notes_flush_inserts}% + \page_postprocessors_linenumbers_deepbox\scratchbox + \setbox\scratchbox\hbox + {\setupcurrentnote + [\c!location=, + \c!width=\v!fit, + \c!height=\v!fit, + \c!strut=\v!no, + \c!offset=\v!overlay]% + \inheritednoteframed + {\ifzeropt\dp\scratchbox % this hack is needed because \vadjust + \hpack{\lower\strutdp\box\scratchbox}% % in margin number placement + \else % hides the (always) present depth + \box\scratchbox + \fi}}% + \setbox\scratchbox\hpack{\lower\strutdepth\box\scratchbox}% + \dp\scratchbox\strutdepth % so we know that it has the note bodyfont depth + \ifvmode + \nointerlineskip % else sometimes empty line + \fi + \box\scratchbox + \egroup + \endgraf + \ifvmode + \noteparameter\c!after + \fi + \fi} + +\def\strc_notes_flush_inserts + {\ifcase\noteparameter\c!n\relax + % should not happen + \or + \strc_notes_flush_inserts_normal + \else + \strc_notes_flush_inserts_columns + \fi} + +\def\strc_notes_flush_inserts_normal + {\strc_notes_flush_global + \obeydepth} % (a) added , since split footnotes will not align properly + +\def\strc_notes_flush_inserts_columns + {\begingroup + \setnotehsize % probably still not ok for columns + \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]% + \strc_notes_flush_global + \stopsimplecolumns + \endgroup} + +% idea: tag with attr and then just flush them again + +\def\strc_notes_flush_global + {\begingroup + \useinterlinespaceparameter\noteparameter + \doifelse{\noteparameter\c!paragraph}\v!yes + {\leftorrightvbox % cf mail from ws to list + {\starthboxestohbox + \iftrialtypesetting\unvcopy\else\unvbox\fi\currentnoteinsertionnumber + \stophboxestohbox}} + {\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteinsertionnumber}% + \endgroup} + +%D Supporting end notes is surprisingly easy. Even better, we can combine this +%D feature with solving the common \TEX\ problem of disappearing inserts when +%D they're called for in deeply nested boxes. The general case looks like: +%D +%D \starttyping +%D \postponenotes +%D \.box{whatever we want with footnotes} +%D \flushnotes +%D \stoptyping +%D +%D This alternative can be used in headings, captions, tables etc. The latter one +%D sometimes calls for notes local to the table, which can be realized by saying +%D +%D \starttyping +%D \setlocalfootnotes +%D some kind of table with local footnotes +%D \placelocalfootnotes +%D \stoptyping +%D +%D Postponing is accomplished by simply redefining the (local) insert operation. A +%D not too robust method uses the \type{\insert} primitive when possible. This +%D method fails in situations where it's not entirely clear in what mode \TEX\ is. +%D Therefore the auto method can is to be overruled when needed. + +\newconditional\postponingnotes + +% we need a proper state: normal, postponing, flushing + +\permanent\protected\def\postponenotes % will be locally overloaded + {\ifcase\insertionmigrationmode + \ifconditional\postponingnotes\else + \global\settrue\postponingnotes + \glet\flushnotes\doflushnotes + \clf_postponenotes + \fi + \fi} + +\let\flushnotes\relax + +% also \ifcase\insertionmigrationmode here, needs testing: + +\permanent\protected\def\startpostponingnotes % experimental, page-mix + {\ifconditional\postponingnotes\else + \global\settrue\postponingnotes + %\glet\flushnotes\doflushnotes + \clf_postponenotes + \fi} + +\permanent\protected\def\stoppostponingnotes % experimental, page-mix + {\doflushnotes} + +\permanent\protected\def\doflushnotes + {\ifconditional\postponingnotes + \begingroup + \enforced\let\flushnotes \relax + \enforced\let\postponenotes\relax + \ifconditional\postponednote + \ifhmode + % needed for tagging ... otherwise we get some weird node free error + \signalcharacter + \fi + \fi + \clf_flushpostponednotes% this also resets the states ! + \global\setfalse\postponednote + \global\setfalse\postponingnotes + \glet\flushnotes\relax + \endgroup + \fi} + +%D \macros +%D {startlocalfootnotes,placelocalfootnotes} +%D +%D The next two macros can be used in for instance tables, as we'll demonstrate +%D later on. +%D +%D \showsetup{startlocalfootnotes} +%D \showsetup{placelocalfootnotes} + +% todo: compatibility mode: when first arg is assignment or missing, then all + +\newtoks\everyplacelocalnotes + +\appendtoks + \enforced\let\flushnotes \relax + \enforced\let\postponenotes\relax +\to \everyplacelocalnotes + +\newconditional\inlocalnotes + +\permanent\tolerant\protected\def\startlocalnotes[#list]% grouping ? (we used to have a second argument ... settings) + {\def\localnoteslist{#list}% + \settrue\inlocalnotes + \processcommacommand[\localnoteslist]\strc_notes_local_start_step} + +\permanent\protected\def\stoplocalnotes + {\processcommacommand[\localnoteslist]\strc_notes_local_stop_step + \setfalse\inlocalnotes} + +\let\p_strc_notes_continue\empty + +\def\strc_notes_local_start_step#tag% + {\p_strc_notes_continue{\noteparameter\c!continue}% + \ifx\p_strc_notes_continue\v!yes \else + \strc_counters_save{#tag}% + \strc_counters_reset{#tag}% + \fi + \clf_savenote{#tag}{store}} + +\def\strc_notes_local_stop_step#tag% + {\p_strc_notes_continue{\noteparameter\c!continue}% + \ifx\p_strc_notes_continue\v!yes \else + \strc_counters_restore{#tag}% + \fi + \clf_restorenote{#tag}} + +\permanent\tolerant\protected\def\placelocalnotes[#tag]#spacer[#settings]% + {\doif{\clf_getnotestate{#tag}}{store}{\strc_notes_local_place_indeed{#settings}{#tag}}} + +\def\strc_notes_local_place_indeed#settings#tag% + {\begingroup + \edef\currentnote{#tag}% is already set? + \the\everyplacelocalnotes + % beware, we cannot trust setting \currentnote here + \setupcurrentnote[#settings]% later we set height etc for framed + \strc_notes_place_local_alternative + \strc_notes_set_properties % restore globals (if needed) + \endgroup + }% TODO: just restore properties \the\everychecknote} % we need to restore the old state + +%D These commands can be used like: +%D +%D \startbuffer +%D \startlocalnotes[footnote] +%D \placetable +%D {Some Table} +%D \placeontopofeachother +%D {\starttable[|l|r|] +%D \HL +%D \VL Nota\footnote{Bene} \VL Bene\footnote{Nota} \VL\SR +%D \VL Bene\footnote{Nota} \VL Nota\footnote{Bene} \VL\SR +%D \HL +%D \stoptable} +%D {\setupnotation[footnote][alternative={serried},distance=.5em,after=\hskip1em]% +%D \placelocalnotes[footnote]} +%D \stoplocalnotes +%D \stopbuffer +%D +%D \typebuffer +%D +%D Because this table placement macro expect box content, and thanks to the grouping +%D of the local footnotes, we don't need additional braces. +%D +%D \getbuffer + +%D \macros +%D {placefootnotes} +%D +%D We still have no decent command for placing footnotes somewhere else than at the +%D bottom of the page (for which no user action is needed). Footnotes (endnotes) can +%D be placed by using +%D +%D \showsetup{placefootnotes} + +\permanent\protected\def\placebottomnotes + {\strc_notes_process\strc_notes_place_inserts} + +\permanent\tolerant\protected\def\placenotes[#list]#spacer[#settings]% + {\processcommalist[#list]{\strc_notes_place_indeed{#settings}}} + +\def\strc_notes_place_indeed#settings#tag% settings note + {\edef\currentnote{#tag}% grouping ? + \doifelse{\clf_getnotestate{#tag}}{store} + \strc_notes_local_place_indeed + \strc_notes_global_place_indeed + {#settings}{#tag}} + +\def\strc_notes_global_place_indeed#settings#tag% + {\begingroup + \setupnote[#tag][#settings]% + \strc_notes_place_inserts + \endgroup + \the\everysetupnote} % to be checked .. synchronize + +%D Placement + +\installcorenamespace{notealternative} + +\permanent\protected\def\installnotealternative#alternative#command% + {\setvalue{\??notealternative#alternative}{#command}} + +\permanent\protected\def\doifnotescollected#tag% + {\clf_doifnotecontent{#tag}} + +\def\strc_notes_place_local_alternative % will be a setup (wrapper) + {\doifnotescollected\currentnote + {\endgraf + \ifvmode + \whitespace + \noteparameter\c!before + \fi + \begingroup + \strc_notes_set_bodyfont + \csname\??notealternative\noteparameter\c!alternative\endcsname + \endgroup + \ifvmode + \noteparameter\c!after + \fi}} + +%D A stupid alternative is also provided: +%D +%D \starttyping +%D \setupfootnotes[location=text,alternative=none] +%D \stoptyping + +% setups ? + +\permanent\def\flushlocalnotes#tag{\clf_flushnotes{#tag}{store}{\noteparameter\c!criterium}} + +\installnotealternative \v!none + {\flushlocalnotes\currentnote} + +\installnotealternative \empty + {\flushlocalnotes\currentnote} + +\installnotealternative \v!grid % test if n > 0 + {\begingroup + \setupcurrentnote[\c!location=]% + \snaptogrid\hbox + {\inheritednoteframed + {\flushlocalnotes\currentnote}}% + \endgroup} + +\installnotealternative \v!fixed % test if n > 0 + {\begingroup + \setupcurrentnote[\c!location=]% + \inheritednoteframed + {\flushlocalnotes\currentnote}% + \endgroup} + +\installnotealternative \v!columns % redundant + {\begingroup + \setupcurrentnote[\c!location=]% + \inheritednoteframed + {\edef\currentnotewidth{\noteparameter\c!width}% + \doifelsedimension\currentnotewidth\donothing + {\edef\currentnotewidth{\the\hsize}}% + \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\currentnotewidth]% + \flushlocalnotes\currentnote + \stopsimplecolumns}% + \endgroup} + +% 0:page 1:firstcolumn 2:lastcolumn + +\newconstant\c_strc_notes_page_location + +\protected\def\strc_notes_check_locations + {\edef\p_strc_notes_location{\rootnoteparameter\c!location}% + \c_strc_notes_page_location + \ifx\p_strc_notes_location\v!firstcolumn\plusone \else + \ifx\p_strc_notes_location\v!lastcolumn \plustwo \else + \zerocount\fi\fi} + +\appendtoks + \strc_notes_check_locations +\to \everysynchronizenote + +% still semi public (but will change) + +\newif\ifnotespresent + +\permanent\protected\def\checknotepresence + {\notespresentfalse + \strc_notes_process\strc_notes_check_presence} + +\def\strc_notes_check_presence + {\ifdim\ht\currentnoteinsertionnumber>\zeropoint + \notespresenttrue + \fi} + +%D \macros +%D {fakenotes} + + % used in page-mul + + \ifdefined\currentnofcolumns\else \def\currentnofcolumns{\nofcolumns} \fi + + \protected\def\fakenotes + {\ifhmode\endgraf\fi\ifvmode + \calculatetotalclevernoteheight + \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi + \fi} + + \protected\def\fakepagenotes + {\ifhmode\endgraf\fi\ifvmode + \calculatetotalpagenoteheight + \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi + \fi} + + % used in page-not but not yet ok + + \newdimen\totalnoteheight + + \protected\def\additionaltotalnoteheight#insert% temp hacks anyway + {\dimexpr + \ifdim\ht#insert>\zeropoint + \ifcase\count#insert % + \zeropoint + \else % todo: divide by count + \ht#insert+\skip#insert% hm, no stretch but a dimen anyway + \fi + \else + \zeropoint + \fi + \relax} + + \def\docalculatetotalnoteheight + {\ifcase\c_strc_notes_page_location % tricky here ! ! ! to be sorted out ! ! ! + \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}% + \fi} + + \def\docalculatetotalclevernoteheight + {\ifcase\c_strc_notes_page_location \else % tricky here ! ! ! to be sorted out ! ! ! + \advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}% + \fi} + + \def\docalculatetotalpagenoteheight + {\advance\totalnoteheight\normalexpanded{\additionaltotalnoteheight\currentnoteinsertionnumber}} + + \def\calculatetotalnoteheight {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalnoteheight} + \def\calculatetotalclevernoteheight{\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalclevernoteheight} + \def\calculatetotalpagenoteheight {\totalnoteheight\zeropoint\strc_notes_process\docalculatetotalpagenoteheight} + +%D Now how can this mechanism be hooked into \CONTEXT\ without explictly postponing +%D footnotes? The solution turned out to be rather simple: +%D +%D \starttyping +%D \everypar {...\flushnotes...} +%D \neverypar {...\postponenotes} +%D \stoptyping +%D +%D We can use \type {\neverypar} because in most commands sensitive to footnote +%D gobbling we disable \type {\everypar} in favor for \type {\neverypar}. In fact, +%D this footnote implementation is the first to use this scheme. + +%D This is a nasty and new secondary footnote flusher. It can be hooked into \type +%D {\everypar} like: +%D +%D \starttyping +%D \appendtoks \synchronizenotes \to \everypar +%D \stoptyping + +\let\synchronizenotes\relax + +%D When typesetting footnotes, we have to return to the footnote specific bodyfont +%D size, which is in most cases derived from the global document bodyfont size. In +%D the previous macros we already used a footnote specific font setting macro. + +\def\strc_notes_set_bodyfont + {\let\strc_notes_set_bodyfont\relax + \restoreglobalbodyfont + \usebodyfontparameter\noteparameter + \usealignparameter\noteparameter} + +%D The footnote mechanism defaults to a traditional one column way of showing them. +%D By default we precede them by a small line. + +% end notes in the margin: +% +% \setuptexttexts +% [margin] +% [] [{\directsetup{notabene}}] +% +% \startsetups notabene +% \vbox to \textheight \bgroup +% \setupalign[tolerant] +% \topskipcorrection +% \placenotes[endnote][before=,after=] +% \vfilll +% \egroup +% \stopsetups + +\definenote [\v!footnote] +\definenote [\v!endnote ] [\c!location=\v!none] % else no break + +%D Compatibility macros: + +\permanent\protected\def\setupfootnotedefinition{\setupnotation [\v!footnote]} +\permanent\protected\def\setupfootnotes {\setupnote [\v!footnote]} +\permanent \def\footnotetext {\setnotetext [\v!footnote]} +\permanent\protected\def\placefootnotes {\dodoubleempty\strc_notes_place_footnotes [\v!footnote]} +\permanent\protected\def\placelocalfootnotes {\dodoubleempty\strc_notes_place_local_footnotes[\v!footnote]} +\permanent\protected\def\startlocalfootnotes {\startlocalnotes [\v!footnote]} % alleen footnote +\permanent\protected\def\stoplocalfootnotes {\stoplocalnotes } + +\def\strc_notes_place_footnotes[#list][#settings]% + {\ifsecondargument + \placenotes[#list][#settings,\c!height=\textheight]% + \else + \placenotes[#list][\c!height=\textheight]% + \fi} + +\def\strc_notes_place_local_footnotes[#list][#settings]% + {\ifsecondargument + \placelocalnotes[#list][#settings,\c!height=\textheight]% + \else + \placelocalnotes[#list][\c!height=\textheight]% + \fi} + +%D Goodies: +%D +%D \starttyping +%D \dorecurse {100} { +%D test \footnote{\doifnoteonsamepageelse[footnote]{ibidem}{aaa}} +%D } +%D \stoptyping + +\permanent\def\doifelsenoteonsamepage#tag{\clf_doifnoteonsamepageasprevious{#tag}} + +\aliased\let\doifnoteonsamepageelse\doifelsenoteonsamepage + +%D New trickery: + +%D \macros +%D {note} +%D +%D Refering to a note is accomplished by the rather short command: +%D +%D \showsetup{note} +%D +%D This command is implemented rather straightforward as: + +\installcorenamespace{notesymbol} + +\let\lastnotesymbol\relax % todo: per class + +\permanent\tolerant\protected\def\notesymbol[#tag]#spacer[#reference]% + {\ifnotesenabled + \dontleavehmode + \begingroup + \edef\currentnote{#tag}% + \usenotestyleandcolor\c!textstyle\c!textcolor + \iftok{#reference}\emptytoks + \noteparameter\c!textcommand\lastnotesymbol % check if command double + \else + \unskip + \noteparameter\c!textcommand{\in[#reference]}% command here? + \fi + \endgroup + \fi} + +\permanent\tolerant\protected\def\note[#tag]#spacer[#reference]% + {\iftok{#reference}\emptytoks + \notesymbol[\v!footnote][#tag]% + \else + \notesymbol[#tag][#reference]% + \fi} + +% will be redone if needed +% +% \def\ownnotesymbol#1% #1 gets number passed +% {\executeifdefined{\??notesymbol\currentnote}\empty} +% +% \protected\def\setnotesymbol[#1]#2#3% +% {\prewordbreak % prevent lookback +% \setgvalue{\??notesymbol#1}{#3} +% \strc_notes_inject_symbol} +% +% \protected\def\ownnote[#1]#2#3#4% +% {\setnotesymbol[#1]{#2}{#3}% +% \setnotetext [#1]{#4}} +% +% \defineconversion +% [ownnote] +% [\ownnotesymbol] + +% tricky: +% +% \enabletrackers[nodes.areas] +% \enabletrackers[nodes.references] +% \enabletrackers[nodes.destinations] +% +% \setupnotes[interaction=all,rule=no] +% \setupinteraction[state=start,focus=standard] +% +% \starttext +% \goto{\input tufte\relax}[page(2)] \par +% \ruledhbox{\gotobox{\vtop{\input tufte\relax}}[page(2)]} \par +% \ruledhbox{\gotobox{\vbox{\input tufte\relax}}[page(2)]} \par +% % \completecontent +% % \chapter{Chapter} +% % \dorecurse{5}{\input knuth} +% a\footnote{\input tufte\par\input ward\relax} +% \stoptext + +%D Bonus: + +\appendtoks + \setsystemmode\currentnote +\to \everysynchronizenote + +\protect \endinput diff --git a/tex/context/base/mkiv/strc-pag.mkiv b/tex/context/base/mkiv/strc-pag.mkiv index 01361e2c5..909c418f9 100644 --- a/tex/context/base/mkiv/strc-pag.mkiv +++ b/tex/context/base/mkiv/strc-pag.mkiv @@ -21,14 +21,14 @@ % Allocation: -\countdef\realpageno \zerocount \realpageno \plusone -\countdef\userpageno \plusone \userpageno \plusone -\countdef\subpageno \plustwo \subpageno \plusone % was \zerocount but that doesn't work well with bytext -\countdef\arrangeno \plusthree \arrangeno \zerocount % ! -\countdef\pagenoshift\plusfour \pagenoshift\zerocount % ! -\countdef\lastpageno \plusfive \lastpageno \zerocount % ! +\ifdefined\realpageno \else \countdef\realpageno \zerocount \fi \realpageno \plusone +\ifdefined\userpageno \else \countdef\userpageno \plusone \fi \userpageno \plusone +\ifdefined\subpageno \else \countdef\subpageno \plustwo \fi \subpageno \plusone % was \zerocount but that doesn't work well with bytext +\ifdefined\arrangeno \else \countdef\arrangeno \plusthree \fi \arrangeno \zerocount % ! +\ifdefined\pagenoshift \else \countdef\pagenoshift\plusfour \fi \pagenoshift\zerocount % ! +\ifdefined\lastpageno \else \countdef\lastpageno \plusfive \fi \lastpageno \zerocount % ! -\let\pageno\userpageno +\ifdefined\pageno \else \let\pageno\userpageno \fi \def\realfolio{\the\realpageno} \def\userfolio{\the\userpageno} @@ -268,8 +268,8 @@ % States: -\newif\ifdoublesided \newconditional\layoutisdoublesided -\newif\ifsinglesided \newconditional\layoutissinglesided +\newconditional\layoutisdoublesided % already defined: \newif\ifdoublesided +\newconditional\layoutissinglesided % already defined: \newif\ifsinglesided % Realpage and subpage numbers: @@ -316,7 +316,8 @@ \doublesidedfalse \setfalse\layoutissinglesided \resetsystemmode\v!singlesided \resetsystemmode\v!doublesided - \processallactionsinset[\directpagenumberingparameter\c!alternative] + \processallactionsinset + [\directpagenumberingparameter\c!alternative]% [ \v!singlesided=>\setsystemmode\v!singlesided\singlesidedtrue\settrue\layoutissinglesided, \v!doublesided=>\setsystemmode\v!doublesided\doublesidedtrue\settrue\layoutisdoublesided]% \the\everysidedswitch diff --git a/tex/context/base/mkiv/strc-ref.mkvi b/tex/context/base/mkiv/strc-ref.mkvi index d68ecb805..3bf339638 100644 --- a/tex/context/base/mkiv/strc-ref.mkvi +++ b/tex/context/base/mkiv/strc-ref.mkvi @@ -1006,8 +1006,8 @@ \unexpanded\def\strc_references_about[#label]% {\dontleavehmode \begingroup - \let\crlf\space - \let\\\space + \enforced\let\crlf\space + \enforced\let\\\space \postponenotes % might go \referencingparameter\c!left \doifelsereferencefound{#label} diff --git a/tex/context/base/mkiv/strc-reg.mkiv b/tex/context/base/mkiv/strc-reg.mkiv index e2fede024..1e632eebc 100644 --- a/tex/context/base/mkiv/strc-reg.mkiv +++ b/tex/context/base/mkiv/strc-reg.mkiv @@ -48,7 +48,7 @@ \let\strc_registers_setup_saved\setupregister -\unexpanded\def\setupregister % maybe we should drop the plural form +\unexpanded\overloaded\def\setupregister % maybe we should drop the plural form {\dotripleempty\strc_registers_setup} \def\strc_registers_setup[#1][#2][#3]% @@ -618,7 +618,7 @@ \edef\currentregister{\firstinset{#1}}% \the\everyplaceregister \ifnum\namedmixedcolumnsparameter\currentregister\c!n>\plusone - \startmixedcolumns[\currentregister] + \startmixedcolumns[\currentregister]% \strc_registers_place_indeed{#1}% \stopmixedcolumns \else diff --git a/tex/context/base/mkiv/strc-ren.mkiv b/tex/context/base/mkiv/strc-ren.mkiv index 2b344bbfb..359bd6aec 100644 --- a/tex/context/base/mkiv/strc-ren.mkiv +++ b/tex/context/base/mkiv/strc-ren.mkiv @@ -187,7 +187,7 @@ \ifx\p_strut\v!no \setnostrut \fi - \let\\\strc_rendering_shortcut_backslash} + \enforced\let\\\strc_rendering_shortcut_backslash} \unexpanded\def\strc_rendering_shortcut_backslash {\crlf @@ -745,8 +745,8 @@ \vbox { \headsetupspacing \veryraggedcenter - \let\\\endgraf - \let\crlf\endgraf + \enforced\let\\\endgraf + \enforced\let\crlf\endgraf \ifconditional\headshownumber \strut \headnumbercontent diff --git a/tex/context/base/mkiv/strc-sbe.mkxl b/tex/context/base/mkiv/strc-sbe.mkxl new file mode 100644 index 000000000..1b903cec7 --- /dev/null +++ b/tex/context/base/mkiv/strc-sbe.mkxl @@ -0,0 +1,139 @@ +%D \module +%D [ file=strc-sbe, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Section Block Environments, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Section Block Environments} + +\unprotect + +% \def\ChapterEntry#1#2#3% +% {chapter : \hbox to \hsize{\strut\bf#2\hss#3}\endgraf\placelist[section]} +% +% \startfrontmatter % optional +% \placelist[chapter][alternative=command,command=\ChapterEntry,criterium=text] \page +% \stopfrontmatter % optional +% +% \startbodymatter % optional +% \chapter{first} \section{one} test \section{two} test \page +% \chapter{second} \section{alpha} test \section{beta} test \page +% \stopbodymatter % optional + +\installcorenamespace{sectionblock} + +\installcommandhandler \??sectionblock {sectionblock} \??sectionblock + +\setupsectionblock + [\c!number=\v!yes, + \c!page=\v!right] % otherwise marks are reset too soon + +\newtoks\everybeforesectionblock +\newtoks\everyaftersectionblock + +\let\strc_sectionblock_define_normal\definesectionblock + +\permanent\overloaded\tolerant\protected\def\definesectionblock[#1]#*[#2]#*[#3]% singular plural settings + {\strc_sectionblock_define_normal[#1][#3]% + %\expandafter\newif\csname if#2\endcsname % obsolete + \strc_sectionblock_set_environment{#1}\empty + \setuvalue{\e!start#2}{\startsectionblock[#1]}% + \setuvalue{\e!stop #2}{\stopsectionblock}} + +\ifdefined \resetallstructuremarks \else + \let\resetallstructuremarks\relax +\fi + +\def\strc_sectionblock_handle_page + {\edef\p_strc_sectionblock_page{\sectionblockparameter\c!page}% + \ifx\p_strc_sectionblock_page\empty \else + \page[\p_strc_sectionblock_page]% + \fi} + +\appendtoks + \strc_sectionblock_handle_page + \resetallstructuremarks + \strc_sectionblock_get_environment\currentsectionblock + \sectionblockparameter\c!before % don't move + \dostarttagged\t!division\currentsectionblock % no parents +\to \everybeforesectionblock + +\appendtoks + \sectionblockparameter\c!after % don't move + \strc_sectionblock_handle_page + \dostoptagged + \resetallstructuremarks +\to \everyaftersectionblock + +\permanent\tolerant\protected\def\setsectionblock[#1]#*[#2]% used to set the default + {\edef\currentsectionblock{#1}% from now on we assume a value + \setupcurrentsectionblock[#2]% + \clf_setsectionblock{#1} + bookmark {\sectionblockparameter\c!bookmark}% + \relax} + +\let\currentsectionblock\empty % was \s!unknown + +\permanent\tolerant\protected\def\startsectionblock[#1]#*[#2]% + {%\ctxlua{structures.counters.check(0)}% we assume sane usage of \page, as this is the only workable place (in push) + \begingroup + \edef\currentsectionblock{#1}% from now on we assume a value + \setupcurrentsectionblock[#2]% + \clf_pushsectionblock{#1} + bookmark {\sectionblockparameter\c!bookmark}% + \relax + %\csname #1true\endcsname % obsolete + \setsystemmode\currentsectionblock + \the\everybeforesectionblock\relax + \showmessage\m!structures1\currentsectionblock} + +\permanent\protected\def\stopsectionblock + {\showmessage\m!structures2\currentsectionblock + \the\everyaftersectionblock\relax + \clf_popsectionblock + \endgroup} + +%D \starttyping +%D \startsectionblockenvironment[frontpart] +%D \setupnumber[userpage][numberconversion=romannumerals,start=1] +%D \stopsectionblockenvironment +%D +%D \startsectionblockenvironment[bodypart] +%D \setupnumber[userpage][numberconversion=numbers,start=1] +%D \stopsectionblockenvironment +%D +%D \startsectionblockenvironment[backpart] +%D \setupnumber[userpage][numberconversion=numbers,start=1] +%D \stopsectionblockenvironment +%D +%D \starttext +%D \startfrontmatter \chapter{test} \stopfrontmatter +%D \startbodymatter \chapter{test} \stopbodymatter +%D \startappendices \chapter{test} \stopappendices +%D \stoptext +%D \stoptyping + +\installcorenamespace{sectionblockenvironment} + +\protected\def\strc_sectionblock_set_environment#1#2% + {\setvalue{\??sectionblockenvironment#1}{#2}} + +\protected\def\strc_sectionblock_get_environment#1% + {\csname\??sectionblockenvironment#1\endcsname} + +\protected\setvalue{\e!start\v!sectionblockenvironment}% + {\dosingleargument\strc_sectionblock_environment_start} + +\letvalue{\e!stop\v!sectionblockenvironment}\relax + +\def\strc_sectionblock_environment_start[#1]% evt \pushendofline \popendofline + {\grabuntil{\e!stop\v!sectionblockenvironment}{\strc_sectionblock_set_environment{#1}}} + +\protect \endinput diff --git a/tex/context/base/mkiv/strc-sec.mkiv b/tex/context/base/mkiv/strc-sec.mkiv index 2a2384656..fb21254f2 100644 --- a/tex/context/base/mkiv/strc-sec.mkiv +++ b/tex/context/base/mkiv/strc-sec.mkiv @@ -1044,7 +1044,7 @@ \def\strc_sectioning_delayed_flush {\ifvoid\b_sectioning_delayed\else - \smashboxed\b_sectioning_delayed + \smashedbox\b_sectioning_delayed \fi} \unexpanded\def\strc_rendering_place_head_section % see hidden below diff --git a/tex/context/base/mkiv/strc-sec.mkxl b/tex/context/base/mkiv/strc-sec.mkxl new file mode 100644 index 000000000..51d1f6019 --- /dev/null +++ b/tex/context/base/mkiv/strc-sec.mkxl @@ -0,0 +1,1345 @@ +%D \module +%D [ file=strc-sec, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Sectioning, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D In retrospect I should have gone futher and move more to the +%D \LUA\ end but here we are now. Maybe some day. + +\writestatus{loading}{ConTeXt Structure Macros / Sectioning} + +\unprotect + +\startcontextdefinitioncode + +\installcorenamespace{structure} + +\installdirectcommandhandler \??structure {structure} % unchecked, so we need to initialize used parameters + +\setupstructure % not a user command so we might need to change the name + [\c!number=, + \c!level=, + \c!name=, + \c!title=, + \c!bookmark=, + \c!marking=, + \c!list=, + \c!label=, + \c!coupling=, + \c!ownnumber=, + % \c!interaction=\v!list, + \c!sectionseparatorset=\s!default, + \c!sectionconversionset=\s!default, + \c!sectionstopper=, + \c!sectionstarter=, + \c!sectionsegments=, + \c!sectionresetset=, + \c!reference=, + \c!backreference=, + \c!expansion=\v!no, + \c!xmlsetup=, + \s!catcodes=, + \c!saveinlist=\v!yes] + +% maybe flags for list, bm, mark + +\def\m_strc_references_prefix_yes{+} +\def\m_strc_references_prefix_nop{-} + +\let\currentstructurereferenceprefix\empty + +\installglobalmacrostack\currentstructurereferenceprefix + +\def\strc_sectioning_set_reference_prefix + {\ifx\currentstructurereferenceprefix\empty + % nothing + \orelse\ifx\currentstructurereferenceprefix\m_strc_references_prefix_yes + \global\advance\prefixcounter \plusone % temp here + \setupglobalreferenceprefix[\the\prefixcounter]% + \orelse\ifx\currentstructurereferenceprefix\m_strc_references_prefix_nop + \setupglobalreferenceprefix[]% + \else + \setupglobalreferenceprefix[\currentstructurereferenceprefix]% + \fi + \glet\currentstructurereferenceprefix\referenceprefix} + +% why xdef ? + +\setupstructure + [\c!label={\headparameter{\currentsectionblock\c!label}}, + \c!incrementnumber=\ifconditional\c_strc_sectioning_increment\v!yes\else\v!no\fi, % not that needed + \c!saveinlist=\ifconditional\c_strc_sectioning_to_list\v!yes\else\v!no\fi, + \c!level=\currentheadlevel, + \c!number=\ifconditional\c_strc_sectioning_increment\ifconditional\headshownumber\v!yes\else\v!no\fi\else\v!no\fi, + \c!expansion=\headparameter\c!expansion, + \c!xmlsetup=\headparameter\c!xmlsetup, + \s!catcodes=\headparameter\s!catcodes, + \c!sectionresetset=\headparameter\c!sectionresetset, + \c!sectionseparatorset=\headparameter\c!sectionseparatorset, + \c!sectionconversionset=\headparameter\c!sectionconversionset, + \c!sectionconversion=\headparameter\c!conversion, % just for compatibility + \c!sectionstarter=\headparameter\c!sectionstarter, + \c!sectionstopper=\headparameter\c!sectionstopper, + \c!sectionset=\headparameter\c!sectionset, + \c!sectionsegments=\headparameter\c!sectionsegments, + \c!reference=\headparameter\c!reference, + \c!referenceprefix=\headparameter\c!referenceprefix, + \c!criterium=\headparameter\c!criterium] + +% see lists/neat-001.tex for usage of: + +\permanent\def\namedstructureheadlocation#1% expandable, maybe [#1] + {\csname\??savedinternalreference\ifcsname\??savedinternalreference#1\endcsname#1\else\s!default\fi\endcsname} + +% The next directive only makes sense when we have sort of garanteed outcome (math is not so +% nice for instance). +% +% \enabledirectives[references.bookmarks.preroll] + +\newconditional\c_strc_bookmarks_preroll + +\installtexdirective + {references.bookmarks.preroll} + {\settrue \c_strc_bookmarks_preroll} + {\setfalse\c_strc_bookmarks_preroll} + +\def\strc_sectioning_autobookmark#1% + {\begingroup + % \settrialtypesetting + \the\everypreroll + \nodestostring\tempstring{#1}% + \glet\currentstructurebookmark\tempstring + \endgroup} + +% zeros: +% +% \setuphead[subsection][criterium=all] +% +% \dorecurse{3} { +% \chapter{Blabla} \subsection{bla 1 1} \subsection{bla 1 2} +% \section{bla 2} \subsection{bla 2 1} \subsection{bla 2 2} +% } + +\protected\def\strc_sectioning_register#1#2#3% #1=interfaced-settings, #2=optional user data (not yet supported) + {\begingroup + \setupstructure[\c!name={#1},#2]% + \xdef\currentstructurename {\structureparameter\c!name}% + \xdef\currentstructurecoupling {\structureparameter\c!coupling}% + \xdef\currentstructureownnumber {\structureparameter\c!ownnumber}% optional own number + \xdef\currentstructurelevel {\structureparameter\c!level}% + \edef\currentstructureexpansion {\structureparameter\c!expansion}% + \xdef\currentstructurexmlsetup {\structureparameter\c!xmlsetup}% + \xdef\currentstructurecatcodes {\structureparameter\s!catcodes}% + \xdef\currentstructurelabel {\structureparameter\c!label}% + \xdef\currentstructurereference {\structureparameter\c!reference}% + \xdef\currentstructurereferenceprefix{\structureparameter\c!referenceprefix}% + \xdef\currentstructurebackreference {\structureparameter\c!backreference}% + \xdef\currentstructureshownumber {\structureparameter\c!number}% + \xdef\currentstructuresaveinlist {\structureparameter\c!saveinlist}% + \xdef\currentstructureincrementnumber{\structureparameter\c!incrementnumber}% + \xdef\currentstructureplaceholder {\structureparameter\c!placeholder}% + \ifx\currentstructureexpansion\s!xml + \xmlstartraw + \xdef\currentstructuretitle {\structureparameter\c!title}% + \xdef\currentstructurebookmark{\structureparameter\c!bookmark}% + \xdef\currentstructuremarking {\structureparameter\c!marking}% + \xdef\currentstructurelist {\structureparameter\c!list}% + \xmlstopraw + \iflocation \ifx\currentstructurebookmark\empty \ifconditional\c_strc_bookmarks_preroll + \strc_sectioning_autobookmark\currentstructuretitle + \fi \fi \fi + \ifx\currentstructurelist\empty + \glet\currentstructurelist\currentstructuretitle + \fi + \glet\currentstructurecoding\s!xml + \else + \ifx\currentstructureexpansion\v!yes + \xdef\currentstructuretitle {\structureparameter\c!title}% + \xdef\currentstructurebookmark{\structureparameter\c!bookmark}% + \xdef\currentstructuremarking {\structureparameter\c!marking}% + \xdef\currentstructurelist {\structureparameter\c!list}% + \iflocation \ifx\currentstructurebookmark\empty \ifconditional\c_strc_bookmarks_preroll + \strc_sectioning_autobookmark\currentstructuretitle + \fi \fi \fi + \else + \xdef\currentstructuretitle {\detokenizedstructureparameter\c!title}% + \xdef\currentstructurebookmark{\detokenizedstructureparameter\c!bookmark}% + \xdef\currentstructuremarking {\detokenizedstructureparameter\c!marking}% + \xdef\currentstructurelist {\detokenizedstructureparameter\c!list}% + \iflocation \ifx\currentstructurebookmark\empty + \ifconditional\c_strc_bookmarks_preroll + \strc_sectioning_autobookmark{\structureparameter\c!title}% + \else + \begingroup + \simplifycommands + \xdef\currentstructurebookmark{\detokenize\expandafter{\normalexpanded{\structureparameter\c!title}}}% + \endgroup + \fi + \fi \fi + \fi + \ifx\currentstructurelist\empty + \glet\currentstructurelist\currentstructuretitle + \fi + \glet\currentstructurecoding\s!tex + \fi + \setnextinternalreference + \storeinternalreference\currentstructurename{\the\locationcount}% + \strc_sectioning_set_reference_prefix + \clf_setsectionentry + references { + internal \locationcount + % block {\currentsectionblock} + prefix {\currentstructurereferenceprefix} + reference {\currentstructurereference} + backreference {\currentstructurebackreference} + } + directives { + resetset {\structureparameter\c!sectionresetset} + } + metadata { + kind {section} + name {\currentstructurename} + catcodes \ifx\currentstructurecatcodes\empty\catcodetable\else\csname\currentstructurecatcodes\endcsname\fi\space + coding {\currentstructurecoding} + \ifx\currentstructurecoding\s!xml + xmlroot {\xmldocument} + \fi + \ifx\currentstructurexmlsetup\empty \else + xmlsetup {\currentstructurexmlsetup} + \fi + \ifx\currentstructuresaveinlist\v!no + nolist \space true\space + \fi + \ifx\currentstructureincrementnumber\v!yes + increment {\currentstructureincrementnumber} + \fi + } + titledata { + label {\detokenize\expandafter{\currentstructurelabel}} + title {\detokenize\expandafter{\currentstructuretitle}} + \ifx\currentstructurebookmark\currentstructuretitle \else + bookmark {\detokenize\expandafter{\currentstructurebookmark}} + \fi + \ifx\currentstructuremarking\currentstructuretitle \else + marking {\detokenize\expandafter{\currentstructuremarking}} + \fi + \ifx\currentstructuresaveinlist\v!no \else + \ifx\currentstructurelist\currentstructuretitle \else + list {\detokenize\expandafter{\currentstructurelist}} + \fi + \fi + } + numberdata { + % block {\currentsectionblock} + \ifx\currentstructureshownumber\v!no + hidenumber \space true\space % space needed for parser + \fi + separatorset {\structureparameter\c!sectionseparatorset} + conversionset {\structureparameter\c!sectionconversionset} + conversion {\structureparameter\c!sectionconversion} + starter {\structureparameter\c!sectionstarter} + stopper {\structureparameter\c!sectionstopper} + set {\structureparameter\c!sectionset} + segments {\structureparameter\c!sectionsegments} + ownnumber {\currentstructureownnumber} + language {\currentlanguage}% for the moment, needed for bookmarks conversion + criterium {\structureparameter\c!criterium} + } + userdata {\detokenize{#3}}% will be converted to table at the lua end + \relax + \xdef\currentstructurelistnumber{\clf_currentsectiontolist}% + % \currentstructuresynchronize has to be called someplace, since it introduces a node + \setstructuresynchronization\currentstructurelistnumber + \endgroup} + +\let\currentsectioncountervalue \!!zerocount % redefined later +\let\previoussectioncountervalue\!!zerocount % redefined later + +% We can access the (stored) data with the following macros. +% +% \def\MyHeadCommand #1#2{\framed{#1}\framed{#2 / \structureuservariable{subtitle}}} +% \def\MyListCommand#1#2#3{\externalfigure[\structurelistuservariable{figure}][height=5mm]#2} +% +% \setuphead[chapter][command=\MyHeadCommand] +% \setuplist[chapter][alternative=command,command=\MyListCommand] +% +% \starttext +% \setupheadertexts[chapter] +% \setupinteraction[state=start] +% \placebookmarks[chapter] +% \placelist[chapter] +% \startchapter[ownnumber=10,title=Ton,list=Hans,marking=Kees,bookmark=Bram][figure=cow.pdf,subtitle=oeps] +% \stopchapter +% \stoptext + +% todo: #1 => "#1" ... adapt lua code for name and number + +\permanent\def\structurenumber {\clf_structurenumber} +\permanent\def\structuretitle {\clf_structuretitle} +\permanent\def\structurevariable #1{\clf_structurevariable {#1}} +\permanent\def\structureuservariable #1{\clf_structureuservariable {#1}} +\permanent\def\structurecatcodedget #1{\clf_structurecatcodedget {#1}} % bad name +\permanent\def\structuregivencatcodedget #1#2{\clf_structuregivencatcodedget {#1}#2 } % bad name +\permanent\def\structureautocatcodedget #1#2{\clf_structureautocatcodedget {#1}{#2}} +\permanent\def\namedstructurevariable #1#2{\clf_namedstructurevariable {#1}{#2}} +\permanent\def\namedstructureuservariable#1#2{\clf_namedstructureuservariable{#1}{#2}} + +% compatibility issue: +% +% \def\setfullsectionnumber #1{} +% \def\preparefullnumber #1{} +% \def\fullsectionnumber {1--1--1} +% \def\makesectionnumber [#1]{} +% \def\makesectionformat {} +% \def\sectionformat {1--1-1-1-1-1-1} +% \def\composedsectionnumber{} +% \def\@@kolist{} + +% \setuphead[section] [separator=\separatorlist{?,!,*}] +% \setuphead[subsection][separator=\separatorlist{??,!!,**}] +% +% \let\spr\separatorlist % this will enable this feature +% +% \setuphead[section] [separator={?,!,*}] +% \setuphead[subsection][separator={??,!!,**}] +% +% \setupheads[separator={A,B,C,D,E,F}] +% \chapter{test} +% \section{test} \subsection{test} \subsection{test} +% \section{test} \subsection{test} \subsection{test} + +% lua interface / names and interface might change + +% \newconditional\c_strc_rendering_continuous % not used (mkii ?) + +\permanent\def\setstructurelevel #1#2{\clf_setstructurelevel {#1}{#2}} % name, level|parent +\permanent\def\getstructurelevel #1{\clf_getstructurelevel {#1}} % name +\permanent\def\setstructurenumber #1#2{\clf_setstructurenumber #1{#2}} % level, number (+/-) +\permanent\def\getstructurenumber #1{\clf_getstructurenumber \numexpr#1\relax} % level +\permanent\def\getsomestructurenumber #1#2{\clf_getsomestructurenumber #1{#2}} % level, what +\permanent\def\getfullstructurenumber #1{\clf_getfullstructurenumber \numexpr#1\relax} % level +\permanent\def\getsomefullstructurenumber#1#2{\clf_getsomefullstructurenumber #1{#2}} % level, what +\permanent\def\getspecificstructuretitle #1{\clf_getspecificstructuretitle {#1}{\headparameter\s!catcodes}} + +% structure heads (like \startchapter) + +% \c!deeptextcommand, \c!deepnumbercommand: undefined ! +% \c!before \c!after \c!distance +% \c!page \c!header \c!text \c!footer=, +% \c!numbercommand \c!textcommand \c!ownnumber \c!number +% \c!file \c!grid \c!margintext +% \c!expansion \c!xmlsetup \s!catcode + +\installcorenamespace{head} +\installcorenamespace{headlevel} +\installcorenamespace{headincrement} +\installcorenamespace{headplace} +\installcorenamespace{headmarkyes} +\installcorenamespace{headmarknop} + +\installcommandhandler \??head {head} \??head + +\installmacrostack\currenthead +\installmacrostack\currentheadparent + +\setuphead [% + %\c!after=, + %\c!align=, + %\c!aligntitle=, + \c!alternative=\v!normal, + %\c!before=, + %\c!color=, + %\c!command=, + \c!continue=\v!yes, + %\c!coupling=, + %\c!deepnumbercommand=, + %\c!deeptextcommand=, + %\c!default=, + \c!distance=\zeropoint, + \c!textdistance=\zeropoint, + \c!textwidth=\zeropoint, % signal too + \c!numberwidth=\zeropoint, % signal too + \c!width=\zeropoint, % signal too + \c!expansion=\v!no, + %\c!file=, + %\c!footer=, + %\c!grid=, + \c!hang=\v!none, + %\c!header=, + \c!incrementnumber=\v!yes, + \c!indentnext=\v!no, + %\c!label=, + %\c!limittext=\languageparameter\c!limittext, + \c!margin=\zeropoint, + %\c!margintext=, + \c!number=\v!yes, + \c!numbercolor=\headparameter\c!color, + \c!textcolor=\headparameter\c!color, + \c!numberstyle=\headparameter\c!style, + \c!textstyle=\headparameter\c!style, + %\c!numbercommand=, + %\c!textcommand=, + \c!ownnumber=\v!no, + %\c!page=, + \c!placehead=\v!yes, + \c!sectionconversionset=\s!default, + \c!sectionnumber=\v!yes, + %\c!sectionsegments=, + \c!sectionseparatorset=\s!default, + \c!sectionset=\v!all, + \c!interlinespace=, + %\c!sectionstopper=, + %\c!sectionstarter=, + %\c!strut=, + %\c!style=, + %\c!text=, + %\c!tolerance=, + %\c!beforesection=\directsetup{document:\currenthead:start}, % these might become defaults i.e. acpect document: namespace + %\c!insidesection=\directsetup{document:\currenthead:inside}, % these might become defaults i.e. acpect document: namespace + %\c!aftersection=\directsetup{document:\currenthead:stop}, % these might become defaults i.e. acpect document: namespace + ] + +\let\setupheads\setuphead % will go + +\appendtoks + \ifx\currentheadparent\empty + \edef\currentheaddefault{\headparameter\c!default}% + \edef\currentheadsection{\headparameter\c!section}% + \ifx\currenthead\currentheaddefault + \let\currentheadparent\currentheadsection + \orelse\ifx\currentheaddefault\empty + \let\currentheadparent\currentheadsection + \else + \let\currentheadparent\currentheaddefault + \fi + \normalexpanded {% + \setheadparameter{\c!label}{\currenthead}% + \setheadparameter{\c!coupling}{\currenthead}% + \setheadparameter{\s!parent}{\??head\currentheadparent}% + \definemarking[\currenthead] [\currentheadsection]% + \definemarking[\currenthead\v!number][\currentheadsection]% + \setupmarking [\currenthead] [\c!filtercommand=\noexpand\sectionheadmarkingtitle {\currenthead}]% + \setupmarking [\currenthead\v!number][\c!filtercommand=\noexpand\sectionheadmarkingnumber{\currenthead}]% + }% + \doifelselist\currenthead\donothing + {\definelist[\currenthead][\c!prefix=\v!no]}% + % we can't do this now for backward compatibility reasons + % \doifelselist\currenthead\donothing + % {\normalexpanded{\definelist[\currenthead][\currentheadparent][\c!prefix=\v!no]}}% + \else + \normalexpanded {% + \setheadparameter{\c!label}{\currenthead}% + \setheadparameter{\c!coupling}{\currentheadparent}% + \definemarking[\currenthead] [\currentheadparent]% + \definemarking[\currenthead\v!number][\currentheadparent\c!number]% + }% + \doifelselist\currenthead\donothing + {\normalexpanded{\definelist[\currenthead][\currentheadparent][\c!prefix=\v!no]}}% + \fi + \presetlabeltext[\currenthead=]% + \the\everysetuphead +\to \everydefinehead + +\newtoks\everyredefinehead + +\appendtoks + \the\everyredefinehead +\to \everydefinehead + +\appendtoks + \setstructurelevel\currenthead{\thenamedheadlevel\currenthead}% +\to \everyredefinehead + +\appendtoks + % beware, this is a global register + \begingroup + \edef\currentsectionheadcoupling{\sectionheadcoupling\currenthead}% + \edef\currentsectionheadsection {\sectionheadsection \currentsectionheadcoupling}% + \edef\currentsectionlevel {\sectionlevel \currentsectionheadsection}% + \clf_registersection {\currenthead} { + coupling {\currentsectionheadcoupling} + section {\currentsectionheadsection} + level \space \currentsectionlevel \space % space needed for parser + parent {\currentheadparent} + }% + \endgroup +\to \everyredefinehead + +\appendtoks + \instance\setuevalue{\e!start\currenthead}{\strc_sectioning_start[\currenthead]}% + \instance\setuevalue{\e!stop \currenthead}{\strc_sectioning_stop [\currenthead]}% +\to \everydefinehead + +% so \subject as well as \section will need two commands when ownnumber +% is used (one can disable it anyway for subject) .. this is not downward +% compatible but better + +\appendtoks + \ifx\currenthead\empty \else + \doifelse{\headparameter\c!ownnumber}\v!yes + {\instance\setuevalue\currenthead{\strc_sectioning_handle_own[\currenthead]}} + {\instance\setuevalue\currenthead{\strc_sectioning_handle_nop[\currenthead]}}% + \fi +\to \everysetuphead + +\permanent\protected\def\doredefinehead#1#2% called at lua end + {\push_macro_currenthead + \push_macro_currentheadparent + \edef\currenthead{#1}% + \edef\currentheadparent{#2}% + \the\everyredefinehead\relax + \pop_macro_currentheadparent + \pop_macro_currenthead} + +\let\currentnamedsection\empty + +\installmacrostack\currentnamedsection + +% todo: add grouping but where: before/after trickery .. probably inside because one can always add +% grouping to the before/after settings + +\permanent\protected\def\startnamedsection + {\dotripleempty\strc_sectioning_start_named_section} + +\permanent\protected\def\stopnamedsection + {\normalexpanded{\strc_sectioning_stop[\currentnamedsection]}} + +% structure sections (the parents of chapter etc) + +\let\firstsectionname\empty +\let\lastsectionname \empty + +\let\resetallstructuremarks \relax +\let\resetcurrentstructuremarks \relax +\let\resetcurrentstructuremarkswithpage\relax + +\def\resetallstructuremarks {\resetmarking[\firstsectionname]} % will become option (was \v!section-1) +\def\resetcurrentstructuremarks {\resetmarking[\lastsectionname]} % will become option +%def\resetcurrentstructuremarkswithpage{\resetmarking[\lastsectionname]} % will become option + +% We could use a commandhandler here but sections are somewhat special in the +% sense that we have two ways of chaining: the main section (levels) as well +% as rendering (head). + +% -2 = text +% -1 = manual +% 0 = block +% +1 = structurelevel 1 .. n + +\newcount\maxstructuredepth + +\permanent\def\sectionlevel#1% + {\csname\??headlevel\ifcsname\??headlevel#1\endcsname#1\else\v!none\fi\endcsname} + +\permanent\def\namedsectionlevel#1#2% direct indirect + {\csname\??headlevel + \ifcsname\??headlevel#1\endcsname + #1% + \orelse\ifcsname\??headlevel#2\endcsname + #2% + \else + \v!none + \fi + \endcsname} + +\permanent\def\xthenamedheadlevel#1% + {\namedsectionlevel{#1}{\sectionheadsection{\sectionheadcoupling{#1}}}} + +\setvalue{\??headlevel\v!block}{0} +\setvalue{\??headlevel\v!none }{-1} +\setvalue{\??headlevel\v!text }{-2} +\setvalue{\??headlevel\v!head }{-3} + +\newtoks\everydefinesection + +\protected\def\definesection[#1]% + {\ifcsname\??headlevel#1\endcsname \else + \edef\currentsection{#1}% not used, will go + \edef\currenthead{#1}% + \global\advance\maxstructuredepth\plusone + \setevalue{\??headlevel#1}{\the\maxstructuredepth}% + \setstructurelevel{#1}{\sectionlevel{#1}}% + \normalexpanded{\setheadparameter{\s!parent}{\??head\lastsectionname}}% TO BE CHECKED, WE HAVE A HELPER + \the\everydefinesection + % so far for these default inheritances + \definemarking[#1]% + \ifnum\maxstructuredepth>\plusone + \normalexpanded{\relatemarking[#1][\lastsectionname]}% so, the parent will reset the child + \fi + \xdef\lastsectionname{#1}% + \ifx\firstsectionname\empty + \glet\firstsectionname\lastsectionname + \fi + \fi} + +\permanent\tolerant\protected\def\setupsection[#1]#*[#2]#*[#3]% + {\ifparameter#1\else + \ifcsname\??headlevel#1\endcsname + \strc_sectioning_setup_indeed[#1][#2][#3]% + \else + \strc_sectioning_setup_indeed[\sectionheadsection{#1}][#2][#3]% + \fi + \fi} + +\def\strc_sectioning_setup_indeed[#1][#2][#3]% + {\push_macro_currenthead + \ifthirdargument + \edef\currenthead{#1#2}% % not used at any more in mkiv (sets now) + \setupcurrenthead[#3]% + \else + \edef\currenthead{#1}% + \setupcurrenthead[#2]% + \fi + \pop_macro_currenthead} + +% we share the parameters as sections are roots of heads so eventually we can +% consider \definesection -> \definehead with one argument + +\appendtoks + % This is a rather practical default that we don't want to + % be part of the parent chain lookup mechanism; it's also + % mkii compatible. Somewhat weird that it's part of the + % top level structure but it will be flattened anyway. + \let\currenthead\currentsection % + \setheadparameter\c!textstyle {\directheadparameter\c!style}% + \setheadparameter\c!textcolor {\directheadparameter\c!color}% + \setheadparameter\c!numberstyle{\directheadparameter\c!style}% + \setheadparameter\c!numbercolor{\directheadparameter\c!color}% +\to \everydefinesection + +% head -> head + +\permanent\def\sectionheadmarkingtitle #1#2{\clf_markingtitle {#1}{#2}} +\permanent\def\sectionheadmarkingnumber#1#2{\clf_markingnumber{#1}{#2}} + +\permanent\def\sectionheadcoupling#1{\namedheadparameter{#1}\c!coupling} +\permanent\def\sectionheadsection #1{\namedheadparameter{#1}\c!section} + +% head construction + +\protected\def\strc_sectioning_handle_own{\dodoubleempty\strc_sectioning_handle_own_indeed} % [ref] {nr} {title} +\protected\def\strc_sectioning_handle_nop{\dodoubleempty\strc_sectioning_handle_nop_indeed} % [ref] {title} +\protected\def\strc_sectioning_start {\dotripleempty\strc_sectioning_start_named_section} % [settings] [userdata] !!! also used at lua end + +\newconditional\currentstructureown + +\newtoks\everybeforehead % hook, todo: before/after keys +\newtoks\everyafterhead % hook, todo: before/after keys + +\protected\def\strc_sectioning_handle_own_indeed[#1][#2]#3#4% + {\settrue\currentstructureown + \triggerautostructurelevel + \strc_sectioning_handle{#1}{\c!reference={#2},\c!ownnumber={#3},\c!title={#4}}{}} % name ref nr title -- + +\protected\def\strc_sectioning_handle_nop_indeed[#1][#2]% for taco: [key=value] variant + {\setfalse\currentstructureown + \triggerautostructurelevel + \ifcondition\validassignment{#2}% + \expandafter\strc_sectioning_handle_nop_indeed_yes + \else + \expandafter\strc_sectioning_handle_nop_indeed_nop + \fi + {#1}{#2}} + +\protected\def\strc_sectioning_handle_nop_indeed_yes#1#2% + {\strc_sectioning_handle{#1}{#2}{}} + +\protected\def\strc_sectioning_handle_nop_indeed_nop#1#2#3% + {\strc_sectioning_handle{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title -- + +\protected\def\strc_sectioning_start_named_section[#1][#2][#3]% for the moment no grouping, too annoying with page breaks + {\push_macro_currentnamedsection + \push_macro_currentstructurereferenceprefix + \edef\currentnamedsection{#1}% + \setfalse\currentstructureown + %\globalpushmacro\currenthead % this does not work out well + \xdef\currenthead{#1}% + \setsystemmode\currenthead % new, also here now + \headparameter\c!beforesection % beware, no users vars set yet + \the\everybeforehead + \strc_sectioning_handle{#1}{#2}{#3}% name -- -- -- userdata (we might move the tagged to here) + % potential: \bgroup (can be optional: grouped = yes) + \headparameter\c!insidesection} + +\protected\def\strc_sectioning_stop[#1]% !!! also used at lua end + {\dostoptagged + \dostoptagged + % potential: \egroup + %\globalpopmacro\currenthead % so we do a hard recover + \xdef\currenthead{#1}% recover + \headparameter\c!aftersection + \the\everyafterhead + \resetsystemmode\currenthead + \pop_macro_currentstructurereferenceprefix + \pop_macro_currentnamedsection} % new, also here now + +\permanent\let\dostarthead\strc_sectioning_start % used at lua end +\permanent\let\dostophead \strc_sectioning_stop % used at lua end + +% \newconditional\structurereversesectionnumbers % todo: key/val + +\newconditional\c_strc_sectioning_to_list +\newconditional\c_strc_sectioning_increment +\newconditional\c_strc_sectioning_place +\newconditional\c_strc_sectioning_empty +\newconditional\c_strc_sectioning_hidden +\newconditional\c_strc_sectioning_section + +\newconditional\headshownumber % public +\newconditional\headisdisplay % public +\newconditional\headissomewhere % public + +\setvalue{\??headincrement\v!yes }{\settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list} +\setvalue{\??headincrement\v!no }{\setfalse\c_strc_sectioning_increment\setfalse\c_strc_sectioning_to_list} +\setvalue{\??headincrement\v!list }{\setfalse\c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list} +\setvalue{\??headincrement\s!empty}{\settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list} + +\protected\def\strc_sectioning_initialize_increment + {\edef\currentheadincrement{\headparameter\c!incrementnumber}% + \ifcsname\??headincrement\currentheadincrement\endcsname + \lastnamedcs + \else + \settrue \c_strc_sectioning_increment\settrue \c_strc_sectioning_to_list + % \filterheadnumber + \fi} + +\permanent\protected\def\filterheadnumber + {\settrue\c_strc_sectioning_increment + \settrue\c_strc_sectioning_to_list + \ifx\currentproduct\empty + % todo : filter from other toc (number, file, title) + % use : \currentheadincrement as spec + \fi} + +\setvalue{\??headplace\v!yes}% + {\setfalse\c_strc_sectioning_empty + \settrue \c_strc_sectioning_place + \setfalse\c_strc_sectioning_hidden + \setfalse\c_strc_sectioning_section} + +\setvalue{\??headplace\v!empty}% + {\settrue \c_strc_sectioning_empty + \settrue \c_strc_sectioning_place + \setfalse\c_strc_sectioning_hidden + \setfalse\c_strc_sectioning_section} + +\setvalue{\??headplace\v!no}% + {\settrue \c_strc_sectioning_empty + \setfalse\c_strc_sectioning_place + \setfalse\c_strc_sectioning_hidden + \setfalse\c_strc_sectioning_section} + +\setvalue{\??headplace\v!hidden}% + {\settrue \c_strc_sectioning_empty + \setfalse\c_strc_sectioning_place + \settrue \c_strc_sectioning_hidden + \setfalse\c_strc_sectioning_section} + +\setvalue{\??headplace\v!section}% + {\settrue \c_strc_sectioning_empty + \setfalse\c_strc_sectioning_place + \settrue \c_strc_sectioning_hidden + \settrue \c_strc_sectioning_section} + +\protected\def\strc_sectioning_initialize_placement + {\expandnamespaceparameter\??headplace\headparameter\c!placehead\v!yes} + +\newmode\v!sectionnumber + +\def\dosetstructureheadnumbercontent + {\setsystemmode\v!sectionnumber + \settrue\headshownumber} % why ? + +\def\doresetstructureheadnumbercontent + {\resetsystemmode\v!sectionnumber + \setfalse\headshownumber} % why ? + +\protected\def\strc_sectioning_initialize_number + {\edef\p_number{\sectionblockparameter\c!number}% + \ifx\p_number\v!yes + \edef\p_number{\headparameter\c!number}% + \ifx\p_number\v!yes + \settrue\headshownumber + \else + \setfalse\headshownumber + \fi + \else + \setfalse\headshownumber + \fi} + +% Beware, we do need some node for anchoring marks and normally a zwnj will +% do but it interferes so we deal with it at the \LUA\ end. + +\newtoks\everyheadsynchronization + +% \appendtoks +% \currentstructuresynchronize +% \to \everyheadsynchronization + +\let\currentstructuresynchronize\donothing + +\appendtoks + \currentstructuresynchronize + \glet\currentstructuresynchronize\donothing +\to \everyheadsynchronization + +\protected\def\theheadsynchonization + {% no, interferes: \signalcharacter + \the\everyheadsynchronization} + +% BEWARE: \marking[section]{my text} does not work as we use list indices instead +% so we need a 'keep track of raw set option' (or maybe a funny internal prefix) + +\permanent\protected\def\setheadmarking % li:: so that we can use \marking[section]{Taco needed this} + {\strc_sectioning_delayed_flush + \normalexpanded{\setmarking[\currenthead]{li::\currentstructurelistnumber}}} + +\let\deepstructurenumbercommand\relax +\let\deepstructuretitlecommand \relax + +\permanent\protected\def\fullheadnumber + {\edef\currentheadlabeltag{\currentsectionblock\c!label}% + \dostarttagged\t!sectionnumber\empty + \labeltexts + {\headparameter\currentheadlabeltag} + {\ifx\deepstructurenumbercommand\relax + \structurenumber + \else + \normalexpanded{\noexpand\deepstructurenumbercommand{\structurenumber}}% + \fi}% + \dostoptagged} + +\permanent\protected\def\fullheadtitle + {\dostarttagged\t!sectiontitle\empty + \ifx\deepstructuretitlecommand\relax + \structuretitle + \else + \normalexpanded{\noexpand\deepstructuretitlecommand{\structuretitle}}% + \fi + \dostoptagged} + +\let\currenthead \empty +\let\currentheadcoupling\empty +\let\currentheadsection \empty +\let\currentheadlevel \!!zerocount +\let\currentheadcounter \!!zerocount + +\let\strc_show_used\relax + +\installtextracker + {structures.showused} + {\let\strc_show_used\clf_showstructure} + {\let\strc_show_used\relax} + +\appendtoks + \strc_show_used +\to \everystoptext + +\permanent\protected\def\placeheadtext {\dosingleempty\strc_sectioning_place_head_text } % use with care +\permanent\protected\def\placeheadnumber{\dosingleempty\strc_sectioning_place_head_number} % use with care + +\protected\def\strc_sectioning_report{\clf_reportstructure} + +\ifdefined\strc_rendering_initialize_style_and_color \else + + \protected\def\strc_rendering_initialize_style_and_color#1#2% + {\dontconvertfont + \useheadstyleandcolor\c!style\c!color + \useheadstyleandcolor#1#2% + \setupinterlinespace} + +\fi + +\def\strc_sectioning_place_head_text[#1]% + {\dontleavehmode + \begingroup + \protected\def\\{\space}% messy here, but the default (and needs to be grouped) + \global\settrue\headisdisplay % triggers interlinespace checking + \edef\currenthead{#1}% + \strc_rendering_initialize_style_and_color\c!textstyle\c!textcolor + \relax + \getspecificstructuretitle{\thenamedheadlevel{#1}}% + \endgraf + \endgroup} + +\def\strc_sectioning_place_head_number[#1]% + {\dontleavehmode + \begingroup + \global\settrue\headisdisplay % triggers interlinespace checking + \edef\currenthead{#1}% + \strc_rendering_initialize_style_and_color\c!numberstyle\c!numbercolor + \relax + \getfullstructurenumber{\thenamedheadlevel{#1}}% + \endgraf + \endgroup} + +\ifdefined\triggerautostructurelevel \else \let\triggerautostructurelevel\relax \fi + +\newtoks\everybeforesectionheadhandle +\newtoks\everyaftersectionheadhandle + +\def\strc_sectioning_handle#1#2#3% name data userdata (we can move #1 to the caller) + {\xdef\currenthead {#1}% + \xdef\currentheadcoupling{\sectionheadcoupling\currenthead}% + \xdef\currentheadsection {\sectionheadsection \currentheadcoupling}% + \xdef\currentheadlevel {\sectionlevel \currentheadsection}% + % + %\writestatus\m!system{setup: \currenthead,\currentheadcoupling,\currentheadsection,\currentheadlevel}% + % + \strc_sectioning_initialize_autolevel + \strc_sectioning_initialize_increment + \strc_sectioning_initialize_placement + \strc_sectioning_initialize_number + % + \the\everybeforesectionheadhandle + % + % todo: also mark (for header) + % + % we might remove the lower level + % + % not here, after optional \page: \strc_sectioning_register{#1}{#2}{#3}% + % +% \xdef\currentheadcounter{\currentsectioncountervalue}% lua call + % + % \currentstructuresynchronize % will move + % + \let\getheadnumber\empty + \let\getheadtitle \empty + \let\getheadsyncs \empty + \ifconditional\c_strc_sectioning_increment + \ifconditional\c_strc_sectioning_place + \strc_sectioning_before_yes + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report + \dostarttagged\t!sectioncaption\empty + \let\getheadsyncs\theheadsynchonization + \let\getheadtitle\fullheadtitle + \ifconditional\headshownumber + \let\getheadnumber\fullheadnumber + \strc_rendering_place_head_number_and_text + \else + \strc_rendering_place_head_text + \fi + \dostoptagged + \strc_sectioning_after_yes + \orelse\ifconditional\c_strc_sectioning_hidden + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report + \dostarttagged\t!sectioncaption\empty + \let\getheadsyncs\theheadsynchonization + \ifconditional\c_strc_sectioning_section + \strc_rendering_place_head_section + \else + \strc_rendering_place_head_hidden % only something when tracing + \fi + \dostoptagged + \else + \strc_sectioning_before_nop % toegevoegd ivm subpaginanr / tug sheets + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report + \dostarttagged\t!sectioncaption\empty + \let\getheadsyncs\theheadsynchonization + \strc_rendering_place_head_empty % just flush 'm + \dostoptagged + \strc_sectioning_after_nop + \fi + \else + \ifconditional\c_strc_sectioning_place + \strc_sectioning_before_yes + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report + \dostarttagged\t!sectioncaption\empty + \let\getheadsyncs\theheadsynchonization + \let\getheadtitle\fullheadtitle + \strc_rendering_place_head_text + \dostoptagged + \strc_sectioning_after_yes + \orelse\ifconditional\c_strc_sectioning_hidden + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report + \let\getheadsyncs\theheadsynchonization + \dostarttagged\t!sectioncaption\empty + \ifconditional\c_strc_sectioning_section + \strc_rendering_place_head_section + \else + \strc_rendering_place_head_hidden % only something when tracing + \fi + \dostoptagged + \else + % do nothing / should be vbox to 0pt + \strc_sectioning_before_nop + \strc_sectioning_register{#1}{#2}{#3}% after optional \page + \strc_sectioning_report + \dostarttagged\t!sectioncaption\empty + \let\getheadsyncs\theheadsynchonization + \strc_rendering_place_head_empty % just flush 'm + \dostoptagged + \strc_sectioning_after_nop + \fi + \fi + % + \the\everyaftersectionheadhandle + % + \setfalse\c_strc_sectioning_ignore_page + % ignorespaces prevents spaces creeping in when after=\dontleavehmode + \dostarttagged\t!sectioncontent\empty + \ifx\currentstructureplaceholder\empty + \ifconditional\headisdisplay + \doubleexpandafter\ignorespaces + \else + \doubleexpandafter\ignorepars + \fi + \else + \expandafter\strc_sectioning_placeholder + \fi} + +%D \starttyping +%D \startsubject[placeholder=todo,title=one] +%D whatever one +%D \stopsubject +%D \stoptyping + +\def\strc_sectioning_placeholder + {\placeholder[\currentstructureplaceholder]% + \gobblenested{\e!start\currenthead}{\e!stop\currenthead}{\e!stop\currenthead}} + +% typesetting (the getters are public) + +\protected\def\strc_rendering_place_head_number_and_text + {\setheadmarking + \getheadnumber/\getheadtitle + \getheadsyncs} + +\protected\def\strc_rendering_place_head_text + {\setheadmarking + \getheadtitle + \getheadsyncs} + +\protected\def\strc_rendering_place_head_empty + {\setheadmarking + \getheadsyncs} + +\installcorenamespace{hiddenheadattr} +\installcorenamespace{hiddenheadsync} + +% todo: when in the page builder we need to resolve the marking immediately +% because otherwise we have an async + +\newbox\b_sectioning_delayed + +\def\strc_sectioning_delayed_flush + {\ifvoid\b_sectioning_delayed\else + \smashedbox\b_sectioning_delayed + \fi} + +\protected\def\strc_rendering_place_head_section % see hidden below + {\global\setbox\b_sectioning_delayed\hpack\bgroup + \setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}% + \hpack\headreferenceattributes{}% also does the mark + \theheadsynchonization + \egroup} + +\protected\def\strc_rendering_place_head_hidden % maybe trialtypesetting check + {\setxvalue{\??hiddenheadattr\currenthead}% + {\headreferenceattributes}% can be used when making a box + \setxvalue{\??hiddenheadsync\currenthead}% + {\noexpand\letgvalue{\??hiddenheadsync\currenthead}\relax + \noexpand\setmarking[\currentheadcoupling]{li::\currentstructurelistnumber}% + \hpack\headreferenceattributes{}% otherwise no destination ... maybe tag ref as hidden and fall back on page reference + \theheadsynchonization}} % and it's a node anyway + +\permanent\def\synchronizehead #1{\csname\??hiddenheadsync#1\endcsname} +\permanent\def\theheadreferenceattributes#1{\csname\??hiddenheadattr#1\endcsname} + +\permanent\protected\def\placerawheaddata [#1]{\synchronizehead{#1}} +\permanent\protected\def\placerawheadtext [#1]{\getspecificstructuretitle{\thenamedheadlevel{#1}}} +\permanent\protected\def\placerawheadnumber[#1]{\getfullstructurenumber{\thenamedheadlevel{#1}}} + +\permanent\protected\def\repeathead[#1]% + {\begingroup + \setupinteraction[\c!state=\v!stop]% + \def\currenthead{#1} + \strc_sectioning_initialize_placement + \strc_sectioning_initialize_number + \dostarttagged\t!sectioncaption\empty + \let\getheadsyncs \relax + \def\getheadtitle {\getmarking[#1]} + \def\getheadnumber{\getmarking[#1\v!number]} + \strc_sectioning_before_yes + \ifconditional\headshownumber + \strc_rendering_place_head_number_and_text + \else + \strc_rendering_place_head_text + \fi + \dostoptagged + \strc_sectioning_after_yes + \endgroup} + +% \setuphead[chapter][placehead=hidden] +% \chapter {test} +% +% %(\synchronizehead{chapter}) % \getheadsyncs +% %(\getfullstructurenumber{\thenamedheadlevel{chapter}}) +% %(\getspecificstructuretitle{\thenamedheadlevel{chapter}}) +% +% (\placerawheaddata [chapter]) +% (\placerawheadnumber[chapter]) +% (\placerawheadtext [chapter]) + +% pagebreaks + +\letvalue{\??headmarknop\v!page }\donothing +\setvalue{\??headmarknop\v!reset }{\resetcurrentstructuremarks} +\letvalue{\??headmarknop\s!unknown}\donothing + +\letvalue{\??headmarkyes\v!page }\donothing % to be checked: {\resetcurrentstructuremarks} +\setvalue{\??headmarkyes\v!reset }{\resetcurrentstructuremarks} +\letvalue{\??headmarkyes\s!unknown}\donothing + +\def\strc_sectioning_check_layout + {\edef\p_page{\headparameter\c!page}% + \ifx\p_page\empty + \strc_sectioning_check_layout_nop + \else + \strc_sectioning_check_layout_yes + \fi} + +\def\strc_sectioning_check_layout_nop + {\expandnamespaceparameter\??headmarknop\headparameter\c!marking\s!unknown} + +\def\strc_sectioning_check_layout_yes + {\page[\p_page]% + \expandnamespaceparameter\??headmarkyes\headparameter\c!marking\s!unknown + \edef\p_header{\headparameter\c!header}% + \ifx\p_header\empty \else + \doifelselayouttextline\v!header{\normalexpanded{\setuplayouttext[\v!header][\c!state=\p_header]}}\donothing + \fi + \edef\p_text{\headparameter\c!text}% + \ifx\p_text\empty \else + \doifelselayouttextline\v!text {\normalexpanded{\setuplayouttext[\v!text ][\c!state=\p_text ]}}\donothing + \fi + \edef\p_footer{\headparameter\c!footer}% + \ifx\p_footer\empty \else + \doifelselayouttextline\v!footer{\normalexpanded{\setuplayouttext[\v!footer][\c!state=\p_footer]}}\donothing + \fi} + +\newcount \c_strc_sectioning_preceding_level \c_strc_sectioning_preceding_level\plusone +\newconditional\c_strc_sectioning_auto_break \settrue\c_strc_sectioning_auto_break +\newconditional\c_strc_sectioning_ignore_page +\newsignal \s_strc_sectioning_continuous_signal + +\protected\def\strc_sectioning_inject_continuous_signal + {\ifhmode + \hskip\s_strc_sectioning_continuous_signal\relax + \fi} + +% \let\dotagsectionlevel\relax + +\def\strc_sectioning_before_yes + {\strc_sectioning_check_before\strc_sectioning_handle_page_yes + \headparameter\c!inbetween + \dostarttaggedchained\t!section\currenthead\??head +% \dotagsectionlevel + } + +\def\strc_sectioning_before_nop + {\strc_sectioning_check_before\strc_sectioning_handle_page_nop + \headparameter\c!inbetween + \dostarttagged\currenthead\empty} % this is a weird one .. needs checking + +\def\strc_sectioning_empty_correction + {\ifconditional\c_strc_sectioning_empty + % this needs checking + \penalty\plustenthousand + \vskip-\lineheight + \kern\zeropoint + \prevdepth\strutdepth + \fi} + +\def\strc_sectioning_after_nop + {} + +\def\strc_sectioning_check_before#1% + {\ifhmode + \scratchcounter\lastpenalty + \unpenalty % no beauty in this + \ifdim\lastskip=\s_strc_sectioning_continuous_signal + % no page break + \ifconditional\c_strc_sectioning_ignore_page + \setfalse\c_strc_sectioning_ignore_page + \else + \global\c_strc_sectioning_preceding_level\currentheadlevel + \nobreak + \fi + % \global\settrue\c_strc_rendering_continuous + \else + \penalty\scratchcounter + % \global\setfalse\c_strc_rendering_continuous + #1% + \fi + \else + % \global\setfalse\c_strc_rendering_continuous + #1% + \fi} + +%permanent\def\currentsectioncountervalue {\clf_depthnumber\numexpr\thenamedheadlevel\currenthead\relax} +%permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\currenthead+\minusone\relax} + +\permanent\def\currentsectioncountervalue {\clf_depthnumber\numexpr\thenamedheadlevel\currenthead\relax} +%permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\currenthead+\minusone\relax} +\permanent\def\previoussectioncountervalue{\clf_depthnumber\numexpr\thenamedheadlevel\previoushead\relax} + +\let\previoushead\empty + +\def\strc_sectioning_handle_page_nop + {\edef\p_continue{\headparameter\c!continue}% + \ifx\p_continue\v!yes + \ifx\currenthead\previoushead % not really needed + \strc_sectioning_check_layout + \orelse\ifnum\previoussectioncountervalue=\zerocount + \strc_sectioning_check_layout + \orelse\ifnum\currentsectioncountervalue>\zerocount + \strc_sectioning_check_layout + \fi + \else + \strc_sectioning_check_layout + \fi + \glet\previoushead\currenthead} + + +\def\strc_sectioning_handle_page_yes + {\ifconditional\c_strc_sectioning_ignore_page + \setfalse\c_strc_sectioning_ignore_page + \else + % beware, these numbers are not yet know here + \strc_sectioning_handle_page_nop + \edef\p_aligntitle{\headparameter\c!aligntitle}% + \ifx\p_aligntitle\v!float + \ifconditional\c_strc_sectioning_auto_break + \spac_vspacing_same_page\currentheadlevel\zerocount + \fi + \headparameter\c!before\relax + \indent + \else + \page_otr_command_flush_side_floats + \ifconditional\c_strc_sectioning_auto_break + \spac_vspacing_same_page\currentheadlevel\zerocount + \fi + \headparameter\c!before\relax + \fi + \global\c_strc_sectioning_preceding_level\currentheadlevel + \fi + \glet\previoushead\currenthead} + +\def\strc_sectioning_depth_correction + {\ifvmode + \edef\p_depthcorrection{\headparameter\c!depthcorrection}% + \ifx\p_depthcorrection\v!strut + \prevdepth\strutdepth + \fi + \fi} + +\def\strc_sectioning_after_yes + {\ifconditional\headisdisplay + \ifconditional\c_strc_sectioning_auto_break + \spac_vspacing_same_page\currentheadlevel\plusone + \fi + \strc_sectioning_empty_correction + \headparameter\c!after + \strc_sectioning_depth_correction + \fi} + +\protected\def\strc_sectioning_prevent_page_break % see strc-con + {\ifconditional\c_strc_sectioning_auto_break + \spac_vspacing_same_page\currentheadlevel\plustwo + \fi} + + +% We do support negative numbers but it can have side effects that we won't catch: +% +% \chapter{some} \setupheadnumber[chapter][3] \chapter{more} +% \setupheadnumber[section][8] \section{b} \section{c} \setupheadnumber[section][-1] \section{d} + +\def\thenamedheadlevel#1% + {\sectionlevel{\sectionheadsection{\sectionheadcoupling{#1}}}} + +\permanent\protected\def\setupheadnumber + {\dodoubleargument\strc_sectioning_setup_number} + +\def\strc_sectioning_setup_number[#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}}}} + +% The previous macro is been replaced by the expandable: + +\permanent\def\namedheadnumber #1{\getstructurenumber {\thenamedheadlevel{#1}}} +\permanent\def\somenamedheadnumber#1#2{\getsomestructurenumber{\thenamedheadlevel{#1}}{#2}} + +\permanent\protected\def\headnumber + {\dodoubleempty\strc_sectioning_number} + +\def\strc_sectioning_number[#1][#2]% simple case is just a number + {\getsomefullstructurenumber{\iffirstargument\thenamedheadlevel{#1}\fi}{#2}} + +\permanent\protected\def\someheadnumber + {\dodoubleempty\strc_sectioning_number_some} + +\def\strc_sectioning_number_some[#1][#2]% + {\dontleavehmode + \begingroup + \edef\currenthead{#1}% + \getsomefullstructurenumber{\thenamedheadlevel{#1}}{#2}% + \endgroup} + +\aliased\let\sectioncountervalue\structurevalue + +\def\currentheadtext{obsolete,\space use marks} + +% list references, will be redone in lua when we need it + +\let\startlistreferences\relax +\let\stoplistreferences \relax + +% experimental + +\newconditional\c_strc_sectioning_auto_levels + +\appendtoks + \settrue\c_strc_sectioning_auto_levels +\to \everyenableelements + +\protected\def\strc_sectioning_initialize_autolevel + {\ifconditional\c_strc_sectioning_auto_levels + \clf_autonextstructurelevel\currentheadlevel\relax + \global\setfalse\c_strc_sectioning_auto_levels + \fi} + +\permanent\protected\def\triggerautostructurelevel + {\global\settrue\c_strc_sectioning_auto_levels} + +\permanent\protected\def\finalizeautostructurelevels + {\clf_autofinishstructurelevels} + +\permanent\protected\def\finalizeautostructurelevel + {\dostoptagged + \dostoptagged} + +\appendtoks + \finalizeautostructurelevels +\to \everystoptext + +\stopcontextdefinitioncode + +\protect \endinput diff --git a/tex/context/base/mkiv/strc-syn.mkxl b/tex/context/base/mkiv/strc-syn.mkxl new file mode 100644 index 000000000..130d1737a --- /dev/null +++ b/tex/context/base/mkiv/strc-syn.mkxl @@ -0,0 +1,658 @@ +%D \module +%D [ file=strc-syn, +%D version=2008.10.20, +%D title=\CONTEXT\ Structure Macros, +%D subtitle=Synonyms and Sorting, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Structure Macros / Synonyms and Sorting} + +\registerctxluafile{strc-syn}{} + +%D Although we could nowadays build this on top of regular lists we keep this +%D more efficient variant around. Eventually we can add some options to lists +%D that also provide such functionality but at the cost of much more overhead. +%D +%D We show a usage of both synonyms and sorts, which are deep down variants of +%D so called simple lists. A definition looks like this: +%D +%D \startbuffer +%D \definesynonyms +%D [myabbreviation] +%D +%D \setupsynonyms +%D [myabbreviation] +%D [headstyle=bold, +%D headcolor=darkred, +%D synonymstyle=boldslanted, +%D synonymcolor=darkblue, +%D textstyle=slanted, +%D textcolor=darkgreen, +%D style=normal, +%D color=darkyellow] +%D +%D \definesorting +%D [mylogo] +%D +%D \setupsorting +%D [mylogo] +%D [style=bold, +%D color=darkmagenta] +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D More complex definitions involves commands to call up meanings and such. The +%D use of the defined commands is as follows: \ +%D +%D \startbuffer +%D \myabbreviation [FIRST] {TheFirst} {The First Words} +%D \myabbreviation [SECOND] {TheSecond} {The Second Words} +%D \myabbreviation [THIRD] {TheThird} {The Third Words} +%D +%D \mylogo [FOURTH] {TheFourth} +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D By default a synonym is just typeset and flagges as being used, so that in +%D a list it wil be shows with its meaning. You can however also expand the +%D meaning automatically at first use: +%D +%D \startbuffer +%D \setupsynonyms[myabbreviation][alternative=first] +%D +%D We have \FIRST, \SECOND\ and also \THIRD\ but no \FOURTH. +%D +%D We have \FIRST, \SECOND\ and also \THIRD\ but no \FOURTH. +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D We can change the order, as demonstrated in: +%D +%D \startbuffer +%D \resetshownsynonyms[myabbreviation] +%D +%D \setupsynonyms[myabbreviation][alternative=last] +%D +%D We have \FIRST\ and \THIRD\ or \FOURTH. +%D +%D We have \FIRST\ and \THIRD\ or \FOURTH. +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D A list is called up with: +%D +%D \startbuffer +%D \placelistofsynonyms[myabbreviation] +%D +%D \placelistofsorts[mylogo] +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D The lists are constructions (like descriptions are) and can be set up +%D likewise. + +% todo: add 'define only' option to descriptions, then add sorting (also based on key) +% and call to definition -> replaces this module + +\unprotect + +% split but common in lua + +\permanent\protected\def\preprocessexpansion#1#2#3#4% do this at the lua end if still needed + {\ifx#1\s!xml + \xmlstartraw + \xdef#2{#4}% + \xmlstopraw + \glet#3\s!xml + \else + \ifx#1\v!yes + \xdef#2{#4}% + \else + \xdef#2{\detokenize{#4}}% + \fi + \glet#3\s!tex + \fi} + +%D We now use a simple list variant: + +\installcorenamespace {simplelist} + +\installcommandhandler \??simplelist {simplelist} \??simplelist + +\let\setupsimplelists\setupsimplelist + +\setupsimplelists[% + %c!title=, + %c!text=, + % + %c!style=, + %c!color=, + %c!command=, + %c!align=, + % + %c!headstyle=, + %c!headcolor=, + %c!headalign=, + % + %c!titlestyle=, + %c!titlecolor=, + %c!titlecommand=, + %c!titleleft=, + %c!titleright=, + % + %c!closesymbol=, + %c!closecommand=, + % + \c!alternative=\v!left, + \c!display=\v!yes, + \c!width=7\emwidth, + \c!distance=\emwidth, + \c!titledistance=.5\emwidth, + %c!hang=, + %c!sample=, + \c!margin=\v!no, + \c!before=\startpacked, + \c!inbetween=\blank, + \c!after=\stoppacked, + %c!indentnext=, + %c!indenting=, + % + \c!expansion=\v!no, + %c!xmlsetup=, + %s!catcodes=, + \s!language=\currentmainlanguage, +] + +\appendtoks + \setfalse\c_strc_constructions_define_commands + \ifx\currentsimplelistparent\empty + \defineconstruction[\currentsimplelist][\s!handler=\v!simplelist,\c!level=1]% + \else + \defineconstruction[\currentsimplelist][\currentsimplelistparent][\s!handler=\v!simplelist,\c!level=1]% + \fi + \settrue\c_strc_constructions_define_commands +\to \everydefinesimplelist + +\setuvalue{\??constructioninitializer\v!simplelist}% + {\let \currentsimplelist \currentconstruction + \enforced\let\constructionparameter \simplelistparameter + \enforced\let\constructionnamespace \??simplelist + \enforced\let\detokenizedconstructionparameter\detokenizedsimplelistparameter + \enforced\let\letconstructionparameter \letsimplelistparameter + \enforced\let\useconstructionstyleandcolor \usesimpleliststyleandcolor + \enforced\let\setupcurrentconstruction \setupcurrentsimplelist} + +\setuvalue{\??constructionfinalizer\v!simplelist}% + {} + +\setuvalue{\??constructiontexthandler\v!simplelist}% + {\begingroup + \useconstructionstyleandcolor\c!headstyle\c!headcolor + \the\everyconstruction + \constructionparameter\c!headcommand + {\strut + \currentsimplelistentry}% + \endgroup} + +% And we build on top of this. + +\ifdefined\dotagsynonym \else \let\dotagsynonym\relax \fi +\ifdefined\dotagsorting \else \let\dotagsorting\relax \fi + +\definesimplelist + [\v!synonym] + [\c!state=\v!start, + %\c!synonymstyle=, + %\c!textstyle=, + %\c!headstyle=, + %\c!headcolor=, + %\c!criterium=, + \c!location=\v!left, + \c!width=5\emwidth, + \c!distance=\zeropoint, + %\c!sample=, + %\c!hang=, + %\c!align=, + %\c!before=, + %\c!inbetween=, + %\c!after=, + \c!indentnext=\v!no, + %\c!expansion=, + \c!method=] + +\aliased\let\setupsynonyms\setupsimplelist + +\permanent\tolerant\protected\def\definesynonyms[#1]#*[#2]#*[#3]#*[#4]% name plural \meaning \use + {\ifnum\lastarguments=\plusfour + \protected\instance\def#4##1{\strc_synonyms_insert{#1}{##1}}% name tag + \frozen\instance\setuvalue{#1}{\definesynonym[\v!no][#1]}% \name + \else + \frozen\instance\setuvalue{#1}{\definesynonym[\v!yes][#1]}% \name + \fi + \ifnum\lastarguments>\plustwo + \protected\frozen\instance\def#3##1{\strc_synonyms_insert_meaning{#1}{##1}}% \meaning + \fi + \edef\currentsynonym{#1}% + % + %\checksynonymparent + %\setupcurrentsynonym[\s!single={#1},\s!multi={#2}]% + \setfalse\c_strc_constructions_define_commands + \definesimplelist + [\currentsynonym]% + [\v!sorting] + [\s!single={#1},% + \s!multi={#2}]% + \settrue\c_strc_constructions_define_commands + \ifparameter#2\or + % + \presetheadtext[#2=\Word{#2}]% changes the \if...argument + % + % These will go away. Actually the overloads catched this empty case! + % + \instance\setuvalue{\e!setup #2\e!endsetup}{\setupsynonyms[#1]}% obsolete definition + \instance\setuvalue{\e!place \e!listof#2}{\placelistofsynonyms[#1]}% accepts extra argument + \instance\setuvalue{\e!complete\e!listof#2}{\completelistofsynonyms[#1]}% + \fi} + +\permanent\tolerant\protected\def\definesynonym[#1]#*[#2]#*[#3]% + {\begingroup + \edef\currentsynonymoption{#1}% + \edef\currentsynonym{#2}% + \edef\currentsynonymtag{#3}% + \strc_synonyms_define_entry} + +\def\strc_synonyms_define_entry#1#2% + {\let\currentsimplelist\currentsynonym + \ifempty\currentsynonymtag + \edef\currentsynonymtag{#1}% + \fi + \ifempty\currentsynonymtag \else + % this is not that efficient, esp when we load a big list + \edef\currentsynonymexpansion{\simplelistparameter\c!expansion}% + \preprocessexpansion\currentsynonymexpansion\m_synonyms_text \currentsynonymcoding{#1}% + \preprocessexpansion\currentsynonymexpansion\m_synonyms_meaning\currentsynonymcoding{#2}% + % + \clf_registersynonym + {\currentsynonym}% + {synonym}% + {% + metadata {% + catcodes \catcodetable + coding {\currentsynonymcoding}% + \ifx\currentsynonymcoding\s!xml + xmlroot {\xmldocument}% + \fi + }% + definition {% + tag {\currentsynonymtag}% + synonym {\m_synonyms_text}% + meaning {\m_synonyms_meaning}% + % used false + }% + }% + \relax + \ifx\currentsynonymoption\v!yes + \instance\setuxvalue\currentsynonymtag{\strc_synonyms_insert{\currentsynonym}{\currentsynonymtag}}% + \fi + \fi + \endgroup} + +\permanent\tolerant\protected\def\registersynonym [#1]#*[#2]{\clf_registerusedsynonym{#1}{#2}} +\permanent \protected\def\currentsynonymname {\clf_synonymname{\currentsimplelist}{\currentsynonymtag}} +\permanent \protected\def\currentsynonymmeaning {\clf_synonymmeaning{\currentsimplelist}{\currentsynonymtag}} +\permanent \protected\def\doifelsecurrentsynonymused {\clf_doifelsesynonymused{\currentsimplelist}{\currentsynonymtag}} +\permanent \protected\def\doifelsecurrentsynonymshown{\clf_doifelsesynonymshown{\currentsimplelist}{\currentsynonymtag}} +\permanent \protected\def\resetusedsynonyms [#1]{\clf_resetusedsynonyms{#1}} +\permanent \protected\def\resetshownsynonyms [#1]{\clf_resetshownsynonyms{#1}} + +\aliased\let\rawsynonymname \clf_synonymname +\aliased\let\rawsynonymmeaning\clf_synonymmeaning + +\installcorenamespace{simplelistalternative} % specific ways of rendering a list +\installcorenamespace{simplelistrenderings} % a namespace for setups (rather local) + +\installcommandhandler \??simplelistalternative {simplelistalternative} \??simplelistalternative + +\setupsimplelist + [\v!synonym] + [\c!alternative=\v!normal] + +\protected\def\strc_synonyms_insert_meaning#1#2% name tag + {\dontleavehmode % otherwise we don't get it right at the beginning of a par + \begingroup + \def\currentsimplelist{#1}% + \def\currentsynonymtag{#2}% + \fastsetup{\??simplelistrenderings::\v!text}% + \endgroup} + +\protected\def\strc_synonyms_insert#1#2% name tag + {\dontleavehmode % otherwise we don't get it right at the beginning of a par + \begingroup + \edef\currentsimplelist{#1}% + \let\currentsynonym\currentsimplelist % for a while + \def\currentsynonymtag{#2}% + \edef\currentsimplelistalternative{\simplelistparameter\c!alternative}% + \doifnotcommandhandler\??simplelistalternative\currentsimplelistalternative + {\let\currentsimplelistalternative\v!normal}% + \fastsetup{\??simplelistrenderings:\v!synonym:\currentsimplelistalternative}% + \normalexpanded{\endgroup\simplelistparameter\c!next}} + +% \setupsimplelistalternative +% [\c!command=\directsimplelistparameter\c!command] + +\definesimplelistalternative + [\v!normal] + [\c!inbetween=\space, + \c!left=(, + \c!right=)] + +\definesimplelistalternative + [\v!first] + [\v!normal] + +\definesimplelistalternative + [\v!last] + [\v!normal] + +\startsetups[\??simplelistrenderings::\v!synonym] + \begingroup + \dostarttaggedchained\t!synonym\currentsynonym\??simplelist + \dotagsynonym + \usesimpleliststyleandcolor\c!synonymstyle\c!synonymcolor + \simplelistparameter\c!synonymcommand{\currentsynonymname}% + \dostoptagged + \endgroup +\stopsetups + +\startsetups[\??simplelistrenderings::\v!text] + \begingroup + \usehyphensparameter\simplelistparameter + \usesimpleliststyleandcolor\c!textstyle\c!textcolor + \simplelistparameter\c!textcommand{\currentsynonymmeaning}% + \endgroup +\stopsetups + +\startsetups[\??simplelistrenderings:\v!synonym:\v!normal] + \fastsetup{\??simplelistrenderings::\v!synonym} +\stopsetups + +\startsetups[\??simplelistrenderings:\v!synonym:\v!first] + \fastsetup{\??simplelistrenderings::\v!synonym} + \doifelsecurrentsynonymshown \donothing { + \simplelistalternativeparameter\c!inbetween + \simplelistalternativeparameter\c!left + \fastsetup{\??simplelistrenderings::\v!text} + \simplelistalternativeparameter\c!right + } +\stopsetups + +\startsetups[\??simplelistrenderings:\v!synonym:\v!last] + \doifelsecurrentsynonymshown { + \fastsetup{\??simplelistrenderings::\v!synonym} + } { + \fastsetup{\??simplelistrenderings::\v!text} + \simplelistalternativeparameter\c!inbetween + \simplelistalternativeparameter\c!left + \fastsetup{\??simplelistrenderings::\v!synonym} + \simplelistalternativeparameter\c!right + } +\stopsetups + +\permanent\tolerant\protected\def\placelistofsynonyms[#1]#*[#2]% + {\begingroup + \edef\currentsimplelist{#1}% + \doifelsecommandhandler\??simplelist\currentsimplelist + {\strc_constructions_initialize{#1}% + \setupcurrentsimplelist[#2]% + \let\synonymentry\strc_synonym_normal + % so we can hook tabulate into before and after + \normalexpanded{\simplelistparameter\c!before + \noexpand\clf_processsynonyms + {#1}% + {% + criterium {\simplelistparameter\c!criterium}% + language {\simplelistparameter\s!language}% + method {\simplelistparameter\c!method}% + }% + \relax + \simplelistparameter\c!after}% + \relax}% + {}% todo: message that invalid + \endgroup} + +\permanent\tolerant\protected\def\completelistofsynonyms[#1]#*[#2]% + {\begingroup + \edef\currentsimplelist{#1}% + \doifelsecommandhandler\??simplelist\currentsimplelist + {\normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\simplelistparameter\s!multi}},\c!reference=#1]}% + \strc_synonyms_place_list[#1][#2]% + \page + \stopnamedsection}% + {}% todo: message that invalid + \endgroup} + +\protected\def\strc_synonym_normal#1#2#3#4% + {\begingroup + \def\currentsimplelistentry{#3}% + \csname\??constructionstarthandler\v!construction\endcsname + #4% + \csname\??constructionstophandler\v!construction\endcsname + \endgroup} + +%D Sorting (a simplified version of synonym). + +\definesimplelist + [\v!sorting] + [\c!state=\v!start, + %\c!command=, % we test for defined ! + %\c!criterium=, + %\c!style=, + \c!before=\startpacked, + \c!after=\stoppacked, + %\c!expansion=, + \c!method=] + +\aliased\let\setupsorting\setupsimplelist + +% if #3=\relax or \v!none, then no command but still protected + +\permanent\tolerant\protected\def\definesorting[#1]#*[#2]#*[#3]% + {\ifnum\lastarguments=\plusthree + \doifnot{#3}\v!none + {\ifx#3\relax \else + \protected\instance\def#3##1{\strc_sorting_insert{#1}{##1}}% + \fi}% + \frozen\instance\setuvalue{#1}{\definesort[\v!no][#1]}% + \else + \frozen\instance\setuvalue{#1}{\definesort[\v!yes][#1]}% + \fi + \edef\currentsorting{#1}% + \setfalse\c_strc_constructions_define_commands + \definesimplelist + [\currentsorting]% + [\v!sorting] + [\s!single={#1},% + \s!multi={#2}]% + \settrue\c_strc_constructions_define_commands + \ifparameter#2\or + % + \presetheadtext[#2=\Word{#2}]% changes the \if...argument + % + % These will go away. Actually the overloads catched this empty case! + % + % + \presetheadtext[#2=\Word{#2}]% after \ifthirdargument -) + % + \instance\setuvalue{\e!setup #2\e!endsetup}{\setupsorting[#1]}% obsolete definition + \instance\setuvalue{\e!place \e!listof#2}{\placelistofsorts[#1]}% + \instance\setuvalue{\e!complete\e!listof#2}{\completelistofsorts[#1]}% + \fi} + +\permanent\tolerant\protected\def\definesort[#1]#*[#2]#*[#3]% + {\begingroup + \edef\currentsortingoption{#1}% + \edef\currentsorting{#2}% + \edef\currentsortingtag{#3}% + \strc_sorting_define_entry} + +\def\strc_sorting_define_entry#1% + {\let\currentsimplelist\currentsimplelist + \ifempty\currentsortingtag + \edef\currentsortingtag{#1}% + \fi + \ifempty\currentsortingtag \else + \edef\currentsortingexpansion{\simplelistparameter\c!expansion}% + \preprocessexpansion\currentsortingexpansion\currentsortingtext\currentsortingcoding{#1}% + \clf_registersynonym + {\currentsorting}% + {sorting}% + {% + metadata {% + catcodes \catcodetable + coding {\currentsortingcoding}% + \ifx\currentsortingcoding\s!xml + xmlroot {\xmldocument}% + \fi + }% + definition {% + tag {\currentsortingtag}% + synonym {\currentsortingtext}% + % used false + }% + }% + \relax + \ifx\currentsortingoption\v!yes + \instance\setuxvalue\currentsortingtag{\strc_sorting_insert{\currentsorting}{\currentsortingtag}}% + \fi + \fi + \endgroup} + +\permanent\protected\def\currentsortingname {\clf_synonymname {\currentsimplelist}{\currentsortingtag}} +\permanent\protected\def\doifelsecurrentsortingused {\clf_doifelsesynonymused {\currentsimplelist}{\currentsortingtag}} +\permanent\protected\def\resetusedsortings [#1]{\clf_resetusedsynonyms {#1}} + +\setupsimplelist + [\v!sorting] + [\c!alternative=\v!normal] + +\protected\def\strc_sorting_insert#1#2% name tag + {\dontleavehmode % otherwise we don't get it right at the beginning of a par + \begingroup + % no kap currently, of .. we need to map cap onto WORD + \edef\currentsorting{#1}% + \edef\currentsortingtag{#2}% + \let\currentsimplelist\currentsorting + \edef\currentsimplelistalternative{\simplelistparameter\c!alternative}% + \doifnotcommandhandler\??simplelistalternative\currentsimplelistalternative + {\let\currentsimplelistalternative\v!normal}% + \fastsetup{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative}% + \normalexpanded{\endgroup\simplelistparameter\c!next}} + +% or: +% +% \doifelsesetups{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative} +% {\fastsetup{\??simplelistrenderings:\v!sorting:\currentsimplelistalternative}} +% {\fastsetup{\??simplelistrenderings:\v!sorting:\v!normal}} + +\startsetups [\??simplelistrenderings:\v!sorting:\v!normal] + \fastsetup{\??simplelistrenderings::\v!sorting}% +\stopsetups + +\startsetups [\??simplelistrenderings::\v!sorting] + \begingroup + \dostarttaggedchained\t!sorting\currentsorting\??simplelist + \dotagsorting + \usesimpleliststyleandcolor\c!style\c!color + \currentsortingname + \dostoptagged + \endgroup +\stopsetups + +\permanent\tolerant\protected\def\registersort[#1]#*[#2]% + {\clf_registerusedsynonym{#1}{#2}} + +% before after +% +% maybe just 'commandset' and then combine + +\permanent\tolerant\protected\def\placelistofsorts[#1]#*[#2]% + {\begingroup + \edef\currentsimplelist{#1}% + \strc_constructions_initialize{#1}% + \setupcurrentsimplelist[#2]% + \edef\p_simplelist_command{\simplelistparameter\c!command}% + \ifx\p_simplelist_command\empty + \let\synonymentry\strc_sorting_normal + \else + \let\synonymentry\strc_sorting_command + \fi + % so we can hook tabulate into before and after + \normalexpanded{\simplelistparameter\c!before + \noexpand\clf_processsynonyms + {#1}% + {% + criterium {\simplelistparameter\c!criterium}% + language {\simplelistparameter\s!language}% + method {\simplelistparameter\c!method}% + }% + \relax + \simplelistparameter\c!after}% + \endgroup} + +\permanent\tolerant\protected\def\completelistofsorts[#1]#*[#2]% + {\begingroup + \edef\currentsimplelist{#1}% + \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\simplelistparameter\s!multi}},\c!reference=#1]}% + \strc_sorting_place_list[#1][#2]% + \page + \stopnamedsection + \endgroup} + +\def\strc_sorting_command#1#2#3#4% #4 is meaning but empty here + {\p_simplelist_command{#1}{#2}{#3}} + +\def\strc_sorting_normal#1#2#3#4% #4 is meaning but empty here + {\begingroup + \usesimpleliststyleandcolor\c!style\c!color + #3% + \endgroup + \par} + +%D Presets. + +% To be considered: +% +% \setupsimplelist +% [\v!sorting] +% [\c!headstyle=\simplelistparameter\c!synonymstyle, +% \c!headcolor=\simplelistparameter\c!synonymcolor, +% \c!style=\simplelistparameter\c!textstyle, +% \c!color=\simplelistparameter\c!textcolor] + +\definesynonyms + [\v!abbreviation] + [\v!abbreviations] + [\infull] + +\setupsynonyms + [\v!abbreviation] + [\c!hyphens=\v!no, % new, not yet in setup definitions + \c!textstyle=\v!capital] + +\definesorting + [\v!logo] + [\v!logos] +% [\logogram] % no + +\protect \endinput diff --git a/tex/context/base/mkiv/supp-box.lmt b/tex/context/base/mkiv/supp-box.lmt index 61ec9b328..8a308f90f 100644 --- a/tex/context/base/mkiv/supp-box.lmt +++ b/tex/context/base/mkiv/supp-box.lmt @@ -29,7 +29,7 @@ local vlist_code = nodecodes.vlist local glue_code = nodecodes.glue local penalty_code = nodecodes.penalty local glyph_code = nodecodes.glyph -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local indent_code = nodes.listcodes.indent @@ -887,7 +887,7 @@ implement { b = getwidth(n) > 0 break end - elseif id ~= localpar_code then + elseif id ~= par_code then break end end @@ -1239,3 +1239,83 @@ do define_two("boxrangedp", "dp") end + +do + + local getbox = tex.getbox + local setfield = nodes.setfield + local getfield = nodes.getfield + local flush = nodes.flush + local copynode = nodes.copy + + local function get(n,field,copy) + local b = getbox(n) + if b then + local p = getfield(b,field) + if copy then + p = copynode(p) + else + setfield(b,field) + end + context(p) + end + end + + local function set(n,l,field) + local b = getbox(n) + if b then + setfield(b,field,l) + else + flush(l) + end + end + + implement { + name = "prelistbox", + public = true, + usage = "value", + arguments = { "integer", '"pre"' }, + actions = get, + } + + implement { + name = "postlistbox", + public = true, + usage = "value", + arguments = { "integer", '"post"' }, + actions = get, + } + + implement { + name = "prelistcopy", + public = true, + usage = "value", + arguments = { "integer", '"pre"', true }, + actions = get, + } + + implement { + name = "postlistcopy", + public = true, + usage = "value", + arguments = { "integer", '"post"', true }, + actions = get, + } + + implement { + name = "setprelistbox", + public = true, + usage = "value", + arguments = { "integer", "box", '"pre"' }, + actions = set, + } + + implement { + name = "setpostlistbox", + public = true, + usage = "value", + arguments = { "integer", "box", '"post"' }, + actions = set, + } + +end diff --git a/tex/context/base/mkiv/supp-box.lua b/tex/context/base/mkiv/supp-box.lua index d26742a5b..4914b6818 100644 --- a/tex/context/base/mkiv/supp-box.lua +++ b/tex/context/base/mkiv/supp-box.lua @@ -29,7 +29,7 @@ local vlist_code = nodecodes.vlist local glue_code = nodecodes.glue local penalty_code = nodecodes.penalty local glyph_code = nodecodes.glyph -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local indent_code = nodes.listcodes.indent @@ -854,7 +854,7 @@ implement { b = getwidth(n) > 0 break end - elseif id ~= localpar_code then + elseif id ~= par_code then break end end diff --git a/tex/context/base/mkiv/supp-box.mkiv b/tex/context/base/mkiv/supp-box.mkiv index b9835875d..16f093023 100644 --- a/tex/context/base/mkiv/supp-box.mkiv +++ b/tex/context/base/mkiv/supp-box.mkiv @@ -112,16 +112,16 @@ %D Smashing is introduced in \PLAIN\ \TEX, and stands for reducing the dimensions of %D a box to zero. The most resolute one is presented first. -\protected\def\smashbox#1% - {\wd#1\zeropoint - \ht#1\zeropoint - \dp#1\zeropoint} +% \protected\def\smashbox#1% +% {\wd#1\zeropoint +% \ht#1\zeropoint +% \dp#1\zeropoint} -\protected\def\smashboxed#1% - {\wd#1\zeropoint - \ht#1\zeropoint - \dp#1\zeropoint - \box#1\relax} +% \protected\def\smashboxed#1% +% {\wd#1\zeropoint +% \ht#1\zeropoint +% \dp#1\zeropoint +% \box#1\relax} %D \macros %D {hsmashbox,vsmashbox} @@ -170,6 +170,8 @@ \dp\c_boxes_register\zeropoint \box\c_boxes_register} +\let\smashboxed\smashedbox + %D \macros %D {hsmash,vsmash, %D hsmashed,vsmashed} @@ -1105,8 +1107,8 @@ \protected\def\processtokens#1#2#3#4#5% {\begingroup \def\lastcharacter{\lastcharacter}% hm, recursive ? + \let\\\space \def\space{ }% - \let\\=\space \def\before {#1}% \def\between{#2}% \def\after {#3}% @@ -2263,9 +2265,9 @@ \scratchdimen\zeropoint \def\docommand {\advance\sizeofbox\scratchdimen - \futurelet\next\dodocommand}% + \futurelet\nexttoken\dodocommand}% \def\dodocommand - {\ifx\next\bgroup + {\ifx\nexttoken\bgroup \expanded{\egroup#1 to \the\sizeofbox}% \else \expandafter\afterassignment\expandafter\docommand\expandafter\scratchdimen diff --git a/tex/context/base/mkiv/supp-box.mkxl b/tex/context/base/mkiv/supp-box.mkxl index 4e29550e2..2ed9ea9c1 100644 --- a/tex/context/base/mkiv/supp-box.mkxl +++ b/tex/context/base/mkiv/supp-box.mkxl @@ -25,18 +25,6 @@ % \fixupboxesmode\plusone % gone: is now the default -%D \macros -%D {dontcomplain} -%D -%D The next macro suppresses over- and underfull messages which often makes sense -%D when we deal with boxes. - -\protected\def\dontcomplain - {\hbadness\plustenthousand - \vbadness\plustenthousand - \hfuzz \maxdimen - \vfuzz \maxdimen} - %D This module implements some box manipulation macros. Some are quite simple, some %D are more advanced and when understood well, all can be of use. %D @@ -47,6 +35,8 @@ %D not, you're in trouble). These shortcuts can be used like a dimension, opposite %D to the core macros \type {\strutdepth} and alike, which are values. +%D These will be overloaded in spac-ver: + \def\strutdp {\dp\strutbox} \def\strutht {\ht\strutbox} \def\strutwd {\wd\strutbox} @@ -72,21 +62,21 @@ \newdimen\nextdepth %D \macros -%D {smashbox, smashedbox} +%D {smashbox, smashboxed, smashedbox} %D %D Smashing is introduced in \PLAIN\ \TEX, and stands for reducing the dimensions of %D a box to zero. The most resolute one is presented first. -\protected\def\smashbox#1% - {\wd#1\zeropoint - \ht#1\zeropoint - \dp#1\zeropoint} - -\protected\def\smashboxed#1% - {\wd#1\zeropoint - \ht#1\zeropoint - \dp#1\zeropoint - \box#1\relax} +% \permanent\protected\def\smashbox#1% +% {\wd#1\zeropoint +% \ht#1\zeropoint +% \dp#1\zeropoint} +% +% \permanent\protected\def\smashboxed#1% +% {\wd#1\zeropoint +% \ht#1\zeropoint +% \dp#1\zeropoint +% \box#1\relax} %D \macros %D {hsmashbox,vsmashbox} @@ -94,18 +84,18 @@ %D Smashing can be used for overlaying boxes. Depending on the mode, horizontal or %D vertical, one can use: -\protected\def\hsmashbox#1% - {\wd#1\zeropoint} - -\protected\def\vsmashbox#1% - {\ht#1\zeropoint - \dp#1\zeropoint} +% \permanent\protected\def\hsmashbox#1% +% {\wd#1\zeropoint} +% +% \permanent\protected\def\vsmashbox#1% +% {\ht#1\zeropoint +% \dp#1\zeropoint} %D The next implementation is less sensitive for spurious spaces. \newcount\c_boxes_register -\protected\def\smashbox +\permanent\protected\def\smashbox {\afterassignment\syst_boxes_smash_boxes_register\c_boxes_register} \def\syst_boxes_smash_boxes_register @@ -113,20 +103,20 @@ \ht\c_boxes_register\zeropoint \dp\c_boxes_register\zeropoint} -\protected\def\hsmashbox +\permanent\protected\def\hsmashbox {\afterassignment\syst_boxes_hsmashed_boxes_register\c_boxes_register} \def\syst_boxes_hsmashed_boxes_register {\wd\c_boxes_register\zeropoint} -\protected\def\vsmashbox +\permanent\protected\def\vsmashbox {\afterassignment\syst_boxes_vsmashed_boxes_register\c_boxes_register} \def\syst_boxes_vsmashed_boxes_register {\ht\c_boxes_register\zeropoint \dp\c_boxes_register\zeropoint} -\protected\def\smashedbox +\permanent\protected\def\smashedbox {\afterassignment\syst_boxes_smashed_boxes_register\c_boxes_register} \protected\def\syst_boxes_smashed_boxes_register @@ -135,6 +125,8 @@ \dp\c_boxes_register\zeropoint \box\c_boxes_register} +\let\smashboxed\smashedbox + %D \macros %D {hsmash,vsmash, %D hsmashed,vsmashed} @@ -143,10 +135,10 @@ %D some subtle differences betreen the smash and smashed alternatives. The later %D ones reduce all dimensions to zero. -\protected\def\hsmash {\bgroup\dowithnextboxcs\syst_boxes_hsmashed_nextbox\hbox} -\protected\def\vsmash {\bgroup\dowithnextboxcs\syst_boxes_vsmashed_nextbox\vbox} -\protected\def\hsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \hbox} -\protected\def\vsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \vbox} +\permanent\protected\def\hsmash {\bgroup\dowithnextboxcs\syst_boxes_hsmashed_nextbox\hbox} +\permanent\protected\def\vsmash {\bgroup\dowithnextboxcs\syst_boxes_vsmashed_nextbox\vbox} +\permanent\protected\def\hsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \hbox} +\permanent\protected\def\vsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \vbox} \protected\def\syst_boxes_hsmashed_nextbox {\wd\nextbox\zeropoint @@ -176,8 +168,8 @@ %D \smashedvbox to ... {...} %D \stoptyping -\protected\def\smashedhbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\hbox} -\protected\def\smashedvbox{\vpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\vbox} +\permanent\protected\def\smashedhbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\hbox} +\permanent\protected\def\smashedvbox{\vpack\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\vbox} %D First we define a helper. We use a \LUATEX\ feature in order to avoid %D mathpalettes. @@ -195,7 +187,7 @@ %D catcode safer. It is needed by the math module (although the \type {\leavevmode} %D is not added here). -\protected\def\smash +\permanent\protected\def\smash {\begingroup \futureexpandis[\syst_boxes_smash_yes\syst_boxes_smash_nop} @@ -267,9 +259,9 @@ %D {\mathchoice}, the next macro looks ugly. We also take care of non||braced %D arguments. -\protected\def\phantom {\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed } -\protected\def\vphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_v} -\protected\def\hphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_h} +\permanent\protected\def\phantom {\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed } +\permanent\protected\def\vphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_v} +\permanent\protected\def\hphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_h} \def\syst_boxes_phantom_math #1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make } \def\syst_boxes_phantom_math_v#1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make_v} @@ -333,7 +325,7 @@ %D We also define plain's \type {\mathstrut}. -\protected\def\mathstrut{\vphantom(} % can be made faster by inlining +\permanent\protected\def\mathstrut{\vphantom(} % can be made faster by inlining %D \macros %D {getboxheight} @@ -367,7 +359,7 @@ %D The next alternative is slightly more clever, since it accepts \type {{12}} as %D well as \type {12} as box number. -\protected\def\getboxheight#1\of#2\box#3% +\permanent\protected\def\getboxheight#1\of#2\box#3% {\def\next{#1\htdp\c_boxes_register}% \afterassignment\next\c_boxes_register=#3} @@ -416,7 +408,7 @@ \newcount\noflines \newdimen\noflinesheight -\protected\def\getnoflines#1% +\permanent\protected\def\getnoflines#1% {\noflinesheight#1\relax \ifzeropt\noflinesheight \noflines\zerocount @@ -432,7 +424,7 @@ \advance\noflines\minusone \fi} -\protected\def\getroundednoflines#1% +\permanent\protected\def\getroundednoflines#1% {\noflinesheight#1\relax \ifzeropt\noflinesheight \noflines\zerocount @@ -446,7 +438,7 @@ \noflines\noflinesheight \fi} -\protected\def\getrawnoflines#1% +\permanent\protected\def\getrawnoflines#1% {\noflinesheight#1\relax \ifzeropt\noflinesheight \noflines\zerocount @@ -510,11 +502,11 @@ \def\syst_boxes_determine_noflines {\expandafter\egroup\expandafter\noflines\noflinesinbox\nextbox\relax} -\protected\def\determinenoflines +\permanent\protected\def\determinenoflines {\bgroup \forgetall - \let\crlf\endgraf - \let\\\endgraf + \enforced\let\crlf\endgraf + \enforced\let\\\endgraf \dowithnextboxcs\syst_boxes_determine_noflines\vbox} %D \macros @@ -528,7 +520,7 @@ %D \doiftext {data} {then branch} %D \stoptyping -\protected\def\doifelsetext#1% +\permanent\protected\def\doifelsetext#1% {\begingroup \setbox\scratchbox\hbox % no \hpack because we can have fallbacks {\settrialtypesetting @@ -539,7 +531,7 @@ \endgroup\expandafter\firstoftwoarguments \fi} -\protected\def\doiftext#1% +\permanent\protected\def\doiftext#1% {\begingroup \setbox\scratchbox\hbox % no \hpack because we can have fallbacks {\settrialtypesetting @@ -589,7 +581,7 @@ %D In this implementation the \type {\aftergroup} construction is needed because %D \type {\afterassignment} is executed inside the box. -\protected\def\dowithnextbox#1% +\permanent\protected\def\dowithnextbox#1% {\def\syst_boxes_with_next_box{#1}% \afterassignment\syst_boxes_with_next_box_indeed \setbox\nextbox} @@ -597,7 +589,7 @@ \def\syst_boxes_with_next_box_indeed {\aftergroup\syst_boxes_with_next_box} -\protected\def\dowithnextboxcs#1% +\permanent\protected\def\dowithnextboxcs#1% {\let\syst_boxes_with_next_box#1% \afterassignment\syst_boxes_with_next_box_indeed \setbox\nextbox} @@ -642,12 +634,12 @@ %D The next couple of shortcuts saves us memory as well as \type {{}}'s in passing %D parameters. -\def\nextboxht {\ht\nextbox} -\def\nextboxwd {\wd\nextbox} -\def\nextboxdp {\dp\nextbox} -\def\nextboxhtdp{\htdp\nextbox} +\permanent\def\nextboxht {\ht\nextbox} +\permanent\def\nextboxwd {\wd\nextbox} +\permanent\def\nextboxdp {\dp\nextbox} +\permanent\def\nextboxhtdp{\htdp\nextbox} -\protected\def\flushnextbox{\box\nextbox} +\permanent\protected\def\flushnextbox{\box\nextbox} %D \macros %D {dowithnextboxcontent} @@ -661,16 +653,24 @@ %D %D {\em todo: Search source for potential usage!} -\protected\def\dowithnextboxcontent#1#2% inside, after - {\def\syst_boxes_with_next_box_one{#2}% - \def\syst_boxes_with_next_box_two{#1}% - \afterassignment\syst_boxes_with_next_box_content_indeed +% \protected\def\dowithnextboxcontent#1#2% inside, after +% {\def\syst_boxes_with_next_box_one{#2}% +% \def\syst_boxes_with_next_box_two{#1}% +% \afterassignment\syst_boxes_with_next_box_content_indeed +% \setbox\nextbox} +% +% \protected\def\dowithnextboxcontentcs#1#2% inside, after +% {\let\syst_boxes_with_next_box_one#2% +% \let\syst_boxes_with_next_box_two#1% +% \afterassignment\syst_boxes_with_next_box_content_indeed +% \setbox\nextbox} + +\permanent\unexpanded\def\dowithnextboxcontent#1#2% inside, after + {\afterassigned{#1\aftergrouped{#2}}% \setbox\nextbox} -\protected\def\dowithnextboxcontentcs#1#2% inside, after - {\let\syst_boxes_with_next_box_one#2% - \let\syst_boxes_with_next_box_two#1% - \afterassignment\syst_boxes_with_next_box_content_indeed +\permanent\unexpanded\def\dowithnextboxcontentcs#1#2% inside, after + {\afterassigned{#1\aftergroup#2}% \setbox\nextbox} \def\syst_boxes_with_next_box_content_indeed @@ -682,27 +682,28 @@ %D Some well known friends, but we implement them our own way. We want the macros to %D work in both math and text mode. -\def\dodorlap{\hpack to \zeropoint{\box\nextbox\hss}\endgroup} -\def\dodollap{\hpack to \zeropoint{\hss\box\nextbox}\endgroup} -\def\dodoclap{\hpack to \zeropoint{\hss\box\nextbox\hss}\endgroup} - -\def\dorlap{\begingroup\dowithnextboxcs\dodorlap\hbox} -\def\dollap{\begingroup\dowithnextboxcs\dodollap\hbox} -\def\doclap{\begingroup\dowithnextboxcs\dodoclap\hbox} - -\def\domathclap{\mathpalette\dodomathclap} \def\dodomathclap#1#2{\doclap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}} -\def\domathllap{\mathpalette\dodomathllap} \def\dodomathllap#1#2{\dollap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}} -\def\domathrlap{\mathpalette\dodomathrlap} \def\dodomathrlap#1#2{\dorlap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}} - -\protected\def\rlap{\mathortext\domathrlap\dorlap} -\protected\def\llap{\mathortext\domathllap\dollap} -\protected\def\clap{\mathortext\domathclap\doclap} - -\def\dodotlap{\vpack to \zeropoint{\vss\box\nextbox}\endgroup} -\def\dodoblap{\vpack to \zeropoint{\box\nextbox\vss}\endgroup} - -\protected\def\tlap{\begingroup\dowithnextboxcs\dodotlap\vbox} -\protected\def\blap{\begingroup\dowithnextboxcs\dodoblap\vbox} +\def\syst_boxes_do_rlap{\hpack to \zeropoint{\box\nextbox\hss}\endgroup} +\def\syst_boxes_do_llap{\hpack to \zeropoint{\hss\box\nextbox}\endgroup} +\def\syst_boxes_do_clap{\hpack to \zeropoint{\hss\box\nextbox\hss}\endgroup} +\def\syst_boxes_do_tlap{\vpack to \zeropoint{\vss\box\nextbox}\endgroup} +\def\syst_boxes_do_blap{\vpack to \zeropoint{\box\nextbox\vss}\endgroup} + +\def\syst_boxes_rlap {\begingroup\dowithnextboxcs\syst_boxes_do_rlap\hbox} +\def\syst_boxes_llap {\begingroup\dowithnextboxcs\syst_boxes_do_llap\hbox} +\def\syst_boxes_clap {\begingroup\dowithnextboxcs\syst_boxes_do_clap\hbox} +\def\syst_boxes_math_clap{\mathpalette\syst_boxes_do_math_clap} +\def\syst_boxes_math_llap{\mathpalette\syst_boxes_do_math_llap} +\def\syst_boxes_math_rlap{\mathpalette\syst_boxes_do_math_rlap} + +\def\syst_boxes_do_math_clap#1#2{\syst_boxes_clap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}} +\def\syst_boxes_do_math_llap#1#2{\syst_boxes_llap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}} +\def\syst_boxes_do_math_rlap#1#2{\syst_boxes_rlap{\normalstartimath\mathsurround\zeropoint#1#2\normalstopimath}} + +\permanent\protected\def\rlap{\mathortext\syst_boxes_math_rlap\syst_boxes_rlap} +\permanent\protected\def\llap{\mathortext\syst_boxes_math_llap\syst_boxes_llap} +\permanent\protected\def\clap{\mathortext\syst_boxes_math_clap\syst_boxes_clap} +\permanent\protected\def\tlap{\begingroup\dowithnextboxcs\syst_boxes_do_tlap\vbox} +\permanent\protected\def\blap{\begingroup\dowithnextboxcs\syst_boxes_do_blap\vbox} %D \macros %D {beginofshapebox, @@ -816,6 +817,10 @@ %D bad spacing. This means that for instance linenumbers etc. should be given zero %D height and depth before being lapped into the margin. The previous examples %D ignore this side effect, but beware! +%D +%D This is ancient stuff and proably not used any more but we keep it around or +%D maybe turn it into a module some day. It shows the kind of struggling that we +%D needed before \LUATEX\ came around. \newif \ifsomeshapeleft \newif \ifreshapingbox @@ -836,7 +841,7 @@ \def\shapesignal{.12345678pt} % or 12345sp -\protected\def\reshapebox#1% +\permanent\protected\def\reshapebox#1% {\doreshapebox {#1}% {\penalty\shapepenalty}% @@ -860,14 +865,14 @@ % We will turn this into a \MKIV\ variant (we can use \type {\vpack} too). -\protected\def\insertshapesignal +\permanent\protected\def\insertshapesignal {\hpack to \shapesignal{\strut\hss}% plus \strut \prevdepth\strutdp} % never \nointerlineskip -\protected\def\restoreshapebox % compensates for the signal +\permanent\protected\def\restoreshapebox % compensates for the signal {\global\setbox\tmpshapebox\vbox{\vskip-\lineheight\unvcopy\oldshapebox}} -\def\dodoreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip +\permanent\def\dodoreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip {\ifnum\lastnodetype=\gluenodecode \shapeskip\lastskip \global\setbox\tmpshapebox\vbox{#4\unvbox\tmpshapebox}% @@ -901,21 +906,21 @@ \advance\shapecounter \plusone \fi} -\protected\def\beginofshapebox +\permanent\protected\def\beginofshapebox {\setbox\oldshapebox\vbox \bgroup \reshapingboxtrue \the\everyshapebox \insertshapesignal} -\protected\def\endofshapebox +\permanent\protected\def\endofshapebox {\endgraf \egroup} \let\beginshapebox\beginofshapebox \let\endshapebox \endofshapebox -\protected\def\flushshapebox +\permanent\protected\def\flushshapebox {\bgroup \ifzeropt\ht\newshapebox \else @@ -966,7 +971,7 @@ % % \omlijnd[offset=0pt,hoogte=8mm,uitlijnen={rechts,laho}]{\bfa test} -\protected\def\innerflushshapebox +\permanent\protected\def\innerflushshapebox {\ifzeropt\ht\newshapebox \else \unvcopy\newshapebox\relax % unvcopy ! else spacing problem % \kern-\dp\newshapebox\relax @@ -989,7 +994,7 @@ %D use \type {\shapedhbox} instead of \type {\hbox}, since it manages the height and %D depth of the line. -\protected\def\shapedhbox % lines with non strutted dimensions have +\permanent\protected\def\shapedhbox % lines with non strutted dimensions have {\expanded{\dowithnextbox % interlineskip so if we want the original {\ht\nextbox\the\ht\shapebox % spacing, we need to preserve the original \dp\nextbox\the\dp\shapebox % height and depth which is definitely @@ -1009,10 +1014,10 @@ %D \showhyphens{dohyphenatedword} %D \stoptyping -\protected\def\doshowhyphenatednextbox +\permanent\protected\def\doshowhyphenatednextbox {\clf_showhyphenatedinlist\nextbox} -\protected\def\showhyphens % hpack: so no processing (we hyphenate in lua) +\permanent\protected\def\showhyphens % hpack: so no processing (we hyphenate in lua) {\dowithnextboxcs\doshowhyphenatednextbox\hpack} %D The following macros are seldom used but handy for tracing. @@ -1023,19 +1028,13 @@ %D \hyphenatedfile{tufte} %D \stoptyping -\protected\def\dohyphenatednextbox - {\clf_hyphenatedlist\nextbox false\relax - \unhbox\nextbox} - -\protected\def\hyphenatedword {\dowithnextboxcs\dohyphenatednextbox\hbox} -\protected\def\hyphenatedpar {\dowithnextboxcs\dohyphenatednextbox\hbox} -\protected\def\hyphenatedfile#1{\dowithnextboxcs\dohyphenatednextbox\hbox{\readfile{#1}\donothing\donothing}} +\def\syst_boxes_hyphenatednextbox {\clf_hyphenatedlist\nextbox false\relax\unhbox\nextbox} +\def\syst_boxes_hyphenatednextboxcolor{\clf_hyphenatedlist\nextbox true \relax\unhbox\nextbox} -\protected\def\dohyphenatednextboxcolor - {\clf_hyphenatedlist\nextbox true\relax - \unhbox\nextbox} - -\protected\def\hyphenatedcoloredword{\dowithnextboxcs\dohyphenatednextboxcolor\hbox} +\permanent\protected\def\hyphenatedword {\dowithnextboxcs\syst_boxes_hyphenatednextbox\hbox} +\permanent\protected\def\hyphenatedpar {\dowithnextboxcs\syst_boxes_hyphenatednextbox\hbox} +\permanent\protected\def\hyphenatedfile #1{\dowithnextboxcs\syst_boxes_hyphenatednextbox\hbox{\readfile{#1}\donothing\donothing}} +\permanent\protected\def\hyphenatedcoloredword{\dowithnextboxcs\syst_boxes_hyphenatednextboxcolor\hbox} %D \macros %D {processtokens} @@ -1064,34 +1063,36 @@ %D The list of tokens may contain spaces, while \type {\\}, \type {{}} and \type {\ %D } are handled as space too. -\protected\def\processtokens#1#2#3#4#5% +%D This can be done in a more modern way but for nostalgic reasons we keep it. + +\permanent\protected\def\processtokens#1#2#3#4#5% {\begingroup \def\lastcharacter{\lastcharacter}% hm, recursive ? - \def\space{ }% - \let\\=\space + \enforced\permanent\def\space{ }% + \enforced\let\\\space \def\before {#1}% \def\between{#2}% \def\after {#3}% \def\white {#4}% \let\savedbefore\before - \doprocesstokens#5\lastcharacter + \syst_boxes_processtokens#5\lastcharacter \endgroup} -\def\doprocesstokens% the space after = is essential - {\afterassignment\dodoprocesstokens\let\nextprocessedtoken= } +\def\syst_boxes_processtokens% the space after = is essential + {\afterassignment\syst_boxes_do_processtokens\let\nextprocessedtoken= } -\def\redoprocessedtoken +\def\syst_boxes_redo_processedtoken {\dowithnextbox {\before{\copy\nextbox}% \before can use nextbox several times \let\before\between - \doprocesstokens} + \syst_boxes_processtokens} \hbox\bgroup} -\def\dodoprocesstokens +\def\syst_boxes_do_processtokens {\ifx\nextprocessedtoken\lastcharacter \after \orelse\ifx\nextprocessedtoken\bgroup - \expandafter\redoprocessedtoken + \expandafter\syst_boxes_redo_processedtoken \else \expandafter\if\space\nextprocessedtoken \after\white @@ -1100,7 +1101,7 @@ \before\nextprocessedtoken \let\before\between \fi - \expandafter\doprocesstokens + \expandafter\syst_boxes_processtokens \fi} %D \macros @@ -1118,20 +1119,22 @@ %D %D When calculating the room needed, we take the width of the third argument into %D account, which leads to a bit more complex macro than needed at first sight. +%D +%D Sort of obsolete I guess: -\def\dodoboundtext#1% +\def\syst_boxes_boundtext#1% {\setbox\scratchboxone\hbox{#1}% \advance\scratchdimen -\wd\scratchboxone \ifdim\scratchdimen>\zeropoint\relax#1\fi} -\def\doboundtext#1#2#3% still used? +\permanent\protected\def\doboundtext#1#2#3% still used? {\hbox {\setbox\scratchbox\hbox{#1}% \scratchdimen#2\relax \ifdim\wd\scratchbox>\scratchdimen \setbox\scratchbox\hbox{#3}% \advance\scratchdimen -\wd\scratchbox - \handletokens#1\with\dodoboundtext + \handletokens#1\with\syst_boxes_boundtext \fi \box\scratchbox}} @@ -1155,7 +1158,7 @@ %D See \MKIV\ file for the older implementation. -\protected\def\limitatetext#1#2#3% +\permanent\protected\def\limitatetext#1#2#3% {\splitatcomma{#2}\leftlimit\rightlimit \limitated left \leftlimit @@ -1173,7 +1176,7 @@ %D \limitatefirstline{\input tufte\relax}{10cm}{\unknown} %D \stoptyping -\protected\def\limitatefirstline#1#2#3% +\permanent\protected\def\limitatefirstline#1#2#3% {\hbox\bgroup\strut % \hpack \setbox\scratchbox\hbox{\begstrut#1\endstrut}% \ifdim\wd\scratchbox>#2\relax @@ -1216,7 +1219,7 @@ % todo: provide variant with #1 picked up as box -\protected\def\processisolatedchars#1#2% +\permanent\protected\def\processisolatedchars#1#2% {\dontleavehmode \begingroup \setbox\scratchbox\hbox{\settrialtypesetting#2{\savecurrentattributes{pic}}}% @@ -1229,7 +1232,7 @@ \relax \endgroup} -\protected\def\processisolatedwords#1#2% +\permanent\protected\def\processisolatedwords#1#2% {\dontleavehmode \begingroup \setbox\scratchbox\hbox{\settrialtypesetting#2{\savecurrentattributes{pic}}}% @@ -1244,7 +1247,7 @@ %D A variant: -\protected\def\applytocharacters#1% +\permanent\protected\def\applytocharacters#1% {\dontleavehmode \dowithnextbox{\clf_applytobox method {char}% @@ -1254,7 +1257,7 @@ \relax}% \hbox} -\protected\def\applytowords#1% +\permanent\protected\def\applytowords#1% {\dontleavehmode \dowithnextbox{\clf_applytobox method {word}% @@ -1266,33 +1269,33 @@ %D The old call: -\protected\def\processwords#1% +\permanent\protected\def\processwords#1% {\processisolatedwords{#1}\processword} \let\processword\relax -\protected\def\applytosplitstringchar#1#2% +\permanent\protected\def\applytosplitstringchar#1#2% {\dontleavehmode\clf_processsplit data {#2}% command {\csstring#1}% method {char}% \relax} -\protected\def\applytosplitstringword#1#2% +\permanent\protected\def\applytosplitstringword#1#2% {\dontleavehmode\clf_processsplit data {#2}% command {\csstring#1}% method {word}% \relax} -\protected\def\applytosplitstringline#1#2% +\permanent\protected\def\applytosplitstringline#1#2% {\dontleavehmode\clf_processsplit data {#2}% command {\csstring#1}% method {line}% \relax} -\protected\def\applytosplitstringcharspaced#1#2% +\permanent\protected\def\applytosplitstringcharspaced#1#2% {\dontleavehmode\clf_processsplit data {#2}% command {\csstring#1}% @@ -1300,7 +1303,7 @@ spaced true% \relax} -\protected\def\applytosplitstringwordspaced#1#2% +\permanent\protected\def\applytosplitstringwordspaced#1#2% {\dontleavehmode\clf_processsplit data {#2}% command {\csstring#1}% @@ -1308,7 +1311,7 @@ spaced true% \relax} -\protected\def\applytosplitstringlinespaced#1#2% +\permanent\protected\def\applytosplitstringlinespaced#1#2% {\dontleavehmode\clf_processsplit data {#2}% command {\csstring#1}% @@ -1341,11 +1344,11 @@ %D would have ended up in the text. This macro can be useful when building %D complicated menus, headers and footers and|/|or margin material. -\protected\def\sbox +\permanent\protected\def\sbox {\vpack\bgroup \dowithnextboxcs\syst_boxes_sbox_finish\vbox} -\protected\def\syst_boxes_sbox_finish +\def\syst_boxes_sbox_finish {\boxyoffset\nextbox-\strutdp \dp\nextbox\strutdp \ht\nextbox\strutht @@ -1358,11 +1361,11 @@ %D xx \ruledhbox{\inlinedbox{\tfd test}} xx %D \stoptyping -\protected\def\inlinedbox +\permanent\protected\def\inlinedbox {\bgroup \dowithnextboxcs\syst_boxes_inlined_finish\hbox} -\protected\def\syst_boxes_inlined_finish +\def\syst_boxes_inlined_finish {\boxyoffset\nextbox-\dimexpr(\htdp\nextbox-\lineheight)/\plustwo+\strutdp\relax \ht\nextbox\strutht \dp\nextbox\strutdp @@ -1374,7 +1377,7 @@ %D %D This boxing macro limits the height and depth to those of a strut. -\protected\def\struttedbox +\permanent\protected\def\struttedbox {\hpack\bgroup \dowithnextboxcs\syst_boxes_struttedbox_finish\hbox} @@ -1390,7 +1393,7 @@ %D This macro compensates the difference between the topskip and strutheight. Watch %D how we preserve the depth when it equals strutdepth. -\protected\def\topskippedbox +\permanent\protected\def\topskippedbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_topskippedbox_finish\hbox} \def\syst_boxes_topskippedbox_finish @@ -1442,7 +1445,7 @@ %D The dimensions of the surrounding box are kept intact. This commands handles %D positive and negative dimensions (which is why we need two boxes with rules). -\protected\def\centeredbox#1#% height +/-dimen width +/-dimen +\permanent\protected\def\centeredbox#1#% height +/-dimen width +/-dimen {\bgroup \dontcomplain \forgetall @@ -1479,7 +1482,7 @@ %D %D Do you see why we call this one \type {next}? -\protected\def\centerednextbox#1#% +\permanent\protected\def\centerednextbox#1#% {\bgroup \dowithnextbox {\hsize\wd\nextbox @@ -1500,7 +1503,7 @@ %D When omitted, the current \type {\hsize} and \type {\vsize} are used. Local %D dimensions are supported. -\protected\def\centerbox#1#% optional height +/-dimen width +/-dimen +\permanent\protected\def\centerbox#1#% optional height +/-dimen width +/-dimen {\bgroup \dowithnextbox {\setlocalhsize @@ -1530,7 +1533,7 @@ \newif\ifstretchrigidcolumns \newif\iftightrigidcolumns % if true: just a vbox, no depth/noflines/gridsnap corrrections -\protected\def\setrigidcolumnhsize#1#2#3% todo: \dimexpr +\permanent\protected\def\setrigidcolumnhsize#1#2#3% todo: \dimexpr {\xdef\savedrigidhsize{\the\hsize}% \hsize#1\relax \global\chardef\rigidcolumns#3\relax @@ -1551,7 +1554,7 @@ \let\rigidcolumnlines\!!zerocount -\protected\def\rigidcolumnbalance#1% +\permanent\protected\def\rigidcolumnbalance#1% {\ifnum\rigidcolumns=1 % tzt ook h/d correctie \ifinner\ifhmode\box\else\unvbox\fi\else\unvbox\fi#1\relax \else @@ -1676,17 +1679,17 @@ %newbox\d_syst_boxes_vboxtohbox \newbox\d_syst_boxes_separator -\protected\def\startvboxtohboxseparator +\permanent\protected\def\startvboxtohboxseparator {\setbox\d_syst_boxes_separator\hbox attr \vboxtohboxseparatorattribute\plusone\bgroup} -\protected\def\stopvboxtohboxseparator +\permanent\protected\def\stopvboxtohboxseparator {\egroup} -\protected\def\startvboxtohbox +\permanent\protected\def\startvboxtohbox {\begingroup \setbox\scratchbox\hbox\bgroup} -\protected\def\stopvboxtohbox +\permanent\protected\def\stopvboxtohbox {\ifvoid\d_syst_boxes_separator \hskip\zeropoint\ifcase\vboxtohboxslack\else\s!minus\vboxtohboxslack\fi % we really need a skip \else @@ -1699,12 +1702,12 @@ % A possible reconstruction: -\protected\def\convertvboxtohbox +\permanent\protected\def\convertvboxtohbox {\makehboxofhboxes \setbox\scratchboxone\hpack{\unhbox\scratchboxone\removehboxes}% \hpack \noindent\unhbox\scratchboxone\par} -\protected\def\makehboxofhboxes +\permanent\protected\def\makehboxofhboxes {\setbox\scratchboxone\emptyhbox \loop % \doloop { .. \exitloop .. } \setbox\scratchboxtwo\lastbox @@ -1712,7 +1715,7 @@ \setbox\scratchboxone\hpack{\box\scratchboxtwo\unhbox\scratchboxone}% \repeat} -\protected\def\removehboxes +\permanent\protected\def\removehboxes {\setbox\scratchboxone\lastbox \ifhbox\scratchboxone {\removehboxes}\unhbox\scratchboxone @@ -1720,11 +1723,11 @@ % And one special for notes: -\protected\def\starthboxestohbox +\permanent\protected\def\starthboxestohbox {\bgroup \setbox\scratchbox\vbox\bgroup} -\protected\def\stophboxestohbox +\permanent\protected\def\stophboxestohbox {\egroup \clf_vboxlisttohbox\scratchbox\nextbox\dimexpr\hboxestohboxslack\relax \dontleavehmode @@ -1744,7 +1747,7 @@ \newdimen \lasthhboxwidth \newskip \hhboxindent -\protected\def\unhhbox#1\with#2% +\permanent\protected\def\unhhbox#1\with#2% {\bgroup \nopenalties \dontcomplain @@ -1770,14 +1773,14 @@ \fi}% \egroup} -\def\dohboxofvbox +\def\syst_boxes_hboxofvbox {\setbox0\vpack{\unvbox\scratchcounter\global\setbox1\lastbox}% \unhbox1 \egroup} -\protected\def\hboxofvbox +\permanent\protected\def\hboxofvbox {\bgroup - \afterassignment\dohboxofvbox + \afterassignment\syst_boxes_hboxofvbox \scratchcounter=} %D This macro can be used to break a paragraph apart and treat each line seperately, @@ -1818,7 +1821,7 @@ %D dimension of this box suggest some content, the resulting box is unboxed and %D surrounded by the first two arguments, else the third arguments is executed. -\protected\def\doifcontent#1#2#3% +\permanent\protected\def\doifcontent#1#2#3% {\dowithnextbox {\ifhbox\nextbox \ifdim\wd\nextbox>\zeropoint @@ -1861,7 +1864,7 @@ \newbox\processbox % public : this is the one where \nextbox's end up in -\protected\def\processboxes#1% +\permanent\protected\def\processboxes#1% {\bgroup \def\syst_boxes_process_indeed{#1}% #1 can be redefined halfway \setbox\processbox\emptybox @@ -1899,7 +1902,7 @@ %D %D \leavevmode\getbuffer -\def\boxisempty#1% +\permanent\def\boxisempty#1% {\ifdim\wd#1=\zeropoint \ifdim\ht#1=\zeropoint \ifdim\dp#1=\zeropoint @@ -1935,7 +1938,7 @@ \kern-\scratchwidth \hpack to \scratchwidth{\hss\box\nextbox \hss}}} -\protected\def\startoverlay +\permanent\protected\def\startoverlay {\bgroup \let\stopoverlay\egroup \processboxes\syst_boxes_overlay_process} @@ -1953,7 +1956,7 @@ %D %D returns an empty box with the dimensions of the box specified, here being zero. -\protected\def\fakebox +\permanent\protected\def\fakebox {\bgroup \afterassignment\syst_boxes_fakebox_finish\scratchcounter} @@ -1980,15 +1983,20 @@ %D \type {to 3cm}, but align to the left, middle and right. These box types can be %D used to typeset paragraphs. -\def\syst_boxes_lrc_process#1{\bgroup\forgetall\let\\\endgraf#1\let\next} +\def\syst_boxes_lrc_process#1% + {\bgroup + \forgetall + \enforced\let\\\endgraf + #1% + \let\nexttoken} -\protected\def\lbox#1#{\vbox#1\syst_boxes_lrc_process\raggedleft } -\protected\def\cbox#1#{\vbox#1\syst_boxes_lrc_process\raggedcenter} -\protected\def\rbox#1#{\vbox#1\syst_boxes_lrc_process\raggedright } +\permanent\protected\def\lbox#1#{\vbox#1\syst_boxes_lrc_process\raggedleft } +\permanent\protected\def\cbox#1#{\vbox#1\syst_boxes_lrc_process\raggedcenter} +\permanent\protected\def\rbox#1#{\vbox#1\syst_boxes_lrc_process\raggedright } -\protected\def\ltop#1#{\vtop#1\syst_boxes_lrc_process\raggedleft } -\protected\def\ctop#1#{\vtop#1\syst_boxes_lrc_process\raggedcenter} -\protected\def\rtop#1#{\vtop#1\syst_boxes_lrc_process\raggedright } +\permanent\protected\def\ltop#1#{\vtop#1\syst_boxes_lrc_process\raggedleft } +\permanent\protected\def\ctop#1#{\vtop#1\syst_boxes_lrc_process\raggedcenter} +\permanent\protected\def\rtop#1#{\vtop#1\syst_boxes_lrc_process\raggedright } %D The alternatives \type {\tbox} and \type {\bbox} can be used to properly align %D boxes, like in: @@ -2010,8 +2018,8 @@ %D %D \getbuffer -\protected\def\tbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_tbox_finish\hbox} -\protected\def\bbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_bbox_finish\hbox} +\permanent\protected\def\tbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_tbox_finish\hbox} +\permanent\protected\def\bbox{\hpack\bgroup\dowithnextboxcs\syst_boxes_bbox_finish\hbox} \def\syst_boxes_tbox_finish {\scratchheight\ht\strutbox @@ -2036,13 +2044,13 @@ %D %D A few more boxes. -\def\dodolhbox{\hpack to \hsize{\box\nextbox\hss }} -\def\dodomhbox{\hpack to \hsize{\hss\box\nextbox\hss}} -\def\dodorhbox{\hpack to \hsize{\hss\box\nextbox }} +\def\syst_boxes_lhbox{\hpack to \hsize{\box\nextbox\hss }} +\def\syst_boxes_mhbox{\hpack to \hsize{\hss\box\nextbox\hss}} +\def\syst_boxes_rhbox{\hpack to \hsize{\hss\box\nextbox }} -\protected\def\lhbox{\dowithnextboxcs\dodolhbox\hbox} -\protected\def\mhbox{\dowithnextboxcs\dodomhbox\hbox} -\protected\def\rhbox{\dowithnextboxcs\dodorhbox\hbox} +\permanent\protected\def\lhbox{\dowithnextboxcs\syst_boxes_lhbox\hbox} +\permanent\protected\def\mhbox{\dowithnextboxcs\syst_boxes_mhbox\hbox} +\permanent\protected\def\rhbox{\dowithnextboxcs\syst_boxes_rhbox\hbox} \let\lefthbox \lhbox \let\midhbox \mhbox @@ -2063,15 +2071,15 @@ \newdimen\sizeofbox -\protected\def\boxofsize#1% +\permanent\protected\def\boxofsize#1% {\bgroup \sizeofbox\zeropoint \scratchdimen\zeropoint \def\docommand {\advance\sizeofbox\scratchdimen - \futurelet\next\dodocommand}% + \futurelet\nexttoken\dodocommand}% \def\dodocommand - {\ifx\next\bgroup + {\ifx\nexttoken\bgroup \expanded{\egroup#1 to \the\sizeofbox}% \else \expandafter\afterassignment\expandafter\docommand\expandafter\scratchdimen @@ -2085,7 +2093,7 @@ % \limitvbox % \limithbox -\protected\def\limitatelines#1#2% size sentinel +\permanent\protected\def\limitatelines#1#2% size sentinel {\dowithnextbox {\scratchdimen#1\hsize \ifdim\wd\nextbox>\scratchdimen @@ -2096,7 +2104,7 @@ \unhbox\nextbox} \hbox} -\protected\def\fittoptobaselinegrid % weg hier +\permanent\protected\def\fittoptobaselinegrid % weg hier {\dowithnextbox {\bgroup \par @@ -2125,7 +2133,7 @@ \setbox\fakedboxcursor\hpack {\vrule\s!width\zeropoint\s!height\zeropoint\s!depth\zeropoint} -\protected\def\boxcursor % overloaded in core-vis +\permanent\protected\def\boxcursor % overloaded in core-vis {\iftraceboxplacement \bgroup \scratchdimen2\onepoint @@ -2142,21 +2150,21 @@ \copy\fakedboxcursor \fi} -\protected\def\placedbox +\permanent\protected\def\placedbox {\iftraceboxplacement\ruledhbox\else\hbox\fi} \newdimen\boxoffset \newdimen\boxhdisplacement \newdimen\boxvdisplacement -\protected\def\rightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbox_finish \placedbox} -\protected\def\leftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbox_finish \placedbox} -\protected\def\topbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_topbox_finish \placedbox} -\protected\def\bottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_bottombox_finish \placedbox} -\protected\def\lefttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_lefttopbox_finish \placedbox} -\protected\def\righttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_righttopbox_finish \placedbox} -\protected\def\leftbottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbottombox_finish \placedbox} -\protected\def\rightbottombox{\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbottombox_finish\placedbox} +\permanent\protected\def\rightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbox_finish \placedbox} +\permanent\protected\def\leftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbox_finish \placedbox} +\permanent\protected\def\topbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_topbox_finish \placedbox} +\permanent\protected\def\bottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_bottombox_finish \placedbox} +\permanent\protected\def\lefttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_lefttopbox_finish \placedbox} +\permanent\protected\def\righttopbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_righttopbox_finish \placedbox} +\permanent\protected\def\leftbottombox {\hpack\bgroup\dowithnextboxcs\syst_boxes_leftbottombox_finish \placedbox} +\permanent\protected\def\rightbottombox{\hpack\bgroup\dowithnextboxcs\syst_boxes_rightbottombox_finish\placedbox} \let\topleftbox \lefttopbox \let\toprightbox \righttopbox @@ -2235,10 +2243,10 @@ \box\nextbox \egroup} -\protected\def\middlebox {\hpack\bgroup\dowithnextboxcs\syst_boxes_middlebox_finish \placedbox} -\protected\def\baselinemiddlebox{\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinemiddlebox_finish\placedbox} -\protected\def\baselineleftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselineleftbox_finish \placedbox} -\protected\def\baselinerightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinerightbox_finish \placedbox} +\permanent\protected\def\middlebox {\hpack\bgroup\dowithnextboxcs\syst_boxes_middlebox_finish \placedbox} +\permanent\protected\def\baselinemiddlebox{\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinemiddlebox_finish\placedbox} +\permanent\protected\def\baselineleftbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselineleftbox_finish \placedbox} +\permanent\protected\def\baselinerightbox {\hpack\bgroup\dowithnextboxcs\syst_boxes_baselinerightbox_finish \placedbox} \def\syst_boxes_middlebox_finish {\global\boxhdisplacement-.5\wd\nextbox @@ -2281,7 +2289,7 @@ %D %D Experimental, not yet frozen: -\protected\def\lrtbbox#1#2#3#4% l r t b +\permanent\protected\def\lrtbbox#1#2#3#4% l r t b {\bgroup \dowithnextboxcontent {\advance\hsize-#1\advance\hsize-#2\relax @@ -2294,7 +2302,7 @@ %D %D See core-tbl.tex for an example of its usage: -\protected\def\toplinebox +\permanent\protected\def\toplinebox {\dowithnextboxcs\syst_boxes_toplinebox_finish\tbox} \def\syst_boxes_toplinebox_finish @@ -2333,20 +2341,20 @@ \installcorenamespace {stackbox} \installcorenamespace {stacklst} -\protected\def\setstackbox#1#2% +\permanent\protected\def\setstackbox#1#2% {\ifcsname\??stackbox#1:#2\endcsname\else \expandafter\newbox\csname\??stackbox#1:#2\endcsname \fi \global\setbox\csname\??stackbox#1:#2\endcsname\vbox} -\protected\def\initializeboxstack#1% +\permanent\protected\def\initializeboxstack#1% {\def\docommand##1{\setstackbox{#1}{##1}{}}% \ifcsname\??stacklst#1\endcsname \expandafter\processcommacommand\expandafter[\lastnamedcs]\docommand \fi \letgvalueempty{\??stacklst#1}} -\protected\def\savebox#1#2% stack name +\permanent\protected\def\savebox#1#2% stack name {% beware, \setxvalue defines the cs beforehand so we cannot use the % test inside the { } \ifcsname\??stacklst#1\endcsname @@ -2357,27 +2365,27 @@ \fi \setstackbox{#1}{#2}} -\protected\def\flushbox#1#2% unwrapped +\permanent\protected\def\flushbox#1#2% unwrapped {\ifcsname\??stackbox#1:#2\endcsname \box\lastnamedcs \else \emptybox \fi} -\protected\def\restorebox#1#2% unwrapped +\permanent\protected\def\restorebox#1#2% unwrapped {\ifcsname\??stackbox#1:#2\endcsname \copy\lastnamedcs \else \emptybox \fi} -\protected\def\foundbox#1#2% wrapped +\permanent\protected\def\foundbox#1#2% wrapped {\vpack {\ifcsname\??stackbox#1:#2\endcsname \copy\lastnamedcs \fi}} -\protected\def\doifelsebox#1#2% +\permanent\protected\def\doifelsebox#1#2% {\ifcsname\??stackbox#1:#2\endcsname \ifvoid\lastnamedcs \doubleexpandafter\secondoftwoarguments @@ -2395,7 +2403,8 @@ \installcorenamespace {boxstack} \newcount\c_syst_boxes_stack -\let \b_syst_boxes_stack\relax + +\mutable\let\b_syst_boxes_stack\relax \protected\def\syst_boxes_stack_allocate {\newbox\b_syst_boxes_stack @@ -2413,11 +2422,11 @@ {#1\setbox#2\box\csname\??boxstack\number\c_syst_boxes_stack\endcsname \global\advance\c_syst_boxes_stack\minusone} -\protected\def\localpushbox {\syst_boxes_push\relax} -\protected\def\localpopbox {\syst_boxes_pop \relax} +\permanent\protected\def\localpushbox {\syst_boxes_push\relax} +\permanent\protected\def\localpopbox {\syst_boxes_pop \relax} -\protected\def\globalpushbox{\syst_boxes_push\global} -\protected\def\globalpopbox {\syst_boxes_pop \global} +\permanent\protected\def\globalpushbox{\syst_boxes_push\global} +\permanent\protected\def\globalpopbox {\syst_boxes_pop \global} %D And here is a more modern one (not yet in i-*): %D @@ -2435,15 +2444,15 @@ %D \resetboxesincache{foo} %D \stoptyping -\protected\def\putboxincache #1#2#3{\clf_putboxincache {#1}{#2}#3\relax} -\protected\def\getboxfromcache #1#2#3{\clf_getboxfromcache {#1}{#2}#3\relax} -\protected\def\doifelseboxincache #1#2{\clf_doifelseboxincache {#1}{#2}} -\protected\def\copyboxfromcache #1#2#3{\clf_copyboxfromcache {#1}{#2}#3\relax} -\protected\def\directboxfromcache #1#2{\clf_directboxfromcache {#1}{#2}} -\protected\def\directcopyboxfromcache#1#2{\clf_directcopyboxfromcache{#1}{#2}} -\protected\def\resetboxesincache #1{\clf_resetboxesincache {#1}} +\permanent\protected\def\putboxincache #1#2#3{\clf_putboxincache {#1}{#2}#3\relax} +\permanent\protected\def\getboxfromcache #1#2#3{\clf_getboxfromcache {#1}{#2}#3\relax} +\permanent\protected\def\doifelseboxincache #1#2{\clf_doifelseboxincache {#1}{#2}} +\permanent\protected\def\copyboxfromcache #1#2#3{\clf_copyboxfromcache {#1}{#2}#3\relax} +\permanent\protected\def\directboxfromcache #1#2{\clf_directboxfromcache {#1}{#2}} +\permanent\protected\def\directcopyboxfromcache#1#2{\clf_directcopyboxfromcache{#1}{#2}} +\permanent\protected\def\resetboxesincache #1{\clf_resetboxesincache {#1}} -\protected\def\putnextboxincache#1#2% +\permanent\protected\def\putnextboxincache#1#2% {\dowithnextbox{\putboxincache{#1}{#2}\nextbox}} %D \macros @@ -2452,21 +2461,21 @@ %D While \type {\removedepth} removes the preceding depth, \type {\obeydepth} makes %D sure we have depth. Both macros leave the \type {\prevdepth} untouched. -\protected\def\removedepth +\permanent\protected\def\removedepth {\ifvmode \ifdim\prevdepth>\zeropoint \kern-\prevdepth \fi \fi} -\protected\def\obeydepth +\permanent\protected\def\obeydepth {\par % watch out for changes in math formulas \ifvmode\ifdim\prevdepth<\zeropoint\orelse\ifdim\prevdepth<\strutdp \kern\dimexpr\strutdp-\prevdepth\relax \prevdepth\strutdp \fi\fi} -\protected\def\undepthed +\permanent\protected\def\undepthed {\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\hbox} %D \macros @@ -2474,10 +2483,10 @@ %D %D A funny (but rather stupid) one, plus a redefinition. -\protected\def\removebottomthings +\permanent\protected\def\removebottomthings {\dorecurse\plusfive{\unskip\unkern\unpenalty}} -\protected\def\removelastskip % \ifvmode the plain tex one \fi +\permanent\protected\def\removelastskip % \ifvmode the plain tex one \fi, overloaded to \permanent in spac-ver {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi} %D \macros @@ -2486,7 +2495,7 @@ %D This macro sets the dimensions of a box to those of a strut. Sort of obsolete so %D it will go away. -\protected\def\makestrutofbox % not used +\permanent\protected\def\makestrutofbox % not used {\afterassignment\syst_boxes_makestrutofbox\c_boxes_register} \def\syst_boxes_makestrutofbox @@ -2505,8 +2514,8 @@ %D \hsmash{\raisebox{100pt}\hbox{test}} %D \stoptyping -\protected\def\raisebox#1{\bgroup\afterassignment\syst_boxes_raise_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted -\protected\def\lowerbox#1{\bgroup\afterassignment\syst_boxes_lower_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted +\permanent\protected\def\raisebox#1{\bgroup\afterassignment\syst_boxes_raise_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted +\permanent\protected\def\lowerbox#1{\bgroup\afterassignment\syst_boxes_lower_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted \def\syst_boxes_raise_indeed{\dowithnextboxcs\syst_boxes_raise_finish} \def\syst_boxes_lower_indeed{\dowithnextboxcs\syst_boxes_lower_finish} @@ -2527,7 +2536,7 @@ % vcenter in text, we kunnen vcenter overloaden -\protected\def\halfwaybox +\permanent\protected\def\halfwaybox {\hpack\bgroup \dowithnextboxcs\syst_boxes_halfwaybox_finish\hbox} @@ -2536,7 +2545,7 @@ \lower.5\ht\nextbox\box\nextbox \egroup} -\protected\def\depthonlybox +\permanent\protected\def\depthonlybox {\tpack\bgroup \dowithnextboxcs\syst_boxes_depthonlybox_finish\vbox} @@ -2547,8 +2556,8 @@ %D New: -\def\setdimentoatleast#1#2{\ifdim#1>\zeropoint\else#1=#2\fi} -\def\setdimentoatmost #1#2{\ifdim#1>#2\relax \else#1=#2\fi} +\permanent\def\setdimentoatleast#1#2{\ifdim#1>\zeropoint\else#1=#2\fi} +\permanent\def\setdimentoatmost #1#2{\ifdim#1>#2\relax \else#1=#2\fi} %D And even rawer: @@ -2561,7 +2570,7 @@ %D %D A not so well unhboxable box can be made with: -\protected\def\frozenhbox +\permanent\protected\def\frozenhbox {\hpack\bgroup \dowithnextboxcs\syst_boxes_frozenhbox_finish\hbox} @@ -2577,19 +2586,17 @@ \installcorenamespace {box_x} \installcorenamespace {box_y} -\protected\def\setboxllx #1#2{\expandafter\edef\csname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}} -\protected\def\setboxlly #1#2{\expandafter\edef\csname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}} +\permanent\protected\def\setboxllx #1#2{\expandafter\edef\csname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}} +\permanent\protected\def\setboxlly #1#2{\expandafter\edef\csname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}} -\protected\def\gsetboxllx#1#2{\expandafter\xdef\csname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}} -\protected\def\gsetboxlly#1#2{\expandafter\xdef\csname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}} +\permanent\protected\def\gsetboxllx#1#2{\expandafter\xdef\csname\??box_x\number#1\endcsname{\the\dimexpr#2\relax}} +\permanent\protected\def\gsetboxlly#1#2{\expandafter\xdef\csname\??box_y\number#1\endcsname{\the\dimexpr#2\relax}} -%def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\csname\??box_x\number#1\endcsname\else\zeropoint\fi} -%def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\csname\??box_y\number#1\endcsname\else\zeropoint\fi} -\def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\lastnamedcs\else\zeropoint\fi} -\def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\lastnamedcs\else\zeropoint\fi} +\permanent\def\getboxllx#1{\ifcsname\??box_x\number#1\endcsname\lastnamedcs\else\zeropoint\fi} +\permanent\def\getboxlly#1{\ifcsname\??box_y\number#1\endcsname\lastnamedcs\else\zeropoint\fi} -\def\directgetboxllx#1{\csname\??box_x\number#1\endcsname} % use when sure existence -\def\directgetboxlly#1{\csname\??box_y\number#1\endcsname} % use when sure existence +\permanent\def\directgetboxllx#1{\csname\??box_x\number#1\endcsname} % use when sure existence +\permanent\def\directgetboxlly#1{\csname\??box_y\number#1\endcsname} % use when sure existence %D \macros %D {shownextbox} @@ -2604,7 +2611,7 @@ %D \shownextbox\vbox{\setupwhitespace[big]test\endgraf\thinrule} %D \stoptyping -\protected\def\shownextbox % seldom used +\permanent\protected\def\shownextbox % seldom used {\dowithnextbox {\bgroup \showboxbreadth\maxdimen @@ -2616,7 +2623,7 @@ \interactionmode\scratchcounter \egroup}} -\protected\def\spreadhbox#1% rebuilds \hbox{<box><hss><box><hss><box>} +\permanent\protected\def\spreadhbox#1% rebuilds \hbox{<box><hss><box><hss><box>} {\bgroup \ifhbox#1\relax \setbox\scratchboxtwo\emptybox @@ -2648,7 +2655,7 @@ %D \minimalhbox 100pt {test} %D \stoptyping -\protected\def\minimalhbox#1#% +\permanent\protected\def\minimalhbox#1#% {\dowithnextbox {\bgroup \setbox\scratchbox\hpack#1{\hss}% @@ -2659,7 +2666,7 @@ %D A bit dirty: -\protected\def\nodestostring#1#2% more tolerant for #2=\cs +\permanent\protected\def\nodestostring#1#2% more tolerant for #2=\cs {\begingroup \setbox\nextbox\hbox{#2}% \normalexpanded{\endgroup\edef\noexpand#1{\clf_boxtostring\nextbox}}} @@ -2690,7 +2697,7 @@ \let\getnaturalwd\clf_getnaturalwd % no intermediate \let\setnaturalwd\clf_setnaturalwd % no intermediate -\protected\def\doifelserighttoleftinbox{\clf_doifelserighttoleftinbox} +\permanent\protected\def\doifelserighttoleftinbox{\clf_doifelserighttoleftinbox} \let\doifrighttoleftinboxelse\doifelserighttoleftinbox @@ -2698,24 +2705,23 @@ \definesystemattribute [runningtext] [public] -%unexpanded\def\runninghbox{\hbox attr \runningtextattribute \plusone} % not yet in i-* -\protected\def\runninghbox{\hbox attr \runningtextattribute \fontid\font} % not yet in i-* +\permanent\protected\def\runninghbox{\hbox attr \runningtextattribute \fontid\font} % not yet in i-* %D To complement lua (yet undocumented): -\protected\def\beginhbox{\hbox\bgroup} \let\endhbox\egroup -\protected\def\beginvbox{\vbox\bgroup} \let\endvbox\egroup -\protected\def\beginvtop{\vtop\bgroup} \let\endvtop\egroup +\permanent\protected\def\beginhbox{\hbox\bgroup} \let\endhbox\egroup +\permanent\protected\def\beginvbox{\vbox\bgroup} \let\endvbox\egroup +\permanent\protected\def\beginvtop{\vtop\bgroup} \let\endvtop\egroup -\protected\def\sethboxregister#1{\setbox#1\hbox} -\protected\def\setvboxregister#1{\setbox#1\vbox} -\protected\def\setvtopregister#1{\setbox#1\vtop} +\permanent\protected\def\sethboxregister#1{\setbox#1\hbox} +\permanent\protected\def\setvboxregister#1{\setbox#1\vbox} +\permanent\protected\def\setvtopregister#1{\setbox#1\vtop} -\protected\def\flushboxregister#1{\box\numexpr#1\relax} +\permanent\protected\def\flushboxregister#1{\box\numexpr#1\relax} -\protected\def\starthboxregister#1{\setbox#1\hbox\bgroup} \let\stophboxregister\egroup -\protected\def\startvboxregister#1{\setbox#1\vbox\bgroup} \let\stopvboxregister\egroup -\protected\def\startvtopregister#1{\setbox#1\vtop\bgroup} \let\stopvtopregister\egroup +\permanent\protected\def\starthboxregister#1{\setbox#1\hbox\bgroup} \let\stophboxregister\egroup +\permanent\protected\def\startvboxregister#1{\setbox#1\vbox\bgroup} \let\stopvboxregister\egroup +\permanent\protected\def\startvtopregister#1{\setbox#1\vtop\bgroup} \let\stopvtopregister\egroup %D For whatever third party package needs it: %D @@ -2731,7 +2737,7 @@ \installcorenamespace{localbox} -\protected\def\newlocalbox#1% +\permanent\protected\def\newlocalbox#1% {\expandafter\let\expandafter#1\csname\??localbox\string#1\endcsname \ifx#1\relax \syst_aux_new_localbox#1% @@ -2743,7 +2749,7 @@ %D Who knows when this comes in handy: -\protected\def\lastlinewidth{\dimexpr\clf_lastlinewidth\scaledpoint\relax} +\permanent\protected\def\lastlinewidth{\dimexpr\clf_lastlinewidth\scaledpoint\relax} %D Keep as reference: @@ -2753,11 +2759,11 @@ %D This one keeps dimensions and sets the shift field (and so it's more for testing %D than for real usage): -\protected\def\shiftbox {\clf_shiftbox} -\protected\def\vpackbox {\clf_vpackbox} -\protected\def\hpackbox {\clf_hpackbox} -\protected\def\vpackedbox{\clf_vpackedbox} -\protected\def\hpackedbox{\clf_hpackedbox} +\permanent\protected\def\shiftbox {\clf_shiftbox} +\permanent\protected\def\vpackbox {\clf_vpackbox} +\permanent\protected\def\hpackbox {\clf_hpackbox} +\permanent\protected\def\vpackedbox{\clf_vpackedbox} +\permanent\protected\def\hpackedbox{\clf_hpackedbox} %D This one has been moved from a 2 decade old file. It makes something boxed %D sit on the baseline. @@ -2772,7 +2778,6 @@ \egroup} \hbox} - %D \macros %D {widthuptohere} %D @@ -2784,9 +2789,9 @@ %D \stopbuffer %D %D \typebuffer \blank \getbuffer \blank - +%D %D Implemented elsewhere: - +%D %D \starttyping %D \boxlines <box> %D \boxline <box> <line> @@ -2818,6 +2823,25 @@ % % \protected\def\namedbox#1{\csname\??namedboxes#1\endcsname} +%D Implemented elsewhere: +%D +%D \startbuffer +%D \setbox0\hbox{test \footnote{test}} (\prelistbox0) (\postlistbox0) +%D \setprelistbox0\hbox{BEFORE} \setpostlistbox0\hbox{AFTER} +%D \box0 +%D \stopbuffer +%D +%D \typebuffer \blank \getbuffer \blank +%D +%D \starttyping +%D \prelistbox <box> +%D \postlistbox <box> +%D \prelistcopy <box> +%D \postlistcopy <box> +%D \setprelistbox <box> <hbox|vbox|vtop|somebox> +%D \setpostlistbox <box> <hbox|vbox|vtop|somebox> +%D \stoptyping + \protect \endinput % a bit of test code: diff --git a/tex/context/base/mkiv/supp-ran.lua b/tex/context/base/mkiv/supp-ran.lua index 03da4262f..7946370d7 100644 --- a/tex/context/base/mkiv/supp-ran.lua +++ b/tex/context/base/mkiv/supp-ran.lua @@ -53,6 +53,9 @@ end math.setrandomseedi = setrandomseedi local function getrandomnumber(min,max) + if min > max then + min, max = max, min + end last = random(min,max) if trace_details then report_system("number %s",last) diff --git a/tex/context/base/mkiv/symb-imp-cc.mkiv b/tex/context/base/mkiv/symb-imp-cc.mkiv index e753d695f..d9f596b9c 100644 --- a/tex/context/base/mkiv/symb-imp-cc.mkiv +++ b/tex/context/base/mkiv/symb-imp-cc.mkiv @@ -69,8 +69,8 @@ \unexpanded\def\creativecommons#1% {\dontleavehmode\lower.15\exheight\hbox\bgroup - \let\inbetween\relax - \processseparatedlist[#1][-]{\inbetween\let\inbetween\enspace\directsymbol{cc}}% + \overloaded\let\inbetween\relax + \processseparatedlist[#1][-]{\inbetween\overloaded\let\inbetween\enspace\directsymbol{cc}}% \egroup} \definesymbol [cc-by-sa-nc] [\creativecommons{cc-by-sa-nc}] diff --git a/tex/context/base/mkiv/syst-aux.lmt b/tex/context/base/mkiv/syst-aux.lmt new file mode 100644 index 000000000..c0de8a953 --- /dev/null +++ b/tex/context/base/mkiv/syst-aux.lmt @@ -0,0 +1,747 @@ + if not modules then modules = { } end modules ['syst-aux'] = { + version = 1.001, + comment = "companion to syst-aux.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- slower than lpeg: +-- +-- utfmatch(str,"(.?)(.*)$") +-- utf.sub(str,1,1) + +local tonumber, next, type = tonumber, next, type +local utfsub = utf.sub +local P, S, R, C, Cc, Cs, Carg, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Carg, lpeg.match +local find, formatters = string.find, string.formatters + +local context = context +local implement = interfaces.implement +local setmacro = interfaces.setmacro +local setcatcode = tex.setcatcode +local texget = tex.get +local utf8character = lpeg.patterns.utf8character +local settings_to_array = utilities.parsers.settings_to_array +local settings_to_set = utilities.parsers.settings_to_set + +local pattern = C(utf8character^-1) * C(P(1)^0) + +implement { + name = "getfirstcharacter", + arguments = "string", + actions = function(str) + local first, rest = lpegmatch(pattern,str) + setmacro("firstcharacter",first) + setmacro("remainingcharacters",rest) + end +} + +implement { + name = "thefirstcharacter", + arguments = "string", + actions = function(str) + local first, rest = lpegmatch(pattern,str) + context(first) + end +} + +implement { + name = "theremainingcharacters", + arguments = "string", + actions = function(str) + local first, rest = lpegmatch(pattern,str) + context(rest) + end +} + +local pattern = C(utf8character^-1) +local ctx_doifelse = commands.doifelse + +implement { + name = "doifelsefirstchar", + arguments = "2 strings", + actions = function(str,chr) + ctx_doifelse(lpegmatch(pattern,str) == chr) + end +} + +implement { + name = "getsubstring", + arguments = "3 strings", + actions = function(str,first,last) + context(utfsub(str,tonumber(first),tonumber(last))) + end +} + +-- function commands.addtocommalist(list,item) +-- if list == "" then +-- context(item) +-- else +-- context("%s,%s",list,item) -- using tex.print is some 10% faster +-- end +-- end +-- +-- function commands.removefromcommalist(list,item) +-- if list == "" then +-- context(item) +-- else +-- -- okay, using a proper lpeg is probably faster +-- -- we could also check for #l = 1 +-- local l = settings_to_array(list) +-- local t, n = { } +-- for i=1,#l do +-- if l[i] ~= item then +-- n = n + 1 +-- t[n] = item +-- end +-- end +-- if n == 0 then +-- context(item) +-- else +-- context(concat(list,",")) +-- end +-- end +-- end + +local pattern = (C((1-P("%"))^1) * Carg(1)) / function(n,d) + return formatters["%.0fsp"](d * tonumber(n)/100) end * P("%") * P(-1) -- .0 ? + +-- percentageof("10%",65536*10) + +implement { + name = "percentageof", + arguments = { "string", "dimen" }, + actions = function(str,dim) + context(lpegmatch(pattern,str,1,dim) or str) + end +} + +-- \gdef\setpercentdimen#1#2% +-- {#1=\ctxcommand{percentageof("#2",\number#1)}\relax} + +local space = P(" ") / "" +local spaces = P(" ")^0 / "" +local nohash = 1 - P("#") +local digit = R("09") +local double = P("##") / "#" +local single = P("#") +local sentinel = spaces * (nohash^1 / "\\%0") +local whatever = S("+-/*_^=:") + digit +local sargument = (single * digit)^1 +local dargument = (double * digit)^1 +local swhatever = (single * whatever)^1 +local dwhatever = (double * whatever)^1 + +-- different ones: + +local space = P(" ") +local spaces = space^0 + +-- see syst-aux.lua for historic variants + +local global = nil +local protected = nil +local expanded = nil +local optional = nil +local tolerant = nil +local instance = nil +local frozen = nil +local csname = nil +local rest = nil + +local function catcodes_s() + setcatcode(32,10) -- space + setcatcode(13, 5) -- endofline +end + +local function catcodes_n() + setcatcode(32, 9) -- ignore + setcatcode(13, 9) -- ignore +end + +local function oldoption(s) + if optional > 1 then + optional = optional - 1 + return s .. "#*" + else + return s + end +end + +local option = ( + P("single") * Cc(1) + + P("double") * Cc(2) + + P("triple") * Cc(3) + + P("quadruple") * Cc(4) + + P("quintuple") * Cc(5) + + P("sixtuple") + ) * (P("empty") + P("argument")) + +local pattern = ( + ( + spaces * ( + ( P("spaces") * space / catcodes_s ) + + ( P("nospaces") * space / catcodes_n ) + + ( P("global") * space / function() global = true end) + + ( P("protected") * space / function() protected = true end) + + ( P("expanded") * space / function() expanded = true end) + + ( P("tolerant") * space / function() tolerant = true end) + + ( P("instance") * space / function() instance = true end) + + ( P("frozen") * space / function() frozen = true end) + + ( P("unexpanded") * space / function() protected = true end) + + ( option * space / function(s) tolerant = true + optional = s end) + ) + )^0 + * spaces * ( C((1-S(" #["))^1) ) + * spaces * Cs( + (Cs(P("[") * dargument * P("]")) / oldoption + dwhatever)^1 * sentinel^-1 * double^-1 + + (Cs(P("[") * sargument * P("]")) / oldoption + swhatever)^1 * sentinel^-1 * single^-1 + + sentinel^-1 * (double+single)^-1 + ) +) + +local ctx_dostarttexdefinition = context.dostarttexdefinition + +local function texdefinition_one(str) + global = false + protected = false + expanded = false + optional = 0 + tolerant = false + instance = false + frozen = false + csname, rest = lpegmatch(pattern,str) + ctx_dostarttexdefinition() +end + +local function texdefinition_two() + context ( + (tolerant and [[\tolerant]] or "") .. (frozen and [[\frozen]] or "") .. (protected and [[\protected]] or "") .. (instance and [[\instance]] or "") .. + [[\expandafter]] .. (global and (expanded and [[\xdef]] or [[\gdef]]) or (expanded and [[\edef]] or [[\def]])) .. + [[\csname ]] .. csname .. [[\endcsname ]] .. + rest + ) +end + +implement { name = "texdefinition_one", actions = texdefinition_one, scope = "private", arguments = "string" } +implement { name = "texdefinition_two", actions = texdefinition_two, scope = "private" } + +do + + -- Quite probably we don't yet have characters loaded so we delay some + -- aliases. + + local _lower_, _upper_, _strip_ + + _lower_ = function(s) + if characters and characters.lower then + _lower_ = characters.lower + return _lower_(s) + end + return string.lower(s) + end + + _upper_ = function(s) + if characters and characters.upper then + _upper_ = characters.upper + return _upper_(s) + end + return string.upper(s) + end + + _strip_ = function(s) + -- or utf.strip + if string.strip then + _strip_ = string.strip + return _strip_(s) + end + return s + end + + local function lower(s) context(_lower_(s)) end + local function upper(s) context(_upper_(s)) end + local function strip(s) context(_strip_(s)) end + + implement { name = "upper", arguments = "string", actions = upper } + implement { name = "lower", arguments = "string", actions = lower } + implement { name = "strip", arguments = "string", actions = strip } + +end + +implement { + name = "converteddimen", + arguments = { "dimen", "string" }, + actions = function(dimen,unit) + context(number.todimen(dimen,unit or "pt","%0.5f")) -- no unit appended (%F) + end +} + +-- where, not really the best spot for this: + +implement { + name = "immediatemessage", + arguments = { "'message'", "string" }, + actions = logs.status +} + +implement { + name = "resettimer", + actions = function() + statistics.resettiming("whatever") + statistics.starttiming("whatever") + end +} + +implement { + name = "benchmarktimer", + actions = function() + statistics.benchmarktimer("whatever") + end +} + +implement { + name = "elapsedtime", + actions = function() + statistics.stoptiming("whatever") + context(statistics.elapsedtime("whatever")) + end +} + +implement { + name = "elapsedsteptime", + arguments = "integer", + actions = function(n) + statistics.stoptiming("whatever") + local t = statistics.elapsed("whatever")/(n > 0 and n or 1) + if t > 0 then + context("%0.9f",t) + else + context(0) + end + end +} + +local accuracy = table.setmetatableindex(function(t,k) + local v = formatters["%0." ..k .. "f"] + t[k] = v + return v +end) + +implement { + name = "rounded", + arguments = "integer", + actions = function(n,m) context(accuracy[n](m)) end +} + +-- not faster but just less tracing: + +local ctx_protected_cs = context.protected.cs -- more efficient + +local ctx_firstoftwoarguments = ctx_protected_cs.firstoftwoarguments +local ctx_secondoftwoarguments = ctx_protected_cs.secondoftwoarguments +local ctx_firstofoneargument = ctx_protected_cs.firstofoneargument +local ctx_gobbleoneargument = ctx_protected_cs.gobbleoneargument + +context.firstoftwoarguments = ctx_firstoftwoarguments +context.secondoftwoarguments = ctx_secondoftwoarguments +context.firstofoneargument = ctx_firstofoneargument +context.gobbleoneargument = ctx_gobbleoneargument + +local ctx_iftrue = context.iftrue +local ctx_iffalse = context.iffalse + +local hash = utilities.parsers.hashes.settings_to_set + +local function doifelsecommon(a,b) + if a == b then + setmacro("commalistelement",a) + if a == "" then + ctx_secondoftwoarguments() + else + ctx_firstoftwoarguments() + end + return + end + local ba = find(a,",",1,true) + local bb = find(b,",",1,true) + if ba and bb then + local ha = hash[a] + local hb = hash[b] + -- local ha = settings_to_set(a) + -- local hb = settings_to_set(b) + for k in next, ha do + if hb[k] then + setmacro("commalistelement",k) + ctx_firstoftwoarguments() + return + end + end + elseif ba then + if hash[a][b] then + -- if settings_to_set(a)[b] then + setmacro("commalistelement",b) + ctx_firstoftwoarguments() + return + end + elseif bb then + if hash[b][a] then + -- if settings_to_set(b)[a] then + setmacro("commalistelement",a) + ctx_firstoftwoarguments() + return + end + end + setmacro("commalistelement","") + ctx_secondoftwoarguments() +end + +local function doifcommon(a,b) + if a == b then + setmacro("commalistelement",a) + if a == "" then + ctx_gobbleoneargument() + else + ctx_firstofoneargument() + end + return + end + local ba = find(a,",",1,true) + local bb = find(b,",",1,true) + if ba and bb then + local ha = hash[a] + local hb = hash[b] + -- local ha = settings_to_set(a) + -- local hb = settings_to_set(b) + for k in next, ha do + if hb[k] then + setmacro("commalistelement",k) + ctx_firstofoneargument() + return + end + end + elseif ba then + if hash[a][b] then + -- if settings_to_set(a)[b] then + setmacro("commalistelement",b) + ctx_firstofoneargument() + return + end + elseif bb then + if hash[b][a] then + -- if settings_to_set(b)[a] then + setmacro("commalistelement",a) + ctx_firstofoneargument() + return + end + end + setmacro("commalistelement","") + ctx_gobbleoneargument() +end + +local function doifnotcommon(a,b) + if a == b then + setmacro("commalistelement",a) + if a == "" then + ctx_firstofoneargument() + else + ctx_gobbleoneargument() + end + return + end + local ba = find(a,",",1,true) + local bb = find(b,",",1,true) + if ba and bb then + local ha = hash[a] + local hb = hash[b] + -- local ha = settings_to_set(a) + -- local hb = settings_to_set(b) + for k in next, ha do + if hb[k] then + setmacro("commalistelement",k) + ctx_gobbleoneargument() + return + end + end + elseif ba then + if hash[a][b] then + -- if settings_to_set(a)[b] then + setmacro("commalistelement",b) + ctx_gobbleoneargument() + return + end + elseif bb then + if hash[b][a] then + -- if settings_to_set(b)[a] then + setmacro("commalistelement",a) + ctx_gobbleoneargument() + return + end + end + setmacro("commalistelement","") + ctx_firstofoneargument() +end + +-- local function hascommonargumentcondition(a,b) +-- if a == b then +-- setmacro("commalistelement",a) +-- if a == "" then +-- ctx_iffalse() +-- else +-- ctx_iftrue() +-- end +-- return +-- end +-- local ba = find(a,",",1,true) +-- local bb = find(b,",",1,true) +-- if ba and bb then +-- local ha = hash[a] +-- local hb = hash[b] +-- for k in next, ha do +-- if hb[k] then +-- setmacro("commalistelement",k) +-- ctx_iftrue() +-- return +-- end +-- end +-- elseif ba then +-- if hash[a][b] then +-- setmacro("commalistelement",b) +-- ctx_iftrue() +-- return +-- end +-- elseif bb then +-- if hash[b][a] then +-- setmacro("commalistelement",a) +-- ctx_iftrue() +-- return +-- end +-- end +-- setmacro("commalistelement","") +-- ctx_iffalse() +-- end + +local function doifelseinset(a,b) + if a == b then + setmacro("commalistelement",a) + if a == "" then + ctx_secondoftwoarguments() + else + ctx_firstoftwoarguments() + end + return + end + local bb = find(b,",",1,true) + if bb then + if hash[b][a] then + -- if settings_to_set(b)[a] then + setmacro("commalistelement",a) + ctx_firstoftwoarguments() + return + end + end + setmacro("commalistelement","") + ctx_secondoftwoarguments() +end + +local function doifinset(a,b) + if a == b then + setmacro("commalistelement",a) + if a == "" then + ctx_gobbleoneargument() + else + ctx_firstofoneargument() + end + return + end + local bb = find(b,",",1,true) + if bb then + if hash[b][a] then + -- if settings_to_set(b)[a] then + setmacro("commalistelement",a) + ctx_firstofoneargument() + return + end + end + setmacro("commalistelement","") + ctx_gobbleoneargument() +end + +local function doifnotinset(a,b) + if a == b then + setmacro("commalistelement",a) + if a == "" then + ctx_firstofoneargument() + else + ctx_gobbleoneargument() + end + return + end + local bb = find(b,",",1,true) + if bb then + if hash[b][a] then + -- if settings_to_set(b)[a] then + setmacro("commalistelement",a) + ctx_gobbleoneargument() + return + end + end + setmacro("commalistelement","") + ctx_firstofoneargument() +end + +implement { + name = "doifelsecommon", + actions = doifelsecommon, + arguments = "2 strings", +} + +implement { + name = "doifcommon", + actions = doifcommon, + arguments = "2 strings", +} + +implement { + name = "doifnotcommon", + actions = doifnotcommon, + arguments = "2 strings", +} + +-- implement { +-- name = "hascommonargumentcondition", +-- actions = hascommonargumentcondition, +-- arguments = "2 strings", +-- arguments = { "argument", "argument" }, +-- } + +implement { + name = "doifelseinset", + actions = doifelseinset, + arguments = "2 strings", +-- arguments = { "argument", "argument" }, +} + +implement { + name = "doifinset", + actions = doifinset, + arguments = "2 strings", +} + +implement { + name = "doifnotinset", + actions = doifnotinset, + arguments = "2 strings", +} + +-- done elsewhere: +-- +-- local function firstinset(a) +-- local aa = hash[a] +-- context(aa and aa[1] or a) +-- end +-- +-- implement { +-- name = "firstinset", +-- actions = firstinset, +-- arguments = "string", +-- private = false, +-- } + +-- implement { +-- name = "stringcompare", +-- arguments = "2 strings", +-- actions = function(a,b) +-- context((a == b and 0) or (a > b and 1) or -1) +-- end +-- } +-- +-- implement { +-- name = "doifelsestringafter", +-- arguments = "2 strings", +-- actions = function(a,b) +-- ctx_doifelse((a == b and 0) or (a > b and 1) or -1) +-- end +-- } +-- +-- implement { +-- name = "doifelsestringbefore", +-- arguments = "2 strings", +-- actions = function(a,b) +-- ctx_doifelse((a == b and 0) or (a < b and -1) or 1) +-- end +-- } + +-- implement { -- not faster than addtocommalist +-- name = "additemtolist", -- unique +-- arguments = "2 strings", +-- actions = function(l,s) +-- if l == "" or s == l then +-- -- s = s +-- elseif find("," .. l .. ",","," .. s .. ",") then +-- s = l +-- else +-- s = l .. "," .. s +-- end +-- context(s) +-- end +-- } + +local bp = number.dimenfactors.bp + +implement { + name = "tobigpoints", + actions = function(d) context("%.5F",bp * d) end, + arguments = "dimension", +} + +implement { + name = "towholebigpoints", + actions = function(d) context("%r",bp * d) end, + arguments = "dimension", +} + +-- for now here: + +local function getshape(s) + local t = texget(s) + local n = t and #t or 0 + context(n) + if n > 0 then + for i=1,n do + local ti = t[i] + if type(ti) == "table" then + context(" %isp %isp",ti[1],ti[2]) + else + context(" %i",ti) + end + end + end +end + +implement { + name = "getparshape", + public = true, + actions = function() getshape("parshape") end, +} +implement { + name = "getclubpenalties", + public = true, + actions = function() getshape("clubpenalties") end, +} +implement { + name = "getinterlinepenalties", + public = true, + actions = function() getshape("interlinepenalties") end, + } +implement { + name = "getdisplaywidowpenalties", + public = true, + actions = function() getshape("displaywidowpenalties") end, +} +implement { + name = "getwidowpenalties", + public = true, + actions = function() getshape("widowpenalties") end, +} diff --git a/tex/context/base/mkiv/syst-aux.lua b/tex/context/base/mkiv/syst-aux.lua index 05a070d30..859e40ead 100644 --- a/tex/context/base/mkiv/syst-aux.lua +++ b/tex/context/base/mkiv/syst-aux.lua @@ -1,4 +1,4 @@ -if not modules then modules = { } end modules ['syst-aux'] = { + if not modules then modules = { } end modules ['syst-aux'] = { version = 1.001, comment = "companion to syst-aux.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", @@ -233,12 +233,12 @@ local dargument = (double * digit)^1 -- third variant: -local global = nil -local unexpanded = nil -local expanded = nil -local optional = nil -local csname = nil -local rest = nil +local global = nil +local unexpanded = nil +local expanded = nil +local optional = nil +local csname = nil +local rest = nil local function catcodes_s() setcatcode(32,10) -- space @@ -262,13 +262,40 @@ local option = ( + P("sixtuple") ) * (P("empty") + P("argument")) +-- local pattern = ( +-- ( P("spaces") * space / catcodes_s )^0 +-- * spaces * ( P("nospaces") * space / catcodes_n )^0 +-- * spaces * ( P("global") * space * Cc(true) + Cc(false) ) +-- * spaces * ( P("unexpanded") * space * Cc(true) + Cc(false) ) +-- * spaces * ( P("expanded") * space * Cc(true) + Cc(false) ) +-- * spaces * ( C(option) * space + Cc(false) ) +-- * spaces * ( C((1-S(" #["))^1) ) +-- * spaces * Cs( +-- ( P("[") * dargument * P("]") + dargument)^1 * sentinel^-1 * double^-1 +-- + ( P("[") * sargument * P("]") + sargument)^1 * sentinel^-1 * single^-1 +-- + sentinel^-1 * (double+single)^-1 +-- ) +-- ) +-- +-- local ctx_dostarttexdefinition = context.dostarttexdefinition +-- +-- local function texdefinition_one(str) +-- global, unexpanded, expanded, optional, csname, rest = lpegmatch(pattern,str) +-- ctx_dostarttexdefinition() +-- end + local pattern = ( - ( P("spaces") * space / catcodes_s )^0 - * spaces * ( P("nospaces") * space / catcodes_n )^0 - * spaces * ( P("global") * space * Cc(true) + Cc(false) ) - * spaces * ( P("unexpanded") * space * Cc(true) + Cc(false) ) - * spaces * ( P("expanded") * space * Cc(true) + Cc(false) ) - * spaces * ( C(option) * space + Cc(false) ) + ( + spaces * ( + ( P("spaces") * space / catcodes_s ) + + ( P("nospaces") * space / catcodes_n ) + + ( P("global") * space / function() global = true end ) + + ( P("unexpanded") * space / function() unexpanded = true end ) + + ( P("protected") * space / function() unexpanded = true end ) + + ( P("expanded") * space / function() expanded = true end ) + + ( C(option) * space / function(s) optional = s end ) + ) + )^0 * spaces * ( C((1-S(" #["))^1) ) * spaces * Cs( ( P("[") * dargument * P("]") + dargument)^1 * sentinel^-1 * double^-1 @@ -280,40 +307,29 @@ local pattern = ( local ctx_dostarttexdefinition = context.dostarttexdefinition local function texdefinition_one(str) - global, unexpanded, expanded, optional, csname, rest = lpegmatch(pattern,str) + global = false + unexpanded = false + expanded = false + optional = false + csname, rest = lpegmatch(pattern,str) ctx_dostarttexdefinition() end local function texdefinition_two() if optional then context ( - [[\unexpanded\expandafter]] .. - (global and [[\xdef]] or [[\edef]]) .. - [[\csname ]] .. - csname .. - [[\endcsname{\expandafter\noexpand\expandafter\do]] .. - optional .. - [[\csname _do_]] .. - csname .. - -- [[_\endcsname}\unexpanded\expandafter]] .. - [[_\endcsname}\expandafter]] .. - (global and [[\gdef]] or [[\edef]]) .. - [[\csname _do_]] .. - csname .. - [[_\endcsname ]] .. + (unexpanded and [[\unexpanded]] or "") .. + [[\expandafter]] .. (global and [[\xdef]] or [[\edef]]) .. + [[\csname ]] .. csname .. [[\endcsname{\expandafter\noexpand\expandafter\do]] .. optional .. + [[\csname _do_]] .. csname .. [[_\endcsname}\expandafter]] .. (global and [[\gdef]] or [[\edef]]) .. + [[\csname _do_]] .. csname .. [[_\endcsname ]] .. rest ) else context ( - [[\unexpanded\expandafter]] .. - ( global and ( - expanded and [[\xdef]] or [[\gdef]] - ) or ( - expanded and [[\edef]] or [[\def]] - ) ) .. - [[\csname ]] .. - csname .. - [[\endcsname ]] .. + (unexpanded and [[\unexpanded]] or "") .. + [[\expandafter]] .. (global and (expanded and [[\xdef]] or [[\gdef]]) or (expanded and [[\edef]] or [[\def]])) .. + [[\csname ]] .. csname .. [[\endcsname ]] .. rest ) end diff --git a/tex/context/base/mkiv/syst-aux.mkiv b/tex/context/base/mkiv/syst-aux.mkiv index 2d1ae17be..29f05c9b8 100644 --- a/tex/context/base/mkiv/syst-aux.mkiv +++ b/tex/context/base/mkiv/syst-aux.mkiv @@ -56,21 +56,10 @@ \let\unexpanded\normalprotected -\ifcase\contextlmtxmode - - \def\startlmtxmode#1\stoplmtxmode{} - \let\stoplmtxmode \relax - \let\startmkivmode\relax - \let\stopmkivmode \relax - -\else - - \let\startlmtxmode\relax - \let\stoplmtxmode \relax - \def\startmkivmode#1\stopmkivmode{} - \let\stopmkivmode \relax - -\fi +\def\startlmtxmode#1\stoplmtxmode{} +\let\stoplmtxmode \relax +\let\startmkivmode\relax +\let\stopmkivmode \relax %D As we don't have namespace definers yet, we use a special one: diff --git a/tex/context/base/mkiv/syst-aux.mkxl b/tex/context/base/mkiv/syst-aux.mkxl index 95a1079e8..4f3b65ad8 100644 --- a/tex/context/base/mkiv/syst-aux.mkxl +++ b/tex/context/base/mkiv/syst-aux.mkxl @@ -11,7 +11,10 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\registerctxluafile{syst-aux}{} +%D In the process of being adapted to \LMTX\ flags so a bit of a mess now. Also +%D our playground. + +\registerctxluafile{syst-aux}{autosuffix} \registerctxluafile{syst-mac}{autosuffix} %D This file is a follow up in \type {syst-aux.mkii} and \type {syst-aux.mkiv} where @@ -46,14 +49,18 @@ %D keep the same name for a similar mechanism. So, effectively we have two ways to %D protect a macro. -\let\unexpanded\normalprotected +\pushoverloadmode + +\aliased\let\unexpanded\normalprotected + +\popoverloadmode %D We're definitely in \LMTX\ mode here. -\let\startlmtxmode\relax -\let\stoplmtxmode \relax -\def\startmkivmode#-\stopmkivmode{} -\let\stopmkivmode \relax +\aliased \let\startlmtxmode\relax +\aliased \let\stoplmtxmode \relax +\permanent\def\startmkivmode#-\stopmkivmode{} +\aliased \let\stopmkivmode \relax %D As we don't have namespace definers yet, we use a special one. Later we will %D do a better job. @@ -71,7 +78,7 @@ \fi -\protected\def\installsystemnamespace#1% maybe move this to syst-ini +\permanent\protected\def\installsystemnamespace#1% maybe move this to syst-ini {\ifcsname ??#1\endcsname \writestatus\m!system{duplicate system namespace '#1'}\wait \else @@ -144,24 +151,25 @@ %D that's the price to pay. More are defined elsewhere. Of course we later pay a %D price when they need to be expanded. -\def\v!prefix! {v!} -\def\c!prefix! {c!} -\def\s!prefix! {s!} - -\def\s!next {next} -\def\s!default {default} -\def\s!dummy {dummy} -\def\s!unknown {unknown} - -\def\s!do {do} -\def\s!dodo {dodo} - -\def\s!complex {complex} -\def\s!start {start} -\def\s!simple {simple} -\def\s!stop {stop} +% \def\v!prefix! {v!} +% \def\c!prefix! {c!} +% \def\s!prefix! {s!} +% +% \def\s!next {next} +% \def\s!default {default} +% \def\s!dummy {dummy} +% \def\s!unknown {unknown} +% +% \def\s!do {do} +% \def\s!dodo {dodo} +% +% \def\s!complex {complex} +% \def\s!simple {simple} +% +% \def\s!start{start} +% \def\s!stop {stop} -\def\s!empty {empty} +% \immutable\def\s!empty {empty} %D Sometimes we pass macros as arguments to commands that don't expand them before %D interpretation. Such commands can be enclosed with \type {\expanded}, like: @@ -178,13 +186,17 @@ \let\m_syst_helpers_expanded\empty -\protected\def\expanded#1% +\pushoverloadmode + +\permanent\protected\def\expanded#1% {\xdef\m_syst_helpers_expanded{\noexpand#1}\m_syst_helpers_expanded} -\protected\def\startexpanded#1\stopexpanded +\popoverloadmode + +\permanent\protected\def\startexpanded#1\stopexpanded {\xdef\m_syst_helpers_expanded{#1}\m_syst_helpers_expanded} -\let\stopexpanded\relax +\aliased\let\stopexpanded\relax %D Recent \TEX\ engines have a primitive \type {\expanded} and we will use that when %D possible. After all, we can make not expandable macros now. The name clash is an @@ -207,21 +219,21 @@ %D is more efficient but it probably won't be noticed. It's anyway cheaper on memory %D access. We use versions that don't even store the arguments. -\def\gobbleoneargument #-{} -\def\gobbletwoarguments #-#-{} -\def\gobblethreearguments #-#-#-{} -\def\gobblefourarguments #-#-#-#-{} -\def\gobblefivearguments #-#-#-#-{} -\def\gobblesixarguments #-#-#-#-{} -\def\gobblesevenarguments #-#-#-#-#-{} -\def\gobbleeightarguments #-#-#-#-#-#-{} -\def\gobbleninearguments #-#-#-#-#-#-#-{} - -\def\gobbleoneoptional [#-]{} -\def\gobbletwooptionals [#-][#-]{} -\def\gobblethreeoptionals[#-][#-][#-]{} -\def\gobblefouroptionals [#-][#-][#-][#-]{} -\def\gobblefiveoptionals [#-][#-][#-][#-][#-]{} +%def\gobbleoneargument #-{} +\permanent\def\gobbletwoarguments #-#-{} +\permanent\def\gobblethreearguments #-#-#-{} +\permanent\def\gobblefourarguments #-#-#-#-{} +\permanent\def\gobblefivearguments #-#-#-#-{} +\permanent\def\gobblesixarguments #-#-#-#-{} +\permanent\def\gobblesevenarguments #-#-#-#-#-{} +\permanent\def\gobbleeightarguments #-#-#-#-#-#-{} +\permanent\def\gobbleninearguments #-#-#-#-#-#-#-{} + +\permanent\def\gobbleoneoptional [#-]{} +\permanent\def\gobbletwooptionals [#-][#-]{} +\permanent\def\gobblethreeoptionals[#-][#-][#-]{} +\permanent\def\gobblefouroptionals [#-][#-][#-][#-]{} +\permanent\def\gobblefiveoptionals [#-][#-][#-][#-][#-]{} %D Reserved macros for tests: @@ -242,10 +254,10 @@ %D blank spaces but in the meantime we can use some \LUATEX\ trickery. Older versions %D use more code and can be find in the \MKIV\ and \MKII\ files. -\let\next \relax -\let\nextnext \relax % kind of obsolete -\let\nextnextnext \relax % kind of obsolete -\let\nexttoken \relax +% \mutable\let\next \relax +% \mutable\let\nextnext \relax % kind of obsolete +% \mutable\let\nextnextnext \relax % kind of obsolete +% \mutable\let\nexttoken \relax \let\m_syst_action_yes\relax \let\m_syst_action_nop\relax @@ -383,21 +395,37 @@ %D As we will see, \CONTEXT\ uses these commands many times, which is mainly due to %D its object oriented and parameter driven character. -\def\setvalue #1{\expandafter\def \csname#1\endcsname} -\def\setgvalue #1{\expandafter\gdef\csname#1\endcsname} -\def\setevalue #1{\expandafter\edef\csname#1\endcsname} -\def\setxvalue #1{\expandafter\xdef\csname#1\endcsname} +% \def\setvalue #1{\expandafter\def \csname#1\endcsname} +% \def\setgvalue #1{\expandafter\gdef\csname#1\endcsname} +% \def\setevalue #1{\expandafter\edef\csname#1\endcsname} +% \def\setxvalue #1{\expandafter\xdef\csname#1\endcsname} +% \def\getvalue #1{\csname#1\endcsname} % maybe: \begincsname#1\endcsname +% \def\letvalue #1{\expandafter\let \csname#1\endcsname} +% \def\letgvalue #1{\expandafter\glet\csname#1\endcsname} +% \def\resetvalue #1{\expandafter\let \csname#1\endcsname\empty} +% \def\undefinevalue#1{\expandafter\let \csname#1\endcsname\undefined} +% \def\ignorevalue#1#2{\expandafter\let \csname#1\endcsname\empty} + +\def\setvalue #1{\expandafter\defcsname#1\endcsname} +\def\setgvalue #1{\global\defcsname#1\endcsname} +\def\setevalue #1{\edefcsname#1\endcsname} +\def\setxvalue #1{\global\edefcsname#1\endcsname} \def\getvalue #1{\csname#1\endcsname} % maybe: \begincsname#1\endcsname -\def\letvalue #1{\expandafter\let \csname#1\endcsname} -\def\letgvalue #1{\expandafter\glet\csname#1\endcsname} -\def\resetvalue #1{\expandafter\let \csname#1\endcsname\empty} -\def\undefinevalue#1{\expandafter\let \csname#1\endcsname\undefined} -\def\ignorevalue#1#2{\expandafter\let \csname#1\endcsname\empty} - -\def\setuvalue #1{\protected\expandafter \def\csname#1\endcsname} -\def\setuevalue #1{\protected\expandafter\edef\csname#1\endcsname} -\def\setugvalue #1{\protected\expandafter\gdef\csname#1\endcsname} -\def\setuxvalue #1{\protected\expandafter\xdef\csname#1\endcsname} +\def\letvalue #1{\letcsname#1\endcsname} +\def\letgvalue #1{\global\letcsname#1\endcsname} +\def\resetvalue #1{\letcsname#1\endcsname\empty} +\def\undefinevalue#1{\letcsname#1\endcsname\undefined} +\def\ignorevalue#1#2{\letcsname#1\endcsname\empty} + +% \def\setuvalue #1{\protected\expandafter \def\csname#1\endcsname} +% \def\setuevalue #1{\protected\expandafter\edef\csname#1\endcsname} +% \def\setugvalue #1{\protected\expandafter\gdef\csname#1\endcsname} +% \def\setuxvalue #1{\protected\expandafter\xdef\csname#1\endcsname} + +\def\setuvalue #1{\protected\defcsname#1\endcsname} +\def\setuevalue #1{\protected\edefcsname#1\endcsname} +\def\setugvalue #1{\protected\global\defcsname#1\endcsname} +\def\setuxvalue #1{\protected\global\edefcsname#1\endcsname} \protected\def\getuvalue#1{\csname#1\endcsname} @@ -798,24 +826,40 @@ %D arguments state. Again it permits leaner and meaner macro definitions with a bit %D less clutter in tracing. -\protected\def\syst_helpers_process_comma_item#1,% +\let\commalistcommand\empty + +\protected\def\syst_helpers_process_comma_item#+,% {\ifarguments \expandafter\syst_helpers_process_comma_item_gobble - \or + \orelse\ifparameter#1\or \commalistcommand{#1}% \expandafter\syst_helpers_process_comma_item_next + \else + \expandafter\syst_helpers_process_comma_item_gobble \fi} \def\syst_helpers_process_comma_item_next {\expandafterspaces\syst_helpers_process_comma_item} -\protected\def\processcommalist[#1]#2% +% \protected\def\processcommalist[#1]#2% +% {\pushmacro\commalistcommand +% \def\commalistcommand{#2}% +% \expandafterspaces\syst_helpers_process_comma_item#1,\ignorearguments\ignorearguments\ignorearguments +% \popmacro\commalistcommand} + +% \protected\def\processcommacommand[#1]#2% +% {\pushmacro\commalistcommand +% \def\commalistcommand{#2}% +% \normalexpanded{\noexpand\expandafterspaces\syst_helpers_process_comma_item#1,}\ignorearguments\ignorearguments\ignorearguments +% \popmacro\commalistcommand} + +\protected\def\processcommalist[#*#+]#2% {\pushmacro\commalistcommand \def\commalistcommand{#2}% \expandafterspaces\syst_helpers_process_comma_item#1,\ignorearguments\ignorearguments\ignorearguments \popmacro\commalistcommand} -\protected\def\processcommacommand[#1]#2% +\protected\def\processcommacommand[#*#+]#2% {\pushmacro\commalistcommand \def\commalistcommand{#2}% \normalexpanded{\noexpand\expandafterspaces\syst_helpers_process_comma_item#1,}\ignorearguments\ignorearguments\ignorearguments @@ -964,7 +1008,7 @@ \let\syst_helpers_do_compare_process_action\syst_helpers_do_compare_process_action_b \fi \edef\syst_helpers_do_process_action##1{\syst_helpers_do_compare_process_action[##1][#1]}% expands #1 - \processnextcommalist\relax\relax\syst_helpers_do_process_action[} + \processnextcommalist\syst_helpers_do_process_action[} \protected\def\syst_helpers_do_compare_process_action_c[#1=>#2][#3]% {\edef\m_syst_string_one{#1}% @@ -990,10 +1034,10 @@ \fi [#1]} -\protected\def\syst_helpers_process_first_action_in_set_indeed[#1]#2[#3]% +\tolerant\protected\def\syst_helpers_process_first_action_in_set_indeed[#1]#*[#2]% {\def\syst_helpers_do_process_action##1% {\def\syst_helpers_do_do_process_action####1{\syst_helpers_do_compare_process_action_c[####1][##1]}% - \processcommalist[#3]\syst_helpers_do_do_process_action}% + \processcommalist[#2]\syst_helpers_do_do_process_action}% \normalexpanded{\processcommalist[#1]}\syst_helpers_do_process_action} \protected\def\syst_helpers_do_compare_process_action_d[#1=>#2][#3]% @@ -1011,12 +1055,12 @@ \fi \fi} -\protected\def\syst_helpers_process_all_actions_in_set_indeed[#1]#2[#3]% +\tolerant\protected\def\syst_helpers_process_all_actions_in_set_indeed[#1]#*[#2]% {\globalpushmacro\syst_process_action_in_set_all \def\syst_process_action_in_set##1% {\def\syst_process_action_in_set_one####1{\syst_helpers_do_compare_process_action_d[####1][##1]}% - \processcommalist[#3]\syst_process_action_in_set_one}% - \processcommacommand[#1]\syst_process_action_in_set + \processcommalist[#2]\syst_process_action_in_set_one}% + \processcommacommand[#1]\syst_process_action_in_set \globalpopmacro\syst_process_action_in_set_all} \protected\def\processallactionsinset[#1]% @@ -1025,18 +1069,21 @@ \expandafter\processaction \else \expandafter\syst_helpers_process_all_actions_in_set_indeed - \fi - [#1]} + \fi[#1]} %D These macros use: -\protected\def\processnextcommalist#1#2#3[#4#5]% - {#1\relax - \pushmacro\commalistcommand - \def\commalistcommand{#3}% - \expandafterspaces\syst_helpers_process_comma_item#4#5\ignorearguments\ignorearguments\ignorearguments - \popmacro\commalistcommand - #2\relax} +% \protected\def\processnextcommalist#1[#2#3]% +% {\pushmacro\commalistcommand +% \def\commalistcommand{#1}% +% \expandafterspaces\syst_helpers_process_comma_item#2#3\ignorearguments\ignorearguments\ignorearguments +% \popmacro\commalistcommand} + +\protected\def\processnextcommalist#1[#2#3]% + {\pushmacro\commalistcommand + \def\commalistcommand{#1}% + \expandafterspaces\syst_helpers_process_comma_item#2#3\ignorearguments\ignorearguments\ignorearguments + \popmacro\commalistcommand} %D \macros %D {getfirstcharacter, firstcharacter, remainingcharacters, doiffirstcharacter} @@ -1281,10 +1328,12 @@ \processcommalist[#1]\syst_helpers_do_make_raw_comma_list \edef#2{\the\scratchtoks}} -\let\rawprocesscommalist \processcommalist -\let\rawprocesscommacommand\processcommacommand +% beware: in mkiv { } were lost so it was not compatible with the non raw -%D Here is one without nesting: +\let\rawprocesscommalist \processcommalist % can go +\let\rawprocesscommacommand\processcommacommand % can go + +%D Here is one without nesting .. still needed? \protected\def\syst_helpers_process_fast_comma_item#1,% {\ifarguments @@ -1410,20 +1459,6 @@ \def\doignorevalue#1#2#3{\expandafter\let \csname#1#2\endcsname\empty} \def\docopyvalue #1#2#3{\expandafter\def \csname#1#3\endcsname{\csname#2#3\endcsname}} -%D Experiment -%D -%D \starttyping -%D \protected\def\fooA{A} \aliasmacro\FooA\fooA -%D \def\fooB{B} \aliasmacro\FooB\fooB -%D -%D \meaning\fooA\crlf \meaning\FooA\crlf -%D \meaning\fooB\crlf \meaning\FooB\crlf -%D \stoptyping - -\protected\def\aliasmacro#1#2% - {\ifprotected#2\protected\protected\fi - \def#1{#2}} - %D \macros %D {doassign,undoassign,doassignempty} %D @@ -1559,12 +1594,11 @@ \def\syst_helpers_grab_parameter_next {\expandafterspaces\syst_helpers_grab_parameter} -\protected\def\dogetparameters#1[#2]#-[#3]% +\protected\def\dogetparameters#1[#2]#*[#3]% {\def\m_syst_parameter_n{#2}% \let\m_syst_parameter_s#1% \expandafterspaces\syst_helpers_grab_parameter#3\ignorearguments\ignorearguments} - %D \macros %D {getemptyparameters} %D @@ -1575,9 +1609,9 @@ %D \getemptyparameters [label] [...=...,...=...] %D \stoptyping -\protected\def\getemptyparameters[#1]#2[#3]% +\protected\def\getemptyparameters[#1]#*[#2]% {\def\syst_helpers_get_empty_parameters##1{\doassignempty[#1][##1]}% - \processcommalist[#3]\syst_helpers_get_empty_parameters} + \processcommalist[#2]\syst_helpers_get_empty_parameters} %D We now just alias these as there is no need for a speedup. These have not been used %D for a long time in core code. @@ -1658,7 +1692,7 @@ %D By using \type {\docopyvalue} we've prepared this command for use in a %D multi||lingual environment. -\protected\def\copyparameters[#1]#-[#2]#-[#3]% +\protected\def\copyparameters[#1]#*[#2]#*[#3]% {\doifnot{#1}{#2} {\def\syst_helpers_copy_parameter{\docopyvalue{#1}{#2}}% ##1 \processcommalist[#3]\syst_helpers_copy_parameter}} @@ -1753,9 +1787,9 @@ \def\syst_helpers_get_from_comma_list_next {\expandafterspaces\syst_helpers_get_from_comma_list} -\protected\def\getfromcommalist[#1]#2[#3]% +\protected\def\getfromcommalist[#1]#*[#2]% {\let\commalistelement\empty - \commalistcounter#3\relax + \commalistcounter#2\relax \expandafterspaces\syst_helpers_get_from_comma_list#1\ignorearguments\ignorearguments} \protected\def\getfromcommacommand[#1]% @@ -1860,6 +1894,8 @@ %D We use some signals for telling the calling macros if all wanted arguments are %D indeed supplied by the user. +\newcount\nofarguments + \newif\iffirstargument \newif\ifsecondargument \newif\ifthirdargument @@ -1902,328 +1938,420 @@ \newtoks\t_syst_aux -\def\syst_helpers_single_empty_one_yes {\firstargumenttrue \the\t_syst_aux} -\def\syst_helpers_double_empty_two_yes {\secondargumenttrue \the\t_syst_aux} -\def\syst_helpers_triple_empty_three_yes {\thirdargumenttrue \the\t_syst_aux} -\def\syst_helpers_quadruple_empty_four_yes {\fourthargumenttrue \the\t_syst_aux} -\def\syst_helpers_quintuple_empty_five_yes {\fifthargumenttrue \the\t_syst_aux} -\def\syst_helpers_sixtuple_empty_six_yes {\sixthargumenttrue \the\t_syst_aux} -\def\syst_helpers_seventuple_empty_seven_yes{\seventhargumenttrue\the\t_syst_aux} - -%D Single: - -\protected\def\dosingleempty#1% - {\t_syst_aux{#1}% - \futureexpand[\syst_helpers_single_empty_one_yes\syst_helpers_single_empty_one_nop} - -\def\syst_helpers_single_empty_one_nop - {\firstargumentfalse - \the\t_syst_aux[]} - -%D Double - -\protected\def\dodoubleempty#1% - {\t_syst_aux{#1}% - \futureexpand[\syst_helpers_double_empty_one_yes\syst_helpers_double_empty_one_nop} - -\def\syst_helpers_double_empty_one_yes[#1]% - {\firstargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_double_empty_two_yes\syst_helpers_double_empty_two_nop} - -\def\syst_helpers_double_empty_one_nop - {\firstargumentfalse - \secondargumentfalse - \the\t_syst_aux[][]} - -\def\syst_helpers_double_empty_two_nop - {\secondargumentfalse - \the\t_syst_aux[]} - -% Triple - -\protected\def\dotripleempty#1% - {\t_syst_aux{#1}% - \futureexpand[\syst_helpers_triple_empty_one_yes\syst_helpers_triple_empty_one_nop} - -\def\syst_helpers_triple_empty_one_yes[#1]% - {\firstargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_triple_empty_two_yes\syst_helpers_triple_empty_two_nop} - -\def\syst_helpers_triple_empty_two_yes[#1]% - {\secondargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_triple_empty_three_yes\syst_helpers_triple_empty_three_nop} - -\def\syst_helpers_triple_empty_one_nop - {\firstargumentfalse - \secondargumentfalse - \thirdargumentfalse - \the\t_syst_aux[][][]} - -\def\syst_helpers_triple_empty_two_nop - {\secondargumentfalse - \thirdargumentfalse - \the\t_syst_aux[][]} - -\def\syst_helpers_triple_empty_three_nop - {\thirdargumentfalse - \the\t_syst_aux[]} - -%D Quadruple: - -\protected\def\doquadrupleempty#1% - {\t_syst_aux{#1}% - \futureexpand[\syst_helpers_quadruple_empty_one_yes\syst_helpers_quadruple_empty_one_nop} - -\def\syst_helpers_quadruple_empty_one_yes[#1]% - {\firstargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_quadruple_empty_two_yes\syst_helpers_quadruple_empty_two_nop} - -\def\syst_helpers_quadruple_empty_two_yes[#1]% - {\secondargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_quadruple_empty_three_yes\syst_helpers_quadruple_empty_three_nop} - -\def\syst_helpers_quadruple_empty_three_yes[#1]% - {\thirdargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_quadruple_empty_four_yes\syst_helpers_quadruple_empty_four_nop} - -\def\syst_helpers_quadruple_empty_one_nop - {\firstargumentfalse - \secondargumentfalse - \thirdargumentfalse - \fourthargumentfalse - \the\t_syst_aux[][][][]} - -\def\syst_helpers_quadruple_empty_two_nop - {\secondargumentfalse - \thirdargumentfalse - \fourthargumentfalse - \the\t_syst_aux[][][]} - -\def\syst_helpers_quadruple_empty_three_nop - {\thirdargumentfalse - \fourthargumentfalse - \the\t_syst_aux[][]} - -\def\syst_helpers_quadruple_empty_four_nop - {\fourthargumentfalse - \the\t_syst_aux[]} - -%D Quintuple: - -\protected\def\doquintupleempty#1% - {\t_syst_aux{#1}% - \futureexpand[\syst_helpers_quintuple_empty_one_yes\syst_helpers_quintuple_empty_one_nop} - -\def\syst_helpers_quintuple_empty_one_yes[#1]% - {\firstargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_quintuple_empty_two_yes\syst_helpers_quintuple_empty_two_nop} - -\def\syst_helpers_quintuple_empty_two_yes[#1]% - {\secondargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_quintuple_empty_three_yes\syst_helpers_quintuple_empty_three_nop} - -\def\syst_helpers_quintuple_empty_three_yes[#1]% - {\thirdargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_quintuple_empty_four_yes\syst_helpers_quintuple_empty_four_nop} - -\def\syst_helpers_quintuple_empty_four_yes[#1]% - {\fourthargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_quintuple_empty_five_yes\syst_helpers_quintuple_empty_five_nop} - -\def\syst_helpers_quintuple_empty_one_nop - {\firstargumentfalse - \secondargumentfalse - \thirdargumentfalse - \fourthargumentfalse - \fifthargumentfalse - \the\t_syst_aux[][][][][]} - -\def\syst_helpers_quintuple_empty_two_nop - {\secondargumentfalse - \thirdargumentfalse - \fourthargumentfalse - \fifthargumentfalse - \the\t_syst_aux[][][][]} - -\def\syst_helpers_quintuple_empty_three_nop - {\thirdargumentfalse - \fourthargumentfalse - \fifthargumentfalse - \the\t_syst_aux[][][]} - -\def\syst_helpers_quintuple_empty_four_nop - {\fourthargumentfalse - \fifthargumentfalse - \the\t_syst_aux[][]} - -\def\syst_helpers_quintuple_empty_five_nop - {\fifthargumentfalse - \the\t_syst_aux[]} - -%D Sixtuple: - -\protected\def\dosixtupleempty#1% - {\t_syst_aux{#1}% - \futureexpand[\syst_helpers_sixtuple_empty_one_yes\syst_helpers_sixtuple_empty_one_nop} - -\def\syst_helpers_sixtuple_empty_one_yes[#1]% - {\firstargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_sixtuple_empty_two_yes\syst_helpers_sixtuple_empty_two_nop} - -\def\syst_helpers_sixtuple_empty_two_yes[#1]% - {\secondargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_sixtuple_empty_three_yes\syst_helpers_sixtuple_empty_three_nop} - -\def\syst_helpers_sixtuple_empty_three_yes[#1]% - {\thirdargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_sixtuple_empty_four_yes\syst_helpers_sixtuple_empty_four_nop} - -\def\syst_helpers_sixtuple_empty_four_yes[#1]% - {\fourthargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_sixtuple_empty_five_yes\syst_helpers_sixtuple_empty_five_nop} - -\def\syst_helpers_sixtuple_empty_five_yes[#1]% - {\fifthargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_sixtuple_empty_six_yes\syst_helpers_sixtuple_empty_six_nop} - -\def\syst_helpers_sixtuple_empty_one_nop - {\firstargumentfalse - \secondargumentfalse - \thirdargumentfalse - \fourthargumentfalse - \fifthargumentfalse - \sixthargumentfalse - \the\t_syst_aux[][][][][][]} - -\def\syst_helpers_sixtuple_empty_two_nop - {\secondargumentfalse - \thirdargumentfalse - \fourthargumentfalse - \fifthargumentfalse - \sixthargumentfalse - \the\t_syst_aux[][][][][]} - -\def\syst_helpers_sixtuple_empty_three_nop - {\thirdargumentfalse - \fourthargumentfalse - \fifthargumentfalse - \sixthargumentfalse - \the\t_syst_aux[][][][]} - -\def\syst_helpers_sixtuple_empty_four_nop - {\fourthargumentfalse - \fifthargumentfalse - \sixthargumentfalse - \the\t_syst_aux[][][]} - -\def\syst_helpers_sixtuple_empty_five_nop - {\fifthargumentfalse - \sixthargumentfalse - \the\t_syst_aux[][]} - -\def\syst_helpers_sixtuple_empty_six_nop - {\sixthargumentfalse - \the\t_syst_aux[]} - -%D Seventuple: - -\protected\def\doseventupleempty#1% - {\t_syst_aux{#1}% - \futureexpand[\syst_helpers_seventuple_empty_one_yes\syst_helpers_seventuple_empty_one_nop} - -\def\syst_helpers_seventuple_empty_one_yes[#1]% - {\firstargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_seventuple_empty_two_yes\syst_helpers_seventuple_empty_two_nop} - -\def\syst_helpers_seventuple_empty_two_yes[#1]% - {\secondargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_seventuple_empty_three_yes\syst_helpers_seventuple_empty_three_nop} - -\def\syst_helpers_seventuple_empty_three_yes[#1]% - {\thirdargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_seventuple_empty_four_yes\syst_helpers_seventuple_empty_four_nop} - -\def\syst_helpers_seventuple_empty_four_yes[#1]% - {\fourthargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_seventuple_empty_five_yes\syst_helpers_seventuple_empty_five_nop} - -\def\syst_helpers_seventuple_empty_five_yes[#1]% - {\fifthargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_seventuple_empty_six_yes\syst_helpers_seventuple_empty_six_nop} - -\def\syst_helpers_seventuple_empty_six_yes[#1]% - {\sixthargumenttrue - \toksapp\t_syst_aux{[{#1}]}% - \futureexpand[\syst_helpers_seventuple_empty_seven_yes\syst_helpers_seventuple_empty_seven_nop} - -\def\syst_helpers_seventuple_empty_one_nop - {\firstargumentfalse - \secondargumentfalse - \thirdargumentfalse - \fourthargumentfalse - \fifthargumentfalse - \sixthargumentfalse - \seventhargumentfalse - \the\t_syst_aux[][][][][][][]} - -\def\syst_helpers_seventuple_empty_two_nop - {\secondargumentfalse - \thirdargumentfalse - \fourthargumentfalse - \fifthargumentfalse - \sixthargumentfalse - \seventhargumentfalse - \the\t_syst_aux[][][][][][]} - -\def\syst_helpers_seventuple_empty_three_nop - {\thirdargumentfalse - \fourthargumentfalse - \fifthargumentfalse - \sixthargumentfalse - \seventhargumentfalse - \the\t_syst_aux[][][][][]} - -\def\syst_helpers_seventuple_empty_four_nop - {\fourthargumentfalse - \fifthargumentfalse - \sixthargumentfalse - \seventhargumentfalse - \the\t_syst_aux[][][][]} - -\def\syst_helpers_seventuple_empty_five_nop - {\fifthargumentfalse - \sixthargumentfalse - \seventhargumentfalse - \the\t_syst_aux[][][]} - -\def\syst_helpers_seventuple_empty_six_nop - {\sixthargumentfalse - \seventhargumentfalse - \the\t_syst_aux[][]} - -\def\syst_helpers_seventuple_empty_seven_nop - {\seventhargumentfalse - \the\t_syst_aux[]} +% \def\syst_helpers_single_empty_one_yes {\firstargumenttrue \the\t_syst_aux} +% \def\syst_helpers_double_empty_two_yes {\secondargumenttrue \the\t_syst_aux} +% \def\syst_helpers_triple_empty_three_yes {\thirdargumenttrue \the\t_syst_aux} +% \def\syst_helpers_quadruple_empty_four_yes {\fourthargumenttrue \the\t_syst_aux} +% \def\syst_helpers_quintuple_empty_five_yes {\fifthargumenttrue \the\t_syst_aux} +% \def\syst_helpers_sixtuple_empty_six_yes {\sixthargumenttrue \the\t_syst_aux} +% \def\syst_helpers_seventuple_empty_seven_yes{\seventhargumenttrue\the\t_syst_aux} +% +% %D Single: +% +% \protected\def\dosingleempty#1% +% {\t_syst_aux{#1}% +% \futureexpand[\syst_helpers_single_empty_one_yes\syst_helpers_single_empty_one_nop} +% +% \def\syst_helpers_single_empty_one_nop +% {\firstargumentfalse +% \the\t_syst_aux[]} +% +% %D Double +% +% \protected\def\dodoubleempty#1% +% {\t_syst_aux{#1}% +% \futureexpand[\syst_helpers_double_empty_one_yes\syst_helpers_double_empty_one_nop} +% +% % \def\syst_helpers_double_empty_one_yes[#1]% +% % {\firstargumenttrue +% % \toksapp\t_syst_aux{[{#1}]}% +% % \futureexpand[\syst_helpers_double_empty_two_yes\syst_helpers_double_empty_two_nop} +% % +% % nicer is: +% +% \def\syst_helpers_double_empty_one_yes[#+]% +% {\firstargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_double_empty_two_yes\syst_helpers_double_empty_two_nop} +% +% \def\syst_helpers_double_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \the\t_syst_aux[][]} +% +% \def\syst_helpers_double_empty_two_nop +% {\secondargumentfalse +% \the\t_syst_aux[]} +% +% % Triple +% +% \protected\def\dotripleempty#1% +% {\t_syst_aux{#1}% +% \futureexpand[\syst_helpers_triple_empty_one_yes\syst_helpers_triple_empty_one_nop} +% +% \def\syst_helpers_triple_empty_one_yes[#+]% +% {\firstargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_triple_empty_two_yes\syst_helpers_triple_empty_two_nop} +% +% \def\syst_helpers_triple_empty_two_yes[#+]% +% {\secondargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_triple_empty_three_yes\syst_helpers_triple_empty_three_nop} +% +% \def\syst_helpers_triple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \the\t_syst_aux[][][]} +% +% \def\syst_helpers_triple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \the\t_syst_aux[][]} +% +% \def\syst_helpers_triple_empty_three_nop +% {\thirdargumentfalse +% \the\t_syst_aux[]} +% +% %D Quadruple: +% +% \protected\def\doquadrupleempty#1% +% {\t_syst_aux{#1}% +% \futureexpand[\syst_helpers_quadruple_empty_one_yes\syst_helpers_quadruple_empty_one_nop} +% +% \def\syst_helpers_quadruple_empty_one_yes[#+]% +% {\firstargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_quadruple_empty_two_yes\syst_helpers_quadruple_empty_two_nop} +% +% \def\syst_helpers_quadruple_empty_two_yes[#+]% +% {\secondargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_quadruple_empty_three_yes\syst_helpers_quadruple_empty_three_nop} +% +% \def\syst_helpers_quadruple_empty_three_yes[#+]% +% {\thirdargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_quadruple_empty_four_yes\syst_helpers_quadruple_empty_four_nop} +% +% \def\syst_helpers_quadruple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \the\t_syst_aux[][][][]} +% +% \def\syst_helpers_quadruple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \the\t_syst_aux[][][]} +% +% \def\syst_helpers_quadruple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \the\t_syst_aux[][]} +% +% \def\syst_helpers_quadruple_empty_four_nop +% {\fourthargumentfalse +% \the\t_syst_aux[]} +% +% %D Quintuple: +% +% \protected\def\doquintupleempty#1% +% {\t_syst_aux{#1}% +% \futureexpand[\syst_helpers_quintuple_empty_one_yes\syst_helpers_quintuple_empty_one_nop} +% +% \def\syst_helpers_quintuple_empty_one_yes[#+]% +% {\firstargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_quintuple_empty_two_yes\syst_helpers_quintuple_empty_two_nop} +% +% \def\syst_helpers_quintuple_empty_two_yes[#+]% +% {\secondargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_quintuple_empty_three_yes\syst_helpers_quintuple_empty_three_nop} +% +% \def\syst_helpers_quintuple_empty_three_yes[#+]% +% {\thirdargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_quintuple_empty_four_yes\syst_helpers_quintuple_empty_four_nop} +% +% \def\syst_helpers_quintuple_empty_four_yes[#+]% +% {\fourthargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_quintuple_empty_five_yes\syst_helpers_quintuple_empty_five_nop} +% +% \def\syst_helpers_quintuple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux[][][][][]} +% +% \def\syst_helpers_quintuple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux[][][][]} +% +% \def\syst_helpers_quintuple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux[][][]} +% +% \def\syst_helpers_quintuple_empty_four_nop +% {\fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux[][]} +% +% \def\syst_helpers_quintuple_empty_five_nop +% {\fifthargumentfalse +% \the\t_syst_aux[]} +% +% %D Sixtuple: +% +% \protected\def\dosixtupleempty#1% +% {\t_syst_aux{#1}% +% \futureexpand[\syst_helpers_sixtuple_empty_one_yes\syst_helpers_sixtuple_empty_one_nop} +% +% \def\syst_helpers_sixtuple_empty_one_yes[#+]% +% {\firstargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_sixtuple_empty_two_yes\syst_helpers_sixtuple_empty_two_nop} +% +% \def\syst_helpers_sixtuple_empty_two_yes[#+]% +% {\secondargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_sixtuple_empty_three_yes\syst_helpers_sixtuple_empty_three_nop} +% +% \def\syst_helpers_sixtuple_empty_three_yes[#+]% +% {\thirdargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_sixtuple_empty_four_yes\syst_helpers_sixtuple_empty_four_nop} +% +% \def\syst_helpers_sixtuple_empty_four_yes[#+]% +% {\fourthargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_sixtuple_empty_five_yes\syst_helpers_sixtuple_empty_five_nop} +% +% \def\syst_helpers_sixtuple_empty_five_yes[#+]% +% {\fifthargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_sixtuple_empty_six_yes\syst_helpers_sixtuple_empty_six_nop} +% +% \def\syst_helpers_sixtuple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \the\t_syst_aux[][][][][][]} +% +% \def\syst_helpers_sixtuple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \the\t_syst_aux[][][][][]} +% +% \def\syst_helpers_sixtuple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \the\t_syst_aux[][][][]} +% +% \def\syst_helpers_sixtuple_empty_four_nop +% {\fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \the\t_syst_aux[][][]} +% +% \def\syst_helpers_sixtuple_empty_five_nop +% {\fifthargumentfalse +% \sixthargumentfalse +% \the\t_syst_aux[][]} +% +% \def\syst_helpers_sixtuple_empty_six_nop +% {\sixthargumentfalse +% \the\t_syst_aux[]} +% +% %D Seventuple: +% +% \protected\def\doseventupleempty#1% +% {\t_syst_aux{#1}% +% \futureexpand[\syst_helpers_seventuple_empty_one_yes\syst_helpers_seventuple_empty_one_nop} +% +% \def\syst_helpers_seventuple_empty_one_yes[#+]% +% {\firstargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_seventuple_empty_two_yes\syst_helpers_seventuple_empty_two_nop} +% +% \def\syst_helpers_seventuple_empty_two_yes[#+]% +% {\secondargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_seventuple_empty_three_yes\syst_helpers_seventuple_empty_three_nop} +% +% \def\syst_helpers_seventuple_empty_three_yes[#+]% +% {\thirdargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_seventuple_empty_four_yes\syst_helpers_seventuple_empty_four_nop} +% +% \def\syst_helpers_seventuple_empty_four_yes[#+]% +% {\fourthargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_seventuple_empty_five_yes\syst_helpers_seventuple_empty_five_nop} +% +% \def\syst_helpers_seventuple_empty_five_yes[#+]% +% {\fifthargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_seventuple_empty_six_yes\syst_helpers_seventuple_empty_six_nop} +% +% \def\syst_helpers_seventuple_empty_six_yes[#+]% +% {\sixthargumenttrue +% \toksapp\t_syst_aux{[#1]}% +% \futureexpand[\syst_helpers_seventuple_empty_seven_yes\syst_helpers_seventuple_empty_seven_nop} +% +% \def\syst_helpers_seventuple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% \the\t_syst_aux[][][][][][][]} +% +% \def\syst_helpers_seventuple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% \the\t_syst_aux[][][][][][]} +% +% \def\syst_helpers_seventuple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% \the\t_syst_aux[][][][][]} +% +% \def\syst_helpers_seventuple_empty_four_nop +% {\fourthargumentfalse +% \fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% \the\t_syst_aux[][][][]} +% +% \def\syst_helpers_seventuple_empty_five_nop +% {\fifthargumentfalse +% \sixthargumentfalse +% \seventhargumentfalse +% \the\t_syst_aux[][][]} +% +% \def\syst_helpers_seventuple_empty_six_nop +% {\sixthargumentfalse +% \seventhargumentfalse +% \the\t_syst_aux[][]} +% +% \def\syst_helpers_seventuple_empty_seven_nop +% {\seventhargumentfalse +% \the\t_syst_aux[]} + +%tolerant\def\syst_single_empty#1\relax[#+]% +\tolerant\def\syst_single_empty#1\relax[#2]% + {\ifarguments + \or\firstargumentfalse + \or\firstargumenttrue + \fi + #1[#2]} + +%tolerant\def\syst_double_empty#1\relax[#2]#*[#3]% +\tolerant\def\syst_double_empty#1\relax[#+]#*[#+]% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse + \or\firstargumenttrue \secondargumentfalse + \or\firstargumenttrue \secondargumenttrue + \fi + #1[#2][#3]} + +%tolerant\def\syst_triple_empty#1\relax[#2]#*[#3]#*[#4]% +\tolerant\def\syst_triple_empty#1\relax[#+]#*[#+]#*[#+]% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue + \fi + #1[#2][#3][#4]} + +%tolerant\def\syst_quadruple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]% +\tolerant\def\syst_quadruple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue + \fi + #1[#2][#3][#4][#5]} + +%\tolerant\def\syst_quintuple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]#*[#6]% +\tolerant\def\syst_quintuple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]#*[#+]% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue + \fi + #1[#2][#3][#4][#5][#6]} + +%tolerant\def\syst_sixtuple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]#*[#6]#*[#7]% +\tolerant\def\syst_sixtuple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]#*[#+]#*[#+]% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse\sixthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse\sixthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumenttrue + \fi + #1[#2][#3][#4][#5][#6][#7]} + +%tolerant\def\syst_seventuple_empty#1\relax[#2]#*[#3]#*[#4]#*[#5]#*[#6]#*[#7]#*[#8]% +\tolerant\def\syst_seventuple_empty#1\relax[#+]#*[#+]#*[#+]#*[#+]#*[#+]#*[#+]#*[#+]% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse\sixthargumentfalse\seventhargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse\sixthargumentfalse\seventhargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumentfalse\seventhargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumenttrue \seventhargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue \sixthargumenttrue \seventhargumenttrue + \fi + #1[#2][#3][#4][#5][#6][#7][#8]} + +\permanent\protected\def\dosingleempty #1{\syst_single_empty #1\relax} +\permanent\protected\def\dodoubleempty #1{\syst_double_empty #1\relax} +\permanent\protected\def\dotripleempty #1{\syst_triple_empty #1\relax} +\permanent\protected\def\doquadrupleempty #1{\syst_quadruple_empty #1\relax} +\permanent\protected\def\doquintupleempty #1{\syst_quintuple_empty #1\relax} +\permanent\protected\def\dosixtupleempty #1{\syst_sixtuple_empty #1\relax} +\permanent\protected\def\doseventupleempty#1{\syst_seventuple_empty#1\relax} %D Aliases: @@ -2363,157 +2491,213 @@ %D \type {conditional} token. Okay, these macros are not called that often but it %D saves crap when tracing. -%D NB: experimental code in cont-exp.mkiv - -\protected\def\dosinglegroupempty#1% - {\t_syst_aux{#1}% - \futureexpand\bgroup\syst_helpers_single_empty_one_yes\syst_helpers_single_group_empty_one_nop} - -\def\syst_helpers_single_group_empty_one_nop - {\firstargumentfalse - \the\t_syst_aux{}} - -\protected\def\dodoublegroupempty#1% - {\t_syst_aux{#1}% - \futureexpand\bgroup\syst_helpers_group_double_empty_one_yes\syst_helpers_group_double_empty_one_nop} - -\def\syst_helpers_group_double_empty_one_yes#1% - {\firstargumenttrue - \toksapp\t_syst_aux{{#1}}% - \futureexpand\bgroup\syst_helpers_double_empty_two_yes\syst_helpers_group_double_empty_two_nop} - -\def\syst_helpers_group_double_empty_one_nop - {\firstargumentfalse - \secondargumentfalse - \the\t_syst_aux{}{}} - -\def\syst_helpers_group_double_empty_two_nop - {\secondargumentfalse - \the\t_syst_aux{}} - -\protected\def\dotriplegroupempty#1% - {\t_syst_aux{#1}% - \futureexpand\bgroup\syst_helpers_group_triple_empty_one_yes\syst_helpers_group_triple_empty_one_nop} - -\def\syst_helpers_group_triple_empty_one_yes#1% - {\firstargumenttrue - \toksapp\t_syst_aux{{#1}}% - \futureexpand\bgroup\syst_helpers_group_triple_empty_two_yes\syst_helpers_group_triple_empty_two_nop} - -\def\syst_helpers_group_triple_empty_two_yes#1% - {\secondargumenttrue - \toksapp\t_syst_aux{{#1}}% - \futureexpand\bgroup\syst_helpers_triple_empty_three_yes\syst_helpers_group_triple_empty_three_nop} - -\def\syst_helpers_group_triple_empty_one_nop - {\firstargumentfalse - \secondargumentfalse - \thirdargumentfalse - \the\t_syst_aux{}{}{}} - -\def\syst_helpers_group_triple_empty_two_nop - {\secondargumentfalse - \thirdargumentfalse - \the\t_syst_aux{}{}} - -\def\syst_helpers_group_triple_empty_three_nop - {\thirdargumentfalse - \the\t_syst_aux{}} - -\protected\def\doquadruplegroupempty#1% - {\t_syst_aux{#1}% - \futureexpand\bgroup\syst_helpers_group_quadruple_empty_one_yes\syst_helpers_group_quadruple_empty_one_nop} - -\def\syst_helpers_group_quadruple_empty_one_yes#1% - {\firstargumenttrue - \toksapp\t_syst_aux{{#1}}% - \futureexpand\bgroup\syst_helpers_group_quadruple_empty_two_yes\syst_helpers_group_quadruple_empty_two_nop} - -\def\syst_helpers_group_quadruple_empty_two_yes#1% - {\secondargumenttrue - \toksapp\t_syst_aux{{#1}}% - \futureexpand\bgroup\syst_helpers_group_quadruple_empty_three_yes\syst_helpers_group_quadruple_empty_three_nop} - -\def\syst_helpers_group_quadruple_empty_three_yes#1% - {\thirdargumenttrue - \toksapp\t_syst_aux{{#1}}% - \futureexpand\bgroup\syst_helpers_quadruple_empty_four_yes\syst_helpers_group_quadruple_empty_four_nop} - -\def\syst_helpers_group_quadruple_empty_one_nop - {\firstargumentfalse - \secondargumentfalse - \thirdargumentfalse - \fourthargumentfalse - \the\t_syst_aux{}{}{}{}} - -\def\syst_helpers_group_quadruple_empty_two_nop - {\secondargumentfalse - \thirdargumentfalse - \fourthargumentfalse - \the\t_syst_aux{}{}{}} - -\def\syst_helpers_group_quadruple_empty_three_nop - {\thirdargumentfalse - \fourthargumentfalse - \the\t_syst_aux{}{}} - -\def\syst_helpers_group_quadruple_empty_four_nop - {\fourthargumentfalse - \the\t_syst_aux{}} - -\protected\def\doquintuplegroupempty#1% - {\t_syst_aux{#1}% - \futureexpand\bgroup\syst_helpers_group_quintuple_empty_one_yes\syst_helpers_group_quintuple_empty_one_nop} - -\def\syst_helpers_group_quintuple_empty_one_yes#1% - {\firstargumenttrue - \toksapp\t_syst_aux{{#1}}% - \futureexpand\bgroup\syst_helpers_group_quintuple_empty_two_yes\syst_helpers_group_quintuple_empty_two_nop} - -\def\syst_helpers_group_quintuple_empty_two_yes#1% - {\secondargumenttrue - \toksapp\t_syst_aux{{#1}}% - \futureexpand\bgroup\syst_helpers_group_quintuple_empty_three_yes\syst_helpers_group_quintuple_empty_three_nop} - -\def\syst_helpers_group_quintuple_empty_three_yes#1% - {\thirdargumenttrue - \toksapp\t_syst_aux{{#1}}% - \futureexpand\bgroup\syst_helpers_group_quintuple_empty_four_yes\syst_helpers_group_quintuple_empty_four_nop} - -\def\syst_helpers_group_quintuple_empty_four_yes#1% - {\fourthargumenttrue - \toksapp\t_syst_aux{{#1}}% - \futureexpand\bgroup\syst_helpers_quintuple_empty_five_yes\syst_helpers_group_quintuple_empty_five_nop} - -\def\syst_helpers_group_quintuple_empty_one_nop - {\firstargumentfalse - \secondargumentfalse - \thirdargumentfalse - \fourthargumentfalse - \fifthargumentfalse - \the\t_syst_aux{}{}{}{}{}} - -\def\syst_helpers_group_quintuple_empty_two_nop - {\secondargumentfalse - \thirdargumentfalse - \fourthargumentfalse - \fifthargumentfalse - \the\t_syst_aux{}{}{}{}} - -\def\syst_helpers_group_quintuple_empty_three_nop - {\thirdargumentfalse - \fourthargumentfalse - \fifthargumentfalse - \the\t_syst_aux{}{}{}} - -\def\syst_helpers_group_quintuple_empty_four_nop - {\fourthargumentfalse - \fifthargumentfalse - \the\t_syst_aux{}{}} - -\def\syst_helpers_group_quintuple_empty_five_nop - {\fifthargumentfalse - \the\t_syst_aux{}} +% \protected\def\dosinglegroupempty#1% +% {\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_single_empty_one_yes\syst_helpers_single_group_empty_one_nop} +% +% \def\syst_helpers_single_group_empty_one_nop +% {\firstargumentfalse +% \the\t_syst_aux{}} +% +% \protected\def\dodoublegroupempty#1% +% {\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_double_empty_one_yes\syst_helpers_group_double_empty_one_nop} +% +% % \def\syst_helpers_group_double_empty_one_yes#1% +% % {\firstargumenttrue +% % \toksapp\t_syst_aux{{#1}}% +% % \futureexpand\bgroup\syst_helpers_double_empty_two_yes\syst_helpers_group_double_empty_two_nop} +% % +% % nicer is: +% +% \def\syst_helpers_group_double_empty_one_yes#+% +% {\firstargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_double_empty_two_yes\syst_helpers_group_double_empty_two_nop} +% +% \def\syst_helpers_group_double_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \the\t_syst_aux{}{}} +% +% \def\syst_helpers_group_double_empty_two_nop +% {\secondargumentfalse +% \the\t_syst_aux{}} +% +% \protected\def\dotriplegroupempty#1% +% {\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_triple_empty_one_yes\syst_helpers_group_triple_empty_one_nop} +% +% \def\syst_helpers_group_triple_empty_one_yes#+% +% {\firstargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_triple_empty_two_yes\syst_helpers_group_triple_empty_two_nop} +% +% \def\syst_helpers_group_triple_empty_two_yes#+% +% {\secondargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_triple_empty_three_yes\syst_helpers_group_triple_empty_three_nop} +% +% \def\syst_helpers_group_triple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \the\t_syst_aux{}{}{}} +% +% \def\syst_helpers_group_triple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \the\t_syst_aux{}{}} +% +% \def\syst_helpers_group_triple_empty_three_nop +% {\thirdargumentfalse +% \the\t_syst_aux{}} +% +% \protected\def\doquadruplegroupempty#1% +% {\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_quadruple_empty_one_yes\syst_helpers_group_quadruple_empty_one_nop} +% +% \def\syst_helpers_group_quadruple_empty_one_yes#+% +% {\firstargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_quadruple_empty_two_yes\syst_helpers_group_quadruple_empty_two_nop} +% +% \def\syst_helpers_group_quadruple_empty_two_yes#+% +% {\secondargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_quadruple_empty_three_yes\syst_helpers_group_quadruple_empty_three_nop} +% +% \def\syst_helpers_group_quadruple_empty_three_yes#+% +% {\thirdargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_quadruple_empty_four_yes\syst_helpers_group_quadruple_empty_four_nop} +% +% \def\syst_helpers_group_quadruple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \the\t_syst_aux{}{}{}{}} +% +% \def\syst_helpers_group_quadruple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \the\t_syst_aux{}{}{}} +% +% \def\syst_helpers_group_quadruple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \the\t_syst_aux{}{}} +% +% \def\syst_helpers_group_quadruple_empty_four_nop +% {\fourthargumentfalse +% \the\t_syst_aux{}} +% +% \protected\def\doquintuplegroupempty#1% +% {\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_one_yes\syst_helpers_group_quintuple_empty_one_nop} +% +% \def\syst_helpers_group_quintuple_empty_one_yes#+% +% {\firstargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_two_yes\syst_helpers_group_quintuple_empty_two_nop} +% +% \def\syst_helpers_group_quintuple_empty_two_yes#+% +% {\secondargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_three_yes\syst_helpers_group_quintuple_empty_three_nop} +% +% \def\syst_helpers_group_quintuple_empty_three_yes#+% +% {\thirdargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_group_quintuple_empty_four_yes\syst_helpers_group_quintuple_empty_four_nop} +% +% \def\syst_helpers_group_quintuple_empty_four_yes#+% +% {\fourthargumenttrue +% \toksapp\t_syst_aux{#1}% +% \futureexpand\bgroup\syst_helpers_quintuple_empty_five_yes\syst_helpers_group_quintuple_empty_five_nop} +% +% \def\syst_helpers_group_quintuple_empty_one_nop +% {\firstargumentfalse +% \secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux{}{}{}{}{}} +% +% \def\syst_helpers_group_quintuple_empty_two_nop +% {\secondargumentfalse +% \thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux{}{}{}{}} +% +% \def\syst_helpers_group_quintuple_empty_three_nop +% {\thirdargumentfalse +% \fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux{}{}{}} +% +% \def\syst_helpers_group_quintuple_empty_four_nop +% {\fourthargumentfalse +% \fifthargumentfalse +% \the\t_syst_aux{}{}} +% +% \def\syst_helpers_group_quintuple_empty_five_nop +% {\fifthargumentfalse +% \the\t_syst_aux{}} + +\tolerant\def\syst_single_group_empty#1\relax#_% + {\ifarguments + \or\firstargumentfalse + \or\firstargumenttrue + \fi + #1#2} + +\tolerant\def\syst_double_group_empty#1\relax#_#*#_% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse + \or\firstargumenttrue \secondargumentfalse + \or\firstargumenttrue \secondargumenttrue + \fi + #1#2#3} + +\tolerant\def\syst_triple_group_empty#1\relax#_#*#_#*#_% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue + \fi + #1#2#3#4} + +\tolerant\def\syst_quadruple_group_empty#1\relax#_#*#_#*#_#*#_% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue + \fi + #1#2#3#4#5} + +\tolerant\def\syst_quintuple_group_empty#1\relax#_#*#_#*#_#*#_#*#_% + {\ifarguments + \or\firstargumentfalse\secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumentfalse\thirdargumentfalse\fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumentfalse\fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumentfalse\fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumentfalse + \or\firstargumenttrue \secondargumenttrue \thirdargumenttrue \fourthargumenttrue \fifthargumenttrue + \fi + #1#2#3#4#5#6} + +\permanent\protected\def\dosinglegroupempty #1{\syst_single_group_empty #1\relax} +\permanent\protected\def\dodoublegroupempty #1{\syst_double_group_empty #1\relax} +\permanent\protected\def\dotriplegroupempty #1{\syst_triple_group_empty #1\relax} +\permanent\protected\def\doquadruplegroupempty #1{\syst_quadruple_group_empty #1\relax} +\permanent\protected\def\doquintuplegroupempty #1{\syst_quintuple_group_empty #1\relax} %D These macros can explictly take care of spaces, which means that the next %D definition and calls are valid: @@ -2542,41 +2726,41 @@ %D The next six macros (dedicated to Taco) can conveniently used to select %D arguments. Their names explain their functionality. -\def\firstofoneargument #1{#1} +\permanent\def\firstofoneargument #1{#1} -\def\firstoftwoarguments #1#-{#1} -\def\secondoftwoarguments #-#1{#1} +\permanent\def\firstoftwoarguments #1#-{#1} +\permanent\def\secondoftwoarguments #-#1{#1} -\def\firstofthreearguments #1#-#-{#1} -\def\secondofthreearguments #-#1#-{#1} -\def\thirdofthreearguments #-#-#1{#1} +\permanent\def\firstofthreearguments #1#-#-{#1} +\permanent\def\secondofthreearguments #-#1#-{#1} +\permanent\def\thirdofthreearguments #-#-#1{#1} -\def\firstoffourarguments #1#-#-#-{#1} -\def\secondoffourarguments #-#1#-#-{#1} -\def\thirdoffourarguments #-#-#1#-{#1} -\def\fourthoffourarguments #-#-#-#1{#1} +\permanent\def\firstoffourarguments #1#-#-#-{#1} +\permanent\def\secondoffourarguments #-#1#-#-{#1} +\permanent\def\thirdoffourarguments #-#-#1#-{#1} +\permanent\def\fourthoffourarguments #-#-#-#1{#1} -\def\firstoffivearguments #1#-#-#-#-{#1} -\def\secondoffivearguments #-#1#-#-#-{#1} -\def\thirdoffivearguments #-#-#1#-#-{#1} -\def\fourthoffivearguments #-#-#-#1#-{#1} -\def\fifthoffivearguments #-#-#-#-#1{#1} +\permanent\def\firstoffivearguments #1#-#-#-#-{#1} +\permanent\def\secondoffivearguments #-#1#-#-#-{#1} +\permanent\def\thirdoffivearguments #-#-#1#-#-{#1} +\permanent\def\fourthoffivearguments #-#-#-#1#-{#1} +\permanent\def\fifthoffivearguments #-#-#-#-#1{#1} -\def\firstofsixarguments #1#-#-#-#-#-{#1} -\def\secondofsixarguments#-#1#-#-#-#-{#1} -\def\thirdofsixarguments #-#-#1#-#-#-{#1} -\def\fourthofsixarguments#-#-#-#1#-#-{#1} -\def\fifthofsixarguments #-#-#-#-#1#-{#1} -\def\sixthofsixarguments #-#-#-#-#-#1{#1} +\permanent\def\firstofsixarguments #1#-#-#-#-#-{#1} +\permanent\def\secondofsixarguments#-#1#-#-#-#-{#1} +\permanent\def\thirdofsixarguments #-#-#1#-#-#-{#1} +\permanent\def\fourthofsixarguments#-#-#-#1#-#-{#1} +\permanent\def\fifthofsixarguments #-#-#-#-#1#-{#1} +\permanent\def\sixthofsixarguments #-#-#-#-#-#1{#1} -\protected\def\firstofoneunexpanded #1{#1} +\permanent\protected\def\firstofoneunexpanded #1{#1} -\protected\def\firstoftwounexpanded #1#-{#1} -\protected\def\secondoftwounexpanded #-#1{#1} +\permanent\protected\def\firstoftwounexpanded #1#-{#1} +\permanent\protected\def\secondoftwounexpanded #-#1{#1} -\protected\def\firstofthreeunexpanded #1#-#-{#1} -\protected\def\secondofthreeunexpanded#-#1#-{#1} -\protected\def\thirdofthreeunexpanded #-#-#1{#1} +\permanent\protected\def\firstofthreeunexpanded #1#-#-{#1} +\permanent\protected\def\secondofthreeunexpanded#-#1#-{#1} +\permanent\protected\def\thirdofthreeunexpanded #-#-#1{#1} %D \macros %D {globalletempty,letempty, @@ -2627,7 +2811,7 @@ %D string with the macro \type {\statuswidth}. \setnewconstant\statuswidth 15 -\setnewconstant\statuswrite 128 % \pluscxxviii +%setnewconstant\statuswrite 128 % \pluscxxviii \ifdefined\writestring \else @@ -2671,7 +2855,7 @@ \def\syst_helpers_grab_raw_parameter_next {\expandafterspaces\syst_helpers_grab_raw_parameter} -\protected\def\rawgetparameters#1[#2]#-[#3]% +\protected\def\rawgetparameters#1[#2]#*[#3]% {\def\m_syst_parameter_n{#2}% %\expandafterspaces\syst_helpers_grab_raw_parameter#3\ignorearguments\ignorearguments} \expandafter\expandafterspaces\expandafter\syst_helpers_grab_raw_parameter#3\ignorearguments\ignorearguments} @@ -2687,15 +2871,15 @@ %D can reset this mechanism with \type {\resetglobal}. \protected\def\resetglobal - {\let\redoglobal\relax - \let\dodoglobal\relax} + {\enforced\let\redoglobal\relax + \enforced\let\dodoglobal\relax} \resetglobal \protected\def\doglobal {\ifx\redoglobal\relax - \let\redoglobal\global - \let\dodoglobal\syst_helpers_dodo_global + \enforced\let\redoglobal\global + \enforced\let\dodoglobal\syst_helpers_dodo_global \fi} \def\syst_helpers_dodo_global @@ -2706,47 +2890,10 @@ \let\syst_helpers_redo_global\redoglobal} \def\restoreglobal - {\let\redoglobal\syst_helpers_redo_global - \let\dodoglobal\syst_helpers_dodo_global} + {\enforced\let\redoglobal\syst_helpers_redo_global + \enforced\let\dodoglobal\syst_helpers_dodo_global} -%D A very useful application of this macro is \type {\newif}, \TEX's fake boolean -%D type. Not being a primitive, \type {\global} hopelessly fails here. But a slight -%D adaption of Knuth's original macro permits: -%D -%D \starttyping -%D \doglobal\newif\iftest -%D \stoptyping -%D -%D Of course one can still say: -%D -%D \starttyping -%D \global\testtrue -%D \global\testfalse -%D \stoptyping -%D -%D Apart from the prefixes, a few more \type {\expandafters} are needed: - -% \protected\def\newif#1% uses the original plain \@if -% {\privatescratchcounter\escapechar -% \escapechar\minusone -% \expandafter\expandafter\expandafter -% \redoglobal\expandafter\expandafter\expandafter -% \edef\@if#1{true}{\let\noexpand#1\noexpand\iftrue}% -% \expandafter\expandafter\expandafter -% \redoglobal\expandafter\expandafter\expandafter -% \edef\@if#1{false}{\let\noexpand#1\noexpand\iffalse}% -% \dodoglobal\@if#1{false}% -% \escapechar\privatescratchcounter} - -\protected\def\newif#1% see syst-ini.mkiv - {\let\new_if_saved\newif - \let\newif\new_if_check - \expandafter\redoglobal\expandafter\def\csname\expandafter\newif\csstring#1true\endcsname {\let#1\iftrue }% - \expandafter\redoglobal\expandafter\def\csname\expandafter\newif\csstring#1false\endcsname{\let#1\iffalse}% - \dodoglobal\csname\expandafter\newif\csstring#1false\endcsname - \let\newif\new_if_saved} - -%D Also new: +%D Whatever: \protected\def\define#1% {\ifdefined#1% @@ -2792,13 +2939,9 @@ % % [\test] -\def\s!unexpanded{unexpanded} - \bgroup \obeylines -\glet\stoptexdefinition\relax - -\protected\gdef\starttexdefinition% +\permanent\protected\gdef\starttexdefinition% {\bgroup% \obeylines% \syst_helpers_start_tex_definition} @@ -2807,7 +2950,9 @@ {\catcode\endoflineasciicode\ignorecatcode% \clf_texdefinition_one{#1}} -\gdef\dostarttexdefinition#1\stoptexdefinition% +\aliased\glet\stoptexdefinition\relax + +\permanent\gdef\dostarttexdefinition#1\stoptexdefinition% {\egroup% \clf_texdefinition_two{#1}} @@ -2815,12 +2960,7 @@ % \protected\def\texdefinition#1{\csname\ifcsname#1\endcsname#1\else donothing\fi\endcsname} % todo: a nop cs: char 0 or some corenamespace -\protected\def\texdefinition#1{\begincsname#1\endcsname} - -% This is a first variant, more might be added: - -\protected\def\starttexcode{\unprotect} -\protected\def\stoptexcode {\protect} +\permanent\protected\def\texdefinition#1{\begincsname#1\endcsname} %D \macros %D {newcounter, @@ -3000,14 +3140,24 @@ \let\recurseaction\relax \let\recursestring\empty -\let\syst_helpers_stepwise_next\relax +% \let\syst_helpers_stepwise_next\relax + +% \protected\def\syst_helpers_stepwise_recurse#1#2#3% from to step +% {\ifnum#1>#2\relax +% \expandafter\syst_helpers_stepwise_recurse_nop +% \else +% \def\recurselevel{#1}% +% \doubleexpandafter\syst_helpers_stepwise_recurse_yes\expandafter +% \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}} \protected\def\syst_helpers_stepwise_recurse#1#2#3% from to step {\ifnum#1>#2\relax - \expandafter\syst_helpers_stepwise_recurse_nop + \expandafter\gobblefourarguments \else \def\recurselevel{#1}% - \doubleexpandafter\syst_helpers_stepwise_recurse_yes\expandafter +% \doubleexpandafter\syst_helpers_stepwise_recurse_yes\expandafter +% \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}} + \doubleexpandafter\syst_helpers_stepwise_recurse_yes \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}} \protected\def\syst_helpers_stepwise_recurse_yes @@ -3016,20 +3166,23 @@ \protected\def\syst_helpers_stepwise_reverse#1#2#3% from to step {\ifnum#1<#2\relax - \expandafter\syst_helpers_stepwise_recurse_nop +% \expandafter\syst_helpers_stepwise_recurse_nop + \expandafter\gobblefourarguments \else \def\recurselevel{#1}% \innerrecurse#1\relax \advance\innerrecurse#3\relax - \doubleexpandafter\syst_helpers_stepwise_reverse_yes\expandafter - \fi\expandafter{\the\innerrecurse}{#2}{#3}} +% \doubleexpandafter\syst_helpers_stepwise_reverse_yes\expandafter +% \fi\expandafter{\the\innerrecurse}{#2}{#3}} + \doubleexpandafter\syst_helpers_stepwise_reverse_yes + \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}} \protected\def\syst_helpers_stepwise_reverse_yes {\syst_helpers_recurse_content \syst_helpers_stepwise_reverse} -\protected\def\syst_helpers_stepwise_exit - {\syst_helpers_stepwise_recurse_nop\relax} +% \protected\def\syst_helpers_stepwise_exit +% {\syst_helpers_stepwise_recurse_nop\relax} \def\doexpandedrecurse#1#2% user macro (also was \doxprecurse) {\ifnum#1>\zerocount @@ -3112,8 +3265,8 @@ \protected\def\doloop#1% {\global\advance\outerrecurse \plusone - \globalpushmacro\recurselevel \globalpushmacro\recurseaction + \globalpushmacro\recurselevel \protected\gdef\recurseaction##1##2{#1}% \let\endofloop\syst_helpers_loop \syst_helpers_loop1}% no \plusone else \recurselevel wrong @@ -3197,32 +3350,54 @@ \globalpopmacro\recurseaction \global\advance\outerrecurse\minusone} -\protected\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 +% \protected\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 +% {\global\advance\outerrecurse \plusone +% \globalpushmacro\recurseaction +% \globalpushmacro\recurselevel +% \protected\gdef\recurseaction##1##2{#4}% +% \normalexpanded{\ifcmpnum#3\zerocount +% \ifnum#1<#2\relax\relax % so we catch \number\numexpr xx without \relax's +% \syst_helpers_stepwise_exit +% \else +% \syst_helpers_stepwise_reverse +% \fi +% \or +% \syst_helpers_stepwise_exit +% \or +% \ifnum#2<#1\relax\relax % so we catch \number\numexpr xx without \relax's +% \syst_helpers_stepwise_exit +% \else +% \syst_helpers_stepwise_recurse +% \fi +% \fi{\number#1}{\number#2}{\number#3}}% +% \globalpopmacro\recurselevel +% \globalpopmacro\recurseaction +% \global\advance\outerrecurse\minusone} + +\protected\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4 ... todo: remove unused helpers {\global\advance\outerrecurse \plusone - \globalpushmacro\recurselevel \globalpushmacro\recurseaction + \globalpushmacro\recurselevel \protected\gdef\recurseaction##1##2{#4}% \normalexpanded{\ifcmpnum#3\zerocount \ifnum#1<#2\relax\relax % so we catch \number\numexpr xx without \relax's - \syst_helpers_stepwise_exit + \doubleexpandafter\gobbletwoarguments \else - \syst_helpers_stepwise_reverse + \tripleexpandafter\syst_helpers_stepwise_reverse \fi \or - \syst_helpers_stepwise_exit - \or - \ifnum#2<#1\relax\relax % so we catch \number\numexpr xx without \relax's - \syst_helpers_stepwise_exit - \else - \syst_helpers_stepwise_recurse - \fi - \fi{\number#1}{\number#2}{\number#3}}% + \doubleexpandafter\gobbletwoarguments + \orelse\ifnum#2<#1\relax\relax % so we catch \number\numexpr xx without \relax's + \doubleexpandafter\gobbletwoarguments + \else + \doubleexpandafter\syst_helpers_stepwise_recurse + \fi\normalexpanded{{\number#1}{\number#2}{\number#3}}}% \globalpopmacro\recurselevel \globalpopmacro\recurseaction \global\advance\outerrecurse\minusone} -\protected\def\syst_helpers_stepwise_recurse_nop#0#0#0#0% - {} +% \protected\def\syst_helpers_stepwise_recurse_nop#0#0#0#0% +% {} \newcount\fastloopindex \newcount\fastloopfinal @@ -3502,7 +3677,7 @@ \fi} \protected\def\validassignment #1{\ifhastok={#1}} % can become: {\ifhastok=} as we enforce {} -\protected\def\novalidassignment#1{\ifnum\ifhastok={#1}\zerocount\else\plusone\fi=\plusone} +\protected\def\novalidassignment#1{\ifnum\ifhastok={#1}\zerocount\else\plusone\fi=\plusone} % or use unless %D In \ETEX\ we can use \type {\detokenize} and gain some speed, but in general far %D less that 1\% for \type {\convertargument} and nil for \type {\convertcommand}. @@ -4257,34 +4432,44 @@ \expandafter\gtokspre \fi#2{#1}} -\def\syst_helpers_append_toks_indeed - {\ifx\dodoglobal\relax - \expandafter\toksapp - \else - \resetglobal - \expandafter\gtoksapp - \fi\m_syst_helpers_scratch\t_syst_helpers_scratch} - -\def\syst_helpers_prepend_toks_indeed - {\ifx\dodoglobal\relax - \expandafter\tokspre - \else - \resetglobal - \expandafter\gtokspre - \fi\m_syst_helpers_scratch\t_syst_helpers_scratch} +% \def\syst_helpers_append_toks_indeed +% {\ifx\dodoglobal\relax +% \expandafter\toksapp +% \else +% \resetglobal +% \expandafter\gtoksapp +% \fi\m_syst_helpers_scratch\t_syst_helpers_scratch} +% +% \def\syst_helpers_prepend_toks_indeed +% {\ifx\dodoglobal\relax +% \expandafter\tokspre +% \else +% \resetglobal +% \expandafter\gtokspre +% \fi\m_syst_helpers_scratch\t_syst_helpers_scratch} +% +% \protected\def\appendtoksonce#1\to#2% +% {\let\m_syst_helpers_scratch#2% +% \t_syst_helpers_scratch{#1}% +% \ifhasxtoks\t_syst_helpers_scratch\m_syst_helpers_scratch\else +% \syst_helpers_append_toks_indeed +% \fi} +% +% \protected\def\prependtoksonce#1\to#2% +% {\let\m_syst_helpers_scratch#2% +% \t_syst_helpers_scratch{#1}% +% \ifhasxtoks\t_syst_helpers_scratch\m_syst_helpers_scratch\else +% \syst_helpers_prepend_toks_indeed +% \fi} \protected\def\appendtoksonce#1\to#2% - {\let\m_syst_helpers_scratch#2% - \t_syst_helpers_scratch{#1}% - \ifhasxtoks\t_syst_helpers_scratch\m_syst_helpers_scratch\else - \syst_helpers_append_toks_indeed + {\ifhasxtoks{#1}#2\else + \appendtoks#1\to#2% \fi} \protected\def\prependtoksonce#1\to#2% - {\let\m_syst_helpers_scratch#2% - \t_syst_helpers_scratch{#1}% - \ifhasxtoks\t_syst_helpers_scratch\m_syst_helpers_scratch\else - \syst_helpers_prepend_toks_indeed + {\ifhasxtoks{#1}{#2}\m_syst_helpers_scratch\else + \prependtoks#1\to#2% \fi} %D The test macro: @@ -4681,7 +4866,7 @@ \let\newcommalistelement\empty -\def\syst_helpers_replace_in_comma_list_step#1% +\def\syst_helpers_replace_in_comma_list_step#1% we can use #+ here too {\ifnum\commalistcounter=\c_syst_helpers_comma_list_index\relax \ifempty\newcommalistelement\else \ifempty\m_syst_helpers_comma_list_target @@ -4803,16 +4988,26 @@ \newcount\c_syst_helpers_swapped \let \m_syst_helpers_swapped\relax -\protected\def\swapdimens#1#2{\d_syst_helpers_swapped#1#1#2#2\d_syst_helpers_swapped} -\protected\def\swapskips #1#2{\s_syst_helpers_swapped#1#1#2#2\s_syst_helpers_swapped} -\protected\def\swapcounts#1#2{\c_syst_helpers_swapped#1#1#2#2\c_syst_helpers_swapped} -\protected\def\swapmacros#1#2{\let\m_syst_helpers_swapped#1\let#1#2\let#2\m_syst_helpers_swapped} +% \protected\def\swapdimens#1#2{\d_syst_helpers_swapped#1#1#2#2\d_syst_helpers_swapped} +% \protected\def\swapskips #1#2{\s_syst_helpers_swapped#1#1#2#2\s_syst_helpers_swapped} +% \protected\def\swapcounts#1#2{\c_syst_helpers_swapped#1#1#2#2\c_syst_helpers_swapped} +% \protected\def\swapmacros#1#2{\let\m_syst_helpers_swapped#1\let#1#2\let#2\m_syst_helpers_swapped} + +\aliased\let\swapdimens\swapcsvalues +\aliased\let\swapskips \swapcsvalues +\aliased\let\swapcounts\swapcsvalues +\aliased\let\swapmacros\swapcsvalues \protected\def\globalswapdimens#1#2{\d_syst_helpers_swapped#1\global#1#2\global#2\d_syst_helpers_swapped} \protected\def\globalswapskips #1#2{\s_syst_helpers_swapped#1\global#1#2\global#2\s_syst_helpers_swapped} \protected\def\globalswapcounts#1#2{\c_syst_helpers_swapped#1\global#1#2\global#2\c_syst_helpers_swapped} \protected\def\globalswapmacros#1#2{\let\m_syst_helpers_swapped#1\glet#1#2\glet#2\m_syst_helpers_swapped} +\protected\def\globalswapdimens{\global\swapcsvalues} +\protected\def\globalswapskips {\global\swapcsvalues} +\protected\def\globalswapcounts{\global\swapcsvalues} +\protected\def\globalswapmacros{\global\swapcsvalues} + %D \macros %D {pushmacro,popmacro} %D @@ -5084,24 +5279,39 @@ %D \definesomething[alfa,beta,...][variable=...,...] %D \stoptyping -\let\m_syst_helpers_with_set_command\empty -\let\syst_helpers_with_set_step \relax - -\def\syst_helpers_with_set_double[#1][#2]% - {\doifsomething{#1}% - {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2]}% +%% \let\syst_helpers_with_set_step\relax +%% \let\m_syst_helpers_with_set_command\empty +%% +%% \def\syst_helpers_with_set_double[#1][#2]% +%% {\doifsomething{#1}% +%% {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2]}% +%% \processcommalist[#1]\syst_helpers_with_set_step}} +%% +%% \def\syst_helpers_with_set_triple[#1][#2][#3]% +%% {\doifsomething{#1}% +%% {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2][#3]}% +%% \processcommalist[#1]\syst_helpers_with_set_step}} +%% +%% \def\dodoubleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dodoubleempty \syst_helpers_with_set_double} % \command +%% \def\dodoubleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dodoubleargument\syst_helpers_with_set_double} % \command +%% +%% \def\dotripleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dotripleempty \syst_helpers_with_set_triple} % \command +%% \def\dotripleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dotripleargument\syst_helpers_with_set_triple} % \command + +\let\syst_helpers_with_set_step\relax % maybe push pop + +\permanent\tolerant\protected\def\dodoubleemptywithset#1#*[#2]#*[#3]% + {\doifsomething{#2}% + {\def\syst_helpers_with_set_step##1{#1[##1][#3]}% \processcommalist[#1]\syst_helpers_with_set_step}} -\def\syst_helpers_with_set_triple[#1][#2][#3]% - {\doifsomething{#1}% - {\def\syst_helpers_with_set_step##1{\m_syst_helpers_with_set_command[##1][#2][#3]}% +\permanent\tolerant\protected\def\dotripleemptywithset#1#*[#2]#*[#3]#*[#4]% + {\doifsomething{#2}% + {\def\syst_helpers_with_set_step##1{#1[##1][#3][#4]}% \processcommalist[#1]\syst_helpers_with_set_step}} -\def\dodoubleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dodoubleempty \syst_helpers_with_set_double} % \command -\def\dodoubleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dodoubleargument\syst_helpers_with_set_double} % \command - -\def\dotripleemptywithset #1{\let\m_syst_helpers_with_set_command#1\dotripleempty \syst_helpers_with_set_triple} % \command -\def\dotripleargumentwithset#1{\let\m_syst_helpers_with_set_command#1\dotripleargument\syst_helpers_with_set_triple} % \command +\let\dodoubleargumentwithset\dodoubleemptywithset +\let\dotripleargumentwithset\dotripleemptywithset %D \macros %D {stripcharacters,stripspaces} @@ -5243,20 +5453,35 @@ \let\syst_helpers_process_separated_list_step\relax -\def\syst_helpers_process_separated_list#1]#2[#3]#4% - {\def\syst_helpers_process_separated_list_step##1##2#3% +% \def\syst_helpers_process_separated_list#1]#*[#2]#3% +% {\def\syst_helpers_process_separated_list_step##1##2#2% +% {\def\m_syst_string_one{##2}% suggested by VZ +% \if]##1% +% \let\syst_helpers_process_separated_list_step\relax +% \orelse\ifx\blankspace\m_syst_string_one +% #3{##1}% +% \orelse\if]##2% +% \let\syst_helpers_process_separated_list_step\relax +% \else +% #3{##1##2}% +% \fi +% \syst_helpers_process_separated_list_step}% +% \expandafter\syst_helpers_process_separated_list_step\gobbleoneargument#1#2]#2} + +\def\syst_helpers_process_separated_list#1]#*[#2]#3% + {\def\syst_helpers_process_separated_list_step##1##2#2% {\def\m_syst_string_one{##2}% suggested by VZ \if]##1% - \let\syst_helpers_process_separated_list_step\relax \orelse\ifx\blankspace\m_syst_string_one - #4{##1}% + #3{##1}% + \expandafter\syst_helpers_process_separated_list_step \orelse\if]##2% - \let\syst_helpers_process_separated_list_step\relax \else - #4{##1##2}% + #3{##1##2}% + \expandafter\syst_helpers_process_separated_list_step \fi - \syst_helpers_process_separated_list_step}% - \expandafter\syst_helpers_process_separated_list_step\gobbleoneargument#1#3]#3} + }% + \expandafter\syst_helpers_process_separated_list_step\gobbleoneargument#1#2]#2} \protected\def\processseparatedlist[% {\syst_helpers_process_separated_list\relax} @@ -5655,11 +5880,8 @@ %D %D These two macros savely grab and dispose two arguments. -\def\dogobblesingleempty{\dosingleempty\syst_helpers_gobble_single_empty} -\def\dogobbledoubleempty{\dodoubleempty\syst_helpers_gobble_double_empty} - -\def\syst_helpers_gobble_single_empty [#1]{} -\def\syst_helpers_gobble_double_empty[#1][#2]{} +\tolerant\protected\def\dogobblesingleempty [#-]{} +\tolerant\protected\def\dogobbledoubleempty[#-]#*[#-]{} \let\gobblesingleempty\dogobblesingleempty % also used \let\gobbledoubleempty\dogobbledoubleempty % also used @@ -5872,29 +6094,16 @@ \installsystemnamespace{measure} -\protected\def\definemeasure - {\dodoubleargument\syst_helpers_define_measure} - -\def\syst_helpers_define_measure[#1][#2]% - {\expandafter\def\csname\??measure#1\endcsname{#2}} - -\protected\def\freezemeasure - {\dodoubleargument\syst_helpers_freeze_measure} - -\def\syst_helpers_freeze_measure[#1][#2]% - {\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}} +\permanent\tolerant\protected\def\definemeasure[#1]#*[#2]{\expandafter \def\csname\??measure#1\endcsname{#2}} +\permanent\tolerant\protected\def\freezemeasure[#1]#*[#2]{\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}} -\protected\def\setmeasure #1#2{\expandafter\def \csname\??measure#1\endcsname{#2}} % quick way -\protected\def\setgmeasure#1#2{\expandafter\gdef\csname\??measure#1\endcsname{#2}} % quick way -\protected\def\setemeasure#1#2{\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way -\protected\def\setxmeasure#1#2{\expandafter\xdef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way +\permanent\protected\def\setmeasure #1#2{\expandafter\def \csname\??measure#1\endcsname{#2}} % quick way +\permanent\protected\def\setgmeasure#1#2{\expandafter\gdef\csname\??measure#1\endcsname{#2}} % quick way +\permanent\protected\def\setemeasure#1#2{\expandafter\edef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way +\permanent\protected\def\setxmeasure#1#2{\expandafter\xdef\csname\??measure#1\endcsname{\the\dimexpr#2}} % quick way -\def\measure - {\the\measured} - -\def\measured#1% - %{\dimexpr\ifcsname\??measure#1\endcsname\csname\??measure#1\endcsname\else\zeropoint\fi\relax} - {\dimexpr\ifcsname\??measure#1\endcsname\lastnamedcs\else\zeropoint\fi\relax} +\permanent\def\measure {\the\measured} +\permanent\def\measured#1{\dimexpr\ifcsname\??measure#1\endcsname\lastnamedcs\else\zeropoint\fi\relax} % #2 could be omitted, but we want to support spaces % @@ -5909,31 +6118,17 @@ \installsystemnamespace{quantity} -\protected\def\definequantity - {\dodoubleargument\syst_helpers_define_quantity} - -\def\syst_helpers_define_quantity[#1][#2]% - {\expandafter\def\csname\??quantity#1\endcsname{#2}} - -\protected\def\freezequantity - {\dodoubleargument\syst_helpers_freeze_quantity} - -\def\syst_helpers_freeze_quantity[#1][#2]% - {\expandafter\edef\csname\??quantity#1\endcsname{\the\numexpr#2}} +\permanent\tolerant\protected\def\definequantity[#1]#*[#2]{\expandafter\def \csname\??quantity#1\endcsname{#2}} +\permanent\tolerant\protected\def\freezequantity[#1]#*[#2]{\expandafter\edef\csname\??quantity#1\endcsname{\the\numexpr#2}} -\protected\def\setquantity #1#2{\expandafter\def \csname\??quantity#1\endcsname{#2}} % quick way -\protected\def\setgquantity#1#2{\expandafter\gdef\csname\??quantity#1\endcsname{#2}} % quick way -\protected\def\setequantity#1#2{\expandafter\edef\csname\??quantity#1\endcsname{\the\numexpr#2}} % quick way -\protected\def\setxquantity#1#2{\expandafter\xdef\csname\??quantity#1\endcsname{\the\numexpr#2}} % quick way +\permanent\protected\def\setquantity #1#2{\expandafter\def \csname\??quantity#1\endcsname{#2}} % quick way +\permanent\protected\def\setgquantity#1#2{\expandafter\gdef\csname\??quantity#1\endcsname{#2}} % quick way +\permanent\protected\def\setequantity#1#2{\expandafter\edef\csname\??quantity#1\endcsname{\the\numexpr#2}} % quick way +\permanent\protected\def\setxquantity#1#2{\expandafter\xdef\csname\??quantity#1\endcsname{\the\numexpr#2}} % quick way -\def\quantity - {\the\quantitied} - -\def\quantitied#1% - {\numexpr\ifcsname\??quantity#1\endcsname\lastnamedcs\else\zeropoint\fi\relax} - -\def\directquantity#1% - {\the\numexpr#1\relax} +\permanent\def\quantity {\the\quantitied} +\permanent\def\quantitied #1{\numexpr\ifcsname\??quantity#1\endcsname\lastnamedcs\else\zeropoint\fi\relax} +\permanent\def\directquantity#1{\the\numexpr#1\relax} % let\quantified\quantitied @@ -5946,7 +6141,7 @@ %D \definemeasure[columnwidth][\dividedsize\textwidth{1em}{3}] %D \stoptyping -\def\dividedsize#1#2#3% size gap n +\permanent\def\dividedsize#1#2#3% size gap n {\dimexpr \ifnum\dimexpr#1\relax>\plusone (\dimexpr#1\relax-\numexpr#3-\plusone\relax\dimexpr#2\relax)/#3\else#1% @@ -5958,14 +6153,14 @@ %D %D This is a dirty one: we simply append a unit and discard it when needed. -\def\doifelsedimension#1% +\permanent\def\doifelsedimension#1% {\ifchkdim#1\or \expandafter\firstoftwoarguments \else \expandafter\secondoftwoarguments \fi} -\let\doifdimensionelse\doifelsedimension +\aliased\let\doifdimensionelse\doifelsedimension %D Ok, here's another one, slower but seldom used. This one scans the text. %D @@ -5984,18 +6179,18 @@ %D \NC 1 \NC \doifdimenstringelse {1}{yes}{no} \NC \NR %D \stoptabulate -\let\doifelsedimenstring\doifelsedimension -\let\doifdimenstringelse\doifelsedimenstring +\aliased\let\doifelsedimenstring\doifelsedimension +\aliased\let\doifdimenstringelse\doifelsedimenstring %D \macros %D {comparedimension,comparedimensioneps} %D -%D This is a dirty one: we simply append a unit and discard it when needed. +%D We no longer use the \MKIV\ dirty trick. These are obsolete anyway. \newdimen \roundingeps \roundingeps=10sp \newconstant\compresult -\def\comparedimension#1#2% +\permanent\def\comparedimension#1#2% {\compresult \ifdim#1<#2% \zerocount @@ -6005,7 +6200,7 @@ \plustwo \fi} -\def\comparedimensioneps#1#2% todo: use eps feature +\permanent\def\comparedimensioneps#1#2% todo: use eps feature {\compresult \ifdim\dimexpr#1-#2\relax<\roudingeps \zerocount @@ -6021,62 +6216,52 @@ % \copycsname xxx\endcsname\csname ..\endcsname -\protected\def\copycsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter\csname} +\permanent\protected\def\copycsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter\csname} % \letcscsname \crap \csname ..\endcsname % \letcsnamecs \csname ..\endcsname\crap % \letcsnamecsname\csname ..\endcsname\csname ..\endcsname -\protected\def\letcscsname {\expandafter\let\expandafter} -\protected\def\letcsnamecs {\expandafter\let} -\protected\def\letcsnamecsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter} +\permanent\protected\def\letcscsname {\expandafter\let\expandafter} +\permanent\protected\def\letcsnamecs {\expandafter\let} +\permanent\protected\def\letcsnamecsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter} % another one, add an item to a commalist -\protected\def\addvalue#1#2% cs item +\permanent\protected\def\addvalue#1#2% cs item {\ifcsname#1\endcsname\else\expandafter\let\csname#1\endcsname\empty\fi \normalexpanded{\addtocommalist{#2}\expandafter\noexpand\csname#1\endcsname}} -\def\unspaced#1% - {\syst_helpers_unspaced#1\end} - -\def\syst_helpers_unspaced#1% - {\ifx#1\end - \expandafter\gobbleoneargument - \orelse\ifx#1\blankspace - % go on - \else - #1% - \fi - \syst_helpers_unspaced} - -\protected\def\unspaceargument#1\to#2% - {\privatescratchcounter\catcode\spaceasciicode - \catcode\spaceasciicode\ignorecatcode - \scantextokens{\edef#2{#1}}% - \catcode\spaceasciicode\privatescratchcounter} +%D Are these ever used? Anyway, these variants are somewhat more efficient than +%D the \MKIV variants for larger strings. -\protected\def\unspaceafter#1#2% - {\unspaceargument#2\to\ascii - \expandafter#1\expandafter{\ascii}} +% A variant: +% +% \permanent\def\unspaced#1% +% {\localcontrolled{\begingroup\catcode\spaceasciicode\ignorecatcode}% +% \tokenized{#1}% +% \localcontrolled{\endgroup}} +% +% but we can also do this: -% sometimes handy: +\permanent\def\unspaced#1% + {\tokenized \s!catcodetable \ctdcatcodes {#1}} -\protected\def\doifelsehasspace#1% - {\edef\m_syst_string_one{#1}% - \normalexpanded{\syst_helpers_if_has_space_else#1\space}\empty\relax} +\permanent\protected\def\unspaceargument#1\to#2% + {\edef#2{\tokenized \s!catcodetable \ctdcatcodes {#1}}} -\let\doifhasspaceelse\doifelsehasspace +\protected\def\unspaceafter#1#2% + {\expandafter#1\expandafter{\tokenized \s!catcodetable \ctdcatcodes {#2}}} -\protected\def\syst_helpers_if_has_space_else#1 #2#3\relax % \space\empty\relax - {\ifx\m_syst_string_one\space +\permanent\protected\def\doifelsehasspace#1% + {\expandafter\ifhastok\space{#1}% \expandafter\firstoftwoarguments - \orelse\ifempty#2% - \expandafter\secondoftwoarguments \else - \expandafter\firstoftwoarguments + \expandafter\secondoftwoarguments \fi} +\aliased\let\doifhasspaceelse\doifelsehasspace + % this will replace loadfile once and alike !!! todo \installsystemnamespace{flag} @@ -6544,4 +6729,24 @@ {\edef\m_syst_string_one{#1}% \ifempty\m_syst_string_one} +%D New (also serves as an example): +%D +%D \starttyping +%D \commandflags\defineframed +%D \stoptyping + +\permanent\def\commandflags#1% + {\beginlocalcontrol\begingroup\scratchtoks\emptytoks\donefalse + \ifflags#1= \frozenflagcode\etoksapp\scratchtoks{\ifdone \space\fi frozen}\donetrue\fi + \ifflags#1=\permanentflagcode\etoksapp\scratchtoks{\ifdone \space\fi permanent}\donetrue\fi + \ifflags#1=\immutableflagcode\etoksapp\scratchtoks{\ifdone \space\fi immutable}\donetrue\fi + \ifflags#1=\primitiveflagcode\etoksapp\scratchtoks{\ifdone \space\fi primitive}\donetrue\fi + \ifflags#1= \mutableflagcode\etoksapp\scratchtoks{\ifdone \space\fi mutable}\donetrue\fi + \ifflags#1=\noalignedflagcode\etoksapp\scratchtoks{\ifdone \space\fi noaligned}\donetrue\fi + \ifflags#1= \instanceflagcode\etoksapp\scratchtoks{\ifdone \space\fi instance}\donetrue\fi + %\ifflags#1= \reservedflagcode\etoksapp\scratchtoks{\ifdone \space\fi reserved}\donetrue\fi + \ifflags#1= \tolerantflagcode\etoksapp\scratchtoks{\ifdone \space\fi tolerant}\donetrue\fi + \ifflags#1=\protectedflagcode\etoksapp\scratchtoks{\ifdone \space\fi protected}\donetrue\fi + \expandafter\endgroup\expandafter\endlocalcontrol\the\scratchtoks} + \protect \endinput diff --git a/tex/context/base/mkiv/syst-con.mkxl b/tex/context/base/mkiv/syst-con.mkxl index ffff5aab7..ed4a4f3c5 100644 --- a/tex/context/base/mkiv/syst-con.mkxl +++ b/tex/context/base/mkiv/syst-con.mkxl @@ -20,40 +20,40 @@ %D In addition to the uppercase hex conversion, as needed in math families, we %D occasionally need a lowercase one. -\def\lchexnumber #1{\clf_lchexnumber \numexpr#1\relax} -\def\uchexnumber #1{\clf_uchexnumber \numexpr#1\relax} -\def\lchexnumbers#1{\clf_lchexnumbers\numexpr#1\relax} -\def\uchexnumbers#1{\clf_uchexnumbers\numexpr#1\relax} +\permanent\def\lchexnumber #1{\clf_lchexnumber \numexpr#1\relax} +\permanent\def\uchexnumber #1{\clf_uchexnumber \numexpr#1\relax} +\permanent\def\lchexnumbers#1{\clf_lchexnumbers\numexpr#1\relax} +\permanent\def\uchexnumbers#1{\clf_uchexnumbers\numexpr#1\relax} -\let\hexnumber\uchexnumber +\aliased\let\hexnumber\uchexnumber %D \macros{octnumber} %D %D For \UNICODE\ remapping purposes, we need octal numbers. -\def\octnumber#1{\clf_octnumber\numexpr#1\relax} +\permanent\def\octnumber#1{\clf_octnumber\numexpr#1\relax} %D \macros{hexstringtonumber,octstringtonumber} %D %D This macro converts a two character hexadecimal number into a decimal number, %D thereby taking care of lowercase characters as well. -\def\hexstringtonumber#1{\clf_hexstringtonumber\numexpr#1\relax} -\def\octstringtonumber#1{\clf_octstringtonumber\numexpr#1\relax} +\permanent\def\hexstringtonumber#1{\clf_hexstringtonumber\numexpr#1\relax} +\permanent\def\octstringtonumber#1{\clf_octstringtonumber\numexpr#1\relax} %D \macros{rawcharacter} %D %D This macro can be used to produce proper 8 bit characters that we sometimes need %D in backends and round||trips. -\def\rawcharacter#1{\clf_rawcharacter\numexpr#1\relax} +\permanent\def\rawcharacter#1{\clf_rawcharacter\numexpr#1\relax} %D \macros{twodigits, threedigits} %D %D These macros provides two or three digits always: -\def\twodigits #1{\ifnum #1<10 0\fi\number#1} -\def\threedigits#1{\ifnum#1<100 \ifnum#1<10 0\fi0\fi\number#1} +\permanent\def\twodigits #1{\ifnum #1<10 0\fi\number#1} +\permanent\def\threedigits#1{\ifnum#1<100 \ifnum#1<10 0\fi0\fi\number#1} %D \macros{modulonumber} %D @@ -68,25 +68,20 @@ %D have behaved like \TEX's normal\type {\divide}, then the expression could have %D been somewhat simpler, like \type {#2-(#2/#1)*#1}. This works just as well, but a %D bit more complex. -%D -%D \starttyping -%D \def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax} -%D \stoptyping -%D -%D But \unknown\ now we can also do this: -\def\modulonumber#1#2{\the\numexpr#2-(#2:#1)*#1\relax} +%permanent\def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax} +%permanent\def\modulonumber#1#2{\the\numexpr#2-(#2:#1)*#1\relax} %D \macros{setcalculatedsin,setcalculatedcos,setcalculatedtan} -\protected\def\setcalculatedsin#1#2{\edef#1{\clf_sind#2}} -\protected\def\setcalculatedcos#1#2{\edef#1{\clf_cosd#2}} -\protected\def\setcalculatedtan#1#2{\edef#1{\clf_tand#2}} +\permanent\protected\def\setcalculatedsin#1#2{\edef#1{\clf_sind#2}} +\permanent\protected\def\setcalculatedcos#1#2{\edef#1{\clf_cosd#2}} +\permanent\protected\def\setcalculatedtan#1#2{\edef#1{\clf_tand#2}} %D \macros{formatted,format} - \def\formatted#1{\ctxcommand{format(#1)}} % not clf -\protected\def\format #1{\ctxcommand{format(#1)}} % not clf +\permanent \def\formatted#1{\ctxcommand{format(#1)}} % not clf +\permanent\protected\def\format #1{\ctxcommand{format(#1)}} % not clf %D The \type {\modulatednumber} and \type {\realnumber} macros have been removed. diff --git a/tex/context/base/mkiv/syst-ini.mkiv b/tex/context/base/mkiv/syst-ini.mkiv index 70a467ec5..b1ba9e0f3 100644 --- a/tex/context/base/mkiv/syst-ini.mkiv +++ b/tex/context/base/mkiv/syst-ini.mkiv @@ -444,6 +444,8 @@ \chardef \pluseight 8 \chardef \plusnine 9 \chardef \plusten 10 +\chardef \pluseleven 11 +\chardef \plustwelve 12 \chardef \plussixteen 16 \chardef \plusfifty 50 \chardef \plushundred 100 @@ -1137,9 +1139,31 @@ \matheqnogapstep\zerocount % for now -%D Experiment: - -\ifdefined\frozen \else \def\frozen{} \let\normalfrozen\frozen \fi +%D For as long as we share code between \MKIV\ and \LMTX\ we need these: + +\ifdefined\overloadmode \else + \newcount\overloadmode + % + \let\frozen \empty + \let\tolerant \empty + \let\overloaded\empty + \let\aliased \empty + \let\permanent \empty + \let\immutable \empty + \let\mutable \empty + \let\instance \empty + \let\noaligned \empty + \let\enforced \empty + % + \let\unletfrozen\gobbleoneargument + \let\letfrozen \gobbleoneargument + \def\letcsname {\expandafter\let \csname} + \def\defcsname {\expandafter\def \csname} + \def\edefcsname {\expandafter\edef\csname} + % + \let\pushoverloadmode\relax + \let\popoverloadmode\relax +\fi %D Now we define a few helpers that we need in a very early stage. We have no %D message system yet but redundant definitions are fatal anyway. @@ -1198,4 +1222,8 @@ \let\unvpack\unvbox \fi +%D Needed: + +\let\nexttoken\relax + \protect \endinput diff --git a/tex/context/base/mkiv/syst-ini.mkxl b/tex/context/base/mkiv/syst-ini.mkxl index 4a6352566..fbce9d780 100644 --- a/tex/context/base/mkiv/syst-ini.mkxl +++ b/tex/context/base/mkiv/syst-ini.mkxl @@ -24,57 +24,57 @@ %D but we're prestine and have no macros defined yet. Abstraction also makes it %D possible to avoid the \type {^^} in the input. -\chardef\escapecatcode 0 -\chardef\begingroupcatcode 1 -\chardef\endgroupcatcode 2 -\chardef\mathshiftcatcode 3 -\chardef\alignmentcatcode 4 -\chardef\endoflinecatcode 5 -\chardef\parametercatcode 6 -\chardef\superscriptcatcode 7 -\chardef\subscriptcatcode 8 -\chardef\ignorecatcode 9 -\chardef\spacecatcode 10 -\chardef\lettercatcode 11 -\chardef\othercatcode 12 % finally obsolete: \let\other \othercatcode -\chardef\activecatcode 13 % finally obsolete: \let\active\activecatcode -\chardef\commentcatcode 14 -\chardef\invalidcatcode 15 +\immutable\integerdef\escapecatcode 0 +\immutable\integerdef\begingroupcatcode 1 +\immutable\integerdef\endgroupcatcode 2 +\immutable\integerdef\mathshiftcatcode 3 +\immutable\integerdef\alignmentcatcode 4 +\immutable\integerdef\endoflinecatcode 5 +\immutable\integerdef\parametercatcode 6 +\immutable\integerdef\superscriptcatcode 7 +\immutable\integerdef\subscriptcatcode 8 +\immutable\integerdef\ignorecatcode 9 +\immutable\integerdef\spacecatcode 10 +\immutable\integerdef\lettercatcode 11 +\immutable\integerdef\othercatcode 12 % finally obsolete: \let\other \othercatcode +\immutable\integerdef\activecatcode 13 % finally obsolete: \let\active\activecatcode +\immutable\integerdef\commentcatcode 14 +\immutable\integerdef\invalidcatcode 15 %chardef\zeroasciicode 0 -\chardef\tabasciicode 9 -\chardef\newlineasciicode 10 % don't confuse this one with \endoflineasciicode -\chardef\formfeedasciicode 12 -\chardef\endoflineasciicode 13 % somewhat messy but this can be the active \par -\chardef\endoffileasciicode 26 -\chardef\spaceasciicode 32 -\chardef\exclamationmarkasciicode 33 % ! used in namespace protection -\chardef\doublequoteasciicode 34 % " -\chardef\hashasciicode 35 -\chardef\dollarasciicode 36 -\chardef\commentasciicode 37 -\chardef\ampersandasciicode 38 -\chardef\singlequoteasciicode 39 % ' -\chardef\primeasciicode 39 % ' -\chardef\leftparentasciicode 40 -\chardef\rightparentasciicode 41 -\chardef\commaasciicode 44 -\chardef\hyphenasciicode 45 -\chardef\periodasciicode 46 -\chardef\forwardslashasciicode 47 % / -\chardef\colonasciicode 58 -\chardef\lessthanasciicode 60 % < used as alternative verbatim { -\chardef\morethanasciicode 62 % > used as alternative verbatim } -\chardef\questionmarkasciicode 63 % ? used in namespace protection -\chardef\atsignasciicode 64 % @ used in namespace protection -\chardef\backslashasciicode 92 % `\\ -\chardef\circumflexasciicode 94 -\chardef\underscoreasciicode 95 -\chardef\leftbraceasciicode 123 % `\{ -\chardef\barasciicode 124 % `\| -\chardef\rightbraceasciicode 125 % `\} -\chardef\tildeasciicode 126 % `\~ -\chardef\delasciicode 127 +\immutable\integerdef\tabasciicode 9 +\immutable\integerdef\newlineasciicode 10 % don't confuse this one with \endoflineasciicode +\immutable\integerdef\formfeedasciicode 12 +\immutable\integerdef\endoflineasciicode 13 % somewhat messy but this can be the active \par +\immutable\integerdef\endoffileasciicode 26 +\immutable\integerdef\spaceasciicode 32 +\immutable\integerdef\exclamationmarkasciicode 33 % ! used in namespace protection +\immutable\integerdef\doublequoteasciicode 34 % " +\immutable\integerdef\hashasciicode 35 +\immutable\integerdef\dollarasciicode 36 +\immutable\integerdef\commentasciicode 37 +\immutable\integerdef\ampersandasciicode 38 +\immutable\integerdef\singlequoteasciicode 39 % ' +\immutable\integerdef\primeasciicode 39 % ' +\immutable\integerdef\leftparentasciicode 40 +\immutable\integerdef\rightparentasciicode 41 +\immutable\integerdef\commaasciicode 44 +\immutable\integerdef\hyphenasciicode 45 +\immutable\integerdef\periodasciicode 46 +\immutable\integerdef\forwardslashasciicode 47 % / +\immutable\integerdef\colonasciicode 58 +\immutable\integerdef\lessthanasciicode 60 % < used as alternative verbatim { +\immutable\integerdef\morethanasciicode 62 % > used as alternative verbatim } +\immutable\integerdef\questionmarkasciicode 63 % ? used in namespace protection +\immutable\integerdef\atsignasciicode 64 % @ used in namespace protection +\immutable\integerdef\backslashasciicode 92 % `\\ +\immutable\integerdef\circumflexasciicode 94 +\immutable\integerdef\underscoreasciicode 95 +\immutable\integerdef\leftbraceasciicode 123 % `\{ +\immutable\integerdef\barasciicode 124 % `\| +\immutable\integerdef\rightbraceasciicode 125 % `\} +\immutable\integerdef\tildeasciicode 126 % `\~ +\immutable\integerdef\delasciicode 127 %catcode\zeroasciicode \ignorecatcode % `\^^@ ascii null is ignored \catcode\tabasciicode \spacecatcode % `\^^I ascii tab is a blank space @@ -94,7 +94,7 @@ \catcode\tildeasciicode \activecatcode % `\~ tilde is active %catcode\delasciicode \invalidcatcode % `\^^? ascii delete is invalid -\chardef\statuswrite 128 +\chardef\statuswrite 128 % we need to get rid of this one %D First we need to initialization the primitives. Because \CONTEXT\ is already a %D pretty old macro package, we have a couple of issues with respect to primitives. @@ -140,20 +140,20 @@ function tex.enableprimitives() end % so we kind of protect what's there } -\def\space{ } -\def\empty{} +\permanent\def\space{ } +\permanent\def\empty{} -\letcharcode \formfeedasciicode \par % \def ^^L{\par} formfeed -\letcharcode \tildeasciicode \ % tilde -\letcharcode \spaceasciicode \space % space +\permanent\letcharcode \formfeedasciicode \par % \def ^^L{\par} formfeed +\permanent\letcharcode \tildeasciicode \ % tilde +\permanent\letcharcode \spaceasciicode \space % space -\expandafter\def\csname\Uchar\tabasciicode \endcsname {\ } % \def\^^I{\ } tab -\expandafter\def\csname\Uchar\formfeedasciicode \endcsname {\par} % \def\^^L{\par} formfeed -\expandafter\def\csname\Uchar\endoflineasciicode\endcsname {\ } % \def\^^M{\ } return +\permanent\expandafter\def\csname\Uchar\tabasciicode \endcsname {\ } % \def\^^I{\ } tab +\permanent\expandafter\def\csname\Uchar\formfeedasciicode \endcsname {\par} % \def\^^L{\par} formfeed +\permanent\expandafter\def\csname\Uchar\endoflineasciicode\endcsname {\ } % \def\^^M{\ } return %D For now: -\def\gobbleoneargument#1{} % will be defined later on anyway +\permanent\def\gobbleoneargument#-{} % will be defined later on anyway %D First we define a simplified version of the \CONTEXT\ protection mechanism. %D Later we will implement a better variant. @@ -176,8 +176,8 @@ %D Some pretty important definitions: -\let\bgroup={ -\let\egroup=} +\immutable\let\bgroup={ +\immutable\let\egroup=} %D \macros %D {normalbgroup,normalgroup} @@ -207,52 +207,42 @@ % % will be blocked: \newfamily \newlanguage -\countdef \c_syst_min_allocated_register = 52 \c_syst_min_allocated_register = 256 % can change -\countdef \c_syst_max_allocated_register = 53 \c_syst_max_allocated_register = 65535 -\countdef \c_syst_min_allocated_read = 54 \c_syst_min_allocated_read = 0 -\countdef \c_syst_max_allocated_read = 55 \c_syst_max_allocated_read = 1023 -\countdef \c_syst_min_allocated_language = 56 \c_syst_min_allocated_language = 0 -\countdef \c_syst_max_allocated_language = 57 \c_syst_max_allocated_language = 8191 -\countdef \c_syst_min_allocated_insert = 58 \c_syst_min_allocated_insert = 128 -\countdef \c_syst_max_allocated_insert = 59 \c_syst_max_allocated_insert = 254 -\countdef \c_syst_min_allocated_family = 60 \c_syst_min_allocated_family = 128 -\countdef \c_syst_max_allocated_family = 61 \c_syst_max_allocated_family = 255 -\countdef \c_syst_min_allocated_attribute = 62 \c_syst_min_allocated_attribute = 1024 % 0-1023 : private -\countdef \c_syst_min_allocated_write = 63 \c_syst_min_allocated_write = 0 -\countdef \c_syst_max_allocated_write = 64 \c_syst_max_allocated_write = 1023 - -\countdef \c_syst_last_allocated_count = 32 \c_syst_last_allocated_count = \c_syst_min_allocated_register -\countdef \c_syst_last_allocated_dimen = 33 \c_syst_last_allocated_dimen = \c_syst_min_allocated_register -\countdef \c_syst_last_allocated_skip = 34 \c_syst_last_allocated_skip = \c_syst_min_allocated_register -\countdef \c_syst_last_allocated_muskip = 35 \c_syst_last_allocated_muskip = \c_syst_min_allocated_register -\countdef \c_syst_last_allocated_box = 36 \c_syst_last_allocated_box = \c_syst_min_allocated_register -\countdef \c_syst_last_allocated_toks = 37 \c_syst_last_allocated_toks = \c_syst_min_allocated_register -\countdef \c_syst_last_allocated_read = 38 \c_syst_last_allocated_read = \c_syst_min_allocated_read -\countdef \c_syst_last_allocated_write = 39 \c_syst_last_allocated_write = \c_syst_min_allocated_write -\countdef \c_syst_last_allocated_marks = 40 \c_syst_last_allocated_marks = \c_syst_min_allocated_register -\countdef \c_syst_last_allocated_language = 41 \c_syst_last_allocated_language = \c_syst_min_allocated_language % not used in context -\countdef \c_syst_last_allocated_insertion = 42 \c_syst_last_allocated_insertion = \c_syst_min_allocated_insert -\countdef \c_syst_last_allocated_family = 43 \c_syst_last_allocated_family = \c_syst_min_allocated_family % not used in context -\countdef \c_syst_last_allocated_attribute = 44 \c_syst_last_allocated_attribute = \c_syst_min_allocated_attribute % not used in context - -\countdef \c_syst_min_counter_value = 125 \c_syst_min_counter_value = -"7FFFFFFF % beware, we use index 125 at the lua end -\countdef \c_syst_max_counter_value = 126 \c_syst_max_counter_value = "7FFFFFFF % beware, we use index 126 at the lua end - -\countdef \zerocount = 120 \zerocount = 0 -\countdef \plusone = 121 \plusone = 1 -\countdef \minusone = 122 \minusone = -1 - -\countdef \normalpagebox = 127 \normalpagebox = 255 % hardcoded in pdftex/xetex - -% Only to be used by developers in very special cases! - -% \def\lastallocatedcount {\the\c_syst_last_allocated_count} -% \def\lastallocateddimen {\the\c_syst_last_allocated_dimen} -% \def\lastallocatedskip {\the\c_syst_last_allocated_skip} -% \def\lastallocatedmuskip {\the\c_syst_last_allocated_muskip} -% \def\lastallocatedbox {\the\c_syst_last_allocated_dimen} -% \def\lastallocatedtoks {\the\c_syst_last_allocated_toks} -% \def\lastallocatedattribute{\the\c_syst_last_allocated_attribute} +\permanent\countdef \c_syst_min_allocated_register = 52 \c_syst_min_allocated_register = 256 % can change +\permanent\countdef \c_syst_max_allocated_register = 53 \c_syst_max_allocated_register = 65535 +\permanent\countdef \c_syst_min_allocated_read = 54 \c_syst_min_allocated_read = 0 +\permanent\countdef \c_syst_max_allocated_read = 55 \c_syst_max_allocated_read = 1023 +\permanent\countdef \c_syst_min_allocated_language = 56 \c_syst_min_allocated_language = 0 +\permanent\countdef \c_syst_max_allocated_language = 57 \c_syst_max_allocated_language = 8191 +\permanent\countdef \c_syst_min_allocated_insert = 58 \c_syst_min_allocated_insert = 128 +\permanent\countdef \c_syst_max_allocated_insert = 59 \c_syst_max_allocated_insert = 254 +\permanent\countdef \c_syst_min_allocated_family = 60 \c_syst_min_allocated_family = 128 +\permanent\countdef \c_syst_max_allocated_family = 61 \c_syst_max_allocated_family = 255 +\permanent\countdef \c_syst_min_allocated_attribute = 62 \c_syst_min_allocated_attribute = 1024 % 0-1023 : private +\permanent\countdef \c_syst_min_allocated_write = 63 \c_syst_min_allocated_write = 0 +\permanent\countdef \c_syst_max_allocated_write = 64 \c_syst_max_allocated_write = 1023 + +\permanent\countdef \c_syst_last_allocated_count = 32 \c_syst_last_allocated_count = \c_syst_min_allocated_register +\permanent\countdef \c_syst_last_allocated_dimen = 33 \c_syst_last_allocated_dimen = \c_syst_min_allocated_register +\permanent\countdef \c_syst_last_allocated_skip = 34 \c_syst_last_allocated_skip = \c_syst_min_allocated_register +\permanent\countdef \c_syst_last_allocated_muskip = 35 \c_syst_last_allocated_muskip = \c_syst_min_allocated_register +\permanent\countdef \c_syst_last_allocated_box = 36 \c_syst_last_allocated_box = \c_syst_min_allocated_register +\permanent\countdef \c_syst_last_allocated_toks = 37 \c_syst_last_allocated_toks = \c_syst_min_allocated_register +\permanent\countdef \c_syst_last_allocated_read = 38 \c_syst_last_allocated_read = \c_syst_min_allocated_read +\permanent\countdef \c_syst_last_allocated_write = 39 \c_syst_last_allocated_write = \c_syst_min_allocated_write +\permanent\countdef \c_syst_last_allocated_marks = 40 \c_syst_last_allocated_marks = \c_syst_min_allocated_register +\permanent\countdef \c_syst_last_allocated_language = 41 \c_syst_last_allocated_language = \c_syst_min_allocated_language % not used in context +\permanent\countdef \c_syst_last_allocated_insertion = 42 \c_syst_last_allocated_insertion = \c_syst_min_allocated_insert +\permanent\countdef \c_syst_last_allocated_family = 43 \c_syst_last_allocated_family = \c_syst_min_allocated_family % not used in context +\permanent\countdef \c_syst_last_allocated_attribute = 44 \c_syst_last_allocated_attribute = \c_syst_min_allocated_attribute % not used in context + +\permanent\countdef \c_syst_min_counter_value = 125 \c_syst_min_counter_value = -"7FFFFFFF % beware, we use index 125 at the lua end +\permanent\countdef \c_syst_max_counter_value = 126 \c_syst_max_counter_value = "7FFFFFFF % beware, we use index 126 at the lua end + +\immutable\integerdef\zerocount = 0 +\immutable\integerdef\plusone = 1 +\immutable\integerdef\minusone = -1 + +\immutable\integerdef\normalpagebox = 255 % hardcoded in pdftex/xetex % A few traditional allocations (these might go): @@ -270,35 +260,41 @@ %D The allocators share a common helper macro. -\protected\def\newcount {\syst_basics_allocate\c_syst_last_allocated_count \count \countdef \c_syst_max_allocated_register} -\protected\def\newdimen {\syst_basics_allocate\c_syst_last_allocated_dimen \dimen \dimendef \c_syst_max_allocated_register} -\protected\def\newskip {\syst_basics_allocate\c_syst_last_allocated_skip \skip \skipdef \c_syst_max_allocated_register} -\protected\def\newmuskip {\syst_basics_allocate\c_syst_last_allocated_muskip \muskip \muskipdef \c_syst_max_allocated_register} -\protected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \mathchardef\c_syst_max_allocated_register} -\protected\def\newtoks {\syst_basics_allocate\c_syst_last_allocated_toks \toks \toksdef \c_syst_max_allocated_register} -\protected\def\newread {\syst_basics_allocate\c_syst_last_allocated_read \read \chardef \c_syst_max_allocated_read} -\protected\def\newwrite {\syst_basics_allocate\c_syst_last_allocated_write \write \chardef \c_syst_max_allocated_write} -\protected\def\newmarks {\syst_basics_allocate\c_syst_last_allocated_marks \marks \mathchardef\c_syst_max_allocated_register} -\protected\def\newinsert {\syst_basics_allocate\c_syst_last_allocated_insertion\insert \chardef \c_syst_max_allocated_insert} +\protected\permanent\def\newcount {\syst_basics_allocate\c_syst_last_allocated_count \count \countdef \c_syst_max_allocated_register} +\protected\permanent\def\newdimen {\syst_basics_allocate\c_syst_last_allocated_dimen \dimen \dimendef \c_syst_max_allocated_register} +\protected\permanent\def\newskip {\syst_basics_allocate\c_syst_last_allocated_skip \skip \skipdef \c_syst_max_allocated_register} +\protected\permanent\def\newmuskip {\syst_basics_allocate\c_syst_last_allocated_muskip \muskip \muskipdef \c_syst_max_allocated_register} +\protected\permanent\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \integerdef\c_syst_max_allocated_register} +\protected\permanent\def\newtoks {\syst_basics_allocate\c_syst_last_allocated_toks \toks \toksdef \c_syst_max_allocated_register} +\protected\permanent\def\newread {\syst_basics_allocate\c_syst_last_allocated_read \read \integerdef\c_syst_max_allocated_read} +\protected\permanent\def\newwrite {\syst_basics_allocate\c_syst_last_allocated_write \write \integerdef\c_syst_max_allocated_write} +\protected\permanent\def\newmarks {\syst_basics_allocate\c_syst_last_allocated_marks \marks \integerdef\c_syst_max_allocated_register} +\protected\permanent\def\newinsert {\syst_basics_allocate\c_syst_last_allocated_insertion\insert \chardef \c_syst_max_allocated_insert} +\protected\permanent\def\newlanguage{\syst_basics_allocate\c_syst_last_allocated_language \language\integerdef\c_syst_max_allocated_language} % not needed in context +\protected\permanent\def\newfamily {\syst_basics_allocate\c_syst_last_allocated_family \fam \integerdef\c_syst_max_allocated_family} % not needed in context -%D We don't need these in \CONTEXT: +\aliased\let\newfam\newfamily -\protected\def\newlanguage{\syst_basics_allocate\c_syst_last_allocated_language \language\chardef \c_syst_max_allocated_language} -\protected\def\newfamily {\syst_basics_allocate\c_syst_last_allocated_family \fam \chardef \c_syst_max_allocated_family} - -\let\newfam\newfamily - -\firstvalidlanguage \plusone % so zero is ignored in hyphenation, this might becoem the default +\firstvalidlanguage \plusone % so zero is ignored in hyphenation, this might become the default % Watch out, for the moment we disable the check for already being defined % later we will revert this but first all chardefs must be replaced. -\protected\def\newconstant #1{\ifdefined#1\let#1\undefined\fi\newcount#1} -\protected\def\setnewconstant #1{\ifdefined#1\let#1\undefined\fi\newcount#1#1} % just a number -\protected\def\setconstant {} % dummy, no checking, so it warns +\protected\def\setconstant {} \protected\def\setconstantvalue#1#2{\csname#1\endcsname\numexpr#2\relax} -% maybe setconstant with check +\protected\def\newconstant#1% + {\ifx#1\relax + %\writestatus{!!!!!!!!!!}{\string #1 => RELAX}% + \unletfrozen#1% + \newcount#1% + \orelse\ifdefined#1% + %\writestatus{!!!!!!!!!!}{\string #1 => DEFINED}% + \else + \newcount#1% + \fi} + +\protected\def\setnewconstant#1{\newconstant#1#1} % %D The next definitions are really needed (in \CONTEXT): @@ -312,13 +308,13 @@ \ifdefined\writestatus \else %\protected\def\writestatus#1#2{\immediate\write\statuswrite{#1: #2}} - \protected\def\writestatus#1#2{\message{#1: #2}} + \frozen\protected\def\writestatus#1#2{\message{#1: #2}} \fi \def\syst_basics_allocate_yes#1#2#3#4#5% last class method max name {\ifnum#1<#4\relax \global\advance#1\plusone - \global#3#5=#1\relax + \permanent\global#3#5=#1\relax \else \writestatus{warning}{no room for \string#2\space \string#5\space (max: \number#4)}% \fi} @@ -339,24 +335,23 @@ %D Since the number of chars exceed 256 now, we can use \type {\chardef} instead of %D the more limited \type {\mathchardef}. -\protected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \chardef\c_syst_max_allocated_register} -\protected\def\newmarks{\syst_basics_allocate\c_syst_last_allocated_marks\marks\chardef\c_syst_max_allocated_register} +% \protected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \chardef\c_syst_max_allocated_register} +% \protected\def\newmarks{\syst_basics_allocate\c_syst_last_allocated_marks\marks\chardef\c_syst_max_allocated_register} %D Attributes are something very \LUATEX. In \CONTEXT\ you are not supposed to use %D the attributes directly but always allocate then first. For instance attribute~0 %D is reserved for special purposes (this might change). Attributes in the range %D 128-1023 are private and should not be touched. -\let\attributeunsetvalue\c_syst_min_counter_value % used to be \minusone +\permanent\integerdef\attributeunsetvalue\c_syst_min_counter_value % used to be \minusone -\protected\def\newattribute{\syst_basics_allocate\c_syst_last_allocated_attribute\attribute\attributedef\c_syst_max_allocated_register} +% \permanent\protected\def\newattribute{\syst_basics_allocate\c_syst_last_allocated_attribute\attribute\attributedef\c_syst_max_allocated_register} %D Not used by \CONTEXT\ but for instance \PICTEX\ needs it. It's a trick to force %D strings instead of tokens that take more memory. It's a trick to trick to force %D strings. This macro is never used in \CONTEXT. -%protected\def\newhelp#1#2{\newtoks#1#1\expandafter{\csname#2\endcsname}} -\protected\def\newhelp#1#2{\newtoks#1#1\expandafter{\detokenize{#2}}} +\permanent\protected\def\newhelp#1#2{\newtoks#1#1\expandafter{\detokenize{#2}}} %D \macros %D {scratchcounter, @@ -445,78 +440,79 @@ %D More allocations: -\newskip \zeroskip \zeroskip 0pt plus 0pt minus 0pt -\newdimen \zeropoint \zeropoint 0pt -\newdimen \onepoint \onepoint 1pt -\newdimen \halfapoint \halfapoint 0.5pt -\newdimen \maxdimen \maxdimen 16383.99999pt % 1073741823sp -\newcount \maxcount \maxcount 2147483647 -\newdimen \onebasepoint \onebasepoint 1bp -\newdimen \scaledpoint \scaledpoint 1sp -\newdimen \thousandpoint \thousandpoint 1000pt -\newmuskip\zeromuskip \zeromuskip 0mu -\newmuskip\onemuskip \onemuskip 1mu +\newskip \zeroskip \immutable\zeroskip 0pt plus 0pt minus 0pt +\newdimen \zeropoint \immutable\zeropoint 0pt +\newdimen \onepoint \immutable\onepoint 1pt +\newdimen \halfapoint \immutable\halfapoint 0.5pt +\newdimen \maxdimen \immutable\maxdimen 16383.99999pt % 1073741823sp +\newcount \maxcount \immutable\maxcount 2147483647 +\newdimen \onebasepoint \immutable\onebasepoint 1bp +\newdimen \scaledpoint \immutable\scaledpoint 1sp +\newdimen \thousandpoint \immutable\thousandpoint 1000pt +\newmuskip\zeromuskip \immutable\zeromuskip 0mu +\newmuskip\onemuskip \immutable\onemuskip 1mu -\newmuskip\muquad \muquad 18mu +\newmuskip\muquad \immutable\muquad 18mu -\let\points \onepoint -\let\halfpoint\halfapoint +\aliased\let\points \onepoint +\aliased\let\halfpoint\halfapoint \newtoks \emptytoks -%D And even more: (todo: countdefs 60+) - -%newcount\minusone \minusone -1 -\newcount\minustwo \minustwo -2 -%chardef \zerocount 0 -%chardef \plusone 1 -\chardef \plustwo 2 -\chardef \plusthree 3 -\chardef \plusfour 4 -\chardef \plusfive 5 -\chardef \plussix 6 -\chardef \plusseven 7 -\chardef \pluseight 8 -\chardef \plusnine 9 -\chardef \plusten 10 -\chardef \plussixteen 16 -\chardef \plusfifty 50 -\chardef \plushundred 100 -\chardef \plusonehundred 100 -\chardef \plustwohundred 200 -\chardef \plusfivehundred 500 -\chardef \pluscxxvii 127 -\chardef \pluscxxviii 128 -\chardef \pluscclv 255 -\chardef \pluscclvi 256 -\chardef \plusthousand 1000 -\chardef \plustenthousand 10000 -\chardef \plustwentythousand 20000 -\chardef \medcard 32768 -\chardef \maxcard 65536 % pdftex has less mathchars -\chardef \maxcardminusone 65535 +%D And even more: (todo: countdefs 60+). Watch out, we need a count for a negative constant +%D but can use chardefs for positive ones. Actually, because we have plenty of counters we +%D can also use counts for those. + +%permanent\integerdef\minusone -1 +\permanent\integerdef\minustwo -2 +%permanent\integerdef\zerocount 0 +%permanent\integerdef\plusone 1 +\permanent\integerdef\plustwo 2 +\permanent\integerdef\plusthree 3 +\permanent\integerdef\plusfour 4 +\permanent\integerdef\plusfive 5 +\permanent\integerdef\plussix 6 +\permanent\integerdef\plusseven 7 +\permanent\integerdef\pluseight 8 +\permanent\integerdef\plusnine 9 +\permanent\integerdef\plusten 10 +\permanent\integerdef\pluseleven 11 +\permanent\integerdef\plustwelve 12 +\permanent\integerdef\plussixteen 16 +\permanent\integerdef\plusfifty 50 +\permanent\integerdef\plushundred 100 +\permanent\integerdef\plusonehundred 100 +\permanent\integerdef\plustwohundred 200 +\permanent\integerdef\plusfivehundred 500 +\permanent\integerdef\pluscxxvii 127 +\permanent\integerdef\pluscxxviii 128 +\permanent\integerdef\pluscclv 255 +\permanent\integerdef\pluscclvi 256 +\permanent\integerdef\plusthousand 1000 +\permanent\integerdef\plustenthousand 10000 +\permanent\integerdef\plustwentythousand 20000 +\permanent\integerdef\medcard 32768 +\permanent\integerdef\maxcard 65536 % pdftex has less mathchars +\permanent\integerdef\maxcardminusone 65535 %D \macros %D {doubleexpandafter,tripleexpandafter,expanded,startexpanded} %D %D A few handy shortcuts -\let\singleexpandafter \expandafter -\def\doubleexpandafter{\expandafter\expandafter\expandafter} -\def\tripleexpandafter{\expandafter\doubleexpandafter\expandafter} +\permanent\let\singleexpandafter \expandafter +\permanent\def\doubleexpandafter{\expandafter\expandafter\expandafter} +\permanent\def\tripleexpandafter{\expandafter\doubleexpandafter\expandafter} %D We prefer the more readable variant than in plain \TEX. User should only %D use \type {\emptybox}: \newbox\voidbox % public -\let\normalhbox\hbox -\let\normalvbox\vbox - -\def\unvoidbox{\unhbox\voidbox} -\def\emptybox {\box \voidbox} % used in initializations so no attributes -\def\emptyvbox{\normalvpack{}} % no copy as we need to set attributes -\def\emptyhbox{\normalhpack{}} % no copy as we need to set attributes +\permanent\def\unvoidbox{\unhbox\voidbox} +\permanent\def\emptybox {\box \voidbox} % used in initializations so no attributes +\permanent\def\emptyvbox{\normalvpack{}} % no copy as we need to set attributes +\permanent\def\emptyhbox{\normalhpack{}} % no copy as we need to set attributes \let\leavevmode\unvoidbox % we prefer to use \dontleavehmode @@ -525,7 +521,7 @@ %D %D We need this one soon: -\protected\def\dontcomplain +\permanent\protected\def\dontcomplain {\hbadness\plustenthousand \vbadness\plustenthousand \hfuzz \maxdimen @@ -534,20 +530,21 @@ %D Some expected plain variants follow. We don't reuse registers because we %D don't want clashes. -\let \p@ \onepoint -\let \m@ne \minusone -\let \z@ \zeropoint -\let \@ne \plusone -\let \tw@ \plustwo -\let \thr@@ \plusthree -\let \sixt@@n \plussixteen -\let \@cclv \pluscclv -\let \@cclvi \pluscclvi -\let \voidb@x \voidbox -\newtoks \toks@ % \scratchtoks - -%D We define \type {\newif} a la plain \TEX, but will redefine it later. As -%D Knuth says: +\aliased\let\p@ \onepoint +\aliased\let\m@ne \minusone +\aliased\let\z@ \zeropoint +\aliased\let\@ne \plusone +\aliased\let\tw@ \plustwo +\aliased\let\thr@@ \plusthree +\aliased\let\sixt@@n\plussixteen +\aliased\let\@cclv \pluscclv +\aliased\let\@cclvi \pluscclvi +\aliased\let\voidb@x\voidbox + +\newtoks \toks@ %scratchtoks + +%D We define \type {\newif} a la plain \TEX, but will redefine it later. As Knuth +%D says: %D %D \startnarrower %D And here's a different sort of allocation: for example, @@ -588,19 +585,14 @@ % \protected\def\new_if_cs#1#2% % {\csname\expandafter\newif\csstring#1#2\endcsname} % -% We wrap all into one macro: +% We wrap all into one macro (the frozen stuff adds 10% runtime): -\protected\def\newif#1% - {\let\new_if_saved\newif - \let\newif\new_if_check - \expandafter\def\csname\expandafter\newif\csstring#1true\endcsname {\let#1\iftrue }% - \expandafter\def\csname\expandafter\newif\csstring#1false\endcsname{\let#1\iffalse}% - \csname\expandafter\newif\csstring#1false\endcsname - \let\newif\new_if_saved} +\permanent\protected\def\newif#1% + {\permanent\protected\expandafter\gdef\csname\expandafter\new_if_check\csstring#1true\endcsname {\overloaded\frozen\let#1\iftrue }% + \permanent\protected\expandafter\gdef\csname\expandafter\new_if_check\csstring#1false\endcsname{\overloaded\frozen\let#1\iffalse}% + \csname\expandafter\new_if_check\csstring#1false\endcsname} -\bgroup - \normalexpanded{\gdef\noexpand\new_if_check\string i\string f{}} -\egroup +\normalexpanded{\gdef\noexpand\new_if_check\string i\string f{}} %D Let's test this one: @@ -611,22 +603,22 @@ %D A few shortcuts: -\protected\def\udef {\protected\def } -\protected\def\ugdef{\protected\gdef} -\protected\def\uedef{\protected\edef} -\protected\def\uxdef{\protected\xdef} +\permanent\protected\def\udef {\protected\def } +\permanent\protected\def\ugdef{\protected\gdef} +\permanent\protected\def\uedef{\protected\edef} +\permanent\protected\def\uxdef{\protected\xdef} %D For a while we keep the following, as systems like tikz need it. Best %D not use that one \CONTEXT. -\let\active\activecatcode +\aliased\let\active\activecatcode %D Constants to be used with \type {\interactionmode}. -\chardef\batchmodecode \zerocount -\chardef\nonstopmodecode \plusone -\chardef\scrollmodecode \plustwo -\chardef\errorstopmodecode \plusthree +\permanent\integerdef\batchmodecode \zerocount +\permanent\integerdef\nonstopmodecode \plusone +\permanent\integerdef\scrollmodecode \plustwo +\permanent\integerdef\errorstopmodecode \plusthree %D Of course we want even bigger log files, so we copied this from the \ETEX\ %D source files. @@ -646,7 +638,7 @@ % no longer \errorstopmode cf. plain tex 3.141592653 -\protected\def\tracingall +\permanent\protected\def\tracingall {\tracingonline \plusone \tracingcommands \plusthree \tracingmacros \plustwo @@ -659,16 +651,18 @@ \tracingnesting \plustwo \tracingassigns \plustwo \tracingmath \plusone + \tracingalignments\plusone \showboxbreadth \maxcount \showboxdepth \maxcount} -\protected\def\loggingall +\permanent\protected\def\loggingall {\tracingall \tracingonline \zerocount} -\protected\def\tracingnone +\permanent\protected\def\tracingnone {\showboxdepth \plusthree \showboxbreadth \plusfive + \tracingalignments\zerocount \tracingmath \zerocount \tracingassigns \zerocount \tracingnesting \zerocount @@ -691,31 +685,31 @@ \tracingstats\plusone -%D Here we also save \type {\input}, more will be saved later. - -\ifdefined\normalinput \else \let\normalinput\input \fi - -%D We don't like outer commands, and we always want access to the original -%D \type {\input} primitive. - -\let\normalouter\outer \def\outer{} % no longer \relax +%D This is only used when we load \CONTEXT: -%D To circumvent dependencies, we can postpone certain initializations to -%D dumping time, by appending them to the \type {\everydump} token register. - -\ifdefined\normaldump \else \let\normaldump\dump \fi +\permanent\def\pushoverloadmode + {\edef\popoverloadmode{\overloadmode\the\overloadmode}% + \overloadmode\zerocount} \newtoks\everydump -\def\dump{\the\everydump\global\everydump\emptytoks\glet\dump\relax\normaldump} - -%D The same applies for the startup actions. +\pushoverloadmode -\ifdefined\normaleveryjob \else \let\normaleveryjob\everyjob \fi +\protected\def\dump + {\the\everydump + \global\everydump\emptytoks + \pushoverloadmode + \glet\dump\relax + \popoverloadmode + %let\pushoverloadmode\relax + %let\popoverloadmode\relax +% \tracingall + \normaldump} -\let\everyjob\relax \newtoks\everyjob +\permanent\protected\def\input + {\normalinput} -\normaleveryjob{\the\everyjob} +\popoverloadmode %D \macros %D {newconditional, @@ -754,27 +748,27 @@ %D Such an implementation gives problems with nested conditionals. The next %D implementation is about as fast and just as straightforward: -\let\conditionalfalse\plusone % maybe we will have a dedicated count/chardef -\let\conditionaltrue \zerocount % maybe we will have a dedicated count/chardef +\aliased\let\conditionalfalse\plusone % maybe we will have a dedicated count/chardef +\aliased\let\conditionaltrue \zerocount % maybe we will have a dedicated count/chardef -\protected\def\settrue #1{\let#1\conditionaltrue } -\protected\def\setfalse#1{\let#1\conditionalfalse} +\permanent\protected\def\settrue #1{\integerdef#1\conditionaltrue } +\permanent\protected\def\setfalse#1{\integerdef#1\conditionalfalse} -\protected\def\settruevalue #1{\expandafter\let\csname#1\endcsname\conditionaltrue } -\protected\def\setfalsevalue#1{\expandafter\let\csname#1\endcsname\conditionalfalse} +\permanent\protected\def\settruevalue #1{\expandafter\integerdef\csname#1\endcsname\conditionaltrue } +\permanent\protected\def\setfalsevalue#1{\expandafter\integerdef\csname#1\endcsname\conditionalfalse} -\let\newconditional\setfalse -\let\ifconditional \ifcase +\aliased\let\newconditional\setfalse +\aliased\let\ifconditional \ifcase -\let\then\relax % so that we can say: \ifnum1>2\then -) +\aliased\let\then\relax % so that we can say: \ifnum1>2\then -) -\def\truecondition {\iftrue} -\def\falsecondition{\iffalse} +\permanent\def\truecondition {\iftrue} +\permanent\def\falsecondition{\iffalse} % This one has to be unprotected otherwise we get a files-ends-to-soon but it's ok % as conditions expand anyway. -\def\quitcondition{\orelse\iffalse} +\permanent\def\quitcondition{\orelse\iffalse} %D \macros %D {newmacro,setnewmacro,newfraction} @@ -782,13 +776,13 @@ %D Let's be complete and also introduce some definers. These are not mandate %D but handy for grepping. -\protected\def\newmacro #1{\let#1\empty} -\protected\def\setnewmacro#1{\let#1} +\permanent\protected\def\newmacro #1{\let#1\empty} +\permanent\protected\def\setnewmacro#1{\let#1} -\def\!!zerocount{0} -\def\!!plusone {1} +\permanent\protected\def\newfraction#1{\let#1\!!plusone} -\protected\def\newfraction#1{\let#1\!!plusone} +\def\!!zerocount{0} % later redefined +\def\!!plusone {1} % later redefined %D It would be handy to have a primitive \type {\unless\ifcase} because then we %D could use nicer values. Anyhow, this conditional code used to be in the \type @@ -804,7 +798,7 @@ %D \ifzeropt \somedimen ... \else ... \fi %D \stoptyping -\let\ifzeropt\ifcase +\aliased\let\ifzeropt\ifcase % these token list helpers might move to syst-aux.mkiv % @@ -815,14 +809,14 @@ \newtoks\t_syst_toks_temp \let\m_syst_toks_temp\t_syst_toks_temp -\protected\def\appendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_l \t_syst_toks_temp=} -\protected\def\prependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_l\t_syst_toks_temp=} +\permanent\protected\def\appendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_l \t_syst_toks_temp=} +\permanent\protected\def\prependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_l\t_syst_toks_temp=} % \def\syst_toks_append {\m_syst_toks_temp\expandafter\expandafter\expandafter{\expandafter\the\expandafter\m_syst_toks_temp\the\t_syst_toks_temp}}} % \def\syst_toks_prepend{\m_syst_toks_temp\expandafter\expandafter\expandafter{\expandafter\the\expandafter\t_syst_toks_temp\the\m_syst_toks_temp}}} -\protected\def\globalappendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_g \t_syst_toks_temp=} -\protected\def\globalprependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_g\t_syst_toks_temp=} +\permanent\protected\def\globalappendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_g \t_syst_toks_temp=} +\permanent\protected\def\globalprependtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_prepend_g\t_syst_toks_temp=} \def\syst_toks_append_l {\normalexpanded{\m_syst_toks_temp{\the\m_syst_toks_temp\the\t_syst_toks_temp}}} \def\syst_toks_prepend_l{\normalexpanded{\m_syst_toks_temp{\the\t_syst_toks_temp\the\m_syst_toks_temp}}} @@ -830,14 +824,14 @@ \def\syst_toks_append_g {\global\syst_toks_append_l } \def\syst_toks_prepend_g{\global\syst_toks_prepend_l} -\protected\def\addtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_l\let\next} -\protected\def\globaladdtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_g\let\next} +\permanent\protected\def\addtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_l\let\next} +\permanent\protected\def\globaladdtotoks#1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_g\let\next} \def\syst_toks_add_l{\m_syst_toks_temp\expandafter\bgroup\the\m_syst_toks_temp} \def\syst_toks_add_g{\global\syst_toks_add_l} -\protected\def\addtotokscs #1#2{#1{\the#1#2}} % saves a few bytes -\protected\def\globaladdtotokscs#1#2{\global#1{\the#1#2}} % saves a few bytes +\permanent\protected\def\addtotokscs #1#2{#1{\the#1#2}} % saves a few bytes +\permanent\protected\def\globaladdtotokscs#1#2{\global#1{\the#1#2}} % saves a few bytes %D \macros %D {begcsname} @@ -846,7 +840,7 @@ % \def\begcsname#1\endcsname{\ifcsname#1\endcsname\csname#1\endcsname\fi} -\let\begcsname\begincsname +\aliased\let\begcsname\begincsname %D Now come a few macros that might be needed in successive loading. We redefine the %D \type {\par} primitive pretty soon so that we get the equivalents right. @@ -863,13 +857,13 @@ % {\everypar \emptytoks % \everyendpar\emptytoks} -\protected\def\reseteverypar +\permanent\protected\def\reseteverypar {\everypar\emptytoks} -\let\endgraf\par -\let\endline\cr +\aliased\let\endgraf\par % plain, a kind of funny name +%aliased\let\endline\cr % plain, not needed and probably also confusing -\protected\def\null{\hpack{}} +\permanent\protected\def\null{\hpack{}} %D The following two might be overloaded later on but some modules need then %D earlier. These functionality is reflected in the name and will not change. @@ -885,8 +879,8 @@ % \obeyspaces\glet =\space% % \egroup -\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\par} -\def\obeyspaces{\catcode\spaceasciicode \activecatcode\letcharcode\spaceasciicode \space} +\def\obeylines {\catcode\endoflineasciicode\activecatcode\letcharcode\endoflineasciicode\par } % check if these can be \permanent +\def\obeyspaces{\catcode\spaceasciicode \activecatcode\letcharcode\spaceasciicode \space} % check if these can be \permanent % %D A constant: % @@ -897,12 +891,12 @@ %D get. Beware: this macro does not support nested loops. We use a namespace %D prefix \type {@@pln}. -\def\loop#1\repeat{\def\@@plnbody{#1}\@@plniterate} % might go +\permanent\def\loop#1\repeat{\def\@@plnbody{#1}\@@plniterate} % might go %D The following makes \type {\loop} \unknown\ \type {\if} \unknown\ \type %D {\repeat} skippable (clever trick): -\let\repeat\fi % so both \loop and \repeat are reserved words! +\permanent\let\repeat\fi % so both \loop and \repeat are reserved words! %D The original (no \type {@@pln} there): %D @@ -927,12 +921,12 @@ %D Although we don't add pagenumbers yet we alias the default register used %D for counting pages: -\countdef\pageno\zerocount \pageno\plusone % first page is number 1 +\permanent\countdef\pageno\zerocount \pageno\plusone % first page is number 1 %D Beside the raw counter \type {\pageno} the \type {\folio} macro provides %D the value. -\def\folio{\the\pageno} % kind of expected and therefore reserved +\permanent\def\folio{\the\pageno} % kind of expected and therefore reserved %D The following registers are kind of standard and (for the moment) we define %D them here. This might change. @@ -948,11 +942,11 @@ %D Sometimes kerns make more sense than glue but we need to be in the %D right mode: -\protected\def\vkern {\ifhmode\par \fi\kern} -\protected\def\hkern {\ifvmode\dontleavehmode\fi\kern} +\permanent\protected\def\vkern {\ifhmode\par \fi\kern} +\permanent\protected\def\hkern {\ifvmode\dontleavehmode\fi\kern} -\protected\def\vpenalty{\ifhmode\par \fi\penalty} -\protected\def\hpenalty{\ifvmode\dontleavehmode\fi\penalty} +\permanent\protected\def\vpenalty{\ifhmode\par \fi\penalty} +\permanent\protected\def\hpenalty{\ifvmode\dontleavehmode\fi\penalty} %D Again a few kind-of-extensions the core. These come from plain \TEX\ but %D are probably not used in \CONTEXT. @@ -960,19 +954,19 @@ \newskip \hideskip \hideskip = -1000pt plus 1fill \newskip \centering \centering = 0pt plus 1000pt minus 1000pt -\def\hidewidth % for alignment entries that can stick out +\permanent\def\hidewidth % for alignment entries that can stick out {\hskip\hideskip} -\def\ialign % initialized \halign +\permanent\def\ialign % initialized \halign {\everycr\emptytoks \tabskip\zeroskip \halign} \newcount \mscount -\def\spanomit{\span\omit} % bypass error message +\permanent\def\spanomit{\span\omit} % bypass error message -\def\multispan#1% +\permanent\def\multispan#1% {\omit \mscount#1\relax \loop @@ -980,30 +974,31 @@ \spanomit \advance\mscount\minusone \repeat} -\let\nopdfcompression \relax -\let\onlypdfobjectcompression\relax -\let\maximumpdfcompression \relax -\let\normalpdfcompression \relax +\let\nopdfcompression \relax % later +\let\onlypdfobjectcompression\relax % later +\let\maximumpdfcompression \relax % later +\let\normalpdfcompression \relax % later %D Basic status stuff. -\newif\ifproductionrun +% \newif\ifproductionrun % already defined %D For those who expect this \unknown -\ifx\fmtname \undefined \def\fmtname {ConTeXt Initial TeX} \fi -\ifx\fmtversion\undefined \def\fmtversion{3.1415926} \fi +\ifx\fmtname \undefined \immutable\def\fmtname {ConTeXt Initial TeX} \fi +\ifx\fmtversion\undefined \immutable\def\fmtversion{3.1415926} \fi %D A few bonus macros: -\def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax} -\def\dividenumber#1#2{\the\numexpr(#2-(#1/2))/#1\relax} +%permanent\def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax} +\permanent\def\modulonumber#1#2{\the\numexpr#2-(#2:#1)*#1\relax} +\permanent\def\dividenumber#1#2{\the\numexpr(#2-(#1/2))/#1\relax} %D These could be set at the \LUA\ end instead: -\edef\texenginename {\directlua{tex.print(LUATEXENGINE)}} -\edef\texengineversion {\directlua{tex.print(LUATEXVERSION)}} -\edef\texenginefunctionality{\directlua{tex.print(LUATEXFUNCTIONALITY)}} +\immutable\edef\texenginename {\directlua{tex.print(LUATEXENGINE)}} +\immutable\edef\texengineversion {\directlua{tex.print(LUATEXVERSION)}} +\immutable\edef\texenginefunctionality{\directlua{tex.print(LUATEXFUNCTIONALITY)}} %D We have no reason not to enable this: @@ -1012,12 +1007,12 @@ %D We only can set this one via directives (system.synctex) and we only support %D the context variant. This will go away completely. -\newcount\synctex \let\normalsynctex\synctex +\newcount\synctex % \let\normalsynctex\synctex %D We get rid of the funny \TEX\ offset defaults of one inch by setting them to zero. -\voffset\zeropoint \let\voffset\relax \newdimen\voffset \let\normalvoffset\voffset -\hoffset\zeropoint \let\hoffset\relax \newdimen\hoffset \let\normalhoffset\hoffset +% \voffset\zeropoint \overloaded\let\voffset\relax \newdimen\voffset \let\normalvoffset\voffset +% \hoffset\zeropoint \overloaded\let\hoffset\relax \newdimen\hoffset \let\normalhoffset\hoffset \matheqnogapstep\zerocount % for now @@ -1029,37 +1024,54 @@ \def\v_interfaces_prefix_template_system{\number \c_syst_helpers_n_of_namespaces>>} %def\v_interfaces_prefix_template_system{\characters\c_syst_helpers_n_of_namespaces>>} % no \characters yet -\protected\def\installsystemnamespace#1% +\protected\def\installsystemnamespace#1% will be redefined {\ifcsname ??#1\endcsname \immediate\write\statuswrite{fatal error: duplicate system namespace '#1'}% - \expandafter\normalend \else \global\advance\c_syst_helpers_n_of_namespaces\plusone - \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template_system}% + \immutable\expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template_system}% \fi} %D It makes more sense to have these here: -\let\normalsuperscript \Usuperscript -\let\normalsubscript \Usubscript -\let\normalnosuperscript\Unosuperscript -\let\normalnosubscript \Unosubscript -\let\normalstartimath \Ustartmath -\let\normalstopimath \Ustopmath -\let\normalstartdmath \Ustartdisplaymath -\let\normalstopdmath \Ustopdisplaymath +\aliased\let\normalsuperscript \Usuperscript +\aliased\let\normalsubscript \Usubscript +\aliased\let\normalnosuperscript\Unosuperscript +\aliased\let\normalnosubscript \Unosubscript +\aliased\let\normalstartimath \Ustartmath +\aliased\let\normalstopimath \Ustopmath +\aliased\let\normalstartdmath \Ustartdisplaymath +\aliased\let\normalstopdmath \Ustopdisplaymath %D Also better here: -\def\wildcardsymbol{*} +\immutable\def\wildcardsymbol{*} %D For a while we will keep these useless numbers as for instance tikz checks for them: -\frozen\chardef\eTeXversion 2 -\frozen\def \eTeXrevision {2} +\immutable\integerdef\eTeXversion 2 +\immutable\def \eTeXrevision {2} %D Experiment: \glyphdimensionsmode\plusone +%D Just in case users use this: + +\aliased\let\immediateassign \immediate +\aliased\let\immediateassigned\localcontrolled + +%D Needed: + +\mutable\let\nexttoken \relax +\mutable\let\next \relax +\mutable\let\nextnext \relax +\mutable\let\nextnextnext\relax + +%D For now here: will get a proper solution + +\pushoverloadmode +\mutable\let\par\par +\popoverloadmode + \protect \endinput diff --git a/tex/context/base/mkiv/syst-lua.lmt b/tex/context/base/mkiv/syst-lua.lmt index b1735d44e..673c99ae3 100644 --- a/tex/context/base/mkiv/syst-lua.lmt +++ b/tex/context/base/mkiv/syst-lua.lmt @@ -41,10 +41,6 @@ local char_given_code = cmd.char_given local math_given_code = cmd.math_given local xmath_given_code = cmd.xmath_given local some_item_code = cmd.some_item ------ call_code = cmd.call ------ the_code = cmd.the ------ convert_code = cmd.convert ------ lua_expandable_call_code = cmd.lua_expandable_call local getdimen = tex.getdimen local getglue = tex.getglue @@ -410,13 +406,28 @@ do end, } + local boolean_value = tokens.values.boolean + implement { name = "ifeof", public = true, usage = "condition", - actions = function(prefix) + actions = function() local n = scaninteger() - return tokens.values.boolean, not channels[n] + return boolean_value, not channels[n] + end, + } + + -- for the moment here: + + local getnest = tex.getnest + + implement { + name = "ifmvl", + public = true, + usage = "condition", + actions = function() + return boolean_value, getnest("ptr") == 0 end, } diff --git a/tex/context/base/mkiv/syst-lua.mkiv b/tex/context/base/mkiv/syst-lua.mkiv index 6ad8f5a99..f0902eaf5 100644 --- a/tex/context/base/mkiv/syst-lua.mkiv +++ b/tex/context/base/mkiv/syst-lua.mkiv @@ -57,8 +57,8 @@ \def\expdoifelsecommon#1#2{\clf_doifelsecommon{#1}{#2}} \def\expdoifelseinset #1#2{\clf_doifelseinset {#1}{#2}} -\def\expdoifcommonelse\expdoifelsecommon -\def\expdoifinsetelse \expdoifelseinset +\let\expdoifcommonelse\expdoifelsecommon +\let\expdoifinsetelse \expdoifelseinset %D We define these here, just in case. This permits \typefile {self} otherwise %D nested b|/|e sep problems. diff --git a/tex/context/base/mkiv/syst-lua.mkxl b/tex/context/base/mkiv/syst-lua.mkxl index d04e78392..615562200 100644 --- a/tex/context/base/mkiv/syst-lua.mkxl +++ b/tex/context/base/mkiv/syst-lua.mkxl @@ -15,48 +15,48 @@ \unprotect -\def\expdoifelse#1#2{\clf_doifelsesame{#1}{#2}} -\def\expdoif #1#2{\clf_doifsame {#1}{#2}} -\def\expdoifnot #1#2{\clf_doifnotsame {#1}{#2}} +\permanent\def\expdoifelse#1#2{\clf_doifelsesame{#1}{#2}} +\permanent\def\expdoif #1#2{\clf_doifsame {#1}{#2}} +\permanent\def\expdoifnot #1#2{\clf_doifnotsame {#1}{#2}} %D Here is variant using a brainwave of the 12\high{+} hour \quotation {Long Road %D Out of Eden}\footnote {Eden being Backo\TeX\ 2018, where the virtues of the \type %D {\expanded} primitive were mentioned in talks.} trip. For now I don't really see %D other useful applications. -\def\expandeddoifelse#1#2{\iftok{#1}{#2}\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} -\def\expandeddoif #1#2{\iftok{#1}{#2}\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi} -\def\expandeddoifnot #1#2{\iftok{#1}{#2}\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \fi} +\permanent\def\expandeddoifelse#1#2{\iftok{#1}{#2}\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} +\permanent\def\expandeddoif #1#2{\iftok{#1}{#2}\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi} +\permanent\def\expandeddoifnot #1#2{\iftok{#1}{#2}\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \fi} % \testfeatureonce{100000}{\doifelse{hello world}{here i am}{}} % 0.3 % \testfeatureonce{100000}{\expandabledoifelse{hello world}{here i am}{}} % 1.5 -\def\expdoifelsecommon#1#2{\clf_doifelsecommon{#1}{#2}} -\def\expdoifelseinset #1#2{\clf_doifelseinset {#1}{#2}} +\permanent\def\expdoifelsecommon#1#2{\clf_doifelsecommon{#1}{#2}} +\permanent\def\expdoifelseinset #1#2{\clf_doifelseinset {#1}{#2}} -\def\expdoifcommonelse\expdoifelsecommon -\def\expdoifinsetelse \expdoifelseinset +\aliased\let\expdoifcommonelse\expdoifelsecommon +\aliased\let\expdoifinsetelse \expdoifelseinset %D We define these here, just in case. This permits \typefile {self} otherwise %D nested b|/|e sep problems. -\def\luastringsep{===} +\immutable\def\luastringsep{===} -\edef\!!bs{[\luastringsep[} -\edef\!!es{]\luastringsep]} +\immutable\edef\!!bs{[\luastringsep[} +\immutable\edef\!!es{]\luastringsep]} -\protected\def\writestatus#1#2{\clf_writestatus{#1}{#2}} +\permanent\overloaded\protected\def\writestatus#1#2{\clf_writestatus{#1}{#2}} %D We can omit the tex.ctxcatcodes here as nowadays we seldom change the regime at %D the \TEX\ end: %def\luaexpr#1{\ctxlua{context (tostring(#1))}} % more efficient: -\def\luaexpr#1{\ctxlua{tex.print(tostring(#1))}} % no use is shortcutting has to be compiled +\permanent\def\luaexpr#1{\ctxlua{tex.print(tostring(#1))}} % no use is shortcutting has to be compiled %D But as we only use write 16 we could as well do all in \LUA\ and ignore the rest. %D Okay, we still can do writes here but only when not blocked. -\let\syst_write_execute\clf_execute % always {...} +\aliased\let\syst_write_execute\clf_execute % always {...} %D There is a probably rather useless \type {\expression} command that can mix \LUA\ numeric %D expressions with \TEX\ commands (for as far that makes sense) that works like this: diff --git a/tex/context/base/mkiv/syst-mac.lmt b/tex/context/base/mkiv/syst-mac.lmt index 6fc8df2a4..410a49f8b 100644 --- a/tex/context/base/mkiv/syst-mac.lmt +++ b/tex/context/base/mkiv/syst-mac.lmt @@ -35,7 +35,7 @@ local function pushmacro(name,global) if s then insert(stack[name],s) else - report("no macro %a",name) + report("no macro %a to push",name) insert(stack[name],false) end end @@ -45,7 +45,7 @@ local function popmacro(name) if s then pop_macro(s) else - -- error + report("no macro %a to pop",name) end end diff --git a/tex/context/base/mkiv/syst-mes.mkiv b/tex/context/base/mkiv/syst-mes.mkiv index cf9da21de..ff7ab1ce3 100644 --- a/tex/context/base/mkiv/syst-mes.mkiv +++ b/tex/context/base/mkiv/syst-mes.mkiv @@ -11,8 +11,8 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\protected\def\writestring {\immediate\write\statuswrite} -\protected\def\writeline {\writestring{}} - \let\message \normalmessage +\protected\def\writestring{\immediate\write\statuswrite} +\protected\def\writeline {\writestring{}} +% \let\message \normalmessage \endinput diff --git a/tex/context/base/mkiv/tabl-com.mkxl b/tex/context/base/mkiv/tabl-com.mkxl new file mode 100644 index 000000000..c6a0c14bc --- /dev/null +++ b/tex/context/base/mkiv/tabl-com.mkxl @@ -0,0 +1,69 @@ +%D \module +%D [ file=tabl-com, +%D version=2009.08.22, +%D title=\CONTEXT\ Table Macros, +%D subtitle=Common Code, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Table Macros / Common Code} + +\unprotect + +\pushoverloadmode + +\permanent\let\AR\relax +\permanent\let\BA\relax +\permanent\let\BC\relax +\permanent\let\BL\relax +\permanent\let\CC\relax +\permanent\let\CL\relax +\permanent\let\CM\relax +\permanent\let\CR\relax +\permanent\let\DB\relax +\permanent\let\EQ\relax +\permanent\let\FB\relax +\permanent\let\FL\relax +\permanent\let\FR\relax +\permanent\let\HC\relax +\permanent\let\HL\relax +\permanent\let\HQ\relax +\permanent\let\HR\relax +\permanent\let\LB\relax +\permanent\let\LL\relax +\permanent\let\LR\relax +\permanent\let\ML\relax +\permanent\let\MR\relax +\permanent\let\NA\relax +\permanent\let\NB\relax +\permanent\let\NC\relax +\permanent\let\ND\relax +\permanent\let\NF\relax +\permanent\let\NG\relax +\permanent\let\NI\relax +\permanent\let\NL\relax +\permanent\let\NN\relax +\permanent\let\NP\relax +\permanent\let\NR\relax +\permanent\let\PB\relax +\permanent\let\RC\relax +\permanent\let\RQ\relax +\permanent\let\SR\relax +\permanent\let\TL\relax +\permanent\let\VL\relax + +\popoverloadmode + +\installmacrostack\BC +\installmacrostack\EC +\installmacrostack\EQ +\installmacrostack\NC +\installmacrostack\NN +\installmacrostack\NR + +\protect \endinput diff --git a/tex/context/base/mkiv/tabl-frm.mkxl b/tex/context/base/mkiv/tabl-frm.mkxl new file mode 100644 index 000000000..5cafec76a --- /dev/null +++ b/tex/context/base/mkiv/tabl-frm.mkxl @@ -0,0 +1,261 @@ +%D \module +%D [ file=tabl-frm, +%D version=2017.04.11, +%D title=\CONTEXT\ Table Macros, +%D subtitle=Framed Tables, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D For Thomas Schmitz who needed 3000 pages long tables. + +\unprotect + +\writestatus{loading}{ConTeXt Table Macros / Framed Tables} + +\installcorenamespace{framedtable} +\installcorenamespace{framedtablerow} +\installcorenamespace{framedtablecolumn} + +\newcount\c_tabl_framed_c +\newcount\c_tabl_framed_r +\newdimen\d_tabl_framed_h +\newdimen\d_tabl_framed_d +\newdimen\b_tabl_framed + +\initializeboxstack\??framedtable + +\defineframed[\??framedtable] +\defineframed[\??framedtablerow][\??framedtable] +\defineframed[\??framedtablecolumn][\??framedtable] + +\setupframed + [\??framedtable] + [\c!distance=\zeropoint, + \c!before=, + \c!after=, + \c!inbetween=] + +\setupframed + [\??framedtablerow] + [\c!strut=\v!no, + \c!offset=\v!overlay] + +% \defineframedtable[foo] +% \defineframedtable[bar][foo] + +\permanent\tolerant\protected\def\defineframedtable[#1]#*[#2]% + {\ifarguments\or + \defineframed[\??framedtable#1][\??framedtable]% + \or + \defineframed[\??framedtable#1][\??framedtable#2]% + \fi} + +% \setupframedtable[foo][...] + +\permanent\tolerant\protected\def\setupframedtable[#1]#*[#2]% + {\ifarguments\or + \setupframed[\??framedtable][#1]% + \or + \ifcsname\??framed:\??framedtable#1\endcsname \else + \defineframed[\??framedtable#1][\??framedtable]% + \fi + \setupframed[\??framedtable#1][#2]% + \fi} + +% \setupframedtable[1][...] +% \setupframedtable[foo][1][...] + +\permanent\tolerant\protected\def\setupframedtablerow[#1]#*[#2]#*[#3]% + {\ifarguments\or\or + \ifcsname\??framed:\??framedtablerow:#1\endcsname \else + \defineframed[\??framedtablerow:#1][\??framedtable]% + \fi + \setupframed[\??framedtablerow:#1][#2]% + \or + \ifcsname\??framed:\??framedtable#1\endcsname \else + \defineframed[\??framedtable#1][\??framedtable]% + \fi + \ifcsname\??framed:\??framedtablerow#1:#2\endcsname \else + \defineframed[\??framedtablerow#1:#2][\??framedtable#1]% + \fi + \setupframed[\??framedtablerow#1:#2][#3]% + \fi} + +\permanent\tolerant\protected\def\setupframedtablecolumn[#1]#*[#2]#*[#3]% + {\ifarguments\or\or + \ifcsname\??framed:\??framedtablecolumn:#1\endcsname \else + \defineframed[\??framedtablecolumn:#1][\??framedtable]% + \fi + \setupframed[\??framedtablecolumn:#1][#2]% + \or + \ifcsname\??framed:\??framedtable#1\endcsname \else + \defineframed[\??framedtable#1][\??framedtable]% + \fi + \ifcsname\??framed:\??framedtablecolumn#1:#2\endcsname \else + \defineframed[\??framedtablecolumn#1:#2][\??framedtable#1]% + \fi + \setupframed[\??framedtablecolumn#1:#2][#3]% + \fi} + +\permanent\tolerant\protected\def\startframedtable[#1]#*[#2]% + {\begingroup + \forgetall + \ifhastok={#1}% + \let\currentframedtable\empty + \setupframed[\??framedtable][#1]% + \else + \edef\currentframedtable{#1}% + \setupframed[\??framedtable][#2]% + \fi + \edef\currentframed{\??framedtable\currentframedtable}% + \c_tabl_framed_r\zerocount + \d_tabl_framed_d\framedparameter\c!distance + \framedparameter\c!before} + +\permanent\protected\def\stopframedtable + {\framedparameter\c!after + \endgroup} + +% a two pass variant that deals with the height .. so no catcode changes here + +\tolerant\protected\def\pack_framed_start_framed_whatever[#1]% + {\pack_framed_initialize + \bgroup + \setupcurrentframed[#1]% here ! + \pack_framed_process_indeed + \bgroup + \ignorespaces} + +% \permanent\protected\def\startframedrow +% {\advance\c_tabl_framed_r\plusone +% \c_tabl_framed_c\zerocount +% \d_tabl_framed_h\zeropoint +% \bgroup +% \edef\currentframed{\number\c_tabl_framed_r}% +% \edef\currentframed +% {\??framedtablerow\currentframedtable +% \ifcsname\??framedtablerow\currentframedtable:\currentframed\endcsname +% :\currentframed +% \else\ifcsname\??framedtablerow\currentframedtable:\v!each\endcsname +% :\v!each +% \fi\fi}% +% \pack_framed_start_framed_whatever} +% +% \permanent\protected\def\stopframedrow +% {\dofastloopcs\c_tabl_framed_c\tabl_framed_flush_row +% \stopframed +% \nointerlineskip +% \vskip\zeropoint\relax +% \framedparameter\c!inbetween} + +\protected\def\tabl_framed_flush_row + {\vpack to \d_tabl_framed_h{\flushbox\??framedtable{\number\fastloopindex}\vfill}% + \ifzeropt\d_tabl_framed_d\else\kern\d_tabl_framed_d\fi} + +\newcount\c_tabl_framed_pass + +\permanent\let\stopframedrow\relax + +\permanent\protected\def\startframedrow#1\stopframedrow + {\advance\c_tabl_framed_r\plusone + \startframedrow_one#1\stopframedrow_one + \startframedrow_two#1\stopframedrow_two} + +\tolerant\def\startframedrow_one[#-]% + {\bgroup + \c_tabl_framed_pass\plusone + \c_tabl_framed_c\zerocount + \d_tabl_framed_h\zeropoint + \settrialtypesetting} + +\protected\def\stopframedrow_one + {\normalexpanded{\egroup\d_tabl_framed_h\the\d_tabl_framed_h\relax}} + +\def\startframedrow_two + {\bgroup + \c_tabl_framed_c\zerocount + \c_tabl_framed_pass\plustwo + \edef\currentframed{\number\c_tabl_framed_r}% + \edef\currentframed + {\??framedtablerow\currentframedtable + \ifcsname\??framedtablerow\currentframedtable:\currentframed\endcsname + :\currentframed + \else\ifcsname\??framedtablerow\currentframedtable:\v!each\endcsname + :\v!each + \fi\fi}% + \pack_framed_start_framed_whatever} + +\protected\def\stopframedrow_two + {\dofastloopcs\c_tabl_framed_c\tabl_framed_flush_row + \stopframed + \nointerlineskip + \vskip\zeropoint\relax + \framedparameter\c!inbetween} + +\protected\def\tabl_framed_flush_row_two + {\vpack to \d_tabl_framed_h{\flushbox\??framedtable{\number\fastloopindex}\vfill}% + \ifzeropt\d_tabl_framed_d\else\kern\d_tabl_framed_d\fi} + +\permanent\protected\def\startframedcell + {\advance\c_tabl_framed_c\plusone + \setbox\b_tabl_framed\hpack\bgroup + %\bgroup + \edef\currentframed{\number\c_tabl_framed_c}% + \edef\currentframed + {\??framedtablecolumn\currentframedtable + \ifcsname\??framedtablecolumn\currentframedtable:\currentframed\endcsname + :\currentframed + \else\ifcsname\??framedtablecolumn\currentframedtable:\v!each\endcsname + :\v!each + \fi\fi}% + \ifcase\c_tabl_framed_pass + \or + \letframedparameter\c!background\empty + \letframedparameter\c!frame\v!off + \or + \letframedparameter\c!height\d_tabl_framed_h + \fi + \pack_framed_start_framed_whatever} + +\permanent\protected\def\stopframedcell + {\stopframed + %\egroup + \ifcase\c_tabl_framed_pass + \or + \ifdim\ht\b_tabl_framed>\d_tabl_framed_h + \d_tabl_framed_h\ht\b_tabl_framed + \fi + \else + \savebox\??framedtable{\number\c_tabl_framed_c}{\box\b_tabl_framed}% + \fi} + +\protect \endinput + +\starttext + +\setupframedtablecolumn [1] [width=3cm,background=color,backgroundcolor=red] +\setupframedtablecolumn [2] [width=4cm,background=color,backgroundcolor=green,align=normal] +% \setupframedtablerow [each] [background=color,backgroundcolor=blue,strut=no] +% \setupframedtablerow [each] [strut=no,offset=overlay] + +\startframedtable[inbetween=\kern-0.4pt,distance=-0.4pt] + +\testfeatureonce{10000}{ +% \testfeatureonce{10}{ + \startframedrow + \startframedcell%[backgroundcolor=yellow] + test + \stopframedcell + \startframedcell + test \par test + \stopframedcell + \stopframedrow +} +\stopframedtable + +\stoptext diff --git a/tex/context/base/mkiv/tabl-ltb.mkxl b/tex/context/base/mkiv/tabl-ltb.mkxl new file mode 100644 index 000000000..b72c5c7d6 --- /dev/null +++ b/tex/context/base/mkiv/tabl-ltb.mkxl @@ -0,0 +1,813 @@ +%D \module +%D [ file=tabl-ltb, +%D version=2002.10.31, % updated 2016.01.08 +%D title=\CONTEXT\ Table Macros, +%D subtitle=Line Tables, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This module was made for some special project where we needed to typeset tables +%D spanning spanning many pages horizontally and vertically, with repeated header +%D lines and (entry) columns, tab tracking, color, etc. We do two passes over a +%D table, which is why the table can go into a buffer or file. As said, tables can +%D be real huge but performance is still quite okay (there is room for some speed +%D up). The code has been adapted to \MKIV\ but the functionality is the same as in +%D \MKII. + +% \BH \BC .. \EC \BC .. \EC \EH % append +% \BR \BC .. \EC \BC .. \EC \ER +% +% or +% +% \NC .. \NC .. \NC \NR (todo: optional last \NC) + +% alternative: +% +% (1) direct run, save content in macro, but only if needed +% +% todo +% +% (2) buffered table content +% +% \startbuffer +% \startlinetablehead +% \stoplinetablehead +% \startlinetablebody +% \stoplinetablebody +% \stopbuffer +% +% \processlinetablebuffer[buffer] +% +% in buffer : head and body +% +% (3) unbuffered run, multipass +% +% - run with starting width zero / prev run +% - clip on prev run +% - flush real widths + +\writestatus{loading}{ConTeXt Table Macros / Line Tables} + +\unprotect + +\installcorenamespace{linetable} +\installcorenamespace{linetablepart} +\installcorenamespace{linetablewidth} +\installcorenamespace{linetableheight} +\installcorenamespace{linetabledepth} + +\newconditional \c_tabl_lines_preroll +\newconditional \c_tabl_lines_in_table + +\newdimen \d_tabl_lines_width +\newdimen \d_tabl_lines_height +%newdimen \d_tabl_lines_depth + +\newbox \b_tabl_lines_cell + +\newcount \c_tabl_lines_n_of_columns +\newcount \c_tabl_lines_n_of_rows +\newcount \c_tabl_lines_n_of_lines +\newcount \c_tabl_lines_n_of_parts +\newcount \c_tabl_lines_part \c_tabl_lines_part\plusone +\newcount \c_tabl_lines_step \c_tabl_lines_step\plusone +\newcount \c_tabl_lines_line +\newcount \c_tabl_lines_row +\newcount \c_tabl_lines_rows +\newcount \c_tabl_lines_column +\newcount \c_tabl_lines_subcol + +\newconstant \c_tabl_lines_hmode +\newconstant \c_tabl_lines_page +\newconstant \c_tabl_lines_repeat +\newconstant \c_tabl_lines_split_state +\newconstant \c_tabl_lines_head_state +\newconstant \c_tabl_lines_mode + +\newtoks \t_tabl_lines_head + +\newconditional \linetableautoheight \settrue\linetableautoheight + +\initializetablebox\zerocount % holds repeater + +\pushoverloadmode + +\permanent\tolerant\protected\def\setuplinetable[#1]#*[#2]#*[#3]% + {\ifarguments\or + \getparameters[\??linetable][#1]% + \or + \getparameters[\??linetable#1:][#2]% + \or + \getparameters[\??linetable#1:#2][#3]% + \fi} + +\permanent\def\linetableparameter#1% + {\begincsname\??linetable#1\endcsname} + +\permanent\protected\def\doifelselinetablecparameter#1% + {\ifcsname\??linetable c:\number\c_tabl_lines_column#1\endcsname + \expandafter\firstoftwoarguments + \else\ifcsname\??linetable c:#1\endcsname + \doubleexpandafter\firstoftwoarguments + \else + \doubleexpandafter\secondoftwoarguments + \fi\fi} + +\aliased\let\doiflinetablecparameterelse\doifelselinetablecparameter + +\permanent\def\linetablecparameter#1% + {\begincsname + \??linetable + \ifcsname\??linetable c:\number\c_tabl_lines_column#1\endcsname + c:\number\c_tabl_lines_column + \else\ifcsname\??linetable c:#1\endcsname + c:% + \fi\fi + #1% + \endcsname} + +\permanent\def\linetablerparameter#1% faster, leaner and meaner + {\begincsname + \??linetable + \ifnum\c_tabl_lines_row=\zerocount % geen ifcase + \ifcsname\??linetable r:\v!header#1\endcsname + r:\v!header + \else\ifcsname\??linetable r:0#1\endcsname + r:0% + \fi\fi + \else + \ifcsname\??linetable r:\number\c_tabl_lines_row#1\endcsname + r:\number\c_tabl_lines_row + \else\ifcsname\??linetable r:\v!oddeven\c_tabl_lines_row#1\endcsname + r:\v!oddeven\c_tabl_lines_row + \fi\fi + \fi + #1% + \endcsname} + +\protected\def\tabl_lines_set + {\edef\p_lines{\linetableparameter\c!lines}% + \ifx\p_lines\v!fit + \tabl_lines_set_indeed + \else + \global\c_tabl_lines_n_of_lines\p_lines + \fi} + +\protected\def\tabl_lines_set_indeed + {% whitespace already added by vertical strut + %\triggerpagebuilder + \scratchdimen + \ifdim\pagegoal<\maxdimen + \dimexpr\pagegoal-\pagetotal\relax + \else + \textheight + \fi + \getrawnoflines\scratchdimen + \global\c_tabl_lines_n_of_lines\noflines + \ifconditional\c_tabl_lines_preroll \else \ifnum\c_tabl_lines_n_of_lines<\plustwo + \page + \tabl_lines_set + \fi \fi} + +\def\tabl_lines_step_cell + {\advance\scratchdimen\linetablecparameter\c!width + \global\advance \c_tabl_lines_column\plusone + \advance\scratchskip \linetablecparameter\c!distance} + +\permanent\tolerant\protected\def\startlinetablecell[#1]% + {\global\setbox\b_tabl_lines_cell\hbox\bgroup + \ifparameter#1\or + \getparameters[\??linetable c:\number\c_tabl_lines_column][#1]% + \fi + \global\c_tabl_lines_step\linetablecparameter\c!nx\relax + \ifcase\c_tabl_lines_step\or + \scratchdimen\linetablecparameter\c!width + \scratchskip \linetablecparameter\c!distance + \else + \scratchdimen \zeropoint + \scratchskip \zeropoint + \scratchcounter\c_tabl_lines_column + \dorecurse\c_tabl_lines_step\tabl_lines_step_cell + \global\c_tabl_lines_column\scratchcounter + \fi + \c_tabl_lines_mode + \ifconditional\c_tabl_lines_preroll + \ifdim\scratchdimen>\zeropoint \zerocount \else \plustwo \fi + \else + \zerocount + \fi + \ifcase\c_tabl_lines_mode + \ifcase\c_tabl_lines_hmode + % nothing + \or + % fit, keep it simple + \or + \c_tabl_lines_mode\plusone % line + \else + % some already calculated height + \fi + \fi + \setbox\scratchbox\hbox + \bgroup + \dontcomplain + \hskip\linetablecparameter\c!leftoffset\relax + % 0 = width, unknown height + % 1 = width, fixed height + % 2 = no width, auto hsize + \ifnum\c_tabl_lines_mode<\plustwo + \advance\scratchdimen-\linetablecparameter\c!leftoffset + \advance\scratchdimen-\linetablecparameter\c!rightoffset + \fi + \ifcase\c_tabl_lines_mode + \dosetraggedcommand{\linetablecparameter\c!align}% + \vtop \ifdim\d_tabl_lines_height>\zeropoint to\d_tabl_lines_height \fi \bgroup + \hsize\scratchdimen + \raggedcommand + \else + \setalignmentswitch{\linetablecparameter\c!align}% + \hbox \ifcase\c_tabl_lines_mode \or to\scratchdimen \fi \bgroup + \ifcase\alignmentswitch\hss\or\hss\fi + \fi + \dousestyleparameter{\linetablecparameter\c!style}% + \dousecolorparameter{\linetablecparameter\c!color}% + \begstrut \ignorespaces} + +\permanent\protected\def\stoplinetablecell + {\unskip \endstrut + \ifcase\c_tabl_lines_mode + \endgraf + \else + \ifcase\alignmentswitch\else\hss\fi + \fi + \egroup + \hskip\linetablecparameter\c!rightoffset + \egroup + \ifconditional\c_tabl_lines_preroll + \box\scratchbox + \else + \tabl_lines_wrap_up + \fi + \egroup} + +\def\tabl_lines_wrap_up + {\edef\p_background{\linetablecparameter\c!background}% + \ifx\p_background\v!color + \ifconditional\linetableautoheight + \tabl_lines_wrap_up_auto + \else + \tabl_lines_wrap_up_line + \fi + \else + \box\scratchbox + \fi} + +% \startuseMPgraphic{one} +% path p, q ; +% numeric r ; +% r := RuleThickness ; +% p := unitsquare xysized(RuleWidth,RuleHeight+RuleDepth) ; +% q := p topenlarged -r bottomenlarged -r ; +% draw q ; +% setbounds currentpicture to p; +% \stopuseMPgraphic +% +% \setuplinetable[r][odd] [type=mp,mp=one,backgroundcolor=gray,rulethickness=1pt] +% \setuplinetable[r][even][type=mp,mp=one,backgroundcolor=green,rulethickness=1pt] +% +% \startlinetable +% \dorecurse{10}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR} +% \stoplinetable + +\def\tabl_lines_wrap_up_auto + {\edef\p_height{\linetablerparameter{x\c!height}}% + \edef\p_depth {\linetablerparameter{x\c!depth }}% + \hpack + {\blackrule + [ \c!color=\linetablecparameter\c!backgroundcolor, + \c!type=\linetablecparameter\c!type, + \c!mp=\linetablecparameter\c!mp, + \c!rulethickness=\linetablecparameter\c!rulethickness, + \c!height=\ifx\p_height\empty\ht\scratchbox\else\p_height\fi, + \c!depth=\ifx\p_depth \empty\dp\scratchbox\else\p_depth \fi, + \c!width=\wd\scratchbox]% + \hskip-\wd\scratchbox\box\scratchbox}} + +\def\tabl_lines_wrap_up_auto_r + {\hpack + {\blackrule + [ \c!color=\linetablerparameter\c!backgroundcolor, + \c!type=\linetablerparameter\c!type, + \c!mp=\linetablerparameter\c!mp, + \c!rulethickness=\linetablerparameter\c!rulethickness, + \c!height=\ht\scratchbox, + \c!depth=\dp\scratchbox, + \c!width=\wd\scratchbox]% + \hskip-\wd\scratchbox\box\scratchbox}} + +\def\tabl_lines_wrap_up_line + {\backgroundline[\linetablecparameter\c!backgroundcolor]{\box\scratchbox}} + +\def\tabl_lines_save_part + {\global\setbox\tablebox\c_tabl_lines_part + \ifcase\c_tabl_lines_part\relax + \box\scratchbox % just storing + \else + \vbox + {\ifvoid\tablebox\c_tabl_lines_part\else\unvbox\tablebox\c_tabl_lines_part\fi + \edef\p_background{\linetablerparameter\c!background}% + \ifx\p_background\v!color + \backgroundline[\linetablerparameter\c!backgroundcolor]{\box\scratchbox}% + \else + \edef\p_type{\linetablerparameter\c!type}% + \ifx\p_type\empty + \box\scratchbox + \else + \tabl_lines_wrap_up_auto_r + \fi + \fi + \endgraf + \linetablerparameter\c!after}% + \fi} + +\def\tabl_lines_flush_parts + {\global\advance\c_tabl_lines_line\plusone + \ifnum\c_tabl_lines_line<\c_tabl_lines_n_of_lines + % keep collecting + \else + \ifconditional\c_tabl_lines_preroll + % forget about them + \else + \dorecurse\c_tabl_lines_n_of_parts + {\c_tabl_lines_part\recurselevel + \dp\tablebox\c_tabl_lines_part\strutdepth + % noindent en endgraf needed else whitespace mess-up! + \whitespace % here not after verticalstrut + \ifdim\topskipgap=\zeropoint\else + \verticalstrut + \nobreak + \kern-\struttotal + \kern-\parskip + \nobreak + \nointerlineskip % fix topskip + \fi + \noindent\strut + \hpack to \hsize{\box\tablebox\c_tabl_lines_part\hss}% + \endgraf + \ifnum\c_tabl_lines_part<\c_tabl_lines_n_of_parts\relax + \linetableparameter\c!inbetween + \fi}% + \ifnum\c_tabl_lines_rows<\c_tabl_lines_n_of_rows + \linetableparameter\c!inbetween + \else + % after, later + \fi + \c_tabl_lines_head_state\plusthree + \global\setbox\tablebox\zerocount\emptybox % here + \fi + % reset \c_tabl_lines_row will be an option, currently + % starts at zero after split + \global\c_tabl_lines_row\zerocount + \global\c_tabl_lines_line\zerocount + \global\c_tabl_lines_page\zerocount + \global\d_tabl_lines_width\zeropoint + \tabl_lines_set + \fi} + +\def\tabl_lines_start_part + {\global\c_tabl_lines_subcol\zerocount + \setbox\scratchbox\hbox\bgroup + \dousestyleparameter{\linetablerparameter\c!style}% + \dousecolorparameter{\linetablerparameter\c!color}% + \ignorespaces} + +\def\tabl_lines_stop_part + {\ifnum\c_tabl_lines_part>\zerocount + \unskip \unskip % remove last intercolumn skip (distance+fill) + \fi + \egroup + \ifconditional\c_tabl_lines_preroll \else + \ifcase\c_tabl_lines_part + % we're collecting the repeater + \else + \ifdim\dimexpr\hsize-\wd\scratchbox\relax>\linetableparameter\c!stretch\else + \setbox\scratchbox\hpack to \hsize{\unhbox\scratchbox}% + \fi + \fi + \fi} + +\def\tabl_lines_check_part + {\global\advance\d_tabl_lines_width\wd\b_tabl_lines_cell + \global\advance\c_tabl_lines_column\c_tabl_lines_step + \global\advance\c_tabl_lines_subcol\c_tabl_lines_step + \relax + %\message{\the\c_tabl_lines_column,\the\c_tabl_lines_subcol}\wait + % from now on the column counter is already incremented + \ifcase\c_tabl_lines_split_state + \ifconditional\c_tabl_lines_preroll \else + \box\b_tabl_lines_cell + % the columncounter is one ahead ! + \hskip\scratchskip + \fi + %%% + \donefalse + \ifcase\c_tabl_lines_repeat\else + % calculate ahead + \ifnum\c_tabl_lines_repeat=\numexpr\c_tabl_lines_column-\plustwo\relax + \donetrue % collecting repeater + \fi + \fi + %%%% + \ifdone + % collecting repeater + \else + \ifnum\c_tabl_lines_column>\csname\??linetablepart\number\c_tabl_lines_part\endcsname\relax + \donetrue + \fi + \fi + \ifdone + \tabl_lines_stop_part + \ifconditional\c_tabl_lines_preroll \else + \tabl_lines_save_part + \fi + \ifcase\c_tabl_lines_page \or + \global\c_tabl_lines_page \plustwo + \else + \global\c_tabl_lines_page \plusone + \fi + \global\advance\c_tabl_lines_part\plusone + \global\d_tabl_lines_width\wd\tablebox\zerocount + \tabl_lines_start_part + \fi + \else + \donefalse + \!!doneafalse + \ifcase\c_tabl_lines_repeat\else + % calculate ahead + \ifnum\c_tabl_lines_repeat=\numexpr\c_tabl_lines_column-\plustwo\relax + \donetrue % collecting repeater + \fi + \fi + \ifdone + \!!doneatrue + % collecting repeater + \orelse\ifdim\d_tabl_lines_width>\hsize + \donetrue + \else + \global\advance\d_tabl_lines_width\scratchskip + \ifdim\d_tabl_lines_width>\hsize % ? + \donetrue + \fi + \fi + \ifdone + \tabl_lines_stop_part + \tabl_lines_save_part + \ifcase\c_tabl_lines_page \or + \global\c_tabl_lines_page \plustwo + \else + \global\c_tabl_lines_page \plusone + \fi + \global\advance\c_tabl_lines_part\plusone + \ifnum\c_tabl_lines_part>\c_tabl_lines_n_of_parts + \global\c_tabl_lines_n_of_parts\c_tabl_lines_part + \initializetablebox\c_tabl_lines_part + \fi + \global\d_tabl_lines_width\wd\b_tabl_lines_cell + \tabl_lines_start_part + \if!!doneb \else \ifcase\c_tabl_lines_repeat \else + % check for left/right page + \ifcase\c_tabl_lines_page\donetrue\or\donetrue\or\donefalse\fi\ifdone + % insert repeater + \global\advance\d_tabl_lines_width\wd\tablebox\zerocount + \ifconditional\c_tabl_lines_preroll\kern\wd\else\unhcopy\fi\tablebox\zerocount + \fi + \fi \fi + \fi + \ifconditional\c_tabl_lines_preroll \else + \box\b_tabl_lines_cell + % the columncounter is one ahead ! + %\dorecurse\c_tabl_lines_step{\strut\hfil}% + \strut + \hskip\scratchskip + \fi + \fi} + +\permanent\protected\def\startlinetablerun % to do: quit when nested + {\bgroup + \dontcomplain + \settrue\c_tabl_lines_in_table + % autowidth + \doif{\linetableparameter\c!maxwidth}\v!fit + {\setuplinetable[\c!maxwidth=\zeropoint]}% + \processaction + [\linetableparameter\c!stretch] + [ \v!no=>{\setuplinetable[\c!stretch=\maxdimen]},% no stretch + \v!yes=>{\setuplinetable[\c!stretch=\zeropoint]}]% max stretch + \c_tabl_lines_repeat\linetableparameter\c!nleft + \c_tabl_lines_split_state % = + \ifdim\linetableparameter\c!maxwidth>\zeropoint + \zerocount \else \plusone + \fi + % optional prevdepth correction + \ifconditional\c_tabl_lines_preroll + \global\c_tabl_lines_n_of_rows\zerocount + \else + \linetableparameter\c!before + \fi + \global\c_tabl_lines_rows\zerocount + \global\c_tabl_lines_n_of_columns\zerocount + \global\c_tabl_lines_n_of_parts\zerocount + \scratchcounter\zerocount + \def\docommand##1% + {\global\advance\c_tabl_lines_n_of_parts\plusone + \advance\scratchcounter##1% + \setxvalue{\??linetablepart\number\c_tabl_lines_n_of_parts}{\the\scratchcounter}}% + \processcommacommand[\linetableparameter\c!n]\docommand + \initializetableboxes\c_tabl_lines_n_of_parts + \global\c_tabl_lines_part\ifcase\c_tabl_lines_repeat\plusone\else\zerocount\fi % repeater + \global\c_tabl_lines_step\plusone + \global\c_tabl_lines_line\zerocount + \global\c_tabl_lines_row \zerocount + \global\c_tabl_lines_column\zerocount + \global\c_tabl_lines_subcol\zerocount + \global\d_tabl_lines_width\zeropoint + \ifconditional\c_tabl_lines_preroll \else \ifdim\pagetotal>\zeropoint + \verticalstrut\kern-\struttotal + \fi \fi + \tabl_lines_set + \tabl_lines_check_page + \enforced\let\BR\tabl_lines_BR + \enforced\let\ER\tabl_lines_ER + \enforced\let\BH\tabl_lines_BR + \enforced\let\EH\tabl_lines_ER + \enforced\let\BC\tabl_lines_BC + \enforced\let\EC\tabl_lines_EC + \enforced\let\NC\tabl_lines_NC + \enforced\let\NR\tabl_lines_NR + \tabl_lines_flush_head} + +\permanent\protected\def\stoplinetablerun + {\global\c_tabl_lines_line\maxcard + \c_tabl_lines_head_state\zerocount % blocked + \tabl_lines_flush_parts + \ifconditional\c_tabl_lines_preroll \else + \linetableparameter\c!after + \fi + \global\c_tabl_lines_part\zerocount + \global\c_tabl_lines_n_of_parts\zerocount + \egroup} + +\permanent\def\checklinecolumndimension#1#2#3% + {\expandafter\xdef\csname#1\number#3\endcsname + {\expandafter\ifx\csname#1\number#3\endcsname\relax + \the#2\b_tabl_lines_cell + \orelse\ifdim\csname#1\number#3\endcsname<#2\b_tabl_lines_cell + \the#2\b_tabl_lines_cell + \else + \csname#1\number#3\endcsname + \fi}} + +\def\tabl_lines_check_width {\checklinecolumndimension\??linetablewidth \wd\c_tabl_lines_column} +\def\tabl_lines_check_height{\checklinecolumndimension\??linetableheight\ht\c_tabl_lines_row} +\def\tabl_lines_check_depth {\checklinecolumndimension\??linetabledepth \dp\c_tabl_lines_row} + +\permanent\tolerant\protected\def\tabl_lines_BR[#1]% #1 not yet implemented + {\ifnum\c_tabl_lines_head_state=1\else + \global\advance\c_tabl_lines_row\plusone + \global\advance\c_tabl_lines_rows\plusone + \fi + \global\c_tabl_lines_column\plusone + \global\c_tabl_lines_subcol\plusone + \d_tabl_lines_height\zeropoint + \edef\p_height{\linetablerparameter\c!height}% + \ifx\p_height\empty + \c_tabl_lines_hmode \zerocount + \orelse\ifx\p_height\v!fit + \c_tabl_lines_hmode \plusone + \orelse\ifx\p_height\v!line + \c_tabl_lines_hmode \plustwo + \else + \d_tabl_lines_height\dimexpr\p_height-\strutdepth\relax + \fi + \tabl_lines_start_part} + +\permanent\protected\def\tabl_lines_BC + {\startlinetablecell} + +\permanent\protected\def\tabl_lines_EC + {\stoplinetablecell + \ifconditional\c_tabl_lines_preroll + \tabl_lines_check_width + \tabl_lines_check_height + \tabl_lines_check_depth + \fi + \tabl_lines_check_part} + +\permanent\protected\def\tabl_lines_ER + {% \stoplinetablecell + % no \box\b_tabl_lines_cell, i.e. dummy columnn, last \NC \NR + \tabl_lines_stop_part + \tabl_lines_save_part + \advance\c_tabl_lines_column \minusone + \ifnum\c_tabl_lines_column>\c_tabl_lines_n_of_columns + \global\c_tabl_lines_n_of_columns\c_tabl_lines_column + \fi + \tabl_lines_flush_parts + \global\c_tabl_lines_column\zerocount + \global\d_tabl_lines_width \zeropoint + \ifcase\c_tabl_lines_repeat + \global\c_tabl_lines_part\plusone + \else + \global\c_tabl_lines_part\zerocount % repeater + \fi + \tabl_lines_check_page + \tabl_lines_flush_head} + +\def\tabl_lines_check_page + {\global\c_tabl_lines_page\zerocount + \ifcase\c_tabl_lines_repeat \else \ifcase\c_tabl_lines_page + \doif{\linetableparameter\c!repeat}\v!no + {\global\c_tabl_lines_page\doifelseoddpage\plusone\plustwo}% + \fi \fi} + +\def\tabl_lines_flush_head + {\ifcase\c_tabl_lines_head_state + % 0 blocked + \or + % 1 doing head + \or + % 2 head done + \or + % 3 trigger flush + \c_tabl_lines_head_state\plusone + \the\t_tabl_lines_head\relax + \c_tabl_lines_head_state\plustwo + \fi} + +\permanent\protected\def\tabl_lines_NC % first time special treatment + {\relax + \ifcase\c_tabl_lines_column + \tabl_lines_BR + \else + \tabl_lines_EC + \fi + \tabl_lines_BC} % beware, this will result in BR BC EC BC NR + +\permanent\protected\def\tabl_lines_NR + {\stoplinetablecell % dummy + \tabl_lines_ER} + +\permanent\protected\def\startlinetable + {\startlinetablerun} + +\permanent\protected\def\stoplinetable + {\stoplinetablerun} + +\permanent\protected\def\startlinetableanalysis + {\bgroup + \settrue\c_tabl_lines_preroll + \settrialtypesetting + \startlinetablerun} + +% \protected\def\stoplinetableanalysis +% {\stoplinetablerun +% \egroup +% \global\c_tabl_lines_n_of_rows\c_tabl_lines_rows +% \dorecurse\c_tabl_lines_n_of_rows % global, from last run {\linetableparameter\c!n} +% {\setevalue{\??linetable r:\recurselevel x\c!height}{\getvalue{\??linetableheight\recurselevel}}% +% \setevalue{\??linetable r:\recurselevel x\c!depth }{\getvalue{\??linetabledepth \recurselevel}}% +% \letgvalue{\??linetableheight\recurselevel}\!!zeropoint +% \letgvalue{\??linetabledepth \recurselevel}\!!zeropoint} +% \dorecurse\c_tabl_lines_n_of_columns % global, from last run {\linetableparameter\c!n} +% {\setevalue{\??linetable c:\recurselevel\c!width}{\getvalue{\??linetablewidth\recurselevel}}% +% \letgvalue{\??linetablewidth\recurselevel}\!!zeropoint}} % init next table + +\permanent\protected\def\stoplinetableanalysis + {\stoplinetablerun + \egroup + \global\c_tabl_lines_n_of_rows\c_tabl_lines_rows + \dorecurse\c_tabl_lines_n_of_rows % global, from last run {\linetableparameter\c!n} + {\setevalue{\??linetable r:##1x\c!height}{\csname\??linetableheight##1\endcsname}% + \setevalue{\??linetable r:##1x\c!depth }{\csname\??linetabledepth ##1\endcsname}% + \letgvalue{\??linetableheight##1}\zeropoint + \letgvalue{\??linetabledepth ##1}\zeropoint} + \dorecurse\c_tabl_lines_n_of_columns % global, from last run {\linetableparameter\c!n} + {\setevalue{\??linetable c:##1\c!width}{\csname\??linetablewidth##1\endcsname}% + \letgvalue{\??linetablewidth##1}\zeropoint}} % init next table + +% todo: store in box instead of macro + +\aliased\let\stoplinetablehead\relax + +\permanent\protected\def\startlinetablehead#1\stoplinetablehead + {\ifconditional\c_tabl_lines_in_table + \t_tabl_lines_head\emptytoks + \fi + \c_tabl_lines_head_state\plusthree % full + \t_tabl_lines_head{#1}% + \ifconditional\c_tabl_lines_in_table + \tabl_lines_flush_head + \fi} + +\permanent\protected\def\tabl_lines_BH + {\ifx\EC\relax + % signal, grabbing lines + \else + \t_tabl_lines_head\emptytoks + \fi + \push_macro_BC + \push_macro_EC + \enforced\permanent\protected\def\BC##1\EC{\appendtoks##1\to\t_tabl_lines_head}% + \enforced\permanent \let\EC\relax} % signal + +\permanent\protected\def\tabl_lines_EH + {\pop_macro_EC + \pop_macro_BC + \expandafter\startlinetablehead\the\t_tabl_lines_head\stoplinetablehead} + +\permanent\let\startlinetablebody\relax +\permanent\let\stoplinetablebody \relax + +\protected\def\processlinetablebuffer + {\dosingleempty\tabl_lines_process_buffer} + +\def\tabl_lines_process_buffer[#1]% + {\bgroup + \enforced\let\startlinetable\relax + \enforced\let\stoplinetable \relax + \startlinetableanalysis\getbuffer[#1]\stoplinetableanalysis + \startlinetablerun \getbuffer[#1]\stoplinetablerun + \egroup} + +\permanent\tolerant\protected\def\processlinetablefile[#1]% maybe accept #1 as well as [#1] + {\bgroup + \enforced\let\startlinetable\relax + \enforced\let\stoplinetable \relax + \startlinetableanalysis\readfile{#1}\donothing\donothing\stoplinetableanalysis + \startlinetablerun \readfile{#1}\donothing\donothing\stoplinetablerun + \egroup} + +\popoverloadmode + +\setuplinetable + [\c!n=\maxcard, + \c!lines=\maxcard, + \c!nx=\plusone, + \c!nleft=\zerocount, + \c!repeat=\v!yes, % when nleft > 0, repeat on both pages + \c!before=, + \c!after=, + \c!inbetween=\page, + \c!distance=\zeropoint, + \c!stretch=\v!no, + \c!align=\c!right, + \c!leftoffset=.25\exheight, + \c!rightoffset=\linetableparameter\c!leftoffset, + \c!maxwidth=\zeropoint, + \c!width=5\emwidth, + \c!height=\v!fit, % \v!line = faster + \c!background=, + \c!backgroundcolor=, + \c!rulethickness=\linewidth] + +\protect + +\continueifinputfile{tabl-ltb.mkxl} + +\setuplinetable[n=6,m={2,2,2},lines=25] % m ? + +\setuplinetable[c][1] [width=2cm,background=color,backgroundcolor=red] +\setuplinetable[c][4] [width=3cm,background=color,backgroundcolor=yellow] +\setuplinetable[c][6] [width=3cm,background=color,backgroundcolor=magenta] +\setuplinetable[r][odd] [background=color,backgroundcolor=gray] +\setuplinetable[r][even][background=color,backgroundcolor=green] + +\starttext + +\showframe \showstruts + +\setuppagenumbering[alternative=doublesided]\page[left] + +\startlinetable +\NC aaa\crlf aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR +\dorecurse{100}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR} +\stoplinetable + +\startlinetable +\NC[style=slanted,color=green,background=color,backgroundcolor=darkred,nx=2,uitlijnen=middle] xxx + \NC yy \NC ddddd \NC eeee \NC ff \NC \NR +\dorecurse{100}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR} +\stoplinetable + +% \startbuffer[lt] +% \NC aaa\crlf aaa \NC bb \NC c \NC ddddd \NC ee \NC ff \NC \NR +% \NC aaa\crlf aaa \NC b \NC cc \NC ddd \NC eeee \NC f \NC \NR +% \stopbuffer +% +% \processlinetablebuffer[lt] + +\stoptext diff --git a/tex/context/base/mkiv/tabl-mis.mkiv b/tex/context/base/mkiv/tabl-mis.mkiv index b2af1993e..d9022b06d 100644 --- a/tex/context/base/mkiv/tabl-mis.mkiv +++ b/tex/context/base/mkiv/tabl-mis.mkiv @@ -130,7 +130,7 @@ \let\typo_paragraphs_setup_saved\setupparagraphs -\unexpanded\def\setupparagraphs +\unexpanded\overloaded\def\setupparagraphs {\dotripleempty\typo_paragraphs_setup} \def\typo_paragraphs_setup[#1][#2][#3]% we are downward compatible with [each] and [1,3] @@ -193,7 +193,7 @@ \fi \parindent\zeropoint \c_typo_paragraphs_n\zerocount - \let\\=\typo_paragraphs_next % downward compatible + \enforced\let\\\typo_paragraphs_next % downward compatible \edef\p_offset{\paragraphsparameter\c!offset}% \doifelsedimension\p_offset {\scratchoffset\p_offset}% diff --git a/tex/context/base/mkiv/tabl-ntb.mkxl b/tex/context/base/mkiv/tabl-ntb.mkxl index 680429822..300821107 100644 --- a/tex/context/base/mkiv/tabl-ntb.mkxl +++ b/tex/context/base/mkiv/tabl-ntb.mkxl @@ -44,12 +44,12 @@ % \eTR % \eTABLE -% \unexpanded\def\startrow {\bTR} -% \unexpanded\def\stoprow {\eTR} -% \unexpanded\def\startcell#1\stopcell{\bTD#1\eTD} -% \let\stopcell \relax -% \let\startcelltable \bTABLE -% \let\stopcelltable \eTABLE +% \protected\def\startrow {\bTR} +% \protected\def\stoprow {\eTR} +% \protected\def\startcell#1\stopcell{\bTD#1\eTD} +% \let\stopcell \relax +% \let\startcelltable \bTABLE +% \let\stopcelltable \eTABLE % \starttext % \startcelltable @@ -100,7 +100,7 @@ % maybe: \the\neverypar \to \t_tabl_ntb_cell_start -\unexpanded\def\tabl_ntb_cell_start +\protected\def\tabl_ntb_cell_start {% \inhibitblank \dotagTABLEcell %\tabl_ntb_next_level @@ -109,7 +109,7 @@ \everypar\t_tabl_ntb_cell_start \font_styles_math_start} -\unexpanded\def\tabl_ntb_cell_stop +\protected\def\tabl_ntb_cell_stop {\font_styles_math_stop \ifhmode \the\t_tabl_ntb_cell_stop @@ -123,7 +123,7 @@ % maybe: % -% \unexpanded\def\tabl_ntb_cell_stop +% \protected\def\tabl_ntb_cell_stop % {\ifhmode % \the\t_tabl_ntb_cell_stop % \par % added 13/4/2006 @@ -213,7 +213,7 @@ \installglobalmacrostack\m_tabl_ntb_saved_row \installglobalmacrostack\m_tabl_ntb_saved_col -\unexpanded\def\tabl_ntb_table_push +\protected\def\tabl_ntb_table_push {\ifnum\m_tabl_tbl_level>\plusone \tabl_ntb_parameters_reset % we need a proper count push/pop @@ -223,7 +223,7 @@ \global\intabletrue \fi} -\unexpanded\def\tabl_ntb_table_pop +\protected\def\tabl_ntb_table_pop {\ifnum\m_tabl_tbl_level>\plusone \pop_macro_m_tabl_ntb_saved_row\global\c_tabl_ntb_row\m_tabl_ntb_saved_row \pop_macro_m_tabl_ntb_saved_col\global\c_tabl_ntb_col\m_tabl_ntb_saved_col @@ -231,11 +231,11 @@ \global\intablefalse \fi} -\unexpanded\def\tabl_ntb_next_level +\protected\def\tabl_ntb_next_level {\advance\c_tabl_level\plusone \edef\m_tabl_tbl_level{\the\c_tabl_level}} -\unexpanded\def\tabl_ntb_prev_level +\protected\def\tabl_ntb_prev_level {\advance\c_tabl_level\minusone \edef\m_tabl_tbl_level{\the\c_tabl_level}} @@ -247,8 +247,8 @@ \installdirectcommandhandler \??naturaltable {naturaltable} % \??naturaltable \installsimpleframedcommandhandler \??naturaltablelocal {naturaltablelocal} \??naturaltablelocal -\unexpanded\def\bTABLEnested{\tabl_ntb_next_level\bTABLE} -\unexpanded\def\eTABLEnested{\eTABLE\tabl_ntb_prev_level} +\permanent\protected\def\bTABLEnested{\tabl_ntb_next_level\bTABLE} +\permanent\protected\def\eTABLEnested{\eTABLE\tabl_ntb_prev_level} \installcorenamespace{naturaltabletal} \installcorenamespace{naturaltablegal} @@ -353,18 +353,6 @@ % \c_tabl_ntb_none % \fi} -% not used -% -% \def\tabl_ntb_tag_state#1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi} -% \def\tabl_ntb_row_state#1#2{\ifcsname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi} -% \def\tabl_ntb_col_state#1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname\zerocount\else\plusone\fi} - -%def\tabl_ntb_set_spn #1{\expandafter\let\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname \!!plusone} -%def\tabl_ntb_spn_doifelse#1{\doifelse {\csname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname}\!!plusone} - -%def\tabl_ntb_set_spn #1{\setvalue {\??naturaltablespn\m_tabl_tbl_level:\number#1}{1}} -%def\tabl_ntb_spn_doifelse#1{\doifelsevalue{\??naturaltablespn\m_tabl_tbl_level:\number#1}{1}} - \def\tabl_ntb_let_ref #1#2{\expandafter\glet\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname} \def\tabl_ntb_set_ref #1#2{\expandafter\xdef\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname} %def\tabl_ntb_get_ref #1#2{\ifcsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\fi} @@ -379,11 +367,11 @@ % keep for a while: % -% \unexpanded\def\tabl_ntb_set_txt_process#1#2#3#4#5#6% nasty: we restore the level +% \protected\def\tabl_ntb_set_txt_process#1#2#3#4#5#6% nasty: we restore the level % {\expandafter\def\csname\??naturaltabletxt\m_tabl_tbl_level:\number#1:\number#2\expandafter\endcsname\expandafter % {\expandafter\def\expandafter\m_tabl_tbl_level\expandafter{\m_tabl_tbl_level}\tabl_ntb_cell_process{#3}{#4}[#5]{#6}}} -\unexpanded\def\tabl_ntb_set_txt_process#1#2#3#4#5#6% +\protected\def\tabl_ntb_set_txt_process#1#2#3#4#5#6% {\expandafter\def\csname\??naturaltabletxt\m_tabl_tbl_level:\number#1:\number#2\endcsname {\tabl_ntb_cell_process{#3}{#4}[#5]{\tabl_ntb_next_level#6\tabl_ntb_prev_level}}} @@ -414,25 +402,24 @@ % so far -\unexpanded\def\tabl_ntb_cell_process#1#2[#3]{} - -\unexpanded\def\bTC#1\eTC{\bTD#1\eTD} \let\eTC\relax -\unexpanded\def\bTX#1\eTX{\bTD#1\eTD} \let\eTX\relax -\unexpanded\def\bTY#1\eTY{\bTR#1\eTR} \let\eTY\relax +\protected\def\tabl_ntb_cell_process#1#2[#3]{} -\unexpanded\def\setupTABLE - {\dotripleempty\tabl_ntb_setup} +\permanent\protected\def\bTC#1\eTC{\bTD#1\eTD} \let\eTC\relax +\permanent\protected\def\bTX#1\eTX{\bTD#1\eTD} \let\eTX\relax +\permanent\protected\def\bTY#1\eTY{\bTR#1\eTR} \let\eTY\relax \let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal -\def\tabl_ntb_setup - {\ifthirdargument +\permanent\tolerant\protected\def\setupTABLE[#1]#*[#2]#*[#3]% + {\ifarguments + \expandafter\gobblethreeoptionals + \or + \expandafter\tabl_ntb_setup_one + \or + \expandafter\tabl_ntb_setup_two + \or \expandafter\tabl_ntb_setup_three - \orelse\ifsecondargument - \doubleexpandafter\tabl_ntb_setup_two - \else - \doubleexpandafter\tabl_ntb_setup_one - \fi} + \fi[#1][#2][#3]} \def\tabl_ntb_setup_one[#1][#2][#3]% {\setupcurrentnaturaltablelocal[#1]} @@ -457,9 +444,6 @@ \installcorenamespace{naturaltablesetupthree} \installcorenamespace{naturaltablesetuptwo} -%def\tabl_ntb_setup_three[#1]{\csname\??naturaltablesetupthree\ifcsname\??naturaltablesetupthree#1\endcsname#1\else\s!unknown\fi\endcsname[#1]} -%def\tabl_ntb_setup_two [#1]{\csname\??naturaltablesetuptwo \ifcsname\??naturaltablesetuptwo #1\endcsname#1\else\s!unknown\fi\endcsname[#1]} - \def\tabl_ntb_setup_three[#1]{\ifcsname\??naturaltablesetupthree#1\endcsname\expandafter\lastnamedcs\else\expandafter\tabl_ntb_setup_un\fi[#1]} \def\tabl_ntb_setup_two [#1]{\ifcsname\??naturaltablesetuptwo #1\endcsname\expandafter\lastnamedcs\else\expandafter\tabl_ntb_setup_ux\fi[#1]} @@ -492,7 +476,7 @@ \def\tabl_ntb_parameters_get[##1]% {\setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[##1,#2]}}% \csname\??naturaltableset\m_tabl_tbl_level:#1\endcsname - \let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal + \enforced\let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal \else \setvalue{\??naturaltableset\m_tabl_tbl_level:#1}{\tabl_ntb_parameters_get[#2]}% \fi @@ -562,7 +546,7 @@ \let\tabl_ntb_setup_section\relax -\unexpanded\def\tabl_ntb_setup_cell#1#2% cell over col over row +\protected\def\tabl_ntb_setup_cell#1#2% cell over col over row {\tabl_ntb_setup_section % already forgotten \edef\m_tabl_ntb_positive_row{\number#1}% \edef\m_tabl_ntb_positive_col{\number#2}% @@ -671,7 +655,7 @@ % \bTR \bTD left \eTD\bTD right \eTD\eTR % \eTABLE -\unexpanded\def\tabl_ntb_tr +\protected\def\tabl_ntb_tr {\c_tabl_ntb_running_col\zerocount \c_tabl_ntb_encountered_col\zerocount \advance\c_tabl_ntb_maximum_row\plusone @@ -687,7 +671,7 @@ \def\m_tabl_ntb_default_nr{\naturaltableparameter\c!nr} \def\m_tabl_ntb_default_nc{\naturaltableparameter\c!nc} -\unexpanded\def\tabl_ntb_td +\protected\def\tabl_ntb_td {\advance\c_tabl_ntb_encountered_col\plusone \iffirstargument \expandafter\tabl_ntb_td_yes @@ -912,18 +896,18 @@ % to be done: head <raw> foot, dus state var -\unexpanded\def\bTABLEhead{\dosingleempty\tabl_ntb_head} \let\eTABLEhead\relax -\unexpanded\def\bTABLEnext{\dosingleempty\tabl_ntb_next} \let\eTABLEnext\relax -\unexpanded\def\bTABLEbody{\dosingleempty\tabl_ntb_body} \let\eTABLEbody\relax -\unexpanded\def\bTABLEfoot{\dosingleempty\tabl_ntb_foot} \let\eTABLEfoot\relax +\let\eTABLEhead\relax +\let\eTABLEnext\relax +\let\eTABLEbody\relax +\let\eTABLEfoot\relax -\def\tabl_ntb_head[#1]#2\eTABLEhead{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head} -\def\tabl_ntb_next[#1]#2\eTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next} -\def\tabl_ntb_body[#1]#2\eTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body} -\def\tabl_ntb_foot[#1]#2\eTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot} +\permanent\tolerant\protected\def\bTABLEhead[#1]#2\eTABLEhead{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head} +\permanent\tolerant\protected\def\bTABLEnext[#1]#2\eTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next} +\permanent\tolerant\protected\def\bTABLEbody[#1]#2\eTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body} +\permanent\tolerant\protected\def\bTABLEfoot[#1]#2\eTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot} \def\tabl_ntb_section[#1]#2% also used in tabl-nte - {\unexpanded\def\tabl_ntb_setup_section{\setupcurrentnaturaltablelocal[#1]}% + {\protected\def\tabl_ntb_setup_section{\setupcurrentnaturaltablelocal[#1]}% #2% \let\tabl_ntb_setup_section\relax} @@ -932,10 +916,7 @@ \begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!oddeven\m_tabl_tbl_level\endcsname \begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\m_tabl_tbl_level\endcsname} -\unexpanded\def\bTABLE - {\dosingleempty\tabl_ntb_table} - -\def\tabl_ntb_table[#1]% +\permanent\tolerant\protected\def\bTABLE[#1]% {\tabl_ntb_table_push % box not here \bgroup @@ -984,10 +965,10 @@ \let\currentTABLEcolumn\tabl_ntb_current_column \let\nofTABLErows \tabl_ntb_n_of_rows \let\nofTABLEcolumns \tabl_ntb_n_of_columns - \let\bTR\dobTR - \let\bTD\dobTD - \let\bTH\dobTH - \let\bTN\dobTN} + \enforced\let\bTR\dobTR + \enforced\let\bTD\dobTD + \enforced\let\bTH\dobTH + \enforced\let\bTN\dobTN} \def\tabl_ntb_current_row {\m_tabl_ntb_positive_row} \def\tabl_ntb_current_column{\m_tabl_ntb_positive_col} @@ -1001,19 +982,21 @@ % there is no gain in a \doifelsenextoptionalcs variant -\unexpanded\def\dobTR{\dosingleempty\tabl_ntb_tr} % also used in tabl-nte -\unexpanded\def\dobTD{\dosingleempty\tabl_ntb_td} % also used in tabl-nte -\unexpanded\def\dobTH{\dosingleempty\tabl_ntb_th} % also used in tabl-nte -\unexpanded\def\dobTN{\dosingleempty\tabl_ntb_tn} % also used in tabl-nte +% todo with tolerant: + +\permanent\protected\def\dobTR{\dosingleempty\tabl_ntb_tr} % also used in tabl-nte +\permanent\protected\def\dobTD{\dosingleempty\tabl_ntb_td} % also used in tabl-nte +\permanent\protected\def\dobTH{\dosingleempty\tabl_ntb_th} % also used in tabl-nte +\permanent\protected\def\dobTN{\dosingleempty\tabl_ntb_tn} % also used in tabl-nte % permits \expanded{\bTD ... \eTD} -\let\bTR\relax \unexpanded\def\eTR{\ignorespaces} % handy in case we use a macro to generate rows -\let\bTD\relax \unexpanded\def\eTD{\ignorespaces} -\let\bTH\relax \unexpanded\def\eTH{\ignorespaces} -\let\bTN\relax \unexpanded\def\eTN{\ignorespaces} +\permanent\let\bTR\relax \permanent\protected\def\eTR{\ignorespaces} % handy in case we use a macro to generate rows +\permanent\let\bTD\relax \permanent\protected\def\eTD{\ignorespaces} +\permanent\let\bTH\relax \permanent\protected\def\eTH{\ignorespaces} +\permanent\let\bTN\relax \permanent\protected\def\eTN{\ignorespaces} -\unexpanded\def\eTABLE % beware, we need to get rid of spurious spaces when in hmode +\protected\def\eTABLE % beware, we need to get rid of spurious spaces when in hmode {% tricky and dirty order -) \setfalse\c_tabl_ntb_okay % head @@ -1214,12 +1197,12 @@ \the\t_tabl_ntb_row \tabl_ntb_row_align_stop}} -\unexpanded\def\tabl_ntb_row_align_set#1#2#3% +\protected\def\tabl_ntb_row_align_set#1#2#3% {\xdef\m_tabl_ntb_before_split{#1}% \xdef\m_tabl_ntb_after_split {#2}% \xdef\m_tabl_ntb_same_page {#3}} -\unexpanded\def\tabl_ntb_row_align_reset +\protected\def\tabl_ntb_row_align_reset {\glet\m_tabl_ntb_before_split\empty \glet\m_tabl_ntb_after_split \empty \glet\m_tabl_ntb_same_page \empty} @@ -1229,7 +1212,7 @@ % \prelocateTBLrows{1000} % may speed up large tables -\def\prelocateTBLrows#1% we start at zero so we have one to much, better play safe anyway +\permanent\protected\def\prelocateTBLrows#1% we start at zero so we have one to much, better play safe anyway {\dostepwiserecurse\c_tabl_prelocated_rows{#1}\plusone {\expandafter\newtoks\csname\??naturaltabletok\recurselevel\endcsname}% \def\tabl_ntb_row_start @@ -1296,7 +1279,7 @@ \fi \fi} -\unexpanded\def\tabl_ntb_row_align_start +\protected\def\tabl_ntb_row_align_start {\global\advance\c_tabl_ntb_row\plusone \global\c_tabl_ntb_col\plusone \global\c_tabl_ntb_spn\zerocount @@ -1307,7 +1290,7 @@ \hbox\bgroup \kern\dimexpr\d_tabl_ntb_leftmargindistance\relax} -\unexpanded\def\tabl_ntb_row_align_stop +\protected\def\tabl_ntb_row_align_stop {\kern\dimexpr\d_tabl_ntb_rightmargindistance-\d_tabl_ntb_columndistance\relax \egroup \ifconditional\c_strc_tags_enabled @@ -1315,7 +1298,7 @@ \fi \tabl_ntb_row_align_stop_inject} -\unexpanded\def\tabl_ntb_before_page +\protected\def\tabl_ntb_before_page {\ifx\m_tabl_ntb_same_page\v!before % \blank[\v!samepage,\v!strong]% \unpenalty @@ -1326,7 +1309,7 @@ \nobreak \fi} -\unexpanded\def\tabl_ntb_after_page +\protected\def\tabl_ntb_after_page {\ifnum\c_tabl_ntb_row>\c_tabl_ntb_n_of_head_lines \ifnum\tabl_ntb_get_nob\c_tabl_ntb_row=\zerocount \unpenalty @@ -1346,7 +1329,7 @@ \allowbreak % else no proper head split off \fi} -\unexpanded\def\tabl_ntb_inbetween +\protected\def\tabl_ntb_inbetween {\scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax \ifnum\scratchcounter>\c_tabl_ntb_n_of_hdnx_lines\relax \ifnum\scratchcounter<\c_tabl_ntb_maximum_row\relax @@ -1357,7 +1340,7 @@ \fi \fi} -\unexpanded\def\tabl_ntb_row_align_start_inject +\protected\def\tabl_ntb_row_align_start_inject {\bgroup % protect local vars \m_tabl_ntb_before_split \egroup @@ -1365,7 +1348,7 @@ \tabl_ntb_before_page \fi} -\unexpanded\def\tabl_ntb_row_align_stop_inject +\protected\def\tabl_ntb_row_align_stop_inject {\par \nointerlineskip \ifenableTBLbreak @@ -1389,16 +1372,16 @@ \the\t_tabl_ntb \dostoptagged} -\unexpanded\def\tabl_ntb_span#1% +\protected\def\tabl_ntb_span#1% {\hskip\tabl_ntb_get_dis\c_tabl_ntb_col \dorecurse{#1} {\hskip\tabl_ntb_get_wid\c_tabl_ntb_col\relax \global\advance\c_tabl_ntb_col\plusone}} -\unexpanded\def\tabl_ntb_skip#1% +\protected\def\tabl_ntb_skip#1% {\global\advance\c_tabl_ntb_col#1\relax} -\unexpanded\def\tabl_ntb_plus +\protected\def\tabl_ntb_plus {\global\advance\c_tabl_ntb_col\plusone \kern\d_tabl_ntb_columndistance} @@ -1421,10 +1404,10 @@ \fi}% \fi} -\unexpanded\def\tabl_ntb_cell#1#2% +\protected\def\tabl_ntb_cell#1#2% {\csname\??naturaltablecell\the\tabl_ntb_get_tag{#1}{#2}\endcsname{#1}{#2}} -\unexpanded\def\tabl_ntb_table_start +\protected\def\tabl_ntb_table_start {\global\c_tabl_ntb_spn\zerocount \global\c_tabl_ntb_row\zerocount \global\c_tabl_ntb_col\zerocount @@ -1522,13 +1505,6 @@ \fi \dostoptagged} % right spot -% \def\tabl_ntb_cell_finalize -% {\doifnotinset\localwidth{\v!fit,\v!broad}% user set -% {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax -% \ifdim\localwidth>\scratchdimen -% \tabl_ntb_set_aut\c_tabl_ntb_col{\the\dimexpr\localwidth}% -% \fi}} - \def\tabl_ntb_cell_finalize {\ifx\localwidth\v!fit % nothing @@ -1643,11 +1619,11 @@ \c_tabl_tbl_pass\plusthree \let\tabl_ntb_pass\tabl_ntb_pass_three \ifnum\m_tabl_tbl_level>\plusone - \tabl_tbl_split_nop + \tabl_ntb_split_nop \orelse\ifenableTBLbreak - \tabl_tbl_split_yes + \tabl_ntb_split_yes \else - \tabl_tbl_split_nop + \tabl_ntb_split_nop \fi} \def\tabl_ntb_stretch_widths % more variants, e.g. a max to \dimend @@ -1677,7 +1653,7 @@ \fi \fi} -\def\tabl_tbl_split_nop +\def\tabl_ntb_split_nop {\setbox\b_tabl_ntb_final\vbox{\tabl_ntb_flush_content}% \postprocessTABLEbox\b_tabl_ntb_final \beforeTABLEbox @@ -1693,7 +1669,7 @@ \box\b_tabl_ntb_final \afterTABLEbox} -\def\tabl_tbl_split_yes +\def\tabl_ntb_split_yes {\ifinsidesplitfloat \donetrue \orelse\ifinsidefloat @@ -1704,7 +1680,7 @@ \ifdone \expandafter\tabl_ntb_split_box \else - \expandafter\tabl_tbl_split_nop + \expandafter\tabl_ntb_split_nop \fi} \newbox\TABLEsplitbox % public, don't change @@ -1897,14 +1873,14 @@ \typo_charalign_adapt_font \signalcharacteralign{#2}{#1}} -\unexpanded\def\tabl_ntb_cell_process_a_extra#1#2% +\protected\def\tabl_ntb_cell_process_a_extra#1#2% {\ifcase\tabl_ntb_get_tal{#2}\relax \expandafter\tabl_ntb_cell_process_x \else \expandafter\tabl_ntb_cell_process_a \fi{#1}{#2}} -\unexpanded\def\tabl_ntb_cell_process_x#1#2[#3]#4% +\protected\def\tabl_ntb_cell_process_x#1#2[#3]#4% {} % problem: when span doesn't break we can have a span that is the sum of cells but @@ -1933,7 +1909,7 @@ \tabl_ntb_set_wid\c_tabl_ntb_col{\the\wd\scratchbox}% \fi} -\unexpanded\def\tabl_ntb_cell_process_a#1#2[#3]#4% grouping added ! ! ! +\protected\def\tabl_ntb_cell_process_a#1#2[#3]#4% grouping added ! ! ! {\bgroup \letnaturaltablelocalparameter\c!option\empty \tabl_ntb_setup_cell{#1}{#2}% @@ -1993,7 +1969,7 @@ \box\scratchboxone \egroup} -\unexpanded\def\tabl_ntb_cell_process_b_c#1#2#3[#4]#5% +\protected\def\tabl_ntb_cell_process_b_c#1#2#3[#4]#5% {\setbox\scratchbox\hbox {\tabl_ntb_setup_cell{#2}{#3}% \setupcurrentnaturaltablelocal[#4,#1]% @@ -2017,7 +1993,7 @@ \fi \box2 } -\unexpanded\def\tabl_ntb_cell_process_b#1#2[#3]#4% +\protected\def\tabl_ntb_cell_process_b#1#2[#3]#4% {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax \ifdim\scratchdimen>\zeropoint\relax \else @@ -2031,10 +2007,10 @@ \normalexpanded{\tabl_ntb_cell_process_b_c{\ifdim\scratchdimen>\zeropoint \c!width=\the\scratchdimen\fi}}% {#1}{#2}[#3]{\tabl_ntb_char_align{#1}{#2}#4}} -\unexpanded\def\tabl_ntb_cell_process_c +\protected\def\tabl_ntb_cell_process_c {\tabl_ntb_cell_process_b_c{}} -\unexpanded\def\tabl_ntb_cell_process_d#1#2[#3]#4% +\protected\def\tabl_ntb_cell_process_d#1#2[#3]#4% {\tabl_ntb_setup_cell{#1}{#2}% \bgroup \setupcurrentnaturaltablelocal[#3]% @@ -2044,7 +2020,7 @@ \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop}% \egroup} -\unexpanded\def\tabl_ntb_cell_process_e#1#2[#3]#4% +\protected\def\tabl_ntb_cell_process_e#1#2[#3]#4% {\tabl_ntb_setup_cell{#1}{#2}% \setupcurrentnaturaltablelocal[#3]% to get the color right, the way we \color % handle color here prevents interference due to whatsit nodes @@ -2185,19 +2161,16 @@ \installcorenamespace{naturaltablesetup} -\unexpanded\def\defineTABLEsetup - {\dodoubleargument\tabl_ntb_define_setup} - -\def\tabl_ntb_define_setup[#1][#2]% - {\setvalue{\??naturaltablesetup#1}{#2}} +\permanent\tolerant\protected\def\defineTABLEsetup[#1]#*[#2]% + {\ifarguments\else\setvalue{\??naturaltablesetup#1}{#2}\fi} -\let\eTDs\relax -\let\eTRs\relax +\permanent\let\eTDs\relax +\permanent\let\eTRs\relax -\unexpanded\def\bTDs[#1]#2\eTDs +\permanent\protected\def\bTDs[#1]#2\eTDs {\normalexpanded{\bTD[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTD} -\unexpanded\def\bTRs[#1]#2\eTRs +\permanent\protected\def\bTRs[#1]#2\eTRs {\normalexpanded{\bTR[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTR} \protect \endinput diff --git a/tex/context/base/mkiv/tabl-nte.mkiv b/tex/context/base/mkiv/tabl-nte.mkiv index af74a2abe..2a8c4c7dd 100644 --- a/tex/context/base/mkiv/tabl-nte.mkiv +++ b/tex/context/base/mkiv/tabl-nte.mkiv @@ -81,10 +81,10 @@ \setfalse\c_tabl_nte_in_nc} \unexpanded\def\tabl_nte_start_nc - {\futurelet\next\tabl_nte_start_nc_indeed} + {\futurelet\nexttoken\tabl_nte_start_nc_indeed} \def\tabl_nte_start_nc_indeed - {\ifx\next\tabl_nte_start_nr \else + {\ifx\nexttoken\tabl_nte_start_nr \else \expandafter\tabl_nte_start_nc_finish \fi} diff --git a/tex/context/base/mkiv/tabl-nte.mkxl b/tex/context/base/mkiv/tabl-nte.mkxl new file mode 100644 index 000000000..40213ad90 --- /dev/null +++ b/tex/context/base/mkiv/tabl-nte.mkxl @@ -0,0 +1,107 @@ +%D \module +%D [ file=core-nte, +%D version=2009.03.08, +%D title=\CONTEXT\ Table Macros, +%D subtitle=Natural Tables Extensions, +%D author=Hans Hagen \& Wolfgang Schuster, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Table Module / Natural Tables Extensions} + +\unprotect + +%D This module is suggested by Wolfgang Schuster who also prototyped +%D it and came up with the rationale: +%D +%D This module provides an easy way to use natural in a similiar +%D way as the older table module (based on the \TABLE\ macros) and +%D the newer tabulate module. +%D +%D You can see the advantage in the following table, once created +%D with the new macros and once with the normal macros provided +%D with the natural table module. +%D +%D Let us start with the original macros: +%D +%D \startbuffer +%D \bTABLE +%D \bTR +%D \bTD Text 1 \eTD +%D \bTD Text 2 \eTD +%D \eTR +%D \bTR +%D \bTD Text 3 \eTD +%D \bTD Text 4 \eTD +%D \eTR +%D \eTABLE +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D Watch how the new macros use less code: +%D +%D \startbuffer +%D \startTABLE +%D \NC Text 1 \NC Text 2 \NC\NR +%D \NC Text 3 \NC Text 4 \NC\NR +%D \stopTABLE +%D \stopbuffer +%D +%D \typebuffer \getbuffer +%D +%D The actual code differs from the prototype that it does not need +%D to collect whole rows and parse them but looks ahead instead. + +\newconditional\c_tabl_nte_in_nc + +\permanent\tolerant\protected\def\startTABLE[#1]% + {\bgroup + \bTABLE[#1]% + \enforced\let\NC\tabl_nte_start_nc + \enforced\let\NR\tabl_nte_start_nr + \enforced\let\bTR\relax + \enforced\let\bTD\relax + \enforced\let\bTH\relax + \enforced\let\bTN\relax} + +\permanent\protected\def\stopTABLE + {\eTABLE + \egroup} + +\permanent\protected\def\tabl_nte_start_nr + {\eTR + \setfalse\c_tabl_nte_in_nc} + +\permanent\protected\def\tabl_nte_start_nc + {\futurelet\nexttoken\tabl_nte_start_nc_indeed} + +\def\tabl_nte_start_nc_indeed + {\ifx\nexttoken\tabl_nte_start_nr \else + \expandafter\tabl_nte_start_nc_finish + \fi} + +\def\tabl_nte_start_nc_finish#1\NC + {\ifconditional\c_tabl_nte_in_nc \else + \settrue\c_tabl_nte_in_nc + \dobTR[]% + \fi + \dobTD#1\eTD\NC} + +%D The related structure commands are also available: + +\permanent\let\stopTABLEhead\relax +\permanent\let\stopTABLEnext\relax +\permanent\let\stopTABLEbody\relax +\permanent\let\stopTABLEfoot\relax + +\permanent\tolerant\protected\def\startTABLEhead[#1]#:#2\stopTABLEhead{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head} +\permanent\tolerant\protected\def\startTABLEnext[#1]#:#2\stopTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next} +\permanent\tolerant\protected\def\startTABLEbody[#1]#:#2\stopTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body} +\permanent\tolerant\protected\def\startTABLEfoot[#1]#:#2\stopTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot} + +\protect \endinput diff --git a/tex/context/base/mkiv/tabl-tab.mkiv b/tex/context/base/mkiv/tabl-tab.mkiv index 3799964c9..e646a1a18 100644 --- a/tex/context/base/mkiv/tabl-tab.mkiv +++ b/tex/context/base/mkiv/tabl-tab.mkiv @@ -1739,7 +1739,7 @@ %D elsewhere. Here we only check for inconsistent spacing. Due to the way \TEX\ %D handles alignments, we cannot automate spacing for colored rows and columns. -\setnewconstant\tablerowzero\zerocount +\tablerowzero\zerocount \appendtoks \let\SR\tabl_table_SR diff --git a/tex/context/base/mkiv/tabl-tab.mkxl b/tex/context/base/mkiv/tabl-tab.mkxl new file mode 100644 index 000000000..5fb7f928c --- /dev/null +++ b/tex/context/base/mkiv/tabl-tab.mkxl @@ -0,0 +1,2229 @@ +%D \module +%D [ file=core-tab, +%D version=1997.10.10, +%D title=\CONTEXT\ Table Macros, +%D subtitle=\TABLE\ Embedding, +%D author=Hans Hagen with copied and patched code from MJ Wichura, +%D date=\currentdate] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Table Macros / TaBlE Embedding} + +% Todo: just for the fun of it ... use lmtx features. + +% Todo: a bitmore namespace protection ... although we want to keep some of the +% original flavour. +% +% In \MKIV\ the old table macros are sort of obsolete. The color extensions have +% been removed and some code is stripped. For practical reasons the \TABLE\ macros +% that are used are embedded in this file. +% +% The following code is based on TABLE 1.0 by Michael J. Wichura (August 1988. We +% used a patched version with many overloads and extensions. The documented (and +% larger) source can be found in \type {thrd-tab.tex}. +% +% Some code has been stripped. Some color has been added. Some macros have been +% renamed. Registers have been replaces. And probably much more can be cleaned up. +% We also need to use \tabl_tab_ prefixes here. + +\unprotect + +\newconditional\c_tabl_table_spacing_left +\newconditional\c_tabl_table_spacing_right + +\newdimen \d_tabl_table_line_thickness_unit +\newdimen \d_tabl_table_strut_unit +\newskip \s_tabl_table_inter_column_space_unit +\newdimen \d_tabl_table_column_width_unit +\newdimen \d_tabl_table_kern_unit + +\def\tablestrutheightfactor {8} +\def\tablestrutdepthfactor {3} +\def\tableintercolumnspacefactor {3} +\def\tablecolumnwidthfactor {10} +\def\tablevspacefactor {2} +\def\tablekernfactor {1} +\def\tablelinethicknessfactor {4} + +\newtoks\everytable +\newtoks\everytableparbox + +\protected\def\tabl_table_begin_par_box#1% + {\setbox\scratchbox\vtop\bgroup % \setbox added + \hsize#1\relax + \dontcomplain + \tabl_table_restore_lineskips + \normalbaselines + \enforced\let~\fixedspace + \inhibitblank % \blank[\v!disable]% % added + \the\everytableparbox} + +\protected\def\tabl_table_end_par_box + {\removelastskip % itemize or so + \endgraf + \ifnum\prevgraf>\zerocount % we want at least + \verticalstrut \nowhitespace \vskip-\struttotal % one line of text + \egroup + \ifdim\dp\scratchbox>\lineheight % see (*) for an + \getnoflines{\dp\scratchbox}% % example of where + \dp\scratchbox\zeropoint % saving can go + \setbox\scratchbox % terrible wrong + \vtop to \noflines\lineheight{\box\scratchbox}% + \fi % esp between rows + \else % of paragraphs + \egroup + \fi + \box\scratchbox} + +\appendtoks + \parindent\zeropoint + \raggedright + \rightskip\zeropoint \s!plus 4em \relax +\to \everytableparbox + +\newskip \tablelefttabskip +\newskip \tablerighttabskip + +\newcount\!taColumnNumber +\newcount\!taRecursionLevel % (Initially 0) + +\newdimen\!taDimenA % used by \Enlarge +\newdimen\!taDimenB % used by \Enlarge +\newdimen\!taDimenC % used by numeric.tex +\newdimen\!taMinimumColumnWidth + +\newtoks \!taTableSpread +\newtoks \!taPreamble +\newtoks \!taDataColumnTemplate +\newtoks \!taRuleColumnTemplate +\newtoks \!taOldRuleColumnTemplate +\newtoks \!taLeftGlue +\newtoks \!taRightGlue + +\newskip \!taLastRegularTabskip + +\newif \if!taBeginFormat +\newif \if!taOnceOnlyTabskip + +\def\!thToksEdef#1#2% + {\edef\tempstring{#2}% + #1\expandafter{\tempstring}% + \ignorespaces} + +\def\!thLoop#1\repeat + {\def\!thIterate{#1\expandafter\!thIterate\fi}% + \!thIterate + \let\!thIterate\relax} + +\def\tabl_table_begin_format + {\!taPreamble\emptytoks + \!taColumnNumber\zerocount + \scratchskip\s_tabl_table_inter_column_space_unit + \multiply\scratchskip\tableintercolumnspacefactor + \divide\scratchskip\plustwo + \!taRuleColumnTemplate\expandafter{\expandafter\tabskip\the\scratchskip}% + \!taLastRegularTabskip\scratchskip + \!taOnceOnlyTabskipfalse + \!taBeginFormattrue + \let\!tfRowOfWidths\empty + \doreadtableformatkeys} + +\def\!tfSetWidth + {\ifempty\!tfRowOfWidths % true if no prior "w" keys + \ifnum\!taColumnNumber>\zerocount % true if "w" key is to right of first "|" + \begingroup % RowOfWidths={\aligntab\omit || n copies of \aligntab\omit\aligntab#\omit}, where n = number of column to the left of this one + \scratchcounter\plusone + \aftergroup\edef + \aftergroup\!tfRowOfWidths + \aftergroup{% + \aftergroup\aligntab + \aftergroup\omit + \!thLoop + \ifnum \scratchcounter<\!taColumnNumber + \advance\scratchcounter\plusone + \aftergroup\!tfAOAO + \repeat + \aftergroup}% + \endgroup + \fi + \fi + \ifx[\tempstring % \!tgGetValue sets \tempstring = token after w + \expandafter\!tfSetWidthText + \else + \expandafter\!tfSetWidthValue + \fi} + +\def\!tfAOAO{\aligntab\omit\aligntab\omit} + +\def\!tfSetWidthText[#1]% + {\def\!tfWidthText{#1}% + \doreadtableformatkeys} + +\def\!tfSetWidthValue + {\!taMinimumColumnWidth + \ifnum\!tgCode=\plusone + \ifempty\!tgValue \tablecolumnwidthfactor \else \!tgValue \fi \d_tabl_table_column_width_unit + \else + \!tgValue + \fi + \let\!tfWidthText\empty % Override possible prior `w[sample entry]' + \doreadtableformatkeys} + +\def\!tfSetTabskip + {\ifnum\!tgCode=\plusone + \scratchskip\s_tabl_table_inter_column_space_unit + \multiply\scratchskip \ifempty\!tgValue\tableintercolumnspacefactor\else\!tgValue\fi + \else + \scratchskip\!tgValue + \fi + \divide\scratchskip\plustwo + \ifnum\!taColumnNumber=\zerocount + %\!thToksEdef\!taRuleColumnTemplate{\the\!taRuleColumnTemplate\tabskip\the\scratchskip}% + \normalexpanded{\!taRuleColumnTemplate{\the\!taRuleColumnTemplate\tabskip\the\scratchskip}}% + \else + %\!thToksEdef\!taDataColumnTemplate{\the\!taDataColumnTemplate\tabskip\the\scratchskip}% + \normalexpanded{\!taDataColumnTemplate{\the\!taDataColumnTemplate\tabskip\the\scratchskip}}% + \fi + \if!taOnceOnlyTabskip\else + \!taLastRegularTabskip\scratchskip % Remember this Tabskip, for possible + \fi % restoration after a subsequent"OnceOnly" + \doreadtableformatkeys} + +\def\!tfSetVrule + {\!thToksEdef\!taRuleColumnTemplate + {\hfil + \vrule + \noexpand\s!width + \ifnum\!tgCode=\plusone + \ifempty\!tgValue + \c_tabl_table_vrule_thickness_factor + \else + \!tgValue + \fi + \d_tabl_table_line_thickness_unit + \else + \!tgValue + \fi + \alignmark\alignmark\alignmark\alignmark + \hfil + \the\!taRuleColumnTemplate}% + \!tfAdjoinPriorColumn} + +\def\!tfSetAlternateVrule + {\afterassignment\!tfSetAlternateA\scratchtoks} + +\def\!tfSetAlternateA + {\!thToksEdef\!taRuleColumnTemplate{\the\scratchtoks\the\!taRuleColumnTemplate}% + \!tfAdjoinPriorColumn} + +\def\!tfAdjoinPriorColumn + {\ifnum\!taColumnNumber=\zerocount + \!taPreamble=\!taRuleColumnTemplate % New \tabskip may have been added + \else + \ifempty\!tfRowOfWidths\else % no "w" keys specified yet, not even this col + \!tfUpdateRowOfWidths + \fi + \!thToksEdef\!taDataColumnTemplate{\the\!taLeftGlue\the\!taDataColumnTemplate\the\!taRightGlue}% + \!thToksEdef\!taPreamble{\the\!taPreamble\aligntab\the\!taDataColumnTemplate\aligntab\the\!taRuleColumnTemplate}% + \fi + \advance\!taColumnNumber\plusone + \if!taOnceOnlyTabskip + \!thToksEdef\!taDataColumnTemplate{\alignmark\alignmark\alignmark\alignmark\tabskip\the\!taLastRegularTabskip}% + \else + \!taDataColumnTemplate{\alignmark\alignmark}% + \fi + \!taRuleColumnTemplate\emptytoks + \!taLeftGlue{\hfil}% + \!taRightGlue{\hfil}% + \!taMinimumColumnWidth\zeropoint + \let\!tfWidthText\empty + \!taOnceOnlyTabskipfalse + \doreadtableformatkeys} + +\def\!tfUpdateRowOfWidths + {\ifempty\!tfWidthText\else + \!tfComputeMinColWidth + \fi + \edef\!tfRowOfWidths + {\!tfRowOfWidths + \aligntab + \omit + \ifdim \!taMinimumColumnWidth>\zeropoint + \hskip \the\!taMinimumColumnWidth + \fi + \aligntab + \omit}} + +\def\!tfComputeMinColWidth + {\setbox\scratchbox\vbox + {\ialign{% Plain's initialized \halign; \tabskip=0pt \everycr={} + \span\the\!taDataColumnTemplate\cr + \!tfWidthText\cr}}% + \!taMinimumColumnWidth\wd\scratchbox} + +\def\!tfFinishFormat + {\!thToksEdef\!taPreamble{% + \alignmark\alignmark\alignmark\alignmark\tabskip\tablelefttabskip + \aligntab + \the\!taPreamble\tabskip\tablerighttabskip + \aligntab + \alignmark\alignmark\alignmark\alignmark\tabskip\zeropoint\cr} + \!taBeginFormatfalse + \!ttDoHalign} + +\def\tabl_table_reformat[#1]% will become local + {\omit + \!taDataColumnTemplate{\alignmark\alignmark}% + \!taLeftGlue\emptytoks + \!taRightGlue\emptytoks + \begingroup + \tabl_table_use_bar + \expanded{\endgroup\noexpand\doreadtableformatkeys#1]}}% appear in a \tabl_table_reformat cmd; this is here as a safeguard. + +\appendtoks + \enforced\let\ReFormat\tabl_table_reformat +\to \everytable + +\def\!tfEndReFormat + {\!tfReFormat} + +\appendtoks \tabl_table_paralignment \to \everytableparbox + +\def\!tfReFormat#1% + {\the \!taLeftGlue + \vbox{\forgetall\ialign{\span\the\!taDataColumnTemplate\cr#1\cr}}% + \the \!taRightGlue + \kern\zeropoint} % prevents \unskip / really needed + +\def\!tgGetValue#1% + {\def\!tgReturn{#1}% + \futurelet\tempstring\!tgCheckForParen} + +\def\!tgCheckForParen% + {\ifx\tempstring (% + \expandafter \!tgDoParen + \else + \expandafter \!tgCheckForSpace + \fi} + +\def\!tgDoParen(#1)% + {\def\!tgCode{2}% will be expanded + \def\!tgValue{#1}% + \!tgReturn} + +\def\!tgCheckForSpace + {\def\!tgCode{1}% + \let\!tgValue\empty + \ifx\tempstring\!thSpaceToken + \expandafter\!tgReturn + \else + \expandafter\!tgCheckForDigit + \fi} + +\def\!tgCheckForDigit % less tokens: (could be an ifcsname) + {\donetrue + \ifx 0\tempstring \orelse \ifx 1\tempstring \orelse + \ifx 2\tempstring \orelse \ifx 3\tempstring \orelse + \ifx 4\tempstring \orelse \ifx 5\tempstring \orelse + \ifx 6\tempstring \orelse \ifx 7\tempstring \orelse + \ifx 8\tempstring \orelse \ifx 9\tempstring \else + \donefalse + \fi + \ifdone + \expandafter\!tgGetNumber + \else + \expandafter\!tgReturn + \fi} + +% \def\!tgCheckForDigit % does not work +% {\relax\doifnumberelse\tempstring\!tgGetNumber\!tgReturn} + +\def\!tgGetNumber {\afterassignment\!tgGetNumberA\scratchcounter=} +\def\!tgGetNumberA{\edef\!tgValue{\the\scratchcounter}\!tgReturn} + +\def\!tgSetUpParBox + {\normalexpanded + {\noexpand \doreadtableformatkeys + b{\tabl_table_begin_par_box + {\ifnum\!tgCode=\plusone + \ifempty\!tgValue + \tablecolumnwidthfactor + \else + \!tgValue + \fi + \d_tabl_table_column_width_unit + \else + \!tgValue + \fi}}% + a{\tabl_table_end_par_box}}} + +\def\!tgInsertKern + {\edef\tempstring + {\kern + \ifnum\!tgCode=\plusone + \ifempty\!tgValue + \tablekernfactor + \else + \!tgValue + \fi + \d_tabl_table_kern_unit + \else + \!tgValue + \fi}% + \edef\tempstring + {\noexpand\doreadtableformatkeys + \ifconditional\c_tabl_table_spacing_left + b{\tempstring} + \fi + \ifconditional\c_tabl_table_spacing_right + a{\tempstring} + \fi}% + \tempstring} + +\def\newtableformatkey #1{\setvalue{!tk<\string#1>}} +\def\doreadtableformatkeys#1{\getvalue{!tk<\string#1>}} + +% Key "b": b{TOKENS} adds TOKENS to the left of (before) the template + +\newtableformatkey b#1% + {\expandafter\!tkJoin\expandafter{\the\!taDataColumnTemplate}{#1}% + \doreadtableformatkeys} + +\def\!tkJoin#1#2% + {\!taDataColumnTemplate{#2#1}}% + +% Key "a": a{TOKENS} adds TOKENS to the right of (after) the template + +\newtableformatkey a#1% + {\toksapp\!taDataColumnTemplate{#1}% + \doreadtableformatkeys} + +% Key "\{": Enclose template in braces. + +\newtableformatkey \{% + {\!taDataColumnTemplate=\expandafter{\expandafter{\the\!taDataColumnTemplate}}% + \doreadtableformatkeys} + +% Key "*": "*{N}{KEY LETTERS}" is equivalent to specifying +% <KEY LETTERS> N times. +% KEY LETTERS may contain further * specifications + +\newtableformatkey *#1#2% + {\scratchcounter=#1\relax + \scratchtoks\emptytoks + \!thLoop + \ifnum\scratchcounter>\zerocount + \toksapp\scratchtoks{#2}% + \advance\scratchcounter\minusone + \repeat + \expandafter\doreadtableformatkeys\the\scratchtoks} + +% Key "\LeftGlue": Specifies the glue (usually \hfil, or nothing) to be +% added to extreme left of the template to position a column + +\newtableformatkey \LeftGlue#1% + {\!taLeftGlue{#1}% + \doreadtableformatkeys} + +\newtableformatkey \RightGlue#1% + {\!taRightGlue{#1}% + \doreadtableformatkeys} + +\newtableformatkey c% + {\prependtoks\raggedcenter\to\!taDataColumnTemplate + \doreadtableformatkeys \LeftGlue\hfil \RightGlue\hfil} + +\newtableformatkey l% + {\prependtoks\raggedright\to\!taDataColumnTemplate + \doreadtableformatkeys \LeftGlue\empty \RightGlue\hfil} + +\newtableformatkey r% + {\prependtoks\raggedleft\to\!taDataColumnTemplate + \doreadtableformatkeys \LeftGlue\hfil \RightGlue\empty} + +\newtableformatkey x% + {\prependtoks\notragged\to\!taDataColumnTemplate + \doreadtableformatkeys \LeftGlue\hfil \RightGlue\empty} + +% Key "k": Adds kerns to left and right of "#" This key and the two below use Plain +% TeX's \if@h as if it were \if@left, and \if@v as if it were \if@right. Table +% making goes on in a group, so even in the unlikely circumstance that a \phantom +% is currently under construction, there's no problem. + +\newtableformatkey k% + {\settrue\c_tabl_table_spacing_left + \settrue\c_tabl_table_spacing_right + \!tgGetValue{\!tgInsertKern}} + +% Key "i": Adds a kern to the left of "#" + +\newtableformatkey i% + {\settrue\c_tabl_table_spacing_left + \setfalse\c_tabl_table_spacing_right + \!tgGetValue{\!tgInsertKern}} + +% Key "j": Adds a kern to the right of "#" + +\newtableformatkey j% + {\setfalse\c_tabl_table_spacing_left + \settrue\c_tabl_table_spacing_right + \!tgGetValue{\!tgInsertKern}} + +% Key "n": numeric item , non-math mode. + +\newtableformatkey n% + {\def\!tnStyle{}% + \futurelet\!tnext\!tnTestForBracket} + +% Key "N": numeric item, math mode. + +\newtableformatkey N% + {\def\!tnStyle{$}% + \futurelet\!tnext\!tnTestForBracket} + +% Key "m": Math mode. + +\newtableformatkey m% + {\doreadtableformatkeys b{\normalstartimath} a{\normalstopimath}} + +% Key "M": Displaymath mode. + +\newtableformatkey M% + {\doreadtableformatkeys \{ b{\normalstartimath\displaystyle} a{\normalstopimath}} + +% Key "\m": Template ${}#\hfil$ + +\newtableformatkey \m% + {\doreadtableformatkeys l b{{}} m} + +% Key "\M": Template $\displaystyle{{}#\hfil}$ + +\newtableformatkey \M% + {\doreadtableformatkeys l b{{}} M} + +% Key "f": Set font (E.g., f\it sets up italic font (assuming \it +% has its usual meaning) + +\newtableformatkey f#1% + {\doreadtableformatkeys b{#1}} + +\newtableformatkey B{\doreadtableformatkeys f\bf} % Key "B": abbreviation for f\bf +\newtableformatkey I{\doreadtableformatkeys f\it} % Key "I": abbreviation for f\it +\newtableformatkey S{\doreadtableformatkeys f\sl} % Key "S": abbreviation for f\sl +\newtableformatkey R{\doreadtableformatkeys f\rm} % Key "R": abbreviation for f\rm +\newtableformatkey T{\doreadtableformatkeys f\tt} % Key "T": abbreviation for f\tt + +% Key "p": ParBox + +\newtableformatkey p% + {\!tgGetValue{\!tgSetUpParBox}} + +% Key "w": minimum column width + +\newtableformatkey w% + {\!tkTestForBeginFormat w{\!tgGetValue{\!tfSetWidth}}} + +% Key "s": Set tabskip for the inter-column space to the right of the current +% column, and all subsequent spaces, until overriden by a new "s" or "o" key. + +\newtableformatkey s% + {\!taOnceOnlyTabskipfalse % in case same column has a prior "o" key + \!tkTestForBeginFormat t{\!tgGetValue{\!tfSetTabskip}}} + +% Key "o": Apply the \tabskip stated for this column ONLY to the inter-column space +% just to the right of this column; restore the the previous \tabskip for +% subsequent columns. + +\newtableformatkey o% + {\!taOnceOnlyTabskiptrue + \!tkTestForBeginFormat o{\!tgGetValue{\!tfSetTabskip}}} + +% Key "|": Standard rule column designator + +\newtableformatkey |% + {\!tkTestForBeginFormat |{\!tgGetValue{\!tfSetVrule}}} + +% Key "\|": Non-standard rule column designator + +\newtableformatkey \|% + {\!tkTestForBeginFormat \|{\!tfSetAlternateVrule}} + +% Key ".": PERIOD -- end of \tabl_table_begin_format section. + +\newtableformatkey .% + {\!tkTestForBeginFormat.{\!tfFinishFormat}} + +% Key "\doendtableformat": Equivalent to "." + +\newtableformatkey \doendtableformat + {\!tkTestForBeginFormat\doendtableformat{\!tfFinishFormat}} + +% Key "]": End of \tabl_table_reformat section + +\newtableformatkey ]% + {\!tkTestForReFormat ] \!tfEndReFormat} + +% TEST FOR BEGIN FORMAT{<Key>}{Intended Action}: This test is run on keys that can +% only be used by \tabl_table_begin_format --- "s", "o", "|", "\|", "w", ".", and +% "\doendtableformat". + +\def\!tkTestForBeginFormat#1#2% + {\if!taBeginFormat + \def\tempstring{#2}% + \expandafter\tempstring + \else + \toks0={#1}% + \toks2=\expandafter{\string\tabl_table_reformat}% + \expandafter\!tkImproperUse + \fi} + +% TEST FOR RE FORMAT{<Key>}{Intended Action}: This test is run on the key "]", +% which can only be used by \tabl_table_reformat. + +\def\!tkTestForReFormat#1#2% + {\if!taBeginFormat + \toks0={#1}% + \toks2=\expandafter{\string\tabl_table_begin_format}% + \expandafter\!tkImproperUse + \else + \def\tempstring{#2}% + \expandafter\tempstring + \fi} + +% NOTE: THE SPACE BETWEEN A NUMERIC ENTRY AND THE FOLLOWING '|', '"', OR '\|' IS +% MANDATORY. EMPTY NUMERIC ENTRIES ARE NOT ALLOWED: USE '{}' OR '\omit' INSTEAD. + +\def\!tnTestForBracket + {\ifx[\!tnext + \expandafter\!tnGetArgument + \else + \expandafter\!tnGetCode + \fi} + +% GET CODE: E.g. "4", or "4.0", "0.4", or "10.2" + +\def\!tnGetCode#1 % + {\!tnConvertCode #1..!} + +% CONVERT CODE: E.g. converts above to [0000], [0000.], [.0000], [0000000000.00] + +\def\!tnConvertCode #1.#2.#3!% + {\begingroup + \aftergroup\edef \aftergroup\tempstring \aftergroup{% + \aftergroup[% + \scratchcounter#1\relax + \!thLoop + \ifnum \scratchcounter>\zerocount + \advance\scratchcounter\minusone + \aftergroup0 + \repeat + \def\tempstring{#3}% + \ifempty\tempstring\else + \aftergroup. + \scratchcounter#2\relax + \!thLoop + \ifnum \scratchcounter>\zerocount + \advance\scratchcounter\minusone + \aftergroup0 + \repeat + \fi + \aftergroup]\aftergroup}% + \endgroup\relax + \expandafter\!tnGetArgument\tempstring} + +% GET ARGUMENT: [<sample left field> <optional .<sample right field>> + +\def\!tnGetArgument[#1]% + {\!tnMakeNumericTemplate\!tnStyle#1..!} + +% MAKE NUMERIC TEMPLATE + +\def\!tnMakeNumericTemplate#1#2.#3.#4!% #1=<empty> or $ + {\def\tempstring{#4}% + \ifempty\tempstring + \!taDimenC\zeropoint + \else + \setbox\scratchbox\hbox{\mathsurround\zeropoint #1.#3#1}% + \!taDimenC\wd\scratchbox + \fi + \setbox\scratchbox\hbox{\mathsurround\zeropoint #1#2#1}% + \!thToksEdef\!taDataColumnTemplate + {\noexpand\!tnSetNumericItem{\the\wd\scratchbox}{\the\!taDimenC}{#1}% + \the\!taDataColumnTemplate}% Might have tabskip glue in here + \doreadtableformatkeys} + +% SET NUMERIC ITEM + +\def\!tnSetNumericItem #1#2#3#4 % + {\!tnSetNumericItemA {#1}{#2}{#3}#4..!} + +\def\!tnSetNumericItemA #1#2#3#4.#5.#6!% + {\def\tempstring{#6}% + \hbox to #1{\hss \mathsurround\zeropoint #3#4#3}% + \hbox to #2{\ifempty\tempstring\else\mathsurround\zeropoint #3.#5#3\fi\hss}} + +% extensions + +\newtableformatkey q% + {\let\!tqStyle\empty + \futurelet\!tnext\!tqTestForBracket} + +\newtableformatkey Q% + {\def\!tqStyle{$}% + \futurelet\!tnext\!tqTestForBracket} + +\def\!tqTestForBracket + {\ifx[\!tnext + \!thx\!tqGetArgument + \else + \!thx\!tqGetCode + \fi} + +\def\!tqGetCode#1 % note the blank + {\!tqConvertCode #1,,!} + +\def\!tqConvertCode #1,#2,#3!% + {\begingroup + \aftergroup\edef + \aftergroup\tempstring + \aftergroup{% + \aftergroup[% + \scratchcounter#1\relax + \!thLoop + \ifnum \scratchcounter>\zerocount + \advance\scratchcounter\minusone + \aftergroup0 + \repeat + \def\tempstring{#3}% + \ifempty\tempstring\else + \aftergroup, + \scratchcounter#2\relax + \!thLoop + \ifnum\scratchcounter>\zerocount + \advance\scratchcounter\minusone + \aftergroup0 + \repeat + \fi + \aftergroup]\aftergroup}% + \endgroup\relax + \!thx\!tqGetArgument\tempstring} + +\def\!tqGetArgument[#1]% + {\!tqMakeQuantityTemplate\!tqStyle#1,,!} + +\def\!tqMakeQuantityTemplate#1#2,#3,#4!% #1=<empty> or $ + {\def\tempstring{#4}% + \ifempty\tempstring + \!taDimenC\zeropoint + \else + \setbox\scratchbox\hbox{\mathsurround\zeropoint #1,#3#1}% + \!taDimenC\wd\scratchbox + \fi + \setbox\scratchbox\hbox{\mathsurround\zeropoint #1#2#1}% + \!thToksEdef\!taDataColumnTemplate + {\noexpand\!tqSetQuantityItem{\the\wd\scratchbox}{\the\!taDimenC}{#1}% + \the\!taDataColumnTemplate}% + \doreadtableformatkeys} + +\def\!tqSetQuantityItem #1#2#3#4 % + {\!tqSetQuantityItemA{#1}{#2}{#3}#4,,!} + +\def\!tqSetQuantityItemA #1#2#3#4,#5,#6!% + {\def\tempstring{#6}% + \hbox to #1{\hss\mathsurround\zeropoint#3#4#3}% + \hbox to #2{\ifempty\tempstring\else\mathsurround\zeropoint#3,#5#3\fi\hss}} + +% \Enlarge<extra height><extra depth><original> +% \enlarge<multiple for extra height><multiple for extra depth><original> + +\def\tabl_table_Enlarge#1#2% + {% 3rd argument is picked up later + % #1=extra height + % #2=extra depth + \!taDimenA=#1\relax + \!taDimenB=#2\relax + \let\!TsSpaceFactor\empty + \ifmmode + \expandafter\mathpalette + \expandafter\!TsEnlargeMath + \else + \expandafter\!TsEnlargeOther + \fi} + +\def\!TsEnlargeOther#1% + {\ifhmode + \setbox\scratchbox\hbox{#1\xdef\!TsSpaceFactor{\spacefactor\the\spacefactor}}% + \else + \setbox\scratchbox\hbox{#1}% + \fi + \!TsFinishEnlarge} + +\def\!TsEnlargeMath#1#2% + {\setbox\scratchbox\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}% + \!TsFinishEnlarge} + +\def\!TsFinishEnlarge + {\ht\scratchbox\dimexpr\ht\scratchbox+\!taDimenA\relax + \dp\scratchbox\dimexpr\dp\scratchbox+\!taDimenB\relax + \box\scratchbox + \!TsSpaceFactor\relax} + +\def\tabl_table_enlarge#1#2% 3rd argument is picked up later + {\tabl_table_Enlarge{#1\d_tabl_table_strut_unit}{#2\d_tabl_table_strut_unit}} + +\appendtoks + \enforced\let\enlarge\tabl_table_enlarge + \enforced\let\Enlarge\tabl_table_Enlarge +\to \everytable + +% BEGIN TABLE + +\let\tabl_table_standard_end\relax + +\def\tabl_table_standard_begin[#1]% \!ttBeginTable (always argument) + {\if#1u% unboxed table + \ifmmode + \let\tabl_table_standard_end\relax % user had better be in display math mode and have only one table at the outer level + \else % user had better be in vertical mode + \bgroup + \let\tabl_table_standard_end\egroup + \fi + \else + \hbox\bgroup + \def\tabl_table_standard_end{\egroup\egroup}% + \if#1t% + \vtop + \orelse\if#1b% + \vbox + \else + \def\tabl_table_standard_end{\egroup\normalstopimath\egroup}% + \scratchtoks\everymath + \everymath\emptytoks + \normalstartimath + \everymath\scratchtoks + \vcenter + \fi + \bgroup % for the \vtop, \vbox, or \vcenter + \fi + \advance\!taRecursionLevel\plusone + \let\!ttRightGlue\relax + \everycr\emptytoks + \ifnum\!taRecursionLevel=\plusone + \the\everytable + \fi} + +\bgroup \catcode\tildeasciicode\activecatcode + + \appendtoks + \catcode\barasciicode\activecatcode + \enforced\protected\def ~{\kern.5em}% + \enforced\protected\def\\{\ifhmode\space\else\par\fi}% + \to \everytable + +\egroup + +\let\!ttRightGlue\relax % This may be changed, in a group, by \JustCenter, etc + +% DO HALIGN: Invoked by END FORMAT (or the key ".") + +\let\tabl_table_restore_lineskips\relax + +\def\!ttDoHalign + {\edef\tabl_table_restore_lineskips + {\baselineskip \the\baselineskip + \lineskiplimit\the\lineskiplimit + \lineskip \the\lineskip + \tabskip \the\tabskip + \relax}% + \baselineskip \zeropoint + \lineskiplimit\zeropoint + \lineskip \zeropoint + \tabskip \zeropoint + \edef\p_tabl_table_textwidth{\directtablesparameter\c!textwidth}% + % we are not in sync so: + \synchronizedisplaydirection + \synchronizeinlinedirection + \halign + \usedirectionparameterreverse\directtablesparameter + \ifempty\p_tabl_table_textwidth \else to \ifx\p_tabl_table_textwidth\v!max \hsize \else \p_tabl_table_textwidth \fi\fi + %\the\!taTableSpread + \bgroup + \span + \the\!taPreamble + \ifempty\!tfRowOfWidths\else + \!tfRowOfWidths\cr + \fi} + +% END TABLE + +\def\tabl_table_normal_end + {\egroup % finishes the \halign + \tabl_table_standard_end} % closes off the table envirnoment set up by \tablestandardbegin + +\def\tabl_table_normal_line_ending + {\cr} + +\def\tabl_table_normal_line_format#1#2% + {\vrule + \s!width \zeropoint + \s!height\dimexpr\tablestrutheightfactor\d_tabl_table_strut_unit+#1\d_tabl_table_strut_unit\relax + \s!depth \dimexpr\tablestrutdepthfactor \d_tabl_table_strut_unit+#2\d_tabl_table_strut_unit\relax + \relax + \cr} + +% INSERT VRULE + +\newcount\c_tabl_table_n_of_vrules \c_tabl_table_n_of_vrules\plusone + +\let\m_tabl_table_vrule_color\empty +\let\m_tabl_table_hrule_color\empty + +\def\do!ttInsertVrule + {\vrule\s!width + \ifnum\!tgCode=\plusone + \ifempty\!tgValue + \c_tabl_table_vrule_thickness_factor + \else + \!tgValue + \fi + \d_tabl_table_line_thickness_unit + \else + \!tgValue + \fi + \hskip.125\emwidth\relax} + +\def\tabl_table_normal_line_simple_bar + {\unskip\!ttRightGlue\aligntab\aligntab} + +\def\tabl_table_normal_line_complex_bar + {\unskip\!ttRightGlue\aligntab\omit + \hfil + \ifempty\m_tabl_table_vrule_color\else + \switchtocolor[\m_tabl_table_vrule_color]% + \fi + \ifcase\c_tabl_table_n_of_vrules\or + \do!ttInsertVrule + \unskip + \else + \dorecurse\c_tabl_table_n_of_vrules\do!ttInsertVrule + \global\c_tabl_table_n_of_vrules\plusone + \unskip + \fi + \glet\m_tabl_table_vrule_color\empty + \hfil + \aligntab} + +\def\tabl_table_normal_no_bar + {\unskip\!ttRightGlue\aligntab\omit\aligntab} + +\def\tabl_table_normal_single_rule + {\aligntab\tabl_table_normal_long_rule\aligntab} + +\def\tabl_table_normal_multi_rule + {\aligntab\tabl_table_use\c_tabl_table_drule_span\tabl_table_normal_long_rule\aligntab} + +% USE + +\def\tabl_table_use#1% + {\ifnum#1>\plusone + \omit + \global\setfalse\c_tabl_table_is_division % added + \scratchcounter\currenttablecolumn % added + \advance\scratchcounter #1% % added + \advance\scratchcounter \minusone % added + \def\next % added + {\global\advance\currenttablecolumn #1% % added + \global\advance\currenttablecolumn \minusone % added + \scratchcounter#1% + \advance\scratchcounter \minusone + \advance\scratchcounter \scratchcounter + \!thLoop + \ifnum\scratchcounter>\plusone + \spanomit \advance\scratchcounter\minusone + \repeat + \span}% + \else % added + \def\next % conflicts with possible next \omit % added + {\global\advance\currenttablecolumn \plusone}%% added + \fi + \next} % added + +\def\tabl_table_Use#1[% + {\tabl_table_use{#1}% + \tabl_table_reformat[} + +\appendtoks + \enforced\let\use\tabl_table_use + \enforced\let\Use\tabl_table_Use +\to \everytable + +% rules + +\def\tabl_table_normal_full_rule + {\noalign\bgroup + \!ttGetHalfRuleThickness + \scratchdistance\directtablesparameter\c!openup + \ifzeropt\scratchdistance\else\kern\scratchdistance\fi + \hrule\s!height\scratchdimen\s!depth\scratchdimen + \ifzeropt\scratchdistance\else\kern\scratchdistance\fi + \egroup} + +\def\tabl_table_normal_short_rule % was: \!ttShortHrule + {\omit + \!ttGetHalfRuleThickness + \ifempty\m_tabl_table_hrule_color\else + \switchtocolor[\m_tabl_table_hrule_color]% see *DL* + \fi + \leaders\hrule\s!height\scratchdimen\s!depth\scratchdimen\hfill + \emptyhbox + \ignorespaces} + +\def\tabl_table_normal_long_rule % was: \!ttLongHrule + {\omit\span + \omit\span + \tabl_table_normal_short_rule} + +\def\!ttGetHalfRuleThickness + {\scratchdimen\dimexpr + \ifnum\!tgCode=\plusone + \ifempty\!tgValue + \c_tabl_table_hrule_thickness_factor + \else + \!tgValue % user-specified integer + \fi + \d_tabl_table_line_thickness_unit + \else + \!tgValue % user-specified dimension + \fi + \divide\scratchdimen\plustwo} + +% \emptyhbox prevents \unskip + +\def\tabl_table_Left #1{#1\hfill\emptyhbox} +\def\tabl_table_Center#1{\hfill#1\hfill\emptyhbox} +\def\tabl_table_Right #1{\hfill#1} + +\def\tabl_table_OpenUp#1#2% + {\edef\tablestrutheightfactor{\withoutpt\the\dimexpr\tablestrutheightfactor\points+#1\points}% + \edef\tablestrutdepthfactor {\withoutpt\the\dimexpr\tablestrutdepthfactor \points+#2\points}} + +% SetTableToWidth -> textwidth=dimension [to dimension] +% Expand -> textwidth=max [to \hsize] +% WidenTableBy -> [spread #1] +% \tablelefttabskip\zeropoint\s!plus1\s!fill +% \tablerighttabskip\tablelefttabskip +% LongLines -> [spread \hsize] + +\def\tabl_table_JustLeft {\omit\let\!ttRightGlue\hfill} +\def\tabl_table_JustCenter{\omit\hfill\emptyhbox\let\!ttRightGlue\hfill} +\def\tabl_table_JustRight {\omit\hfill\emptyhbox} + +\def\tabl_table_Smash + {\relax + \ifmmode + \expandafter\mathpalette + \expandafter\!thDoMathVCS + \else + \expandafter\!thDoVCS + \fi} + +\def\!thDoVCS#1% + {\setbox\zerocount\hbox{#1}% + \!thFinishVCS} + +\def\!thDoMathVCS#1#2% + {\setbox\zerocount\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}% + \!thFinishVCS} + +\def\!thFinishVCS + {\vpack to\zeropoint{\vss\box\zerocount\vss}} + +\def\tabl_table_Raise + {\def\!thSign{+}% + \!tgGetValue\!thSetDimen} + +\def\tabl_table_Lower + {\def\!thSign{-}% + \!tgGetValue\!thSetDimen} + +\def\!thSetDimen + {\ifnum\!tgCode=\plusone + \ifempty\!tgValue + \!taDimenA\tablestrutheightfactor\d_tabl_table_strut_unit + \advance\!taDimenA\tablestrutdepthfactor\d_tabl_table_strut_unit + \divide\!taDimenA\plustwo + \else + \!taDimenA\!tgValue\d_tabl_table_strut_unit + \fi + \else + \!taDimenA\!tgValue + \fi + \!taDimenA\!thSign\!taDimenA\relax + \ifmmode + \expandafter\mathpalette + \expandafter\!thDoMathRaise + \else + \expandafter\!thDoSimpleRaise + \fi} + +\def\!thDoSimpleRaise#1% + {\setbox\zerocount\hbox{\raise \!taDimenA\hbox{#1}}% + \!thFinishRaise} % From Plain TeX: \ht0=0pt \dp0=0pt \box0 + +\def\!thDoMathRaise#1#2% + {\setbox\zerocount\hbox{\raise \!taDimenA\hbox{\normalstartimath\mathsurround\zeropoint#1{#2}\normalstopimath}}% + \!thFinishRaise} + +\def\!thFinishRaise + {\ht\zerocount\zeropoint + \dp\zerocount\zeropoint + \box\zerocount} + +\def\tabl_table_BackSpace + {\!tgGetValue\!thKernBack} + +\def\!thKernBack + {\kern - + \ifnum\!tgCode=\plusone + \ifempty\!tgValue + \tablekernfactor + \else + \!tgValue % user-specified integer + \fi + \d_tabl_table_kern_unit + \else + \!tgValue % user-specified dimension + \fi + \ignorespaces} + +\def\tabl_table_Vspace + {\noalign + \bgroup + \!tgGetValue\!thVspace} + +\def\!thVspace + {\vskip + \ifnum\!tgCode=\plusone + \ifempty\!tgValue + \tablevspacefactor + \else + \!tgValue % user-specified integer + \fi + \d_tabl_table_strut_unit + \else + \!tgValue % user-specified skip + \fi + \egroup} % Ends the \noalign + +\appendtoks + \enforced\let\JustLeft \tabl_table_JustLeft + \enforced\let\JustCenter \tabl_table_JustCenter + \enforced\let\JustRight \tabl_table_JustRight + \enforced\let\Smash \tabl_table_Smash + \enforced\let\Raise \tabl_table_Raise + \enforced\let\Lower \tabl_table_Lower + \enforced\let\BackSpace \tabl_table_BackSpace + \enforced\let\Vspace \tabl_table_Vspace + \enforced\let\OpenUp \tabl_table_OpenUp + \enforced\let\TableLeft \tabl_table_Left + \enforced\let\TableCenter\tabl_table_Center + \enforced\let\TableRight \tabl_table_Right +\to \everytable + +%D \macros +%D {inintable, ifsplittables} +%D +%D First we declare some variables. These show a bit what we are dealing with. First +%D we introdoce some booleans that enable us, inside as well as outside this module, +%D to determine in what mode we are. + +\newif\ifintable +\newif\ifsplittables + +%D We show this feature in an example that also shows some of the basic table +%D typesetting commands. +%D +%D \startbuffer +%D \starttable[|||] +%D \HL +%D \VL first \VL second \VL\AR +%D \HL +%D \VL alfa \VL 1 \VL\AR +%D \VL beta \VL 2 \VL\AR +%D \VL gamma \VL 3 \VL\AR +%D \HL +%D \stoptable +%D \stopbuffer +%D +%D \startlinecorrection +%D \getbuffer +%D \stoplinecorrection +%D +%D This table is specified as: +%D +%D \typebuffer +%D +%D This examples shows about the minimum of commands needed to typeset such a table. +%D In this table, the \type {\AR} is automatically translated into the more +%D primitive (but more verbose) commands \type {\SR}, \type {\FR}, \type {\MR} and +%D \type {\LR} commands. +%D +%D \startbuffer +%D \starttables[|||] +%D \HL +%D \VL first \VL second \VL\AR +%D \HL +%D \VL alfa \VL 1 \VL\AR +%D \VL beta \VL 2 \VL\AR +%D \VL gamma \VL 3 \VL\AR +%D \HL +%D \stoptables +%D \stopbuffer +%D +%D \getbuffer +%D +%D Some simple color support is provided: +%D +%D \startbuffer +%D \starttable[|c|c|] +%D \HL +%D \VL test \VL test \VL \SR +%D \HL[green,5] +%D \VL[red] test \VL test \VL \FR +%D \VL test \VL[10,red] test \VL \MR +%D \VL test \VL test \VL[10] \LR +%D \HL +%D \stoptable +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\installcorenamespace{tabletemplate} + +\immutable\def\m!TABLE{TABLE} + +%D We already saw that the table macros report errors and provide automatic spacing. +%D These features can only be implemented by keeping track of the state, often the +%D last command on a row. + +\newconstant\tableforcestate +\newconstant\tableactionstate + +\setnewconstant\tableunknownstate 0 + +\setnewconstant\tableseparaterowstate 1 +\setnewconstant\tablefirstrowstate 2 +\setnewconstant\tablemidrowstate 3 +\setnewconstant\tablelastrowstate 4 +\setnewconstant\tablerulestate 5 +%setnewconstant\tableskipstate 6 +%setnewconstant\tableautorowstate 7 + +\setnewconstant\tableforcefirstrowstate 1 +\setnewconstant\tableforcelastrowstate 2 + +\newconstant\tablerowfactor +\newconstant\TABLEendofrowdepth +\newconstant\TABLEendofrowheight +\newconstant\TABLEcr +\newconstant\tablerowzero +\newconstant\TABLEn + +%D We store these states using \type {constants}'s and like most variables, these +%D are global ones. When needed, especially when we flush the backgrounds, we can +%D temporary disable the assignment. + +\newconditional\tableactionstatepermitted + +\def\tabl_table_set_action#1{\ifconditional\tableactionstatepermitted\global\tableactionstate#1\fi} +\def\tabl_table_set_force #1{\ifconditional\tableactionstatepermitted\global\tableforcestate #1\fi} + +%D To give an impression of what the (well documented) source of \TABLE\ looks like, +%D we first implement an alternative for the numeric keys. The quantity keys +%D (\type{q} and \type{Q}) support the more european way of writing numbers: +%D +%D \startnarrower +%D 100.000.000,00 instead of 100,000,000.00 +%D \stopnarrower +%D +%D The next table shows how to use these keys. We use braces instead of brackets because +%D we need brackets to specify the format. +%D +%D \starttyping +%D \starttable{|q[00,000]|Q[00,00]|} +%D \HL +%D \VL -1,2 \VL 12,35 \VL\FR +%D \VL 11,203 \VL 2,4 \VL\LR +%D \HL +%D \stoptable +%D \stoptyping +%D +%D Although a more efficient implementation is possible |<|we can for instance share +%D common macros|>| we just adapt a copy of the numeric ones. To permit double +%D loading of this module, we check for the existence of one of the macros. +%D +%D To be compatible with the tabulate environment, we also support the \type {l}, +%D \type {c} and \type {r} keys for paragraph entries. +%D +%D All commands that are executed between rows are to be put in \type {\noalign}. We +%D can however not verify if we (that is \TABLE) does or did not enter this mode. A +%D moderate dirty but useful trick is using our own alternative:\footnote{Once one +%D has entered the stage of redefining \TEX\ primitives, such hacks become a second +%D nature. However, redefining \type {\omit} and \type{\span} is not that easy.} + +%D We no longer need this in \LUAMETATEX: +%D +%D \starttyping +%D \aliased\let\tablenoalign \noalign +%D \def\starttablenoalign{\noalign\bgroup} +%D \let\stoptablenoalign \egroup +%D \stoptyping + +%D \macros +%D {starttable} +%D +%D The rest of this module is not easy to comprehend, mainly because we have to take +%D care of: +%D +%D \startitemize[packed] +%D \item \type{\startitemize[template]} +%D \item \type{\startitemize{template}} +%D \item \type{\startitemize[predefined]} +%D \stopitemize +%D +%D as well as: +%D +%D \startitemize[continue] +%D \item restart after table break +%D \stopitemize +%D +%D The official specification of the start command is: +%D +%D \showsetup{starttable} + +\newconditional\c_tabl_table_repeat_head +\newconditional\c_tabl_table_repeat_tail + +\permanent\tolerant\protected\def\starttable[#1]#*[#2]% preamble optional-settings + {\bgroup + \ifarguments\or\or + \setupcurrenttables[#2]% + \fi + \edef\p_tabl_table_split{\directtablesparameter\c!split}% + \edef\p_tabl_table_frame{\directtablesparameter\c!frame}% + \ifx\p_tabl_table_split\v!auto + \ifinsidesplitfloat + \let\p_tabl_table_split\v!yes + \lettablesparameter\c!split\v!yes % might be used later, best make a proper mode + \fi + \fi + \ifx\p_tabl_table_split\v!yes + \enforced\let\stoptable\table_table_stop_g % not \protected as we look ahead + \expandafter\starttables + \orelse\ifx\p_tabl_table_split\v!repeat + \enforced\let\stoptable\table_table_stop_g % not \protected as we look ahead + \expandafter\starttables + \else + \enforced\let\stoptable\table_table_stop + \ifempty\p_tabl_table_frame + \ifinsidefloat\else\startbaselinecorrection\fi + \else + \startframedcontent[\p_tabl_table_frame]% + \fi + \postponenotes + \expandafter\tabl_table_first_stage + \fi[#1]} + +% We cannot define the stopper as \type {\protected} because lookahead in +% alignments fail then, so we relax it and define it locally. + +\permanent\let\stoptable\relax + +\permanent\def\table_table_stop + {\tabl_tables_chuck_auto_row % before the tail, else noalign problem + \tabl_table_insert_tail + \noalign\bgroup + \glet\tabl_table_head\empty + \glet\tabl_table_tail\empty + \egroup + \tabl_table_finish + \ifempty\p_tabl_table_frame + \ifinsidefloat\else + \stopbaselinecorrection + \goodbreak % compensates all the nobreaks + \fi + \else + \stopframedcontent + \fi + \egroup} + +\permanent\def\table_table_stop_g + {\table_table_stop_s\egroup} + +%D Before we can grab the argument, we have to make sure that the \CATCODES\ are +%D set. The first stage takes care of that. + +\def\tabl_table_first_stage + {\bgroup + \global\intabletrue + \tabl_table_second_stage} + +%D \macros +%D {definetabletemplate} +%D +%D The complex (and main) start macro first takes care of the predefined case. Such +%D a predefined setup looks like: +%D +%D \starttyping +%D \definetabletemplate[test][|||] +%D +%D \starttable[test] +%D \VL test \VL test \VL\AR +%D \VL test \VL test \VL\AR +%D \VL test \VL test \VL\AR +%D \stoptable +%D \stoptyping +%D +%D The implementation of the definition macro is not that complicated: + +\installcorenamespace{tablehead} +\installcorenamespace{tabletail} + +\permanent\protected\def\definetabletemplate % to be redone + {\bgroup + \catcode\barasciicode\othercatcode + \tabl_table_define_template} + +\tolerant\def\tabl_table_define_template[#1]#*[#2]#*[#3]#*[#4]% + {\ifarguments\or\else + \setgvalue{\??tabletemplate#1}{\tabl_table_use_template{#2}{#3}{#4}}% + \fi + \egroup} + +\def\tabl_table_use_template#1#2#3% + {\gdef\tabl_table_head{\begincsname\??tablehead#2\endcsname}% + \gdef\tabl_table_tail{\begincsname\??tabletail#3\endcsname}% + \tabl_table_second_stage[#1]} + +%D The optional third and fourth arguments define which table head and tail to use. +%D +%D \starttyping +%D \definetabletemplate[test][|||][before][after] +%D \stoptyping +%D +%D This also means that one can define table heads and tails by name! +%D +%D \starttyping +%D \starttablehead[before] +%D \HL \VL first \VL second \VL \SR \HL +%D \stoptablehead +%D \stoptyping +%D +%D Templates defined this way get protected names, that cannot conflict with +%D existing commands. +%D +%D \showsetup{definetabletemplate} +%D +%D The second half of the next macro prepares table +%D splitting. + +\def\tabl_table_insert_head + {\noalign{\global\settrue\preventtablebreak\global\setfalse\hassometablehead}% + \tabl_table_head + \noalign{\global\setfalse\preventtablebreak}} + +\def\tabl_table_insert_tail + {\noalign{\global\settrue\preventtablebreak\global\setfalse\hassometabletail}% + \tabl_table_tail + \noalign{\global\setfalse\preventtablebreak}} + +% \def\doverysimpletableHL % todo +% {\noalign{\normalexpanded{\noexpand\tabl_table_normal_full_rule\m_tabl_table_HLheight}} + +\def\tabl_table_restart_indeed#1% + {\gdef\tabl_table_restart{#1}% + \tabl_table_restart +% \noalign{\globalpushmacro\simpletableHL\glet\simpletableHL\doverysimpletableHL}% + \tabl_table_insert_head + \ifsplittables \ifconditional \c_tabl_table_repeat_tail + \noalign{\goodbreak}% + \tabl_table_insert_tail + \noalign{\goodbreak}% + \fi \fi +% \noalign{\globalpopmacro\simpletableHL}% + } + +\bgroup \catcode\barasciicode\othercatcode + +\gdef\tabl_table_second_stage[#1]% brr nested mess + {\bgroup + \tabl_table_use_bar + \global\setfalse\tableactionstatepermitted + \global\setfalse\hassometablehead + \global\setfalse\hassometabletail + \expanded{\doifelseinstring{|}{#1}} + {\xdef\tabl_table_restart{\noexpand\tabl_table_restart_indeed{\noexpand\tabl_table_third_stage{#1}}}} + {\doifelsedefined{\??tabletemplate#1} + {\gdef\tabl_table_restart{\getvalue{\??tabletemplate#1}}} + {\gdef\tabl_table_restart{\tabl_table_restart_indeed{\getvalue{#1}}}}}% + \egroup + \tabl_table_restart} + +\egroup + +%D The third stage involves a lot of (re)sets, which we will explain later. + +\appendtoks + \fixedspaces + \enforced\let\_\normalunderscore +\to \everytable + +%D Now we can start the table. + +\newtoks\localtabledefinitions + +\def\tabl_table_third_stage#1% + {\global\settrue\tableactionstatepermitted + \tabl_table_set_action\tableunknownstate + \tabl_table_set_force\tableunknownstate + \tabl_table_resetVLvalues + \appendtoks\tabl_table_local_setups\to\everytable + \tabl_table_standard_begin[\ifsplittables u\else b\fi]% + \the\localtabledefinitions + \forgetall % added + \edef\currenttableformat{#1}% + \doifsomething\currenttableformat + {\dogettablenofcolumns\currenttableformat + % more modern is to use catcode tables + \expandafter\tabl_table_begin_format\currenttableformat\doendtableformat}} + +\def\tabl_table_finish + {\tabl_tables_chuck_auto_row + \unskip\crcr + \tabl_table_normal_end + \global\intablefalse + \egroup} + +%D \macros +%D {starttables} +%D +%D Split tables are specified using the plural form of the start and stop commands. +%D +%D \showsetup{starttables} +%D +%D For example: +%D +%D \starttyping +%D \starttables[|||] +%D \HL +%D \VL element \VL atom weight \VL\AR +%D \HL +%D \VL ....... \VL ........... \VL\AR +%D \VL ....... \VL ........... \VL\AR +%D \HL +%D \stoptables +%D \stoptyping + +\newbox\tablecontentbox + +\permanent\protected\def\starttables + {\bgroup + \enforced\let\stoptables\table_table_stop_s + \splittablestrue + \edef\p_tabl_table_split{\directtablesparameter\c!split}% + \ifx\p_tabl_table_split\v!repeat + \settrue\c_tabl_table_repeat_head + \settrue\c_tabl_table_repeat_tail + \else + \setfalse\c_tabl_table_repeat_head + \setfalse\c_tabl_table_repeat_tail + \fi + \flushnotes + \setbox\tablecontentbox\vbox\bgroup + \forgetall + \tabl_table_first_stage} + +\permanent\let\stoptables\relax % needed for \noalign + +\def\table_table_stop_s % not \protected as we need the lookahead (brrr) + {\tabl_tables_chuck_auto_row % AM: before the tail, else noalign problem + \ifconditional\c_tabl_table_repeat_tail\else\tabl_table_insert_tail\fi + \tabl_table_finish + \egroup + \dontcomplain + \tabl_table_split_box\tablecontentbox + \glet\tabl_table_head\empty % new here + \glet\tabl_table_tail\empty % new here + \flushnotes + \egroup} + +\def\tabl_table_split_box#1% + {\resettsplit + \def\tsplitminimumfreelines{2}% + \def\tsplitminimumfreespace{\zeropoint}% + \setbox\tsplitcontent\box#1% + \ifconditional\c_tabl_table_repeat_head \ifconditional\hassometablehead + \setbox\tsplithead\vsplit\tsplitcontent to \lineheight + \setbox\tsplithead\vbox{\unvbox\tsplithead}% \vpack ? + \fi \fi + \ifconditional\c_tabl_table_repeat_tail \ifconditional\hassometabletail + \setbox\tsplittail\vsplit\tsplitcontent to \lineheight + \setbox\tsplittail\vbox{\unvbox\tsplittail}% \vpack ? + \fi \fi + \ifinsidefloat\else + \def\tsplitbeforeresult{\startbaselinecorrection}% + \def\tsplitafterresult {\stopbaselinecorrection}% + \fi + \handletsplit} + +%D When the table in the previous example is split across pages, only the first gets +%D a head. We could have said something like: +%D +%D \starttyping +%D \starttablehead +%D \HL +%D \VL element \VL atom weight \VL\AR +%D \HL +%D \stoptablehead +%D +%D \starttabletail +%D \HL +%D \stoptabletail +%D +%D \starttables[|||] +%D \VL ....... \VL ........... \VL\AR +%D \VL ....... \VL ........... \VL\AR +%D \stoptables +%D \stoptyping +%D +%D This time each split table gets a head line and ends with a rule. Keep in mind +%D that such heads also apply to the unbroken ones and should be defined local +%D (grouped) if needed. The rather complicated definition below is due to the fact +%D that the stopcondition is interface language dependant. + +\let\tabl_table_head\empty % needs checking +\let\tabl_table_tail\empty % needs checking + +\letvalue{\e!start\v!tablehead}\relax % todo: frozen, but we use a grabber +\letvalue{\e!stop \v!tablehead}\relax % todo: frozen, but we use a grabber +\letvalue{\e!start\v!tabletail}\relax % todo: frozen, but we use a grabber +\letvalue{\e!stop \v!tabletail}\relax % todo: frozen, but we use a grabber + +%D The second argument is a dummy one, by scanning for it, we get rid of +%D interfering spaces. + +\newconditional\preventtablebreak +\newconditional\hassometablehead +\newconditional\hassometabletail + +% \def\tabl_table_set_head[#1][#2]#3\end{\setvalue{\??tablehead#1}{\noalign{\global\settrue\hassometablehead}#3}} +% \def\tabl_table_set_tail[#1][#2]#3\end{\setvalue{\??tabletail#1}{\noalign{\global\settrue\hassometabletail}#3}} + +\permanent\protected\def\settablehead{\dodoubleempty\tabl_table_set_head} % todo: use pickup +\permanent\protected\def\settabletail{\dodoubleempty\tabl_table_set_tail} % todo: use pickup + +\def\tabl_table_set_head[#1][#2]#3\end + {\gdef\tabl_table_head{\begincsname\??tablehead#1\endcsname}% new + \setvalue{\??tablehead#1}{\noalign{\global\settrue\hassometablehead}#3}} + +\def\tabl_table_set_tail[#1][#2]#3\end + {\gdef\tabl_table_tail{\begincsname\??tabletail#1\endcsname}% new + \setvalue{\??tabletail#1}{\noalign{\global\settrue\hassometabletail}#3}} + +\normalexpanded + {\def\csname\e!start\v!tablehead\endcsname#1\csname\e!stop\v!tablehead\endcsname% + {\settablehead#1\noexpand\end}} + +\normalexpanded + {\def\csname\e!start\v!tabletail\endcsname#1\csname\e!stop\v!tabletail\endcsname% + {\settabletail#1\noexpand\end}} + +%D Redundant \type{\HL}'s are removed automatically, so mid||lines can be used +%D without problems. +%D +%D The order of the next macros is more or less random. First we implement error +%D recovery. Errors are reported to the screen and log file as well as visualized in +%D the table in teletype. + +\def\tabl_table_finish_row + {\crcr + \noalign\bgroup + \nobreak + \tabl_table_set_action\tableunknownstate + \glet\tabl_tables_check_auto_row\empty + \glet\tabl_tables_chuck_auto_row\empty + \global\currenttablecolumn\zerocount + \egroup} + +%D Next we enter the more complicated area of column and row switching. I won't go +%D into much detail from now on, but just mention the general principles. +%D +%D \startitemize[3*ruim] +%D \sym{\type{\SR}} end a separate row (between rules) +%D \sym{\type{\FR}} end a first row (after a rule) +%D \sym{\type{\MR}} end a mid row (between text lines) +%D \sym{\type{\LR}} end a last row (before a rule) +%D \stopitemize +%D +%D and best of all: +%D +%D \startitemize[continue] +%D \sym{\type{\AR}} end a row with automatic spacing +%D \stopitemize +%D +%D As far as possible, we report confusing situations. In most cases one can use +%D \type{\AR}, which transfigurates itself into one of the other types. +%D +%D \starttyping +%D \starttable[||] +%D \HL +%D \VL a separate row \VL\SR +%D \HL +%D \VL a first row \VL\FR +%D \VL a mid row \VL\MR +%D \VL a last row \VL\LR +%D \HL +%D \stoptable +%D \stoptyping +%D +%D In this example we could have used \type{\AR} without problems. +%D +%D Color or gray scale backgrounds precede the content. They are passed over +%D horizontal (division) lines when needed. Errors in the color template are traced +%D elsewhere. Here we only check for inconsistent spacing. Due to the way \TEX\ +%D handles alignments, we cannot automate spacing for colored rows and columns. + +\tablerowzero\zerocount + +\appendtoks + \enforced\let\SR\tabl_table_SR + \enforced\let\FR\tabl_table_FR + \enforced\let\MR\tabl_table_MR + \enforced\let\LR\tabl_table_LR + \enforced\let\AR\tabl_table_AR +\to \localtabledefinitions + +\protected\def\tabl_table_SR + {\ifnum\tableactionstate=\tablefirstrowstate + \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}% + \orelse\ifnum\tableactionstate=\tablemidrowstate + \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}% + \orelse\ifnum\tableactionstate=\tablemidrowstate + \writestatus\m!TABLE{change \string\SR\space into \string\MR/\string\LR}% + \fi + \tabl_table_end_row_indeed\tableseparaterowstate\tablerowfactor\tablerowfactor} + +\protected\def\tabl_table_FR + {\ifnum\tableactionstate=\tablemidrowstate + \writestatus\m!TABLE{change \string\FR\space into \string\MR/\string\LR}% + \orelse\ifnum\tableactionstate=\tablelastrowstate + \writestatus\m!TABLE{change \string\FR\space into \string\MR/\string\LR}% + \fi + \tabl_table_end_row_indeed\tablefirstrowstate\tablerowfactor\tablerowzero} + +\protected\def\tabl_table_MR + {\ifnum\tableactionstate=\tablerulestate + \writestatus\m!TABLE{change \string\MR\space into \string\FR/\string\SR}% + \orelse\ifnum\tableactionstate=\tablelastrowstate + \writestatus\m!TABLE{change \string\MR\space into \string\FR}% + \fi + \tabl_table_end_row_indeed\tablemidrowstate00} + +\protected\def\tabl_table_LR + {\ifnum\tableactionstate=\tablerulestate + \writestatus\m!TABLE{change \string\LR\space into \string\FR/\string\SR}% + \fi + \tabl_table_end_row_indeed\tablelastrowstate\tablerowzero\tablerowfactor} + +%D \macros +%D {ifcheckTABLEcolums} +%D +%D The next macros handle the actual row ending. This macro also take care of space +%D corrections due to table splitting when \type{\MR} and collegues are used. When +%D tracing is enabled, the corrections as well as the values used to determine the +%D available space are shown (in color). By default checking is off. + +\def\tabl_table_end_row_indeed#1#2#3% + {\tabl_table_set_action#1% + \ifcase#1\relax + % unknown + \or + \tabl_tables_end_line\SR\SR\tablerowfactor\tablerowfactor + \or + \tabl_tables_end_line\FR\FR\tablerowfactor\tablerowzero + \or + \ifnum\tableforcestate=\tableforcelastrowstate + \tabl_tables_end_line\MR\LR\tablerowzero\tablerowfactor + \orelse\ifnum\tableforcestate=\tableforcefirstrowstate + \tabl_tables_end_line\MR\FR\tablerowfactor\tablerowzero + \else + \tabl_tables_end_line\MR\MR\tablerowzero\tablerowzero + \fi + \or + \tabl_tables_end_line\LR\LR\tablerowzero\tablerowfactor + \fi + \noalign\bgroup + \tabl_table_set_force\tableunknownstate + \global\currenttablecolumn\zerocount + \ifconditional\preventtablebreak + \nobreak + \else + \goodbreak + \fi + \egroup} + +%D Handling \type{\AR} is postponed till the next row. The check takes care of +%D the first and mid rows, the chuck macro |<|how about that name|>| handles +%D the last row. + +\protected\def\tabl_table_AR + {\glet\tabl_tables_check_auto_row\tabl_tables_check_auto_row_indeed + \glet\tabl_tables_chuck_auto_row\tabl_tables_chuck_auto_row_indeed} + +\let\tabl_tables_check_auto_row\empty +\let\tabl_tables_chuck_auto_row\empty + +\def\tabl_tables_check_auto_row_indeed + {\glet\tabl_tables_check_auto_row\empty + \ifnum\tableactionstate=\tablerulestate \FR\orelse + \ifnum\tableactionstate=\tableunknownstate\FR\else + \MR\fi} + +\def\tabl_tables_chuck_auto_row_indeed + {\glet\tabl_tables_check_auto_row\empty + \glet\tabl_tables_chuck_auto_row\empty + \ifnum\tableactionstate=\tablerulestate \SR\orelse + \ifnum\tableactionstate=\tableunknownstate\SR\else + \LR\fi} + +%D When a table is split, we also add a tail and when present we repeat the table +%D head. If a gets split indeed, the spacing before and after a horizontal rule is +%D corrected according to what we expect. + +\def\tabl_tables_end_line#1#2#3#4% + {\ifx#1#2\else + \writestatus\m!TABLE{\string#1\space changed into \string#2}% + \fi + \expandafter\tabl_table_normal_line_format#3#4\crcr % \crcr nodig ? + \noalign{\nobreak\global\settrue\tableactionstatepermitted}} + +%D In order to prevent (as good as possible) alignment overflow and therefore \TEX\ +%D error messages, we check the maximum number of columns. We keep track of the +%D current column and maximum column by means of two \COUNTERS. Keep in mind that +%D the number of \type{|}'s and \type{\VL}'s or alike is always one more than the +%D number of columns. + +\newcount\currenttablecolumn + +% DWhile defining this macro we change the \CATCODE\ of \type{|}. When counting the +% Dbars, we use a non active representation of the bar, simply because we cannot be +% Dsure if the bar is active or not.\footnote{Normally it is, but \TABLE\ changes +% Dthe catcode when needed.} + +\bgroup + \catcode\barasciicode\othercatcode \permanent\gdef\tabl_table_bar{|} + \catcode\barasciicode\activecatcode\gdef\tabl_table_use_bar{\enforced\let|\tabl_table_bar} +\egroup + +\bgroup \catcode\barasciicode\othercatcode + +\gdef\dogettablenofcolumns#1% todo: also divert this to lua as with tabulate + {\bgroup + \cleanupfeatures % needed ! + \tabl_table_use_bar + \egroup} + +\egroup + +%D \startitemize[3*ruim] +%D \sym{\type{\VL}} a vertical line +%D \sym{\type{\VC}} a vertical colored line +%D \sym{\type{\HL}} a horizontal line +%D \sym{\type{\HC}} a horizontal colored line +%D \stopitemize + +\newcount\c_tabl_table_vrule_thickness_factor +\newcount\c_tabl_table_hrule_thickness_factor +\newcount\c_tabl_table_drule_span + +\let\m_tabl_table_vrule_color\empty +\let\m_tabl_table_hrule_color\empty + +\appendtoks + \enforced\let\VL\tabl_table_VL + \enforced\let\VC\tabl_table_VC + \enforced\let\HL\tabl_table_HL + \enforced\let\HC\tabl_table_HC + \enforced\let\VS\tabl_table_VS + \enforced\let\VD\tabl_table_VD + \enforced\let\VT\tabl_table_VT + \enforced\let\VN\tabl_table_VN +\to \localtabledefinitions + +\def\tabl_table_resetVLvalues + {\global\currenttablecolumn\zerocount} + +\def\tabl_table_vrulecommand#1% global assignments + {\doifelsenumber{#1} + {\global\c_tabl_table_vrule_thickness_factor#1\relax + \global\multiply\c_tabl_table_vrule_thickness_factor\m_tabl_table_VLwidth\relax} + {\xdef\m_tabl_table_vrule_color{#1}}} + +\permanent\tolerant\protected\def\tabl_table_VL[#1]% + {\tabl_tables_check_auto_row + \global\advance\currenttablecolumn\plusone + \glet\m_tabl_table_vrule_color\empty + \global\c_tabl_table_vrule_thickness_factor\m_tabl_table_VLwidth\relax + \iftok{#1}\emptytoks\else + \rawprocesscommalist[#1]\tabl_table_vrulecommand + \fi + \tabl_table_normal_line_complex_bar}% \relax breaks \use + +\permanent\let\tabl_table_VC\tabl_table_VL % for mojca + +% \starttable[|||] +% \HL +% \VL test \VS test \VL \FR +% \VL test \VD test \VL \MR +% \VL test \VT test \VL \LR +% \HL +% \stoptable + +\permanent\protected\def\tabl_table_VS {\VN1} +\permanent\protected\def\tabl_table_VD {\VN2} +\permanent\protected\def\tabl_table_VT {\VN3} +\permanent\protected\def\tabl_table_VN#1{\global\c_tabl_table_n_of_vrules#1\relax\VL} + +\def\tabl_table_hrulecommand#1% global assignments + {\doifelsenumber{#1} + {\global\c_tabl_table_hrule_thickness_factor#1\relax + \global\multiply\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax} + {\xdef\m_tabl_table_hrule_color{#1}}} + +\permanent\tolerant\protected\def\tabl_table_HL[#1]% + {\tabl_tables_chuck_auto_row + \tabl_table_finish_row + \noalign\bgroup + \nobreak + \ifnum\tableactionstate=\tablerulestate + \writestatus\m!TABLE{skipping \string\HL}% \statusmessage + \else + \ifnum\tableactionstate=\tablemidrowstate + \writestatus\m!TABLE{change \string\MR\space into \string\LR/\string\SR}% + \orelse\ifnum\tableactionstate=\tablefirstrowstate + \writestatus\m!TABLE{change \string\MR\space into \string\SR}% + \fi + \bgroup + \global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax + \iffirstargument + \glet\m_tabl_table_hrule_color\empty + \rawprocesscommalist[#1]\tabl_table_hrulecommand + \ifempty\m_tabl_table_hrule_color\else + \switchtocolor[\m_tabl_table_hrule_color]% + \fi + \fi + \tabl_table_normal_full_rule + \egroup + \tabl_table_account_width + \fi + \tabl_table_set_action\tablerulestate + \nobreak + \egroup} + +\aliased\let\tabl_table_HC\tabl_table_HL % for mojca + +%D \startitemize[3*ruim] +%D \sym{\type{\NL}} a vertical skip +%D \sym{\type{\NR}} goto the next row +%D \sym{\type{\NC}} goto the next column +%D \sym{\type{\FC}} a first column +%D \sym{\type{\MC}} a mid column +%D \sym{\type{\LC}} a last column +%D \stopitemize + +% \starttable[|||] +% \VL text \VL text \VL \AR +% \TB[small] +% \VL text \VL text \VL \AR +% \TB[4*big] +% \VL text \VL text \VL \AR +% \stoptable + +% n+1 uitleggen + +\appendtoks + \enforced\let\TB\tabl_table_TB + \enforced\let\NL\tabl_table_NL % old + \enforced\let\NR\tabl_table_NR + \enforced\let\NC\tabl_table_NC + \enforced\let\FC\tabl_table_NC + \enforced\let\MC\tabl_table_NC + \enforced\let\LC\tabl_table_NC +\to \localtabledefinitions + +\permanent\tolerant\protected\def\tabl_table_TB[#1]% + {\tabl_tables_chuck_auto_row + \tabl_table_finish_row + \noalign\bgroup + \blank[\iftok{#1}\emptytoks\c!NL\else#1\fi]% + \nobreak + \egroup} + +\aliased\let\tabl_table_NL\tabl_table_TB + +\protected\def\tabl_table_NR + {\global\currenttablecolumn\zerocount + \tabl_table_normal_line_ending + \noalign\bgroup + \nobreak + \tabl_table_set_action\tableunknownstate + \egroup} + +\protected\def\tabl_table_NC + {\tabl_tables_check_auto_row + \global\advance\currenttablecolumn \plusone + \tabl_table_normal_no_bar} + +%D \startitemize[3*broad] +%D \sym{\type{\DL}} +%D \sym{\type{\DV}} (\type{\VD}) +%D \sym{\type{\DC}} +%D \sym{\type{\DR}} +%D \stopitemize + +\newconditional\c_tabl_table_is_division + +\appendtoks + \global\setfalse\c_tabl_table_is_division + \enforced\let\DL\tabl_table_DL + \enforced\let\DC\tabl_table_DC + \enforced\let\DV\tabl_table_DV + \enforced\let\DR\tabl_table_DR +\to \localtabledefinitions + +\def\tabl_table_check_division + {\ifconditional\c_tabl_table_is_division\else + \tabl_tables_chuck_auto_row + \global\currenttablecolumn\zerocount + \global\settrue\c_tabl_table_is_division + \fi} + +\def\tabl_table_drulecommand#1% global assignments + {\doifelsenumber{#1} + {\ifcase\c_tabl_table_drule_span + \global\c_tabl_table_drule_span#1\relax + \else + \global\c_tabl_table_hrule_thickness_factor#1\relax + \global\multiply\c_tabl_table_hrule_thickness_factor\m_tabl_table_VLwidth\relax + \fi} + {\xdef\m_tabl_table_hrule_color{#1}}} + +\permanent\tolerant\protected\def\tabl_table_DL[#1]% + {\tabl_table_check_division + \ifnum\tableactionstate=\tablerulestate + \writestatus\m!TABLE{skipping \string\DL}% + \else + \ifnum\tableactionstate=\tablemidrowstate + \writestatus\m!TABLE{change \string\MR\space into \string\LR/\string\SR}% + \orelse\ifnum\tableactionstate=\tablefirstrowstate + \writestatus\m!TABLE{change \string\MR\space into \string\SR}% + \fi + \tabl_table_set_action\tableunknownstate + \global\c_tabl_table_hrule_thickness_factor\m_tabl_table_HLheight\relax + \global\c_tabl_table_drule_span\zerocount + \iftok{#1}\emptytoks\else + \glet\m_tabl_table_hrule_color\empty + \rawprocesscommalist[#1]\tabl_table_drulecommand + % \ifempty\m_tabl_table_hrule_color\else + % \switchtocolor[\m_tabl_table_hrule_color]% see *DL* + % \fi + \fi + \ifcase\c_tabl_table_drule_span + \global\advance\currenttablecolumn \plusone + \tabl_table_normal_single_rule + \or + \global\advance\currenttablecolumn \plustwo + \tabl_table_normal_single_rule + \else + \global\advance\currenttablecolumn \plusone + \tabl_table_normal_multi_rule + \fi + \fi} + +\permanent\protected\def\tabl_table_DV + {\tabl_table_DCV\tabl_table_normal_line_simple_bar} + +\permanent\protected\def\tabl_table_DC + {\tabl_table_DCV\tabl_table_normal_no_bar} + +\permanent\protected\def\tabl_table_DCV#1% + {\tabl_table_check_division + \tabl_tables_check_auto_row + \global\advance\currenttablecolumn \plusone + #1} + +\permanent\protected\def\tabl_table_DR + {\global\currenttablecolumn\zerocount % nog check + \tabl_table_normal_line_ending + \noalign\bgroup + \nobreak + \global\setfalse\c_tabl_table_is_division + \tabl_table_account_width % temporary solution + \tabl_table_set_action\tablerulestate + \egroup} + +\def\tabl_table_account_width + {\scratchdimen\d_tabl_table_line_thickness_unit} + +\permanent\def\tabl_table_TWO {\use\plustwo} +\permanent\def\tabl_table_THREE{\use\plusthree} +\permanent\def\tabl_table_FOUR {\use\plusfour} +\permanent\def\tabl_table_FIVE {\use\plusfive} +\permanent\def\tabl_table_SIX {\use\plussix} + +\appendtoks + \enforced\let\TWO \tabl_table_TWO + \enforced\let\THREE\tabl_table_THREE + \enforced\let\FOUR \tabl_table_FOUR + \enforced\let\FIVE \tabl_table_FIVE + \enforced\let\SIX \tabl_table_SIX + \enforced\let\SPAN \use + \enforced\let\REF \tabl_table_reformat +\to \localtabledefinitions + +\installcorenamespace{tables} +\installcorenamespace{tabledistance} +\installcorenamespace{tablealign} + +\installsetuponlycommandhandler \??tables {tables} % some day we can have named tables + +\setvalue{\??tabledistance\v!none }{\tabl_table_OpenUp00\def\LOW{\Lower6 }} +\setvalue{\??tabledistance\v!small }{\tabl_table_OpenUp00\def\LOW{\Lower6 }} % == baseline +\setvalue{\??tabledistance\v!medium}{\tabl_table_OpenUp11\def\LOW{\Lower7 }} +\setvalue{\??tabledistance\v!big }{\tabl_table_OpenUp22\def\LOW{\Lower8 }} + +\appendtoks + \expandnamespaceparameter\??tabledistance\directtablesparameter\c!distance\v!medium +\to \localtabledefinitions + +\setvalue{\??tablealign\v!right }{\def\tabl_table_paralignment{\raggedright}} +\setvalue{\??tablealign\v!left }{\def\tabl_table_paralignment{\raggedleft}} +\setvalue{\??tablealign\v!middle }{\def\tabl_table_paralignment{\raggedcenter}} +\setvalue{\??tablealign\s!unknown}{\def\tabl_table_paralignment{\notragged}} + +\appendtoks + \doifelse{\directtablesparameter\c!distance}\v!none + {\tablerowfactor\zerocount} + {\tablerowfactor\plustwo }% +\to \localtabledefinitions + +\def\dohandlebar % here ? + {\ifmmode + \expandafter\domathmodebar + \orelse\ifintable + \expandafter\domathmodebar + \else + \expandafter\dotextmodebar + \fi} + +\appendtoks + \expandnamespaceparameter\??tablealign\directtablesparameter\c!align\s!unknown + \assignalfadimension{\directtablesparameter\c!VL}\m_tabl_table_VLwidth 246% + \assignalfadimension{\directtablesparameter\c!HL}\m_tabl_table_HLheight246% +\to \everysetuptables + +\def\tabl_table_local_setups + {\directtablesparameter\c!commands\relax + \usebodyfontparameter\directtablesparameter + \d_tabl_table_line_thickness_unit\dimexpr\directtablesparameter\c!rulethickness/\tablelinethicknessfactor\relax + \edef\p_tabl_table_height{\directtablesparameter\c!height}% + \edef\p_tabl_table_depth{\directtablesparameter\c!depth}% + \ifx\p_tabl_table_height\v!strut + \let\tablestrutheightfactor\tablestrutheightfactor + \else + \let\tablestrutheightfactor\p_tabl_table_height + \fi + \ifx\p_tabl_table_depth\v!strut + \let\tablestrutdepthfactor\tablestrutdepthfactor + \else + \let\tablestrutdepthfactor\p_tabl_table_depth + \fi + \edef\tablestrutheightfactor{\withoutpt\the\dimexpr10\dimexpr\tablestrutheightfactor\points}% + \edef\tablestrutdepthfactor {\withoutpt\the\dimexpr10\dimexpr\tablestrutdepthfactor \points}% + \d_tabl_table_strut_unit \dimexpr\normalbaselineskip/12\relax % 12 is default bodyfont + \d_tabl_table_kern_unit .5em\relax + \s_tabl_table_inter_column_space_unit.5em plus 1fil minus .25em\relax + \d_tabl_table_column_width_unit \d_tabl_table_kern_unit + \d_tabl_table_kern_unit \d_tabl_table_kern_unit} + +%D As one can see, we didn't only add color, but also more control over spacing. +%D +%D \startbuffer[a] +%D \starttable[|c|] +%D \HL +%D \VL \strut test \VL \FR +%D \VL \strut test \VL \MR +%D \VL \strut test \VL \MR +%D \VL \strut test \VL \LR +%D \HL +%D \stoptable +%D \stopbuffer +%D +%D \startbuffer[b] +%D \starttabulate[|c|] +%D \HL +%D \NC test \NC \NR +%D \NC test \NC \NR +%D \NC test \NC \NR +%D \NC test \NC \NR +%D \HL +%D \stoptabulate +%D \stopbuffer +%D +%D In the next example, the first table is defined as: +%D +%D \typebuffer[a] +%D +%D and the second one as: +%D +%D \typebuffer[b] +%D +%D The first table is typeset using the default height and depth factors .8 and .4. +%D The second table has both factors set to \type {strut}, and the third table shows +%D what happens when we set the values to zero. The rightmost table is typeset using +%D the tabulate environment. +%D +%D \startcombination[4*1] +%D {$\vcenter{\getbuffer[a]}$} +%D {\hbox{h=.8 d=.4}} +%D {\setuptables[height=strut,depth=strut]$\vcenter{\getbuffer[a]}$} +%D {\hbox{h=d=\type{strut}}} +%D {\setuptables[height=0,depth=0]$\vcenter{\getbuffer[a]}$} +%D {\hbox{h=d=0}} +%D {$\vcenter{\getbuffer[b]}$} +%D {\hbox{tabulate}} +%D \stopcombination + +\setuptables + [\c!HL=\v!medium, + \c!VL=\v!medium, + \c!NL=\v!small, + \c!frame=, + \c!align=\v!right, + \c!depth=.40, % \v!strut + \c!height=.80, % \v!strut + \c!textwidth=, + \c!rulethickness=\linewidth, + \c!rulecolor=, + \c!distance=\v!medium, + \c!bodyfont=, + \c!commands=, + \c!background=, + \c!backgroundcolor=, + \c!split=\v!auto, + \c!openup=\zeropoint] + +\protect \endinput diff --git a/tex/context/base/mkiv/tabl-tbl.lua b/tex/context/base/mkiv/tabl-tbl.lua index 13d899de6..aa4d5051f 100644 --- a/tex/context/base/mkiv/tabl-tbl.lua +++ b/tex/context/base/mkiv/tabl-tbl.lua @@ -18,13 +18,16 @@ local commands = commands local texsetcount = tex.setcount -local separator = P("|") -local nested = lpeg.patterns.nested -local pattern = Ct((separator * (C(nested) + Cc("")) * C((1-separator)^0))^0) +local separator = P("|") -- keep { } +----- nested = C(lpeg.patterns.nested) -- remove { } +local nested = lpeg.patterns.argument +local pattern = Ct((separator * (nested + Cc("")) * C((1-separator)^0))^0) local ctx_settabulatelastentry = context.settabulatelastentry local ctx_settabulateentry = context.settabulateentry +-- the lmtx raw processor handles {} like the normal one so we need to prune + local function presettabulate(preamble) preamble = gsub(preamble,"~","d") -- let's get rid of ~ mess here if find(preamble,"*",1,true) then diff --git a/tex/context/base/mkiv/tabl-tbl.mkxl b/tex/context/base/mkiv/tabl-tbl.mkxl index 4b2f31721..e9d45e0e8 100644 --- a/tex/context/base/mkiv/tabl-tbl.mkxl +++ b/tex/context/base/mkiv/tabl-tbl.mkxl @@ -231,8 +231,8 @@ \newtoks \everytabulatepar % where used ? \newtoks \everytabulate % public ? -\unexpanded\def\tolerantTABLEbreaktrue {\settrue \c_tabl_tabulate_tolerant_break} % used in styles ! -\unexpanded\def\handletabulatepbreakfalse{\setfalse\c_tabl_tabulate_handlepbreak } % depricated +\protected\def\tolerantTABLEbreaktrue {\settrue \c_tabl_tabulate_tolerant_break} % used in styles ! +\protected\def\handletabulatepbreakfalse{\setfalse\c_tabl_tabulate_handlepbreak } % depricated \def\noftabulaterows{\number\c_tabl_tabulate_noflines} % handy for testing if a table is empty @@ -297,22 +297,6 @@ % 1 = RC column raw RQ equal column raw % 2 = HC column hook HQ equal column hook -% handy helper (problem: we have an extra group when we nest; playing with en engine -% solution turned out to be too messy due to states; an ignoreendgroup trick also is -% messy and interferes). - -\def\tabulatenoalign % public ? - {\noalign - \bgroup - \let\noalign\relax - \let\tabulatenoalign\relax - \let\next=} - -\def\starttabulatenoalign % public ? - {\tabulatenoalign\bgroup} - -\let\stoptabulatenoalign\egroup - % [|lg{.}|] => \NG 12.34 \NC \def\tabl_tabulate_nobreak_inject_tracer @@ -334,22 +318,22 @@ \tabl_tabulate_break_no_tracer} \def\tabl_tabulate_nobreak_inject - {\tabulatenoalign{\tabl_tabulate_nobreak_inject_indeed}} + {\noalign{\tabl_tabulate_nobreak_inject_indeed}} -\unexpanded\def\tabl_tabulate_hook_check +\protected\def\tabl_tabulate_hook_check {\ifnum\c_tabl_tabulate_type<\plustwo \glet\tabl_tabulate_hook\tabl_tabulate_hook_nop \else \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes \fi} -\unexpanded\def\tabl_tabulate_setups_check +\protected\def\tabl_tabulate_setups_check {\begincsname\??tabulatesetup\the\c_tabl_tabulate_column\endcsname} -\unexpanded\def\tabl_tabulate_entry_before{\ignorespaces\tabl_tabulate_hook} -\unexpanded\def\tabl_tabulate_entry_after {\unskip\unskip\ifmmode\else\endgraf\fi} +\protected\def\tabl_tabulate_entry_before{\ignorespaces\tabl_tabulate_hook} +\protected\def\tabl_tabulate_entry_after {\unskip\unskip\ifmmode\else\endgraf\fi} -\unexpanded\def\tabl_tabulate_shaped_par_begin +\protected\def\tabl_tabulate_shaped_par_begin {\dowithnextboxcs\tabl_tabulate_shaped_par_finish\vbox\bgroup} \def\tabl_tabulate_shaped_par_finish @@ -361,10 +345,10 @@ \ifdefined\dotagtabulatecell \else \let\dotagtabulatecell \relax \fi \ifdefined\dotagtabulatesignal \else \let\dotagtabulatesignal\relax \fi -\unexpanded\def\tabl_tabulate_check_local_color_first#1#2% +\protected\def\tabl_tabulate_check_local_color_first#1#2% {\relax} -\unexpanded\def\tabl_tabulate_check_local_color_second#1#2% +\protected\def\tabl_tabulate_check_local_color_second#1#2% {\relax \ifempty\m_tabl_tabulate_color_local \xdef\m_tabl_tabulate_color{#1}% @@ -379,7 +363,7 @@ \global\c_tabl_tabulate_localcolorspan\zerocount \fi} -\unexpanded\def\tabl_tabulate_check_local_vrule_thickness#1% +\protected\def\tabl_tabulate_check_local_vrule_thickness#1% {\relax \ifcase\d_tabl_tabulate_vrulethickness_local \global\d_tabl_tabulate_vrulethickness#1\relax @@ -388,10 +372,10 @@ \global\d_tabl_tabulate_vrulethickness_local\zeropoint \fi} -\unexpanded\def\tabl_tabulate_check_local_vrule_color_first#1% +\protected\def\tabl_tabulate_check_local_vrule_color_first#1% {\relax} -\unexpanded\def\tabl_tabulate_check_local_vrule_color_second#1% +\protected\def\tabl_tabulate_check_local_vrule_color_second#1% {\relax \ifempty\m_tabl_tabulate_vrule_color_local \xdef\m_tabl_tabulate_vrule_color{#1}% @@ -413,7 +397,7 @@ \let\tabl_tabulate_check_local_vrule_color\tabl_tabulate_check_local_vrule_color_second \to \t_tabl_tabulate_initializers_second -% \unexpanded % we can expand this one +% \protected % we can expand this one \def\tabl_tabulate_inject_pre_skip#1% {\ifdim#1>\zeropoint \kern#1\relax % was \hskip @@ -425,7 +409,7 @@ \fi \fi} -% \unexpanded % we can expand this one +% \protected % we can expand this one \def\tabl_tabulate_inject_post_skip#1% {\ifdim#1>\zeropoint \kern#1\relax % was \hskip @@ -531,7 +515,7 @@ %\let\gettabulateexit\dogettabulateexit % still needed ? \d_tabl_tabulate_width\zeropoint} -\unexpanded\def\installtabulatepreambleoption#1#2% +\protected\def\installtabulatepreambleoption#1#2% {\setvalue{\??tabulatepreamble\string#1}{#2}}% \installtabulatepreambleoption{x}{\c_tabl_tabulate_align\zerocount @@ -824,6 +808,7 @@ \global\d_tabl_tabulate_vrulethickness\zeropoint \else \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default + % the lmtx raw processor handles {} like the normal one so we need to prune \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command \fi \tabl_tabulate_set_preamble#2\relax\relax % permits i without n @@ -906,7 +891,7 @@ \tabl_tabulate_check_linenumbers \box\b_tabl_tabulate} -\unexpanded\def\tabl_tabulate_hook_nop +\protected\def\tabl_tabulate_hook_nop {} \let\tabl_tabulate_hook\tabl_tabulate_hook_nop @@ -945,12 +930,12 @@ \fi} \def\tabl_tabulate_pbreak_check - {\starttabulatenoalign + {\noalign\bgroup \tabl_tabulate_pbreak_inject \ifconditional\c_tabl_tabulate_splitoff_whitespace \tabl_tabulate_whitespace \fi - \stoptabulatenoalign} + \egroup} %D \startbuffer %D \starttabulate[|c|p|p|] @@ -1040,44 +1025,42 @@ %\c!title=, \c!indenting=\v!no] -\unexpanded\def\definetabulate - {\dotripleempty\tabl_tabulate_define} - -\def\tabl_tabulate_define[#1][#2][#3]% - {\ifthirdargument +\permanent\tolerant\protected\def\definetabulate[#1]#*[#2]#*[#3]% + {\ifarguments + % ignore + \or + % [tag] + \definetabulation[#1][\c!format={|l|p|},\s!check=]% + \or + % [tag] [template] + \definetabulation[#1][\c!format={#2},\s!check=]% + \or % [tag] [sub] [template] \ifcsname\namedtabulationhash{#1}\s!check\endcsname \else \definetabulation[#1][\c!format={#3},\s!check=]% \fi \definetabulation[#1:#2][#1][\c!format={#3},\s!check=]% - \orelse\ifsecondargument - % [tag] [template] - \definetabulation[#1][\c!format={#2},\s!check=]% - \else - % [tag] - \definetabulation[#1][\c!format={|l|p|},\s!check=]% \fi} -\unexpanded\def\setuptabulate - {\dotripleempty\tabl_tabulate_setup} - -\def\tabl_tabulate_setup[#1][#2][#3]% - {\ifthirdargument - % [tag] [sub] [settings] - \setuptabulation[#1:#2][#3]% - \orelse\ifsecondargument - % [tag] [settings] - \setuptabulation[#1][#2]% - \else +\permanent\tolerant\protected\def\setuptabulate[#1]#*[#2]#*[#3]% + {\ifarguments + % ignore + \or % [tag] \setuptabulation[#1]% + \or + % [tag] [settings] + \setuptabulation[#1][#2]% + \or + % [tag] [sub] [settings] + \setuptabulation[#1:#2][#3]% \fi} \appendtoks - \setuevalue{\e!start\currenttabulation}{\tabl_start_defined[\currenttabulation]}% - \letvalue{\e!stop\currenttabulation}\relax - \letvalue{\??tabulatehead\currenttabulation}\empty - \letvalue{\??tabulatefoot\currenttabulation}\empty + \enforced\expandafter\edef\csname\e!start \currenttabulation\endcsname{\tabl_start_defined[\currenttabulation]}% + \enforced\expandafter\let \csname\e!stop \currenttabulation\endcsname\relax + \enforced\expandafter\let \csname\??tabulatehead\currenttabulation\endcsname\empty + \enforced\expandafter\let \csname\??tabulatefoot\currenttabulation\endcsname\empty \to \everydefinetabulation \let\tabulateparameter\tabulationparameter % will stay for a while @@ -1090,14 +1073,14 @@ \let\tabl_tabulate_insert_foot\empty \def\tabl_tabulate_insert_head_content - {\tabulatenoalign{\global\settrue\c_tabl_tabulate_someamble}% + {\noalign{\global\settrue\c_tabl_tabulate_someamble}% \begincsname\??tabulatehead\currenttabulation\endcsname - \tabulatenoalign{\global\setfalse\c_tabl_tabulate_someamble}}% + \noalign{\global\setfalse\c_tabl_tabulate_someamble}}% \def\tabl_tabulate_insert_foot_content - {\tabulatenoalign{\global\settrue\c_tabl_tabulate_someamble}% + {\noalign{\global\settrue\c_tabl_tabulate_someamble}% \begincsname\??tabulatefoot\currenttabulation\endcsname - \tabulatenoalign{\global\setfalse\c_tabl_tabulate_someamble}}% + \noalign{\global\setfalse\c_tabl_tabulate_someamble}}% \def\tabl_tabulate_check_full_content % - needed, else confusion with \c!header {\ifcsname\??tabulatehead\currenttabulation\endcsname @@ -1124,7 +1107,7 @@ \def\tabl_tabulate_insert_content {\tabl_tabulate_insert_head \ifcase\c_tabl_tabulate_repeathead \else - \tabulatenoalign{\penalty\zerocount}% added 7/5/2014 WS mail + \noalign{\penalty\zerocount}% added 7/5/2014 WS mail \fi \tabl_tabulate_insert_body \tabl_tabulate_insert_foot @@ -1133,7 +1116,7 @@ \def\tabl_tabulate_remove_funny_line {\ifhmode \strut\crcr - \tabulatenoalign{\kern-\lineheight}% + \noalign{\kern-\lineheight}% \fi} % todo: make footer synonym to tail @@ -1152,95 +1135,70 @@ \def\tabl_tabulate_start_head_nop{\tabl_tabulate_start_head_yes[\v!tabulate]} \def\tabl_tabulate_start_foot_nop{\tabl_tabulate_start_foot_yes[\v!tabulate]} -\unexpanded\def\tabl_start_defined[#1]% +\protected\def\tabl_start_defined[#1]% {\bgroup \edef\currenttabulationparent{#1}% \let\currenttabulation\currenttabulationparent - \edef\p_format{\tabulationparameter\c!format}% - \ifx\p_format\v!none + \iftok{\tabulationparameter\c!format}{\v!none}% % this is special case: we need to define the generic english % \starttabulate in other interfaces as well - \expandafter\dodoubleempty \expandafter\tabl_start_regular + \lettabulationparameter\c!format\tabl_default_format + \expandafter\tabl_start_regular \else - \expandafter\dodoubleargument\expandafter\tabl_start_defined_indeed + \expandafter\tabl_start_defined_indeed \fi} -\def\tabl_start_defined_indeed - {\iffirstargument - \ifsecondargument - \doubleexpandafter\tabl_start_defined_two +\tolerant\def\tabl_start_defined_indeed[#1]#*[#2]% + {\ifarguments\or + \ifhastok={#1}% + \setuptabulation[\currenttabulation][#1]% \else - \doubleexpandafter\tabl_start_defined_one + \edef\currenttabulation{\currenttabulation:#1}% \fi \else - \singleexpandafter\tabl_start_defined_zero - \fi} - -\def\tabl_start_defined_one[#1][#2]% - {\ifcondition\validassignment{#1}% - \setuptabulation[\currenttabulation][#1]% - \else \edef\currenttabulation{\currenttabulation:#1}% + \setuptabulation[\currenttabulation][#2]% \fi \tabl_tabulate_start_building} -\def\tabl_start_defined_two[#1][#2]% - {\edef\currenttabulation{\currenttabulation:#1}% - \setuptabulation[\currenttabulation][#2]% - \tabl_tabulate_start_building} - -\def\tabl_start_defined_zero[#1][#2]% - {\tabl_tabulate_start_building} - % \definetabulate[\v!tabulate][|l|p|] % we need to get rid of this one -\unexpanded\setuvalue{\e!start\v!tabulate}% +\def\tabl_default_format{|l|p|} % actually format is always set + +\permanent\protected\setuvalue{\e!start\v!tabulate}% {\bgroup % whole thing \let\currenttabulationparent\empty - \dodoubleempty\tabl_start_regular} + \tabl_start_regular} -\def\tabl_start_regular +\tolerant\protected\def\tabl_start_regular[#1]#*[#2]% [format] | [settings] | [format] [settings] | [settings] [format] {\let\currenttabulation\currenttabulationparent - \ifsecondargument - \expandafter\tabl_start_regular_two - \else - \expandafter\tabl_start_regular_one - \fi} - -\def\tabl_default_format{|l|p|} - -\def\tabl_start_regular_one[#1][#2]% - {\ifcondition\validassignment{#1}% - \lettabulationparameter\c!format\tabl_default_format + \iftok{#1}\emptytoks + \ifhastok={#2}\relax + \setupcurrenttabulation[#2]% + \fi + \orelse\ifhastok={#1} + \ifhastok{#2}\relax + \settabulationparameter\c!format{#2}% + \fi \setupcurrenttabulation[#1]% \else - \def\p_format{#1}% - \ifempty\p_format - \def\p_format{|l|p|}% + \settabulationparameter\c!format{#1}% + \ifhastok={#2}\relax + \setupcurrenttabulation[#2]% \fi - \lettabulationparameter\c!format\p_format - \fi - \tabl_tabulate_start_building} - -\def\tabl_start_regular_two[#1][#2]% - {\def\p_format{#1}% - \ifempty\p_format - \let\p_format\tabl_default_format \fi - \lettabulationparameter\c!format\p_format - \setupcurrenttabulation[#2]% \tabl_tabulate_start_building} \letvalue{\e!stop\v!tabulate }\relax \letvalue{\e!stop\v!tabulatehead}\relax \letvalue{\e!stop\v!tabulatetail}\relax -\unexpanded\def\tabl_tabulate_start_ignore +\permanent\protected\def\tabl_tabulate_start_ignore % todo when we go frozen {\em Nested tabulate is not (yet) supported.\relax \expandafter\gobbleuntil\csname\ifconditional\c_tabl_generic stoptabulate\else\e!stop\v!tabulate\fi\endcsname} \appendtoks - \letvalue{\e!start\v!tabulate}\tabl_tabulate_start_ignore % only the main one + \enforced\letvalue{\e!start\v!tabulate}\tabl_tabulate_start_ignore % only the main one \to \everytabulate \setvalue{\??tabulatesplit\v!yes }{\settrue\c_tabl_tabulate_split} @@ -1283,7 +1241,7 @@ \let\tabl_tabulate_inside_inbetween \relax \let\tabl_tabulate_outside_inbetween\relax -\unexpanded\def\tabl_tabulate_inside_before +\protected\def\tabl_tabulate_inside_before {\ifhmode\par\fi \ifhmode \ifinsidesplitfloat @@ -1296,7 +1254,7 @@ \let\tabl_tabulate_inside_after\relax \fi} -\unexpanded\def\tabl_tabulate_outside_before +\protected\def\tabl_tabulate_outside_before {\ifhmode\par\fi \ifhmode \vbox\bgroup @@ -1328,7 +1286,7 @@ \verticalstrut \vskip-\struttotal}} -\unexpanded\def\tabl_tabulate_start_building +\protected\def\tabl_tabulate_start_building {\ifinsidefloat \tabl_tabulate_inside_before \else @@ -1380,7 +1338,7 @@ \tabulationparameter\c!inner \d_tabl_tabulate_indent\dimexpr\leftskip+\hangindent\ifx\p_indenting\v!yes+\parindent\fi\relax \global\c_tabl_tabulate_column\zerocount - \processcontent + \processcontent % stoptabulate needs to match the frozen one {\ifconditional\c_tabl_generic stoptabulate\else\e!stop\ifempty\currenttabulationparent\v!tabulate\else\currenttabulationparent\fi\fi} \tabl_tabulate_insert_body \tabl_tabulate_process} @@ -1422,13 +1380,13 @@ \global \d_tabl_tabulate_vrulethickness_local\zeropoint \to \t_tabl_tabulate_every_row -\unexpanded\def\tabl_tabulate_color_side_right_second +\protected\def\tabl_tabulate_color_side_right_second {\ifempty\m_tabl_tabulate_color_previous \else \tabl_tabulate_color_set\m_tabl_tabulate_color_previous \glet\m_tabl_tabulate_color_previous\empty \fi} -\unexpanded\def\tabl_tabulate_color_side_left_second +\protected\def\tabl_tabulate_color_side_left_second {\ifempty\m_tabl_tabulate_color \else \ifcase\c_tabl_tabulate_colorspan \or @@ -1438,7 +1396,7 @@ \fi \fi} -\unexpanded\def\tabl_tabulate_color_side_both_second +\protected\def\tabl_tabulate_color_side_both_second {\ifempty\m_tabl_tabulate_color \else \tabl_tabulate_color_set\m_tabl_tabulate_color \ifcase\c_tabl_tabulate_colorspan @@ -1462,7 +1420,7 @@ \let\tabl_tabulate_color_side_both \tabl_tabulate_color_side_both_second \to \t_tabl_tabulate_initializers_second -\def\tabl_tabulate_set_color_column#1% overloaded +\def\tabl_tabulate_set_color_column#1% overloaded / todo {\unskip \doifelsefastoptionalcheck{\tabl_tabulate_set_color_column_yes#1}{\tabl_tabulate_set_color_column_nop#1}} @@ -1566,13 +1524,13 @@ {\dousecolorparameter\m_tabl_tabulate_vrule_color \vrule\s!width\d_tabl_tabulate_vrulethickness\relax} -\unexpanded\def\tabl_tabulate_column_vrule_inject_first +\protected\def\tabl_tabulate_column_vrule_inject_first {\ifcase\d_tabl_tabulate_vrulethickness\else \tabl_tabulate_column_vruled_normal % could be a skip instead \fi \global\d_tabl_tabulate_vrulethickness\zeropoint} % nils second one -\unexpanded\def\tabl_tabulate_column_vrule_inject_second +\protected\def\tabl_tabulate_column_vrule_inject_second {\ifcase\d_tabl_tabulate_vrulethickness\else \ifempty\m_tabl_tabulate_vrule_color \tabl_tabulate_column_vruled_normal @@ -1602,9 +1560,9 @@ \expandafter\ignorespaces % interferes with the more tricky hooks \fi} -\unexpanded\def\setquicktabulate#1% see \startlegend \startgiven (for the moment still public) - {\let#1\tabl_tabulate_column_inject_auto - \let\\\tabl_tabulate_column_inject_auto} % brrr, will go +\protected\def\setquicktabulate#1% see \startlegend \startgiven (for the moment still public) + {\enforced\let#1\tabl_tabulate_column_inject_auto + \enforced\let\\\tabl_tabulate_column_inject_auto} % brrr, will go \setvalue{\??tabulateseparator\v!blank }{\s_tabl_tabulate_separator\bigskipamount} \setvalue{\??tabulateseparator\v!depth }{\s_tabl_tabulate_separator\strutdp} @@ -1636,24 +1594,15 @@ \directvskip\s_tabl_tabulate_separator \egroup} -\def\tabl_tabulate_hrule_spec_ignore#1% - {%\glet\currenttabulationlocalhrulecolor\empty - %\global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default - \doifelsefastoptionalcheck#1#1} - -\def\tabl_tabulate_hrule_spec_pickup#1% - {\glet\currenttabulationlocalhrulecolor\m_tabl_tabulate_hrule_color_default - \global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default - \doifelsefastoptionalcheck{\tabl_tabulate_hrule_preset#1}#1} - \def\tabl_tabulate_hrule_preset_step#1% {\doifelsenumber{#1} {\global\d_tabl_tabulate_hrulethickness_local#1\d_tabl_tabulate_hrulethickness_default} {\xdef\currenttabulationlocalhrulecolor{#1}}} -\def\tabl_tabulate_hrule_preset#1[#2]% - {\rawprocesscommalist[#2]\tabl_tabulate_hrule_preset_step - #1} +\def\tabl_tabulate_hrule_preset[#1]% + {\glet\currenttabulationlocalhrulecolor\m_tabl_tabulate_hrule_color_default + \global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default + \iftok{#1}\emptytoks\else\rawprocesscommalist[#1]\tabl_tabulate_hrule_preset_step\fi} \def\tabl_tabulate_hrule_inject_normal {\autorule @@ -1666,12 +1615,12 @@ {\dousecolorparameter\currenttabulationlocalhrulecolor \tabl_tabulate_hrule_inject_normal} -\unexpanded\def\tabl_tabulate_hrule_inject_first +\protected\def\tabl_tabulate_hrule_inject_first {\ifcase\d_tabl_tabulate_hrulethickness_local\else \tabl_tabulate_hrule_inject_normal \fi} -\unexpanded\def\tabl_tabulate_hrule_inject_second +\protected\def\tabl_tabulate_hrule_inject_second {\ifcase\d_tabl_tabulate_hrulethickness_local\else \ifempty\currenttabulationlocalhrulecolor \tabl_tabulate_hrule_inject_normal @@ -1715,7 +1664,7 @@ % \NC test \CC[yellow] test \NC test \NC \NR % \stoptabulate -\unexpanded\def\tabl_tabulate_color_set#1% we could store the attributes at the cost of a lua call +\protected\def\tabl_tabulate_color_set#1% we could store the attributes at the cost of a lua call {\begingroup \clf_enablebackgroundalign % was \node_backgrounds_align_initialize \glet\tabl_tabulate_color_repeat\tabl_tabulate_color_repeat_second @@ -1821,7 +1770,7 @@ \def\tabl_tabulate_digits{\digits} -%D Beware, we cannot use \type {\unexpanded} on \type {\HL} cum suis, since \TEX's +%D Beware, we cannot use \type {\protected} on \type {\HL} cum suis, since \TEX's %D hard coded noalign lookahead fails on it! I mistakenly added this for a while. \setvalue{\??tabulatealigning\v!normal}{0} @@ -1832,10 +1781,10 @@ \setvalue{\??tabulateheader\v!repeat}{\plusone} \setvalue{\??tabulateheader\v!text }{\plustwo} -\unexpanded\def\tabl_tabulate_bskip_first {\setbox\b_tabl_tabulate\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop} -\unexpanded\def\tabl_tabulate_eskip_first {\par\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes} -\unexpanded\def\tabl_tabulate_xbskip_first{\hpack\bgroup\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop} -\unexpanded\def\tabl_tabulate_xeskip_first{\par\egroup\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes} +\protected\def\tabl_tabulate_bskip_first {\setbox\b_tabl_tabulate\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop} +\protected\def\tabl_tabulate_eskip_first {\par\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes} +\protected\def\tabl_tabulate_xbskip_first{\hpack\bgroup\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop} +\protected\def\tabl_tabulate_xeskip_first{\par\egroup\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes} \let\tabl_tabulate_bbskip\relax \let\tabl_tabulate_eeskip\relax @@ -1873,28 +1822,28 @@ % so far -\unexpanded\def\tabl_tabulate_VL_first{\tabl_tabulate_column_vruled\zerocount\zerocount} -\unexpanded\def\tabl_tabulate_NC_first{\tabl_tabulate_column_normal\zerocount\zerocount} -\unexpanded\def\tabl_tabulate_RC_first{\tabl_tabulate_column_normal\zerocount\plusone} -\unexpanded\def\tabl_tabulate_HC_first{\tabl_tabulate_column_normal\zerocount\plustwo} -\unexpanded\def\tabl_tabulate_EQ_first{\tabl_tabulate_column_equal \plustwo \zerocount} -\unexpanded\def\tabl_tabulate_RQ_first{\tabl_tabulate_column_equal \zerocount\plusone} -\unexpanded\def\tabl_tabulate_HQ_first{\tabl_tabulate_column_equal \zerocount\plustwo} +\permanent\protected\def\tabl_tabulate_VL_first{\tabl_tabulate_column_vruled\zerocount\zerocount} +\permanent\protected\def\tabl_tabulate_NC_first{\tabl_tabulate_column_normal\zerocount\zerocount} +\permanent\protected\def\tabl_tabulate_RC_first{\tabl_tabulate_column_normal\zerocount\plusone} +\permanent\protected\def\tabl_tabulate_HC_first{\tabl_tabulate_column_normal\zerocount\plustwo} +\permanent\protected\def\tabl_tabulate_EQ_first{\tabl_tabulate_column_equal \plustwo \zerocount} +\permanent\protected\def\tabl_tabulate_RQ_first{\tabl_tabulate_column_equal \zerocount\plusone} +\permanent\protected\def\tabl_tabulate_HQ_first{\tabl_tabulate_column_equal \zerocount\plustwo} -\unexpanded\def\tabl_tabulate_NG_first{\tabl_tabulate_column_normal\zerocount\zerocount} -\unexpanded\def\tabl_tabulate_NN_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % new, undocumented, test first -\unexpanded\def\tabl_tabulate_ND_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % same, for old times sake +\permanent\protected\def\tabl_tabulate_NG_first{\tabl_tabulate_column_normal\zerocount\zerocount} +\permanent\protected\def\tabl_tabulate_NN_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % new, undocumented, test first +\permanent\protected\def\tabl_tabulate_ND_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % same, for old times sake -\unexpanded\def\tabl_tabulate_NR_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_check_penalties} % next row -\unexpanded\def\tabl_tabulate_NB_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_nobreak_inject } % next row no break +\permanent\protected\def\tabl_tabulate_NR_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_check_penalties} % next row +\permanent\protected\def\tabl_tabulate_NB_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_nobreak_inject } % next row no break -\unexpanded\def\tabl_tabulate_NR_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_check_penalties} % next row -\unexpanded\def\tabl_tabulate_NB_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_nobreak_inject } % next row no break +\permanent\protected\def\tabl_tabulate_NR_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_check_penalties} % next row +\permanent\protected\def\tabl_tabulate_NB_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_nobreak_inject } % next row no break -\unexpanded\def\tabl_tabulate_CC_first{\global\c_tabl_tabulate_localcolorspan\zerocount\tabl_tabulate_set_color_column\zerocount} -\unexpanded\def\tabl_tabulate_CL_first{\global\c_tabl_tabulate_localcolorspan\plusone \tabl_tabulate_set_color_column\zerocount} -\unexpanded\def\tabl_tabulate_CM_first{\global\c_tabl_tabulate_localcolorspan\plustwo \tabl_tabulate_set_color_column\zerocount} -\unexpanded\def\tabl_tabulate_CR_first{\global\c_tabl_tabulate_localcolorspan\plusthree\tabl_tabulate_set_color_column\zerocount} +\permanent\protected\def\tabl_tabulate_CC_first{\global\c_tabl_tabulate_localcolorspan\zerocount\tabl_tabulate_set_color_column\zerocount} +\permanent\protected\def\tabl_tabulate_CL_first{\global\c_tabl_tabulate_localcolorspan\plusone \tabl_tabulate_set_color_column\zerocount} +\permanent\protected\def\tabl_tabulate_CM_first{\global\c_tabl_tabulate_localcolorspan\plustwo \tabl_tabulate_set_color_column\zerocount} +\permanent\protected\def\tabl_tabulate_CR_first{\global\c_tabl_tabulate_localcolorspan\plusthree\tabl_tabulate_set_color_column\zerocount} %D Sort of special: %D @@ -1920,53 +1869,50 @@ %D %D \typebuffer \getbuffer -\unexpanded\def\tabl_tabulate_NI_first{\doifelsefastoptionalcheck\tabl_tbl_NI_yes\tabl_tbl_NI_nop} - -\def\tabl_tbl_NI_yes[#1]{\NC \itemtag[#1]\NC} -\def\tabl_tbl_NI_nop {\NC \itemtag \NC} +\permanent\tolerant\protected\def\tabl_tabulate_NI_first[#1]{\NC\itemtag[#1]\NC} %D The following shortcut is handy for tables where one needs bold headers: -\unexpanded\def\tabl_tabulate_BC_first +\permanent\protected\def\tabl_tabulate_BC_first {\tabl_tabulate_column_normal\plusone\zerocount \let\fontstyle\globalfontstyle \bf} \appendtoks - \let\VL\tabl_tabulate_VL_first - \let\NC\tabl_tabulate_NC_first - \let\BC\tabl_tabulate_BC_first - \let\RC\tabl_tabulate_RC_first - \let\HC\tabl_tabulate_HC_first - \let\EQ\tabl_tabulate_EQ_first - \let\RQ\tabl_tabulate_RQ_first - \let\HQ\tabl_tabulate_HQ_first - \let\NG\tabl_tabulate_NG_first - \let\NN\tabl_tabulate_NN_first - \let\ND\tabl_tabulate_ND_first - \let\NR\tabl_tabulate_NR_first - \let\NB\tabl_tabulate_NB_first - \let\CC\tabl_tabulate_CC_first - \let\CL\tabl_tabulate_CL_first - \let\CM\tabl_tabulate_CM_first - \let\CR\tabl_tabulate_CR_first - \let\NI\tabl_tabulate_NI_first + \enforced\let\VL\tabl_tabulate_VL_first + \enforced\let\NC\tabl_tabulate_NC_first + \enforced\let\BC\tabl_tabulate_BC_first + \enforced\let\RC\tabl_tabulate_RC_first + \enforced\let\HC\tabl_tabulate_HC_first + \enforced\let\EQ\tabl_tabulate_EQ_first + \enforced\let\RQ\tabl_tabulate_RQ_first + \enforced\let\HQ\tabl_tabulate_HQ_first + \enforced\let\NG\tabl_tabulate_NG_first + \enforced\let\NN\tabl_tabulate_NN_first + \enforced\let\ND\tabl_tabulate_ND_first + \enforced\let\NR\tabl_tabulate_NR_first + \enforced\let\NB\tabl_tabulate_NB_first + \enforced\let\CC\tabl_tabulate_CC_first + \enforced\let\CL\tabl_tabulate_CL_first + \enforced\let\CM\tabl_tabulate_CM_first + \enforced\let\CR\tabl_tabulate_CR_first + \enforced\let\NI\tabl_tabulate_NI_first \to \t_tabl_tabulate_initializers_first \appendtoks - \let\NR\tabl_tabulate_NR_second - \let\NB\tabl_tabulate_NB_second + \enforced\let\NR\tabl_tabulate_NR_second + \enforced\let\NB\tabl_tabulate_NB_second \to \t_tabl_tabulate_initializers_second \appendtoks - \let\SR\NR - \let\FR\NR - \let\MR\NR - \let\LR\NR - \let\AR\NR + \enforced\let\SR\NR + \enforced\let\FR\NR + \enforced\let\MR\NR + \enforced\let\LR\NR + \enforced\let\AR\NR \to \t_tabl_tabulate_initializers_first -\unexpanded\def\tabl_tabulate_NR_common#1#2% +\permanent\protected\def\tabl_tabulate_NR_common#1#2% {\global\advance\c_tabl_tabulate_noflines\plusone \global\setfalse\c_tabl_tabulate_firstflushed \global\setfalse\c_tabl_tabulate_equal @@ -1977,10 +1923,7 @@ \tabl_tabulate_pheight_reset \unskip\unskip\crcr\tabl_tabulate_flush_collected % can we omit the next one in the first run? probably - \starttabulatenoalign - \the\t_tabl_tabulate_every_after_row - #2% - \stoptabulatenoalign} + \noalign{\the\t_tabl_tabulate_every_after_row#2}} \def\tabl_tabulate_check_penalties {\ifconditional\c_tabl_tabulate_tolerant_break\else @@ -2005,20 +1948,20 @@ \fi \global\setfalse\c_tabl_tabulate_firstflushed} -\unexpanded\def\tabl_tabulate_bbskip_second_split_yes +\protected\def\tabl_tabulate_bbskip_second_split_yes {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column \ifempty\tabl_tabulate_flush_collected_indeed\else \setbox0\hbox \fi \fi} -\unexpanded\def\tabl_tabulate_eskip_second +\protected\def\tabl_tabulate_eskip_second {\par\egroup \tabl_tabulate_pheight_set \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes \tabl_tabulate_splitoff_box} -\unexpanded\def\tabl_tabulate_bskip_second_split_yes +\protected\def\tabl_tabulate_bskip_second_split_yes {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column % first line \global\setbox\b_tabl_tabulate_current\c_tabl_tabulate_column\vbox @@ -2037,33 +1980,33 @@ \expandafter\tabl_tabulate_splitoff_box \fi} -\unexpanded\def\tabl_tabulate_xbskip_second{\tabl_tabulate_bskip} -\unexpanded\def\tabl_tabulate_xeskip_second{\tabl_tabulate_eskip} +\protected\def\tabl_tabulate_xbskip_second{\tabl_tabulate_bskip} +\protected\def\tabl_tabulate_xeskip_second{\tabl_tabulate_eskip} -\unexpanded\def\tabl_tabulate_flush_second_indeed +\protected\def\tabl_tabulate_flush_second_indeed {\glet\tabl_tabulate_flush_collected_indeed\empty \global\c_tabl_tabulate_column\zerocount \tabl_tabulate_pbreak_check \dofastloopcs\c_tabl_tabulate_columns\tabl_tabulate_flush_second_step \global\settrue\c_tabl_tabulate_firstflushed} -\unexpanded\def\tabl_tabulate_flush_second_step +\protected\def\tabl_tabulate_flush_second_step {\ifvoid\b_tabl_tabulate_current\fastloopindex\else \gdef\tabl_tabulate_flush_collected_indeed{\the\t_tabl_tabulate_dummy}% \fi} \def\tabl_tabulate_flush_second - {\tabulatenoalign{\tabl_tabulate_flush_second_indeed}% + {\noalign{\tabl_tabulate_flush_second_indeed}% \tabl_tabulate_flush_collected_indeed} -\unexpanded\def\tabl_tabulate_bskip_second_split_nop +\protected\def\tabl_tabulate_bskip_second_split_nop {\vtop\bgroup \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi % \begstrut % interferes with pre-\pars % evt: \appendtoks\begstrut\to\everypar \ignorespaces} -\unexpanded\def\tabl_tabulate_eskip_second_split_nop % vertical strut added august 2003 +\protected\def\tabl_tabulate_eskip_second_split_nop % vertical strut added august 2003 {\par\verticalstrut \vskip-\struttotal \egroup} @@ -2090,19 +2033,15 @@ % \starttabulate[||] \dorecurse{100}{\NC Eins \NC \NR \HL} \stoptabulate % \stoptext -\def\tabl_tabulate_XX_none - {\starttabulatenoalign - \tabl_tabulate_break_state_set - \tabl_tabulate_hrule_spec_ignore - \stoptabulatenoalign} +\permanent\tolerant\noaligned\protected\def\tabl_tabulate_XX_none [#1]{\noalign{\tabl_tabulate_break_state_set}} -\def\tabl_tabulate_FL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_FL_second_indeed} -\def\tabl_tabulate_ML_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_ML_second_indeed} -\def\tabl_tabulate_LL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_LL_second_indeed} -\def\tabl_tabulate_TL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_TL_second_indeed} -\def\tabl_tabulate_BL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_BL_second_indeed} +\permanent\tolerant\noaligned\protected\def\tabl_tabulate_FL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_FL_second_indeed}} +\permanent\tolerant\noaligned\protected\def\tabl_tabulate_ML_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_ML_second_indeed}} +\permanent\tolerant\noaligned\protected\def\tabl_tabulate_LL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_LL_second_indeed}} +\permanent\tolerant\noaligned\protected\def\tabl_tabulate_TL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_TL_second_indeed}} +\permanent\tolerant\noaligned\protected\def\tabl_tabulate_BL_second[#1]{\noalign{\tabl_tabulate_hrule_preset[#1]\tabl_tabulate_BL_second_indeed}} -\unexpanded\def\tabl_tabulate_FL_second_indeed +\protected\def\tabl_tabulate_FL_second_indeed {\ifinsidefloat\else \doifempty{\tabulationparameter\c!before}\tabl_tabulate_baselinecorrection % no expansion \fi @@ -2110,13 +2049,12 @@ \tabl_tabulate_nobreak_inject \tabl_tabulate_column_rule_separator_inject \prevdepth\strutdp - \tabl_tabulate_nobreak_inject - \stoptabulatenoalign} + \tabl_tabulate_nobreak_inject} \def\spac_vspacing_no_topskip % use grouped {\c_attr_skipcategory\plusten} -\unexpanded\def\tabl_tabulate_ML_second_indeed +\protected\def\tabl_tabulate_ML_second_indeed {\tabl_tabulate_break_no \tabl_tabulate_column_rule_separator_inject \tabl_tabulate_break_no @@ -2127,10 +2065,9 @@ \tabl_tabulate_hrule_inject \endgroup \tabl_tabulate_break_no - \tabl_tabulate_column_rule_separator_inject - \stoptabulatenoalign} + \tabl_tabulate_column_rule_separator_inject} -\unexpanded\def\tabl_tabulate_LL_second_indeed +\protected\def\tabl_tabulate_LL_second_indeed {\tabl_tabulate_nobreak_inject \tabl_tabulate_column_rule_separator_inject \tabl_tabulate_nobreak_inject @@ -2139,10 +2076,9 @@ \tabl_tabulate_inside_inbetween \else \tabl_tabulate_outside_inbetween - \fi - \stoptabulatenoalign} + \fi} -\unexpanded\def\tabl_tabulate_TL_second_indeed +\protected\def\tabl_tabulate_TL_second_indeed {\tabl_tabulate_nobreak_inject \tabl_tabulate_column_rule_separator_inject \tabl_tabulate_nobreak_inject @@ -2150,12 +2086,11 @@ \tabl_tabulate_nobreak_inject \tabl_tabulate_column_rule_separator_inject %\prevdepth\strutdp % todo, might differ between TL and BL - \tabl_tabulate_nobreak_inject - \stoptabulatenoalign} + \tabl_tabulate_nobreak_inject} \let\tabl_tabulate_BL_second_indeed\tabl_tabulate_TL_second_indeed -\def\tabl_tabulate_HL_second +\permanent\def\tabl_tabulate_HL_second {\csname \ifnum\c_tabl_tabulate_noflines=\zerocount F\orelse \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_totalnoflines L\else @@ -2163,52 +2098,25 @@ L\endcsname} \appendtoks - \let\FL\tabl_tabulate_XX_none - \let\ML\tabl_tabulate_XX_none - \let\LL\tabl_tabulate_XX_none - \let\TL\tabl_tabulate_XX_none - \let\BL\tabl_tabulate_XX_none - \let\HL\tabl_tabulate_XX_none - \let\HR\tabl_tabulate_XX_none + \enforced\let\FL\tabl_tabulate_XX_none + \enforced\let\ML\tabl_tabulate_XX_none + \enforced\let\LL\tabl_tabulate_XX_none + \enforced\let\TL\tabl_tabulate_XX_none + \enforced\let\BL\tabl_tabulate_XX_none + \enforced\let\HL\tabl_tabulate_XX_none + \enforced\let\HR\tabl_tabulate_XX_none \to \t_tabl_tabulate_initializers_first \appendtoks - \let\FL\tabl_tabulate_FL_second - \let\ML\tabl_tabulate_ML_second - \let\LL\tabl_tabulate_LL_second - \let\TL\tabl_tabulate_TL_second - \let\BL\tabl_tabulate_BL_second - \let\HL\tabl_tabulate_HL_second - \let\HR\tabl_tabulate_HL_second + \enforced\let\FL\tabl_tabulate_FL_second + \enforced\let\ML\tabl_tabulate_ML_second + \enforced\let\LL\tabl_tabulate_LL_second + \enforced\let\TL\tabl_tabulate_TL_second + \enforced\let\BL\tabl_tabulate_BL_second + \enforced\let\HL\tabl_tabulate_HL_second + \enforced\let\HR\tabl_tabulate_HL_second \to \t_tabl_tabulate_initializers_second -% \def\tabulatedoHRfive % horizontal rule line (break untested) -% {\starttabulatenoalign -% \glet\dotabulateautoline\dotabulatelinerule -% %\ifcase#1\or % todo: check what this does -% \ifnum\noftabulatelines=\zerocount -% \glet\dotabulateautoline\donothing -% \orelse\ifnum\noftabulatelines=\totalnoftabulatelines -% \glet\dotabulateautoline\donothing -% \fi -% %\fi -% \dotabulatenobreak -% \stoptabulatenoalign -% \dotabulateautoline -% \starttabulatenoalign -% \tabl_tabulate_break_no -% \ifx\dotabulateautoline\dotabulatelinerule\kern-\lineheight\fi -% \ifnum\noftabulatelines=\totalnoftabulatelines -% \expandafter\dotabulatenobreak -% \else -% \expandafter\tabl_tabulate_break_allow -% \fi -% \stoptabulatenoalign -% \dotabulateautoline -% \starttabulatenoalign -% \dotabulatenobreak -% \stoptabulatenoalign} - % \dorecurse{10}{ % \starttabulate[|l|] % \FL @@ -2393,7 +2301,7 @@ \the\t_tabl_tabulate_initializers_second % collect more here % \ifx\p_line\v!line - \let\HL\HR + \enforced\let\HL\HR \let\tabulateautoline\tabulateautorule \let\tabulateline\tabulaterule \fi @@ -2505,36 +2413,19 @@ % \NC text \NC text \NC \NR % \stoptabulate -\def\tabl_tabulate_TB - {\starttabulatenoalign - \dosingleempty\tabl_tabulate_TB_indeed} - -\def\tabl_tabulate_TB_indeed[#1]% - {\iffirstargument - \blank[#1] - \orelse\ifempty\m_tabl_tabulate_blank_default - \blank - \else - \blank[\m_tabl_tabulate_blank_default]% - \fi - \stoptabulatenoalign} - -% to be tested: -% -% \def\tabl_tabulate_TB -% {\starttabulatenoalign -% \doiffastoptionalcheckelse\tabl_tabulate_TB_yes\tabl_tabulate_TB_nop} -% -% \def\tabl_tabulate_TB_yes[#1]% -% {\blank[#1] -% \stoptabulatenoalign} -% -% \def\tabl_tabulate_TB_nop[#1]% -% {\blank -% \stoptabulatenoalign} +\permanent\tolerant\noaligned\protected\def\tabl_tabulate_TB[#1]% + {\noalign\bgroup + \unless\iftok{#1}\emptytoks + \blank[#1] + \orelse\ifempty\m_tabl_tabulate_blank_default + \blank + \else + \blank[\m_tabl_tabulate_blank_default]% + \fi + \egroup} \appendtoks - \let\TB\tabl_tabulate_TB + \enforced\let\TB\tabl_tabulate_TB \to \everytabulate % %D Between alignment lines certain rules apply, and even a simple test can mess @@ -2701,13 +2592,17 @@ \newconditional\c_tabl_generic -\unexpanded\setuvalue{starttabulate}% +\pushoverloadmode + +\permanent\protected\setuvalue{starttabulate}% {\bgroup % whole thing \settrue\c_tabl_generic \let\currenttabulationparent\empty - \dodoubleempty\tabl_start_regular} + \tabl_start_regular} -\letvalue{stoptabulate}\relax +\permanent\letvalue{stoptabulate}\relax % testcase cvs-002.tex + +\popoverloadmode %D The following helpers are just there because we also have them at the \LUA\ end: %D @@ -2734,10 +2629,10 @@ \expandafter\tabl_tabulate_compact_step \fi#1} -\unexpanded\def\tabulaterow {\tabl_tabulate_compact_row\relax} -\unexpanded\def\tabulaterowbold{\tabl_tabulate_compact_row\bold} -\unexpanded\def\tabulaterowtype{\tabl_tabulate_compact_row\type} -\unexpanded\def\tabulaterowtyp {\tabl_tabulate_compact_row\typ} +\permanent\protected\def\tabulaterow {\tabl_tabulate_compact_row\relax} +\permanent\protected\def\tabulaterowbold{\tabl_tabulate_compact_row\bold} +\permanent\protected\def\tabulaterowtype{\tabl_tabulate_compact_row\type} +\permanent\protected\def\tabulaterowtyp {\tabl_tabulate_compact_row\typ} %D Here we plug in a row background feature. As we only have support for %D \type {frame=name} we can use these variables. @@ -2823,13 +2718,13 @@ \let\m_table_current_row_background_defaultfiller\empty \let\m_table_current_row_background_auto \empty -\unexpanded\def\tabl_register_row_background#1% +\protected\def\tabl_register_row_background#1% {\xdef\m_table_current_row_background{#1}} -\unexpanded\def\tabl_register_row_background_filler#1% +\protected\def\tabl_register_row_background_filler#1% {\xdef\m_table_current_row_background_filler{#1}} -\unexpanded\def\tabl_synchronize_row_background +\protected\def\tabl_synchronize_row_background {\iftrialtypesetting\else \ifempty\m_table_current_row_background_filler \ifempty\m_table_current_row_background @@ -2843,7 +2738,7 @@ \fi \fi} -\unexpanded\def\tabl_synchronize_row_background_dummy +\protected\def\tabl_synchronize_row_background_dummy {\iftrialtypesetting\else \begingroup %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\zerocount\zeropoint @@ -2851,7 +2746,7 @@ \endgroup \fi} -\unexpanded\def\tabl_synchronize_row_background_indeed#1% +\protected\def\tabl_synchronize_row_background_indeed#1% {\iftrialtypesetting\else \begingroup \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata @@ -2862,7 +2757,7 @@ \endgroup \fi} -\unexpanded\def\tabl_synchronize_row_background_filler_indeed#1% +\protected\def\tabl_synchronize_row_background_filler_indeed#1% {\iftrialtypesetting\else \begingroup \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata @@ -2898,21 +2793,27 @@ \glet\m_table_current_row_background_filler\empty \to \t_tabl_tabulate_every_after_row -\unexpanded\def\tabl_tabulate_NL_first[#1]% +\permanent\protected\def\tabl_tabulate_NL_first[#1]% {\tabl_tabulate_column_normal\zerocount\zerocount\relax \ifcase\c_tabl_tabulate_column\or \tabl_register_row_background{#1}% \fi \ignorespaces} -\unexpanded\def\tabl_tabulate_ND_first - {\tabl_tabulate_column_normal\zerocount\zerocount\relax - \ifcase\c_tabl_tabulate_column\or - \tabl_register_row_background\m_table_current_row_background_default - \fi - \ignorespaces} +\pushoverloadmode + + % redefinition needs checking -\unexpanded\def\tabl_tabulate_LB_first[#1]% + \permanent\overloaded\protected\def\tabl_tabulate_ND_first + {\tabl_tabulate_column_normal\zerocount\zerocount\relax + \ifcase\c_tabl_tabulate_column\or + \tabl_register_row_background\m_table_current_row_background_default + \fi + \ignorespaces} + +\popoverloadmode + +\permanent\protected\def\tabl_tabulate_LB_first[#1]% {\tabl_tabulate_column_normal\plusone\zerocount\relax \ifcase\c_tabl_tabulate_column\or \tabl_register_row_background{#1}% @@ -2920,30 +2821,30 @@ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor \ignorespaces} -\unexpanded\def\tabl_tabulate_DB_first +\permanent\protected\def\tabl_tabulate_DB_first {\tabl_tabulate_column_normal\plusone\zerocount\relax \ifcase\c_tabl_tabulate_column\or \tabl_register_row_background\m_table_current_row_background_default \fi - \let\fontstyle\globalfontstyle + \enforced\let\fontstyle\globalfontstyle \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor \ignorespaces} -\unexpanded\def\tabl_tabulate_NF_first[#1]% +\permanent\protected\def\tabl_tabulate_NF_first[#1]% {\tabl_tabulate_column_normal\zerocount\zerocount\relax \ifcase\c_tabl_tabulate_column\or \tabl_register_row_background_filler{#1}% \fi \ignorespaces} -\unexpanded\def\tabl_tabulate_NP_first +\permanent\protected\def\tabl_tabulate_NP_first {\tabl_tabulate_column_normal\zerocount\zerocount\relax \ifcase\c_tabl_tabulate_column\or \tabl_register_row_background_filler\m_table_current_row_background_default_filler \fi \ignorespaces} -\unexpanded\def\tabl_tabulate_FB_first[#1]% +\permanent\protected\def\tabl_tabulate_FB_first[#1]% {\tabl_tabulate_column_normal\plusone\zerocount\relax \ifcase\c_tabl_tabulate_column\or \tabl_register_row_background_filler{#1}% @@ -2951,29 +2852,33 @@ \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor \ignorespaces} -\unexpanded\def\tabl_tabulate_PB_first +\permanent\protected\def\tabl_tabulate_PB_first {\tabl_tabulate_column_normal\plusone\zerocount\relax \ifcase\c_tabl_tabulate_column\or \tabl_register_row_background_filler\m_table_current_row_background_default_filler \fi - \let\fontstyle\globalfontstyle + \enforced\let\fontstyle\globalfontstyle \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor \ignorespaces} -\unexpanded\def\tabl_tabulate_BC_first % overloaded - {\tabl_tabulate_column_normal\plusone\zerocount - \let\fontstyle\globalfontstyle - \ifempty\m_table_current_row_background - \ifempty\m_table_current_row_background_filler - \usetabulationstyleandcolor\c!headstyle\c!headcolor - \else - \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor - \fi - \else - \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor - \fi} +\pushoverloadmode + + \permanent\overloaded\protected\def\tabl_tabulate_BC_first + {\tabl_tabulate_column_normal\plusone\zerocount + \enforced\let\fontstyle\globalfontstyle + \ifempty\m_table_current_row_background + \ifempty\m_table_current_row_background_filler + \usetabulationstyleandcolor\c!headstyle\c!headcolor + \else + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \fi + \else + \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor + \fi} + +\popoverloadmode -\unexpanded\def\tabl_tabulate_A_first +\permanent\protected\def\tabl_tabulate_A_first {\global\advance\c_tabl_tabulate_autocolor\plusone \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}% \ifempty\m_table_current_row_background_auto @@ -2985,7 +2890,7 @@ \fi \tabl_register_row_background{\m_table_current_row_background_auto}} -\unexpanded\def\tabl_tabulate_NA_first +\permanent\protected\def\tabl_tabulate_NA_first {\tabl_tabulate_column_normal\zerocount\zerocount\relax \iftrialtypesetting\else \ifcase\c_tabl_tabulate_column\or @@ -2994,7 +2899,7 @@ \fi \ignorespaces} -\unexpanded\def\tabl_tabulate_BA_first +\permanent\protected\def\tabl_tabulate_BA_first {\tabl_tabulate_column_normal\plusone\zerocount\relax \iftrialtypesetting\else \ifcase\c_tabl_tabulate_column\or @@ -3005,16 +2910,16 @@ \ignorespaces} \appendtoks - \let\NL\tabl_tabulate_NL_first % NC with Line - \let\ND\tabl_tabulate_ND_first % NC with Default Line - \let\LB\tabl_tabulate_LB_first % BC with Line - \let\DB\tabl_tabulate_DB_first % BC with Default Line - \let\NF\tabl_tabulate_NF_first % NC with Filler - \let\NP\tabl_tabulate_NP_first % NC with Predefined Filler - \let\FB\tabl_tabulate_FB_first % BC with Filler - \let\PB\tabl_tabulate_PB_first % BC with Predefined Filler - \let\NA\tabl_tabulate_NA_first % NC with Auto Line - \let\BA\tabl_tabulate_BA_first % NC with Auto Line + \enforced\let\NL\tabl_tabulate_NL_first % NC with Line + \enforced\let\ND\tabl_tabulate_ND_first % NC with Default Line + \enforced\let\LB\tabl_tabulate_LB_first % BC with Line + \enforced\let\DB\tabl_tabulate_DB_first % BC with Default Line + \enforced\let\NF\tabl_tabulate_NF_first % NC with Filler + \enforced\let\NP\tabl_tabulate_NP_first % NC with Predefined Filler + \enforced\let\FB\tabl_tabulate_FB_first % BC with Filler + \enforced\let\PB\tabl_tabulate_PB_first % BC with Predefined Filler + \enforced\let\NA\tabl_tabulate_NA_first % NC with Auto Line + \enforced\let\BA\tabl_tabulate_BA_first % NC with Auto Line \to \t_tabl_tabulate_initializers_first \appendtoks diff --git a/tex/context/base/mkiv/tabl-xnt.mklx b/tex/context/base/mkiv/tabl-xnt.mklx new file mode 100644 index 000000000..f2a41c500 --- /dev/null +++ b/tex/context/base/mkiv/tabl-xnt.mklx @@ -0,0 +1,142 @@ +% macros=mkvi + +%D \module +%D [ file=tabl-xtb, +%D version=2011.10.28, +%D title=\CONTEXT\ Table Macros, +%D subtitle=Natural to Xtreme Tables, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Table Macros / Natural to Xtreme Tables} + +\unprotect + +%D Don't expect wonders but it might come in handy: +%D +%D \starttyping +%D \mapTABLEtoxtable +%D \restoreTABLEfromxtable +%D \stoptyping +%D +%D We stick to a simple example: +%D +%D \startbuffer +%D \bTABLE +%D \bTR +%D \bTD[width=1cm,background=color,backgroundcolor=red] one \eTD +%D \bTD[width=2cm] two \eTD +%D \eTR +%D \bTR +%D \bTD alpha \eTD +%D \bTD beta \eTD +%D \eTR +%D \eTABLE +%D \stopbuffer +%D +%D \typebuffer +%D +%D \startbuffer +%D \startlinecorrection +%D \getbuffer +%D \stoplinecorrection +%D +%D \startlinecorrection +%D \mapTABLEtoxtable \getbuffer +%D \stoplinecorrection +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\pushoverloadmode % this file is runtime loaded + +\overloaded\permanent\let\tabl_x_normal_bTABLEhead\bTABLEhead +\overloaded\permanent\let\tabl_x_normal_eTABLEhead\eTABLEhead +\overloaded\permanent\let\tabl_x_normal_bTABLEnext\bTABLEnext +\overloaded\permanent\let\tabl_x_normal_eTABLEnext\eTABLEnext +\overloaded\permanent\let\tabl_x_normal_bTABLEfoot\bTABLEfoot +\overloaded\permanent\let\tabl_x_normal_eTABLEfoot\eTABLEfoot +\overloaded\permanent\let\tabl_x_normal_bTABLEbody\bTABLEbody +\overloaded\permanent\let\tabl_x_normal_eTABLEbody\eTABLEbody +\overloaded\permanent\let\tabl_x_normal_bTR \bTR +\overloaded\permanent\let\tabl_x_normal_eTR \eTR +\overloaded\permanent\let\tabl_x_normal_bTD \bTD +\overloaded\permanent\let\tabl_x_normal_eTD \eTD +\overloaded\permanent\let\tabl_x_normal_bTH \bTH +\overloaded\permanent\let\tabl_x_normal_eTH \eTH +\overloaded\permanent\let\tabl_x_normal_setupTABLE\setupTABLE +\overloaded\permanent\let\tabl_x_normal_bTABLE \bTABLE +\overloaded\permanent\let\tabl_x_normal_eTABLE \eTABLE + +\permanent\protected\def\restoreTABLEfromxtable + {\enforced\let\bTABLEhead\tabl_x_normal_bTABLEhead + \enforced\let\eTABLEhead\tabl_x_normal_eTABLEhead + \enforced\let\bTABLEnext\tabl_x_normal_bTABLEnext + \enforced\let\eTABLEnext\tabl_x_normal_eTABLEnext + \enforced\let\bTABLEfoot\tabl_x_normal_bTABLEfoot + \enforced\let\eTABLEfoot\tabl_x_normal_eTABLEfoot + \enforced\let\bTABLEbody\tabl_x_normal_bTABLEbody + \enforced\let\eTABLEbody\tabl_x_normal_eTABLEbody + \enforced\let\bTR \tabl_x_normal_bTR + \enforced\let\eTR \tabl_x_normal_eTR + \enforced\let\bTD \tabl_x_normal_bTD + \enforced\let\eTD \tabl_x_normal_eTD + \enforced\let\bTH \tabl_x_normal_bTH + \enforced\let\eTH \tabl_x_normal_eTH + \enforced\let\setupTABLE\tabl_x_normal_setupTABLE + \enforced\let\bTABLE \tabl_x_normal_bTABLE + \enforced\let\eTABLE \tabl_x_normal_eTABLE} + +\permanent\protected\def\mapTABLEtoxtable + {\enforced\let\bTABLEhead\startxtablehead + \enforced\let\eTABLEhead\stopxtablehead + \enforced\let\bTABLEnext\startxtablefoot + \enforced\let\eTABLEnext\stopxtablefoot + \enforced\let\bTABLEfoot\startxtablefoot + \enforced\let\eTABLEfoot\stopxtablefoot + \enforced\let\bTABLEbody\startxtablebody + \enforced\let\eTABLEbody\stopxtablebody + \enforced\let\bTR \startxrow + \enforced\let\eTR \stopxrow + \enforced\let\bTD \startxcell + \enforced\let\eTD \stopxcell + \enforced\let\bTH \tabl_x_TABLE_TH_start_cell + \enforced\let\eTH \tabl_x_TABLE_TH_stop_cell + \enforced\let\setupTABLE\tabl_x_TABLE_setup + \enforced\let\bTABLE \tabl_x_TABLE_start + \enforced\let\eTABLE \tabl_x_TABLE_stop} + +\popoverloadmode + +\permanent\protected\def\tabl_x_TABLE_TH_start_cell + {\startxcellgroup[\c!foregroundstyle=\v!bold]% + \startxcell} + +\permanent\protected\def\tabl_x_TABLE_TH_stop_cell + {\stopxcell + \stopxcellgroup} + +\permanent\protected\tolerant\def\tabl_x_TABLE_setup[#settings]% + {\ifarguments\or + %\ifparameter#1\or + \setupxtable[#settings]% + \fi} + +\permanent\protected\tolerant\def\tabl_x_TABLE_start[#settings]% + {\bgroup + \ifarguments\or + %\ifparameter#1\or + \tabl_x_prepare{#settings}% + \fi + \edef\tabl_x_current_buffer{\tabl_x_default_buffer}% + \buff_pickup\tabl_x_current_buffer{bTABLE}{eTABLE}\relax\tabl_x_process\zerocount} + +\permanent\protected\def\tabl_x_TABLE_stop + {\stopxtable} + +\protect \endinput diff --git a/tex/context/base/mkiv/tabl-xtb.mklx b/tex/context/base/mkiv/tabl-xtb.mklx new file mode 100644 index 000000000..b54685863 --- /dev/null +++ b/tex/context/base/mkiv/tabl-xtb.mklx @@ -0,0 +1,983 @@ +% macros=mkvi + +%D \module +%D [ file=tabl-xtb, +%D version=2011.10.26, +%D title=\CONTEXT\ Table Macros, +%D subtitle=Xtreme, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Table Macros / Xtreme} + +\registerctxluafile{tabl-xtb}{} + +% todo: +% +% - yes or no: foregroundstyle/color <- style/color +% - template alignment +% - maybe split horizontal (a la linetables) +% - before/after and wrapping (linecorrection) +% - maybe also some before/after commands +% - maybe correction when non float usage +% - tagging needs to be checked +% - maybe only tag the box +% - scale to fit +% +% - buffers permit verbatim but are not always handy + +%D This module started as an afternoon experiment and surprisingly could be +%D mostly finished the same evening. Of course it builds upon existing +%D functionality. The main reason for writing it is that we occasionally +%D run into pretty large tables that take tens of pages and need to be split +%D into floats. Speed is one issue there, avoiding to use vsplit is another. +%D +%D \starttyping +%D \definextable [tag] | [tag][parent] +%D \setupxtable [settings] | [tag][settings] +%D +%D \startxtable[tag|settings] +%D \startxtablehead|\startxtablenext|\startxtablebody|\startxtablefoot +%D \startxrowgroup[tag|settings] +%D \startxrow[settings] +%D \startxcellgroup[tag|settings] +%D \startxcell[settings] ... \stopxcell +%D \stopxcellgroup +%D \stopxrow +%D \startxrowgroup +%D \stopxtablehead|\stopxtablenext|\stopxtablebody|\stopxtablefoot +%D \stopxtable +%D \stoptyping +%D +%D See xtables-001.tex etc for some examples. + +% We can avoid some checking by using the fastoptionalcheckcs helpers +% instead of dosingleempty but the speed gain is neglectable. + +\unprotect + +% option=stretch : equal distribution +% option={stretch,width} : proportional distribution +% option={max} : prefer max over forced width/height +% +% cells: option=fixed : nils autostretch (not yet complete) + +% \setbox\scratchbox\hbox attr \taggedattribute \c_attr_tagged {...} +% +% \let\tsplitbeforeresult\donothing +% \let\tsplitafterresult \donothing +% \let\tsplitinbetween \donothing +% \let\tsplitbefore \donothing +% \let\tsplitafter \donothing +% \let\postprocesstsplit \donothing + +\let\dotagxtablecell \relax % names will change +\let\dotagxtablesignal\relax % names will change + +\appendtoks + \def\dotagxtablecell + {\clf_settagtablecell + \numexpr\tablecellrows\relax + \numexpr\tablecellcolumns\relax + \numexpr\raggedstatus\relax}% + \def\dotagxtablesignal + {\signalcharacter}% not used +\to \everyenableelements + +\newdimen\d_tabl_x_width +\newdimen\d_tabl_x_height +\newdimen\d_tabl_x_depth % not used +\newdimen\d_tabl_x_distance +\newcount\c_tabl_x_nx +\newcount\c_tabl_x_ny +\newcount\c_tabl_x_mode +\newbox \b_tabl_x +\newcount\c_tabl_x_state % 0=empty 1=content 3=splitleft +\newdimen\d_tabl_x_final_width +\newcount\c_tabl_x_nesting +\newcount\c_tabl_x_skip_mode % 1 = skip +\newdimen\d_tabl_x_textwidth +\newcount\c_tabl_x_swapped +\newcount\c_tabl_x_swapped_max + +\let\m_tabl_x_swapped_settings\empty + +\aliased\let\currentxtablerow \clf_x_table_r +\aliased\let\currentxtablecolumn\clf_x_table_c + +% \setupxtable[one][parent][a=b,c=d] +% \setupxtable[one] [a=b,c=d] +% \setupxtable [a=b,c=d] + +\installcorenamespace{xtable} +\installcorenamespace{xtablecheck} +\installcorenamespace{xtableswap} + +\installframedautocommandhandler \??xtable {xtable} \??xtable + +\appendtoks + \checkxtableparent % so we can deal with undefined settings, not that it's efficient +\to \everysetupxtable + +\setupxtable[% + \c!nr=\plusone, + \c!nc=\plusone, + \c!nx=\plusone, % slow + \c!ny=\plusone, % slow + \c!align=\v!table, % {\v!flushleft,\v!broad,\v!high}, % just as \bTABLE .. \eTABLE + \c!frameoffset=.5\linewidth, + \c!backgroundoffset=\v!frame, + % \c!framecolor=\s!black, + % \c!foregroundstyle=\xtableparameter\c!style, % not clean, better capture elsewhere + % \c!foregroundcolor=\xtableparameter\c!color, % not clean, better capture elsewhere + % \c!bodyfont=, + \c!width=\v!fit, + \c!height=\v!fit, + \c!maxwidth=8\emwidth, + \c!autowidth=\v!yes, % controls framed + \c!rulethickness=\linewidth, + \c!strut=\v!yes, + \c!autostrut=\v!no, + \c!split=\v!auto, % a number will take that many lines + \c!splitoffset=\zeropoint, % extra space taken + \c!aligncharacter=\v!no, + \c!alignmentcharacter={,}, + \c!alignmentleftsample=, + \c!alignmentrightsample=, + \c!alignmentleftwidth=\zeropoint, + \c!alignmentrightwidth=\zeropoint, + % \c!option=, % \v!stretch {\v!stretch,\v!width} + % \c!footer=, + % \c!header=, + \c!spaceinbetween=, + \c!textwidth=\v!local, % was \hsize, + \c!textheight=\vsize, % used for vertical spread + \c!distance=\zeropoint, % individual column + \c!columndistance=\zeropoint, % each column (whole table) + \c!leftmargindistance=\zeropoint, % whole table + \c!rightmargindistance=\zeropoint,% whole table +] + +\def\tabl_x_default_buffer{x_table_\number\c_tabl_x_nesting} +\let\tabl_x_current_buffer\empty + +\permanent\protected\def\startxtable{\tabl_x_start_table} + +\protected\tolerant\def\tabl_x_start_table[#settings]% maybe two arguments: [tag][settings] | [tag] | [settings] + {\bgroup + \tabl_x_prepare{#settings}% + \edef\tabl_x_current_buffer{\tabl_x_default_buffer}% + \buff_pickup{\tabl_x_current_buffer}{startxtable}{stopxtable}\relax\tabl_x_process\zerocount} + +% \permanent\protected\aliased\startxtable\tabl_x_start_table + +\aliased\permanent\let\stopxtable\relax + +% These direct buffers can be somewhat faster but it's probably neglectable. +% Anyway, no nesting is supported as we then need to catch (e.g.) rows and +% keep track of nesting and have a more complex redefinition of nested +% instanced \unknown\ it's not worth the trouble. Only use them when you +% really need them and use the embeddedxtable command when nesting them. +% Implementing nesting would be slower than not using direct buffers. + +\permanent\tolerant\protected\def\processxtablebuffer[#name]% + {\bgroup + \let\tabl_x_start_table\tabl_x_process_buffer + \edef\tabl_x_current_buffer{#name}% + \tabl_x_get_buffer % settings + \tabl_x_process} + +\protected\tolerant\def\tabl_x_start_ignore[#settings]% + {} + +\protected\tolerant\def\tabl_x_process_buffer[#settings]% + {\tabl_x_prepare{#settings}% + \let\tabl_x_start_table\tabl_x_start_ignore + \gobbleuntil\stopxtable} % nested xtables are not supported, + +%D A bonus: you have to use the following construct inside a macro or +%D direct buffer. + +\permanent\tolerant\protected\def\startembeddedxtable[#settings]#;#content\stopembeddedxtable + {\tabl_x_prepare{#settings}% + \clf_assignbuffer{embedded_x_table}{\detokenize{#content}}\catcodetable\relax + \bgroup + \let\tabl_x_start_table\tabl_x_process_buffer + \edef\tabl_x_current_buffer{embedded_x_table}% + \tabl_x_process} + +\aliased\permanent\let\stopembeddedxtable\relax + +%D We can also define xtables. + +\appendtoks + \permanent\setuevalue{\e!start\currentxtable}{\tabl_x_start_named[\currentxtable]}% + \permanent\setuevalue{\e!stop \currentxtable}{\tabl_x_stop_named}% +\to \everydefinextable + +\protected\def\tabl_x_start_named[#tag]#spacer[#settings]% + {\bgroup + \edef\currentxtable{#tag}% + \advance\c_tabl_x_nesting\plusone + \dostarttaggedchained\t!table\empty\??xtable + \setupcurrentxtable[#settings]% + \tabl_x_check_textwidth + %\forgetall % else whitespace mess + \edef\tabl_x_current_buffer{\tabl_x_default_buffer}% + \normalexpanded{\buff_pickup{\tabl_x_current_buffer}{\e!start\currentxtable}{\e!stop\currentxtable}\relax\tabl_x_process\zerocount}} + +\protected\def\tabl_x_stop_named + {} + +%D Now we come to processing: + +\protected\def\tabl_x_check_textwidth + {\edef\p_textwidth{\xtableparameter\c!textwidth}% + \ifx\p_textwidth\v!local + \d_tabl_x_textwidth\availablehsize + \else + \d_tabl_x_textwidth\p_textwidth + \fi} + +\newtoks\everypreparextable + +\protected\def\tabl_x_prepare#settings% + {\advance\c_tabl_x_nesting\plusone + \dostarttaggedchained\t!table\empty\??xtable + \tabl_x_set_checked{#settings}% + \tabl_x_check_textwidth + \the\everypreparextable + }% else whitespace mess + +\def\tabl_x_get_buffer + {\clf_gettexbuffer{\tabl_x_current_buffer}} + +\let\tabl_x_start_row_yes \relax +\let\tabl_x_start_row_nop \relax +\let\tabl_x_stop_row \relax +\let\tabl_x_start_cell_yes\relax +\let\tabl_x_start_cell_nop\relax +\let\tabl_x_stop_cell \relax + +\newtoks\t_table_x_cleanup + +\protected\def\tabl_x_process + {\begingroup % * + \forgetall % moved here + \dontcomplain % for the moment here till we figure out where we get the overflow + \usebodyfontparameter\xtableparameter + \setbox\scratchbox\vbox + {\doifsomething{\xtableparameter\c!spaceinbetween}{\blank[\xtableparameter\c!spaceinbetween]}}% + \clf_x_table_create + option {\xtableparameter\c!option}% + textwidth \d_tabl_x_textwidth + textheight \dimexpr\xtableparameter\c!textheight\relax + maxwidth \dimexpr\xtableparameter\c!maxwidth\relax + lineheight \openlineheight + columndistance \dimexpr\xtableparameter\c!columndistance\relax + leftmargindistance \dimexpr\xtableparameter\c!leftmargindistance\relax + rightmargindistance \dimexpr\xtableparameter\c!rightmargindistance\relax + rowdistance \ht\scratchbox + header {\xtableparameter\c!header}% + footer {\xtableparameter\c!footer}% + \relax + % + \letxtableparameter\c!option\empty + % not so nice but needed as we use this in the setup + \linewidth\xtableparameter\c!rulethickness\relax + % so we freeze it + \c_tabl_x_swapped_max\zerocount + \begingroup + \let\tabl_x_start_row_yes \tabl_x_start_row_reflow_width_yes + \let\tabl_x_start_row_nop \tabl_x_start_row_reflow_width_nop + \let\tabl_x_stop_row \tabl_x_stop_row_reflow_width + \let\tabl_x_start_cell_yes\tabl_x_start_cell_reflow_width_yes + \let\tabl_x_start_cell_nop\tabl_x_start_cell_reflow_width_nop + \let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_width + \settrialtypesetting + \tabl_x_get_buffer + \ifcase\c_tabl_x_swapped_max + \else + \tabl_x_flush_swapped + \fi + \clf_x_table_reflow_width + \endgroup + \begingroup + \let\tabl_x_start_row_yes \tabl_x_start_row_reflow_height_yes + \let\tabl_x_start_row_nop \tabl_x_start_row_reflow_height_nop + \let\tabl_x_stop_row \tabl_x_stop_row_reflow_height + \let\tabl_x_start_cell_yes\tabl_x_start_cell_reflow_height_yes + \let\tabl_x_start_cell_nop\tabl_x_start_cell_reflow_height_nop + \let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_height + \settrialtypesetting + \ifcase\c_tabl_x_swapped_max + \tabl_x_get_buffer + \else + \tabl_x_flush_swapped + \fi + \clf_x_table_reflow_height + \endgroup + \begingroup + \let\tabl_x_start_row_yes \tabl_x_start_row_construct_yes + \let\tabl_x_start_row_nop \tabl_x_start_row_construct_nop + \let\tabl_x_stop_row \tabl_x_stop_row_construct + \let\tabl_x_start_cell_yes\tabl_x_start_cell_construct_yes + \let\tabl_x_start_cell_nop\tabl_x_start_cell_construct_nop + \let\tabl_x_stop_cell \tabl_x_stop_cell_construct + \ifcase\c_tabl_x_swapped_max + \tabl_x_get_buffer + \else + \tabl_x_flush_swapped + \fi + \clf_x_table_construct + \endgroup + \endgroup % * + \ifinsidesplitfloat + \tabl_x_flush_float_split + \orelse\ifinsidefloat + \tabl_x_flush_float_normal + \else + \tabl_x_flush_text_checked + \fi + \clf_x_table_cleanup + \dostoptagged + \resetbuffer[\tabl_x_current_buffer]% + \resetcharacteralign + \the\t_table_x_cleanup + \egroup} + +% text flow split modes + +\installcorenamespace{xtableflushsplit} + +\protected\def\tabl_x_flush_text_checked + {\expandnamespaceparameter\??xtableflushsplit\xtableparameter\c!split\v!no} + +% in text flow: headers and footers only once + +\setvalue{\??xtableflushsplit\v!yes}% + {\clf_x_table_flush + method {\v!split}% + \relax} + +% in text flow: headers and footers only once + +\setvalue{\??xtableflushsplit\v!no}% + {% \noindent % gives extra line after table + % \noindentation % messes up the next indentation + % \dontleavehmode % no leftskip + \kern\zeropoint % yet another guess + \ignorespaces + \clf_x_table_flush + method {\v!normal}% + \relax + \removeunwantedspaces} + +% in text flow: headers and footers get repeated + +\setvalue{\??xtableflushsplit\v!repeat}% + {\doloop + {\clf_x_table_flush + method {\v!split}% + height \ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi + \relax + \ifcase\c_tabl_x_state + \exitloop + \else + \page + \fi}} + +% \setvalue{\??xtableflushsplit\v!setups}% +% {\directsetup{xtable:split:user}} +% +% \startsetups[xtable:split:user] +% \doloop { +% \xtablesplitflush % uses \xtablesplitvsize (a macro) +% \ifcase\xtablesplitstate +% \exitloop +% \else +% \page +% \fi +% } +% \stopsetups +% +% \protected\def\xtablesplitflush +% {\clf_x_table_flush +% method {\v!split}% +% height \dimexpr\xtablesplitvsize\relax +% \relax} +% +% \def\xtablesplitvsize +% {\ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi} +% +% \let\xtablesplitstate\c_tabl_x_state + +\let\extratxtablesplitheight\zeropoint % might disappear so don't depend on it + +\protected\def\tabl_x_flush_float_normal + {\clf_x_table_flush + method {\v!normal}% + \relax} + +\protected\def\tabl_x_flush_float_split + {\resetdirecttsplit + \edef\extrasplitfloatlines {\xtableparameter\c!split}% + \edef\tsplitminimumfreespace{\the\dimexpr\extratxtablesplitheight+\xtableparameter\c!splitoffset\relax}% + % \edef\tsplitminimumfreelines{2}% not needed here as we're precise enough + \let\tsplitdirectsplitter\tabl_x_split_splitter + \let\tsplitdirectwidth \d_tabl_x_final_width + \handledirecttsplit} + +\protected\def\tabl_x_split_splitter#height% + {\setbox\tsplitresult\vbox + {\clf_x_table_flush + method {\v!split}% + height \dimexpr#height\relax + \relax}% + \ifcase\c_tabl_x_state + \global\setfalse\somenextsplitofffloat + \else + \global\settrue \somenextsplitofffloat + \fi} + +% \permanent\protected\def\startxrow +% {\begingroup +% \doifelsenextoptionalcs\tabl_x_start_row_yes\tabl_x_start_row_nop} + +% \permanent\protected\def\stopxrow +% {\tabl_x_stop_row +% \endgroup} + +\protected\def\tabl_x_start_row_reflow_width_yes[#settings]% + {\setupcurrentxtable[#settings]% + \clf_x_table_next_row} + +\protected\def\tabl_x_start_row_reflow_width_nop + {\clf_x_table_next_row} + +\protected\def\tabl_x_stop_row_reflow_width + {} + +\let\tabl_x_start_row_reflow_height_yes\tabl_x_start_row_reflow_width_yes +\let\tabl_x_start_row_reflow_height_nop\tabl_x_start_row_reflow_width_nop +\let\tabl_x_stop_row_reflow_height \tabl_x_stop_row_reflow_width + +\protected\def\tabl_x_start_row_construct_yes[#settings]% + {\setupcurrentxtable[#settings]% + \dostarttagged\t!tablerow\empty + \clf_x_table_next_row_option{\xtableparameter\c!samepage}} + +\protected\def\tabl_x_start_row_construct_nop + {\dostarttagged\t!tablerow\empty + \clf_x_table_next_row} + +\protected\def\tabl_x_stop_row_construct + {\clf_x_table_finish_row + \dostoptagged} + +\permanent\protected\def\dummyxcell + {\begingroup + \let\inheritedxtableframed\relax + \tabl_x_start_cell_nop + \tabl_x_stop_cell + \endgroup} + +\def\tabl_x_setup_character_align + {\edef\p_left {\directxtableparameter\c!alignmentleftsample}% + \edef\p_right{\directxtableparameter\c!alignmentrightsample}% + \ifx\p_left\empty + \scratchdimenone\dimexpr\directxtableparameter\c!alignmentleftwidth\relax + \else + \setbox\scratchbox\hbox{\p_left}% + \scratchdimenone\wd\scratchbox + \fi + \ifx\p_right\empty + \scratchdimentwo\dimexpr\directxtableparameter\c!alignmentrightwidth\relax + \else + \setbox\scratchbox\hbox{\p_right}% + \scratchdimentwo\wd\scratchbox + \fi + \clf_setcharacteraligndetail + \clf_x_table_c + {\directxtableparameter\c!alignmentcharacter}% + \scratchdimenone + \scratchdimentwo + \relax} + +\newtoks\t_tabl_x_every_cell + +% \appendtoks +% \inhibitblank % already in framed +% \to \t_tabl_x_every_cell + +\appendtoks + \edef\p_characteralign{\directxtableparameter\c!aligncharacter}% + \ifx\p_characteralign\v!yes + \ifcase\clf_x_table_r\or + \tabl_x_setup_character_align + \fi + \signalcharacteralign\clf_x_table_c\clf_x_table_r + \fi +\to \t_tabl_x_every_cell + +\protected\def\tabl_x_begin_of_cell + {\the\t_tabl_x_every_cell + \everypar{\delayedbegstrut}} + +\protected\def\tabl_x_end_of_cell + {\ifhmode + \delayedendstrut + \par + \else + \par + \ifdim\prevdepth<\zeropoint % =-1000pt ? + \vskip-\strutdp + \else + \removebottomthings + \fi + \fi} + +% For historic reasons we support both nx/nc and ny/nr : maybe nx/ny becomes +% obsolete some day. The let as well as the direct speed things up a bit. We +% could also consider a \defaultxtableparameter. +% +% \c_tabl_x_nx\defaultxtableparameter\c!nc{\defaultxtableparameter\c!nx\plusone} +% \c_tabl_x_ny\defaultxtableparameter\c!nr{\defaultxtableparameter\c!ny\plusone} +% +% Although this becomes kind of messy. It saves already time that we only check +% for it when we have settings. + +% \def\tabl_x_set_hsize +% {\hsize.25\maxdimen} % let's be reasonable + +% \def\tabl_x_set_hsize +% {\edef\p_width{\xtableparameter\c!width}% +% \ifx\p_width\empty +% \hsize.25\maxdimen % is this really needed +% \fi} + +\let\tabl_x_set_hsize\relax + +\protected\def\tabl_x_start_cell_reflow_width_yes[#settings]% + {\setbox\b_tabl_x\hpack\bgroup + \ifnum\c_tabl_x_nesting>\plusone + \letxtableparameter\c!width \v!fit % overloads given width + \letxtableparameter\c!height\v!fit % overloads given height + \fi + % + \letxtableparameter\c!nx\plusone + \letxtableparameter\c!ny\plusone + \letxtableparameter\c!nc\plusone + \letxtableparameter\c!nr\plusone + % + \setupcurrentxtable[#settings]% + % + \c_tabl_x_nx\directxtableparameter\c!nc\relax + \c_tabl_x_ny\directxtableparameter\c!nr\relax + \ifnum\c_tabl_x_nx=\plusone + \c_tabl_x_nx\directxtableparameter\c!nx\relax + \fi + \ifnum\c_tabl_x_ny=\plusone + \c_tabl_x_ny\directxtableparameter\c!ny\relax + \fi + % + \d_tabl_x_distance\xtableparameter\c!distance\relax + \clf_x_table_init_reflow_width_option{\xtableparameter\c!option}% + \inheritedxtableframed\bgroup + \tabl_x_begin_of_cell + \tabl_x_set_hsize} + +\protected\def\tabl_x_start_cell_reflow_width_nop + {\setbox\b_tabl_x\hpack\bgroup + \ifnum\c_tabl_x_nesting>\plusone + \letxtableparameter\c!width \v!fit % overloads given width + \letxtableparameter\c!height\v!fit % overloads given height + \fi + \c_tabl_x_nx\plusone + \c_tabl_x_ny\plusone + \d_tabl_x_distance\xtableparameter\c!distance\relax + \clf_x_table_init_reflow_width + \inheritedxtableframed\bgroup + \tabl_x_begin_of_cell + \tabl_x_set_hsize} + +\protected\def\tabl_x_stop_cell_reflow_width + {\tabl_x_end_of_cell + \egroup + \egroup + \clf_x_table_set_reflow_width} + +\protected\def\tabl_x_start_cell_reflow_height_yes[#settings]% + {\setbox\b_tabl_x\hpack\bgroup + \clf_x_table_init_reflow_height + \ifcase\c_tabl_x_skip_mode % can be sped up + \ifnum\c_tabl_x_nesting>\plusone + \letxtableparameter\c!height\v!fit % overloads given height + \fi + \setupcurrentxtable[#settings]% + \relax + \letxtableparameter\c!width\d_tabl_x_width % overloads given width + \inheritedxtableframed\bgroup + \tabl_x_begin_of_cell + \fi} + +\protected\def\tabl_x_start_cell_reflow_height_nop + {\setbox\b_tabl_x\hpack\bgroup + \clf_x_table_init_reflow_height + \ifcase\c_tabl_x_skip_mode % can be sped up + \ifnum\c_tabl_x_nesting>\plusone + \letxtableparameter\c!height\v!fit % overloads given height + \fi + \relax + \letxtableparameter\c!width\d_tabl_x_width % overloads given width + \inheritedxtableframed\bgroup + \tabl_x_begin_of_cell + \fi} + +\protected\def\tabl_x_stop_cell_reflow_height + {\ifcase\c_tabl_x_skip_mode + \tabl_x_end_of_cell + \egroup + \fi + \egroup + \clf_x_table_set_reflow_height} + +\protected\def\tabl_x_start_cell_construct_yes[#settings]% + {\dostarttagged\t!tablecell\empty % can't we just tag the box + \setbox\b_tabl_x\hpack\bgroup + \setupcurrentxtable[#settings]% + \letxtableparameter\c!width \d_tabl_x_width % overloads given width + \letxtableparameter\c!height\d_tabl_x_height % overloads given height + \clf_x_table_init_construct + \inheritedxtableframed\bgroup + \tabl_x_begin_of_cell + \dotagxtablecell} + +\protected\def\tabl_x_start_cell_construct_nop + {\dostarttagged\t!tablecell\empty % can't we just tag the box + \setbox\b_tabl_x\hpack\bgroup + \letxtableparameter\c!width \d_tabl_x_width % overloads given width + \letxtableparameter\c!height\d_tabl_x_height % overloads given height (commenting it ... nice option) + \clf_x_table_init_construct + \inheritedxtableframed\bgroup + \tabl_x_begin_of_cell + \dotagxtablecell} + +\protected\def\tabl_x_stop_cell_construct + {\tabl_x_end_of_cell + \egroup + \dotagxtablesignal % harmless spot + \egroup + \clf_x_table_set_construct + \dostoptagged} + +% \permanent\tolerant\protected\def\startxcellgroup[#settings]% +% {\begingroup +% \ifarguments\or +% \tabl_x_set_checked{#settings}% +% \fi} +% +% \permanent\protected\def\stopxcellgroup +% {\endgroup} +% +% \permanent\tolerant\protected\def\startxrowgroup[#settings]% +% {\begingroup +% \ifarguments\or +% \tabl_x_set_checked{#settings}% +% \fi} +% +% \permanent\protected\def\stopxrowgroup +% {\dostoptagged +% \endgroup} + +\protected\def\tabl_x_set_checked#settings% + {\ifcsname\namedxtablehash{#settings}\s!parent\endcsname + \edef\currentxtable{#settings}% + \else + \setupcurrentxtable[#settings]% + \fi} + +\permanent\protected\def\startxtablehead{\begingroup\c_tabl_x_mode\plusone \tabl_x_start_partition} +\permanent\protected\def\startxtablefoot{\begingroup\c_tabl_x_mode\plustwo \tabl_x_start_partition} +\permanent\protected\def\startxtablenext{\begingroup\c_tabl_x_mode\plusthree\tabl_x_start_partition} +\permanent\protected\def\startxtablebody{\begingroup\c_tabl_x_mode\plusfour \tabl_x_start_partition} + +\permanent\tolerant\protected\def\tabl_x_start_partition[#settings]% + {\ifarguments\or + \tabl_x_set_checked{#settings}% + \fi} + +\protected\def\tabl_x_stop_partition + {\endgroup} + +\permanent\aliased\let\stopxtablehead\tabl_x_stop_partition +\permanent\aliased\let\stopxtablefoot\tabl_x_stop_partition +\permanent\aliased\let\stopxtablenext\tabl_x_stop_partition +\permanent\aliased\let\stopxtablebody\tabl_x_stop_partition + +%D This is an experiment! Beware: you can create loops by using nested +%D references to already chained settings. +%D +%D \startbuffer +%D \setupxtable[suffix][align=middle,foregroundcolor=red] +%D \setupxtable[blabla][foregroundstyle=slanted] +%D \setupxtable[crap] [foregroundcolor=blue] +%D \setupxtable[bold] [crap][foregroundstyle=bold] +%D +%D \startxtable[frame=off] +%D \startxtablehead +%D \startxrow[bold] +%D \startxcell[suffix] a 0 \stopxcell +%D \startxcell[blabla] a 1 \stopxcell +%D \startxcell a 2 \stopxcell +%D \stopxrow +%D \stopxtablehead +%D \startxtablebody +%D \startxrow \startxcell[suffix][ny=2] a 1 \stopxcell \startxcell b 1 \stopxcell \startxcell c 1 \stopxcell \stopxrow +%D \startxrow \startxcell b 2 \stopxcell \startxcell c 2 \stopxcell \stopxrow +%D \startxrow \startxcell[suffix] a 3 \stopxcell \startxcell b 3 \stopxcell \startxcell c 3 \stopxcell \stopxrow +%D \startxrow \startxcell[suffix] a 4 \stopxcell \startxcell b 4 \stopxcell \startxcell c 4 \stopxcell \stopxrow +%D \startxrow \startxcell[suffix] a 5 \stopxcell \startxcell b 5 \stopxcell \startxcell c 5 \stopxcell \stopxrow +%D \stopxtablebody +%D \stopxtable +%D \stopbuffer +%D +%D \typebuffer \placetable{}{\getbuffer} + +\appendtoks + \letvalue{\??xtablecheck\currentxtable}\relax % faster than checking parent +\to \everysetupxtable + +% \definefontfamily[newtimes][serif][TeX Gyre Termes] +% \setupxtable[newtimes][foregroundstyle=\newtimes] +% \startxcell[newtimes] ...\stopxcell +% \startxcell[foregroundstyle=\newtimes] ...\stopxcell + +% % \ifcsname\namedxtablehash{#tag}\s!parent\endcsname +% % \ifcsname\??xtablecheck#tag\endcsname +% \ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname % two times slower on keywords +% \expandafter\whatever % but more tolerant for tricky key=value +% \else +% \expandafter\whatever +% \fi[#tag] + +% groups + +\permanent\protected\def\startxgroup + {\begingroup + \doifelsenextoptionalcs\tabl_x_start_group_delayed_one\relax} + +\permanent\protected\def\stopxgroup + {\endgroup} + +\protected\def\tabl_x_start_group_delayed_one[#tag]% + {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname + \expandafter\tabl_x_start_group_delayed_two + \else + \expandafter\setupcurrentxtable + \fi[#tag]} + +\protected\def\tabl_x_start_group_delayed_two[#tag]% + {\ifx\currentxtable\empty \else + \chaintocurrentxtable{#tag}% + \fi + \edef\currentxtable{#tag}% + \doifelsenextoptionalcs\setupcurrentxtable\relax} + +\aliased\let\startxrowgroup \startxgroup +\aliased\let\stopxrowgroup \stopxgroup +\aliased\let\startxcellgroup\startxgroup +\aliased\let\stopxcellgroup \stopxgroup + +% cells (maybe also check for 1 etc but it becomes messy) + +\permanent\protected\def\startxcell + {\begingroup + \doifelsenextoptionalcs\tabl_x_start_cell_delayed_one\tabl_x_start_cell_nop} + +\protected\def\tabl_x_start_cell_delayed_one[#tag]% + {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname + \expandafter\tabl_x_start_cell_delayed_two + \else + \expandafter\tabl_x_start_cell_yes + \fi[#tag]} + +\protected\def\tabl_x_start_cell_delayed_two[#tag]% + {\ifx\currentxtable\empty \else + \chaintocurrentxtable{#tag}% + \fi + \edef\currentxtable{#tag}% + \doifelsenextoptionalcs\tabl_x_start_cell_yes\tabl_x_start_cell_nop} + +\permanent\protected\def\stopxcell + {\tabl_x_stop_cell + \endgroup} + +% rows + +\permanent\protected\def\startxrow + {\begingroup + \doifelsenextoptionalcs\tabl_x_start_row_delayed_one\tabl_x_start_row_nop} + +\protected\def\tabl_x_start_row_delayed_one[#tag]% + {\ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname + \expandafter\tabl_x_start_row_delayed_two + \else + \expandafter\tabl_x_start_row_yes + \fi[#tag]} + +\permanent\protected\def\tabl_x_start_row_delayed_two[#tag]% + {\ifx\currentxtable\empty \else + \chaintocurrentxtable{#tag}% + \fi + \edef\currentxtable{#tag}% + \doifelsenextoptionalcs\tabl_x_start_row_yes\tabl_x_start_row_nop} + +\permanent\protected\def\stopxrow + {\tabl_x_stop_row + \endgroup} + +%D A bonus, not advertised but some like it this way: + +\protected\def\tabl_x_nc + {\startxrow + \enforced\let\NC\tabl_x_nc_next + \enforced\let\NR\tabl_x_nr + \startxcell} + +\protected\def\tabl_x_nc_next + {\stopxcell + \startxcell} + +\protected\def\tabl_x_nr + {\stopxcell + \stopxrow + \enforced\let\NC\tabl_x_nc} + +\appendtoks + \enforced\let\NC\tabl_x_nc + \enforced\let\NR\tabl_x_nr +\to \everypreparextable + +%D Another bonus, suggested by Taco at the 2018 \CONTEXT\ meeting. + +\protected\def\tabl_x_c_cell_start#settings% + {\begingroup + \tabl_x_set_checked{#settings}% + \doifelsenextoptionalcs\tabl_x_start_cell_yes\tabl_x_start_cell_nop} + +\protected\def\tabl_x_c_cell_stop + {\tabl_x_stop_cell + \endgroup} + +% \protected\def\dummyxcell +% {\tabl_x_start_cell_nop +% \tabl_x_stop_cell} + +\mutable\let\t_tabl_x_swapped\relax + +\def\tabl_x_flush_swapped + {\dorecurse\c_tabl_x_swapped_max + {\expandafter + \startxrow + \the\csname\??xtableswap##1\endcsname\relax + \stopxrow}} + +\def\tabl_x_collect_allocate + {\expandafter\newtoks\csname\??xtableswap\number\c_tabl_x_swapped\endcsname + \expandafter\let\expandafter\t_tabl_x_swapped\csname\??xtableswap\number\c_tabl_x_swapped\endcsname} + +\def\tabl_x_collect_advance + {\global\advance\c_tabl_x_swapped\plusone + \ifnum\c_tabl_x_swapped>\c_tabl_x_swapped_max + \global\c_tabl_x_swapped_max\c_tabl_x_swapped + \fi + \mutable\expandafter\let\expandafter\t_tabl_x_swapped\csname\??xtableswap\number\c_tabl_x_swapped\endcsname + \ifx\t_tabl_x_swapped\relax + \tabl_x_collect_allocate + \fi} + +\protected\def\tabl_x_collect_cell_start + {\doifelsenextoptionalcs + \tabl_x_collect_cell_start_yes + \tabl_x_collect_cell_start_nop} + +\def\tabl_x_collect_cell_start_nop#content\stopxcell + {\tabl_x_collect_advance + \ifx\m_tabl_x_swapped_settings\empty + \gtoksapp\t_tabl_x_swapped{\tabl_x_c_cell_start{}#content\tabl_x_c_cell_stop}% + \else + \gtoksapp\t_tabl_x_swapped\expandafter{\expandafter\tabl_x_c_cell_start\expandafter{\m_tabl_x_swapped_settings}#content\tabl_x_c_cell_stop}% + \fi} + +\def\tabl_x_collect_cell_start_yes[#settings]#content\stopxcell + {\tabl_x_collect_advance + \ifx\m_tabl_x_swapped_settings\empty + \gtoksapp\t_tabl_x_swapped{\tabl_x_c_cell_start{}[#settings]#content\tabl_x_c_cell_stop}% + \else + \gtoksapp\t_tabl_x_swapped\expandafter{\expandafter\tabl_x_c_cell_start\expandafter{\m_tabl_x_swapped_settings}[#settings]#content\tabl_x_c_cell_stop}% + \fi + \getdummyparameters[\c!ny=1,#settings]% + \scratchcounter\numexpr\dummyparameter\c!ny-\plusone\relax + \ifcase\scratchcounter\else + \dorecurse\scratchcounter\tabl_x_collect_advance + \fi} + +\permanent\tolerant\protected\def\startxcolumn[#1]% + {\begingroup + \global\c_tabl_x_swapped\zerocount + \enforced\let\startxcell\tabl_x_collect_cell_start + \enforced\let\stopxcell \relax + \xdef\m_tabl_x_swapped_settings{#1}} + +\permanent\protected\def\stopxcolumn + {\endgroup} + +\appendtoks + \dorecurse\c_tabl_x_swapped_max + {\global\csname\??xtableswap\number#1\endcsname\emptytoks}% +\to \t_table_x_cleanup + +%D \startbuffer +%D \setupxtable[one][foregroundcolor=red] +%D \setupxtable[two][foregroundcolor=blue] +%D +%D \startlinecorrection +%D \startxtable +%D \startxrow[one] +%D \startxcell[width=5cm] Row 1, Column 1 \stopxcell +%D \startxcell Row 1, Column 2 \stopxcell +%D \startxcell Row 1, Column 3 \stopxcell +%D \stopxrow +%D \startxrow[two] +%D \startxcell Row 2, Column 1 \stopxcell +%D \startxcell Row 2, Column 2 \stopxcell +%D \startxcell Row 2, Column 3 \stopxcell +%D \stopxrow +%D \stopxtable +%D \stoplinecorrection +%D +%D \startlinecorrection +%D \startxtable +%D \startxcolumn[one] +%D \startxcell[width=5cm] Row 1, Column 1 \stopxcell +%D \startxcell Row 1, Column 2 \stopxcell +%D \startxcell Row 1, Column 3 \stopxcell +%D \stopxcolumn +%D \startxcolumn[two] +%D \startxcell Row 2, Column 1 \stopxcell +%D \startxcell Row 2, Column 2 \stopxcell +%D \startxcell Row 2, Column 3 \stopxcell +%D \stopxcolumn +%D \stopxtable +%D \stoplinecorrection +%D \stopbuffer +%D +%D \typebuffer \getbuffer + +\protect \endinput diff --git a/tex/context/base/mkiv/task-ini.lua b/tex/context/base/mkiv/task-ini.lua index 033672f45..45c0c3239 100644 --- a/tex/context/base/mkiv/task-ini.lua +++ b/tex/context/base/mkiv/task-ini.lua @@ -53,7 +53,6 @@ appendaction("processors", "fonts", "typesetters.fontkerns.handler", appendaction("processors", "fonts", "nodes.handlers.protectglyphs", nil, "nonut", "enabled" ) appendaction("processors", "fonts", "builders.kernel.ligaturing", nil, "nut", "disabled" ) appendaction("processors", "fonts", "builders.kernel.kerning", nil, "nut", "disabled" ) -appendaction("processors", "fonts", "builders.kernel.cleanup", nil, "nut", "enabled" ) appendaction("processors", "fonts", "nodes.handlers.stripping", nil, "nut", "disabled" ) appendaction("processors", "fonts", "nodes.handlers.flatten", nil, "nut", "disabled" ) appendaction("processors", "fonts", "fonts.goodies.colorschemes.coloring", nil, "nut", "disabled" ) diff --git a/tex/context/base/mkiv/toks-aux.lmt b/tex/context/base/mkiv/toks-aux.lmt index c77c868fc..e1a4e89b3 100644 --- a/tex/context/base/mkiv/toks-aux.lmt +++ b/tex/context/base/mkiv/toks-aux.lmt @@ -5,113 +5,172 @@ if not modules then modules = { } end modules ['toks-aux'] = { license = "see context related readme files" } -if CONTEXTLMTXMODE > 0 then +local type, tostring = type, tostring +local max = math.max +local formatters, gsub, char = string.formatters, string.gsub, string.char +local concat = table.concat - local type, tostring = type, tostring - local max = math.max - local formatters, gsub = string.formatters, string.gsub +local function flags(t) + if type(t) == "string" then + t = token.create(t) + end + local r = { } + if t.frozen then r[#r+1] = "frozen" end + if t.permanent then r[#r+1] = "permanent" end + if t.immutable then r[#r+1] = "immutable" end + if t.primitive then r[#r+1] = "primitive" end + if t.mutable then r[#r+1] = "mutable" end + if t.noaligned then r[#r+1] = "noaligned" end + if t.instance then r[#r+1] = "instance" end + if t.tolerant then r[#r+1] = "tolerant" end + if t.protected then r[#r+1] = "protected" end + return r +end + +tokens.flags= flags - interfaces.implement { - name = "showluatokens", - public = true, - protected = true, - actions = function() - local f0 = formatters["%s: %s"] - local nl = logs.newline - local wr = logs.writer - local t = token.peek_next() -- local t = token.scan_next() token.put_back(t) - local n = "" - local w = "" - local c = t.cmdname - if c == "left_brace" then - w = "given token list" - t = token.scan_toks(false) - elseif c == "register_toks" then - token.scan_next() - w = "token register" - n = t.csname or t.index - t = tex.gettoks(n,true) - elseif c == "internal_toks" then - token.scan_next() - w = "internal token variable" - n = t.csname or t.index - t = tex.gettoks(n,true) +interfaces.implement { + name = "showluatokens", + public = true, + protected = true, + actions = function() + local f0 = formatters["%s: %s"] + local nl = logs.newline + local wr = logs.writer + local t = token.peek_next() -- local t = token.scan_next() token.put_back(t) + local n = "" + local w = "" + local c = t.cmdname + if c == "left_brace" then + w = "given token list" + t = token.scan_toks(false) + elseif c == "register_toks" then + token.scan_next() + w = "token register" + n = t.csname or t.index + t = tex.gettoks(n,true) + elseif c == "internal_toks" then + token.scan_next() + w = "internal token variable" + n = t.csname or t.index + t = tex.gettoks(n,true) + else + n = token.scan_csname() + local r = flags(t) + local m = token.get_meaning(n,true) + r[#r+1] = "control sequence" + if type(m) == "table" then + t = m else - if t.protected then - w = "protected control sequence" - else - w = "control sequence" - end - n = token.scan_csname() - t = token.get_meaning(n,true) + t = { t } end - wr(f0(w,n)) - nl() - if type(t) == "table" then - local w1 = 4 - local w2 = 1 - local w3 = 3 - local w4 = 3 - for i=1,#t do - local ti = t[i] - w1 = max(w1,#tostring(ti.id)) - w2 = max(w2,#tostring(ti.command)) - w3 = max(w3,#tostring(ti.index)) - w4 = max(w4,#ti.cmdname) + w = concat(r, " ") + end + wr(f0(w,n)) + nl() + if type(t) == "table" then + local w1 = 4 + local w2 = 1 + local w3 = 3 + local w4 = 3 + for i=1,#t do + local ti = t[i] + w1 = max(w1,#tostring(ti.id)) + w2 = max(w2,#tostring(ti.command)) + w3 = max(w3,#tostring(ti.index)) + w4 = max(w4,#ti.cmdname) + end + local f1 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %s"] + local f2 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s"] + local f3 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %C"] + for i=1,#t do + local ti = t[i] + local cs = ti.csname + local id = ti.id + local ix = ti.index + local cd = ti.command + local cn = ti.cmdname + if cn == "prefix" and not cs then + cs = "always enforced" end - local f1 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %s"] - local f2 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s"] - local f3 = formatters["%" .. w1 .. "i %" .. w2 .. "i %" .. w3 .. "i %-" .. w4 .. "s %C"] - for i=1,#t do - local ti = t[i] - local cs = ti.csname - local id = ti.id - local ix = ti.index - local cd = ti.command - local cn = gsub(ti.cmdname,"_"," ") - if cs then - wr(f1(id,cd,ix,cn,cs)) - elseif cn == "letter" or cn == "other_char" then - wr(f3(id,cd,ix,cn,ix)) - else - wr(f2(id,cd,ix,cn)) - if cn == "end_match" then - wr("-------") - end + cn = gsub(cn,"_"," ") + if cs then + wr(f1(id,cd,ix,cn,cs)) + elseif cn == "letter" or cn == "other char" then + wr(f3(id,cd,ix,cn,ix)) + elseif cn == "match" then + local s + if ix == 32 then s = "optional spacer" -- space + elseif ix == 42 then s = "skip spaces" -- * + elseif ix == 43 then s = "keep braces" -- + + elseif ix == 45 then s = "thrash" -- - + elseif ix == 47 then s = "prune" -- / + elseif ix == 58 then s = "continue" -- : + elseif ix == 59 then s = "quit" -- ; + elseif ix == 61 then s = "mandate braces" -- = + elseif ix == 94 then s = "keep spaces" -- ^ + elseif ix == 95 then s = "keep mandate braces" -- _ + else s = "argument " .. char(ix) + end + wr(f1(id,cd,ix,cn,s)) + else + wr(f2(id,cd,ix,cn)) + if cn == "end match" then + wr("--------------") end end - nl() end + nl() end - } + end +} - -- For the moment here, will move to initex only (also see node-ini.lua); we need - -- to actually store these. +-- For the moment here, will move to initex only (also see node-ini.lua); we need +-- to actually store these. - local groupcodes = { } - local hyphenationcodes = { } +local groupcodes = { } +local glyphoptioncodes = { } +local hyphenationcodes = { } +local frozenparcodes = { } +local flagcodes = { } - for k, v in next, tex.getgroupvalues() do - groupcodes[k] = gsub(v,"_","") - end - for k, v in next, tex.gethyphenationvalues() do - hyphenationcodes[k] = gsub(v,"_","") - end +for k, v in next, tex.getgroupvalues() do + groupcodes[k] = gsub(v,"[_ ]","") +end +for k, v in next, tex.gethyphenationvalues() do + hyphenationcodes[k] = gsub(v,"[_ ]","") +end +for k, v in next, tex.getglyphoptionvalues() do + glyphoptioncodes[k] = gsub(v,"[_ ]","") +end +for k, v in next, tex.getfrozenparvalues() do + frozenparcodes[k] = gsub(v,"[_ ]","") +end +for k, v in next, tex.getflagvalues() do + flagcodes[k] = gsub(v,"[_ ]","") +end - if environment.initex then - local texchardef = tex.chardef +if environment.initex then - -- for k, v in next, prefixcodes do texchardef(v .. "prefixcode", k) end - for k, v in next, groupcodes do texchardef(v .. "groupcode", k) end - for k, v in next, hyphenationcodes do texchardef(v .. "hyphenationmodecode",k) end + local texintegerdef = tex.integerdef - end + for k, v in next, groupcodes do texintegerdef(v .. "groupcode", k,"immutable") end + for k, v in next, glyphoptioncodes do texintegerdef(v .. "code", k,"immutable") end + for k, v in next, hyphenationcodes do texintegerdef(v .. "hyphenationmodecode",k,"immutable") end + for k, v in next, frozenparcodes do texintegerdef("frozen" .. v .. "code", k,"immutable") end + for k, v in next, flagcodes do texintegerdef(v .. "flagcode", k,"immutable") end - groupcodes = utilities.storage.allocate(table.swapped(groupcodes, groupcodes)) - hyphenationcodes = utilities.storage.allocate(table.swapped(hyphenationcodes,hyphenationcodescodes)) +end - tex.groupcodes = groupcodes - tex.hyphenationcodes = hyphenationcodes +groupcodes = utilities.storage.allocate(table.swapped(groupcodes, groupcodes)) +glyphoptioncodes = utilities.storage.allocate(table.swapped(glyphoptioncodes,glyphoptioncodes)) +hyphenationcodes = utilities.storage.allocate(table.swapped(hyphenationcodes,hyphenationcodes)) +frozenparcodes = utilities.storage.allocate(table.swapped(frozenparcodes, frozenparcodes)) +flagcodes = utilities.storage.allocate(table.swapped(flagcodes, flagcodes)) -end +tex.groupcodes = groupcodes +tex.glyphoptioncodes = glyphoptioncodes +tex.hyphenationcodes = hyphenationcodes +tex.frozenparcodes = frozenparcodes +tex.flagcodes = flagcodes diff --git a/tex/context/base/mkiv/toks-aux.mkiv b/tex/context/base/mkiv/toks-aux.mkiv index 817a5aba9..f66b51ec5 100644 --- a/tex/context/base/mkiv/toks-aux.mkiv +++ b/tex/context/base/mkiv/toks-aux.mkiv @@ -65,8 +65,4 @@ \lastnamedcs\emptytoks \fi} -\ifcase\contextlmtxmode \or - \chardef\discretionarygroupcode = \discgroupcode -\fi - \protect diff --git a/tex/context/base/mkiv/toks-ini.lmt b/tex/context/base/mkiv/toks-ini.lmt index cf1edd272..23896883c 100644 --- a/tex/context/base/mkiv/toks-ini.lmt +++ b/tex/context/base/mkiv/toks-ini.lmt @@ -72,8 +72,8 @@ tokens.istoken = is_token tokens.isdefined = is_defined tokens.defined = is_defined -tokens.getdata = token.get_data -- only lmtx -tokens.setdata = token.set_data -- only lmtx +tokens.getinteger = token.get_integer +tokens.setinteger = token.set_integer local bits = { escape = 0x00000001, -- 2^00 @@ -296,8 +296,14 @@ if setinspector then cmdname = cmdname, active = t.active, expandable = t.expandable, - protected = t.protected, frozen = t.frozen, + tolerant = t.tolerant, + protected = t.protected, + primitive = t.primitive, + permanent = t.permanent, + noaligned = t.noaligned, + instance = t.instance, + immutable = t.imutable, user = t.user, } end diff --git a/tex/context/base/mkiv/toks-ini.lua b/tex/context/base/mkiv/toks-ini.lua index 7f3254dde..7120b47c3 100644 --- a/tex/context/base/mkiv/toks-ini.lua +++ b/tex/context/base/mkiv/toks-ini.lua @@ -66,9 +66,6 @@ tokens.istoken = is_token tokens.isdefined = is_defined tokens.defined = is_defined -tokens.getdata = token.get_data -- only lmtx -tokens.setdata = token.set_data -- only lmtx - local bits = { escape = 0x00000001, -- 2^00 begingroup = 0x00000002, -- 2^01 diff --git a/tex/context/base/mkiv/trac-deb.lmt b/tex/context/base/mkiv/trac-deb.lmt index 7a2eba2a0..88d686462 100644 --- a/tex/context/base/mkiv/trac-deb.lmt +++ b/tex/context/base/mkiv/trac-deb.lmt @@ -119,7 +119,7 @@ do local writenl = texio.write_nl local write = texio.write - local runtoks = tex.runtoks + local runlocal = tex.runlocal local terminaldata = false local context = context @@ -140,7 +140,7 @@ do terminaldata = false break else - runtoks("t_syst_terminal_data",nil,nil,true) -- obeymode + runlocal("t_syst_terminal_data",nil,nil,true) -- obeymode end end end @@ -284,7 +284,11 @@ function tracers.printerror(specification) local offset = specification.offset local endoffile = specification.endoffile local report = errorreporter(luaerrorline) - if errortype == errorvalues.eof then + if errortype == errorvalues.warning then + report("warning error: %s",lasttexerror or "-") + busy = false; + return; + elseif errortype == errorvalues.eof then report("runaway error: %s",lasttexerror or "-") if not quitonerror and texio.terminal then texio.terminal() -- not well tested @@ -377,7 +381,7 @@ directives.register("system.errorcontext", function(v) register('show_error_message', nop) register('show_warning_message', function() processwarning(v) end) register('intercept_lua_error', function() processerror(v) end) - register('intercept_tex_error', function(mode,eof) processerror(v,eof) end) + register('intercept_tex_error', function(mode,eof) processerror(v,eof) return mode end) else register('show_error_message', nil) register('show_warning_message', nil) diff --git a/tex/context/base/mkiv/trac-deb.mkiv b/tex/context/base/mkiv/trac-deb.mkiv index 994c357d0..77f54b5aa 100644 --- a/tex/context/base/mkiv/trac-deb.mkiv +++ b/tex/context/base/mkiv/trac-deb.mkiv @@ -13,11 +13,11 @@ \writestatus{loading}{ConTeXt Tracing Macros / Debugger} -\unprotect - %registerctxluafile{trac-lmx}{} \registerctxluafile{trac-deb}{autosuffix} +\unprotect + \unexpanded\def\breakpoint {\showdebuginfo\wait} \unexpanded\def\showtrackers {\clf_showtrackers} @@ -40,14 +40,10 @@ % \enabledirectives[system.showerror] -\unprotect - \ifcase\contextlmtxmode \else \newtoks \t_syst_terminal_data % \t_syst_terminal_data {\beginlocalcontrol\clf_fetchterminaldata\endlocalcontrol} \t_syst_terminal_data {\clf_fetchterminaldata} \fi -\protect - \protect \endinput diff --git a/tex/context/base/mkiv/trac-log.lua b/tex/context/base/mkiv/trac-log.lua index 4fbab5cdc..96b69a73e 100644 --- a/tex/context/base/mkiv/trac-log.lua +++ b/tex/context/base/mkiv/trac-log.lua @@ -8,6 +8,11 @@ if not modules then modules = { } end modules ['trac-log'] = { -- In fact all writes could go through lua and we could write the console and -- terminal handler in lua then. Ok, maybe it's slower then, so a no-go. +-- +-- This is the version for mtxrun. The alternative functions for the TeX engines +-- have been separated. In order to keep in sync we use tex specific witer names. +-- +-- Todo: some cleanup (less local needed). local next, type, select, print = next, type, select, print local format, gmatch, find = string.format, string.gmatch, string.find @@ -17,30 +22,16 @@ local utfchar = utf.char local datetime = os.date local openfile = io.open -local runningtex = tex and (tex.jobname or tex.formatname) --- local write_nl = texio and texio.write_nl or print --- local write = texio and texio.write or io.write - -local write_nl = runningtex and texio and texio.write_nl or print -local write = runningtex and texio and texio.write or io.write +local write_nl = print +local write = io.write local setmetatableindex = table.setmetatableindex local formatters = string.formatters local settings_to_hash = utilities.parsers.settings_to_hash local sortedkeys = table.sortedkeys --- variant is set now - local variant = "default" --- local variant = "ansi" - --- todo: less categories, more subcategories (e.g. nodes) --- todo: split into basics and ctx specific - ---[[ldx-- -<p>This is a prelude to a more extensive logging module. We no longer -provide <l n='xml'/> based logging as parsing is relatively easy anyway.</p> ---ldx]]-- +----- variant = "ansi" logs = logs or { } local logs = logs @@ -53,23 +44,6 @@ webpage : http://www.pragma-ade.nl / http://tex.aanhet.net wiki : http://contextgarden.net ]] --- -- we extend the formatters: --- --- function utilities.strings.unichr(s) return "U+" .. format("%05X",s) .. " (" .. utfchar(s) .. ")" end --- function utilities.strings.chruni(s) return utfchar(s) .. " (U+" .. format("%05X",s) .. ")" end --- --- utilities.strings.formatters.add ( --- string.formatters, "unichr", --- [[unichr(%s)]], --- [[local unichr = utilities.strings.unichr]] --- ) --- --- utilities.strings.formatters.add ( --- string.formatters, "chruni", --- [[chruni(%s)]], --- [[local chruni = utilities.strings.chruni]] --- ) - formatters.add ( formatters, "unichr", [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]] @@ -80,26 +54,6 @@ formatters.add ( [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]] ) --- function utilities.strings.unichk(s) return s <= 0xFFFF and ("U+" .. format("%05X",s) .. " (" .. utfchar(s) .. ")") or ("U+" .. format("%05X",s)) end --- function utilities.strings.chkuni(s) return s <= 0xFFFF and (utfchar(s) .. " (U+" .. format("%05X",s) .. ")") or ("U+" .. format("%05X",s)) end --- --- utilities.strings.formatters.add ( --- string.formatters, "unichk", --- [[unichk(%s)]], --- [[local unichk = utilities.strings.unichk]] --- ) --- --- utilities.strings.formatters.add ( --- string.formatters, "chkuni", --- [[chkuni(%s)]], --- [[local chkuni = utilities.strings.chkuni]] --- ) --- --- print(formatters["Missing character %!chruni! in font."](234)) --- print(formatters["Missing character %!unichr! in font."](234)) --- print(formatters["Missing character %!chkuni! in font."](234)) --- print(formatters["Missing character %!unichk! in font."](234)) - -- basic loggers local function ignore() end @@ -124,322 +78,7 @@ local function ansisupported(specification) end end -if runningtex and texio then - - if texio.setescape then - texio.setescape(0) -- or (false) - end - - if arg and ansisupported then - -- we're don't have environment.arguments yet - for k, v in next, arg do -- k can be negative ! - if v == "--ansi" or v == "--c:ansi" then - if ansisupported("ansi") then - variant = "ansi" - end - break - elseif v == "--ansilog" or v == "--c:ansilog" then - if ansisupported("ansilog") then - variant = "ansilog" - end - break - end - end - end - - local function useluawrites() - - -- quick hack, awaiting speedup in engine (8 -> 6.4 sec for --make with console2) - -- still needed for luajittex .. luatex should not have that ^^ mess - - local texio_write_nl = texio.write_nl - local texio_write = texio.write - local io_write = io.write - - write_nl = function(target,...) - if not io_write then - io_write = io.write - end - if target == "term and log" then - texio_write_nl("log",...) - texio_write_nl("term","") - io_write(...) - elseif target == "log" then - texio_write_nl("log",...) - elseif target == "term" then - texio_write_nl("term","") - io_write(...) - elseif type(target) == "number" then - texio_write_nl(target,...) -- a tex output channel - elseif target ~= "none" then - texio_write_nl("log",target,...) - texio_write_nl("term","") - io_write(target,...) - end - end - - write = function(target,...) - if not io_write then - io_write = io.write - end - if target == "term and log" then - texio_write("log",...) - io_write(...) - elseif target == "log" then - texio_write("log",...) - elseif target == "term" then - io_write(...) - elseif type(target) == "number" then - texio_write(target,...) -- a tex output channel - elseif target ~= "none" then - texio_write("log",target,...) - io_write(target,...) - end - end - - texio.write = write - texio.write_nl = write_nl - - useluawrites = ignore - - end - - -- local format = string.formatter - - local whereto = "both" - local target = nil - local targets = nil - - local formats = table.setmetatableindex("self") - local translations = table.setmetatableindex("self") - - local report_yes, subreport_yes, direct_yes, subdirect_yes, status_yes - local report_nop, subreport_nop, direct_nop, subdirect_nop, status_nop - - local variants = { - default = { - formats = { - report_yes = formatters["%-15s > %s\n"], - report_nop = formatters["%-15s >\n"], - direct_yes = formatters["%-15s > %s"], - direct_nop = formatters["%-15s >"], - subreport_yes = formatters["%-15s > %s > %s\n"], - subreport_nop = formatters["%-15s > %s >\n"], - subdirect_yes = formatters["%-15s > %s > %s"], - subdirect_nop = formatters["%-15s > %s >"], - status_yes = formatters["%-15s : %s\n"], - status_nop = formatters["%-15s :\n"], - }, - targets = { - logfile = "log", - log = "log", - file = "log", - console = "term", - terminal = "term", - both = "term and log", - }, - }, - ansi = { - formats = { - report_yes = formatters["[0;33m%-15s [0;1m>[0m %s\n"], - report_nop = formatters["[0;33m%-15s [0;1m>[0m\n"], - direct_yes = formatters["[0;33m%-15s [0;1m>[0m %s"], - direct_nop = formatters["[0;33m%-15s [0;1m>[0m"], - subreport_yes = formatters["[0;33m%-15s [0;1m>[0;35m %s [0;1m>[0m %s\n"], - subreport_nop = formatters["[0;33m%-15s [0;1m>[0;35m %s [0;1m>[0m\n"], - subdirect_yes = formatters["[0;33m%-15s [0;1m>[0;35m %s [0;1m>[0m %s"], - subdirect_nop = formatters["[0;33m%-15s [0;1m>[0;35m %s [0;1m>[0m"], - status_yes = formatters["[0;33m%-15s [0;1m:[0m %s\n"], - status_nop = formatters["[0;33m%-15s [0;1m:[0m\n"], - }, - targets = { - logfile = "none", - log = "none", - file = "none", - console = "term", - terminal = "term", - both = "term", - }, - } - } - - variants.ansilog = { - formats = variants.ansi.formats, - targets = variants.default.targets, - } - - logs.flush = io.flush - - writer = function(...) - write_nl(target,...) - end - - newline = function() - write_nl(target,"\n") - end - - report = function(a,b,c,...) - if c ~= nil then - write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...))) - elseif b then - write_nl(target,report_yes(translations[a],formats[b])) - elseif a then - write_nl(target,report_nop(translations[a])) - else - write_nl(target,"\n") - end - end - - direct = function(a,b,c,...) - if c ~= nil then - return direct_yes(translations[a],formatters[formats[b]](c,...)) - elseif b then - return direct_yes(translations[a],formats[b]) - elseif a then - return direct_nop(translations[a]) - else - return "" - end - end - - subreport = function(a,s,b,c,...) - if c ~= nil then - write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...))) - elseif b then - write_nl(target,subreport_yes(translations[a],translations[s],formats[b])) - elseif a then - write_nl(target,subreport_nop(translations[a],translations[s])) - else - write_nl(target,"\n") - end - end - - subdirect = function(a,s,b,c,...) - if c ~= nil then - return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...)) - elseif b then - return subdirect_yes(translations[a],translations[s],formats[b]) - elseif a then - return subdirect_nop(translations[a],translations[s]) - else - return "" - end - end - - status = function(a,b,c,...) - if c ~= nil then - write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...))) - elseif b then - write_nl(target,status_yes(translations[a],formats[b])) - elseif a then - write_nl(target,status_nop(translations[a])) - else - write_nl(target,"\n") - end - end - - settarget = function(askedwhereto) - whereto = askedwhereto or whereto or "both" - target = targets[whereto] - if not target then - whereto = "both" - target = targets[whereto] - end - if target == "term" or target == "term and log" then - logs.flush = io.flush - else - logs.flush = ignore - end - end - - local stack = { } - - pushtarget = function(newtarget) - insert(stack,target) - settarget(newtarget) - end - - poptarget = function() - if #stack > 0 then - settarget(remove(stack)) - end - end - - setformats = function(f) - formats = f - end - - settranslations = function(t) - translations = t - end - - setprocessor = function(f) - local writeline = write_nl - write_nl = function(target,...) - writeline(target,f(...)) - end - end - - setformatters = function(specification) - local t = nil - local f = nil - local d = variants.default - if not specification then - -- - elseif type(specification) == "table" then - t = specification.targets - f = specification.formats or specification - else - if not ansisupported(specification) then - specification = "default" - end - local v = variants[specification] - if v then - t = v.targets - f = v.formats - variant = specification - end - end - targets = t or d.targets - target = targets[whereto] or target - if f then - d = d.formats - else - f = d.formats - d = f - end - setmetatableindex(f,d) - report_yes = f.report_yes - report_nop = f.report_nop - subreport_yes = f.subreport_yes - subreport_nop = f.subreport_nop - direct_yes = f.direct_yes - direct_nop = f.direct_nop - subdirect_yes = f.subdirect_yes - subdirect_nop = f.subdirect_nop - status_yes = f.status_yes - status_nop = f.status_nop - if variant == "ansi" or variant == "ansilog" then - useluawrites() -- because tex escapes ^^, not needed in lmtx - end - settarget(whereto) - end - - setformatters(variant) - - setlogfile = ignore - settimedlog = ignore - - -- settimedlog = function() - -- local localtime = os.localtime - -- local writeline = write_nl - -- write_nl = function(f,...) - -- writeline(f,localtime() .. " | " .. concat { ... }) - -- end - -- settimedlog = ignore - -- end - -else +do local report_yes, subreport_yes, status_yes local report_nop, subreport_nop, status_nop @@ -788,80 +427,6 @@ directives.register("logs.target", function(v) settarget(v) end) --- tex specific loggers (might move elsewhere) - -if tex then - - local report = logs.reporter("pages") -- not needed but saves checking when we grep for it - local texgetcount = tex and tex.getcount - - local real, user, sub = 0, 0, 0 - - function logs.start_page_number() - real = texgetcount("realpageno") - user = texgetcount("userpageno") - sub = texgetcount("subpageno") - end - - local timing = false - local usage = false - local lasttime = nil - - logs.private = { - enablepagetiming = function() - usage = true - end, - getpagetiming = function() - return type(usage) == "table" and usage - end, - } - - trackers.register("pages.timing", function() timing = "" end) - - function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average - if timing or usage then - local elapsed = statistics.currenttime(statistics) - local average, page - if not lasttime or real < 2 then - average = elapsed - page = elapsed - else - average = elapsed / (real - 1) - page = elapsed - lasttime - end - lasttime = elapsed - if timing then - timing = formatters[", total %0.03f, page %0.03f, average %0.03f"](elapsed,page,average) - end - if usage then - usage = { - page = { - real = real, - user = user, - sub = sub, - }, - time = { - elapsed = elapsed, - page = page, - average = average, - } - } - end - end - if real <= 0 then - report("flushing page%s",timing) - elseif user <= 0 then - report("flushing realpage %s%s",real,timing) - elseif sub <= 0 then - report("flushing realpage %s, userpage %s%s",real,user,timing) - else - report("flushing realpage %s, userpage %s, subpage %s%s",real,user,sub,timing) - end - logs.flush() - end - -end - -- we don't have show_open and show_close callbacks yet ----- report_files = logs.reporter("files") @@ -888,14 +453,6 @@ logs.help = ignore -- obsolete -- applications --- local function reportlines(t,str) --- if str then --- for line in gmatch(str,"([^\n\r]*)[\n\r]") do --- t.report(line) --- end --- end --- end - local Carg, C, lpegmatch = lpeg.Carg, lpeg.C, lpeg.match local p_newline = lpeg.patterns.newline @@ -950,12 +507,12 @@ local function reportexport(t,method) end local reporters = { - lines = reportlines, -- not to be overloaded - banner = reportbanner, - version = reportversion, - help = reporthelp, - info = reportinfo, - export = reportexport, + lines = reportlines, -- not to be overloaded + banner = reportbanner, + version = reportversion, + help = reporthelp, + info = reportinfo, + export = reportexport, } local exporters = { @@ -1024,47 +581,10 @@ end local report_system = logs.reporter("system","logs") -function logs.obsolete(old,new) - local o = loadstring("return " .. new)() - if type(o) == "function" then - return function(...) - report_system("function %a is obsolete, use %a",old,new) - loadstring(old .. "=" .. new .. " return ".. old)()(...) - end - elseif type(o) == "table" then - local t, m = { }, { } - m.__index = function(t,k) - report_system("table %a is obsolete, use %a",old,new) - m.__index, m.__newindex = o, o - return o[k] - end - m.__newindex = function(t,k,v) - report_system("table %a is obsolete, use %a",old,new) - m.__index, m.__newindex = o, o - o[k] = v - end - if libraries then - libraries.obsolete[old] = t -- true - end - setmetatable(t,m) - return t - end -end - if utilities then utilities.report = report_system end -do - local texerror = tex and tex.error or print - local formatters = string.formatters - - function logs.texerrormessage(fmt,first,...) -- for the moment we put this function here - texerror(first and formatters[fmt](first,...) or fmt) - end - -end - -- this is somewhat slower but prevents out-of-order messages when print is mixed -- with texio.write @@ -1077,104 +597,3 @@ end if package.helpers.report then package.helpers.report = logs.reporter("package loader") -- when used outside mtxrun end - -if tex then - - local finalactions = { } - local fatalerrors = { } - local possiblefatal = { } - local loggingerrors = false - - function logs.loggingerrors() - return loggingerrors - end - - directives.register("logs.errors",function(v) - loggingerrors = v - if type(v) == "string" then - fatalerrors = settings_to_hash(v) - else - fatalerrors = { } - end - end) - - function logs.registerfinalactions(...) - insert(finalactions,...) -- so we can force an order if needed - end - - local what = nil - local report = nil - local state = nil - local target = nil - - local function startlogging(t,r,w,s) - target = t - state = force - force = true - report = type(r) == "function" and r or logs.reporter(r) - what = w - pushtarget(target) - newline() - if s then - report("start %s: %s",what,s) - else - report("start %s",what) - end - if target == "logfile" then - newline() - end - return report - end - - local function stoplogging() - if target == "logfile" then - newline() - end - report("stop %s",what) - if target == "logfile" then - newline() - end - poptarget() - state = oldstate - end - - function logs.startfilelogging(...) - return startlogging("logfile", ...) - end - - logs.stopfilelogging = stoplogging - - local done = false - - function logs.starterrorlogging(r,w,...) - if not done then - pushtarget("terminal") - newline() - logs.report("error logging","start possible issues") - poptarget() - done = true - end - if fatalerrors[w] then - possiblefatal[w] = true - end - return startlogging("terminal",r,w,...) - end - - logs.stoperrorlogging = stoplogging - - function logs.finalactions() - if #finalactions > 0 then - for i=1,#finalactions do - finalactions[i]() - end - if done then - pushtarget("terminal") - newline() - logs.report("error logging","stop possible issues") - poptarget() - end - return next(possiblefatal) and sortedkeys(possiblefatal) or false - end - end - -end diff --git a/tex/context/base/mkiv/trac-vis.lmt b/tex/context/base/mkiv/trac-vis.lmt new file mode 100644 index 000000000..7ac5964da --- /dev/null +++ b/tex/context/base/mkiv/trac-vis.lmt @@ -0,0 +1,1700 @@ +if not modules then modules = { } end modules ['trac-vis'] = { + version = 1.001, + optimize = true, + comment = "companion to trac-vis.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local node, nodes, attributes, tex = node, nodes, attributes, tex +local type, tonumber, next, rawget = type, tonumber, next, rawget +local gmatch = string.gmatch +local formatters = string.formatters +local round = math.round + +-- This module started out in the early days of mkiv and luatex with visualizing +-- kerns related to fonts. In the process of cleaning up the visual debugger code it +-- made sense to integrate some other code that I had laying around and replace the +-- old supp-vis debugging code. As only a subset of the old visual debugger makes +-- sense it has become a different implementation. Soms of the m-visual +-- functionality will also be ported. The code is rather trivial. The caching is not +-- really needed but saves upto 50% of the time needed to add visualization. Of +-- course the overall runtime is larger because of color and layer processing in the +-- backend (can be times as much) so the runtime is somewhat larger with full +-- visualization enabled. In practice this will never happen unless one is demoing. + +-- todo: global switch (so no attributes) +-- todo: maybe also xoffset, yoffset of glyph +-- todo: inline concat (more efficient) +-- todo: tags can also be numbers (just add to hash) +-- todo: make a lmtx variant (a few more efficient fetchers) + +local nodecodes = nodes.nodecodes + +local nuts = nodes.nuts +local tonut = nuts.tonut + +local setboth = nuts.setboth +local setlink = nuts.setlink +local setdisc = nuts.setdisc +local setlist = nuts.setlist +local setleader = nuts.setleader +local setsubtype = nuts.setsubtype +local setattr = nuts.setattr +local setwidth = nuts.setwidth +local setshift = nuts.setshift + +local getid = nuts.getid +local getfont = nuts.getfont +local getattr = nuts.getattr +local getsubtype = nuts.getsubtype +local getbox = nuts.getbox +local getlist = nuts.getlist +local getleader = nuts.getleader +local getnext = nuts.getnext +local getboth = nuts.getboth +local getdisc = nuts.getdisc +local getwhd = nuts.getwhd +local getkern = nuts.getkern +local getpenalty = nuts.getpenalty +local getwidth = nuts.getwidth +local getdepth = nuts.getdepth +local getshift = nuts.getshift +local getexpansion = nuts.getexpansion +local getdirection = nuts.getdirection +local getstate = nuts.getstate + +local isglyph = nuts.isglyph + +local hpack_nodes = nuts.hpack +local vpack_nodes = nuts.vpack +local copy_list = nuts.copy_list +local copy_node = nuts.copy_node +local flush_node_list = nuts.flush_list +local insert_node_before = nuts.insert_before +local insert_node_after = nuts.insert_after +local apply_to_nodes = nuts.apply +local effectiveglue = nuts.effective_glue + +local hpack_string = nuts.typesetters.tohpack + +local texgetattribute = tex.getattribute +local texsetattribute = tex.setattribute + +local setmetatableindex = table.setmetatableindex + +local unsetvalue = attributes.unsetvalue + +local current_font = font.current + +local fonthashes = fonts.hashes +local chardata = fonthashes.characters +local exheights = fonthashes.exheights +local emwidths = fonthashes.emwidths +local pt_factor = number.dimenfactors.pt + +local nodepool = nuts.pool +local new_rule = nodepool.rule +local new_kern = nodepool.kern +local new_glue = nodepool.glue +local new_hlist = nodepool.hlist +local new_vlist = nodepool.vlist + +local tracers = nodes.tracers +local visualizers = nodes.visualizers + +local setcolor = tracers.colors.set +local setlistcolor = tracers.colors.setlist +local settransparency = tracers.transparencies.set +local setlisttransparency = tracers.transparencies.setlist + +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming + +local a_visual = attributes.private("visual") +local a_layer = attributes.private("viewerlayer") + +local band = bit32.band +local bor = bit32.bor + +local enableaction = nodes.tasks.enableaction + +-- local trace_hbox +-- local trace_vbox +-- local trace_vtop +-- local trace_kern +-- local trace_glue +-- local trace_penalty +-- local trace_fontkern +-- local trace_strut +-- local trace_whatsit +-- local trace_user +-- local trace_math +-- local trace_italic +-- local trace_discretionary +-- local trace_expansion +-- local trace_line +-- local trace_space + +local report_visualize = logs.reporter("visualize") + +local modes = { + hbox = 0x000001, + vbox = 0x000002, + vtop = 0x000004, + kern = 0x000008, + glue = 0x000010, + penalty = 0x000020, + fontkern = 0x000040, + strut = 0x000080, + whatsit = 0x000100, + glyph = 0x000200, + simple = 0x000400, + simplehbox = 0x000401, + simplevbox = 0x000402, + simplevtop = 0x000404, + user = 0x000800, + math = 0x001000, + italic = 0x002000, + origin = 0x004000, + discretionary = 0x008000, + expansion = 0x010000, + line = 0x020000, + space = 0x040000, + depth = 0x080000, + marginkern = 0x100000, + mathlistkern = 0x200000, + dir = 0x400000, + par = 0x800000, +} + +local usedfont, exheight, emwidth +local l_penalty, l_glue, l_kern, l_fontkern, l_hbox, l_vbox, l_vtop, l_strut, l_whatsit, l_glyph, l_user, l_math, l_marginkern, l_mathlistkern, l_italic, l_origin, l_discretionary, l_expansion, l_line, l_space, l_depth, + l_dir, l_whatsit + +local enabled = false +local layers = { } + +local preset_boxes = modes.hbox + modes.vbox + modes.vtop + modes.origin +local preset_makeup = preset_boxes + + modes.kern + modes.glue + modes.penalty +local preset_all = preset_makeup + + modes.fontkern + modes.marginkern + modes.mathlistkern + + modes.whatsit + modes.glyph + modes.user + modes.math + + modes.dir + modes.whatsit + +function visualizers.setfont(id) + usedfont = id or current_font() + exheight = exheights[usedfont] + emwidth = emwidths[usedfont] +end + +-- we can preset a bunch of bits + +local userrule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule") +local outlinerule -- bah, not yet defined: todo, delayed(nuts.rules,"userrule") + +local function initialize() + -- + if not usedfont then + -- we use a narrow monospaced font -- infofont ? + visualizers.setfont(fonts.definers.define { name = "lmmonoltcond10regular", size = tex.sp("4pt") }) + end + -- + for mode, value in next, modes do + local tag = formatters["v_%s"](mode) + attributes.viewerlayers.define { + tag = tag, + title = formatters["visualizer %s"](mode), + visible = "start", + editable = "yes", + printable = "yes" + } + layers[mode] = attributes.viewerlayers.register(tag,true) + end + l_hbox = layers.hbox + l_vbox = layers.vbox + l_vtop = layers.vtop + l_glue = layers.glue + l_kern = layers.kern + l_penalty = layers.penalty + l_fontkern = layers.fontkern + l_strut = layers.strut + l_whatsit = layers.whatsit + l_glyph = layers.glyph + l_user = layers.user + l_math = layers.math + l_italic = layers.italic + l_marginkern = layers.marginkern + l_mathlistkern = layers.mathlistkern + l_origin = layers.origin + l_discretionary = layers.discretionary + l_expansion = layers.expansion + l_line = layers.line + l_space = layers.space + l_depth = layers.depth + l_dir = layers.dir + l_par = layers.par + -- + if not userrule then + userrule = nuts.rules.userrule + end + -- + if not outlinerule then + outlinerule = nuts.pool.outlinerule + end + initialize = false +end + +local function enable() + if initialize then + initialize() + end + enableaction("shipouts","nodes.visualizers.handler") + report_visualize("enabled") + enabled = true + tex.setcount("global","c_syst_visualizers_state",1) -- so that we can optimize at the tex end +end + +local function setvisual(n,a,what,list) -- this will become more efficient when we have the bit lib linked in + if not n or n == "reset" then + return unsetvalue + elseif n == true or n == "makeup" then + if not a or a == 0 or a == unsetvalue then + a = preset_makeup + else + a = bor(a,preset_makeup) + end + elseif n == "boxes" then + if not a or a == 0 or a == unsetvalue then + a = preset_boxes + else + a = bor(a,preset_boxes) + end + elseif n == "all" then + if what == false then + return unsetvalue + elseif not a or a == 0 or a == unsetvalue then + a = preset_all + else + a = bor(a,preset_all) + end + else + for s in gmatch(n,"[a-z]+") do + local m = modes[s] + if not m then + -- go on + elseif not a or a == 0 or a == unsetvalue then + a = m + else + a = bor(a,m) + end + end + end + if not a or a == 0 or a == unsetvalue then + return unsetvalue + elseif not enabled then -- must happen at runtime (as we don't store layers yet) + enable() + end + return a +end + +function nuts.setvisual(n,mode) + setattr(n,a_visual,setvisual(mode,getattr(n,a_visual),true)) +end + +function nuts.setvisuals(n,mode) -- currently the same + setattr(n,a_visual,setvisual(mode,getattr(n,a_visual),true,true)) +end + +-- fast setters + +do + + local cached = setmetatableindex(function(t,k) + if k == true then + return texgetattribute(a_visual) + elseif not k then + t[k] = unsetvalue + return unsetvalue + else + local v = setvisual(k) + t[k] = v + return v + end + end) + + -- local function applyvisuals(n,mode) + -- local a = cached[mode] + -- apply_to_nodes(n,function(n) setattr(n,a_visual,a) end) + -- end + + local a = unsetvalue + + local f = function(n) setattr(n,a_visual,a) end + + local function applyvisuals(n,mode) + a = cached[mode] + apply_to_nodes(n,f) + end + + nuts.applyvisuals = applyvisuals + + function nodes.applyvisuals(n,mode) + applyvisuals(tonut(n),mode) + end + + function visualizers.attribute(mode) + return cached[mode] + end + + visualizers.attributes = cached + +end + +function nuts.copyvisual(n,m) + setattr(n,a_visual,getattr(m,a_visual)) +end + +function visualizers.setvisual(n) + texsetattribute(a_visual,setvisual(n,texgetattribute(a_visual))) +end + +function visualizers.setlayer(n) + texsetattribute(a_layer,layers[n] or unsetvalue) +end + +local function set(mode,v) + texsetattribute(a_visual,setvisual(mode,texgetattribute(a_visual),v)) +end + +for mode, value in next, modes do + trackers.register(formatters["visualizers.%s"](mode), function(v) set(mode,v) end) +end + +local fraction = 10 + +trackers .register("visualizers.reset", function(v) set("reset", v) end) +trackers .register("visualizers.all", function(v) set("all", v) end) +trackers .register("visualizers.makeup", function(v) set("makeup",v) end) +trackers .register("visualizers.boxes", function(v) set("boxes", v) end) +directives.register("visualizers.fraction", function(v) fraction = (v and tonumber(v)) or (v == "more" and 5) or 10 end) + +local c_positive = "trace:b" +local c_negative = "trace:r" +local c_zero = "trace:g" +local c_text = "trace:s" +local c_space = "trace:y" +local c_space_x = "trace:m" +local c_skip_a = "trace:c" +local c_skip_b = "trace:m" +local c_glyph = "trace:o" +local c_ligature = "trace:s" +local c_white = "trace:w" +----- c_math = "trace:s" +----- c_origin = "trace:o" +----- c_discretionary = "trace:d" +----- c_expansion = "trace:o" +local c_depth = "trace:o" +local c_indent = "trace:s" + +local c_positive_d = "trace:db" +local c_negative_d = "trace:dr" +local c_zero_d = "trace:dg" +local c_text_d = "trace:ds" +local c_space_d = "trace:dy" +local c_space_x_d = "trace:dm" +local c_skip_a_d = "trace:dc" +local c_skip_b_d = "trace:dm" +local c_glyph_d = "trace:do" +local c_ligature_d = "trace:ds" +local c_white_d = "trace:dw" +local c_math_d = "trace:dr" +local c_origin_d = "trace:do" +local c_discretionary_d = "trace:dd" +----- c_expansion_d = "trace:do" +----- c_depth_d = "trace:do" +----- c_indent_d = "trace:ds" + +local function sometext(str,layer,color,textcolor,lap) -- we can just paste verbatim together .. no typesteting needed + local text = hpack_string(str,usedfont) + local size = getwidth(text) + local rule = new_rule(size,2*exheight,exheight/2) + local kern = new_kern(-size) + if color then + setcolor(rule,color) + end + if textcolor then + setlistcolor(getlist(text),textcolor) + end + local info = setlink(rule,kern,text) + setlisttransparency(info,c_zero) + info = hpack_nodes(info) + local width = getwidth(info) + if lap then + info = new_hlist(setlink(new_kern(-width),info)) + else + info = new_hlist(info) -- a bit overkill: double wrapped + end + if layer then + setattr(info,a_layer,layer) + end + return info, width +end + +local function someblob(str,layer,color,textcolor,width) + local text = hpack_string(str,usedfont) + local size = getwidth(text) + local rule = new_rule(width,2*exheight,exheight/2) + local kern = new_kern(-width + (width-size)/2) + if color then + setcolor(rule,color) + end + if textcolor then + setlistcolor(getlist(text),textcolor) + end + local info = setlink(rule,kern,text) + setlisttransparency(info,c_zero) + info = hpack_nodes(info) + local width = getwidth(info) + info = new_hlist(info) + if layer then + setattr(info,a_layer,layer) + end + return info, width +end + +local caches = setmetatableindex("table") + +local fontkern, italickern, marginkern, mathlistkern do + + local f_cache = caches["fontkern"] + local i_cache = caches["italickern"] + local m_cache = caches["marginkern"] + local l_cache = caches["mathlistkern"] + + local function somekern(head,current,cache,color,layer) + local width = getkern(current) + local extra = getexpansion(current) + local kern = width + extra + local info = cache[kern] + if not info then + local text = hpack_string(formatters[" %0.3f"](kern*pt_factor),usedfont) + local rule = new_rule(emwidth/fraction,6*exheight,2*exheight) + local list = getlist(text) + if kern > 0 then + setlistcolor(list,c_positive_d) + elseif kern < 0 then + setlistcolor(list,c_negative_d) + else + setlistcolor(list,c_zero_d) + end + setlisttransparency(list,color) + setcolor(rule,color) + settransparency(rule,color) + setshift(text,-5 * exheight) + info = new_hlist(setlink(rule,text)) + setattr(info,a_layer,layer) + f_cache[kern] = info + end + head = insert_node_before(head,current,copy_list(info)) + return head, current + end + + fontkern = function(head,current) + return somekern(head,current,f_cache,c_text_d,l_fontkern) + end + + italickern = function(head,current) + return somekern(head,current,i_cache,c_glyph_d,l_italic) + end + + marginkern = function(head,current) + return somekern(head,current,m_cache,c_glyph_d,l_marginkern) + end + + mathlistkern = function(head,current) + return somekern(head,current,l_cache,c_glyph_d,l_mathlistkern) + end + +end + +local glyphexpansion do + + local f_cache = caches["glyphexpansion"] + + glyphexpansion = function(head,current) + local extra = getexpansion(current) + if extra and extra ~= 0 then + extra = extra / 1000 + local info = f_cache[extra] + if not info then + local text = hpack_string(round(extra),usedfont) + local rule = new_rule(emwidth/fraction,exheight,2*exheight) + local list = getlist(text) + if extra > 0 then + setlistcolor(list,c_positive_d) + elseif extra < 0 then + setlistcolor(list,c_negative_d) + end + setlisttransparency(list,c_text_d) + setcolor(rule,c_text_d) + settransparency(rule,c_text_d) + setshift(text,1.5 * exheight) + info = new_hlist(setlink(rule,text)) + setattr(info,a_layer,l_expansion) + f_cache[extra] = info + end + head = insert_node_before(head,current,copy_list(info)) + return head, current + end + return head, current + end + +end + +local kernexpansion do + + local f_cache = caches["kernexpansion"] + + -- in mkiv we actually need to reconstruct but let's not do that now + + kernexpansion = function(head,current) + local extra = getexpansion(current) + if extra ~= 0 then + extra = extra / 1000 + local info = f_cache[extra] + if not info then + local text = hpack_string(round(extra),usedfont) + local rule = new_rule(emwidth/fraction,exheight,4*exheight) + local list = getlist(text) + if extra > 0 then + setlistcolor(list,c_positive_d) + elseif extra < 0 then + setlistcolor(list,c_negative_d) + end + setlisttransparency(list,c_text_d) + setcolor(rule,c_text_d) + settransparency(rule,c_text_d) + setshift(text,3.5 * exheight) + info = new_hlist(setlink(rule,text)) + setattr(info,a_layer,l_expansion) + f_cache[extra] = info + end + head = insert_node_before(head,current,copy_list(info)) + return head, current + end + return head, current + end + +end + +local whatsit do + + local whatsitcodes = nodes.whatsitcodes + local w_cache = caches["whatsit"] + + local tags = { + open = "OPN", + write = "WRI", + close = "CLS", + special = "SPE", + latelua = "LUA", + savepos = "POS", + userdefined = "USR", + literal = "LIT", + setmatrix = "MAT", + save = "SAV", + restore = "RES", + } + + whatsit = function(head,current) + local what = getsubtype(current) + local info = w_cache[what] + if info then + -- print("hit whatsit") + else + info = sometext(formatters["W:%s"](what),usedfont,nil,c_white) + setattr(info,a_layer,l_whatsit) + w_cache[what] = info + end + head, current = insert_node_after(head,current,copy_list(info)) + return head, current + end + +end + +local dir, par do + + local dircodes = nodes.dircodes + local dirvalues = nodes.dirvalues + + local cancel_code = dircodes.cancel + local l2r_code = dirvalues.l2r + local r2l_code = dirvalues.r2l + + local d_cache = caches["dir"] + + local tags = { + l2r = "L2R", + r2l = "R2L", + cancel = "CAN", + par = "PAR", + } + + par = function(head,current) + local what = "par" -- getsubtype(current) + local info = d_cache[what] + if info then + -- print("hit par") + else + info = sometext(formatters["L:%s"](what),usedfont,nil,c_white) + setattr(info,a_layer,l_dir) + d_cache[what] = info + end + return head, current + end + + dir = function(head,current) + local what = getsubtype(current) + if what == cancelcode then + what = "cancel" + elseif getdirection(current) == r2l_code then + what = "r2l" + else + what = "l2r" + end + local info = d_cache[what] + if info then + -- print("hit dir") + else + info = sometext(formatters["D:%s"](what),usedfont,nil,c_white) + setattr(info,a_layer,l_dir) + d_cache[what] = info + end + return head, current + end + +end + +local user do + + local u_cache = caches["user"] + + user = function(head,current) + local what = getsubtype(current) + local info = u_cache[what] + if info then + -- print("hit user") + else + info = sometext(formatters["U:%s"](what),usedfont) + setattr(info,a_layer,l_user) + u_cache[what] = info + end + head, current = insert_node_after(head,current,copy_list(info)) + return head, current + end + +end + +local math do + + local mathcodes = nodes.mathcodes + local m_cache = { + beginmath = caches["bmath"], + endmath = caches["emath"], + } + local tags = { + beginmath = "B", + endmath = "E", + } + + math = function(head,current) + local what = getsubtype(current) + local tag = mathcodes[what] + local skip = getkern(current) + getwidth(current) -- surround + local info = m_cache[tag][skip] + if info then + -- print("hit math") + else + local text, width = sometext(formatters["M:%s"](tag and tags[tag] or what),usedfont,nil,c_math_d) + local rule = new_rule(skip,-655360/fraction,2*655360/fraction) + setcolor(rule,c_math_d) + settransparency(rule,c_math_d) + setattr(rule,a_layer,l_math) + if tag == "beginmath" then + info = new_hlist(setlink(new_glue(-skip),rule,new_glue(-width),text)) + else + info = new_hlist(setlink(new_glue(-skip),rule,new_glue(-skip),text)) + end + setattr(info,a_layer,l_math) + m_cache[tag][skip] = info + end + head, current = insert_node_after(head,current,copy_list(info)) + return head, current + end + +end + +local ruleddepth do + + ruleddepth = function(current,wd,ht,dp) + local wd, ht, dp = getwhd(current) + if dp ~= 0 then + local rule = new_rule(wd,0,dp) + setcolor(rule,c_depth) + settransparency(rule,c_zero) + setattr(rule,a_layer,l_depth) + setlist(current,setlink(rule,new_kern(-wd),getlist(current))) + end + end + +end + +local ruledbox do + + local b_cache = caches["box"] + local o_cache = caches["origin"] + + setmetatableindex(o_cache,function(t,size) + local rule = new_rule(2*size,size,size) + local origin = hpack_nodes(rule) + setcolor(rule,c_origin_d) + settransparency(rule,c_origin_d) + setattr(rule,a_layer,l_origin) + t[size] = origin + return origin + end) + + ruledbox = function(head,current,vertical,layer,what,simple,previous,trace_origin,parent) + local wd, ht, dp = getwhd(current) + if wd ~= 0 then + local shift = getshift(current) + local next = getnext(current) + local prev = previous + setboth(current) + local linewidth = emwidth/fraction + local size = 2*linewidth + local this + if not simple then + this = b_cache[what] + if not this then + local text = hpack_string(what,usedfont) + this = setlink(new_kern(-getwidth(text)),text) + setlisttransparency(this,c_text) + this = new_hlist(this) + b_cache[what] = this + end + end + -- we need to trigger the right mode (else sometimes no whatits) + local info = setlink( + this and copy_list(this) or nil, + (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule { + width = wd, + height = ht, + depth = dp, + line = linewidth, + type = "box", + dashed = 3*size, + } + ) + -- + setlisttransparency(info,c_text) + info = new_hlist(info) -- important + -- + setattr(info,a_layer,layer) + if vertical then + if shift == 0 then + info = setlink(current,dp ~= 0 and new_kern(-dp) or nil,info) + elseif trace_origin then + local size = 2*size + local origin = o_cache[size] + origin = copy_list(origin) + if getid(parent) == vlist_code then + setshift(origin,-shift) + info = setlink(current,new_kern(-size),origin,new_kern(-size-dp),info) + else + -- todo .. i need an example + info = setlink(current,dp ~= 0 and new_kern(-dp) or nil,info) + end + setshift(current,0) + else + info = setlink(current,new_dp ~= 0 and new_kern(-dp) or nil,info) + setshift(current,0) + end + info = new_vlist(info,wd,ht,dp,shift) + else + if shift == 0 then + info = setlink(current,new_kern(-wd),info) + elseif trace_origin then + local size = 2*size + local origin = o_cache[size] + origin = copy_list(origin) + if getid(parent) == vlist_code then + info = setlink(current,new_kern(-wd-size-shift),origin,new_kern(-size+shift),info) + else + setshift(origin,-shift) + info = setlink(current,new_kern(-wd-size),origin,new_kern(-size),info) + end + setshift(current,0) + else + info = setlink(current,new_kern(-wd),info) + setshift(current,0) + end + info = new_hlist(info,wd,ht,dp,shift) + end + if next then + setlink(info,next) + end + if prev and prev > 0 then + setlink(prev,info) + end + if head == current then + return info, info + else + return head, info + end + else + return head, current + end + end + +end + +local ruledglyph do + + -- see boundingbox feature .. maybe a pdf stream is more efficient, after all we + -- have a frozen color anyway or i need a more detailed cache .. below is a more + -- texie approach + + ruledglyph = function(head,current,previous) -- wrong for vertical glyphs + local wd = getwidth(current) + if wd ~= 0 then + local wd, ht, dp = getwhd(current) + local next = getnext(current) + local prev = previous + setboth(current) + local linewidth = emwidth/(2*fraction) + local info + -- + info = setlink( + (dp == 0 and outlinerule and outlinerule(wd,ht,dp,linewidth)) or userrule { + width = wd, + height = ht, + depth = dp, + line = linewidth, + type = "box", + }, + new_kern(-wd) + ) + -- + local c, f = isglyph(current) + local char = chardata[f][c] + if char and type(char.unicode) == "table" then -- hackery test + setlistcolor(info,c_ligature) + setlisttransparency(info,c_ligature_d) + else + setlistcolor(info,c_glyph) + setlisttransparency(info,c_glyph_d) + end + info = new_hlist(info) + setattr(info,a_layer,l_glyph) + local info = setlink(current,new_kern(-wd),info) + info = hpack_nodes(info) + setwidth(info,wd) + if next then + setlink(info,next) + end + if prev then + setlink(prev,info) + end + if head == current then + return info, info + else + return head, info + end + else + return head, current + end + end + + function visualizers.setruledglyph(f) + ruledglyph = f or ruledglyph + end + +end + +local ruledglue do + + local gluecodes = nodes.gluecodes + + local userskip_code = gluecodes.userskip + local spaceskip_code = gluecodes.spaceskip + local xspaceskip_code = gluecodes.xspaceskip + local zerospaceskip_code = gluecodes.zerospaceskip or gluecodes.userskip + -- local keepskip_code = gluecodes.keepskip or gluecodes.userskip + local leftskip_code = gluecodes.leftskip + local rightskip_code = gluecodes.rightskip + local parfillleftskip_code = gluecodes.parfillleftskip or parfillskip_code + local parfillrightskip_code = gluecodes.parfillrightskip or parfillskip_code + local indentskip_code = gluecodes.indentskip + local correctionskip_code = gluecodes.correctionskip + + local g_cache_v = caches["vglue"] + local g_cache_h = caches["hglue"] + + local tags = { + -- [userskip_code] = "US", + [gluecodes.lineskip] = "LI", + [gluecodes.baselineskip] = "BS", + [gluecodes.parskip] = "PS", + [gluecodes.abovedisplayskip] = "DA", + [gluecodes.belowdisplayskip] = "DB", + [gluecodes.abovedisplayshortskip] = "SA", + [gluecodes.belowdisplayshortskip] = "SB", + [gluecodes.topskip] = "TS", + [gluecodes.splittopskip] = "ST", + [gluecodes.tabskip] = "AS", + [gluecodes.lefthangskip] = "LH", + [gluecodes.righthangskip] = "RH", + [gluecodes.thinmuskip] = "MS", + [gluecodes.medmuskip] = "MM", + [gluecodes.thickmuskip] = "ML", + [gluecodes.intermathskip] = "IM", + [gluecodes.keepskip or 99] = "KS", + [gluecodes.mathskip] = "MT", + [gluecodes.leaders] = "NL", + [gluecodes.cleaders] = "CL", + [gluecodes.xleaders] = "XL", + [gluecodes.gleaders] = "GL", + -- true = "VS", + -- false = "HS", + [leftskip_code] = "LS", + [rightskip_code] = "RS", + [spaceskip_code] = "SP", + [xspaceskip_code] = "XS", + [zerospaceskip_code] = "ZS", + [parfillleftskip_code] = "PL", + [parfillrightskip_code] = "PR", + [indentskip_code] = "IN", + [correctionskip_code] = "CS", + } + + -- we sometimes pass previous as we can have issues in math (not watertight for all) + + ruledglue = function(head,current,vertical,parent) + local subtype = getsubtype(current) + local width = effectiveglue(current,parent) + local amount = formatters["%s:%0.3f"](tags[subtype] or (vertical and "VS") or "HS",width*pt_factor) + local info = (vertical and g_cache_v or g_cache_h)[amount] + if info then + -- print("glue hit") + else + if subtype == spaceskip_code or subtype == xspaceskip_code or subtype == zerospaceskip_code then + 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 == 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 + if width > 0 then + info = sometext(amount,l_glue,c_positive) + elseif width < 0 then + info = sometext(amount,l_glue,c_negative) + else + info = sometext(amount,l_glue,c_zero) + end + else + info = sometext(amount,l_glue,c_skip_b) + end + (vertical and g_cache_v or g_cache_h)[amount] = info + end + info = copy_list(info) + if vertical then + info = vpack_nodes(info) + end + head, current = insert_node_before(head,current,info) + return head, getnext(current) + end + + -- ruledspace = function(head,current,parent) + -- local subtype = getsubtype(current) + -- if subtype == spaceskip_code or subtype == xspaceskip_code or subtype == zerospaceskip_code then + -- local width = effectiveglue(current,parent) + -- local amount = formatters["%s:%0.3f"](tags[subtype] or "HS",width*pt_factor) + -- local info = g_cache_h[amount] + -- if info then + -- -- print("space hit") + -- else + -- info = sometext(amount,l_glue,c_space) + -- g_cache_h[amount] = info + -- end + -- info = copy_list(info) + -- head, current = insert_node_before(head,current,info) + -- return head, getnext(current) + -- else + -- return head, current + -- end + -- end + + local g_cache_s = caches["space"] + local g_cache_x = caches["xspace"] + + ruledspace = function(head,current,parent) + local subtype = getsubtype(current) + if subtype == spaceskip_code or subtype == xspaceskip_code or subtype == zerospaceskip_code then -- not yet all space + local width = effectiveglue(current,parent) + local info + if subtype == spaceskip_code then + info = g_cache_s[width] + if not info then + info = someblob("SP",l_glue,c_space,nil,width) + g_cache_s[width] = info + end + else + info = g_cache_x[width] + if not info then + info = someblob("XS",l_glue,c_space_x,nil,width) + g_cache_x[width] = info + end + end + info = copy_list(info) + head, current = insert_node_before(head,current,info) + return head, getnext(current) + else + return head, current + end + end + +end + +local ruledkern do + + local k_cache_v = caches["vkern"] + local k_cache_h = caches["hkern"] + + ruledkern = function(head,current,vertical,mk) + local kern = getkern(current) + local cache = vertical and k_cache_v or k_cache_h + local info = cache[kern] + if not info then + local amount = formatters["%s:%0.3f"](vertical and "VK" or (mk and "MK") or "HK",kern*pt_factor) + if kern > 0 then + info = sometext(amount,l_kern,c_positive) + elseif kern < 0 then + info = sometext(amount,l_kern,c_negative) + else + info = sometext(amount,l_kern,c_zero) + end + cache[kern] = info + end + info = copy_list(info) + if vertical then + info = vpack_nodes(info) + end + head, current = insert_node_before(head,current,info) + return head, getnext(current) + end + +end + +local ruleditalic do + + local i_cache = caches["italic"] + + ruleditalic = function(head,current) + local kern = getkern(current) + local info = i_cache[kern] + if not info then + local amount = formatters["%s:%0.3f"]("IC",kern*pt_factor) + if kern > 0 then + info = sometext(amount,l_kern,c_positive) + elseif kern < 0 then + info = sometext(amount,l_kern,c_negative) + else + info = sometext(amount,l_kern,c_zero) + end + i_cache[kern] = info + end + info = copy_list(info) + head, current = insert_node_before(head,current,info) + return head, getnext(current) + end + +end + +local ruledmarginkern do + + local m_cache = caches["marginkern"] + + ruledmarginkern = function(head,current) + local kern = getkern(current) + local info = m_cache[kern] + if not info then + local amount = formatters["%s:%0.3f"]("MK",kern*pt_factor) + if kern > 0 then + info = sometext(amount,l_marginkern,c_positive) + elseif kern < 0 then + info = sometext(amount,l_marginkern,c_negative) + else + info = sometext(amount,l_marginkern,c_zero) + end + m_cache[kern] = info + end + info = copy_list(info) + head, current = insert_node_before(head,current,info) + return head, getnext(current) + end + +end + +local ruledmathlistkern do + + local l_cache = caches["mathlistkern"] + + ruledmathlistkern = function(head,current) + local kern = getkern(current) + local info = l_cache[kern] + if not info then + local amount = formatters["%s:%0.3f"]("LK",kern*pt_factor) + if kern > 0 then + info = sometext(amount,l_mathlistkern,c_positive) + elseif kern < 0 then + info = sometext(amount,l_mathlistkern,c_negative) + else + info = sometext(amount,l_mathlistkern,c_zero) + end + l_cache[kern] = info + end + info = copy_list(info) + head, current = insert_node_before(head,current,info) + return head, getnext(current) + end + +end + +local ruleddiscretionary do + + local d_cache = caches["discretionary"] + + ruleddiscretionary = function(head,current) + local d = d_cache[true] + if not the_discretionary then + local rule = new_rule(4*emwidth/fraction,4*exheight,exheight) + local kern = new_kern(-2*emwidth/fraction) + setlink(kern,rule) + setcolor(rule,c_discretionary_d) + settransparency(rule,c_discretionary_d) + setattr(rule,a_layer,l_discretionary) + d = new_hlist(kern) + d_cache[true] = d + end + insert_node_after(head,current,copy_list(d)) + return head, current + end + +end + +local ruledpenalty do + + local p_cache_v = caches["vpenalty"] + local p_cache_h = caches["hpenalty"] + + local raisepenalties = false + + directives.register("visualizers.raisepenalties",function(v) raisepenalties = v end) + + ruledpenalty = function(head,current,vertical) + local penalty = getpenalty(current) + local info = (vertical and p_cache_v or p_cache_h)[penalty] + if info then + -- print("penalty hit") + else + local amount = formatters["%s:%s"](vertical and "VP" or "HP",penalty) + if penalty > 0 then + info = sometext(amount,l_penalty,c_positive) + elseif penalty < 0 then + info = sometext(amount,l_penalty,c_negative) + else + info = sometext(amount,l_penalty,c_zero) + end + (vertical and p_cache_v or p_cache_h)[penalty] = info + end + info = copy_list(info) + if vertical then + info = vpack_nodes(info) + elseif raisepenalties then + setshift(info,-65536*4) + end + head, current = insert_node_before(head,current,info) + return head, getnext(current) + end + +end + +do + + local disc_code = nodecodes.disc + local kern_code = nodecodes.kern + local glyph_code = nodecodes.glyph + local glue_code = nodecodes.glue + local penalty_code = nodecodes.penalty + local whatsit_code = nodecodes.whatsit + local user_code = nodecodes.user + local math_code = nodecodes.math + local hlist_code = nodecodes.hlist + local vlist_code = nodecodes.vlist + local marginkern_code = nodecodes.marginkern + local mathlistkern_code = nodecodes.mathlistkern + local dir_code = nodecodes.dir + local par_code = nodecodes.par + + local kerncodes = nodes.kerncodes + local fontkern_code = kerncodes.fontkern + local italickern_code = kerncodes.italiccorrection + local leftmarginkern_code = kerncodes.leftmarginkern + local rightmarginkern_code = kerncodes.rightmarginkern + local mathlistkern_code = kerncodes.mathlistkern + ----- userkern_code = kerncodes.userkern + + local listcodes = nodes.listcodes + local linelist_code = listcodes.line + + local vtop_package_state = 3 -- todo: symbolic + + local cache + + local function visualize(head,vertical,forced,parent) + local trace_hbox = false + local trace_vbox = false + local trace_vtop = false + local trace_kern = false + local trace_glue = false + local trace_penalty = false + local trace_fontkern = false + local trace_strut = false + local trace_whatsit = false + local trace_glyph = false + local trace_simple = false + local trace_user = false + local trace_math = false + local trace_italic = false + local trace_origin = false + local trace_discretionary = false + local trace_expansion = false + local trace_line = false + local trace_space = false + local trace_depth = false + local trace_dir = false + local trace_par = false + local current = head + local previous = nil + local attr = unsetvalue + local prev_trace_fontkern = nil + local prev_trace_italic = nil + local prev_trace_marginkern = nil +-- local prev_trace_mathlist = nil + local prev_trace_expansion = nil + + while current do + local id = getid(current) + local a = forced or getattr(current,a_visual) or unsetvalue + local subtype + if a ~= attr then + prev_trace_fontkern = trace_fontkern + prev_trace_italic = trace_italic + prev_trace_marginkern = trace_marginkern +-- prev_trace_mathlistkern = trace_mathlistkern + prev_trace_expansion = trace_expansion + attr = a + if a == unsetvalue then + trace_hbox = false + trace_vbox = false + trace_vtop = false + trace_kern = false + trace_glue = false + trace_penalty = false + trace_fontkern = false + trace_strut = false + trace_whatsit = false + trace_glyph = false + trace_simple = false + trace_user = false + trace_math = false + trace_italic = false + trace_origin = false + trace_discretionary = false + trace_expansion = false + trace_line = false + trace_space = false + trace_depth = false + trace_marginkern = false + trace_mathlistkern = false + trace_dir = false + trace_par = false + if id == kern_code then + goto kern + else + goto list + end + else -- dead slow: + -- cache[a]() + trace_hbox = band(a,0x000001) ~= 0 + trace_vbox = band(a,0x000002) ~= 0 + trace_vtop = band(a,0x000004) ~= 0 + trace_kern = band(a,0x000008) ~= 0 + trace_glue = band(a,0x000010) ~= 0 + trace_penalty = band(a,0x000020) ~= 0 + trace_fontkern = band(a,0x000040) ~= 0 + trace_strut = band(a,0x000080) ~= 0 + trace_whatsit = band(a,0x000100) ~= 0 + trace_glyph = band(a,0x000200) ~= 0 + trace_simple = band(a,0x000400) ~= 0 + trace_user = band(a,0x000800) ~= 0 + trace_math = band(a,0x001000) ~= 0 + trace_italic = band(a,0x002000) ~= 0 + trace_origin = band(a,0x004000) ~= 0 + trace_discretionary = band(a,0x008000) ~= 0 + trace_expansion = band(a,0x010000) ~= 0 + trace_line = band(a,0x020000) ~= 0 + trace_space = band(a,0x040000) ~= 0 + trace_depth = band(a,0x080000) ~= 0 + trace_marginkern = band(a,0x100000) ~= 0 + trace_mathlistkern = band(a,0x200000) ~= 0 + trace_dir = band(a,0x400000) ~= 0 + trace_whatsit = band(a,0x800000) ~= 0 + end + elseif a == unsetvalue then + goto list + end + if trace_strut then + setattr(current,a_layer,l_strut) + elseif id == glyph_code then + if trace_glyph then + head, current = ruledglyph(head,current,previous) + end + if trace_expansion then + head, current = glyphexpansion(head,current) + end + elseif id == disc_code then + if trace_discretionary then + head, current = ruleddiscretionary(head,current) + end + local pre, post, replace = getdisc(current) + if pre then + pre = visualize(pre,false,a,parent) + end + if post then + post = visualize(post,false,a,parent) + end + if replace then + replace = visualize(replace,false,a,parent) + end + setdisc(current,pre,post,replace) + elseif id == kern_code then + goto kern + elseif id == glue_code then + local content = getleader(current) + if content then + setleader(current,visualize(content,false,nil,parent)) + elseif trace_glue then + head, current = ruledglue(head,current,vertical,parent) + elseif trace_space then + head, current = ruledspace(head,current,parent) + end + elseif id == penalty_code then + if trace_penalty then + head, current = ruledpenalty(head,current,vertical) + end + elseif id == hlist_code or id == vlist_code then + goto list + elseif id == whatsit_code then + if trace_whatsit then + head, current = whatsit(head,current) + end + elseif id == user_code then + if trace_user then + head, current = user(head,current) + end + elseif id == math_code then + if trace_math then + head, current = math(head,current) + end + elseif id == marginkern_code then + if trace_kern then + head, current = ruledkern(head,current,vertical,true) + end + elseif id == dir_code then + if trace_dir then + head, current = dir(head,current) + end + elseif id == par_code then + if trace_par then + head, current = par(head,current) + end + end + goto next + ::kern:: + subtype = getsubtype(current) + if subtype == fontkern_code then + if trace_fontkern or prev_trace_fontkern then + head, current = fontkern(head,current) + end + if trace_expansion or prev_trace_expansion then + head, current = kernexpansion(head,current) + end + elseif subtype == italickern_code then + if trace_italic or prev_trace_italic then + head, current = italickern(head,current) + elseif trace_kern then + head, current = ruleditalic(head,current) + end + elseif subtype == leftmarginkern_code or subtype == rightmarginkern_code then + if trace_marginkern or prev_trace_marginkern then + head, current = marginkern(head,current) + elseif trace_kern then + head, current = ruledmarginkern(head,current) + end + elseif subtype == mathlistkern_code then + if trace_mathlist then -- or prev_trace_mathlist then + head, current = mathlistkern(head,current) + elseif trace_kern then + head, current = ruledmathlistkern(head,current) + end + else + if trace_kern then + head, current = ruledkern(head,current,vertical) + end + end + goto next; + ::list:: + if id == hlist_code then + local content = getlist(current) + if content then + setlist(current,visualize(content,false,nil,current)) + end + if trace_depth then + ruleddepth(current) + end + if trace_line and getsubtype(current) == linelist_code then + head, current = ruledbox(head,current,false,l_line,"L__",trace_simple,previous,trace_origin,parent) + elseif trace_hbox then + head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple,previous,trace_origin,parent) + end + elseif id == vlist_code then + local content = getlist(current) + local isvtop = getstate(current) == vtop_package_state + local tag = nil + local layer = nil + if content then + setlist(current,visualize(content,true,nil,current)) + end + if trace_vtop then + if isvtop then + tag = "_T_" + layer = l_vtop + elseif trace_vbox then + tag = "__V" + layer = l_vbox + end + elseif trace_vbox then + if not isvtop then + tag = "__V" + layer = l_vbox + end + end + if tag then + head, current = ruledbox(head,current,true,layer,tag,trace_simple,previous,trace_origin,parent) + end + end + ::next:: + previous = current + current = getnext(current) + end + return head + end + + local function cleanup() + for tag, cache in next, caches do + for k, v in next, cache do + flush_node_list(v) + end + end + cleanup = function() + report_visualize("error, duplicate cleanup") + end + end + + luatex.registerstopactions(cleanup) + + function visualizers.handler(head) + if usedfont then + starttiming(visualizers) + head = visualize(head,true) + stoptiming(visualizers) + return head, true + else + return head, false + end + end + + function visualizers.box(n) + if usedfont then + starttiming(visualizers) + local box = getbox(n) + if box then + setlist(box,visualize(getlist(box),getid(box) == vlist_code)) + end + stoptiming(visualizers) + return head, true + else + return head, false + end + end + +end + +do + + local hlist_code = nodecodes.hlist + local vlist_code = nodecodes.vlist + local nextnode = nuts.traversers.node + + local last = nil + local used = nil + + local mark = { + "trace:1", "trace:2", "trace:3", + "trace:4", "trace:5", "trace:6", + "trace:7", + } + + local function markfonts(list) + for n, id in nextnode, list do + if id == glyph_code then + local font = getfont(n) + local okay = used[font] + if not okay then + last = last + 1 + okay = mark[last] + used[font] = okay + end + setcolor(n,okay) + elseif id == hlist_code or id == vlist_code then + markfonts(getlist(n)) + end + end + end + + function visualizers.markfonts(list) + last, used = 0, { } + markfonts(type(n) == "number" and getlist(getbox(n)) or n) + end + +end + +statistics.register("visualization time",function() + if enabled then + -- cleanup() -- in case we don't don't do it each time + return formatters["%s seconds"](statistics.elapsedtime(visualizers)) + end +end) + +-- interface + +do + + local implement = interfaces.implement + + implement { + name = "setvisual", + arguments = "string", + actions = visualizers.setvisual + } + + implement { + name = "setvisuals", + arguments = "string", + actions = visualizers.setvisual + } + + implement { + name = "getvisual", + arguments = "string", + actions = { setvisual, context } + } + + implement { + name = "setvisuallayer", + arguments = "string", + actions = visualizers.setlayer + } + + implement { + name = "markvisualfonts", + arguments = "integer", + actions = visualizers.markfonts + } + + implement { + name = "setvisualfont", + arguments = "integer", + actions = visualizers.setfont + } + +end + +-- Here for now: + +do + + local function make(str,forecolor,rulecolor,layer) + if initialize then + initialize() + end + local rule = new_rule(emwidth/fraction,exheight,4*exheight) + setcolor(rule,rulecolor) + settransparency(rule,rulecolor) + local info + if str == "" then + info = new_hlist(rule) + else + local text = hpack_string(str,usedfont) + local list = getlist(text) + setlistcolor(list,textcolor) + setlisttransparency(list,textcolor) + setshift(text,3.5 * exheight) + info = new_hlist(setlink(rule,text)) + end + setattr(info,a_layer,layer) + return info + end + + function visualizers.register(name,textcolor,rulecolor) + if rawget(layers,name) then + -- message + return + end + local cache = caches[name] + local layer = layers[name] + if not textcolor then + textcolor = c_text_d + end + if not rulecolor then + rulecolor = c_origin_d + end + return function(str) + if not str then + str = "" + end + local info = cache[str] + if not info then + info = make(str,textcolor,rulecolor,layer) + cache[str] = info + end + return copy_node(info) + end + end + +end diff --git a/tex/context/base/mkiv/trac-vis.lua b/tex/context/base/mkiv/trac-vis.lua index c676f4dd7..fb5ef98d9 100644 --- a/tex/context/base/mkiv/trac-vis.lua +++ b/tex/context/base/mkiv/trac-vis.lua @@ -28,12 +28,12 @@ local round = math.round -- todo: maybe also xoffset, yoffset of glyph -- todo: inline concat (more efficient) -- todo: tags can also be numbers (just add to hash) +-- todo: make a lmtx variant (a few more efficient fetchers) local nodecodes = nodes.nodecodes local nuts = nodes.nuts local tonut = nuts.tonut -local tonode = nuts.tonode local setboth = nuts.setboth local setlink = nuts.setlink @@ -64,6 +64,7 @@ local getdepth = nuts.getdepth local getshift = nuts.getshift local getexpansion = nuts.getexpansion local getdirection = nuts.getdirection +local getstate = nuts.getstate local isglyph = nuts.isglyph @@ -167,7 +168,7 @@ local modes = { marginkern = 0x100000, mathlistkern = 0x200000, dir = 0x400000, - localpar = 0x800000, + par = 0x800000, } local usedfont, exheight, emwidth @@ -236,7 +237,7 @@ local function initialize() l_space = layers.space l_depth = layers.depth l_dir = layers.dir - l_localpar = layers.localpar + l_par = layers.par -- if not userrule then userrule = nuts.rules.userrule @@ -559,6 +560,8 @@ local kernexpansion do local f_cache = caches["kernexpansion"] + -- in mkiv we actually need to reconstruct but let's not do that now + kernexpansion = function(head,current) local extra = getexpansion(current) if extra ~= 0 then @@ -624,7 +627,7 @@ local whatsit do end -local dir, localpar do +local dir, par do local dircodes = nodes.dircodes local dirvalues = nodes.dirvalues @@ -642,11 +645,11 @@ local dir, localpar do par = "PAR", } - localpar = function(head,current) + par = function(head,current) local what = "par" -- getsubtype(current) local info = d_cache[what] if info then - -- print("hit localpar") + -- print("hit par") else info = sometext(formatters["L:%s"](what),usedfont,nil,c_white) setattr(info,a_layer,l_dir) @@ -927,7 +930,6 @@ end local ruledglue do local gluecodes = nodes.gluecodes - local leadercodes = nodes.gluecodes local userskip_code = gluecodes.userskip local spaceskip_code = gluecodes.spaceskip @@ -936,14 +938,11 @@ local ruledglue do -- local keepskip_code = gluecodes.keepskip or gluecodes.userskip local leftskip_code = gluecodes.leftskip local rightskip_code = gluecodes.rightskip - local parfillskip_code = gluecodes.parfillskip local parfillleftskip_code = gluecodes.parfillleftskip or parfillskip_code local parfillrightskip_code = gluecodes.parfillrightskip or parfillskip_code local indentskip_code = gluecodes.indentskip local correctionskip_code = gluecodes.correctionskip - local cleaders_code = leadercodes.cleaders - local g_cache_v = caches["vglue"] local g_cache_h = caches["hglue"] @@ -967,10 +966,10 @@ local ruledglue do [gluecodes.intermathskip] = "IM", [gluecodes.keepskip or 99] = "KS", [gluecodes.mathskip] = "MT", - [leadercodes.leaders] = "NL", - [leadercodes.cleaders] = "CL", - [leadercodes.xleaders] = "XL", - [leadercodes.gleaders] = "GL", + [gluecodes.leaders] = "NL", + [gluecodes.cleaders] = "CL", + [gluecodes.xleaders] = "XL", + [gluecodes.gleaders] = "GL", -- true = "VS", -- false = "HS", [leftskip_code] = "LS", @@ -978,7 +977,6 @@ local ruledglue do [spaceskip_code] = "SP", [xspaceskip_code] = "XS", [zerospaceskip_code] = "ZS", - [parfillskip_code] = "PR", [parfillleftskip_code] = "PL", [parfillrightskip_code] = "PR", [indentskip_code] = "IN", @@ -999,7 +997,7 @@ 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 == parfillskip_code or subtype == parfillleftskip_code or subtype == parfillrightskip_code or subtype == indentskip_code or subtype == correctionskip_code then + 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 if width > 0 then @@ -1252,7 +1250,7 @@ do local marginkern_code = nodecodes.marginkern local mathlistkern_code = nodecodes.mathlistkern local dir_code = nodecodes.dir - local localpar_code = nodecodes.localpar + local par_code = nodecodes.par local kerncodes = nodes.kerncodes local fontkern_code = kerncodes.fontkern @@ -1289,7 +1287,7 @@ do local trace_space = false local trace_depth = false local trace_dir = false - local trace_localpar = false + local trace_par = false local current = head local previous = nil local attr = unsetvalue @@ -1334,7 +1332,7 @@ do trace_marginkern = false trace_mathlistkern = false trace_dir = false - trace_localpar = false + trace_par = false if id == kern_code then goto kern else @@ -1431,9 +1429,9 @@ do if trace_dir then head, current = dir(head,current) end - elseif id == localpar_code then - if trace_localpar then - head, current = localpar(head,current) + elseif id == par_code then + if trace_par then + head, current = par(head,current) end end goto next diff --git a/tex/context/base/mkiv/trac-vis.mkiv b/tex/context/base/mkiv/trac-vis.mkiv index b261747c1..5357c8414 100644 --- a/tex/context/base/mkiv/trac-vis.mkiv +++ b/tex/context/base/mkiv/trac-vis.mkiv @@ -70,26 +70,18 @@ \unexpanded\def\ruledmbox#1{\ruledhbox{\startimath#1\stopimath}} -\ifcase\contextlmtxmode +\unexpanded\def\sys_ruled_vcenter{\syst_visualizers_vcenter attr \visualattribute \clf_getvisual {simplevbox}} - \unexpanded\def\sys_ruled_vcenter{\syst_visualizers_vcenter attr \visualattribute \clf_getvisual {simplevbox}} +\unexpanded\def\ruledvcenter + {\ruledvbox\bgroup + \dowithnextboxcs\syst_boxes_ruled_vcenter_finish\ruledvbox} - \unexpanded\def\ruledvcenter - {\ruledvbox\bgroup - \dowithnextboxcs\syst_boxes_ruled_vcenter_finish\ruledvbox} +\def\syst_boxes_ruled_vcenter_finish + {\ruledhpack{\normalstartimath\ruledvcenter{\box\nextbox}\normalstopimath}% + \egroup} - \def\syst_boxes_ruled_vcenter_finish - {\ruledhpack{\normalstartimath\ruledvcenter{\box\nextbox}\normalstopimath}% - \egroup} - - \prependtoks \let\ruledvcenter\sys_ruled_vcenter \to \everymath - \prependtoks \let\ruledvcenter\sys_ruled_vcenter \to \everydisplay - -\else - - \unexpanded\def\ruledvcenter{\syst_visualizers_vcenter attr \visualattribute \clf_getvisual {simplevbox}} - -\fi +\prependtoks \let\ruledvcenter\sys_ruled_vcenter \to \everymath +\prependtoks \let\ruledvcenter\sys_ruled_vcenter \to \everydisplay \appendtoks \ifcase\c_syst_visualizers_state\else diff --git a/tex/context/base/mkiv/trac-vis.mkxl b/tex/context/base/mkiv/trac-vis.mkxl new file mode 100644 index 000000000..77df80848 --- /dev/null +++ b/tex/context/base/mkiv/trac-vis.mkxl @@ -0,0 +1,219 @@ +%D \module +%D [ file=trac-vis, % replaces supp-vis plus some s-* modules +%D version=2012.06.23, % 1996.10.21, +%D title=\CONTEXT\ Tracing Macros, +%D subtitle=Visualization, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D The old visual debugger dates from 1996 and started out as joke. In practice +%D it's not used that often although the \type {\ruledhbox} cum suis macros come +%D in handy when writing code. In the process of luafication some additional +%D tracing options were tested, for instance showing font kerns. As part of the +%D \MKIV\ cleanup the decision was made to reimplement, reintegrate and reconsider +%D all these features. The old code is gone and the new code will get extended +%D when needed. We still provide placeholders for some old visualization commands +%D but they might go away. +%D +%D Control over what gets visualized happens with the tracker command: +%D +%D \enabletrackers[visualizers.*] +%D +%D Possible values are: \type {fontkern}, \type {kern}, \type {glue}, \type +%D {penalty}, \type {hbox}, \type {vbox}, \type {all}, \type {reset}, \type +%D {makeup}, \type {whatsit}, \type{glyph}. +%D +%D In due time some special visualzation of math will move here as well. + +\writestatus{loading}{ConTeXt Tracing Macros / Visualization} + +\registerctxluafile{trac-vis}{autosuffix,optimize} + +\unprotect + +\newconstant\c_syst_visualizers_state +\newtoks \t_syst_visualizers_optimize + +% \definesystemattribute[visual][public,global] % already defined + +% no, but can become an option: +% +% \appendtoks +% \c_attr_visual\attributeunsetvalue +% \to \everybeforepagebody + +%D We only provide box visualizers as they can come in handy for testing +%D macros. In due time we will move some of the m-visual code here too. + +\aliased\let\syst_visualizers_hbox \hbox +\aliased\let\syst_visualizers_vbox \vbox +\aliased\let\syst_visualizers_vtop \vtop +\aliased\let\syst_visualizers_vcenter\vcenter +\aliased\let\syst_visualizers_hpack \hpack +\aliased\let\syst_visualizers_vpack \vpack +\aliased\let\syst_visualizers_tpack \tpack + +\permanent\protected\def\ruledhbox {\syst_visualizers_hbox attr \visualattribute \clf_getvisual{simplehbox} } +\permanent\protected\def\ruledhpack {\syst_visualizers_hpack attr \visualattribute \clf_getvisual{simplehbox} } +\permanent\protected\def\ruledvbox {\syst_visualizers_vbox attr \visualattribute \clf_getvisual{simplevbox} } +\permanent\protected\def\ruledvpack {\syst_visualizers_vpack attr \visualattribute \clf_getvisual{simplevbox} } +\permanent\protected\def\ruledvtop {\syst_visualizers_vtop attr \visualattribute \clf_getvisual{simplevtop} } +\permanent\protected\def\ruledtpack {\syst_visualizers_tpack attr \visualattribute \clf_getvisual{simplevtop} } +\permanent\protected\def\ruledvcenter{\syst_visualizers_vcenter attr \visualattribute \clf_getvisual{simplevbox} } +\permanent\protected\def\ruledmbox #1{\ruledhbox{\startimath#1\stopimath}} + +\appendtoks + \ifcase\c_syst_visualizers_state\else + \syst_visualizers_speedup + \fi +\to \everyshipout + +\appendtoks + \glet\syst_visualizers_speedup\relax + \global\t_syst_visualizers_optimize\emptytoks +\to \t_syst_visualizers_optimize + +\def\syst_visualizers_speedup{\the\t_syst_visualizers_optimize} + +\appendtoks +% \enforced\global\protected\edef\ruledhbox {\syst_visualizers_hbox attr \visualattribute \number\clf_getvisual{simplehbox} } +% \enforced\global\protected\edef\ruledhpack {\syst_visualizers_hpack attr \visualattribute \number\clf_getvisual{simplehbox} } +% \enforced\global\protected\edef\ruledvbox {\syst_visualizers_vbox attr \visualattribute \number\clf_getvisual{simplevbox} } +% \enforced\global\protected\edef\ruledvpack {\syst_visualizers_vpack attr \visualattribute \number\clf_getvisual{simplevbox} } +% \enforced\global\protected\edef\ruledvtop {\syst_visualizers_vtop attr \visualattribute \number\clf_getvisual{simplevtop} } +% \enforced\global\protected\edef\ruledtpack {\syst_visualizers_tpack attr \visualattribute \number\clf_getvisual{simplevtop} } +% \enforced\global\protected\edef\ruledvcenter{\syst_visualizers_vcenter attr \visualattribute \number\clf_getvisual{simplevbox} } +\to \t_syst_visualizers_optimize + +\permanent\tolerant\protected\def\showmakeup[#1]% + {\ifarguments + \clf_setvisual{makeup}% + \else + \clf_setvisual{#1}% + \fi} + +\permanent\protected\def\showallmakeup {\clf_setvisual{all}\showstruts} +\permanent\protected\def\showboxes {\clf_setvisual{boxes}} +\permanent\protected\def\showglyphs {\clf_setvisual{glyph}} +\permanent\protected\def\showfontkerns {\clf_setvisual{fontkern}} +\permanent\protected\def\showfontitalics {\clf_setvisual{italic}} +\permanent\protected\def\showglyphdata {\showglyphs\showfontkerns\showfontitalics} +\permanent\protected\def\showfontexpansion{\clf_setvisual{expansion}} + +\permanent\tolerant\protected\def\setvisualizerfont[#1]% somename at 4pt + {\begingroup + \iftok{#1}\emptytoks + \definedfont[Mono at 4pt]% + \else + \definedfont[#1]% + \fi + \clf_setvisualfont\fontid\font + \endgroup} + +\permanent\protected\def\resetvisualizers + {\c_attr_visual\attributeunsetvalue} + +%D New (these might also be a visualizers): + +% \definecolor[f:r:t][a=1,t=.25,r=1] +% \definecolor[f:g:t][a=1,t=.25,g=1] +% \definecolor[f:b:t][a=1,t=.25,b=1] +% \definecolor[f:c:t][a=1,t=.25,c=1] +% \definecolor[f:m:t][a=1,t=.25,m=1] +% \definecolor[f:y:t][a=1,t=.25,y=1] +% \definecolor[f:k:t][a=1,t=.25,s=0] + +\permanent\protected\def\filledhboxr{\node_backgrounds_boxes_add\hbox[f:r:t]} +\permanent\protected\def\filledhboxg{\node_backgrounds_boxes_add\hbox[f:g:t]} +\permanent\protected\def\filledhboxb{\node_backgrounds_boxes_add\hbox[f:b:t]} +\permanent\protected\def\filledhboxc{\node_backgrounds_boxes_add\hbox[f:c:t]} +\permanent\protected\def\filledhboxm{\node_backgrounds_boxes_add\hbox[f:m:t]} +\permanent\protected\def\filledhboxy{\node_backgrounds_boxes_add\hbox[f:y:t]} +\permanent\protected\def\filledhboxk{\node_backgrounds_boxes_add\hbox[f:k:t]} + +%D Overload: + +\protected\def\spac_struts_vide_hbox + {\hbox attr \visualattribute \clf_getvisual{strut} } + +\appendtoks + \normalexpanded{\protected\xdef\spac_struts_vide_hbox\expandafter{\spac_struts_vide_hbox}}% +\to \t_syst_visualizers_optimize + +%D For manuals: + +\permanent\protected\def\markfonts#1% + {\dontleavehmode + \begingroup + \setbox\scratchbox\hbox{\getbuffer}% + \clf_markvisualfonts\scratchbox + \unhbox\scratchbox + \endgroup} + +% As demo: +% +% \startbuffer +% \hbox {\raise1cm\hbox{raised} normal \lower1cm\hbox{lowered}} +% \blank +% \moveleft1cm\hbox{left} +% \blank +% \hbox{normal} +% \blank +% \moveright1cm\hbox{right} +% \blank +% \stopbuffer +% +% \start \showboxes \getbuffer \stop \blank[4*big] \getbuffer +% +% \startbuffer +% \moveleft1cm\vbox{left} +% \blank +% \vbox{normal} +% \blank +% \moveright1cm\vbox{right} +% \blank +% \stopbuffer +% +% \start \showboxes \getbuffer \stop \blank[4*big] \getbuffer + +%D We keep this one: + +\permanent\protected\def\dontinterfere + {\reseteverypar + \parindent\zeropoint + \parskip \zeropoint + \leftskip \zeropoint + \rightskip\zeropoint + \relax} + +%D We keep these for a while: + +\let\ruledhss \hss +\let\ruledhfil \hfil +\let\ruledhfill \hfill +\let\ruledhfilll \hfilll +\let\ruledhfilneg \hfilneg +\let\ruledhfillneg \hfillneg +\let\ruledhfilllneg \hfilllneg +\let\ruledvss \vss +\let\ruledvfil \vfil +\let\ruledvfill \vfill +\let\ruledvfilll \vfilll +\let\ruledvfilneg \vfilneg +\let\ruledvfillneg \vfillneg +\let\ruledvfilllneg \vfilllneg +\let\ruledhskip \hskip +\let\ruledvskip \vskip +\let\ruledkern \kern +\let\ruledhglue \hglue +\let\ruledvglue \vglue +\let\ruledmkern \mkern +\let\ruledmskip \mskip +\let\ruledpenalty \penalty + +\protect \endinput diff --git a/tex/context/base/mkiv/type-ini.mklx b/tex/context/base/mkiv/type-ini.mklx index 1cb9bc2e5..f6dd7780d 100644 --- a/tex/context/base/mkiv/type-ini.mklx +++ b/tex/context/base/mkiv/type-ini.mklx @@ -27,8 +27,6 @@ \unprotect -\definesystemvariable {ts} % TypeScript / for the moment we keep this one - \newcount \c_font_typescripts_n_of_preloaded \newconditional\c_font_typescripts_quit \newtoks \c_font_typescripts_document @@ -69,7 +67,7 @@ \installmacrostack\m_font_typescripts_two \installmacrostack\m_font_typescripts_three -\let\t_font_typescripts\relax % uses as synonym +\mutable\let\t_font_typescripts\relax % uses as synonym \installcorenamespace{typescriptcache} \installcorenamespace{typescriptfiles} @@ -97,29 +95,41 @@ %D that one is also grouped and loading bodyfonts grouped is a real bad idea. %D Ignoring all spaces is also not a solution. So, our verdict is: no catch. -\unexpanded\def\starttypescriptcollection +\permanent\protected\def\starttypescriptcollection % redefined on the fly {\dosingleempty\font_typescripts_collection_start} \def\font_typescripts_collection_start[#tag]% {} -\let\stoptypescriptcollection\relax +\permanent\let\stoptypescriptcollection\relax + +\permanent\protected\def\usetypescriptfile[#filename]% + {\iftok{#filename}{\v!reset}% + \let\typescriptfiles\empty + \else + \splitfilename{#filename}% + \addtocommalist\splitoffbase\typescriptfiles + \fi} + +\installmacrostack\stoptypescript -\unexpanded\def\usetypescriptfile[#filename]% - {\doifelse{#filename}\v!reset - {\let\typescriptfiles\empty} - {\splitfilename{#filename}% - \addtocommalist\splitoffbase\typescriptfiles}} +% \permanent\protected\def\usetypescript {\dotripleempty\font_typescripts_use_one} +% \permanent\protected\def\usetypescriptexact{\dotripleempty\font_typescripts_use_two} +% +% \def\font_typescripts_use_one{\let\typescriptmethod\plusone\font_typescripts_use} +% \def\font_typescripts_use_two{\let\typescriptmethod\plustwo\font_typescripts_use} +% +% \protected\def\font_typescripts_use[#one][#two][#three]% -\unexpanded\def\usetypescript {\dotripleempty\font_typescripts_use_one} -\unexpanded\def\usetypescriptexact{\dotripleempty\font_typescripts_use_two} +% todo: just pass the method ... also further on then .. first test \def\font_typescripts_use_one{\let\typescriptmethod\plusone\font_typescripts_use} \def\font_typescripts_use_two{\let\typescriptmethod\plustwo\font_typescripts_use} -\installmacrostack\stoptypescript +\permanent\protected\def\usetypescript {\font_typescripts_use_one} +\permanent\protected\def\usetypescriptexact{\font_typescripts_use_two} -\unexpanded\def\font_typescripts_use[#one][#two][#three]% +\tolerant\protected\def\font_typescripts_use[#one]#spacer[#two]#spacer[#three]% {\push_macro_m_font_typescripts_one \push_macro_m_font_typescripts_two \push_macro_m_font_typescripts_three @@ -159,20 +169,20 @@ \let\font_typescripts_use_inline\font_typescripts_use_display -\unexpanded\def\preloadtypescripts +\permanent\protected\def\preloadtypescripts {\ifproductionrun\settrue\c_font_typescripts_preload\fi} \prependtoks \preloadtypescripts \to \everyjob -\unexpanded\def\loadtypescriptfile[#1]% +\permanent\protected\def\loadtypescriptfile[#1]% {\push_macro_typescriptstate \let\typescriptstate\plustwo % assumes 2 at the outer level \clf_loadtypescriptfile{#1}% \pop_macro_typescriptstate} -\unexpanded\def\loadfoundtypescriptfile#1#2% name foundname / not a user command +\permanent\protected\def\loadfoundtypescriptfile#1#2% name foundname / not a user command {\startreadingfile \unprotect \pushendofline @@ -181,17 +191,17 @@ \protect \stopreadingfile} -\unexpanded\def\quittypescriptscanning +\permanent\protected\def\quittypescriptscanning {\settrue\c_font_typescripts_quit} % public -\def\font_typescripts_start_store#definitions\stoptypescript +\permanent\protected\def\font_typescripts_start_store#definitions\stoptypescript {\global\advance\c_font_typescripts_n_of_preloaded\plusone \expandafter\normalgdef\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname {\starttypescript#definitions\stoptypescript}% \gtoksapp\t_font_typescripts\expandafter {\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}} -\def\font_typescripts_collection_start_store#definitions\stoptypescriptcollection +\permanent\protected\def\font_typescripts_collection_start_store#definitions\stoptypescriptcollection {\global\advance\c_font_typescripts_n_of_preloaded\plusone \expandafter\normalgdef\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname {\starttypescriptcollection#definitions\stoptypescriptcollection}% @@ -215,6 +225,7 @@ \def\font_typescript_process_typescript_file_and_store {\expandafter\let\expandafter\t_font_typescripts\csname\??typescriptfiles\currenttypefile\endcsname +% {\aliased\expandafter\let\expandafter\t_font_typescripts\csname\??typescriptfiles\currenttypefile\endcsname \ifx\t_font_typescripts\relax \font_typescript_process_typescript_store_indeed \fi @@ -223,8 +234,8 @@ \def\font_typescript_process_typescript_store_indeed {\newtoks\t_font_typescripts % is \relaxed elsewhere \begingroup - \let\starttypescript \font_typescripts_start_store - \let\starttypescriptcollection\font_typescripts_collection_start_store + \enforced\let\starttypescript \font_typescripts_start_store + \enforced\let\starttypescriptcollection\font_typescripts_collection_start_store \font_typescript_process_typescript_file \endgroup \expandafter\let\csname\??typescriptfiles\currenttypefile\endcsname\t_font_typescripts} @@ -232,10 +243,7 @@ \def\font_typescript_process_typescript_file {\clf_doprocesstypescriptfile{\currenttypefile}} -\unexpanded\def\usetypescriptonce - {\dotripleempty\font_typescripts_use_once} - -\def\font_typescripts_use_once[#one][#two][#three]% +\permanent\tolerant\protected\def\usetypescriptonce[#one]#spacer[#two]#spacer[#three]% {\ifcsname\??typescriptonce#one:#two:#three\endcsname \writestatus\m!fonts{once (#one) (#two) (#three)}% \else @@ -245,13 +253,10 @@ % \definetypescriptsynonym[lbr][cmr] -\unexpanded\def\definetypescriptsynonym - {\dodoubleempty\font_typescripts_synonym_define} - -\def\font_typescripts_synonym_define[#name][#synonym]% +\permanent\tolerant\protected\def\definetypescriptsynonym[#name]#spacer[#synonym]% {\ifsecondargument\setevalue{\??typescriptsynonyms#name}{#synonym}\fi} -\def\truetypescript#name% recursive so no \lastnamedcs +\permanent\def\truetypescript#name% recursive so no \lastnamedcs {\ifcsname\??typescriptsynonyms#name\endcsname %\expandafter\truetypescript\csname\??typescriptsynonyms#name\endcsname \expandafter\truetypescript\lastnamedcs @@ -269,7 +274,7 @@ \settrue\c_font_typescripts_first_pass \to \everyjob -\unexpanded\def\starttypescript +\permanent\protected\def\starttypescript {\ifcase\typescriptstate % 0 = skip \expandafter\font_typescripts_start_gobble @@ -338,7 +343,7 @@ \def\font_typescripts_start_process_indeed {\push_macro_fontclass} -\unexpanded\def\stoptypescript +\permanent\protected\def\stoptypescript {\pop_macro_fontclass} \def\font_typescripts_check#asked#target#followup[#value]% script use value next @@ -366,23 +371,15 @@ \expandafter\font_typescripts_start_gobble \fi} -\def\extendtypescriptmatch +\permanent\protected\def\extendtypescriptmatch {\edef\m_font_typescripts_match{\m_font_typescripts_match\space[\m_font_typescripts_check]}} %D Map files will go away in \LUATEX, but till that happens we use stripped down %D support for loading them. -\unexpanded\def\loadmapfile{\dosingleempty\font_map_load_file} -\unexpanded\def\loadmapline{\dodoubleempty\font_map_load_line} - -\def\font_map_load_file[#filename]% - {\clf_loadmapfile{#filename}} - -\def\font_map_load_line[#kind][#data]% - {\clf_loadmapline{#kind}{#data}} - -\unexpanded\def\forgetmapfiles - {\clf_resetmapfiles} +\permanent\tolerant\protected\def\loadmapfile [#filename]{\clf_loadmapfile{#filename}} +\permanent\tolerant\protected\def\loadmapline [#kind]#spacer[#data]{\clf_loadmapline{#kind}{#data}} +\permanent \protected\def\forgetmapfiles {\clf_resetmapfiles} % \prependtoks % \loadmapfile[mkiv-base.map]% can't we preload this one? @@ -398,10 +395,13 @@ % \setupfontsynonym [\typescriptprefix\typescriptone] [handling=\typescriptthree] % \stoptypescript -\unexpanded\def\definetypescriptprefix - {\dodoubleargument\font_typescripts_define_prefix} +% \protected\def\definetypescriptprefix +% {\dodoubleargument\font_typescripts_define_prefix} +% +% \def\font_typescripts_define_prefix[#name][#prefix]% +% {\setgvalue{\??typescriptprefix#name}{#prefix}} % made global -\def\font_typescripts_define_prefix[#name][#prefix]% +\permanent\tolerant\protected\def\definetypescriptprefix[#name]#spacer[#prefix]% {\setgvalue{\??typescriptprefix#name}{#prefix}} % made global \def\typescriptprefix#name% @@ -417,9 +417,6 @@ % \definetypeface [joke] [rm] [serif] [lucida] [size] [settings] % \definetypeface [joke] [specification] -\unexpanded\def\definetypeface - {\dosixtupleargument\font_typefaces_define} - \appendtoks \font_helpers_reset_fontclass_math_families\fontclass \to \everybeforedefinetypeface @@ -428,7 +425,7 @@ \settrue\autotypescripts -\unexpanded\def\trycurrentfontclass#typeface% +\protected\def\trycurrentfontclass#typeface% {\ifconditional\autotypescripts \usetypescript[#typeface]% \ifcsname\??fontclassyes#typeface\endcsname @@ -451,16 +448,25 @@ %D Now we define: -\def\font_typefaces_define - {\iffifthargument - \expandafter\font_typefaces_define_a - \orelse\iffourthargument - \expandafter\font_typefaces_define_b - \orelse\ifthirdargument - \expandafter\font_typefaces_define_c - \else +\permanent\tolerant\protected\def\definetypeface[#name]#spacer[#style]#spacer[#fontshape]#spacer[#fontname]#spacer[#fontsize]#spacer[#settings]% + {\ifarguments + \expandafter\font_typefaces_define_e + \or \expandafter\font_typefaces_define_d - \fi} + \or + \expandafter\font_typefaces_define_d + \or + \expandafter\font_typefaces_define_c + \or + \expandafter\font_typefaces_define_b + \or + \expandafter\font_typefaces_define_a + \or + \expandafter\font_typefaces_define_a + \fi[#name][#style][#fontshape][#fontname][#fontsize][#settings]} + +\def\font_typefaces_define_e[#name][#style][#fontshape][#fontname][#fontsize][#settings]% + {} \def\font_typefaces_define_a[#name][#style][#fontshape][#fontname][#fontsize][#settings]% {\iftracetypescripts\writestatus\m!fonts{define: [#name] [#style] [#fontshape] [#fontname]}\fi @@ -477,13 +483,13 @@ \font_typescripts_use_one[#fontshape][#fontsize][\s!size]% \font_typefaces_defining_stop} -\def\font_typefaces_define_b[#name][#style][#fontshape][#fontname][#dummya][#dummyb]% - {\font_typefaces_define_a[#name][#style][#fontshape][#fontname][\s!default][#dummyb]} +\def\font_typefaces_define_b[#name][#style][#fontshape][#fontname][#discard][#discard]% + {\font_typefaces_define_a[#name][#style][#fontshape][#fontname][\s!default][#discard]} -\def\font_typefaces_define_c[#name][#style][#dummya][#dummyb][#dummyc][#dummyd]% +\def\font_typefaces_define_c[#name][#style][#discard][#discard][#discard][#discard]% {\font_typefaces_define_indeed[#name][#style]} -\def\font_typefaces_define_d[#name][#specification][#dummya][#dummyb][#dummyc][#dummyd]% use definitions in lfg file +\def\font_typefaces_define_d[#name][#specification][#discard][#discard][#discard][#discard]% use definitions in lfg file {\clf_definetypeface{#name}{#specification}} \def\font_typefaces_define_indeed[#name][#style]% saveguard against redefinition @@ -496,21 +502,62 @@ \setugvalue{#name}{\switchtotypeface[#name][#style]}% \fi}} +% needs testing first ... let'd do it stepwise + +% \permanent\tolerant\protected\def\definetypeface[#name]#spacer[#style]#spacer[#fontshape]#spacer[#fontname]#spacer[#fontsize]#spacer[#settings]% +% {\ifarguments +% \or +% \clf_definetypeface{#name}{#specification}% +% \or +% \clf_definetypeface{#name}{#specification}% +% \or +% \font_typefaces_define_simplex[#name][#style]% +% \or +% \font_typefaces_define_complex[#name][#style][#fontshape][#fontname][\s!default][#discard]% +% \else +% \font_typefaces_define_complex[#name][#style][#fontshape][#fontname][#fontsize][#settings]% +% \fi} +% +% \def\font_typefaces_define_complex[#name][#style][#fontshape][#fontname][#fontsize][#settings]% +% {\iftracetypescripts\writestatus\m!fonts{define: [#name] [#style] [#fontshape] [#fontname]}\fi +% \font_typefaces_define_simplex[#name][#style]% +% \font_typefaces_defining_start{#name}{#style}{#settings}% +% \font_typescripts_use_one[#fontshape][#fontname][\s!name]% [\s!name,\s!default]% +% \iftypescriptfound +% % we're okay +% \orelse\ifconditional\autotypescripts +% \iftracetypescripts\writestatus\m!fonts{auto load typescript file 2: [#fontname]}\fi +% \usetypescriptfile[#fontname]% +% \font_typescripts_use_one[#fontshape][#fontname][\s!name]% [\s!name,\s!default]% +% \fi +% \font_typescripts_use_one[#fontshape][#fontsize][\s!size]% +% \font_typefaces_defining_stop} +% +% \def\font_typefaces_define_simplex[#name][#style]% saveguard against redefinition +% {\doifsomething{#name} +% {\ifcsname\??typescriptdefaultstyles#name\endcsname \else +% \registerfontclass{#name}% +% \setxvalue{\??typescriptdefaultstyles#name}{#style}% +% \fi +% \ifcsname#name\endcsname \else +% \setugvalue{#name}{\switchtotypeface[#name][#style]}% +% \fi}} + \def\font_typefaces_defining_start#name#style#settings% - {\let\@@tsrscale \!!plusone % as we push/pop - \let\@@tsfeatures \empty - \let\@@tsfallbacks \empty - \let\@@tsgoodies \empty - \let\@@tsdirection \empty - \let\@@tsdesignsize\empty - \geteparameters[\??ts][#settings]% todo raw + {\let\m_ts_rscale \!!plusone % as we push/pop + \let\m_ts_features \empty + \let\m_ts_fallbacks \empty + \let\m_ts_goodies \empty + \let\m_ts_direction \empty + \let\m_ts_designsize\empty + \geteparameters[m_ts_][#settings]% todo raw ... no need for key interpretation \push_macro_fontclass \push_macro_fontclassstyle \setcurrentfontclass{#name}% - \savefontclassparameters{#style}\@@tsrscale\@@tsfeatures\@@tsfallbacks\@@tsgoodies\@@tsdesignsize\@@tsdirection + \savefontclassparameters{#style}\m_ts_rscale\m_ts_features\m_ts_fallbacks\m_ts_goodies\m_ts_designsize\m_ts_direction \the\everybeforedefinetypeface} -\def\tsvar#key#default% undocumented and unofficial +\permanent\def\tsvar#key#default% undocumented and unofficial {\expandafter\ifempty\csname\??ts#key\endcsname #default% \else @@ -528,39 +575,77 @@ \font_typescripts_use_one[#fontshape][#fontsize][\s!size]% \font_typefaces_defining_stop} -\unexpanded\def\setuptypeface% [class] [settings] - {\dodoubleempty\font_typefaces_setup} - -\unexpanded\def\switchtotypeface% [class] [settings] - {\dodoubleempty\font_typefaces_switch} +% \protected\def\setuptypeface% [class] [settings] +% {\dodoubleempty\font_typefaces_setup} +% +% \protected\def\switchtotypeface% [class] [settings] +% {\dodoubleempty\font_typefaces_switch} +% +% \def\font_typefaces_setup[#class][#settings]% +% {\setcurrentfontclass{#class}% +% \let\globalfontclass\fontclass +% \ifsecondargument +% \setupbodyfont[#settings]% +% \orelse\ifempty\fontclass +% \setupbodyfont[\s!rm]% +% \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname +% %\setupbodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]% +% \expandafter\setupbodyfont\expandafter[\lastnamedcs]% +% \else +% \setupbodyfont[\s!rm]% +% \fi +% \ifmmode\mr\else\tf\fi} % needed ? +% +% \def\font_typefaces_switch[#class]#spacer[#settings]% +% {\setcurrentfontclass{#class}% +% \let\globalfontclass\globalfontclass +% \ifsecondargument +% \switchtobodyfont[#settings]% +% \orelse\ifempty\fontclass +% \switchtobodyfont[\s!rm]% +% \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname +% %\switchtobodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]% +% \expandafter\switchtobodyfont\expandafter[\lastnamedcs]% +% \else +% \switchtobodyfont[\s!rm]% +% \fi +% \ifmmode\mr\else\tf\fi} % needed ? -\def\font_typefaces_setup[#class][#settings]% - {\setcurrentfontclass{#class}% - \let\globalfontclass\fontclass - \ifsecondargument +\permanent\tolerant\protected\def\setuptypeface[#class]#spacer[#settings]% + {\ifarguments + \or + \setcurrentfontclass{#class}% + \let\globalfontclass\fontclass + \ifempty\fontclass + \setupbodyfont[\s!rm]% + \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname + \expandafter\setupbodyfont\expandafter[\lastnamedcs]% + \else + \setupbodyfont[\s!rm]% + \fi + \or + \setcurrentfontclass{#class}% + \let\globalfontclass\fontclass \setupbodyfont[#settings]% - \orelse\ifempty\fontclass - \setupbodyfont[\s!rm]% - \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname - %\setupbodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]% - \expandafter\setupbodyfont\expandafter[\lastnamedcs]% - \else - \setupbodyfont[\s!rm]% \fi \ifmmode\mr\else\tf\fi} % needed ? -\def\font_typefaces_switch[#class][#settings]% - {\setcurrentfontclass{#class}% - \let\globalfontclass\globalfontclass - \ifsecondargument - \switchtobodyfont[#settings]% - \orelse\ifempty\fontclass - \switchtobodyfont[\s!rm]% - \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname - %\switchtobodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]% - \expandafter\switchtobodyfont\expandafter[\lastnamedcs]% - \else - \switchtobodyfont[\s!rm]% +\permanent\tolerant\protected\def\switchtotypeface[#class]#spacer[#settings]% + {\ifarguments + \or + \setcurrentfontclass{#class}% + \let\globalfontclass\globalfontclass + \ifempty\fontclass + \switchtobodyfont[\s!rm]% + \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname + \expandafter\switchtobodyfont\expandafter[\lastnamedcs]% + \else + \switchtobodyfont[\s!rm]% + \fi + \or + \setcurrentfontclass{#class}% + \let\globalfontclass\globalfontclass + \switchtobodyfont[#settings]% \fi \ifmmode\mr\else\tf\fi} % needed ? @@ -573,16 +658,14 @@ %D \inherittypeface[palatino] % == [rm,ss,tt,mm] %D \stoptyping -\unexpanded\def\inherittypeface - {\dotripleempty\font_typescripts_inherit_indeed} - -\def\font_typescripts_inherit_indeed[#name][#styles][#parentclass]% - {\doifelsenothing{#styles} - {\font_typescripts_inherit_indeed[#name][\s!rm,\s!ss,\s!tt,\s!mm][\fontclass]} - {\doifnot{#name}{#parentclass} - {\glet\font_typescripts_inherit_check\font_typescripts_inherit_check_indeed - \def\font_typescripts_inherit_check_step#style{\setevalue{\??typescriptinheritances#name:#style}{#parentclass}}% - \processcommalist[#styles]\font_typescripts_inherit_check_step}}} +\permanent\tolerant\protected\def\inherittypeface[#name]#spacer[#styles]#spacer[#parentclass]% + {\iftok{#styles}\emptytoks + \font_typescripts_inherit_indeed[#name][\s!rm,\s!ss,\s!tt,\s!mm][\fontclass]% + \orelse\iftok{#name}{#parentclass}\else + \glet\font_typescripts_inherit_check\font_typescripts_inherit_check_indeed + \def\font_typescripts_inherit_check_step#style{\setevalue{\??typescriptinheritances#name:#style}{#parentclass}}% + \processcommalist[#styles]\font_typescripts_inherit_check_step + \fi} \let\font_typescripts_inherit_check_step\relax @@ -612,7 +695,7 @@ \expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!tt \s!Mono \else \s!Serif \fi\fi\fi} -\unexpanded\def\font_helpers_set_fontstyle_of_fontclass +\protected\def\font_helpers_set_fontstyle_of_fontclass {\ifempty\fontclass \let\fontstyle\s!rm \orelse\ifcsname\??typescriptdefaultstyles\fontclass\endcsname diff --git a/tex/context/base/mkiv/typo-bld.lua b/tex/context/base/mkiv/typo-bld.lua index 6874d385a..269386e6c 100644 --- a/tex/context/base/mkiv/typo-bld.lua +++ b/tex/context/base/mkiv/typo-bld.lua @@ -242,31 +242,65 @@ end -- this will be split into contribute_filter for these 4 so at some point -- the check can go away -function builders.buildpage_filter(groupcode) - -- the next check saves 1% runtime on 1000 tufte pages - local head = texlists.contrib_head - local done = false - if head then - -- called quite often ... maybe time to remove timing - starttiming(builders) - if trace_page_builder then - report(groupcode,head) +if CONTEXTLMTXMODE > 0 then + + -- Todo: contrib_head can be any head (kind of) not per se the page one so maybe I will + -- intercept that in the engine with page_contribute_head or so. + + function builders.buildpage_filter(groupcode) + local head = texlists.contribute_head + if head then + local done = false + -- called quite often ... maybe time to remove timing + starttiming(builders) + if trace_page_builder then + report(groupcode,head) + end + head, done = pageactions(head,groupcode) + stoptiming(builders) + -- -- doesn't work here (not passed on?) + -- texset("pagegoal,texget("vsize") - texgetdimen("d_page_floats_inserted_top") - texgetdimen("d_page_floats_inserted_bottom") + texlists.contribute_head = head or nil -- needs checking + -- tex.setlist("contribute_head",head,head and nodes.tail(head)) + return done and head or true -- no return value needed + else + -- happens quite often + if trace_page_builder then + report(groupcode) + end + -- return nil, false -- no return value needed + return nil end - head, done = pageactions(head,groupcode) - stoptiming(builders) - -- -- doesn't work here (not passed on?) - -- texset("pagegoal,texget("vsize") - texgetdimen("d_page_floats_inserted_top") - texgetdimen("d_page_floats_inserted_bottom") - texlists.contrib_head = head or nil -- needs checking - -- tex.setlist("contrib_head",head,head and nodes.tail(head)) - return done and head or true -- no return value needed - else - -- happens quite often - if trace_page_builder then - report(groupcode) + end + +else + + function builders.buildpage_filter(groupcode) + local head = texlists.contrib_head + if head then + local done = false + -- called quite often ... maybe time to remove timing + starttiming(builders) + if trace_page_builder then + report(groupcode,head) + end + head, done = pageactions(head,groupcode) + stoptiming(builders) + -- -- doesn't work here (not passed on?) + -- texset("pagegoal,texget("vsize") - texgetdimen("d_page_floats_inserted_top") - texgetdimen("d_page_floats_inserted_bottom") + texlists.contrib_head = head or nil -- needs checking + -- tex.setlist("contrib_head",head,head and nodes.tail(head)) + return done and head or true -- no return value needed + else + -- happens quite often + if trace_page_builder then + report(groupcode) + end + -- return nil, false -- no return value needed + return nil end --- return nil, false -- no return value needed - return nil end + end registercallback('vpack_filter', builders.vpack_filter, "vertical spacing etc") diff --git a/tex/context/base/mkiv/typo-brk.lua b/tex/context/base/mkiv/typo-brk.lua index d670c5319..89eb7e52d 100644 --- a/tex/context/base/mkiv/typo-brk.lua +++ b/tex/context/base/mkiv/typo-brk.lua @@ -33,7 +33,7 @@ local getid = nuts.getid ----- getattr = nuts.getattr local getattrlist = nuts.getattrlist local takeattr = nuts.takeattr -local getlang = nuts.getlang +local getlanguage = nuts.getlanguage local isglyph = nuts.isglyph local setattr = nuts.setattr @@ -168,7 +168,7 @@ methods[2] = function(head,start) -- ( => (- head, start, replace = remove_node(head,start) local post = copy_node(replace) local hyphen = copy_node(post) - setchar(hyphen,languages.prehyphenchar(getlang(post))) + setchar(hyphen,languages.prehyphenchar(getlanguage(post))) setlink(post,hyphen) head, start = insert_node_before(head,start,new_disc(nil,post,replace)) setattrlist(start,replace) @@ -184,7 +184,7 @@ methods[3] = function(head,start) -- ) => -) head, start, replace = remove_node(head,start) local pre = copy_node(replace) local hyphen = copy_node(pre) - setchar(hyphen,languages.prehyphenchar(getlang(pre))) + setchar(hyphen,languages.prehyphenchar(getlanguage(pre))) setlink(hyphen,pre) head, start = insert_node_before(head,start,new_disc(hyphen,nil,replace)) -- so not pre ! setattrlist(start,tmp) @@ -264,7 +264,7 @@ function breakpoints.handler(head) -- setattr(current,a_breakpoints,unsetvalue) -- should not be needed -- for now we collect but when found ok we can move the handler here -- although it saves nothing in terms of performance - local lang = getlang(current) + local lang = getlanguage(current) local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[languages.numbers[lang]] or cmap[""]) if smap then local skip = smap.skip @@ -322,7 +322,7 @@ function breakpoints.handler(head) local cmap = data[3] local smap = data[4] -- we do a sanity check for language - -- local lang = getlang(start) + -- local lang = getlanguage(start) -- local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[numbers[lang]] or cmap[""]) -- if smap then local nleft = smap.nleft diff --git a/tex/context/base/mkiv/typo-chr.lua b/tex/context/base/mkiv/typo-chr.lua index 7a0f1fd75..bb3883b33 100644 --- a/tex/context/base/mkiv/typo-chr.lua +++ b/tex/context/base/mkiv/typo-chr.lua @@ -91,7 +91,7 @@ local boundarycodes = nodes.boundarycodes local subtypes = nodes.subtypes local glyph_code = nodecodes.glyph -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local boundary_code = nodecodes.boundary local wordboundary_code = boundarycodes.word @@ -175,7 +175,7 @@ local function pickup(head,tail,str) while true do local prev = first.prev if prev and prev[a_marked] == attr then - if prev.id == localpar_code then -- and start_of_par(prev) + if prev.id == par_code then -- and start_of_par(prev) break else first = prev diff --git a/tex/context/base/mkiv/typo-dha.lua b/tex/context/base/mkiv/typo-dha.lua index 7be74caa1..ac72ae394 100644 --- a/tex/context/base/mkiv/typo-dha.lua +++ b/tex/context/base/mkiv/typo-dha.lua @@ -78,7 +78,7 @@ local math_code = nodecodes.math local kern_code = nodecodes.kern local glue_code = nodecodes.glue local dir_code = nodecodes.dir -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local dirvalues = nodes.dirvalues local lefttoright_code = dirvalues.lefttoright @@ -332,7 +332,7 @@ local function process(start) end textdir = autodir setprop(current,"direction",true) - elseif id == localpar_code and start_of_par(current) then + elseif id == par_code and start_of_par(current) then local direction = getdirection(current) if direction == righttoleft_code then autodir = -1 diff --git a/tex/context/base/mkiv/typo-dir.mkxl b/tex/context/base/mkiv/typo-dir.mkxl index 577434e56..e9c7e47d6 100644 --- a/tex/context/base/mkiv/typo-dir.mkxl +++ b/tex/context/base/mkiv/typo-dir.mkxl @@ -33,18 +33,18 @@ \installsimplecommandhandler \??directions {directions} \??directions % no \define... yet -\edef\lefttorightmark{\normalUchar"200E} \let\lrm\lefttorightmark -\edef\righttoleftmark{\normalUchar"200F} \let\rlm\righttoleftmark +\permanent\edef\lefttorightmark{\normalUchar"200E} \let\lrm\lefttorightmark % expandable +\permanent\edef\righttoleftmark{\normalUchar"200F} \let\rlm\righttoleftmark % expandable -\unexpanded\def\setdirection[#1]% todo: symbolic names +\permanent\protected\def\setdirection[#1]% todo: symbolic names {\clf_setdirection#1\relax} -% \unexpanded\def\resetdirection +% \protected\def\resetdirection % {\clf_setdirection\zerocount} % % is in fact: -\unexpanded\def\resetdirection +\protected\def\resetdirection {\c_attr_directions\attributeunsetvalue} \newconstant\directionsbidimode % this one might become pivate @@ -100,16 +100,16 @@ \c!break=\v!both, % experimental value, maybe \v!no will be default (bad name too) \c!fences=\v!yes] -\unexpanded\edef\bidilre{\normalUchar"202A} -\unexpanded\edef\bidirle{\normalUchar"202B} -\unexpanded\edef\bidipop{\normalUchar"202C} -\unexpanded\edef\bidilro{\normalUchar"202D} -\unexpanded\edef\bidirlo{\normalUchar"202E} +\permanent\protected\edef\bidilre{\normalUchar"202A} +\permanent\protected\edef\bidirle{\normalUchar"202B} +\permanent\protected\edef\bidipop{\normalUchar"202C} +\permanent\protected\edef\bidilro{\normalUchar"202D} +\permanent\protected\edef\bidirlo{\normalUchar"202E} -\unexpanded\def\dirlre{\ifcase\directionsbidimode\or\bidilre\or\textdirection\directionlefttoright\fi} -\unexpanded\def\dirrle{\ifcase\directionsbidimode\or\bidirle\or\textdirection\directionrighttoleft\fi} -\unexpanded\def\dirlro{\ifcase\directionsbidimode\or\bidilro\or\setdirection[3]\fi} -\unexpanded\def\dirrlo{\ifcase\directionsbidimode\or\bidirlo\or\setdirection[4]\fi} +\permanent\protected\def\dirlre{\ifcase\directionsbidimode\or\bidilre\or\textdirection\directionlefttoright\fi} +\permanent\protected\def\dirrle{\ifcase\directionsbidimode\or\bidirle\or\textdirection\directionrighttoleft\fi} +\permanent\protected\def\dirlro{\ifcase\directionsbidimode\or\bidilro\or\setdirection[3]\fi} +\permanent\protected\def\dirrlo{\ifcase\directionsbidimode\or\bidirlo\or\setdirection[4]\fi} % for the moment: \setdirection[\plusone] @@ -143,7 +143,7 @@ % end % \stopluacode % -% \unexpanded\def\biditest#1#2#3% font text raw +% \protected\def\biditest#1#2#3% font text raw % {\dontleavehmode\hbox % {\framed[offset=overlay]{\tttf#2}\quad % \enabletrackers[typesetters.directions]% diff --git a/tex/context/base/mkiv/typo-drp.lua b/tex/context/base/mkiv/typo-drp.lua index ad4a80a57..12864e52d 100644 --- a/tex/context/base/mkiv/typo-drp.lua +++ b/tex/context/base/mkiv/typo-drp.lua @@ -82,7 +82,7 @@ local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist local glue_code = nodecodes.glue local kern_code = nodecodes.kern -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local actions = { } initials.actions = actions @@ -270,7 +270,7 @@ actions[v_default] = function(head,setting) end -- We pack so that successive handling cannot touch the dropped cap. Packaging -- in a hlist is also needed because we cannot locally adapt e.g. parindent (not - -- yet stored in with localpar). + -- yet stored in with par). local prev = getprev(first) local next = getnext(last) -- @@ -339,7 +339,7 @@ end -- we can count ... when all done, we can disable ... function initials.handler(head) - if getid(head) == localpar_code and start_of_par(head) then + if getid(head) == par_code and start_of_par(head) then local settings = getprop(head,a_initial) if settings then disableaction("processors","typesetters.initials.handler") diff --git a/tex/context/base/mkiv/typo-dua.lua b/tex/context/base/mkiv/typo-dua.lua index 92cca7ae4..5e1d4c109 100644 --- a/tex/context/base/mkiv/typo-dua.lua +++ b/tex/context/base/mkiv/typo-dua.lua @@ -99,7 +99,7 @@ local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local math_code = nodecodes.math local dir_code = nodecodes.dir -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local parfillskip_code = gluecodes.parfillskip @@ -337,7 +337,7 @@ local function get_baselevel(head,list,size,direction) -- This is an adapted version: if direction == lefttoright_code or direction == righttoleft_code then return direction, true - elseif getid(head) == localpar_code and start_of_par(head) then + elseif getid(head) == par_code and start_of_par(head) then direction = getdirection(head) if direction == lefttoright_code or direction == righttoleft_code then return direction, true @@ -769,8 +769,8 @@ local function apply_to_list(list,size,head,pardir) enddir = false end elseif begindir then - if id == localpar_code and start_of_par(current) then - -- localpar should always be the 1st node + if id == par_code and start_of_par(current) then + -- par should always be the 1st node local d = new_direction(begindir) -- setprop(d,"directions",true) -- setattrlist(d,current) diff --git a/tex/context/base/mkiv/typo-dub.lua b/tex/context/base/mkiv/typo-dub.lua index ccbcc0a06..88b3361da 100644 --- a/tex/context/base/mkiv/typo-dub.lua +++ b/tex/context/base/mkiv/typo-dub.lua @@ -87,7 +87,7 @@ local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local math_code = nodecodes.math local dir_code = nodecodes.dir -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local parfillskip_code = gluecodes.parfillskip @@ -398,7 +398,7 @@ end local function get_baselevel(head,list,size,direction) if direction == lefttoright_code or direction == righttoleft_code then return direction, true - elseif getid(head) == localpar_code and start_of_par(head) then + elseif getid(head) == par_code and start_of_par(head) then direction = getdirection(head) if direction == lefttoright_code or direction == righttoleft_code then return direction, true @@ -902,8 +902,8 @@ local function apply_to_list(list,size,head,pardir) enddir = false end elseif begindir then - if id == localpar_code and start_of_par(current) then - -- localpar should always be the 1st node + if id == par_code and start_of_par(current) then + -- par should always be the 1st node local d = new_direction(begindir) -- setprop(d,"directions",true) -- setattrlist(d,current) diff --git a/tex/context/base/mkiv/typo-duc.lua b/tex/context/base/mkiv/typo-duc.lua index a1ee14a28..6e4f27de2 100644 --- a/tex/context/base/mkiv/typo-duc.lua +++ b/tex/context/base/mkiv/typo-duc.lua @@ -51,70 +51,73 @@ local utfchar = utf.char local setmetatable = setmetatable local formatters = string.formatters -local directiondata = characters.directions -local mirrordata = characters.mirrors -local textclassdata = characters.textclasses +local directiondata = characters.directions +local mirrordata = characters.mirrors +local textclassdata = characters.textclasses -local nuts = nodes.nuts +local nuts = nodes.nuts -local getnext = nuts.getnext -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getlist = nuts.getlist -local getchar = nuts.getchar -local getattr = nuts.getattr -local getprop = nuts.getprop -local getdirection = nuts.getdirection -local isglyph = nuts.isglyph +local getnext = nuts.getnext +local getprev = nuts.getprev +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local getlist = nuts.getlist +local getchar = nuts.getchar +local getattr = nuts.getattr +local getprop = nuts.getprop +local getdirection = nuts.getdirection +local isglyph = nuts.isglyph -local setprop = nuts.setprop -local setchar = nuts.setchar -local setdirection = nuts.setdirection -local setattrlist = nuts.setattrlist +local setprop = nuts.setprop +local setchar = nuts.setchar +local setdirection = nuts.setdirection +local setattrlist = nuts.setattrlist -local properties = nodes.properties.data +local properties = nodes.properties.data -local remove_node = nuts.remove -local insert_node_after = nuts.insert_after -local insert_node_before = nuts.insert_before -local start_of_par = nuts.start_of_par +local remove_node = nuts.remove +local insert_node_after = nuts.insert_after +local insert_node_before = nuts.insert_before +local start_of_par = nuts.start_of_par -local nodepool = nuts.pool -local new_direction = nodepool.direction +local nodepool = nuts.pool +local new_direction = nodepool.direction -local nodecodes = nodes.nodecodes -local gluecodes = nodes.gluecodes +local nodecodes = nodes.nodecodes +local gluecodes = nodes.gluecodes -local glyph_code = nodecodes.glyph -local glue_code = nodecodes.glue -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local math_code = nodecodes.math -local dir_code = nodecodes.dir -local localpar_code = nodecodes.localpar +local glyph_code = nodecodes.glyph +local glue_code = nodecodes.glue +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local math_code = nodecodes.math +local dir_code = nodecodes.dir +local par_code = nodecodes.par +local penalty_code = nodecodes.penalty -local parfillskip_code = gluecodes.parfillskip +local parfillskip_code = gluecodes.parfillskip +local parfillleftskip_code = gluecodes.parfillleftskip -local dirvalues = nodes.dirvalues -local lefttoright_code = dirvalues.lefttoright -local righttoleft_code = dirvalues.righttoleft +local dirvalues = nodes.dirvalues +local lefttoright_code = dirvalues.lefttoright +local righttoleft_code = dirvalues.righttoleft -local maximum_stack = 0xFF +local maximum_stack = 0xFF -local a_directions = attributes.private('directions') +local a_directions = attributes.private('directions') -local directions = typesetters.directions -local setcolor = directions.setcolor -local getfences = directions.getfences +local directions = typesetters.directions +local setcolor = directions.setcolor +local getfences = directions.getfences -local remove_controls = true directives.register("typesetters.directions.removecontrols",function(v) remove_controls = v end) ------ analyze_fences = true directives.register("typesetters.directions.analyzefences", function(v) analyze_fences = v end) +local remove_controls = true directives.register("typesetters.directions.removecontrols",function(v) remove_controls = v end) +----- analyze_fences = true directives.register("typesetters.directions.analyzefences", function(v) analyze_fences = v end) -local report_directions = logs.reporter("typesetting","directions three") +local report_directions = logs.reporter("typesetting","directions three") -local trace_directions = false trackers.register("typesetters.directions", function(v) trace_directions = v end) -local trace_details = false trackers.register("typesetters.directions.details", function(v) trace_details = v end) -local trace_list = false trackers.register("typesetters.directions.list", function(v) trace_list = v end) +local trace_directions = false trackers.register("typesetters.directions", function(v) trace_directions = v end) +local trace_details = false trackers.register("typesetters.directions.details", function(v) trace_details = v end) +local trace_list = false trackers.register("typesetters.directions.list", function(v) trace_list = v end) -- strong (old): -- @@ -413,7 +416,7 @@ end local function get_baselevel(head,list,size,direction) if direction == lefttoright_code or direction == righttoleft_code then return direction, true - elseif getid(head) == localpar_code and start_of_par(head) then + elseif getid(head) == par_code and start_of_par(head) then direction = getdirection(head) if direction == lefttoright_code or direction == righttoleft_code then return direction, true @@ -943,14 +946,25 @@ local function apply_to_list(list,size,head,pardir) elseif id == hlist_code or id == vlist_code then setdirection(current,pardir) -- is this really needed? elseif id == glue_code then + -- Maybe I should also fix dua and dub but on the other hand ... why? if enddir and getsubtype(current) == parfillskip_code then -- insert the last enddir before \parfillskip glue - head = insert_node_before(head,current,new_direction(enddir,true)) + local c = current + local p = getprev(c) + if p and getid(p) == glue_code and getsubtype(p) == parfillleftskip_code then + c = p + p = getprev(c) + end + if p and getid(p) == penalty_code then -- linepenalty + c = p + end + -- there is always a par nodes so head will stay + head = insert_node_before(head,c,new_direction(enddir,true)) enddir = false end elseif begindir then - if id == localpar_code and start_of_par(current) then - -- localpar should always be the 1st node + if id == par_code and start_of_par(current) then + -- par should always be the 1st node head, current = insert_node_after(head,current,new_direction(begindir)) begindir = nil end diff --git a/tex/context/base/mkiv/typo-fln.lua b/tex/context/base/mkiv/typo-fln.lua index c4a14846e..3941e65ef 100644 --- a/tex/context/base/mkiv/typo-fln.lua +++ b/tex/context/base/mkiv/typo-fln.lua @@ -56,7 +56,7 @@ local glyph_code = nodecodes.glyph local disc_code = nodecodes.disc local kern_code = nodecodes.kern local glue_code = nodecodes.glue -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local spaceskip_code = nodes.gluecodes.spaceskip @@ -372,7 +372,7 @@ end actions[v_default] = actions[v_line] function firstlines.handler(head) - if getid(head) == localpar_code and start_of_par(head) then + if getid(head) == par_code and start_of_par(head) then local settings = getprop(head,a_firstline) if settings then disableaction("processors","typesetters.firstlines.handler") diff --git a/tex/context/base/mkiv/typo-itc.mkvi b/tex/context/base/mkiv/typo-itc.mkvi index 312a2efb4..2bde63857 100644 --- a/tex/context/base/mkiv/typo-itc.mkvi +++ b/tex/context/base/mkiv/typo-itc.mkvi @@ -37,8 +37,12 @@ \unexpanded\def\italiccorrection {\ifnum\c_attr_italics<\plusone\normalitaliccorrection\fi} +\pushoverloadmode + \let\/\italiccorrection +\popoverloadmode + % 1 = end of word % 2 = end of word and end of a list diff --git a/tex/context/base/mkiv/typo-lig.mkxl b/tex/context/base/mkiv/typo-lig.mkxl new file mode 100644 index 000000000..e30774d8e --- /dev/null +++ b/tex/context/base/mkiv/typo-lig.mkxl @@ -0,0 +1,23 @@ +%D \module +%D [ file=typo-lig, +%D version=2014.12.01, +%D title=\CONTEXT\ Typesetting Macros, +%D subtitle=Ligatures, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Typesetting Macros / Ligatures} + +%D The original macro was mostly used for testing an attribute that blocks ligatures +%D in the nodemode handler. In \LMTX\ things are done differently. + +\unprotect + +\permanent\protected\def\noligature{\dontleavehmode\groupedcommandcs\noligaturing\donothing} + +\protect \endinput diff --git a/tex/context/base/mkiv/typo-lin.lua b/tex/context/base/mkiv/typo-lin.lua index 95f9c13fa..4496bd44b 100644 --- a/tex/context/base/mkiv/typo-lin.lua +++ b/tex/context/base/mkiv/typo-lin.lua @@ -38,7 +38,7 @@ if not modules then modules = { } end modules ['typo-lin'] = { -- But, maybe there are good reasons for having just that anchor (mostly for educational purposes -- I guess.) -- --- At this stage the localpar node is no longer of any use so we remove it (each line has the +-- At this stage the par node is no longer of any use so we remove it (each line has the -- direction attached). We might at some point also strip the disc nodes as they no longer serve -- a purpose but that can better be a helper. Anchoring left has advantage of keeping page -- stream. @@ -65,7 +65,7 @@ local hlist_code = nodecodes.hlist local glue_code = nodecodes.glue local kern_code = nodecodes.kern local linelist_code = listcodes.line ------ localpar_code = nodecodes.localpar +----- par_code = nodecodes.par local leftskip_code = gluecodes.leftskip local rightskip_code = gluecodes.rightskip local parfillskip_code = gluecodes.parfillskip @@ -185,7 +185,7 @@ local function normalize(line,islocal) -- assumes prestine lines, nothing pre/ap id = getid(current) end -- no: - -- if id == localpar_code then + -- if id == par_code then -- head = remove_node(head,head,true) -- end local tail = find_tail(head) diff --git a/tex/context/base/mkiv/typo-mar.mkiv b/tex/context/base/mkiv/typo-mar.mkiv index 921f1f230..95010ab8e 100644 --- a/tex/context/base/mkiv/typo-mar.mkiv +++ b/tex/context/base/mkiv/typo-mar.mkiv @@ -161,8 +161,6 @@ % trialtypesetting: no need for margin stuff while trialing as % is has no dimensions -\definesystemconstant{margintext} - \newcount\nofmargintexts \definepagestate[\s!margintext] @@ -337,7 +335,7 @@ {\endgraf\ifhmode\space\fi} \appendtoks - \let\\\spaceorpar + \enforced\let\\\spaceorpar \to \everymargindatacontent %D Another one: diff --git a/tex/context/base/mkiv/typo-rub.lua b/tex/context/base/mkiv/typo-rub.lua index da63d7b64..6c6ab9a33 100644 --- a/tex/context/base/mkiv/typo-rub.lua +++ b/tex/context/base/mkiv/typo-rub.lua @@ -63,7 +63,7 @@ local glue_code = nodecodes.glue local penalty_code = nodecodes.penalty local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist -local localpar_code = nodecodes.localpar +local par_code = nodecodes.par local dir_code = nodecodes.dir local kerncodes = nodes.kerncodes @@ -310,7 +310,7 @@ local function whatever(current) -- go on elseif id == hlist_code and getwidth(c) == 0 then -- go on - elseif id == whatsit_code or id == localpar_code or id == dir_code then + elseif id == whatsit_code or id == par_code or id == dir_code then -- go on else l = false |